diff --git a/src/descriptor/key_map.rs b/src/descriptor/key_map.rs index 00c797ee1..dd8dc7690 100644 --- a/src/descriptor/key_map.rs +++ b/src/descriptor/key_map.rs @@ -74,14 +74,27 @@ impl GetKey for DescriptorSecretKey { } if descriptor_xkey.matches(key_source, secp).is_some() { - let (_, derivation_path) = key_source; - return Ok(Some( - descriptor_xkey - .xkey - .derive_priv(secp, &derivation_path) - .map_err(GetKeyError::Bip32)? - .to_priv(), - )); + let (_, full_path) = key_source; + + match &descriptor_xkey.origin { + Some((_, origin_path)) => { + let derivation_path = &full_path[origin_path.len()..]; + return Ok(Some( + descriptor_xkey + .xkey + .derive_priv(secp, &derivation_path)? + .to_priv(), + )); + } + None => { + return Ok(Some( + descriptor_xkey + .xkey + .derive_priv(secp, &full_path)? + .to_priv(), + )) + } + }; } Ok(None) @@ -252,7 +265,7 @@ mod tests { } #[test] - fn get_key_xpriv_with_key_origin() { + fn get_key_xpriv_with_key_origin_and_wildcard() { let secp = Secp256k1::new(); let descriptor_str = "wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)"; @@ -265,11 +278,49 @@ mod tests { _ => unreachable!(), }; - let path = DerivationPath::from_str("84'/1'/0'/0").unwrap(); - let expected_pk = xpriv.xkey.derive_priv(&secp, &path).unwrap().to_priv(); + let expected_deriv_path: DerivationPath = (&[ChildNumber::Normal { index: 0 }][..]).into(); + let expected_pk = xpriv + .xkey + .derive_priv(&secp, &expected_deriv_path) + .unwrap() + .to_priv(); + + let derivation_path = DerivationPath::from_str("84'/1'/0'/0").unwrap(); + let (fp, _) = xpriv.origin.unwrap(); + let key_request = KeyRequest::Bip32((fp, derivation_path)); + + let pk = keymap_wrapper + .get_key(key_request, &secp) + .expect("get_key should not fail") + .expect("get_key should return a `PrivateKey`"); + + assert_eq!(pk, expected_pk); + } + + #[test] + fn get_key_xpriv_with_key_origin_and_no_wildcard() { + let secp = Secp256k1::new(); + + let descriptor_str = "wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/0)"; + let (_descriptor_pk, keymap) = Descriptor::parse_descriptor(&secp, descriptor_str).unwrap(); + let keymap_wrapper = KeyMapWrapper::from(keymap); + + let descriptor_sk = DescriptorSecretKey::from_str("[d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/0").unwrap(); + let xpriv = match descriptor_sk { + DescriptorSecretKey::XPrv(descriptor_xkey) => descriptor_xkey, + _ => unreachable!(), + }; + + let expected_deriv_path: DerivationPath = (&[ChildNumber::Normal { index: 0 }][..]).into(); + let expected_pk = xpriv + .xkey + .derive_priv(&secp, &expected_deriv_path) + .unwrap() + .to_priv(); + let derivation_path = DerivationPath::from_str("84'/1'/0'/0").unwrap(); let (fp, _) = xpriv.origin.unwrap(); - let key_request = KeyRequest::Bip32((fp, path)); + let key_request = KeyRequest::Bip32((fp, derivation_path)); let pk = keymap_wrapper .get_key(key_request, &secp) diff --git a/src/policy/concrete.rs b/src/policy/concrete.rs index 6c4321326..75d31a400 100644 --- a/src/policy/concrete.rs +++ b/src/policy/concrete.rs @@ -350,6 +350,7 @@ impl Policy { /// It is **not recommended** to use policy as a stable identifier for a miniscript. You should /// use the policy compiler once, and then use the miniscript output as a stable identifier. See /// the compiler document in [`doc/compiler.md`] for more details. + #[allow(rustdoc::broken_intra_doc_links)] #[cfg(feature = "compiler")] pub fn compile_to_descriptor( &self,