1- use std:: { error, fmt, str:: FromStr } ;
1+ use std:: { cmp , error, fmt, hash , str:: FromStr } ;
22
33use bitcoin:: {
44 self ,
5- hashes:: Hash ,
5+ hashes:: { hash160 , Hash } ,
66 hashes:: { hex:: FromHex , HashEngine } ,
7- secp256k1,
8- secp256k1:: { Secp256k1 , Signing } ,
7+ secp256k1:: { Secp256k1 , Signing , Verification } ,
98 util:: bip32,
109 XOnlyPublicKey , XpubIdentifier ,
1110} ;
@@ -58,6 +57,15 @@ pub enum DescriptorSecretKey {
5857 XPrv ( DescriptorXKey < bip32:: ExtendedPrivKey > ) ,
5958}
6059
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+
6169impl fmt:: Display for DescriptorSecretKey {
6270 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
6371 match self {
@@ -438,7 +446,11 @@ impl DescriptorPublicKey {
438446 /// If this public key has a wildcard, replace it by the given index
439447 ///
440448 /// 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 > {
442454 if let DescriptorPublicKey :: XPub ( mut xpub) = self {
443455 match xpub. wildcard {
444456 Wildcard :: None => { }
@@ -456,7 +468,8 @@ impl DescriptorPublicKey {
456468 xpub. wildcard = Wildcard :: None ;
457469 self = DescriptorPublicKey :: XPub ( xpub) ;
458470 }
459- self
471+
472+ DerivedDescriptorKey :: new ( self , index, secp)
460473 }
461474
462475 /// Computes the public key corresponding to this descriptor key.
@@ -471,7 +484,7 @@ impl DescriptorPublicKey {
471484 /// to avoid hardened derivation steps, start from a `DescriptorSecretKey`
472485 /// and call `as_public`, or call `TranslatePk2::translate_pk2` with
473486 /// 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 > (
475488 & self ,
476489 secp : & Secp256k1 < C > ,
477490 ) -> Result < bitcoin:: PublicKey , ConversionError > {
@@ -717,6 +730,115 @@ impl MiniscriptKey for DescriptorPublicKey {
717730 }
718731}
719732
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+ f. debug_struct ( "DerivedDescriptorKey" )
767+ . field ( "key" , & self . key )
768+ . field ( "index" , & self . index )
769+ . finish ( )
770+ }
771+ }
772+ impl < ' secp , C : Verification > fmt:: Debug for DerivedDescriptorKey < ' secp , C > {
773+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
774+ self . key . fmt ( f)
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+
720842#[ cfg( test) ]
721843mod test {
722844 use super :: { DescriptorKeyParseError , DescriptorPublicKey , DescriptorSecretKey } ;
0 commit comments