From 448fbd8d3a72ef0a2314697a644a6870adea712a Mon Sep 17 00:00:00 2001 From: Daniela Brozzoni <danielabrozzoni@protonmail.com> Date: Mon, 26 Jun 2023 19:10:42 +0200 Subject: [PATCH] Add full_derivation_paths on DescriptorPublicKey --- src/descriptor/key.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs index 83308e0dc..f39c5f05f 100644 --- a/src/descriptor/key.rs +++ b/src/descriptor/key.rs @@ -592,6 +592,33 @@ impl DescriptorPublicKey { } } + /// Returns a vector containing the full derivation paths from the master key. + /// The vector will contain just one element for single keys, and multiple elements + /// for multipath extended keys. + /// + /// For wildcard keys this will return the path up to the wildcard, so you + /// can get full paths by appending one additional derivation step, according + /// to the wildcard type (hardened or normal). + pub fn full_derivation_paths(&self) -> Vec<bip32::DerivationPath> { + match self { + DescriptorPublicKey::MultiXPub(xpub) => { + let origin_path = if let Some((_, ref path)) = xpub.origin { + path.clone() + } else { + bip32::DerivationPath::from(vec![]) + }; + xpub.derivation_paths + .paths() + .into_iter() + .map(|p| origin_path.extend(p)) + .collect() + } + _ => vec![self + .full_derivation_path() + .expect("Must be Some for non-multipath keys")], + } + } + /// Whether or not the key has a wildcard #[deprecated(note = "use has_wildcard instead")] pub fn is_deriveable(&self) -> bool { @@ -1075,6 +1102,12 @@ impl DefiniteDescriptorKey { self.0.full_derivation_path() } + /// Full paths from the master key. The vector will contain just one path for single + /// keys, and multiple ones for multipath extended keys + pub fn full_derivation_paths(&self) -> Vec<bip32::DerivationPath> { + self.0.full_derivation_paths() + } + /// Reference to the underlying `DescriptorPublicKey` pub fn as_descriptor_public_key(&self) -> &DescriptorPublicKey { &self.0 @@ -1476,6 +1509,14 @@ mod test { let desc_key = DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1>/8h/*'").unwrap(); assert!(desc_key.full_derivation_path().is_none()); assert!(desc_key.is_multipath()); + // But you can get all the derivation paths + assert_eq!( + desc_key.full_derivation_paths(), + vec![ + bip32::DerivationPath::from_str("m/0'/1'/9478'/0'/8'").unwrap(), + bip32::DerivationPath::from_str("m/0'/1'/9478'/1/8'").unwrap(), + ], + ); assert_eq!(desc_key.into_single_keys(), vec![DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/0'/8h/*'").unwrap(), DescriptorPublicKey::from_str("[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/1/8h/*'").unwrap()]); // All the same but with extended private keys instead of xpubs.