]> Untitled Git - bdk/commitdiff
Bump rust-bitcoin to 0.25, fix Cargo dependencies
authorAlekos Filini <alekos.filini@gmail.com>
Fri, 9 Oct 2020 10:03:47 +0000 (12:03 +0200)
committerAlekos Filini <alekos.filini@gmail.com>
Tue, 13 Oct 2020 08:39:48 +0000 (10:39 +0200)
Closes #112, closes #113, closes #124

Cargo.toml
examples/parse_descriptor.rs
src/descriptor/error.rs
src/descriptor/mod.rs
src/descriptor/policy.rs
src/keys/mod.rs
src/wallet/mod.rs
src/wallet/signer.rs
src/wallet/tx_builder.rs
testutils/Cargo.toml
testutils/src/lib.rs

index ef1a0d2a48eb56cbcd8643b56a9d848336a3b192..ae590c50dadd3d1cbcd3588d21cea6d4c513aaaf 100644 (file)
@@ -7,15 +7,15 @@ authors = ["Alekos Filini <alekos.filini@gmail.com>", "Riccardo Casatta <riccard
 [dependencies]
 bdk-macros = { version = "0.1.0-beta.1", path = "./macros" }
 log = "^0.4"
-bitcoin = { version = "0.23", features = ["use-serde"] }
-miniscript = { version = "1.0" }
+bitcoin = { version = "0.25", features = ["use-serde"] }
+miniscript = { git = "https://github.com/MagicalBitcoin/rust-miniscript", rev = "dfc53201aa5796b6bf3b5a40581d192abaa84133" }
 serde = { version = "^1.0", features = ["derive"] }
 serde_json = { version = "^1.0" }
 rand = "^0.7"
 
 # Optional dependencies
 sled = { version = "0.34", optional = true }
-electrum-client = { version = "0.2.0-beta.1", optional = true }
+electrum-client = { version = "0.3.0-beta.1", optional = true }
 reqwest = { version = "0.10", optional = true, features = ["json"] }
 futures = { version = "0.3", optional = true }
 clap = { version = "2.33", optional = true }
@@ -26,10 +26,6 @@ socks = { version = "0.3", optional = true }
 lazy_static = { version = "1.4", optional = true }
 tiny-bip39 = { version = "^0.7", optional = true }
 
-[patch.crates-io]
-bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin/", rev = "478e091" }
-miniscript = { git = "https://github.com/MagicalBitcoin/rust-miniscript", rev = "d0322ac" }
-
 # Platform-specific dependencies
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
 tokio = { version = "0.2", features = ["rt-core"] }
index 73161c6045fb11aee28a0b01e4e263b18559ce8f..7728a82e570b827ba230949a83076d3c7e8172eb 100644 (file)
@@ -46,7 +46,7 @@ fn main() {
     let policy = extended_desc.extract_policy(signers).unwrap();
     println!("policy: {}", serde_json::to_string(&policy).unwrap());
 
-    let derived_desc = extended_desc.derive(&[ChildNumber::from_normal_idx(42).unwrap()]);
+    let derived_desc = extended_desc.derive(ChildNumber::from_normal_idx(42).unwrap());
     println!("{:?}", derived_desc);
 
     let addr = derived_desc.address(Network::Testnet).unwrap();
index 5730fc97f4bcbc5583fac3abd629ce35eb7e379a..14c5d8cc924acec0eb9858498a62df8e45efdefc 100644 (file)
@@ -31,6 +31,7 @@ pub enum Error {
     InvalidPrefix(Vec<u8>),
     HardenedDerivationOnXpub,
     MalformedInput,
+    InvalidHDKeyPath,
 
     KeyParsingError(String),
     Key(crate::keys::KeyError),
index 8632419d5182f8f61fd5c2ec7b1ad3f122600355..430b38773a0f8be2cdb591c3183fb986f1d5c23b 100644 (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)
+            }
+        };
 
-                if networks.contains(&network) {
-                    Ok(pk)
-                } else {
-                    Err(KeyError::InvalidNetwork)
-                }
-            },
-            |pkh| Ok::<_, KeyError>(*pkh),
-        )?;
+        // 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;
 
-        // 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(),
-                    };
+        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)
-                }
-            },
-            |pkh| Ok::<_, KeyError>(*pkh),
-        )?;
+                Ok(pk)
+            } else {
+                Err(KeyError::InvalidNetwork)
+            }
+        };
+
+        // fixup the network for keys that need it
+        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()) };
+        }
+
+        let mut answer_pk = BTreeMap::new();
+        let mut answer_pkh = BTreeMap::new();
 
