Bump rust-bitcoin to 0.25, fix Cargo dependencies

Closes #112, closes #113, closes #124
This commit is contained in:
Alekos Filini
2020-10-09 12:03:47 +02:00
parent 69ef56cfed
commit 100f0aaa0a
11 changed files with 219 additions and 179 deletions

View File

@@ -31,6 +31,7 @@ pub enum Error {
InvalidPrefix(Vec<u8>),
HardenedDerivationOnXpub,
MalformedInput,
InvalidHDKeyPath,
KeyParsingError(String),
Key(crate::keys::KeyError),

View File

@@ -31,7 +31,6 @@ use std::collections::{BTreeMap, HashMap};
use std::fmt;
use std::sync::Arc;
use bitcoin::hashes::hash160;
use bitcoin::secp256k1::Secp256k1;
use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
use bitcoin::util::psbt;
@@ -122,27 +121,26 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap) {
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
use crate::keys::DescriptorKey;
// check the network for the keys
let translated = self.0.translate_pk(
|pk| {
let (pk, _, networks) = if self.0.is_witness() {
let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
} else {
let desciptor_key: DescriptorKey<miniscript::Legacy> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
};
let check_key = |pk: &DescriptorPublicKey| {
let (pk, _, networks) = if self.0.is_witness() {
let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
} else {
let desciptor_key: DescriptorKey<miniscript::Legacy> =
pk.clone().to_descriptor_key()?;
desciptor_key.extract()?
};
if networks.contains(&network) {
Ok(pk)
} else {
Err(KeyError::InvalidNetwork)
}
},
|pkh| Ok::<_, KeyError>(*pkh),
)?;
if networks.contains(&network) {
Ok(pk)
} else {
Err(KeyError::InvalidNetwork)
}
};
// check the network for the keys
let translated = self.0.translate_pk(check_key, check_key)?;
Ok((translated, self.1))
}
@@ -155,32 +153,31 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap, ValidNetworks) {
) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
let valid_networks = &self.2;
let fix_key = |pk: &DescriptorPublicKey| {
if valid_networks.contains(&network) {
// workaround for xpubs generated by other key types, like bip39: since when the
// conversion is made one network has to be chosen, what we generally choose
// "mainnet", but then override the set of valid networks to specify that all of
// them are valid. here we reset the network to make sure the wallet struct gets a
// descriptor with the right network everywhere.
let pk = match pk {
DescriptorPublicKey::XPub(ref xpub) => {
let mut xpub = xpub.clone();
xpub.xkey.network = network;
DescriptorPublicKey::XPub(xpub)
}
other => other.clone(),
};
Ok(pk)
} else {
Err(KeyError::InvalidNetwork)
}
};
// fixup the network for keys that need it
let translated = self.0.translate_pk(
|pk| {
if valid_networks.contains(&network) {
// workaround for xpubs generated by other key types, like bip39: since when the
// conversion is made one network has to be chosen, what we generally choose
// "mainnet", but then override the set of valid networks to specify that all of
// them are valid. here we reset the network to make sure the wallet struct gets a
// descriptor with the right network everywhere.
let pk = match pk {
DescriptorPublicKey::XPub(ref xpub) => {
let mut xpub = xpub.clone();
xpub.xkey.network = network;
DescriptorPublicKey::XPub(xpub)
}
other => other.clone(),
};
Ok(pk)
} else {
Err(KeyError::InvalidNetwork)
}
},
|pkh| Ok::<_, KeyError>(*pkh),
)?;
let translated = self.0.translate_pk(fix_key, fix_key)?;
Ok((translated, self.1))
}
@@ -188,10 +185,7 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap, ValidNetworks) {
/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
pub trait ExtractPolicy {
fn extract_policy(
&self,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Result<Option<Policy>, Error>;
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error>;
}
pub(crate) trait XKeyUtils {
@@ -201,7 +195,7 @@ pub(crate) trait XKeyUtils {
impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
let full_path = match self.source {
let full_path = match self.origin {
Some((_, ref path)) => path
.into_iter()
.chain(self.derivation_path.into_iter())
@@ -222,7 +216,7 @@ impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
}
fn root_fingerprint(&self) -> Fingerprint {
match self.source {
match self.origin {
Some((fingerprint, _)) => fingerprint,
None => self.xkey.xkey_fingerprint(),
}
@@ -280,11 +274,13 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
}
fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error> {
let mut answer = BTreeMap::new();
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
fn translate_key(
key: &DescriptorPublicKey,
index: u32,
paths: &mut HDKeyPaths,
) -> Result<DummyKey, Error> {
match key {
DescriptorPublicKey::PubKey(_) => {}
DescriptorPublicKey::SinglePub(_) => {}
DescriptorPublicKey::XPub(xpub) => {
let derive_path = if xpub.is_wildcard {
xpub.derivation_path
@@ -299,7 +295,7 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
.xkey
.derive_pub(&Secp256k1::verification_only(), &derive_path)?;
answer.insert(
paths.insert(
derived_pubkey.public_key,
(
xpub.root_fingerprint(),
@@ -310,42 +306,54 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
}
Ok(DummyKey::default())
};
let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
}
self.translate_pk(translatefpk, translatefpkh)?;
let mut answer_pk = BTreeMap::new();
let mut answer_pkh = BTreeMap::new();
Ok(answer)
self.translate_pk(
|pk| translate_key(pk, index, &mut answer_pk),
|pkh| translate_key(pkh, index, &mut answer_pkh),
)?;
answer_pk.append(&mut answer_pkh);
Ok(answer_pk)
}
fn is_fixed(&self) -> bool {
let mut found_wildcard = false;
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
fn check_key(key: &DescriptorPublicKey, flag: &mut bool) -> Result<DummyKey, Error> {
match key {
DescriptorPublicKey::PubKey(_) => {}
DescriptorPublicKey::SinglePub(_) => {}
DescriptorPublicKey::XPub(xpub) => {
if xpub.is_wildcard {
found_wildcard = true;
*flag = true;
}
}
}
Ok(DummyKey::default())
};
let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
}
self.translate_pk(translatefpk, translatefpkh).unwrap();
let mut found_wildcard_pk = false;
let mut found_wildcard_pkh = false;
!found_wildcard
self.translate_pk(
|pk| check_key(pk, &mut found_wildcard_pk),
|pkh| check_key(pkh, &mut found_wildcard_pkh),
)
.unwrap();
!found_wildcard_pk && !found_wildcard_pkh
}
fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self> {
let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
let mut derive_path = None::<DerivationPath>;
let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
if derive_path.is_some() {
fn try_key(
key: &DescriptorPublicKey,
index: &HashMap<Fingerprint, DerivationPath>,
found_path: &mut Option<ChildNumber>,
) -> Result<DummyKey, Error> {
if found_path.is_some() {
// already found a matching path, we are done
return Ok(DummyKey::default());
}
@@ -353,9 +361,10 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
if let DescriptorPublicKey::XPub(xpub) = key {
// Check if the key matches one entry in our `index`. If it does, `matches()` will
// return the "prefix" that matched, so we remove that prefix from the full path
// found in `index` and save it in `derive_path`
// found in `index` and save it in `derive_path`. We expect this to be a derivation
// path of length 1 if the key `is_wildcard` and an empty path otherwise.
let root_fingerprint = xpub.root_fingerprint();
derive_path = index
let derivation_path: Option<Vec<ChildNumber>> = index
.get_key_value(&root_fingerprint)
.and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
.map(|prefix| {
@@ -367,15 +376,46 @@ impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
.cloned()
.collect()
});
match derivation_path {
Some(path) if xpub.is_wildcard && path.len() == 1 => {
*found_path = Some(path[0])
}
Some(path) if !xpub.is_wildcard && path.is_empty() => {
*found_path = Some(ChildNumber::Normal { index: 0 })
}
Some(_) => return Err(Error::InvalidHDKeyPath),
_ => {}
}
}
Ok(DummyKey::default())
};
let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
self.translate_pk(translatefpk, translatefpkh).unwrap();
let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
derive_path.map(|path| self.derive(path.as_ref()))
let mut found_path_pk = None;
let mut found_path_pkh = None;
if self
.translate_pk(
|pk| try_key(pk, &index, &mut found_path_pk),
|pkh| try_key(pkh, &index, &mut found_path_pkh),
)
.is_err()
{
return None;
}
// if we have found a path for both `found_path_pk` and `found_path_pkh` but they are
// different we consider this an error and return None. we only return a path either if
// they are equal or if only one of them is Some(_)
let merged_path = match (found_path_pk, found_path_pkh) {
(Some(a), Some(b)) if a != b => return None,
(a, b) => a.or(b),
};
merged_path.map(|path| self.derive(path))
}
fn derive_from_psbt_input(

View File

@@ -56,7 +56,7 @@ use bitcoin::util::bip32::Fingerprint;
use bitcoin::PublicKey;
use miniscript::descriptor::DescriptorPublicKey;
use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal};
use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal, ToPublicKey};
#[allow(unused_imports)]
use log::{debug, error, info, trace};
@@ -82,8 +82,8 @@ pub struct PKOrF {
impl PKOrF {
fn from_key(k: &DescriptorPublicKey) -> Self {
match k {
DescriptorPublicKey::PubKey(pubkey) => PKOrF {
pubkey: Some(*pubkey),
DescriptorPublicKey::SinglePub(pubkey) => PKOrF {
pubkey: Some(pubkey.key),
..Default::default()
},
DescriptorPublicKey::XPub(xpub) => PKOrF {
@@ -524,7 +524,7 @@ impl Policy {
fn make_multisig(
keys: &[DescriptorPublicKey],
signers: Arc<SignersContainer<DescriptorPublicKey>>,
signers: Arc<SignersContainer>,
threshold: usize,
) -> Result<Option<Policy>, PolicyError> {
if threshold == 0 {
@@ -648,17 +648,14 @@ impl From<SatisfiableItem> for Policy {
}
}
fn signer_id(key: &DescriptorPublicKey) -> SignerId<DescriptorPublicKey> {
fn signer_id(key: &DescriptorPublicKey) -> SignerId {
match key {
DescriptorPublicKey::PubKey(pubkey) => pubkey.to_pubkeyhash().into(),
DescriptorPublicKey::SinglePub(pubkey) => pubkey.key.to_pubkeyhash().into(),
DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
}
}
fn signature(
key: &DescriptorPublicKey,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Policy {
fn signature(key: &DescriptorPublicKey, signers: Arc<SignersContainer>) -> Policy {
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
policy.contribution = if signers.find(signer_id(key)).is_some() {
@@ -673,12 +670,13 @@ fn signature(
}
fn signature_key(
key_hash: &<DescriptorPublicKey as MiniscriptKey>::Hash,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
key: &<DescriptorPublicKey as MiniscriptKey>::Hash,
signers: Arc<SignersContainer>,
) -> Policy {
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(*key_hash)).into();
let key_hash = key.to_public_key().to_pubkeyhash();
let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(key_hash)).into();
if signers.find(SignerId::PkHash(*key_hash)).is_some() {
if signers.find(SignerId::PkHash(key_hash)).is_some() {
policy.contribution = Satisfaction::Complete {
condition: Default::default(),
}
@@ -688,10 +686,7 @@ fn signature_key(
}
impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
fn extract_policy(
&self,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Result<Option<Policy>, Error> {
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error> {
Ok(match &self.node {
// Leaves
Terminal::True | Terminal::False => None,
@@ -781,10 +776,7 @@ impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>
}
impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
fn extract_policy(
&self,
signers: Arc<SignersContainer<DescriptorPublicKey>>,
) -> Result<Option<Policy>, Error> {
fn extract_policy(&self, signers: Arc<SignersContainer>) -> Result<Option<Policy>, Error> {
match self {
Descriptor::Pk(pubkey)
| Descriptor::Pkh(pubkey)