@@ -18,13 +18,15 @@ use crate::prelude::*;
18
18
use crate :: serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
19
19
use crate :: { hash256, MiniscriptKey , ToPublicKey } ;
20
20
21
+ type DescriptorExtendedPublicKey = DescriptorXKey < bip32:: ExtendedPubKey > ;
22
+
21
23
/// The descriptor pubkey, either a single pubkey or an xpub.
22
24
#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
23
25
pub enum DescriptorPublicKey {
24
26
/// Single public key.
25
27
Single ( SinglePub ) ,
26
28
/// Extended public key (xpub).
27
- XPub ( DescriptorXKey < bip32 :: ExtendedPubKey > ) ,
29
+ XPub ( DescriptorExtendedPublicKey ) ,
28
30
/// Multiple extended public keys.
29
31
MultiXPub ( DescriptorMultiXKey < bip32:: ExtendedPubKey > ) ,
30
32
}
@@ -283,6 +285,20 @@ impl error::Error for DescriptorKeyParseError {
283
285
}
284
286
}
285
287
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
+
286
302
impl fmt:: Display for DescriptorPublicKey {
287
303
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
288
304
match * self {
@@ -294,17 +310,7 @@ impl fmt::Display for DescriptorPublicKey {
294
310
} ?;
295
311
Ok ( ( ) )
296
312
}
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) ,
308
314
DescriptorPublicKey :: MultiXPub ( ref xpub) => {
309
315
maybe_fmt_master_id ( f, & xpub. origin ) ?;
310
316
xpub. xkey . fmt ( f) ?;
@@ -558,17 +564,86 @@ pub trait DescriptorInnerKey {
558
564
/// Whether or not this key has multiple derivation paths.
559
565
fn is_multipath ( & self ) -> bool ;
560
566
}
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
+
561
642
impl DescriptorPublicKey {
562
643
/// The fingerprint of the master key associated with this key, `0x00000000` if none.
563
644
pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
564
645
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 ( ) ,
572
647
DescriptorPublicKey :: MultiXPub ( ref xpub) => {
573
648
if let Some ( ( fingerprint, _) ) = xpub. origin {
574
649
fingerprint
@@ -606,14 +681,7 @@ impl DescriptorPublicKey {
606
681
/// For multipath extended keys, this returns `None`.
607
682
pub fn full_derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
608
683
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 ( ) ,
617
685
DescriptorPublicKey :: Single ( ref single) => {
618
686
Some ( if let Some ( ( _, ref path) ) = single. origin {
619
687
path. clone ( )
@@ -635,7 +703,7 @@ impl DescriptorPublicKey {
635
703
pub fn has_wildcard ( & self ) -> bool {
636
704
match * self {
637
705
DescriptorPublicKey :: Single ( ..) => false ,
638
- DescriptorPublicKey :: XPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
706
+ DescriptorPublicKey :: XPub ( ref xpub) => xpub. has_wildcard ( ) ,
639
707
DescriptorPublicKey :: MultiXPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
640
708
}
641
709
}
@@ -659,40 +727,19 @@ impl DescriptorPublicKey {
659
727
///
660
728
/// - If `index` is hardened.
661
729
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
+ }
690
736
}
691
737
692
738
/// Whether or not this key has multiple derivation paths.
693
739
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 ( ) ,
696
743
DescriptorPublicKey :: MultiXPub ( _) => true ,
697
744
}
698
745
}
0 commit comments