@@ -83,6 +83,11 @@ impl DerivPaths {
8383 pub fn paths ( & self ) -> & Vec < bip32:: DerivationPath > {
8484 & self . 0
8585 }
86+
87+ /// Get the list of derivation paths.
88+ pub fn into_paths ( self ) -> Vec < bip32:: DerivationPath > {
89+ self . 0
90+ }
8691}
8792
8893/// Instance of one or more extended keys, as specified in BIP 389.
@@ -334,6 +339,45 @@ impl DescriptorSecretKey {
334339
335340 Ok ( pk)
336341 }
342+
343+ /// Whether or not this key has multiple derivation paths.
344+ pub fn is_multipath ( & self ) -> bool {
345+ match * self {
346+ DescriptorSecretKey :: Single ( ..) | DescriptorSecretKey :: XPrv ( ..) => false ,
347+ DescriptorSecretKey :: MultiXPrv ( _) => true ,
348+ }
349+ }
350+
351+ /// Get as many keys as derivation paths in this key.
352+ ///
353+ /// For raw keys and single-path extended keys it will return the key itself.
354+ /// For multipath extended keys it will return a single-path extended key per derivation
355+ /// path.
356+ pub fn into_single_keys ( self ) -> Vec < DescriptorSecretKey > {
357+ match self {
358+ DescriptorSecretKey :: Single ( ..) | DescriptorSecretKey :: XPrv ( ..) => vec ! [ self ] ,
359+ DescriptorSecretKey :: MultiXPrv ( xpub) => {
360+ let DescriptorMultiXKey {
361+ origin,
362+ xkey,
363+ derivation_paths,
364+ wildcard,
365+ } = xpub;
366+ derivation_paths
367+ . into_paths ( )
368+ . into_iter ( )
369+ . map ( |derivation_path| {
370+ DescriptorSecretKey :: XPrv ( DescriptorXKey {
371+ origin : origin. clone ( ) ,
372+ xkey,
373+ derivation_path,
374+ wildcard,
375+ } )
376+ } )
377+ . collect ( )
378+ }
379+ }
380+ }
337381}
338382
339383/// Writes the fingerprint of the origin, if there is one.
@@ -604,6 +648,45 @@ impl DescriptorPublicKey {
604648 Ok ( DefiniteDescriptorKey :: new ( definite)
605649 . expect ( "The key should not contain any wildcards at this point" ) )
606650 }
651+
652+ /// Whether or not this key has multiple derivation paths.
653+ pub fn is_multipath ( & self ) -> bool {
654+ match * self {
655+ DescriptorPublicKey :: Single ( ..) | DescriptorPublicKey :: XPub ( ..) => false ,
656+ DescriptorPublicKey :: MultiXPub ( _) => true ,
657+ }
658+ }
659+
660+ /// Get as many keys as derivation paths in this key.
661+ ///
662+ /// For raw public key and single-path extended keys it will return the key itself.
663+ /// For multipath extended keys it will return a single-path extended key per derivation
664+ /// path.
665+ pub fn into_single_keys ( self ) -> Vec < DescriptorPublicKey > {
666+ match self {
667+ DescriptorPublicKey :: Single ( ..) | DescriptorPublicKey :: XPub ( ..) => vec ! [ self ] ,
668+ DescriptorPublicKey :: MultiXPub ( xpub) => {
669+ let DescriptorMultiXKey {
670+ origin,
671+ xkey,
672+ derivation_paths,
673+ wildcard,
674+ } = xpub;
675+ derivation_paths
676+ . into_paths ( )
677+ . into_iter ( )
678+ . map ( |derivation_path| {
679+ DescriptorPublicKey :: XPub ( DescriptorXKey {
680+ origin : origin. clone ( ) ,
681+ xkey,
682+ derivation_path,
683+ wildcard,
684+ } )
685+ } )
686+ . collect ( )
687+ }
688+ }
689+ }
607690}
608691
609692impl FromStr for DescriptorSecretKey {
@@ -1337,6 +1420,8 @@ mod test {
13371420 // You can't get the "full derivation path" for a multipath extended public key.
13381421 let desc_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1>/8h/*'" ) . unwrap ( ) ;
13391422 assert ! ( desc_key. full_derivation_path( ) . is_none( ) ) ;
1423+ assert ! ( desc_key. is_multipath( ) ) ;
1424+ 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( ) ] ) ;
13401425
13411426 // All the same but with extended private keys instead of xpubs.
13421427 let xprv = get_multipath_xprv ( "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;42;9854>" ) ;
@@ -1408,6 +1493,8 @@ mod test {
14081493 ) ;
14091494 let desc_key = DescriptorSecretKey :: from_str ( "[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1>/8h/*'" ) . unwrap ( ) ;
14101495 assert ! ( desc_key. to_public( & secp) . is_err( ) ) ;
1496+ assert ! ( desc_key. is_multipath( ) ) ;
1497+ assert_eq ! ( desc_key. into_single_keys( ) , vec![ DescriptorSecretKey :: from_str( "[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/0'/8h/*'" ) . unwrap( ) , DescriptorSecretKey :: from_str( "[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/1/8h/*'" ) . unwrap( ) ] ) ;
14111498
14121499 // It's invalid to:
14131500 // - Not have opening or closing brackets
0 commit comments