Skip to content

Commit df002e7

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 df002e7

File tree

1 file changed

+39
-5
lines changed

1 file changed

+39
-5
lines changed

src/descriptor/key_map.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,18 @@ 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()..];
142+
let derivation_path = match &descriptor_xkey.origin {
143+
Some((_, origin_path)) => &full_path[origin_path.len()..].into(),
144+
None => full_path,
145+
};
143146

144147
return Ok(Some(
145148
descriptor_xkey
146149
.xkey
147-
.derive_priv(secp, &derivation_path)
148-
.map_err(GetKeyError::Bip32)?
150+
.derive_priv(secp, &derivation_path)?
149151
.to_priv(),
150152
));
151153
}
@@ -314,7 +316,7 @@ mod tests {
314316
}
315317

316318
#[test]
317-
fn get_key_xpriv_with_key_origin() {
319+
fn get_key_xpriv_with_key_origin_and_wildcard() {
318320
let secp = Secp256k1::new();
319321

320322
let descriptor_str = "wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)";
@@ -345,6 +347,38 @@ mod tests {
345347
assert_eq!(pk, expected_pk);
346348
}
347349

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

0 commit comments

Comments
 (0)