@@ -68,14 +68,9 @@ pub struct DescriptorXKey<K: InnerXKey> {
68
68
pub wildcard : Wildcard ,
69
69
}
70
70
71
- /// A derived [`DescriptorPublicKey`]
72
- ///
73
- /// Derived keys are guaranteed to never contain wildcards
71
+ /// A [`DescriptorPublicKey`] without any wildcards.
74
72
#[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
75
- pub struct DerivedDescriptorKey {
76
- key : DescriptorPublicKey ,
77
- index : u32 ,
78
- }
73
+ pub struct DefiniteDescriptorKey ( DescriptorPublicKey ) ;
79
74
80
75
impl fmt:: Display for DescriptorSecretKey {
81
76
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
@@ -354,22 +349,14 @@ impl FromStr for DescriptorPublicKey {
354
349
/// Descriptor key conversion error
355
350
#[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Copy ) ]
356
351
pub enum ConversionError {
357
- /// Attempted to convert a key with a wildcard to a bitcoin public key
358
- Wildcard ,
359
352
/// Attempted to convert a key with hardened derivations to a bitcoin public key
360
353
HardenedChild ,
361
- /// Attempted to convert a key with a hardened wildcard to a bitcoin public key
362
- HardenedWildcard ,
363
354
}
364
355
365
356
impl fmt:: Display for ConversionError {
366
357
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
367
358
f. write_str ( match * self {
368
- ConversionError :: Wildcard => "uninstantiated wildcard in bip32 path" ,
369
359
ConversionError :: HardenedChild => "hardened child step in bip32 path" ,
370
- ConversionError :: HardenedWildcard => {
371
- "hardened and uninstantiated wildcard in bip32 path"
372
- }
373
360
} )
374
361
}
375
362
}
@@ -379,7 +366,7 @@ impl error::Error for ConversionError {
379
366
use self :: ConversionError :: * ;
380
367
381
368
match self {
382
- Wildcard | HardenedChild | HardenedWildcard => None ,
369
+ HardenedChild => None ,
383
370
}
384
371
}
385
372
}
@@ -437,40 +424,50 @@ impl DescriptorPublicKey {
437
424
}
438
425
}
439
426
440
- /// Whether or not the key has a wildcards
427
+ /// Whether or not the key has a wildcard
428
+ #[ deprecated( note = "use has_wildcard instead" ) ]
441
429
pub fn is_deriveable ( & self ) -> bool {
430
+ self . has_wildcard ( )
431
+ }
432
+
433
+ /// Whether or not the key has a wildcard
434
+ pub fn has_wildcard ( & self ) -> bool {
442
435
match * self {
443
436
DescriptorPublicKey :: Single ( ..) => false ,
444
437
DescriptorPublicKey :: XPub ( ref xpub) => xpub. wildcard != Wildcard :: None ,
445
438
}
446
439
}
447
440
448
- /// Derives the [`DescriptorPublicKey`] at `index` if this key is an xpub and has a wildcard.
441
+ #[ deprecated( note = "use at_derivation_index instead" ) ]
442
+ /// Deprecated name of [`at_derivation_index`].
443
+ pub fn derive ( self , index : u32 ) -> DefiniteDescriptorKey {
444
+ self . at_derivation_index ( index)
445
+ }
446
+
447
+ /// Replaces any wildcard (i.e. `/*`) in the key with a particular derivation index, turning it into a
448
+ /// *definite* key (i.e. one where all the derivation paths are set).
449
449
///
450
450
/// # Returns
451
451
///
452
452
/// - If this key is not an xpub, returns `self`.
453
453
/// - If this key is an xpub but does not have a wildcard, returns `self`.
454
- /// - Otherwise, returns the derived xpub at `index` (removing the wildcard).
455
- ///
456
- /// Since it's guaranteed that extended keys won't have wildcards, the key is returned as
457
- /// [`DerivedDescriptorKey`].
454
+ /// - Otherwise, returns the xpub at derivation `index` (removing the wildcard).
458
455
///
459
456
/// # Panics
460
457
///
461
458
/// If `index` ≥ 2^31
462
- pub fn derive ( self , index : u32 ) -> DerivedDescriptorKey {
463
- let derived = match self {
459
+ pub fn at_derivation_index ( self , index : u32 ) -> DefiniteDescriptorKey {
460
+ let definite = match self {
464
461
DescriptorPublicKey :: Single ( _) => self ,
465
462
DescriptorPublicKey :: XPub ( xpub) => {
466
463
let derivation_path = match xpub. wildcard {
467
464
Wildcard :: None => xpub. derivation_path ,
468
- Wildcard :: Unhardened => xpub
469
- . derivation_path
470
- . into_child ( bip32 :: ChildNumber :: from_normal_idx ( index ) . unwrap ( ) ) ,
471
- Wildcard :: Hardened => xpub
472
- . derivation_path
473
- . into_child ( bip32 :: ChildNumber :: from_hardened_idx ( index ) . unwrap ( ) ) ,
465
+ Wildcard :: Unhardened => xpub. derivation_path . into_child (
466
+ bip32 :: ChildNumber :: from_normal_idx ( index ) . expect ( "index must < 2^31" ) ,
467
+ ) ,
468
+ Wildcard :: Hardened => xpub. derivation_path . into_child (
469
+ bip32 :: ChildNumber :: from_hardened_idx ( index ) . expect ( "index must < 2^31" ) ,
470
+ ) ,
474
471
} ;
475
472
DescriptorPublicKey :: XPub ( DescriptorXKey {
476
473
origin : xpub. origin ,
@@ -481,7 +478,7 @@ impl DescriptorPublicKey {
481
478
}
482
479
} ;
483
480
484
- DerivedDescriptorKey :: new ( derived , index )
481
+ DefiniteDescriptorKey :: new ( definite )
485
482
. expect ( "The key should not contain any wildcards at this point" )
486
483
}
487
484
@@ -490,13 +487,10 @@ impl DescriptorPublicKey {
490
487
/// and returns the obtained full [`bitcoin::PublicKey`]. All BIP32 derivations
491
488
/// always return a compressed key
492
489
///
493
- /// Will return an error if the descriptor key has any hardened
494
- /// derivation steps in its path, or if the key has any wildcards .
490
+ /// Will return an error if the descriptor key has any hardened derivation steps in its path. To
491
+ /// avoid this error you should replace any such public keys first with [`translate_pk`] .
495
492
///
496
- /// To ensure there are no wildcards, call `.derive(0)` or similar;
497
- /// to avoid hardened derivation steps, start from a `DescriptorSecretKey`
498
- /// and call `to_public`, or call `TranslatePk2::translate_pk2` with
499
- /// some function which has access to secret key data.
493
+ /// [`translate_pk`]: crate::TranslatePk::translate_pk
500
494
pub fn derive_public_key < C : Verification > (
501
495
& self ,
502
496
secp : & Secp256k1 < C > ,
@@ -507,8 +501,9 @@ impl DescriptorPublicKey {
507
501
SinglePubKey :: XOnly ( xpk) => Ok ( xpk. to_public_key ( ) ) ,
508
502
} ,
509
503
DescriptorPublicKey :: XPub ( ref xpk) => match xpk. wildcard {
510
- Wildcard :: Unhardened => Err ( ConversionError :: Wildcard ) ,
511
- Wildcard :: Hardened => Err ( ConversionError :: HardenedWildcard ) ,
504
+ Wildcard :: Unhardened | Wildcard :: Hardened => {
505
+ unreachable ! ( "we've excluded this error case" )
506
+ }
512
507
Wildcard :: None => match xpk. xkey . derive_pub ( secp, & xpk. derivation_path . as_ref ( ) ) {
513
508
Ok ( xpub) => Ok ( bitcoin:: PublicKey :: new ( xpub. public_key ) ) ,
514
509
Err ( bip32:: Error :: CannotDeriveFromHardenedKey ) => {
@@ -747,7 +742,7 @@ impl MiniscriptKey for DescriptorPublicKey {
747
742
}
748
743
}
749
744
750
- impl DerivedDescriptorKey {
745
+ impl DefiniteDescriptorKey {
751
746
/// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
752
747
///
753
748
/// Will return an error if the key has any hardened derivation steps
@@ -758,32 +753,51 @@ impl DerivedDescriptorKey {
758
753
& self ,
759
754
secp : & Secp256k1 < C > ,
760
755
) -> Result < bitcoin:: PublicKey , ConversionError > {
761
- self . key . derive_public_key ( secp)
762
- }
763
-
764
- /// Return the derivation index of this key
765
- pub fn index ( & self ) -> u32 {
766
- self . index
756
+ self . 0 . derive_public_key ( secp)
767
757
}
768
758
769
759
/// Construct an instance from a descriptor key and a derivation index
770
760
///
771
761
/// Returns `None` if the key contains a wildcard
772
- fn new ( key : DescriptorPublicKey , index : u32 ) -> Option < Self > {
773
- match key {
774
- DescriptorPublicKey :: XPub ( ref xpk) if xpk. wildcard != Wildcard :: None => None ,
775
- k => Some ( DerivedDescriptorKey { key : k, index } ) ,
762
+ fn new ( key : DescriptorPublicKey ) -> Option < Self > {
763
+ if key. has_wildcard ( ) {
764
+ None
765
+ } else {
766
+ Some ( Self ( key) )
776
767
}
777
768
}
769
+
770
+ /// The fingerprint of the master key associated with this key, `0x00000000` if none.
771
+ pub fn master_fingerprint ( & self ) -> bip32:: Fingerprint {
772
+ self . 0 . master_fingerprint ( )
773
+ }
774
+
775
+ /// Full path, from the master key
776
+ pub fn full_derivation_path ( & self ) -> bip32:: DerivationPath {
777
+ self . 0 . full_derivation_path ( )
778
+ }
779
+ }
780
+
781
+ impl FromStr for DefiniteDescriptorKey {
782
+ type Err = DescriptorKeyParseError ;
783
+
784
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
785
+ let inner = DescriptorPublicKey :: from_str ( s) ?;
786
+ Ok (
787
+ DefiniteDescriptorKey :: new ( inner) . ok_or ( DescriptorKeyParseError (
788
+ "cannot parse key with a wilcard as a DerivedDescriptorKey" ,
789
+ ) ) ?,
790
+ )
791
+ }
778
792
}
779
793
780
- impl fmt:: Display for DerivedDescriptorKey {
794
+ impl fmt:: Display for DefiniteDescriptorKey {
781
795
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
782
- self . key . fmt ( f)
796
+ self . 0 . fmt ( f)
783
797
}
784
798
}
785
799
786
- impl MiniscriptKey for DerivedDescriptorKey {
800
+ impl MiniscriptKey for DefiniteDescriptorKey {
787
801
// This allows us to be able to derive public keys even for PkH s
788
802
type RawPkHash = Self ;
789
803
type Sha256 = sha256:: Hash ;
@@ -792,22 +806,22 @@ impl MiniscriptKey for DerivedDescriptorKey {
792
806
type Hash160 = hash160:: Hash ;
793
807
794
808
fn is_uncompressed ( & self ) -> bool {
795
- self . key . is_uncompressed ( )
809
+ self . 0 . is_uncompressed ( )
796
810
}
797
811
798
812
fn is_x_only_key ( & self ) -> bool {
799
- self . key . is_x_only_key ( )
813
+ self . 0 . is_x_only_key ( )
800
814
}
801
815
802
816
fn to_pubkeyhash ( & self ) -> Self {
803
817
self . clone ( )
804
818
}
805
819
}
806
820
807
- impl ToPublicKey for DerivedDescriptorKey {
821
+ impl ToPublicKey for DefiniteDescriptorKey {
808
822
fn to_public_key ( & self ) -> bitcoin:: PublicKey {
809
823
let secp = Secp256k1 :: verification_only ( ) ;
810
- self . key . derive_public_key ( & secp) . unwrap ( )
824
+ self . 0 . derive_public_key ( & secp) . unwrap ( )
811
825
}
812
826
813
827
fn hash_to_hash160 ( hash : & Self ) -> hash160:: Hash {
@@ -831,6 +845,12 @@ impl ToPublicKey for DerivedDescriptorKey {
831
845
}
832
846
}
833
847
848
+ impl From < DefiniteDescriptorKey > for DescriptorPublicKey {
849
+ fn from ( d : DefiniteDescriptorKey ) -> Self {
850
+ d. 0
851
+ }
852
+ }
853
+
834
854
#[ cfg( test) ]
835
855
mod test {
836
856
use std:: str:: FromStr ;
@@ -936,17 +956,17 @@ mod test {
936
956
let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2" ) . unwrap ( ) ;
937
957
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
938
958
assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'/2" ) ;
939
- assert_eq ! ( public_key. is_deriveable ( ) , false ) ;
959
+ assert_eq ! ( public_key. has_wildcard ( ) , false ) ;
940
960
941
961
let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*" ) . unwrap ( ) ;
942
962
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
943
963
assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'" ) ;
944
- assert_eq ! ( public_key. is_deriveable ( ) , true ) ;
964
+ assert_eq ! ( public_key. has_wildcard ( ) , true ) ;
945
965
946
966
let public_key = DescriptorPublicKey :: from_str ( "[abcdef00/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/*h" ) . unwrap ( ) ;
947
967
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "abcdef00" ) ;
948
968
assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'" ) ;
949
- assert_eq ! ( public_key. is_deriveable ( ) , true ) ;
969
+ assert_eq ! ( public_key. has_wildcard ( ) , true ) ;
950
970
}
951
971
952
972
#[ test]
@@ -958,7 +978,7 @@ mod test {
958
978
assert_eq ! ( public_key. to_string( ) , "[2cbe2a6d/0'/1']tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi/2" ) ;
959
979
assert_eq ! ( public_key. master_fingerprint( ) . to_string( ) , "2cbe2a6d" ) ;
960
980
assert_eq ! ( public_key. full_derivation_path( ) . to_string( ) , "m/0'/1'/2" ) ;
961
- assert_eq ! ( public_key. is_deriveable ( ) , false ) ;
981
+ assert_eq ! ( public_key. has_wildcard ( ) , false ) ;
962
982
963
983
let secret_key = DescriptorSecretKey :: from_str ( "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/0'/1'/2'" ) . unwrap ( ) ;
964
984
let public_key = secret_key. to_public ( & secp) . unwrap ( ) ;
0 commit comments