@@ -328,19 +328,23 @@ impl DescriptorMultiXKey<bip32::Xpriv> {
328
328
}
329
329
330
330
/// Kinds of malformed key data
331
- #[ derive( Debug , PartialEq , Clone ) ]
331
+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
332
332
#[ non_exhaustive]
333
333
#[ allow( missing_docs) ]
334
334
pub enum NonDefiniteKeyError {
335
335
Wildcard ,
336
336
Multipath ,
337
+ HardenedStep ,
337
338
}
338
339
339
340
impl fmt:: Display for NonDefiniteKeyError {
340
341
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
341
342
match * self {
342
343
Self :: Wildcard => f. write_str ( "key with a wildcard cannot be a DerivedDescriptorKey" ) ,
343
344
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
+ }
344
348
}
345
349
}
346
350
}
@@ -349,7 +353,7 @@ impl fmt::Display for NonDefiniteKeyError {
349
353
impl error:: Error for NonDefiniteKeyError { }
350
354
351
355
/// Kinds of malformed key data
352
- #[ derive( Debug , PartialEq , Clone ) ]
356
+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
353
357
#[ non_exhaustive]
354
358
#[ allow( missing_docs) ]
355
359
pub enum MalformedKeyDataKind {
@@ -393,7 +397,7 @@ impl fmt::Display for MalformedKeyDataKind {
393
397
}
394
398
395
399
/// Descriptor Key parsing errors
396
- #[ derive( Debug , PartialEq , Clone ) ]
400
+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
397
401
#[ non_exhaustive]
398
402
pub enum DescriptorKeyParseError {
399
403
/// Error while parsing a BIP32 extended private key
@@ -685,33 +689,6 @@ impl From<PublicKey> for DescriptorPublicKey {
685
689
}
686
690
}
687
691
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
-
715
692
impl DescriptorPublicKey {
716
693
/// The fingerprint of the master key associated with this key, `0x00000000` if none.
717
694
pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
@@ -806,10 +783,6 @@ impl DescriptorPublicKey {
806
783
}
807
784
}
808
785
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
-
813
786
/// Whether or not the key has a wildcard
814
787
pub fn has_wildcard ( & self ) -> bool {
815
788
match * self {
@@ -819,10 +792,21 @@ impl DescriptorPublicKey {
819
792
}
820
793
}
821
794
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
826
810
}
827
811
828
812
/// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
@@ -838,7 +822,10 @@ impl DescriptorPublicKey {
838
822
///
839
823
/// - If `index` is hardened.
840
824
/// - 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 > {
842
829
let definite = match self {
843
830
DescriptorPublicKey :: Single ( _) => self ,
844
831
DescriptorPublicKey :: XPub ( xpub) => {
@@ -847,12 +834,12 @@ impl DescriptorPublicKey {
847
834
Wildcard :: Unhardened => xpub. derivation_path . into_child (
848
835
bip32:: ChildNumber :: from_normal_idx ( index)
849
836
. ok ( )
850
- . ok_or ( ConversionError :: HardenedChild ) ?,
837
+ . ok_or ( NonDefiniteKeyError :: HardenedStep ) ?,
851
838
) ,
852
839
Wildcard :: Hardened => xpub. derivation_path . into_child (
853
840
bip32:: ChildNumber :: from_hardened_idx ( index)
854
841
. ok ( )
855
- . ok_or ( ConversionError :: HardenedChild ) ?,
842
+ . ok_or ( NonDefiniteKeyError :: HardenedStep ) ?,
856
843
) ,
857
844
} ;
858
845
DescriptorPublicKey :: XPub ( DescriptorXKey {
@@ -862,7 +849,7 @@ impl DescriptorPublicKey {
862
849
wildcard : Wildcard :: None ,
863
850
} )
864
851
}
865
- DescriptorPublicKey :: MultiXPub ( _) => return Err ( ConversionError :: MultiKey ) ,
852
+ DescriptorPublicKey :: MultiXPub ( _) => return Err ( NonDefiniteKeyError :: Multipath ) ,
866
853
} ;
867
854
868
855
Ok ( DefiniteDescriptorKey :: new ( definite)
@@ -1243,29 +1230,26 @@ impl DefiniteDescriptorKey {
1243
1230
///
1244
1231
/// Will return an error if the descriptor key has any hardened derivation steps in its path. To
1245
1232
/// 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 {
1250
1234
match self . 0 {
1251
1235
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 ( ) ,
1254
1238
} ,
1255
1239
DescriptorPublicKey :: XPub ( ref xpk) => match xpk. wildcard {
1256
1240
Wildcard :: Unhardened | Wildcard :: Hardened => {
1257
- unreachable ! ( "we've excluded this error case " )
1241
+ unreachable ! ( "impossible by construction of DefiniteDescriptorKey " )
1258
1242
}
1259
1243
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 ) ,
1261
1245
Err ( bip32:: Error :: CannotDeriveFromHardenedKey ) => {
1262
- Err ( ConversionError :: HardenedChild )
1246
+ unreachable ! ( "impossible by construction of DefiniteDescriptorKey" )
1263
1247
}
1264
1248
Err ( e) => unreachable ! ( "cryptographically unreachable: {}" , e) ,
1265
1249
} ,
1266
1250
} ,
1267
1251
DescriptorPublicKey :: MultiXPub ( _) => {
1268
- unreachable ! ( "A definite key cannot contain a multipath key. " )
1252
+ unreachable ! ( "impossible by construction of DefiniteDescriptorKey " )
1269
1253
}
1270
1254
}
1271
1255
}
@@ -1276,6 +1260,8 @@ impl DefiniteDescriptorKey {
1276
1260
pub fn new ( key : DescriptorPublicKey ) -> Result < Self , NonDefiniteKeyError > {
1277
1261
if key. has_wildcard ( ) {
1278
1262
Err ( NonDefiniteKeyError :: Wildcard )
1263
+ } else if key. has_hardened_step ( ) {
1264
+ Err ( NonDefiniteKeyError :: HardenedStep )
1279
1265
} else if key. is_multipath ( ) {
1280
1266
Err ( NonDefiniteKeyError :: Multipath )
1281
1267
} else {
@@ -1333,7 +1319,7 @@ impl MiniscriptKey for DefiniteDescriptorKey {
1333
1319
impl ToPublicKey for DefiniteDescriptorKey {
1334
1320
fn to_public_key ( & self ) -> bitcoin:: PublicKey {
1335
1321
let secp = Secp256k1 :: verification_only ( ) ;
1336
- self . derive_public_key ( & secp) . unwrap ( )
1322
+ self . derive_public_key ( & secp)
1337
1323
}
1338
1324
1339
1325
fn to_sha256 ( hash : & sha256:: Hash ) -> sha256:: Hash { * hash }
@@ -1785,5 +1771,13 @@ mod test {
1785
1771
. parse :: < DescriptorPublicKey > ( )
1786
1772
. unwrap ( ) ;
1787
1773
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
+ ) ) ;
1788
1782
}
1789
1783
}
0 commit comments