@@ -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} ;
@@ -70,6 +69,15 @@ pub enum SinglePubKey {
7069 XOnly ( XOnlyPublicKey ) ,
7170}
7271
72+ /// A derived [`DescriptorPublicKey`]
73+ ///
74+ /// Derived keys are guaranteed to never contain wildcards
75+ #[ derive( Debug , Eq , PartialEq , Clone , Ord , PartialOrd , Hash ) ]
76+ pub struct DerivedDescriptorKey {
77+ key : DescriptorPublicKey ,
78+ index : u32 ,
79+ }
80+
7381impl fmt:: Display for DescriptorSecretKey {
7482 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
7583 match self {
@@ -434,7 +442,7 @@ impl DescriptorPublicKey {
434442 /// If this public key has a wildcard, replace it by the given index
435443 ///
436444 /// Panics if given an index ≥ 2^31
437- pub fn derive ( mut self , index : u32 ) -> DescriptorPublicKey {
445+ pub fn derive ( mut self , index : u32 ) -> DerivedDescriptorKey {
438446 if let DescriptorPublicKey :: XPub ( mut xpub) = self {
439447 match xpub. wildcard {
440448 Wildcard :: None => { }
@@ -452,7 +460,9 @@ impl DescriptorPublicKey {
452460 xpub. wildcard = Wildcard :: None ;
453461 self = DescriptorPublicKey :: XPub ( xpub) ;
454462 }
455- self
463+
464+ DerivedDescriptorKey :: new ( self , index)
465+ . expect ( "The key should not contain any wildcards at this point" )
456466 }
457467
458468 /// Computes the public key corresponding to this descriptor key.
@@ -467,7 +477,7 @@ impl DescriptorPublicKey {
467477 /// to avoid hardened derivation steps, start from a `DescriptorSecretKey`
468478 /// and call `as_public`, or call `TranslatePk2::translate_pk2` with
469479 /// some function which has access to secret key data.
470- pub fn derive_public_key < C : secp256k1 :: Verification > (
480+ pub fn derive_public_key < C : Verification > (
471481 & self ,
472482 secp : & Secp256k1 < C > ,
473483 ) -> Result < bitcoin:: PublicKey , ConversionError > {
@@ -713,6 +723,70 @@ impl MiniscriptKey for DescriptorPublicKey {
713723 }
714724}
715725
726+ impl DerivedDescriptorKey {
727+ /// Computes the raw [`bitcoin::PublicKey`] for this descriptor key.
728+ ///
729+ /// Will return an error if the key has any hardened derivation steps
730+ /// in its path, but unlike [`DescriptorPublicKey::derive_public_key`]
731+ /// this won't error in case of wildcards, because derived keys are
732+ /// guaranteed to never contain one.
733+ pub fn derive_public_key < C : Verification > (
734+ & self ,
735+ secp : & Secp256k1 < C > ,
736+ ) -> Result < bitcoin:: PublicKey , ConversionError > {
737+ self . key . derive_public_key ( secp)
738+ }
739+
740+ /// Return the derivation index of this key
741+ pub fn get_index ( & self ) -> u32 {
742+ self . index
743+ }
744+
745+ /// Construct an instance from a descriptor key and a derivation index
746+ ///
747+ /// Returns `None` if the key contains a wildcard
748+ fn new ( key : DescriptorPublicKey , index : u32 ) -> Option < Self > {
749+ match key {
750+ DescriptorPublicKey :: XPub ( ref xpk) if xpk. wildcard != Wildcard :: None => None ,
751+ k => Some ( DerivedDescriptorKey { key : k, index } ) ,
752+ }
753+ }
754+ }
755+
756+ impl fmt:: Display for DerivedDescriptorKey {
757+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
758+ self . key . fmt ( f)
759+ }
760+ }
761+
762+ impl MiniscriptKey for DerivedDescriptorKey {
763+ // This allows us to be able to derive public keys even for PkH s
764+ type Hash = Self ;
765+
766+ fn is_uncompressed ( & self ) -> bool {
767+ self . key . is_uncompressed ( )
768+ }
769+
770+ fn is_x_only_key ( & self ) -> bool {
771+ self . key . is_x_only_key ( )
772+ }
773+
774+ fn to_pubkeyhash ( & self ) -> Self {
775+ self . clone ( )
776+ }
777+ }
778+
779+ impl ToPublicKey for DerivedDescriptorKey {
780+ fn to_public_key ( & self ) -> bitcoin:: PublicKey {
781+ let secp = Secp256k1 :: verification_only ( ) ;
782+ self . key . derive_public_key ( & secp) . unwrap ( )
783+ }
784+
785+ fn hash_to_hash160 ( hash : & Self ) -> hash160:: Hash {
786+ hash. to_public_key ( ) . to_pubkeyhash ( )
787+ }
788+ }
789+
716790#[ cfg( test) ]
717791mod test {
718792 use super :: { DescriptorKeyParseError , DescriptorPublicKey , DescriptorSecretKey } ;
0 commit comments