@@ -285,6 +285,20 @@ impl error::Error for DescriptorKeyParseError {
285285 }
286286}
287287
288+ impl fmt:: Display for DescriptorExtendedPublicKey {
289+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
290+ maybe_fmt_master_id ( f, & self . origin ) ?;
291+ self . xkey . fmt ( f) ?;
292+ fmt_derivation_path ( f, & self . derivation_path ) ?;
293+ match self . wildcard {
294+ Wildcard :: None => { }
295+ Wildcard :: Unhardened => write ! ( f, "/*" ) ?,
296+ Wildcard :: Hardened => write ! ( f, "/*h" ) ?,
297+ }
298+ Ok ( ( ) )
299+ }
300+ }
301+
288302impl fmt:: Display for DescriptorPublicKey {
289303 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
290304 match * self {
@@ -296,17 +310,7 @@ impl fmt::Display for DescriptorPublicKey {
296310 } ?;
297311 Ok ( ( ) )
298312 }
299- DescriptorPublicKey :: XPub ( ref xpub) => {
300- maybe_fmt_master_id ( f, & xpub. origin ) ?;
301- xpub. xkey . fmt ( f) ?;
302- fmt_derivation_path ( f, & xpub. derivation_path ) ?;
303- match xpub. wildcard {
304- Wildcard :: None => { }
305- Wildcard :: Unhardened => write ! ( f, "/*" ) ?,
306- Wildcard :: Hardened => write ! ( f, "/*h" ) ?,
307- }
308- Ok ( ( ) )
309- }
313+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. fmt ( f) ,
310314 DescriptorPublicKey :: MultiXPub ( ref xpub) => {
311315 maybe_fmt_master_id ( f, & xpub. origin ) ?;
312316 xpub. xkey . fmt ( f) ?;
@@ -527,17 +531,85 @@ impl error::Error for ConversionError {
527531 }
528532}
529533
534+ impl DescriptorExtendedPublicKey {
535+ /// The fingerprint of the master key associated with this key, `0x00000000` if none.
536+ pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
537+ if let Some ( ( fingerprint, _) ) = self . origin {
538+ fingerprint
539+ } else {
540+ self . xkey . fingerprint ( )
541+ }
542+ }
543+
544+ /// Full path, from the master key
545+ ///
546+ /// For wildcard keys this will return the path up to the wildcard, so you
547+ /// can get full paths by appending one additional derivation step, according
548+ /// to the wildcard type (hardened or normal).
549+ ///
550+ /// For multipath extended keys, this returns `None`.
551+ pub fn full_derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
552+ let origin_path = if let Some ( ( _, ref path) ) = self . origin {
553+ path. clone ( )
554+ } else {
555+ bip32:: DerivationPath :: from ( vec ! [ ] )
556+ } ;
557+ Some ( origin_path. extend ( & self . derivation_path ) )
558+ }
559+
560+ /// Whether or not the key has a wildcard
561+ pub fn has_wildcard ( & self ) -> bool {
562+ self . wildcard != Wildcard :: None
563+ }
564+
565+ /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
566+ /// *definite* key (i.e. one where all the derivation paths are set).
567+ ///
568+ /// # Returns
569+ ///
570+ /// - If this key is not an xpub, returns `self`.
571+ /// - If this key is an xpub but does not have a wildcard, returns `self`.
572+ /// - Otherwise, returns the xpub at derivation `index` (removing the wildcard).
573+ ///
574+ /// # Errors
575+ ///
576+ /// - If `index` is hardened.
577+ pub fn at_derivation_index ( self , index : u32 ) -> Result < DefiniteDescriptorKey , ConversionError > {
578+ let derivation_path = match self . wildcard {
579+ Wildcard :: None => self . derivation_path ,
580+ Wildcard :: Unhardened => self . derivation_path . into_child (
581+ bip32:: ChildNumber :: from_normal_idx ( index)
582+ . ok ( )
583+ . ok_or ( ConversionError :: HardenedChild ) ?,
584+ ) ,
585+ Wildcard :: Hardened => self . derivation_path . into_child (
586+ bip32:: ChildNumber :: from_hardened_idx ( index)
587+ . ok ( )
588+ . ok_or ( ConversionError :: HardenedChild ) ?,
589+ ) ,
590+ } ;
591+ let definite = DescriptorPublicKey :: XPub ( DescriptorXKey {
592+ origin : self . origin ,
593+ xkey : self . xkey ,
594+ derivation_path,
595+ wildcard : Wildcard :: None ,
596+ } ) ;
597+
598+ Ok ( DefiniteDescriptorKey :: new ( definite)
599+ . expect ( "The key should not contain any wildcards at this point" ) )
600+ }
601+
602+ /// Whether or not this key has multiple derivation paths.
603+ pub fn is_multipath ( & self ) -> bool {
604+ false
605+ }
606+ }
607+
530608impl DescriptorPublicKey {
531609 /// The fingerprint of the master key associated with this key, `0x00000000` if none.
532610 pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
533611 match * self {
534- DescriptorPublicKey :: XPub ( ref xpub) => {
535- if let Some ( ( fingerprint, _) ) = xpub. origin {
536- fingerprint
537- } else {
538- xpub. xkey . fingerprint ( )
539- }
540- }
612+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. master_fingerprint ( ) ,
541613 DescriptorPublicKey :: MultiXPub ( ref xpub) => {
542614 if let Some ( ( fingerprint, _) ) = xpub. origin {
543615 fingerprint
@@ -575,14 +647,7 @@ impl DescriptorPublicKey {
575647 /// For multipath extended keys, this returns `None`.
576648 pub fn full_derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
577649 match * self {
578- DescriptorPublicKey :: XPub ( ref xpub) => {
579- let origin_path = if let Some ( ( _, ref path) ) = xpub. origin {
580- path. clone ( )
581- } else {
582- bip32:: DerivationPath :: from ( vec ! [ ] )
583- } ;
584- Some ( origin_path. extend ( & xpub. derivation_path ) )
585- }
650+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. full_derivation_path ( ) ,
586651 DescriptorPublicKey :: Single ( ref single) => {
587652 Some ( if let Some ( ( _, ref path) ) = single. origin {
588653 path. clone ( )
@@ -604,7 +669,7 @@ impl DescriptorPublicKey {
604669 pub fn has_wildcard ( & self ) -> bool {
605670 match * self {
606671 DescriptorPublicKey :: Single ( ..) => false ,
607- DescriptorPublicKey :: XPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
672+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. has_wildcard ( ) ,
608673 DescriptorPublicKey :: MultiXPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
609674 }
610675 }
@@ -628,40 +693,19 @@ impl DescriptorPublicKey {
628693 ///
629694 /// - If `index` is hardened.
630695 pub fn at_derivation_index ( self , index : u32 ) -> Result < DefiniteDescriptorKey , ConversionError > {
631- let definite = match self {
632- DescriptorPublicKey :: Single ( _) => self ,
633- DescriptorPublicKey :: XPub ( xpub) => {
634- let derivation_path = match xpub. wildcard {
635- Wildcard :: None => xpub. derivation_path ,
636- Wildcard :: Unhardened => xpub. derivation_path . into_child (
637- bip32:: ChildNumber :: from_normal_idx ( index)
638- . ok ( )
639- . ok_or ( ConversionError :: HardenedChild ) ?,
640- ) ,
641- Wildcard :: Hardened => xpub. derivation_path . into_child (
642- bip32:: ChildNumber :: from_hardened_idx ( index)
643- . ok ( )
644- . ok_or ( ConversionError :: HardenedChild ) ?,
645- ) ,
646- } ;
647- DescriptorPublicKey :: XPub ( DescriptorXKey {
648- origin : xpub. origin ,
649- xkey : xpub. xkey ,
650- derivation_path,
651- wildcard : Wildcard :: None ,
652- } )
653- }
654- DescriptorPublicKey :: MultiXPub ( _) => return Err ( ConversionError :: MultiKey ) ,
655- } ;
656-
657- Ok ( DefiniteDescriptorKey :: new ( definite)
658- . expect ( "The key should not contain any wildcards at this point" ) )
696+ match self {
697+ DescriptorPublicKey :: Single ( _) => Ok ( DefiniteDescriptorKey :: new ( self )
698+ . expect ( "The key should not contain any wildcards at this point" ) ) ,
699+ DescriptorPublicKey :: XPub ( xpub) => xpub. at_derivation_index ( index) ,
700+ DescriptorPublicKey :: MultiXPub ( _) => Err ( ConversionError :: MultiKey ) ,
701+ }
659702 }
660703
661704 /// Whether or not this key has multiple derivation paths.
662705 pub fn is_multipath ( & self ) -> bool {
663706 match * self {
664- DescriptorPublicKey :: Single ( ..) | DescriptorPublicKey :: XPub ( ..) => false ,
707+ DescriptorPublicKey :: Single ( ..) => false ,
708+ DescriptorPublicKey :: XPub ( ..) => self . is_multipath ( ) ,
665709 DescriptorPublicKey :: MultiXPub ( _) => true ,
666710 }
667711 }
0 commit comments