-        self.translate_pk(translatefpk, translatefpkh)?;
+        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)
+        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();
+
+        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),
+        };
 
-        derive_path.map(|path| self.derive(path.as_ref()))
+        merged_path.map(|path| self.derive(path))
     }
 
     fn derive_from_psbt_input(
index 6c0246389297256fc9d85d702235567fc36c86a9..69441c24641909390c3bfb4e1f90d283df6ca5e5 100644 (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)
index 9aa17d334104f82119f8b320f3242af91564ab43..d8fe8bda989c5b69c1e9abb4a800f210cd41be8c 100644 (file)
@@ -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<Ctx: ScriptContext + 'static> 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<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
 ///
 /// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
 ///     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, 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<Ctx: ScriptContext> {
     /// 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<DescriptorKey<Ctx>, KeyError>;
 }
@@ -294,11 +299,11 @@ pub trait DerivableKey<Ctx: ScriptContext> {
 impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
     fn add_metadata(
         self,
-        source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
+        origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
         derivation_path: bip32::DerivationPath,
     ) -> Result<DescriptorKey<Ctx>, KeyError> {
         DescriptorPublicKey::XPub(DescriptorXKey {
-            source,
+            origin,
             xkey: self,
             derivation_path,
             is_wildcard: true,
@@ -310,11 +315,11 @@ impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
 impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
     fn add_metadata(
         self,
-        source: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
+        origin: Option<(bip32::Fingerprint, bip32::DerivationPath)>,
         derivation_path: bip32::DerivationPath,
     ) -> Result<DescriptorKey<Ctx>, 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<DescriptorKey<Ctx>, 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<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx> {
 impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, 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<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
 
 impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey {
     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        DescriptorPublicKey::PubKey(self).to_descriptor_key()
+        DescriptorPublicKey::SinglePub(DescriptorSinglePub {
+            key: self,
+            origin: None,
+        })
+        .to_descriptor_key()
     }
 }
 
 impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, 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<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
 
 impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PrivateKey {
     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        DescriptorSecretKey::PrivKey(self).to_descriptor_key()
+        DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
+            key: self,
+            origin: None,
+        })
+        .to_descriptor_key()
     }
 }
 
index 67a8570aac0bd2462dd365fed4d86dbf7c58815e..1629107be28688af7447b5625e9cc4662da8640b 100644 (file)
@@ -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<B: BlockchainMarker, D: BatchDatabase> {
     descriptor: ExtendedDescriptor,
     change_descriptor: Option<ExtendedDescriptor>,
 
-    signers: Arc<SignersContainer<DescriptorPublicKey>>,
-    change_signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    signers: Arc<SignersContainer>,
+    change_signers: Arc<SignersContainer>,
 
     address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
 
@@ -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<DescriptorPublicKey>,
+        id: SignerId,
         ordering: SignerOrdering,
         signer: Arc<Box<dyn Signer>>,
     ) {
@@ -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<Script, Error> {
@@ -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();
index 989d4d9d5bc52a121b78e32f9dadc598fcd5c34b..e6d8b4e4aa2e1926d755cf8264622d0f38bd8270 100644 (file)
@@ -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<Pk: MiniscriptKey> {
-    PkHash(<Pk as MiniscriptKey>::Hash),
+pub enum SignerId {
+    PkHash(hash160::Hash),
     Fingerprint(Fingerprint),
 }
 
-impl From<hash160::Hash> for SignerId<DescriptorPublicKey> {
-    fn from(hash: hash160::Hash) -> SignerId<DescriptorPublicKey> {
+impl From<hash160::Hash> for SignerId {
+    fn from(hash: hash160::Hash) -> SignerId {
         SignerId::PkHash(hash)
     }
 }
 
-impl From<Fingerprint> for SignerId<DescriptorPublicKey> {
-    fn from(fing: Fingerprint) -> SignerId<DescriptorPublicKey> {
+impl From<Fingerprint> for SignerId {
+    fn from(fing: Fingerprint) -> SignerId {
         SignerId::Fingerprint(fing)
     }
 }
@@ -284,7 +284,10 @@ impl Signer for PrivateKey {
     }
 
     fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        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<Pk: MiniscriptKey> {
-    id: SignerId<Pk>,
+struct SignersContainerKey {
+    id: SignerId,
     ordering: SignerOrdering,
 }
 
-impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContainerKey<Pk> {
-    fn from(tuple: (SignerId<Pk>, 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<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContaine
 
 /// Container for multiple signers
 #[derive(Debug, Default, Clone)]
-pub struct SignersContainer<Pk: MiniscriptKey>(
-    BTreeMap<SignersContainerKey<Pk>, Arc<Box<dyn Signer>>>,
-);
+pub struct SignersContainer(BTreeMap<SignersContainerKey, Arc<Box<dyn Signer>>>);
 
-impl SignersContainer<DescriptorPublicKey> {
+impl SignersContainer {
     pub fn as_key_map(&self) -> KeyMap {
         self.0
             .values()
@@ -333,20 +334,21 @@ impl SignersContainer<DescriptorPublicKey> {
     }
 }
 
-impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
-    fn from(keymap: KeyMap) -> SignersContainer<DescriptorPublicKey> {
+impl From<KeyMap> 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<KeyMap> for SignersContainer<DescriptorPublicKey> {
     }
 }
 
-impl<Pk: MiniscriptKey> SignersContainer<Pk> {
+impl SignersContainer {
     /// Default constructor
     pub fn new() -> Self {
         SignersContainer(Default::default())
@@ -370,7 +372,7 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
     /// signer that was previosuly in the container, if any
     pub fn add_external(
         &mut self,
-        id: SignerId<Pk>,
+        id: SignerId,
         ordering: SignerOrdering,
         signer: Arc<Box<dyn Signer>>,
     ) -> Option<Arc<Box<dyn Signer>>> {
@@ -380,14 +382,14 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
     /// Removes a signer from the container and returns it
     pub fn remove(
         &mut self,
-        id: SignerId<Pk>,
+        id: SignerId,
         ordering: SignerOrdering,
     ) -> Option<Arc<Box<dyn Signer>>> {
         self.0.remove(&(id, ordering).into())
     }
 
     /// Returns the list of identifiers of all the signers in the container
-    pub fn ids(&self) -> Vec<&SignerId<Pk>> {
+    pub fn ids(&self) -> Vec<&SignerId> {
         self.0
             .keys()
             .map(|SignersContainerKey { id, .. }| id)
@@ -400,7 +402,7 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
     }
 
     /// Finds the signer with lowest ordering for a given id in the container.
-    pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>> {
+    pub fn find(&self, id: SignerId) -> Option<&Arc<Box<dyn Signer>>> {
         self.0
             .range((
                 Included(&(id.clone(), SignerOrdering(0)).into()),
@@ -515,22 +517,22 @@ impl ComputeSighash for Segwitv0 {
     }
 }
 
-impl<Pk: MiniscriptKey> PartialOrd for SignersContainerKey<Pk> {
+impl PartialOrd for SignersContainerKey {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         Some(self.cmp(other))
     }
 }
 
-impl<Pk: MiniscriptKey> Ord for SignersContainerKey<Pk> {
+impl Ord for SignersContainerKey {
     fn cmp(&self, other: &Self) -> Ordering {
         self.ordering.cmp(&other.ordering)
     }
 }
 
-impl<Pk: MiniscriptKey> PartialEq for SignersContainerKey<Pk> {
+impl PartialEq for SignersContainerKey {
     fn eq(&self, other: &Self) -> bool {
         self.ordering == other.ordering
     }
 }
 
-impl<Pk: MiniscriptKey> Eq for SignersContainerKey<Pk> {}
+impl Eq for SignersContainerKey {}
index d24bd435deb32297019666b1fe2840eed566b636..017d26f7feb05960e177f5a3764e66354cb44d06 100644 (file)
@@ -206,7 +206,7 @@ impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
     ///
     /// 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 {
index 40e87eb99ca026e98dc878ec3334ea5f91818f38..77b4e4505eba3930fd15c9accab18a93c3c0e1a7 100644 (file)
@@ -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"
index 496f1b84a49d71bd5dd328b59a302d874f05e03c..b73a8de3443185be78e4b5bf7746ec7395416fd1 100644 (file)
@@ -119,13 +119,13 @@ macro_rules! testutils {
         use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
 
         let parsed = Descriptor::<DescriptorPublicKey>::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::<DescriptorPublicKey>::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(),
             )