@@ -83,6 +83,11 @@ impl DerivPaths {
83
83
pub fn paths ( & self ) -> & Vec < bip32:: DerivationPath > {
84
84
& self . 0
85
85
}
86
+
87
+ /// Get the list of derivation paths.
88
+ pub fn into_paths ( self ) -> Vec < bip32:: DerivationPath > {
89
+ self . 0
90
+ }
86
91
}
87
92
88
93
/// Instance of one or more extended keys, as specified in BIP 389.
@@ -334,6 +339,45 @@ impl DescriptorSecretKey {
334
339
335
340
Ok ( pk)
336
341
}
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
+ }
337
381
}
338
382
339
383
/// Writes the fingerprint of the origin, if there is one.
@@ -604,6 +648,45 @@ impl DescriptorPublicKey {
604
648
Ok ( DefiniteDescriptorKey :: new ( definite)
605
649
. expect ( "The key should not contain any wildcards at this point" ) )
606
650
}
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
+ }
607
690
}
608
691
609
692
impl FromStr for DescriptorSecretKey {
@@ -1337,6 +1420,8 @@ mod test {
1337
1420
// You can't get the "full derivation path" for a multipath extended public key.
1338
1421
let desc_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/9478'/<0';1>/8h/*'" ) . unwrap ( ) ;
1339
1422
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( ) ] ) ;
1340
1425
1341
1426
// All the same but with extended private keys instead of xpubs.
1342
1427
let xprv = get_multipath_xprv ( "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/2/<0;1;42;9854>" ) ;
@@ -1408,6 +1493,8 @@ mod test {
1408
1493
) ;
1409
1494
let desc_key = DescriptorSecretKey :: from_str ( "[abcdef00/0'/1']tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/9478'/<0';1>/8h/*'" ) . unwrap ( ) ;
1410
1495
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( ) ] ) ;
1411
1498
1412
1499
// It's invalid to:
1413
1500
// - Not have opening or closing brackets
0 commit comments