Skip to content

Commit ff9419c

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 10fd701 commit ff9419c

File tree

1 file changed

+57
-12
lines changed

1 file changed

+57
-12
lines changed

src/descriptor/key_map.rs

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ pub struct KeyMapWrapper {
1212
}
1313

1414
impl From<KeyMap> for KeyMapWrapper {
15-
fn from(map: KeyMap) -> Self { KeyMapWrapper { map } }
15+
fn from(map: KeyMap) -> Self {
16+
KeyMapWrapper { map }
17+
}
1618
}
1719

1820
impl GetKey for KeyMapWrapper {
@@ -73,18 +75,28 @@ impl GetKey for DescriptorSecretKey {
7375
return Ok(Some(key));
7476
}
7577

76-
if let Some(matched_path) = descriptor_xkey.matches(key_source, secp) {
78+
if descriptor_xkey.matches(key_source, secp).is_some() {
7779
let (_, full_path) = key_source;
7880

79-
let derivation_path = &full_path[matched_path.len()..];
80-
81-
return Ok(Some(
82-
descriptor_xkey
83-
.xkey
84-
.derive_priv(secp, &derivation_path)
85-
.map_err(GetKeyError::Bip32)?
86-
.to_priv(),
87-
));
81+
match &descriptor_xkey.origin {
82+
Some((_, origin_path)) => {
83+
let derivation_path = &full_path[origin_path.len()..];
84+
return Ok(Some(
85+
descriptor_xkey
86+
.xkey
87+
.derive_priv(secp, &derivation_path)?
88+
.to_priv(),
89+
));
90+
}
91+
None => {
92+
return Ok(Some(
93+
descriptor_xkey
94+
.xkey
95+
.derive_priv(secp, &full_path)?
96+
.to_priv(),
97+
))
98+
}
99+
};
88100
}
89101

90102
Ok(None)
@@ -255,7 +267,7 @@ mod tests {
255267
}
256268

257269
#[test]
258-
fn get_key_xpriv_with_key_origin() {
270+
fn get_key_xpriv_with_key_origin_and_wildcard() {
259271
let secp = Secp256k1::new();
260272

261273
let descriptor_str = "wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)";
@@ -287,6 +299,39 @@ mod tests {
287299
assert_eq!(pk, expected_pk);
288300
}
289301

302+
#[test]
303+
fn get_key_xpriv_with_key_origin_and_no_wildcard() {
304+
let secp = Secp256k1::new();
305+
306+
let descriptor_str = "wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/0)";
307+
let (_descriptor_pk, keymap) = Descriptor::parse_descriptor(&secp, descriptor_str).unwrap();
308+
let keymap_wrapper = KeyMapWrapper::from(keymap);
309+
310+
let descriptor_sk = DescriptorSecretKey::from_str("[d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/0").unwrap();
311+
let xpriv = match descriptor_sk {
312+
DescriptorSecretKey::XPrv(descriptor_xkey) => descriptor_xkey,
313+
_ => unreachable!(),
314+
};
315+
316+
let expected_deriv_path: DerivationPath = (&[ChildNumber::Normal { index: 0 }][..]).into();
317+
let expected_pk = xpriv
318+
.xkey
319+
.derive_priv(&secp, &expected_deriv_path)
320+
.unwrap()
321+
.to_priv();
322+
323+
let derivation_path = DerivationPath::from_str("84'/1'/0'/0").unwrap();
324+
let (fp, _) = xpriv.origin.unwrap();
325+
let key_request = KeyRequest::Bip32((fp, derivation_path));
326+
327+
let pk = keymap_wrapper
328+
.get_key(key_request, &secp)
329+
.expect("get_key should not fail")
330+
.expect("get_key should return a `PrivateKey`");
331+
332+
assert_eq!(pk, expected_pk);
333+
}
334+
290335
#[test]
291336
fn get_key_keymap_no_match() {
292337
let secp = Secp256k1::new();

0 commit comments

Comments
 (0)