Skip to content

Commit 64483f3

Browse files
committed
fix(get_key): for Xprv with key origin info
- fixes the implementation of `GetKey` for `Xprv` with `KeyRequest::Bip32` and a key_origin information. - adds a new test for a scenario where no wildcard is used, and an specific derivation index is used.
1 parent 1fafde2 commit 64483f3

File tree

2 files changed

+54
-11
lines changed

2 files changed

+54
-11
lines changed

src/descriptor/key_map.rs

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -136,18 +136,28 @@ impl GetKey for DescriptorSecretKey {
136136
return Ok(Some(key));
137137
}
138138

139-
if let Some(matched_path) = descriptor_xkey.matches(key_source, secp) {
139+
if descriptor_xkey.matches(key_source, secp).is_some() {
140140
let (_, full_path) = key_source;
141141

142-
let derivation_path = &full_path[matched_path.len()..];
143-
144-
return Ok(Some(
145-
descriptor_xkey
146-
.xkey
147-
.derive_priv(secp, &derivation_path)
148-
.map_err(GetKeyError::Bip32)?
149-
.to_priv(),
150-
));
142+
match &descriptor_xkey.origin {
143+
Some((_, origin_path)) => {
144+
let derivation_path = &full_path[origin_path.len()..];
145+
return Ok(Some(
146+
descriptor_xkey
147+
.xkey
148+
.derive_priv(secp, &derivation_path)?
149+
.to_priv(),
150+
));
151+
}
152+
None => {
153+
return Ok(Some(
154+
descriptor_xkey
155+
.xkey
156+
.derive_priv(secp, &full_path)?
157+
.to_priv(),
158+
))
159+
}
160+
};
151161
}
152162

153163
Ok(None)
@@ -314,7 +324,7 @@ mod tests {
314324
}
315325

316326
#[test]
317-
fn get_key_xpriv_with_key_origin() {
327+
fn get_key_xpriv_with_key_origin_and_wildcard() {
318328
let secp = Secp256k1::new();
319329

320330
let descriptor_str = "wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)";
@@ -345,6 +355,38 @@ mod tests {
345355
assert_eq!(pk, expected_pk);
346356
}
347357

358+
#[test]
359+
fn get_key_xpriv_with_key_origin_and_no_wildcard() {
360+
let secp = Secp256k1::new();
361+
362+
let descriptor_str = "wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/0)";
363+
let (_descriptor_pk, keymap) = Descriptor::parse_descriptor(&secp, descriptor_str).unwrap();
364+
365+
let descriptor_sk = DescriptorSecretKey::from_str("[d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/0").unwrap();
366+
let xpriv = match descriptor_sk {
367+
DescriptorSecretKey::XPrv(descriptor_xkey) => descriptor_xkey,
368+
_ => unreachable!(),
369+
};
370+
371+
let expected_deriv_path: DerivationPath = (&[ChildNumber::Normal { index: 0 }][..]).into();
372+
let expected_pk = xpriv
373+
.xkey
374+
.derive_priv(&secp, &expected_deriv_path)
375+
.unwrap()
376+
.to_priv();
377+
378+
let derivation_path = DerivationPath::from_str("84'/1'/0'/0").unwrap();
379+
let (fp, _) = xpriv.origin.unwrap();
380+
let key_request = KeyRequest::Bip32((fp, derivation_path));
381+
382+
let pk = keymap
383+
.get_key(key_request, &secp)
384+
.expect("get_key should not fail")
385+
.expect("get_key should return a `PrivateKey`");
386+
387+
assert_eq!(pk, expected_pk);
388+
}
389+
348390
#[test]
349391
fn get_key_keymap_no_match() {
350392
let secp = Secp256k1::new();

src/policy/concrete.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
347347
/// It is **not recommended** to use policy as a stable identifier for a miniscript. You should
348348
/// use the policy compiler once, and then use the miniscript output as a stable identifier. See
349349
/// the compiler document in [`doc/compiler.md`] for more details.
350+
#[allow(rustdoc::broken_intra_doc_links)]
350351
#[cfg(feature = "compiler")]
351352
pub fn compile_to_descriptor<Ctx: ScriptContext>(
352353
&self,

0 commit comments

Comments
 (0)