@@ -34,14 +34,17 @@ use Miniscript;
3434use ScriptContext ;
3535use Terminal ;
3636
37- /// Type for a signature/hashtype pair
37+ type LegacySigHashType = bitcoin:: SigHashType ;
38+ type SchnorrSigHashType = bitcoin:: util:: sighash:: SigHashType ;
39+ /// Type for a EC signature/hashtype pair
3840#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
3941pub struct BitcoinECSig {
4042 /// The underlying signature
4143 pub sig : secp256k1:: Signature ,
4244 /// The associated hash type
43- pub hash_ty : bitcoin :: SigHashType ,
45+ pub hash_ty : LegacySigHashType ,
4446}
47+
4548/// Type alias for 32 byte Preimage.
4649pub type Preimage32 = [ u8 ; 32 ] ;
4750
@@ -50,7 +53,9 @@ impl BitcoinECSig {
5053 /// Useful for downstream when implementing Satisfier.
5154 /// Returns underlying secp if the Signature is not of correct format
5255 pub fn from_rawsig ( rawsig : & [ u8 ] ) -> Result < BitcoinECSig , :: interpreter:: Error > {
53- let ( flag, sig) = rawsig. split_last ( ) . unwrap ( ) ;
56+ let ( flag, sig) = rawsig
57+ . split_last ( )
58+ . ok_or ( :: interpreter:: Error :: NonStandardSigHash ( Vec :: from ( rawsig) ) ) ?;
5459 let flag = bitcoin:: SigHashType :: from_u32_standard ( * flag as u32 ) . map_err ( |_| {
5560 :: interpreter:: Error :: NonStandardSigHash ( [ sig, & [ * flag] ] . concat ( ) . to_vec ( ) )
5661 } ) ?;
@@ -69,6 +74,53 @@ impl BitcoinECSig {
6974 }
7075}
7176
77+ impl BitcoinSchnorrSig {
78+ /// Helper function to create BitcoinSchnorrSig from raw sig bytes
79+ /// Useful for downstream when implementing Satisfier.
80+ /// Returns underlying secp if the Signature is not of correct format
81+ pub fn from_rawsig ( rawsig : & [ u8 ] ) -> Result < BitcoinSchnorrSig , :: interpreter:: Error > {
82+ let ( flag, sig) = if rawsig. len ( ) == 65 {
83+ let ( flag, sig) = rawsig. split_last ( ) . unwrap ( ) ;
84+ // Workaround to parse sighash type.
85+ let legacy_flag = LegacySigHashType :: from_u32_standard ( * flag as u32 ) . map_err ( |_| {
86+ :: interpreter:: Error :: InvalidSchnorrSigHashType ( [ sig, & [ * flag] ] . concat ( ) . to_vec ( ) )
87+ } ) ?;
88+ let schnorr_sighash_ty = SchnorrSigHashType :: from ( legacy_flag) ;
89+ let schnorr_sig = secp256k1:: schnorrsig:: Signature :: from_slice ( sig) ?;
90+ ( schnorr_sighash_ty, schnorr_sig)
91+ } else {
92+ // Other lengths would be correctly handled by secp
93+ let schnorr_sig = secp256k1:: schnorrsig:: Signature :: from_slice ( rawsig) ?;
94+ ( bitcoin:: util:: sighash:: SigHashType :: Default , schnorr_sig)
95+ } ;
96+ Ok ( BitcoinSchnorrSig {
97+ sig : sig,
98+ hash_ty : flag,
99+ } )
100+ }
101+
102+ /// Serialize to vec of bytes
103+ pub fn serialize ( & self ) -> Vec < u8 > {
104+ let mut ret = self . sig . as_ref ( ) . to_vec ( ) ;
105+ if let bitcoin:: util:: sighash:: SigHashType :: Default = self . hash_ty {
106+ // If the type is default, the sig is explicit 64 bytes
107+ // nothing to push for sighash type
108+ } else {
109+ ret. push ( self . hash_ty as u8 ) ;
110+ }
111+ ret
112+ }
113+ }
114+
115+ /// Type for a schnorr signature/hashtype pair
116+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
117+ pub struct BitcoinSchnorrSig {
118+ /// The underlying schnorr signature
119+ pub sig : secp256k1:: schnorrsig:: Signature ,
120+ /// The associated hash type
121+ pub hash_ty : SchnorrSigHashType ,
122+ }
123+
72124/// Trait describing a lookup table for signatures, hash preimages, etc.
73125/// Every method has a default implementation that simply returns `None`
74126/// on every query. Users are expected to override the methods that they
@@ -79,6 +131,11 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
79131 None
80132 }
81133
134+ /// Given a public key, look up an schnorr signature with that key
135+ fn lookup_schnorr_sig ( & self , _: & Pk ) -> Option < BitcoinSchnorrSig > {
136+ None
137+ }
138+
82139 /// Given a `Pkh`, lookup corresponding `Pk`
83140 fn lookup_pkh_pk ( & self , _: & Pk :: Hash ) -> Option < Pk > {
84141 None
@@ -92,6 +149,17 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
92149 None
93150 }
94151
152+ /// Given a keyhash, look up the schnorr signature and the associated key
153+ /// Even if signatures for public key Hashes are not available, the users
154+ /// can use this map to provide pkh -> pk mapping which can be useful
155+ /// for dissatisfying pkh.
156+ fn lookup_pkh_schnorr_sig (
157+ & self ,
158+ _: & Pk :: Hash ,
159+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
160+ None
161+ }
162+
95163 /// Given a SHA256 hash, look up its preimage
96164 fn lookup_sha256 ( & self , _: sha256:: Hash ) -> Option < Preimage32 > {
97165 None
@@ -172,6 +240,12 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for HashMap<Pk, BitcoinECSig
172240 }
173241}
174242
243+ impl < Pk : MiniscriptKey + ToPublicKey > Satisfier < Pk > for HashMap < Pk , BitcoinSchnorrSig > {
244+ fn lookup_schnorr_sig ( & self , key : & Pk ) -> Option < BitcoinSchnorrSig > {
245+ self . get ( key) . map ( |x| * x)
246+ }
247+ }
248+
175249impl < Pk : MiniscriptKey + ToPublicKey > Satisfier < Pk > for HashMap < Pk :: Hash , ( Pk , BitcoinECSig ) >
176250where
177251 Pk : MiniscriptKey + ToPublicKey ,
@@ -190,11 +264,36 @@ where
190264 }
191265}
192266
267+ impl < Pk : MiniscriptKey + ToPublicKey > Satisfier < Pk > for HashMap < Pk :: Hash , ( Pk , BitcoinSchnorrSig ) >
268+ where
269+ Pk : MiniscriptKey + ToPublicKey ,
270+ {
271+ fn lookup_schnorr_sig ( & self , key : & Pk ) -> Option < BitcoinSchnorrSig > {
272+ self . get ( & key. to_pubkeyhash ( ) ) . map ( |x| x. 1 )
273+ }
274+
275+ fn lookup_pkh_pk ( & self , pk_hash : & Pk :: Hash ) -> Option < Pk > {
276+ self . get ( pk_hash) . map ( |x| x. 0 . clone ( ) )
277+ }
278+
279+ fn lookup_pkh_schnorr_sig (
280+ & self ,
281+ pk_hash : & Pk :: Hash ,
282+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
283+ self . get ( pk_hash)
284+ . map ( |& ( ref pk, sig) | ( pk. to_public_key ( ) , sig) )
285+ }
286+ }
287+
193288impl < ' a , Pk : MiniscriptKey + ToPublicKey , S : Satisfier < Pk > > Satisfier < Pk > for & ' a S {
194289 fn lookup_ec_sig ( & self , p : & Pk ) -> Option < BitcoinECSig > {
195290 ( * * self ) . lookup_ec_sig ( p)
196291 }
197292
293+ fn lookup_schnorr_sig ( & self , p : & Pk ) -> Option < BitcoinSchnorrSig > {
294+ ( * * self ) . lookup_schnorr_sig ( p)
295+ }
296+
198297 fn lookup_pkh_pk ( & self , pkh : & Pk :: Hash ) -> Option < Pk > {
199298 ( * * self ) . lookup_pkh_pk ( pkh)
200299 }
@@ -203,6 +302,13 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
203302 ( * * self ) . lookup_pkh_ec_sig ( pkh)
204303 }
205304
305+ fn lookup_pkh_schnorr_sig (
306+ & self ,
307+ pkh : & Pk :: Hash ,
308+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
309+ ( * * self ) . lookup_pkh_schnorr_sig ( pkh)
310+ }
311+
206312 fn lookup_sha256 ( & self , h : sha256:: Hash ) -> Option < Preimage32 > {
207313 ( * * self ) . lookup_sha256 ( h)
208314 }
@@ -233,6 +339,10 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
233339 ( * * self ) . lookup_ec_sig ( p)
234340 }
235341
342+ fn lookup_schnorr_sig ( & self , p : & Pk ) -> Option < BitcoinSchnorrSig > {
343+ ( * * self ) . lookup_schnorr_sig ( p)
344+ }
345+
236346 fn lookup_pkh_pk ( & self , pkh : & Pk :: Hash ) -> Option < Pk > {
237347 ( * * self ) . lookup_pkh_pk ( pkh)
238348 }
@@ -241,6 +351,13 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
241351 ( * * self ) . lookup_pkh_ec_sig ( pkh)
242352 }
243353
354+ fn lookup_pkh_schnorr_sig (
355+ & self ,
356+ pkh : & Pk :: Hash ,
357+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
358+ ( * * self ) . lookup_pkh_schnorr_sig ( pkh)
359+ }
360+
244361 fn lookup_sha256 ( & self , h : sha256:: Hash ) -> Option < Preimage32 > {
245362 ( * * self ) . lookup_sha256 ( h)
246363 }
@@ -284,6 +401,16 @@ macro_rules! impl_tuple_satisfier {
284401 None
285402 }
286403
404+ fn lookup_schnorr_sig( & self , key: & Pk ) -> Option <BitcoinSchnorrSig > {
405+ let & ( $( ref $ty, ) * ) = self ;
406+ $(
407+ if let Some ( result) = $ty. lookup_schnorr_sig( key) {
408+ return Some ( result) ;
409+ }
410+ ) *
411+ None
412+ }
413+
287414 fn lookup_pkh_ec_sig(
288415 & self ,
289416 key_hash: & Pk :: Hash ,
@@ -297,6 +424,19 @@ macro_rules! impl_tuple_satisfier {
297424 None
298425 }
299426
427+ fn lookup_pkh_schnorr_sig(
428+ & self ,
429+ key_hash: & Pk :: Hash ,
430+ ) -> Option <( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
431+ let & ( $( ref $ty, ) * ) = self ;
432+ $(
433+ if let Some ( result) = $ty. lookup_pkh_schnorr_sig( key_hash) {
434+ return Some ( result) ;
435+ }
436+ ) *
437+ None
438+ }
439+
300440 fn lookup_pkh_pk(
301441 & self ,
302442 key_hash: & Pk :: Hash ,
0 commit comments