@@ -70,14 +70,9 @@ pub enum SinglePubKey {
7070 XOnly ( XOnlyPublicKey ) ,
7171}
7272
73- /// A derived [`DescriptorPublicKey`]
74- ///
75- /// Derived keys are guaranteed to never contain wildcards
73+ /// A [`DescriptorPublicKey`] without any wildcards.
7674#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
77- pub struct DerivedDescriptorKey {
78- key : DescriptorPublicKey ,
79- index : u32 ,
80- }
75+ pub struct DefiniteDescriptorKey ( DescriptorPublicKey ) ;
8176
8277impl fmt:: Display for DescriptorSecretKey {
8378 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -357,22 +352,14 @@ impl FromStr for DescriptorPublicKey {
357352/// Descriptor key conversion error
358353#[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Copy ) ]
359354pub enum ConversionError {
360- /// Attempted to convert a key with a wildcard to a bitcoin public key
361- Wildcard ,
362355 /// Attempted to convert a key with hardened derivations to a bitcoin public key
363356 HardenedChild ,
364- /// Attempted to convert a key with a hardened wildcard to a bitcoin public key
365- HardenedWildcard ,
366357}
367358
368359impl fmt:: Display for ConversionError {
369360 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
370361 f. write_str ( match * self {
371- ConversionError :: Wildcard => "uninstantiated wildcard in bip32 path" ,
372362 ConversionError :: HardenedChild => "hardened child step in bip32 path" ,
373- ConversionError :: HardenedWildcard => {
374- "hardened and uninstantiated wildcard in bip32 path"
375- }
376363 } )
377364 }
378365}
@@ -383,7 +370,7 @@ impl error::Error for ConversionError {
383370 use self :: ConversionError :: * ;
384371
385372 match self {
386- Wildcard | HardenedChild | HardenedWildcard => None ,
373+ HardenedChild => None ,
387374 }
388375 }
389376}
@@ -441,40 +428,50 @@ impl DescriptorPublicKey {
441428 }
442429 }
443430
444- /// Whether or not the key has a wildcards
431+ /// Whether or not the key has a wildcard
432+ #[ deprecated( note = "use has_wildcard instead" ) ]
445433 pub fn is_deriveable ( & self ) -> bool {
434+ self . has_wildcard ( )
435+ }
436+
437+ /// Whether or not the key has a wildcard
438+ pub fn has_wildcard ( & self ) -> bool {
446439 match * self {
447440 DescriptorPublicKey :: Single ( ..) => false ,
448441 DescriptorPublicKey :: XPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
449442 }
450443 }
451444
452- /// Derives the [`DescriptorPublicKey`] at `index` if this key is an xpub and has a wildcard.
445+ #[ deprecated( note = "use at_derivation_index instead" ) ]
446+ /// Deprecated name of [`at_derivation_index`].
447+ pub fn derive ( self , index : u32 ) -> DefiniteDescriptorKey {
448+ self . at_derivation_index ( index)
449+ }
450+
451+ /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
452+ /// *definite* key (i.e. one where all the derivation paths are set).
453453 ///
454454 /// # Returns
455455 ///
456456 /// - If this key is not an xpub, returns `self`.
457457 /// - If this key is an xpub but does not have a wildcard, returns `self`.
458- /// - Otherwise, returns the derived xpub at `index` (removing the wildcard).
459- ///
460- /// Since it's guaranteed that extended keys won't have wildcards, the key is returned as
461- /// [`DerivedDescriptorKey`].
458+ /// - Otherwise, returns the xpub at derivation `index` (removing the wildcard).
462459 ///
463460 /// # Panics
464461 ///
465462 /// If `index` ≥ 2^31
466- pub fn derive ( self , index : u32 ) -> DerivedDescriptorKey {
467- let derived = match self {
463+ pub fn at_derivation_index ( self , index : u32 ) -> DefiniteDescriptorKey {
464+ let definite = match self {
468465 DescriptorPublicKey :: Single ( _) => self ,
469466 DescriptorPublicKey :: XPub ( xpub) => {
470467 let derivation_path = match xpub. wildcard {
471468 Wildcard :: None => xpub. derivation_path ,
472- Wildcard :: Unhardened => xpub
473- . derivation_path
474- . into_child ( bip32 :: ChildNumber :: from_normal_idx ( index ) . unwrap ( ) ) ,
475- Wildcard :: Hardened => xpub
476- . derivation_path
477- . into_child ( bip32 :: ChildNumber :: from_hardened_idx ( index ) . unwrap ( ) ) ,
469+ Wildcard :: Unhardened => xpub. derivation_path . into_child (
470+ bip32 :: ChildNumber :: from_normal_idx ( index ) . expect ( "index must < 2^31" ) ,
471+ ) ,
472+ Wildcard :: Hardened => xpub. derivation_path . into_child (
473+ bip32 :: ChildNumber :: from_hardened_idx ( index ) . expect ( "index must < 2^31" ) ,
474+ ) ,
478475 } ;
479476 DescriptorPublicKey :: XPub ( DescriptorXKey {
480477 origin : xpub. origin ,
@@ -485,7 +482,7 @@ impl DescriptorPublicKey {
485482 }
486483 } ;
487484
488- DerivedDescriptorKey :: new ( derived , index )
485+ DefiniteDescriptorKey :: new ( definite )
489486 . expect ( "The key should not contain any wildcards at this point" )
490487 }
491488
@@ -494,13 +491,10 @@ impl DescriptorPublicKey {
494491 /// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
495492 /// always return a compressed key
496493 ///
497- /// Will return an error if the descriptor key has any hardened
498- /// derivation steps in its path, or if the key has any wildcards .
494+ /// Will return an error if the descriptor key has any hardened derivation steps in its path. To
495+ /// avoid this error you should replace any such public keys first with [`translate_pk`] .
499496 ///
500- /// To ensure there are no wildcards, call `.derive(0)` or similar;
501- /// to avoid hardened derivation steps, start from a `DescriptorSecretKey`
502- /// and call `to_public`, or call `TranslatePk2::translate_pk2` with
503- /// some function which has access to secret key data.
497+ /// [`translate_pk`]: crate::TranslatePk::translate_pk
504498 pub fn derive_public_key < C : Verification > (
505499 & self ,
506500 secp : & Secp256k1 < C > ,
@@ -511,8 +505,9 @@ impl DescriptorPublicKey {
511505 SinglePubKey :: XOnly ( xpk) => Ok ( xpk. to_public_key ( ) ) ,
512506 } ,
513507 DescriptorPublicKey :: XPub ( ref xpk) => match xpk. wildcard {
514- Wildcard :: Unhardened => Err ( ConversionError :: Wildcard ) ,
515- Wildcard :: Hardened => Err ( ConversionError :: HardenedWildcard ) ,
508+ Wildcard :: Unhardened | Wildcard :: Hardened => {
509+ unreachable ! ( "we've excluded this error case" )
510+ }
516511 Wildcard :: None => match xpk. xkey . derive_pub ( secp, & xpk. derivation_path . as_ref ( ) ) {
517512 Ok ( xpub) => Ok ( bitcoin:: PublicKey :: new ( xpub. public_key ) ) ,
518513 Err ( bip32:: Error :: CannotDeriveFromHardenedKey ) => {
@@ -767,7 +762,7 @@ impl MiniscriptKey for DescriptorPublicKey {
767762 }
768763}
769764
770- impl DerivedDescriptorKey {
765+ impl DefiniteDescriptorKey {
771766 /// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
772767 ///
773768 /// Will return an error if the key has any hardened derivation steps
@@ -778,32 +773,51 @@ impl DerivedDescriptorKey {
778773 & self ,
779774 secp : & Secp256k1 < C > ,
780775 ) -> Result < bitcoin:: PublicKey , ConversionError > {
781- self . key . derive_public_key ( secp)
782- }
783-
784- /// Return the derivation index of this key
785- pub fn index ( & self ) -> u32 {
786- self . index
776+ self . 0 . derive_public_key ( secp)
787777 }
788778
789779 /// Construct an instance from a descriptor key and a derivation index
790780 ///
791781 /// Returns `None` if the key contains a wildcard
792- fn new ( key : DescriptorPublicKey , index : u32 ) -> Option < Self > {
793- match key {
794- DescriptorPublicKey :: XPub ( ref xpk) if xpk. wildcard != Wildcard :: None => None ,
795- k => Some ( DerivedDescriptorKey { key : k, index } ) ,
782+ fn new ( key : DescriptorPublicKey ) -> Option < Self > {
783+ if key. has_wildcard ( ) {
784+ None
785+ } else {
786+ Some ( Self ( key) )
796787 }
797788 }
789+
790+ /// The fingerprint of the master key associated with this key, `0x00000000` if none.
791+ pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
792+ self . 0 . master_fingerprint ( )
793+ }
794+
795+ /// Full path, from the master key
796+ pub fn full_derivation_path ( & self ) -> bip32:: DerivationPath {
797+ self . 0 . full_derivation_path ( )
798+ }
799+ }
800+
801+ impl FromStr for DefiniteDescriptorKey {
802+ type Err = DescriptorKeyParseError ;
803+
804+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
805+ let inner = DescriptorPublicKey :: from_str ( s) ?;
806+ Ok (
807+ DefiniteDescriptorKey :: new ( inner) . ok_or ( DescriptorKeyParseError (
808+ "cannot parse key with a wilcard as a DerivedDescriptorKey" ,
809+ ) ) ?,
810+ )
811+ }
798812}
799813
800- impl fmt:: Display for DerivedDescriptorKey {
814+ impl fmt:: Display for DefiniteDescriptorKey {
801815 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
802- self . key . fmt ( f)
816+ self . 0 . fmt ( f)
803817 }
804818}
805819
806- impl MiniscriptKey for DerivedDescriptorKey {
820+ impl MiniscriptKey for DefiniteDescriptorKey {
807821 // This allows us to be able to derive public keys even for PkH s
808822 type RawPkHash = Self ;
809823 type Sha256 = sha256:: Hash ;
@@ -812,22 +826,22 @@ impl MiniscriptKey for DerivedDescriptorKey {
812826 type Hash160 = hash160:: Hash ;
813827
814828 fn is_uncompressed ( & self ) -> bool {
815- self . key . is_uncompressed ( )
829+ self . 0 . is_uncompressed ( )
816830 }
817831
818832 fn is_x_only_key ( & self ) -> bool {
819- self . key . is_x_only_key ( )
833+ self . 0 . is_x_only_key ( )
820834 }
821835
822836 fn to_pubkeyhash ( & self ) -> Self {
823837 self . clone ( )
824838 }
825839}
826840
827- impl ToPublicKey for DerivedDescriptorKey {
841+ impl ToPublicKey for DefiniteDescriptorKey {
828842 fn to_public_key ( & self ) -> bitcoin:: PublicKey {
829843 let secp = Secp256k1 :: verification_only ( ) ;
830- self . key . derive_public_key ( & secp) . unwrap ( )
844+ self . 0 . derive_public_key ( & secp) . unwrap ( )
831845 }
832846
833847 fn hash_to_hash160 ( hash : & Self ) -> hash160:: Hash {
@@ -851,6 +865,12 @@ impl ToPublicKey for DerivedDescriptorKey {
851865 }
852866}
853867
868+ impl From < DefiniteDescriptorKey > for DescriptorPublicKey {
869+ fn from ( d : DefiniteDescriptorKey ) -> Self {
870+ d. 0
871+ }
872+ }
873+
854874#[ cfg( test) ]
855875mod test {
856876 use core:: str:: FromStr ;
@@ -957,17 +977,17 @@ mod test {
957977 let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2" ) . unwrap ( ) ;
958978 assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
959979 assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'/2" ) ;
960- assert_eq ! ( public_key. is_deriveable ( ) , false ) ;
980+ assert_eq ! ( public_key. has_wildcard ( ) , false ) ;
961981
962982 let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*" ) . unwrap ( ) ;
963983 assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
964984 assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'" ) ;
965- assert_eq ! ( public_key. is_deriveable ( ) , true ) ;
985+ assert_eq ! ( public_key. has_wildcard ( ) , true ) ;
966986
967987 let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h" ) . unwrap ( ) ;
968988 assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
969989 assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'" ) ;
970- assert_eq ! ( public_key. is_deriveable ( ) , true ) ;
990+ assert_eq ! ( public_key. has_wildcard ( ) , true ) ;
971991 }
972992
973993 #[ test]
@@ -979,7 +999,7 @@ mod test {
979999 assert_eq ! ( public_key. to_string( ) , "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2" ) ;
9801000 assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "2cbe2a6d" ) ;
9811001 assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'/2" ) ;
982- assert_eq ! ( public_key. is_deriveable ( ) , false ) ;
1002+ assert_eq ! ( public_key. has_wildcard ( ) , false ) ;
9831003
9841004 let secret_key = DescriptorSecretKey :: from_str ( "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'" ) . unwrap ( ) ;
9851005 let public_key = secret_key. to_public ( & secp) . unwrap ( ) ;
0 commit comments