@@ -18,13 +18,15 @@ use crate::prelude::*;
1818use crate :: serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
1919use crate :: { hash256, MiniscriptKey , ToPublicKey } ;
2020
21+ type DescriptorExtendedPublicKey = DescriptorXKey < bip32:: ExtendedPubKey > ;
22+
2123/// The descriptor pubkey, either a single pubkey or an xpub.
2224#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
2325pub enum DescriptorPublicKey {
2426 /// Single public key.
2527 Single ( SinglePub ) ,
2628 /// Extended public key (xpub).
27- XPub ( DescriptorXKey < bip32 :: ExtendedPubKey > ) ,
29+ XPub ( DescriptorExtendedPublicKey ) ,
2830 /// Multiple extended public keys.
2931 MultiXPub ( DescriptorMultiXKey < bip32:: ExtendedPubKey > ) ,
3032}
@@ -283,6 +285,20 @@ impl error::Error for DescriptorKeyParseError {
283285 }
284286}
285287
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+
286302impl fmt:: Display for DescriptorPublicKey {
287303 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
288304 match * self {
@@ -294,17 +310,7 @@ impl fmt::Display for DescriptorPublicKey {
294310 } ?;
295311 Ok ( ( ) )
296312 }
297- DescriptorPublicKey :: XPub ( ref xpub) => {
298- maybe_fmt_master_id ( f, & xpub. origin ) ?;
299- xpub. xkey . fmt ( f) ?;
300- fmt_derivation_path ( f, & xpub. derivation_path ) ?;
301- match xpub. wildcard {
302- Wildcard :: None => { }
303- Wildcard :: Unhardened => write ! ( f, "/*" ) ?,
304- Wildcard :: Hardened => write ! ( f, "/*h" ) ?,
305- }
306- Ok ( ( ) )
307- }
313+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. fmt ( f) ,
308314 DescriptorPublicKey :: MultiXPub ( ref xpub) => {
309315 maybe_fmt_master_id ( f, & xpub. origin ) ?;
310316 xpub. xkey . fmt ( f) ?;
@@ -558,17 +564,86 @@ pub trait DescriptorInnerKey {
558564 /// Whether or not this key has multiple derivation paths.
559565 fn is_multipath ( & self ) -> bool ;
560566}
567+
568+ impl DescriptorInnerKey for DescriptorExtendedPublicKey {
569+ /// The fingerprint of the master key associated with this key, `0x00000000` if none.
570+ fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
571+ if let Some ( ( fingerprint, _) ) = self . origin {
572+ fingerprint
573+ } else {
574+ self . xkey . fingerprint ( )
575+ }
576+ }
577+
578+ /// Full path, from the master key
579+ ///
580+ /// For wildcard keys this will return the path up to the wildcard, so you
581+ /// can get full paths by appending one additional derivation step, according
582+ /// to the wildcard type (hardened or normal).
583+ ///
584+ /// For multipath extended keys, this returns `None`.
585+ fn full_derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
586+ let origin_path = if let Some ( ( _, ref path) ) = self . origin {
587+ path. clone ( )
588+ } else {
589+ bip32:: DerivationPath :: from ( vec ! [ ] )
590+ } ;
591+ Some ( origin_path. extend ( & self . derivation_path ) )
592+ }
593+
594+ /// Whether or not the key has a wildcard
595+ fn has_wildcard ( & self ) -> bool {
596+ self . wildcard != Wildcard :: None
597+ }
598+
599+ /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
600+ /// *definite* key (i.e. one where all the derivation paths are set).
601+ ///
602+ /// # Returns
603+ ///
604+ /// - If this key is not an xpub, returns `self`.
605+ /// - If this key is an xpub but does not have a wildcard, returns `self`.
606+ /// - Otherwise, returns the xpub at derivation `index` (removing the wildcard).
607+ ///
608+ /// # Errors
609+ ///
610+ /// - If `index` is hardened.
611+ fn at_derivation_index ( self , index : u32 ) -> Result < DefiniteDescriptorKey , ConversionError > {
612+ let derivation_path = match self . wildcard {
613+ Wildcard :: None => self . derivation_path ,
614+ Wildcard :: Unhardened => self . derivation_path . into_child (
615+ bip32:: ChildNumber :: from_normal_idx ( index)
616+ . ok ( )
617+ . ok_or ( ConversionError :: HardenedChild ) ?,
618+ ) ,
619+ Wildcard :: Hardened => self . derivation_path . into_child (
620+ bip32:: ChildNumber :: from_hardened_idx ( index)
621+ . ok ( )
622+ . ok_or ( ConversionError :: HardenedChild ) ?,
623+ ) ,
624+ } ;
625+ let definite = DescriptorPublicKey :: XPub ( DescriptorXKey {
626+ origin : self . origin ,
627+ xkey : self . xkey ,
628+ derivation_path,
629+ wildcard : Wildcard :: None ,
630+ } ) ;
631+
632+ Ok ( DefiniteDescriptorKey :: new ( definite)
633+ . expect ( "The key should not contain any wildcards at this point" ) )
634+ }
635+
636+ /// Whether or not this key has multiple derivation paths.
637+ fn is_multipath ( & self ) -> bool {
638+ false
639+ }
640+ }
641+
561642impl DescriptorPublicKey {
562643 /// The fingerprint of the master key associated with this key, `0x00000000` if none.
563644 pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
564645 match * self {
565- DescriptorPublicKey :: XPub ( ref xpub) => {
566- if let Some ( ( fingerprint, _) ) = xpub. origin {
567- fingerprint
568- } else {
569- xpub. xkey . fingerprint ( )
570- }
571- }
646+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. master_fingerprint ( ) ,
572647 DescriptorPublicKey :: MultiXPub ( ref xpub) => {
573648 if let Some ( ( fingerprint, _) ) = xpub. origin {
574649 fingerprint
@@ -606,14 +681,7 @@ impl DescriptorPublicKey {
606681 /// For multipath extended keys, this returns `None`.
607682 pub fn full_derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
608683 match * self {
609- DescriptorPublicKey :: XPub ( ref xpub) => {
610- let origin_path = if let Some ( ( _, ref path) ) = xpub. origin {
611- path. clone ( )
612- } else {
613- bip32:: DerivationPath :: from ( vec ! [ ] )
614- } ;
615- Some ( origin_path. extend ( & xpub. derivation_path ) )
616- }
684+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. full_derivation_path ( ) ,
617685 DescriptorPublicKey :: Single ( ref single) => {
618686 Some ( if let Some ( ( _, ref path) ) = single. origin {
619687 path. clone ( )
@@ -635,7 +703,7 @@ impl DescriptorPublicKey {
635703 pub fn has_wildcard ( & self ) -> bool {
636704 match * self {
637705 DescriptorPublicKey :: Single ( ..) => false ,
638- DescriptorPublicKey :: XPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
706+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. has_wildcard ( ) ,
639707 DescriptorPublicKey :: MultiXPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
640708 }
641709 }
@@ -659,40 +727,19 @@ impl DescriptorPublicKey {
659727 ///
660728 /// - If `index` is hardened.
661729 pub fn at_derivation_index ( self , index : u32 ) -> Result < DefiniteDescriptorKey , ConversionError > {
662- let definite = match self {
663- DescriptorPublicKey :: Single ( _) => self ,
664- DescriptorPublicKey :: XPub ( xpub) => {
665- let derivation_path = match xpub. wildcard {
666- Wildcard :: None => xpub. derivation_path ,
667- Wildcard :: Unhardened => xpub. derivation_path . into_child (
668- bip32:: ChildNumber :: from_normal_idx ( index)
669- . ok ( )
670- . ok_or ( ConversionError :: HardenedChild ) ?,
671- ) ,
672- Wildcard :: Hardened => xpub. derivation_path . into_child (
673- bip32:: ChildNumber :: from_hardened_idx ( index)
674- . ok ( )
675- . ok_or ( ConversionError :: HardenedChild ) ?,
676- ) ,
677- } ;
678- DescriptorPublicKey :: XPub ( DescriptorXKey {
679- origin : xpub. origin ,
680- xkey : xpub. xkey ,
681- derivation_path,
682- wildcard : Wildcard :: None ,
683- } )
684- }
685- DescriptorPublicKey :: MultiXPub ( _) => return Err ( ConversionError :: MultiKey ) ,
686- } ;
687-
688- Ok ( DefiniteDescriptorKey :: new ( definite)
689- . expect ( "The key should not contain any wildcards at this point" ) )
730+ match self {
731+ DescriptorPublicKey :: Single ( _) => Ok ( DefiniteDescriptorKey :: new ( self )
732+ . expect ( "The key should not contain any wildcards at this point" ) ) ,
733+ DescriptorPublicKey :: XPub ( xpub) => xpub. at_derivation_index ( index) ,
734+ DescriptorPublicKey :: MultiXPub ( _) => Err ( ConversionError :: MultiKey ) ,
735+ }
690736 }
691737
692738 /// Whether or not this key has multiple derivation paths.
693739 pub fn is_multipath ( & self ) -> bool {
694- match * self {
695- DescriptorPublicKey :: Single ( ..) | DescriptorPublicKey :: XPub ( ..) => false ,
740+ match self {
741+ DescriptorPublicKey :: Single ( ..) => false ,
742+ DescriptorPublicKey :: XPub ( xpub) => xpub. is_multipath ( ) ,
696743 DescriptorPublicKey :: MultiXPub ( _) => true ,
697744 }
698745 }
0 commit comments