1
- use std:: { error, fmt, str:: FromStr } ;
1
+ use std:: { cmp , error, fmt, hash , str:: FromStr } ;
2
2
3
3
use bitcoin:: {
4
4
self ,
5
- hashes:: Hash ,
5
+ hashes:: { hash160 , Hash } ,
6
6
hashes:: { hex:: FromHex , HashEngine } ,
7
- secp256k1,
8
- secp256k1:: { Secp256k1 , Signing } ,
7
+ secp256k1:: { Secp256k1 , Signing , Verification } ,
9
8
util:: bip32,
10
9
XOnlyPublicKey , XpubIdentifier ,
11
10
} ;
@@ -58,6 +57,15 @@ pub enum DescriptorSecretKey {
58
57
XPrv ( DescriptorXKey < bip32:: ExtendedPrivKey > ) ,
59
58
}
60
59
60
+ /// A derived [`DescriptorPublicKey`]
61
+ ///
62
+ /// Derived keys are guaranteed to never contain wildcards
63
+ pub struct DerivedDescriptorKey < ' secp , C : ' secp + Verification > {
64
+ key : DescriptorPublicKey ,
65
+ index : u32 ,
66
+ secp : & ' secp Secp256k1 < C > ,
67
+ }
68
+
61
69
impl fmt:: Display for DescriptorSecretKey {
62
70
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
63
71
match self {
@@ -438,7 +446,11 @@ impl DescriptorPublicKey {
438
446
/// If this public key has a wildcard, replace it by the given index
439
447
///
440
448
/// Panics if given an index ≥ 2^31
441
- pub fn derive ( mut self , index : u32 ) -> DescriptorPublicKey {
449
+ pub fn derive < ' secp , C : Verification > (
450
+ mut self ,
451
+ index : u32 ,
452
+ secp : & ' secp Secp256k1 < C > ,
453
+ ) -> DerivedDescriptorKey < ' secp , C > {
442
454
if let DescriptorPublicKey :: XPub ( mut xpub) = self {
443
455
match xpub. wildcard {
444
456
Wildcard :: None => { }
@@ -456,7 +468,8 @@ impl DescriptorPublicKey {
456
468
xpub. wildcard = Wildcard :: None ;
457
469
self = DescriptorPublicKey :: XPub ( xpub) ;
458
470
}
459
- self
471
+
472
+ DerivedDescriptorKey :: new ( self , index, secp)
460
473
}
461
474
462
475
/// Computes the public key corresponding to this descriptor key.
@@ -471,7 +484,7 @@ impl DescriptorPublicKey {
471
484
/// to avoid hardened derivation steps, start from a `DescriptorSecretKey`
472
485
/// and call `as_public`, or call `TranslatePk2::translate_pk2` with
473
486
/// some function which has access to secret key data.
474
- pub fn derive_public_key < C : secp256k1 :: Verification > (
487
+ pub fn derive_public_key < C : Verification > (
475
488
& self ,
476
489
secp : & Secp256k1 < C > ,
477
490
) -> Result < bitcoin:: PublicKey , ConversionError > {
@@ -717,6 +730,115 @@ impl MiniscriptKey for DescriptorPublicKey {
717
730
}
718
731
}
719
732
733
+ impl < ' secp , C : Verification > DerivedDescriptorKey < ' secp , C > {
734
+ /// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
735
+ ///
736
+ /// Will return an error if the key has any hardened derivation steps
737
+ /// in its path, but unlike [`DescriptorPublicKey::derive_public_key`]
738
+ /// this won't error in case of wildcards, because derived keys are
739
+ /// guaranteed to never contain one.
740
+ pub fn derive_public_key ( & self ) -> Result < bitcoin:: PublicKey , ConversionError > {
741
+ self . key . derive_public_key ( self . secp )
742
+ }
743
+
744
+ /// Return the derivation index of this key
745
+ pub fn get_index ( & self ) -> u32 {
746
+ self . index
747
+ }
748
+
749
+ /// Construct an instance from a descriptor key and a derivation index
750
+ ///
751
+ /// Panics if the key contains a wildcard
752
+ fn new ( key : DescriptorPublicKey , index : u32 , secp : & ' secp Secp256k1 < C > ) -> Self {
753
+ if let DescriptorPublicKey :: XPub ( ref xpk) = & key {
754
+ assert ! (
755
+ xpk. wildcard == Wildcard :: None ,
756
+ "Derived descriptor keys cannot contain any wildcards"
757
+ ) ;
758
+ }
759
+
760
+ DerivedDescriptorKey { key, index, secp }
761
+ }
762
+ }
763
+
764
+ impl < ' secp , C : Verification > fmt:: Display for DerivedDescriptorKey < ' secp , C > {
765
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
766
+ self . key . fmt ( f)
767
+ }
768
+ }
769
+ impl < ' secp , C : Verification > fmt:: Debug for DerivedDescriptorKey < ' secp , C > {
770
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
771
+ f. debug_struct ( "DerivedDescriptorKey" )
772
+ . field ( "key" , & self . key )
773
+ . field ( "index" , & self . index )
774
+ . finish ( )
775
+ }
776
+ }
777
+
778
+ impl < ' secp , C : Verification > PartialEq for DerivedDescriptorKey < ' secp , C > {
779
+ fn eq ( & self , other : & Self ) -> bool {
780
+ self . key . eq ( & other. key ) && self . index . eq ( & other. index )
781
+ }
782
+ }
783
+ impl < ' secp , C : Verification > Eq for DerivedDescriptorKey < ' secp , C > { }
784
+
785
+ impl < ' secp , C : Verification > PartialOrd for DerivedDescriptorKey < ' secp , C > {
786
+ fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
787
+ Some ( self . cmp ( other) )
788
+ }
789
+ }
790
+ impl < ' secp , C : Verification > Ord for DerivedDescriptorKey < ' secp , C > {
791
+ fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
792
+ self . key
793
+ . cmp ( & other. key )
794
+ . then_with ( || self . index . cmp ( & other. index ) )
795
+ }
796
+ }
797
+
798
+ impl < ' secp , C : Verification > Clone for DerivedDescriptorKey < ' secp , C > {
799
+ fn clone ( & self ) -> Self {
800
+ DerivedDescriptorKey {
801
+ key : self . key . clone ( ) ,
802
+ index : self . index ,
803
+ secp : self . secp ,
804
+ }
805
+ }
806
+ }
807
+
808
+ impl < ' secp , C : Verification > hash:: Hash for DerivedDescriptorKey < ' secp , C > {
809
+ fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
810
+ self . key . hash ( state) ;
811
+ self . index . hash ( state) ;
812
+ }
813
+ }
814
+
815
+ impl < ' secp , C : Verification > MiniscriptKey for DerivedDescriptorKey < ' secp , C > {
816
+ // This allows us to be able to derive public keys even for PkH s
817
+ type Hash = Self ;
818
+
819
+ fn is_uncompressed ( & self ) -> bool {
820
+ self . key . is_uncompressed ( )
821
+ }
822
+
823
+ fn is_x_only_key ( & self ) -> bool {
824
+ self . key . is_x_only_key ( )
825
+ }
826
+
827
+ fn to_pubkeyhash ( & self ) -> Self {
828
+ self . clone ( )
829
+ }
830
+ }
831
+
832
+ impl < ' secp , C : Verification > ToPublicKey for DerivedDescriptorKey < ' secp , C > {
833
+ fn to_public_key ( & self ) -> bitcoin:: PublicKey {
834
+ self . key . derive_public_key ( & self . secp ) . unwrap ( )
835
+ }
836
+
837
+ fn hash_to_hash160 ( hash : & Self ) -> hash160:: Hash {
838
+ hash. to_public_key ( ) . to_pubkeyhash ( )
839
+ }
840
+ }
841
+
720
842
#[ cfg( test) ]
721
843
mod test {
722
844
use super :: { DescriptorKeyParseError , DescriptorPublicKey , DescriptorSecretKey } ;
0 commit comments