diff --git a/Cargo.toml b/Cargo.toml index ae590c50..1b36a80a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ authors = ["Alekos Filini ", "Riccardo Casatta {{ #[allow(unused_imports)] use $crate::keys::{DescriptorKey, ToDescriptorKey}; + let secp = $crate::bitcoin::secp256k1::Secp256k1::new(); $key.to_descriptor_key() - .and_then(|key: DescriptorKey<$ctx>| key.extract()) + .and_then(|key: DescriptorKey<$ctx>| key.extract(&secp)) .map(|(pk, key_map, valid_networks)| { ( $crate::miniscript::Descriptor::< @@ -314,7 +315,8 @@ macro_rules! fragment { $crate::impl_leaf_opcode!(False) }); ( pk_k $key:expr ) => ({ - $crate::keys::make_pk($key) + let secp = $crate::bitcoin::secp256k1::Secp256k1::new(); + $crate::keys::make_pk($key, &secp) }); ( pk $key:expr ) => ({ $crate::fragment!(+c pk_k $key) @@ -391,6 +393,7 @@ macro_rules! fragment { }); ( multi $thresh:expr $(, $key:expr )+ ) => ({ use $crate::keys::ToDescriptorKey; + let secp = $crate::bitcoin::secp256k1::Secp256k1::new(); let mut keys = vec![]; $( @@ -398,7 +401,7 @@ macro_rules! fragment { )* keys.into_iter().collect::, _>>() - .and_then(|keys| $crate::keys::make_multi($thresh, keys)) + .and_then(|keys| $crate::keys::make_multi($thresh, keys, &secp)) }); } @@ -406,7 +409,8 @@ macro_rules! fragment { #[cfg(test)] mod test { use bitcoin::hashes::hex::ToHex; - use miniscript::descriptor::{DescriptorPublicKey, KeyMap}; + use bitcoin::secp256k1::Secp256k1; + use miniscript::descriptor::{DescriptorPublicKey, DescriptorPublicKeyCtx, KeyMap}; use miniscript::{Descriptor, Legacy, Segwitv0}; use std::str::FromStr; @@ -426,6 +430,9 @@ mod test { is_fixed: bool, expected: &[&str], ) { + let secp = Secp256k1::new(); + let deriv_ctx = DescriptorPublicKeyCtx::new(&secp, ChildNumber::Normal { index: 0 }); + let (desc, _key_map, _networks) = desc.unwrap(); assert_eq!(desc.is_witness(), is_witness); assert_eq!(desc.is_fixed(), is_fixed); @@ -436,11 +443,11 @@ mod test { } else { desc.derive(ChildNumber::from_normal_idx(index).unwrap()) }; - let address = child_desc.address(Regtest); + let address = child_desc.address(Regtest, deriv_ctx); if address.is_some() { assert_eq!(address.unwrap().to_string(), *expected.get(i).unwrap()); } else { - let script = child_desc.script_pubkey(); + let script = child_desc.script_pubkey(deriv_ctx); assert_eq!(script.to_hex().as_str(), *expected.get(i).unwrap()); } } @@ -649,6 +656,8 @@ mod test { // - verify the key_maps are correctly merged together #[test] fn test_key_maps_merged() { + let secp = Secp256k1::new(); + let xprv1 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let path1 = bip32::DerivationPath::from_str("m/0").unwrap(); let desc_key1 = (xprv1, path1.clone()).to_descriptor_key().unwrap(); @@ -672,9 +681,9 @@ mod test { let desc_key3: DescriptorKey = (xprv3, path3.clone()).to_descriptor_key().unwrap(); - let (key1, _key_map, _valid_networks) = desc_key1.extract().unwrap(); - let (key2, _key_map, _valid_networks) = desc_key2.extract().unwrap(); - let (key3, _key_map, _valid_networks) = desc_key3.extract().unwrap(); + let (key1, _key_map, _valid_networks) = desc_key1.extract(&secp).unwrap(); + let (key2, _key_map, _valid_networks) = desc_key2.extract(&secp).unwrap(); + let (key3, _key_map, _valid_networks) = desc_key3.extract(&secp).unwrap(); assert_eq!(key_map.get(&key1).unwrap().to_string(), "tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/0/*"); assert_eq!(key_map.get(&key2).unwrap().to_string(), "tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF/2147483647'/0/*"); assert_eq!(key_map.get(&key3).unwrap().to_string(), "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf/10/20/30/40/*"); diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index 430b3877..b87124bd 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -53,6 +53,7 @@ use self::error::Error; pub use self::policy::Policy; use crate::keys::{KeyError, ToDescriptorKey, ValidNetworks}; use crate::wallet::signer::SignersContainer; +use crate::wallet::utils::{descriptor_to_pk_ctx, SecpCtx}; /// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`] pub type ExtendedDescriptor = Descriptor; @@ -92,7 +93,7 @@ impl ToWalletDescriptor for &str { self }; - ExtendedDescriptor::parse_secret(descriptor)?.to_wallet_descriptor(network) + ExtendedDescriptor::parse_descriptor(descriptor)?.to_wallet_descriptor(network) } } @@ -121,15 +122,17 @@ impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap) { ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> { use crate::keys::DescriptorKey; + let secp = Secp256k1::new(); + 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()? + desciptor_key.extract(&secp)? } else { let desciptor_key: DescriptorKey = pk.clone().to_descriptor_key()?; - desciptor_key.extract()? + desciptor_key.extract(&secp)? }; if networks.contains(&network) { @@ -185,12 +188,16 @@ 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, + secp: &SecpCtx, + ) -> Result, Error>; } pub(crate) trait XKeyUtils { fn full_path(&self, append: &[ChildNumber]) -> DerivationPath; - fn root_fingerprint(&self) -> Fingerprint; + fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint; } impl XKeyUtils for DescriptorXKey { @@ -215,46 +222,55 @@ impl XKeyUtils for DescriptorXKey { } } - fn root_fingerprint(&self) -> Fingerprint { + fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint { match self.origin { Some((fingerprint, _)) => fingerprint, - None => self.xkey.xkey_fingerprint(), + None => self.xkey.xkey_fingerprint(secp), } } } pub(crate) trait DescriptorMeta: Sized { fn is_witness(&self) -> bool; - fn get_hd_keypaths(&self, index: u32) -> Result; + fn get_hd_keypaths(&self, index: u32, secp: &SecpCtx) -> Result; fn is_fixed(&self) -> bool; - fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option; - fn derive_from_psbt_input(&self, psbt_input: &psbt::Input, utxo: Option) - -> Option; + fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths, secp: &SecpCtx) -> Option; + fn derive_from_psbt_input( + &self, + psbt_input: &psbt::Input, + utxo: Option, + secp: &SecpCtx, + ) -> Option; } pub(crate) trait DescriptorScripts { - fn psbt_redeem_script(&self) -> Option