Bump rust-bitcoin to 0.25, fix Cargo dependencies
Closes #112, closes #113, closes #124
This commit is contained in:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user