@@ -2,10 +2,9 @@ use std::{error, fmt, 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+ #[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
64+ pub struct DerivedDescriptorKey {
65+ key : DescriptorPublicKey ,
66+ index : u32 ,
67+ }
68+
6169impl fmt:: Display for DescriptorSecretKey {
6270 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
6371 match self {
@@ -438,7 +446,7 @@ 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 ( mut self , index : u32 ) -> DerivedDescriptorKey {
442450 if let DescriptorPublicKey :: XPub ( mut xpub) = self {
443451 match xpub. wildcard {
444452 Wildcard :: None => { }
@@ -456,7 +464,8 @@ impl DescriptorPublicKey {
456464 xpub. wildcard = Wildcard :: None ;
457465 self = DescriptorPublicKey :: XPub ( xpub) ;
458466 }
459- self
467+
468+ DerivedDescriptorKey :: new ( self , index)
460469 }
461470
462471 /// Computes the public key corresponding to this descriptor key.
@@ -471,7 +480,7 @@ impl DescriptorPublicKey {
471480 /// to avoid hardened derivation steps, start from a `DescriptorSecretKey`
472481 /// and call `as_public`, or call `TranslatePk2::translate_pk2` with
473482 /// some function which has access to secret key data.
474- pub fn derive_public_key < C : secp256k1 :: Verification > (
483+ pub fn derive_public_key < C : Verification > (
475484 & self ,
476485 secp : & Secp256k1 < C > ,
477486 ) -> Result < bitcoin:: PublicKey , ConversionError > {
@@ -717,6 +726,74 @@ impl MiniscriptKey for DescriptorPublicKey {
717726 }
718727}
719728
729+ impl DerivedDescriptorKey {
730+ /// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
731+ ///
732+ /// Will return an error if the key has any hardened derivation steps
733+ /// in its path, but unlike [`DescriptorPublicKey::derive_public_key`]
734+ /// this won't error in case of wildcards, because derived keys are
735+ /// guaranteed to never contain one.
736+ pub fn derive_public_key < C : Verification > (
737+ & self ,
738+ secp : & Secp256k1 < C > ,
739+ ) -> Result < bitcoin:: PublicKey , ConversionError > {
740+ self . key . derive_public_key ( secp)
741+ }
742+
743+ /// Return the derivation index of this key
744+ pub fn get_index ( & self ) -> u32 {
745+ self . index
746+ }
747+
748+ /// Construct an instance from a descriptor key and a derivation index
749+ ///
750+ /// Panics if the key contains a wildcard
751+ fn new ( key : DescriptorPublicKey , index : u32 ) -> Self {
752+ if let DescriptorPublicKey :: XPub ( ref xpk) = & key {
753+ assert ! (
754+ xpk. wildcard == Wildcard :: None ,
755+ "Derived descriptor keys cannot contain any wildcards"
756+ ) ;
757+ }
758+
759+ DerivedDescriptorKey { key, index }
760+ }
761+ }
762+
763+ impl fmt:: Display for DerivedDescriptorKey {
764+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
765+ self . key . fmt ( f)
766+ }
767+ }
768+
769+ impl MiniscriptKey for DerivedDescriptorKey {
770+ // This allows us to be able to derive public keys even for PkH s
771+ type Hash = Self ;
772+
773+ fn is_uncompressed ( & self ) -> bool {
774+ self . key . is_uncompressed ( )
775+ }
776+
777+ fn is_x_only_key ( & self ) -> bool {
778+ self . key . is_x_only_key ( )
779+ }
780+
781+ fn to_pubkeyhash ( & self ) -> Self {
782+ self . clone ( )
783+ }
784+ }
785+
786+ impl ToPublicKey for DerivedDescriptorKey {
787+ fn to_public_key ( & self ) -> bitcoin:: PublicKey {
788+ let secp = Secp256k1 :: verification_only ( ) ;
789+ self . key . derive_public_key ( & secp) . unwrap ( )
790+ }
791+
792+ fn hash_to_hash160 ( hash : & Self ) -> hash160:: Hash {
793+ hash. to_public_key ( ) . to_pubkeyhash ( )
794+ }
795+ }
796+
720797#[ cfg( test) ]
721798mod test {
722799 use super :: { DescriptorKeyParseError , DescriptorPublicKey , DescriptorSecretKey } ;
0 commit comments