@@ -328,19 +328,23 @@ impl DescriptorMultiXKey<bip32::Xpriv> {
328328}
329329
330330/// Kinds of malformed key data
331- #[ derive( Debug , PartialEq , Clone ) ]
331+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
332332#[ non_exhaustive]
333333#[ allow( missing_docs) ]
334334pub enum NonDefiniteKeyError {
335335 Wildcard ,
336336 Multipath ,
337+ HardenedStep ,
337338}
338339
339340impl fmt:: Display for NonDefiniteKeyError {
340341 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
341342 match * self {
342343 Self :: Wildcard => f. write_str ( "key with a wildcard cannot be a DerivedDescriptorKey" ) ,
343344 Self :: Multipath => f. write_str ( "multipath key cannot be a DerivedDescriptorKey" ) ,
345+ Self :: HardenedStep => {
346+ f. write_str ( "key with hardened derivation steps cannot be a DerivedDescriptorKey" )
347+ }
344348 }
345349 }
346350}
@@ -349,7 +353,7 @@ impl fmt::Display for NonDefiniteKeyError {
349353impl error:: Error for NonDefiniteKeyError { }
350354
351355/// Kinds of malformed key data
352- #[ derive( Debug , PartialEq , Clone ) ]
356+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
353357#[ non_exhaustive]
354358#[ allow( missing_docs) ]
355359pub enum MalformedKeyDataKind {
@@ -393,7 +397,7 @@ impl fmt::Display for MalformedKeyDataKind {
393397}
394398
395399/// Descriptor Key parsing errors
396- #[ derive( Debug , PartialEq , Clone ) ]
400+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
397401#[ non_exhaustive]
398402pub enum DescriptorKeyParseError {
399403 /// Error while parsing a BIP32 extended private key
@@ -685,33 +689,6 @@ impl From<PublicKey> for DescriptorPublicKey {
685689 }
686690}
687691
688- /// Descriptor key conversion error
689- #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Copy ) ]
690- pub enum ConversionError {
691- /// Attempted to convert a key with hardened derivations to a bitcoin public key
692- HardenedChild ,
693- /// Attempted to convert a key with multiple derivation paths to a bitcoin public key
694- MultiKey ,
695- }
696-
697- impl fmt:: Display for ConversionError {
698- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
699- f. write_str ( match * self {
700- Self :: HardenedChild => "hardened child step in bip32 path" ,
701- Self :: MultiKey => "multiple existing keys" ,
702- } )
703- }
704- }
705-
706- #[ cfg( feature = "std" ) ]
707- impl error:: Error for ConversionError {
708- fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
709- match self {
710- Self :: HardenedChild | Self :: MultiKey => None ,
711- }
712- }
713- }
714-
715692impl DescriptorPublicKey {
716693 /// The fingerprint of the master key associated with this key, `0x00000000` if none.
717694 pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
@@ -806,10 +783,6 @@ impl DescriptorPublicKey {
806783 }
807784 }
808785
809- /// Whether or not the key has a wildcard
810- #[ deprecated( note = "use has_wildcard instead" ) ]
811- pub fn is_deriveable ( & self ) -> bool { self . has_wildcard ( ) }
812-
813786 /// Whether or not the key has a wildcard
814787 pub fn has_wildcard ( & self ) -> bool {
815788 match * self {
@@ -819,10 +792,21 @@ impl DescriptorPublicKey {
819792 }
820793 }
821794
822- #[ deprecated( note = "use at_derivation_index instead" ) ]
823- /// Deprecated name for [`Self::at_derivation_index`].
824- pub fn derive ( self , index : u32 ) -> Result < DefiniteDescriptorKey , ConversionError > {
825- self . at_derivation_index ( index)
795+ /// Whether or not the key has a wildcard
796+ pub fn has_hardened_step ( & self ) -> bool {
797+ let paths = match self {
798+ DescriptorPublicKey :: Single ( ..) => & [ ] ,
799+ DescriptorPublicKey :: XPub ( xpub) => core:: slice:: from_ref ( & xpub. derivation_path ) ,
800+ DescriptorPublicKey :: MultiXPub ( xpub) => & xpub. derivation_paths . paths ( ) [ ..] ,
801+ } ;
802+ for p in paths {
803+ for step in p. into_iter ( ) {
804+ if step. is_hardened ( ) {
805+ return true ;
806+ }
807+ }
808+ }
809+ false
826810 }
827811
828812 /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
@@ -838,7 +822,10 @@ impl DescriptorPublicKey {
838822 ///
839823 /// - If `index` is hardened.
840824 /// - If the key contains multi-path derivations
841- pub fn at_derivation_index ( self , index : u32 ) -> Result < DefiniteDescriptorKey , ConversionError > {
825+ pub fn at_derivation_index (
826+ self ,
827+ index : u32 ,
828+ ) -> Result < DefiniteDescriptorKey , NonDefiniteKeyError > {
842829 let definite = match self {
843830 DescriptorPublicKey :: Single ( _) => self ,
844831 DescriptorPublicKey :: XPub ( xpub) => {
@@ -847,12 +834,12 @@ impl DescriptorPublicKey {
847834 Wildcard :: Unhardened => xpub. derivation_path . into_child (
848835 bip32:: ChildNumber :: from_normal_idx ( index)
849836 . ok ( )
850- . ok_or ( ConversionError :: HardenedChild ) ?,
837+ . ok_or ( NonDefiniteKeyError :: HardenedStep ) ?,
851838 ) ,
852839 Wildcard :: Hardened => xpub. derivation_path . into_child (
853840 bip32:: ChildNumber :: from_hardened_idx ( index)
854841 . ok ( )
855- . ok_or ( ConversionError :: HardenedChild ) ?,
842+ . ok_or ( NonDefiniteKeyError :: HardenedStep ) ?,
856843 ) ,
857844 } ;
858845 DescriptorPublicKey :: XPub ( DescriptorXKey {
@@ -862,7 +849,7 @@ impl DescriptorPublicKey {
862849 wildcard : Wildcard :: None ,
863850 } )
864851 }
865- DescriptorPublicKey :: MultiXPub ( _) => return Err ( ConversionError :: MultiKey ) ,
852+ DescriptorPublicKey :: MultiXPub ( _) => return Err ( NonDefiniteKeyError :: Multipath ) ,
866853 } ;
867854
868855 Ok ( DefiniteDescriptorKey :: new ( definite)
@@ -1243,29 +1230,26 @@ impl DefiniteDescriptorKey {
12431230 ///
12441231 /// Will return an error if the descriptor key has any hardened derivation steps in its path. To
12451232 /// avoid this error you should replace any such public keys first with [`crate::Descriptor::translate_pk`].
1246- pub fn derive_public_key < C : Verification > (
1247- & self ,
1248- secp : & Secp256k1 < C > ,
1249- ) -> Result < bitcoin:: PublicKey , ConversionError > {
1233+ pub fn derive_public_key < C : Verification > ( & self , secp : & Secp256k1 < C > ) -> bitcoin:: PublicKey {
12501234 match self . 0 {
12511235 DescriptorPublicKey :: Single ( ref pk) => match pk. key {
1252- SinglePubKey :: FullKey ( pk) => Ok ( pk ) ,
1253- SinglePubKey :: XOnly ( xpk) => Ok ( xpk. to_public_key ( ) ) ,
1236+ SinglePubKey :: FullKey ( pk) => pk ,
1237+ SinglePubKey :: XOnly ( xpk) => xpk. to_public_key ( ) ,
12541238 } ,
12551239 DescriptorPublicKey :: XPub ( ref xpk) => match xpk. wildcard {
12561240 Wildcard :: Unhardened | Wildcard :: Hardened => {
1257- unreachable ! ( "we've excluded this error case " )
1241+ unreachable ! ( "impossible by construction of DefiniteDescriptorKey " )
12581242 }
12591243 Wildcard :: None => match xpk. xkey . derive_pub ( secp, & xpk. derivation_path . as_ref ( ) ) {
1260- Ok ( xpub) => Ok ( bitcoin:: PublicKey :: new ( xpub. public_key ) ) ,
1244+ Ok ( xpub) => bitcoin:: PublicKey :: new ( xpub. public_key ) ,
12611245 Err ( bip32:: Error :: CannotDeriveFromHardenedKey ) => {
1262- Err ( ConversionError :: HardenedChild )
1246+ unreachable ! ( "impossible by construction of DefiniteDescriptorKey" )
12631247 }
12641248 Err ( e) => unreachable ! ( "cryptographically unreachable: {}" , e) ,
12651249 } ,
12661250 } ,
12671251 DescriptorPublicKey :: MultiXPub ( _) => {
1268- unreachable ! ( "A definite key cannot contain a multipath key. " )
1252+ unreachable ! ( "impossible by construction of DefiniteDescriptorKey " )
12691253 }
12701254 }
12711255 }
@@ -1276,6 +1260,8 @@ impl DefiniteDescriptorKey {
12761260 pub fn new ( key : DescriptorPublicKey ) -> Result < Self , NonDefiniteKeyError > {
12771261 if key. has_wildcard ( ) {
12781262 Err ( NonDefiniteKeyError :: Wildcard )
1263+ } else if key. has_hardened_step ( ) {
1264+ Err ( NonDefiniteKeyError :: HardenedStep )
12791265 } else if key. is_multipath ( ) {
12801266 Err ( NonDefiniteKeyError :: Multipath )
12811267 } else {
@@ -1333,7 +1319,7 @@ impl MiniscriptKey for DefiniteDescriptorKey {
13331319impl ToPublicKey for DefiniteDescriptorKey {
13341320 fn to_public_key ( & self ) -> bitcoin:: PublicKey {
13351321 let secp = Secp256k1 :: verification_only ( ) ;
1336- self . derive_public_key ( & secp) . unwrap ( )
1322+ self . derive_public_key ( & secp)
13371323 }
13381324
13391325 fn to_sha256 ( hash : & sha256:: Hash ) -> sha256:: Hash { * hash }
@@ -1785,5 +1771,13 @@ mod test {
17851771 . parse :: < DescriptorPublicKey > ( )
17861772 . unwrap ( ) ;
17871773 assert ! ( matches!( DefiniteDescriptorKey :: new( desc) , Err ( NonDefiniteKeyError :: Multipath ) ) ) ;
1774+ // xpub with hardened path
1775+ let desc = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/1'/2"
1776+ . parse :: < DescriptorPublicKey > ( )
1777+ . unwrap ( ) ;
1778+ assert ! ( matches!(
1779+ DefiniteDescriptorKey :: new( desc) ,
1780+ Err ( NonDefiniteKeyError :: HardenedStep )
1781+ ) ) ;
17881782 }
17891783}
0 commit comments