@@ -20,6 +20,7 @@ use crate::{hash256, MiniscriptKey, ToPublicKey};
2020
2121type DescriptorSinglePublicKey = SinglePub ;
2222type DescriptorExtendedPublicKey = DescriptorXKey < bip32:: ExtendedPubKey > ;
23+ type DescriptorMultiExtendedPublicKey = DescriptorMultiXKey < bip32:: ExtendedPubKey > ;
2324
2425/// The descriptor pubkey, either a single pubkey or an xpub.
2526#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
@@ -29,7 +30,7 @@ pub enum DescriptorPublicKey {
2930 /// Extended public key (xpub).
3031 XPub ( DescriptorExtendedPublicKey ) ,
3132 /// Multiple extended public keys.
32- MultiXPub ( DescriptorMultiXKey < bip32 :: ExtendedPubKey > ) ,
33+ MultiXPub ( DescriptorMultiExtendedPublicKey ) ,
3334}
3435
3536/// The descriptor secret key, either a single private key or an xprv.
@@ -310,22 +311,26 @@ impl fmt::Display for DescriptorExtendedPublicKey {
310311 }
311312}
312313
314+ impl fmt:: Display for DescriptorMultiExtendedPublicKey {
315+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
316+ maybe_fmt_master_id ( f, & self . origin ) ?;
317+ self . xkey . fmt ( f) ?;
318+ fmt_derivation_paths ( f, self . derivation_paths . paths ( ) ) ?;
319+ match self . wildcard {
320+ Wildcard :: None => { }
321+ Wildcard :: Unhardened => write ! ( f, "/*" ) ?,
322+ Wildcard :: Hardened => write ! ( f, "/*h" ) ?,
323+ }
324+ Ok ( ( ) )
325+ }
326+ }
327+
313328impl fmt:: Display for DescriptorPublicKey {
314329 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
315330 match * self {
316331 DescriptorPublicKey :: Single ( ref pk) => pk. fmt ( f) ,
317332 DescriptorPublicKey :: XPub ( ref xpub) => xpub. fmt ( f) ,
318- DescriptorPublicKey :: MultiXPub ( ref xpub) => {
319- maybe_fmt_master_id ( f, & xpub. origin ) ?;
320- xpub. xkey . fmt ( f) ?;
321- fmt_derivation_paths ( f, xpub. derivation_paths . paths ( ) ) ?;
322- match xpub. wildcard {
323- Wildcard :: None => { }
324- Wildcard :: Unhardened => write ! ( f, "/*" ) ?,
325- Wildcard :: Hardened => write ! ( f, "/*h" ) ?,
326- }
327- Ok ( ( ) )
328- }
333+ DescriptorPublicKey :: MultiXPub ( ref xpub) => xpub. fmt ( f) ,
329334 }
330335 }
331336}
@@ -501,6 +506,30 @@ impl FromStr for DescriptorExtendedPublicKey {
501506 }
502507}
503508
509+ impl FromStr for DescriptorMultiExtendedPublicKey {
510+ type Err = DescriptorKeyParseError ;
511+
512+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
513+ let ( key_part, origin) = parse_key_origin ( s) ?;
514+
515+ let ( xpub, derivation_paths, wildcard) =
516+ parse_xkey_deriv :: < bip32:: ExtendedPubKey > ( key_part) ?;
517+
518+ if derivation_paths. len ( ) < 2 {
519+ return Err ( DescriptorKeyParseError (
520+ "Multiple derivation paths are required for multi extended keys" ,
521+ ) ) ;
522+ }
523+
524+ Ok ( Self {
525+ origin,
526+ xkey : xpub,
527+ derivation_paths : DerivPaths :: new ( derivation_paths) . expect ( "Not empty" ) ,
528+ wildcard,
529+ } )
530+ }
531+ }
532+
504533impl FromStr for DescriptorPublicKey {
505534 type Err = DescriptorKeyParseError ;
506535
@@ -518,12 +547,7 @@ impl FromStr for DescriptorPublicKey {
518547 let ( xpub, derivation_paths, wildcard) =
519548 parse_xkey_deriv :: < bip32:: ExtendedPubKey > ( key_part) ?;
520549 if derivation_paths. len ( ) > 1 {
521- Ok ( DescriptorPublicKey :: MultiXPub ( DescriptorMultiXKey {
522- origin,
523- xkey : xpub,
524- derivation_paths : DerivPaths :: new ( derivation_paths) . expect ( "Not empty" ) ,
525- wildcard,
526- } ) )
550+ DescriptorMultiExtendedPublicKey :: from_str ( s) . map ( Self :: MultiXPub )
527551 } else {
528552 DescriptorExtendedPublicKey :: from_str ( s) . map ( Self :: XPub )
529553 }
@@ -757,18 +781,45 @@ impl DescriptorKey for DescriptorExtendedPublicKey {
757781 }
758782}
759783
784+ impl DescriptorKey for DescriptorMultiExtendedPublicKey {
785+ fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
786+ if let Some ( ( fingerprint, _) ) = self . origin {
787+ fingerprint
788+ } else {
789+ self . xkey . fingerprint ( )
790+ }
791+ }
792+
793+ fn full_derivation_path ( & self ) -> Option < bip32:: DerivationPath > {
794+ None
795+ }
796+
797+ fn has_wildcard ( & self ) -> bool {
798+ self . wildcard != Wildcard :: None
799+ }
800+
801+ fn at_derivation_index ( self , _index : u32 ) -> Result < DefiniteDescriptorKey , ConversionError > {
802+ Err ( ConversionError :: MultiKey )
803+ }
804+
805+ fn is_multipath ( & self ) -> bool {
806+ true
807+ }
808+
809+ fn derive_public_key < C : Verification > (
810+ & self ,
811+ _secp : & Secp256k1 < C > ,
812+ ) -> Result < bitcoin:: PublicKey , ConversionError > {
813+ Err ( ConversionError :: MultiKey )
814+ }
815+ }
816+
760817impl DescriptorPublicKey {
761818 /// The fingerprint of the master key associated with this key, `0x00000000` if none.
762819 pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
763820 match * self {
764821 DescriptorPublicKey :: XPub ( ref xpub) => xpub. master_fingerprint ( ) ,
765- DescriptorPublicKey :: MultiXPub ( ref xpub) => {
766- if let Some ( ( fingerprint, _) ) = xpub. origin {
767- fingerprint
768- } else {
769- xpub. xkey . fingerprint ( )
770- }
771- }
822+ DescriptorPublicKey :: MultiXPub ( ref xpub) => xpub. master_fingerprint ( ) ,
772823 DescriptorPublicKey :: Single ( ref single) => single. master_fingerprint ( ) ,
773824 }
774825 }
@@ -784,7 +835,7 @@ impl DescriptorPublicKey {
784835 match * self {
785836 DescriptorPublicKey :: XPub ( ref xpub) => xpub. full_derivation_path ( ) ,
786837 DescriptorPublicKey :: Single ( ref single) => single. full_derivation_path ( ) ,
787- DescriptorPublicKey :: MultiXPub ( _ ) => None ,
838+ DescriptorPublicKey :: MultiXPub ( ref xpub ) => xpub . full_derivation_path ( ) ,
788839 }
789840 }
790841
@@ -799,7 +850,7 @@ impl DescriptorPublicKey {
799850 match * self {
800851 DescriptorPublicKey :: Single ( ref single) => single. has_wildcard ( ) ,
801852 DescriptorPublicKey :: XPub ( ref xpub) => xpub. has_wildcard ( ) ,
802- DescriptorPublicKey :: MultiXPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
853+ DescriptorPublicKey :: MultiXPub ( ref xpub) => xpub. has_wildcard ( ) ,
803854 }
804855 }
805856
@@ -825,7 +876,7 @@ impl DescriptorPublicKey {
825876 match self {
826877 DescriptorPublicKey :: Single ( single) => single. at_derivation_index ( index) ,
827878 DescriptorPublicKey :: XPub ( xpub) => xpub. at_derivation_index ( index) ,
828- DescriptorPublicKey :: MultiXPub ( _ ) => Err ( ConversionError :: MultiKey ) ,
879+ DescriptorPublicKey :: MultiXPub ( xpub ) => xpub . at_derivation_index ( index ) ,
829880 }
830881 }
831882
@@ -834,7 +885,7 @@ impl DescriptorPublicKey {
834885 match self {
835886 DescriptorPublicKey :: Single ( single) => single. is_multipath ( ) ,
836887 DescriptorPublicKey :: XPub ( xpub) => xpub. is_multipath ( ) ,
837- DescriptorPublicKey :: MultiXPub ( _ ) => true ,
888+ DescriptorPublicKey :: MultiXPub ( xpub ) => xpub . is_multipath ( ) ,
838889 }
839890 }
840891
@@ -1208,9 +1259,7 @@ impl DefiniteDescriptorKey {
12081259 match self . 0 {
12091260 DescriptorPublicKey :: Single ( ref pk) => pk. derive_public_key ( secp) ,
12101261 DescriptorPublicKey :: XPub ( ref xpk) => xpk. derive_public_key ( secp) ,
1211- DescriptorPublicKey :: MultiXPub ( _) => {
1212- unreachable ! ( "A definite key cannot contain a multipath key." )
1213- }
1262+ DescriptorPublicKey :: MultiXPub ( ref xpk) => xpk. derive_public_key ( secp) ,
12141263 }
12151264 }
12161265
0 commit comments