diff --git a/Cargo.toml b/Cargo.toml index ef1a0d2a..ae590c50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,15 +7,15 @@ authors = ["Alekos Filini ", "Riccardo Casatta ), HardenedDerivationOnXpub, MalformedInput, + InvalidHDKeyPath, KeyParsingError(String), Key(crate::keys::KeyError), diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index 8632419d..430b3877 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -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 = - pk.clone().to_descriptor_key()?; - desciptor_key.extract()? - } else { - let desciptor_key: DescriptorKey = - 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 = + pk.clone().to_descriptor_key()?; + desciptor_key.extract()? + } else { + let desciptor_key: DescriptorKey = + 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>, - ) -> Result, Error>; + fn extract_policy(&self, signers: Arc) -> Result, Error>; } pub(crate) trait XKeyUtils { @@ -201,7 +195,7 @@ pub(crate) trait XKeyUtils { impl XKeyUtils for DescriptorXKey { 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 XKeyUtils for DescriptorXKey { } 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 { } fn get_hd_keypaths(&self, index: u32) -> Result { - let mut answer = BTreeMap::new(); - - let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> { + fn translate_key( + key: &DescriptorPublicKey, + index: u32, + paths: &mut HDKeyPaths, + ) -> Result { 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 { .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 { } 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 { 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 { - let index: HashMap<_, _> = hd_keypaths.values().cloned().collect(); - - let mut derive_path = None::; - let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> { - if derive_path.is_some() { + fn try_key( + key: &DescriptorPublicKey, + index: &HashMap, + found_path: &mut Option, + ) -> Result { + 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 { 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> = index .get_key_value(&root_fingerprint) .and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path)) .map(|prefix| { @@ -367,15 +376,46 @@ impl DescriptorMeta for Descriptor { .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( diff --git a/src/descriptor/policy.rs b/src/descriptor/policy.rs index 6c024638..69441c24 100644 --- a/src/descriptor/policy.rs +++ b/src/descriptor/policy.rs @@ -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>, + signers: Arc, threshold: usize, ) -> Result, PolicyError> { if threshold == 0 { @@ -648,17 +648,14 @@ impl From for Policy { } } -fn signer_id(key: &DescriptorPublicKey) -> SignerId { +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>, -) -> Policy { +fn signature(key: &DescriptorPublicKey, signers: Arc) -> 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: &::Hash, - signers: Arc>, + key: &::Hash, + signers: Arc, ) -> 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 ExtractPolicy for Miniscript { - fn extract_policy( - &self, - signers: Arc>, - ) -> Result, Error> { + fn extract_policy(&self, signers: Arc) -> Result, Error> { Ok(match &self.node { // Leaves Terminal::True | Terminal::False => None, @@ -781,10 +776,7 @@ impl ExtractPolicy for Miniscript } impl ExtractPolicy for Descriptor { - fn extract_policy( - &self, - signers: Arc>, - ) -> Result, Error> { + fn extract_policy(&self, signers: Arc) -> Result, Error> { match self { Descriptor::Pk(pubkey) | Descriptor::Pkh(pubkey) diff --git a/src/keys/mod.rs b/src/keys/mod.rs index 9aa17d33..d8fe8bda 100644 --- a/src/keys/mod.rs +++ b/src/keys/mod.rs @@ -32,7 +32,9 @@ use std::ops::Deref; use bitcoin::util::bip32; use bitcoin::{Network, PrivateKey, PublicKey}; -pub use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey}; +pub use miniscript::descriptor::{ + DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePriv, DescriptorSinglePub, +}; use miniscript::descriptor::{DescriptorXKey, KeyMap}; pub use miniscript::ScriptContext; use miniscript::{Miniscript, Terminal}; @@ -198,7 +200,7 @@ impl ExtScriptContext for Ctx { /// ``` /// use bdk::bitcoin::PublicKey; /// -/// use bdk::keys::{mainnet_network, ScriptContext, ToDescriptorKey, DescriptorKey, DescriptorPublicKey, KeyError}; +/// use bdk::keys::{mainnet_network, ScriptContext, ToDescriptorKey, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError}; /// /// pub struct MyKeyType { /// pubkey: PublicKey, @@ -206,7 +208,10 @@ impl ExtScriptContext for Ctx { /// /// impl ToDescriptorKey for MyKeyType { /// fn to_descriptor_key(self) -> Result, KeyError> { -/// Ok(DescriptorKey::from_public(DescriptorPublicKey::PubKey(self.pubkey), mainnet_network())) +/// Ok(DescriptorKey::from_public(DescriptorPublicKey::SinglePub(DescriptorSinglePub { +/// origin: None, +/// key: self.pubkey +/// }), mainnet_network())) /// } /// } /// ``` @@ -286,7 +291,7 @@ pub trait DerivableKey { /// Add a extra metadata, consume `self` and turn it into a [`DescriptorKey`] fn add_metadata( self, - source: Option<(bip32::Fingerprint, bip32::DerivationPath)>, + origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>, derivation_path: bip32::DerivationPath, ) -> Result, KeyError>; } @@ -294,11 +299,11 @@ pub trait DerivableKey { impl DerivableKey for bip32::ExtendedPubKey { fn add_metadata( self, - source: Option<(bip32::Fingerprint, bip32::DerivationPath)>, + origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>, derivation_path: bip32::DerivationPath, ) -> Result, KeyError> { DescriptorPublicKey::XPub(DescriptorXKey { - source, + origin, xkey: self, derivation_path, is_wildcard: true, @@ -310,11 +315,11 @@ impl DerivableKey for bip32::ExtendedPubKey { impl DerivableKey for bip32::ExtendedPrivKey { fn add_metadata( self, - source: Option<(bip32::Fingerprint, bip32::DerivationPath)>, + origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>, derivation_path: bip32::DerivationPath, ) -> Result, KeyError> { DescriptorSecretKey::XPrv(DescriptorXKey { - source, + origin, xkey: self, derivation_path, is_wildcard: true, @@ -355,10 +360,10 @@ where { fn add_metadata( self, - source: Option<(bip32::Fingerprint, bip32::DerivationPath)>, + origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>, derivation_path: bip32::DerivationPath, ) -> Result, KeyError> { - let descriptor_key = self.key.add_metadata(source, derivation_path)?; + let descriptor_key = self.key.add_metadata(origin, derivation_path)?; Ok(descriptor_key.override_valid_networks(self.valid_networks)) } } @@ -483,7 +488,7 @@ impl ToDescriptorKey for DescriptorKey { impl ToDescriptorKey for DescriptorPublicKey { fn to_descriptor_key(self) -> Result, KeyError> { let networks = match self { - DescriptorPublicKey::PubKey(_) => any_network(), + DescriptorPublicKey::SinglePub(_) => any_network(), DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. }) if xkey.network == Network::Bitcoin => { @@ -498,14 +503,20 @@ impl ToDescriptorKey for DescriptorPublicKey { impl ToDescriptorKey for PublicKey { fn to_descriptor_key(self) -> Result, KeyError> { - DescriptorPublicKey::PubKey(self).to_descriptor_key() + DescriptorPublicKey::SinglePub(DescriptorSinglePub { + key: self, + origin: None, + }) + .to_descriptor_key() } } impl ToDescriptorKey for DescriptorSecretKey { fn to_descriptor_key(self) -> Result, KeyError> { - let networks = match self { - DescriptorSecretKey::PrivKey(sk) if sk.network == Network::Bitcoin => mainnet_network(), + let networks = match &self { + DescriptorSecretKey::SinglePriv(sk) if sk.key.network == Network::Bitcoin => { + mainnet_network() + } DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. }) if xkey.network == Network::Bitcoin => { @@ -520,7 +531,11 @@ impl ToDescriptorKey for DescriptorSecretKey { impl ToDescriptorKey for PrivateKey { fn to_descriptor_key(self) -> Result, KeyError> { - DescriptorSecretKey::PrivKey(self).to_descriptor_key() + DescriptorSecretKey::SinglePriv(DescriptorSinglePriv { + key: self, + origin: None, + }) + .to_descriptor_key() } } diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index 67a8570a..1629107b 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -37,7 +37,7 @@ use bitcoin::util::bip32::ChildNumber; use bitcoin::util::psbt::PartiallySignedTransaction as PSBT; use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid}; -use miniscript::descriptor::DescriptorPublicKey; +use miniscript::psbt::PsbtInputSatisfier; #[allow(unused_imports)] use log::{debug, error, info, trace}; @@ -87,8 +87,8 @@ pub struct Wallet { descriptor: ExtendedDescriptor, change_descriptor: Option, - signers: Arc>, - change_signers: Arc>, + signers: Arc, + change_signers: Arc, address_validators: Vec>>, @@ -158,7 +158,7 @@ where let index = self.fetch_and_increment_index(ScriptType::External)?; self.descriptor - .derive(&[ChildNumber::from_normal_idx(index).unwrap()]) + .derive(ChildNumber::from_normal_idx(index)?) .address(self.network) .ok_or(Error::ScriptDoesntHaveAddressForm) } @@ -204,7 +204,7 @@ where pub fn add_signer( &mut self, script_type: ScriptType, - id: SignerId, + id: SignerId, ordering: SignerOrdering, signer: Arc>, ) { @@ -803,7 +803,7 @@ where match desc.satisfy( input, ( - psbt_input.clone(), + PsbtInputSatisfier::new(&psbt, n), After::new(current_height, false), Older::new(current_height, create_height, false), ), @@ -846,7 +846,7 @@ where .borrow() .get_path_from_script_pubkey(&txout.script_pubkey)? .map(|(script_type, child)| (self.get_descriptor_for_script_type(script_type).0, child)) - .map(|(desc, child)| desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()]))) + .map(|(desc, child)| desc.derive(ChildNumber::from_normal_idx(child).unwrap()))) } fn get_change_address(&self) -> Result { @@ -854,7 +854,7 @@ where let index = self.fetch_and_increment_index(script_type)?; Ok(desc - .derive(&[ChildNumber::from_normal_idx(index).unwrap()]) + .derive(ChildNumber::from_normal_idx(index)?) .script_pubkey()) } @@ -879,7 +879,7 @@ where let hd_keypaths = descriptor.get_hd_keypaths(index)?; let script = descriptor - .derive(&[ChildNumber::from_normal_idx(index).unwrap()]) + .derive(ChildNumber::from_normal_idx(index)?) .script_pubkey(); for validator in &self.address_validators { validator.validate(script_type, &hd_keypaths, &script)?; @@ -909,7 +909,7 @@ where for i in from..(from + count) { address_batch.set_script_pubkey( &descriptor - .derive(&[ChildNumber::from_normal_idx(i).unwrap()]) + .derive(ChildNumber::from_normal_idx(i)?) .script_pubkey(), script_type, i, @@ -1004,7 +1004,7 @@ where let (desc, _) = self.get_descriptor_for_script_type(script_type); psbt_input.hd_keypaths = desc.get_hd_keypaths(child)?; - let derived_descriptor = desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()]); + let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?); psbt_input.redeem_script = derived_descriptor.psbt_redeem_script(); psbt_input.witness_script = derived_descriptor.psbt_witness_script(); diff --git a/src/wallet/signer.rs b/src/wallet/signer.rs index 989d4d9d..e6d8b4e4 100644 --- a/src/wallet/signer.rs +++ b/src/wallet/signer.rs @@ -102,7 +102,7 @@ use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint}; use bitcoin::util::{bip143, psbt}; use bitcoin::{PrivateKey, Script, SigHash, SigHashType}; -use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, KeyMap}; +use miniscript::descriptor::{DescriptorSecretKey, DescriptorSinglePriv, DescriptorXKey, KeyMap}; use miniscript::{Legacy, MiniscriptKey, Segwitv0}; use crate::descriptor::XKeyUtils; @@ -110,19 +110,19 @@ use crate::descriptor::XKeyUtils; /// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among /// multiple of them #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum SignerId { - PkHash(::Hash), +pub enum SignerId { + PkHash(hash160::Hash), Fingerprint(Fingerprint), } -impl From for SignerId { - fn from(hash: hash160::Hash) -> SignerId { +impl From for SignerId { + fn from(hash: hash160::Hash) -> SignerId { SignerId::PkHash(hash) } } -impl From for SignerId { - fn from(fing: Fingerprint) -> SignerId { +impl From for SignerId { + fn from(fing: Fingerprint) -> SignerId { SignerId::Fingerprint(fing) } } @@ -284,7 +284,10 @@ impl Signer for PrivateKey { } fn descriptor_secret_key(&self) -> Option { - Some(DescriptorSecretKey::PrivKey(*self)) + Some(DescriptorSecretKey::SinglePriv(DescriptorSinglePriv { + key: *self, + origin: None, + })) } } @@ -303,13 +306,13 @@ impl std::default::Default for SignerOrdering { } #[derive(Debug, Clone)] -struct SignersContainerKey { - id: SignerId, +struct SignersContainerKey { + id: SignerId, ordering: SignerOrdering, } -impl From<(SignerId, SignerOrdering)> for SignersContainerKey { - fn from(tuple: (SignerId, SignerOrdering)) -> Self { +impl From<(SignerId, SignerOrdering)> for SignersContainerKey { + fn from(tuple: (SignerId, SignerOrdering)) -> Self { SignersContainerKey { id: tuple.0, ordering: tuple.1, @@ -319,11 +322,9 @@ impl From<(SignerId, SignerOrdering)> for SignersContaine /// Container for multiple signers #[derive(Debug, Default, Clone)] -pub struct SignersContainer( - BTreeMap, Arc>>, -); +pub struct SignersContainer(BTreeMap>>); -impl SignersContainer { +impl SignersContainer { pub fn as_key_map(&self) -> KeyMap { self.0 .values() @@ -333,20 +334,21 @@ impl SignersContainer { } } -impl From for SignersContainer { - fn from(keymap: KeyMap) -> SignersContainer { +impl From for SignersContainer { + fn from(keymap: KeyMap) -> SignersContainer { let mut container = SignersContainer::new(); for (_, secret) in keymap { match secret { - DescriptorSecretKey::PrivKey(private_key) => container.add_external( + DescriptorSecretKey::SinglePriv(private_key) => container.add_external( SignerId::from( private_key + .key .public_key(&Secp256k1::signing_only()) .to_pubkeyhash(), ), SignerOrdering::default(), - Arc::new(Box::new(private_key)), + Arc::new(Box::new(private_key.key)), ), DescriptorSecretKey::XPrv(xprv) => container.add_external( SignerId::from(xprv.root_fingerprint()), @@ -360,7 +362,7 @@ impl From for SignersContainer { } } -impl SignersContainer { +impl SignersContainer { /// Default constructor pub fn new() -> Self { SignersContainer(Default::default()) @@ -370,7 +372,7 @@ impl SignersContainer { /// signer that was previosuly in the container, if any pub fn add_external( &mut self, - id: SignerId, + id: SignerId, ordering: SignerOrdering, signer: Arc>, ) -> Option>> { @@ -380,14 +382,14 @@ impl SignersContainer { /// Removes a signer from the container and returns it pub fn remove( &mut self, - id: SignerId, + id: SignerId, ordering: SignerOrdering, ) -> Option>> { self.0.remove(&(id, ordering).into()) } /// Returns the list of identifiers of all the signers in the container - pub fn ids(&self) -> Vec<&SignerId> { + pub fn ids(&self) -> Vec<&SignerId> { self.0 .keys() .map(|SignersContainerKey { id, .. }| id) @@ -400,7 +402,7 @@ impl SignersContainer { } /// Finds the signer with lowest ordering for a given id in the container. - pub fn find(&self, id: SignerId) -> Option<&Arc>> { + pub fn find(&self, id: SignerId) -> Option<&Arc>> { self.0 .range(( Included(&(id.clone(), SignerOrdering(0)).into()), @@ -515,22 +517,22 @@ impl ComputeSighash for Segwitv0 { } } -impl PartialOrd for SignersContainerKey { +impl PartialOrd for SignersContainerKey { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for SignersContainerKey { +impl Ord for SignersContainerKey { fn cmp(&self, other: &Self) -> Ordering { self.ordering.cmp(&other.ordering) } } -impl PartialEq for SignersContainerKey { +impl PartialEq for SignersContainerKey { fn eq(&self, other: &Self) -> bool { self.ordering == other.ordering } } -impl Eq for SignersContainerKey {} +impl Eq for SignersContainerKey {} diff --git a/src/wallet/tx_builder.rs b/src/wallet/tx_builder.rs index d24bd435..017d26f7 100644 --- a/src/wallet/tx_builder.rs +++ b/src/wallet/tx_builder.rs @@ -206,7 +206,7 @@ impl TxBuilder { /// /// The `version` should always be greater than `0` and greater than `1` if the wallet's /// descriptors contain an "older" (OP_CSV) operator. - pub fn version(mut self, version: u32) -> Self { + pub fn version(mut self, version: i32) -> Self { self.version = Some(Version(version)); self } @@ -316,7 +316,7 @@ impl TxOrdering { /// /// Has a default value of `1` #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)] -pub(crate) struct Version(pub(crate) u32); +pub(crate) struct Version(pub(crate) i32); impl Default for Version { fn default() -> Self { diff --git a/testutils/Cargo.toml b/testutils/Cargo.toml index 40e87eb9..77b4e450 100644 --- a/testutils/Cargo.toml +++ b/testutils/Cargo.toml @@ -9,17 +9,11 @@ name = "testutils" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -# The latest bitcoincore-rpc depends on an older version of bitcoin, which in turns depends on an -# older version of secp256k1, which causes conflicts during linking. Use my fork right now, we can -# switch back to crates.io as soon as rust-bitcoin is updated in rust-bitcoincore-rpc. -# -# Tracking issue: https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/80 - [dependencies] log = "0.4.8" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serial_test = "0.4" -bitcoin = "0.23" -bitcoincore-rpc = "0.11" -electrum-client = "0.2.0-beta.1" +bitcoin = "0.25" +bitcoincore-rpc = "0.12" +electrum-client = "0.3.0-beta.1" diff --git a/testutils/src/lib.rs b/testutils/src/lib.rs index 496f1b84..b73a8de3 100644 --- a/testutils/src/lib.rs +++ b/testutils/src/lib.rs @@ -119,13 +119,13 @@ macro_rules! testutils { use miniscript::descriptor::{Descriptor, DescriptorPublicKey}; let parsed = Descriptor::::parse_secret(&$descriptors.0).expect("Failed to parse descriptor in `testutils!(@external)`").0; - parsed.derive(&[bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()]).address(bitcoin::Network::Regtest).expect("No address form") + parsed.derive(bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()).address(bitcoin::Network::Regtest).expect("No address form") }); ( @internal $descriptors:expr, $child:expr ) => ({ use miniscript::descriptor::{Descriptor, DescriptorPublicKey}; let parsed = Descriptor::::parse_secret(&$descriptors.1.expect("Missing internal descriptor")).expect("Failed to parse descriptor in `testutils!(@internal)`").0; - parsed.derive(&[bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()]).address(bitcoin::Network::Regtest).expect("No address form") + parsed.derive(bitcoin::util::bip32::ChildNumber::from_normal_idx($child).unwrap()).address(bitcoin::Network::Regtest).expect("No address form") }); ( @e $descriptors:expr, $child:expr ) => ({ testutils!(@external $descriptors, $child) }); ( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) }); @@ -386,7 +386,7 @@ impl TestClient { trace!("getblocktemplate: {:#?}", block_template); let header = BlockHeader { - version: block_template["version"].as_u64().unwrap() as u32, + version: block_template["version"].as_i64().unwrap() as i32, prev_blockhash: BlockHash::from_hex( block_template["previousblockhash"].as_str().unwrap(), )