]> Untitled Git - bdk/commitdiff
handle descriptor xkey origin
authordavemo88 <david@kasofsk.xyz>
Thu, 11 Mar 2021 22:39:02 +0000 (17:39 -0500)
committerdavemo88 <david@kasofsk.xyz>
Thu, 11 Mar 2021 22:39:02 +0000 (17:39 -0500)
src/wallet/mod.rs
src/wallet/signer.rs

index 817d00283bb399e1a65e88a5e6d7b5be92b9009b..88831d388d923f8c9c90cd7743ce4cd85b1c3fe4 100644 (file)
@@ -3316,6 +3316,23 @@ mod test {
         assert_eq!(extracted.input[0].witness.len(), 2);
     }
 
+    #[test]
+    fn test_sign_single_xprv_with_master_fingerprint_and_path() {
+        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .set_single_recipient(addr.script_pubkey())
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
     #[test]
     fn test_sign_single_xprv_bip44_path() {
         let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
index 0dc22413b75ecb5f7474d337f2da25147faba8f8..f8efb844a2437f9f9d79c71a437ddfe1b825f1ac 100644 (file)
@@ -92,7 +92,7 @@ use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::script::Builder as ScriptBuilder;
 use bitcoin::hashes::{hash160, Hash};
 use bitcoin::secp256k1::{Message, Secp256k1};
-use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
+use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, Fingerprint};
 use bitcoin::util::{bip143, psbt};
 use bitcoin::{PrivateKey, Script, SigHash, SigHashType};
 
@@ -206,7 +206,7 @@ impl Signer for DescriptorXKey<ExtendedPrivKey> {
             return Err(SignerError::InputIndexOutOfRange);
         }
 
-        let (public_key, deriv_path) = match psbt.inputs[input_index]
+        let (public_key, full_path) = match psbt.inputs[input_index]
             .bip32_derivation
             .iter()
             .filter_map(|(pk, &(fingerprint, ref path))| {
@@ -222,7 +222,21 @@ impl Signer for DescriptorXKey<ExtendedPrivKey> {
             None => return Ok(()),
         };
 
-        let derived_key = self.xkey.derive_priv(&secp, &deriv_path).unwrap();
+        let derived_key = match self.origin.clone() {
+            Some((_fingerprint, path)) => {
+                let split_origin_path: Vec<&ChildNumber> = path.into_iter().collect();
+                let mut deriv_path = DerivationPath::default();
+                for (i, child) in full_path.into_iter().cloned().enumerate() {
+                    match split_origin_path.get(i) {
+                        Some(_) => continue,
+                        None => deriv_path = deriv_path.extend(&[child]),
+                    }
+                }
+                self.xkey.derive_priv(&secp, &deriv_path).unwrap()
+            }
+            None => self.xkey.derive_priv(&secp, &full_path).unwrap(),
+        };
+
         if &derived_key.private_key.public_key(&secp) != public_key {
             Err(SignerError::InvalidKey)
         } else {