@@ -70,14 +70,9 @@ pub enum SinglePubKey {
70
70
XOnly ( XOnlyPublicKey ) ,
71
71
}
72
72
73
- /// A derived [`DescriptorPublicKey`]
74
- ///
75
- /// Derived keys are guaranteed to never contain wildcards
73
+ /// A [`DescriptorPublicKey`] without any wildcards.
76
74
#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
77
- pub struct DerivedDescriptorKey {
78
- key : DescriptorPublicKey ,
79
- index : u32 ,
80
- }
75
+ pub struct DefiniteDescriptorKey ( DescriptorPublicKey ) ;
81
76
82
77
impl fmt:: Display for DescriptorSecretKey {
83
78
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -357,22 +352,14 @@ impl FromStr for DescriptorPublicKey {
357
352
/// Descriptor key conversion error
358
353
#[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Copy ) ]
359
354
pub enum ConversionError {
360
- /// Attempted to convert a key with a wildcard to a bitcoin public key
361
- Wildcard ,
362
355
/// Attempted to convert a key with hardened derivations to a bitcoin public key
363
356
HardenedChild ,
364
- /// Attempted to convert a key with a hardened wildcard to a bitcoin public key
365
- HardenedWildcard ,
366
357
}
367
358
368
359
impl fmt:: Display for ConversionError {
369
360
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
370
361
f. write_str ( match * self {
371
- ConversionError :: Wildcard => "uninstantiated wildcard in bip32 path" ,
372
362
ConversionError :: HardenedChild => "hardened child step in bip32 path" ,
373
- ConversionError :: HardenedWildcard => {
374
- "hardened and uninstantiated wildcard in bip32 path"
375
- }
376
363
} )
377
364
}
378
365
}
@@ -383,7 +370,7 @@ impl error::Error for ConversionError {
383
370
use self :: ConversionError :: * ;
384
371
385
372
match self {
386
- Wildcard | HardenedChild | HardenedWildcard => None ,
373
+ HardenedChild => None ,
387
374
}
388
375
}
389
376
}
@@ -441,40 +428,50 @@ impl DescriptorPublicKey {
441
428
}
442
429
}
443
430
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" ) ]
445
433
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 {
446
439
match * self {
447
440
DescriptorPublicKey :: Single ( ..) => false ,
448
441
DescriptorPublicKey :: XPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
449
442
}
450
443
}
451
444
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).
453
453
///
454
454
/// # Returns
455
455
///
456
456
/// - If this key is not an xpub, returns `self`.
457
457
/// - 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).
462
459
///
463
460
/// # Panics
464
461
///
465
462
/// 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 {
468
465
DescriptorPublicKey :: Single ( _) => self ,
469
466
DescriptorPublicKey :: XPub ( xpub) => {
470
467
let derivation_path = match xpub. wildcard {
471
468
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
+ ) ,
478
475
} ;
479
476
DescriptorPublicKey :: XPub ( DescriptorXKey {
480
477
origin : xpub. origin ,
@@ -485,7 +482,7 @@ impl DescriptorPublicKey {
485
482
}
486
483
} ;
487
484
488
- DerivedDescriptorKey :: new ( derived , index )
485
+ DefiniteDescriptorKey :: new ( definite )
489
486
. expect ( "The key should not contain any wildcards at this point" )
490
487
}
491
488
@@ -494,13 +491,10 @@ impl DescriptorPublicKey {
494
491
/// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
495
492
/// always return a compressed key
496
493
///
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`] .
499
496
///
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
504
498
pub fn derive_public_key < C : Verification > (
505
499
& self ,
506
500
secp : & Secp256k1 < C > ,
@@ -511,8 +505,9 @@ impl DescriptorPublicKey {
511
505
SinglePubKey :: XOnly ( xpk) => Ok ( xpk. to_public_key ( ) ) ,
512
506
} ,
513
507
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
+ }
516
511
Wildcard :: None => match xpk. xkey . derive_pub ( secp, & xpk. derivation_path . as_ref ( ) ) {
517
512
Ok ( xpub) => Ok ( bitcoin:: PublicKey :: new ( xpub. public_key ) ) ,
518
513
Err ( bip32:: Error :: CannotDeriveFromHardenedKey ) => {
@@ -767,7 +762,7 @@ impl MiniscriptKey for DescriptorPublicKey {
767
762
}
768
763
}
769
764
770
- impl DerivedDescriptorKey {
765
+ impl DefiniteDescriptorKey {
771
766
/// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
772
767
///
773
768
/// Will return an error if the key has any hardened derivation steps
@@ -778,32 +773,51 @@ impl DerivedDescriptorKey {
778
773
& self ,
779
774
secp : & Secp256k1 < C > ,
780
775
) -> 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)
787
777
}
788
778
789
779
/// Construct an instance from a descriptor key and a derivation index
790
780
///
791
781
/// 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) )
796
787
}
797
788
}
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
+ }
798
812
}
799
813
800
- impl fmt:: Display for DerivedDescriptorKey {
814
+ impl fmt:: Display for DefiniteDescriptorKey {
801
815
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
802
- self . key . fmt ( f)
816
+ self . 0 . fmt ( f)
803
817
}
804
818
}
805
819
806
- impl MiniscriptKey for DerivedDescriptorKey {
820
+ impl MiniscriptKey for DefiniteDescriptorKey {
807
821
// This allows us to be able to derive public keys even for PkH s
808
822
type RawPkHash = Self ;
809
823
type Sha256 = sha256:: Hash ;
@@ -812,22 +826,22 @@ impl MiniscriptKey for DerivedDescriptorKey {
812
826
type Hash160 = hash160:: Hash ;
813
827
814
828
fn is_uncompressed ( & self ) -> bool {
815
- self . key . is_uncompressed ( )
829
+ self . 0 . is_uncompressed ( )
816
830
}
817
831
818
832
fn is_x_only_key ( & self ) -> bool {
819
- self . key . is_x_only_key ( )
833
+ self . 0 . is_x_only_key ( )
820
834
}
821
835
822
836
fn to_pubkeyhash ( & self ) -> Self {
823
837
self . clone ( )
824
838
}
825
839
}
826
840
827
- impl ToPublicKey for DerivedDescriptorKey {
841
+ impl ToPublicKey for DefiniteDescriptorKey {
828
842
fn to_public_key ( & self ) -> bitcoin:: PublicKey {
829
843
let secp = Secp256k1 :: verification_only ( ) ;
830
- self . key . derive_public_key ( & secp) . unwrap ( )
844
+ self . 0 . derive_public_key ( & secp) . unwrap ( )
831
845
}
832
846
833
847
fn hash_to_hash160 ( hash : & Self ) -> hash160:: Hash {
@@ -851,6 +865,12 @@ impl ToPublicKey for DerivedDescriptorKey {
851
865
}
852
866
}
853
867
868
+ impl From < DefiniteDescriptorKey > for DescriptorPublicKey {
869
+ fn from ( d : DefiniteDescriptorKey ) -> Self {
870
+ d. 0
871
+ }
872
+ }
873
+
854
874
#[ cfg( test) ]
855
875
mod test {
856
876
use core:: str:: FromStr ;
@@ -957,17 +977,17 @@ mod test {
957
977
let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2" ) . unwrap ( ) ;
958
978
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
959
979
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 ) ;
961
981
962
982
let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*" ) . unwrap ( ) ;
963
983
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
964
984
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 ) ;
966
986
967
987
let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h" ) . unwrap ( ) ;
968
988
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
969
989
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 ) ;
971
991
}
972
992
973
993
#[ test]
@@ -979,7 +999,7 @@ mod test {
979
999
assert_eq ! ( public_key. to_string( ) , "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2" ) ;
980
1000
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "2cbe2a6d" ) ;
981
1001
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 ) ;
983
1003
984
1004
let secret_key = DescriptorSecretKey :: from_str ( "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'" ) . unwrap ( ) ;
985
1005
let public_key = secret_key. to_public ( & secp) . unwrap ( ) ;
0 commit comments