@@ -34,14 +34,17 @@ use Miniscript;
34
34
use ScriptContext ;
35
35
use Terminal ;
36
36
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
38
40
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
39
41
pub struct BitcoinECSig {
40
42
/// The underlying signature
41
43
pub sig : secp256k1:: Signature ,
42
44
/// The associated hash type
43
- pub hash_ty : bitcoin :: SigHashType ,
45
+ pub hash_ty : LegacySigHashType ,
44
46
}
47
+
45
48
/// Type alias for 32 byte Preimage.
46
49
pub type Preimage32 = [ u8 ; 32 ] ;
47
50
@@ -50,7 +53,9 @@ impl BitcoinECSig {
50
53
/// Useful for downstream when implementing Satisfier.
51
54
/// Returns underlying secp if the Signature is not of correct format
52
55
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) ) ) ?;
54
59
let flag = bitcoin:: SigHashType :: from_u32_standard ( * flag as u32 ) . map_err ( |_| {
55
60
:: interpreter:: Error :: NonStandardSigHash ( [ sig, & [ * flag] ] . concat ( ) . to_vec ( ) )
56
61
} ) ?;
@@ -69,6 +74,53 @@ impl BitcoinECSig {
69
74
}
70
75
}
71
76
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
+
72
124
/// Trait describing a lookup table for signatures, hash preimages, etc.
73
125
/// Every method has a default implementation that simply returns `None`
74
126
/// on every query. Users are expected to override the methods that they
@@ -79,6 +131,11 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
79
131
None
80
132
}
81
133
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
+
82
139
/// Given a `Pkh`, lookup corresponding `Pk`
83
140
fn lookup_pkh_pk ( & self , _: & Pk :: Hash ) -> Option < Pk > {
84
141
None
@@ -92,6 +149,17 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
92
149
None
93
150
}
94
151
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
+
95
163
/// Given a SHA256 hash, look up its preimage
96
164
fn lookup_sha256 ( & self , _: sha256:: Hash ) -> Option < Preimage32 > {
97
165
None
@@ -172,6 +240,12 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for HashMap<Pk, BitcoinECSig
172
240
}
173
241
}
174
242
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
+
175
249
impl < Pk : MiniscriptKey + ToPublicKey > Satisfier < Pk > for HashMap < Pk :: Hash , ( Pk , BitcoinECSig ) >
176
250
where
177
251
Pk : MiniscriptKey + ToPublicKey ,
@@ -190,11 +264,36 @@ where
190
264
}
191
265
}
192
266
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
+
193
288
impl < ' a , Pk : MiniscriptKey + ToPublicKey , S : Satisfier < Pk > > Satisfier < Pk > for & ' a S {
194
289
fn lookup_ec_sig ( & self , p : & Pk ) -> Option < BitcoinECSig > {
195
290
( * * self ) . lookup_ec_sig ( p)
196
291
}
197
292
293
+ fn lookup_schnorr_sig ( & self , p : & Pk ) -> Option < BitcoinSchnorrSig > {
294
+ ( * * self ) . lookup_schnorr_sig ( p)
295
+ }
296
+
198
297
fn lookup_pkh_pk ( & self , pkh : & Pk :: Hash ) -> Option < Pk > {
199
298
( * * self ) . lookup_pkh_pk ( pkh)
200
299
}
@@ -203,6 +302,13 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
203
302
( * * self ) . lookup_pkh_ec_sig ( pkh)
204
303
}
205
304
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
+
206
312
fn lookup_sha256 ( & self , h : sha256:: Hash ) -> Option < Preimage32 > {
207
313
( * * self ) . lookup_sha256 ( h)
208
314
}
@@ -233,6 +339,10 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
233
339
( * * self ) . lookup_ec_sig ( p)
234
340
}
235
341
342
+ fn lookup_schnorr_sig ( & self , p : & Pk ) -> Option < BitcoinSchnorrSig > {
343
+ ( * * self ) . lookup_schnorr_sig ( p)
344
+ }
345
+
236
346
fn lookup_pkh_pk ( & self , pkh : & Pk :: Hash ) -> Option < Pk > {
237
347
( * * self ) . lookup_pkh_pk ( pkh)
238
348
}
@@ -241,6 +351,13 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
241
351
( * * self ) . lookup_pkh_ec_sig ( pkh)
242
352
}
243
353
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
+
244
361
fn lookup_sha256 ( & self , h : sha256:: Hash ) -> Option < Preimage32 > {
245
362
( * * self ) . lookup_sha256 ( h)
246
363
}
@@ -284,6 +401,16 @@ macro_rules! impl_tuple_satisfier {
284
401
None
285
402
}
286
403
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
+
287
414
fn lookup_pkh_ec_sig(
288
415
& self ,
289
416
key_hash: & Pk :: Hash ,
@@ -297,6 +424,19 @@ macro_rules! impl_tuple_satisfier {
297
424
None
298
425
}
299
426
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
+
300
440
fn lookup_pkh_pk(
301
441
& self ,
302
442
key_hash: & Pk :: Hash ,
0 commit comments