@@ -23,6 +23,7 @@ use std::sync::Arc;
23
23
use std:: { cmp, i64, mem} ;
24
24
25
25
use bitcoin:: hashes:: { hash160, ripemd160, sha256, sha256d} ;
26
+ use bitcoin:: util:: sighash;
26
27
use bitcoin:: { self , secp256k1} ;
27
28
use { MiniscriptKey , ToPublicKey } ;
28
29
@@ -34,14 +35,17 @@ use Miniscript;
34
35
use ScriptContext ;
35
36
use Terminal ;
36
37
37
- /// Type for a signature/hashtype pair
38
+ type LegacySigHashType = bitcoin:: SigHashType ;
39
+ type SchnorrSigHashType = sighash:: SigHashType ;
40
+ /// Type for a EC signature/hashtype pair
38
41
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
39
42
pub struct BitcoinECSig {
40
43
/// The underlying signature
41
44
pub sig : secp256k1:: Signature ,
42
45
/// The associated hash type
43
- pub hash_ty : bitcoin :: SigHashType ,
46
+ pub hash_ty : LegacySigHashType ,
44
47
}
48
+
45
49
/// Type alias for 32 byte Preimage.
46
50
pub type Preimage32 = [ u8 ; 32 ] ;
47
51
@@ -50,7 +54,9 @@ impl BitcoinECSig {
50
54
/// Useful for downstream when implementing Satisfier.
51
55
/// Returns underlying secp if the Signature is not of correct format
52
56
pub fn from_rawsig ( rawsig : & [ u8 ] ) -> Result < BitcoinECSig , :: interpreter:: Error > {
53
- let ( flag, sig) = rawsig. split_last ( ) . unwrap ( ) ;
57
+ let ( flag, sig) = rawsig
58
+ . split_last ( )
59
+ . ok_or ( :: interpreter:: Error :: NonStandardSigHash ( Vec :: from ( rawsig) ) ) ?;
54
60
let flag = bitcoin:: SigHashType :: from_u32_standard ( * flag as u32 ) . map_err ( |_| {
55
61
:: interpreter:: Error :: NonStandardSigHash ( [ sig, & [ * flag] ] . concat ( ) . to_vec ( ) )
56
62
} ) ?;
@@ -69,6 +75,53 @@ impl BitcoinECSig {
69
75
}
70
76
}
71
77
78
+ impl BitcoinSchnorrSig {
79
+ /// Helper function to create BitcoinSchnorrSig from raw sig bytes
80
+ /// Useful for downstream when implementing Satisfier.
81
+ /// Returns underlying secp if the Signature is not of correct format
82
+ pub fn from_rawsig ( rawsig : & [ u8 ] ) -> Result < BitcoinSchnorrSig , :: interpreter:: Error > {
83
+ let ( flag, sig) = if rawsig. len ( ) == 65 {
84
+ let ( flag, sig) = rawsig. split_last ( ) . unwrap ( ) ;
85
+ // Workaround to parse sighash type.
86
+ let legacy_flag = LegacySigHashType :: from_u32_standard ( * flag as u32 ) . map_err ( |_| {
87
+ :: interpreter:: Error :: InvalidSchnorrSigHashType ( [ sig, & [ * flag] ] . concat ( ) . to_vec ( ) )
88
+ } ) ?;
89
+ let schnorr_sighash_ty = SchnorrSigHashType :: from ( legacy_flag) ;
90
+ let schnorr_sig = secp256k1:: schnorrsig:: Signature :: from_slice ( sig) ?;
91
+ ( schnorr_sighash_ty, schnorr_sig)
92
+ } else {
93
+ // Other lengths would be correctly handled by secp
94
+ let schnorr_sig = secp256k1:: schnorrsig:: Signature :: from_slice ( rawsig) ?;
95
+ ( SchnorrSigHashType :: Default , schnorr_sig)
96
+ } ;
97
+ Ok ( BitcoinSchnorrSig {
98
+ sig : sig,
99
+ hash_ty : flag,
100
+ } )
101
+ }
102
+
103
+ /// Serialize to vec of bytes
104
+ pub fn serialize ( & self ) -> Vec < u8 > {
105
+ let mut ret = self . sig . as_ref ( ) . to_vec ( ) ;
106
+ if let SchnorrSigHashType :: Default = self . hash_ty {
107
+ // If the type is default, the sig is explicit 64 bytes
108
+ // nothing to push for sighash type
109
+ } else {
110
+ ret. push ( self . hash_ty as u8 ) ;
111
+ }
112
+ ret
113
+ }
114
+ }
115
+
116
+ /// Type for a schnorr signature/hashtype pair
117
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
118
+ pub struct BitcoinSchnorrSig {
119
+ /// The underlying schnorr signature
120
+ pub sig : secp256k1:: schnorrsig:: Signature ,
121
+ /// The associated hash type
122
+ pub hash_ty : SchnorrSigHashType ,
123
+ }
124
+
72
125
/// Trait describing a lookup table for signatures, hash preimages, etc.
73
126
/// Every method has a default implementation that simply returns `None`
74
127
/// on every query. Users are expected to override the methods that they
@@ -79,6 +132,11 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
79
132
None
80
133
}
81
134
135
+ /// Given a public key, look up an schnorr signature with that key
136
+ fn lookup_schnorr_sig ( & self , _: & Pk ) -> Option < BitcoinSchnorrSig > {
137
+ None
138
+ }
139
+
82
140
/// Given a `Pkh`, lookup corresponding `Pk`
83
141
fn lookup_pkh_pk ( & self , _: & Pk :: Hash ) -> Option < Pk > {
84
142
None
@@ -92,6 +150,17 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
92
150
None
93
151
}
94
152
153
+ /// Given a keyhash, look up the schnorr signature and the associated key
154
+ /// Even if signatures for public key Hashes are not available, the users
155
+ /// can use this map to provide pkh -> pk mapping which can be useful
156
+ /// for dissatisfying pkh.
157
+ fn lookup_pkh_schnorr_sig (
158
+ & self ,
159
+ _: & Pk :: Hash ,
160
+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
161
+ None
162
+ }
163
+
95
164
/// Given a SHA256 hash, look up its preimage
96
165
fn lookup_sha256 ( & self , _: sha256:: Hash ) -> Option < Preimage32 > {
97
166
None
@@ -172,6 +241,12 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for HashMap<Pk, BitcoinECSig
172
241
}
173
242
}
174
243
244
+ impl < Pk : MiniscriptKey + ToPublicKey > Satisfier < Pk > for HashMap < Pk , BitcoinSchnorrSig > {
245
+ fn lookup_schnorr_sig ( & self , key : & Pk ) -> Option < BitcoinSchnorrSig > {
246
+ self . get ( key) . map ( |x| * x)
247
+ }
248
+ }
249
+
175
250
impl < Pk : MiniscriptKey + ToPublicKey > Satisfier < Pk > for HashMap < Pk :: Hash , ( Pk , BitcoinECSig ) >
176
251
where
177
252
Pk : MiniscriptKey + ToPublicKey ,
@@ -190,11 +265,36 @@ where
190
265
}
191
266
}
192
267
268
+ impl < Pk : MiniscriptKey + ToPublicKey > Satisfier < Pk > for HashMap < Pk :: Hash , ( Pk , BitcoinSchnorrSig ) >
269
+ where
270
+ Pk : MiniscriptKey + ToPublicKey ,
271
+ {
272
+ fn lookup_schnorr_sig ( & self , key : & Pk ) -> Option < BitcoinSchnorrSig > {
273
+ self . get ( & key. to_pubkeyhash ( ) ) . map ( |x| x. 1 )
274
+ }
275
+
276
+ fn lookup_pkh_pk ( & self , pk_hash : & Pk :: Hash ) -> Option < Pk > {
277
+ self . get ( pk_hash) . map ( |x| x. 0 . clone ( ) )
278
+ }
279
+
280
+ fn lookup_pkh_schnorr_sig (
281
+ & self ,
282
+ pk_hash : & Pk :: Hash ,
283
+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
284
+ self . get ( pk_hash)
285
+ . map ( |& ( ref pk, sig) | ( pk. to_public_key ( ) , sig) )
286
+ }
287
+ }
288
+
193
289
impl < ' a , Pk : MiniscriptKey + ToPublicKey , S : Satisfier < Pk > > Satisfier < Pk > for & ' a S {
194
290
fn lookup_ec_sig ( & self , p : & Pk ) -> Option < BitcoinECSig > {
195
291
( * * self ) . lookup_ec_sig ( p)
196
292
}
197
293
294
+ fn lookup_schnorr_sig ( & self , p : & Pk ) -> Option < BitcoinSchnorrSig > {
295
+ ( * * self ) . lookup_schnorr_sig ( p)
296
+ }
297
+
198
298
fn lookup_pkh_pk ( & self , pkh : & Pk :: Hash ) -> Option < Pk > {
199
299
( * * self ) . lookup_pkh_pk ( pkh)
200
300
}
@@ -203,6 +303,13 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
203
303
( * * self ) . lookup_pkh_ec_sig ( pkh)
204
304
}
205
305
306
+ fn lookup_pkh_schnorr_sig (
307
+ & self ,
308
+ pkh : & Pk :: Hash ,
309
+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
310
+ ( * * self ) . lookup_pkh_schnorr_sig ( pkh)
311
+ }
312
+
206
313
fn lookup_sha256 ( & self , h : sha256:: Hash ) -> Option < Preimage32 > {
207
314
( * * self ) . lookup_sha256 ( h)
208
315
}
@@ -233,6 +340,10 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
233
340
( * * self ) . lookup_ec_sig ( p)
234
341
}
235
342
343
+ fn lookup_schnorr_sig ( & self , p : & Pk ) -> Option < BitcoinSchnorrSig > {
344
+ ( * * self ) . lookup_schnorr_sig ( p)
345
+ }
346
+
236
347
fn lookup_pkh_pk ( & self , pkh : & Pk :: Hash ) -> Option < Pk > {
237
348
( * * self ) . lookup_pkh_pk ( pkh)
238
349
}
@@ -241,6 +352,13 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
241
352
( * * self ) . lookup_pkh_ec_sig ( pkh)
242
353
}
243
354
355
+ fn lookup_pkh_schnorr_sig (
356
+ & self ,
357
+ pkh : & Pk :: Hash ,
358
+ ) -> Option < ( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
359
+ ( * * self ) . lookup_pkh_schnorr_sig ( pkh)
360
+ }
361
+
244
362
fn lookup_sha256 ( & self , h : sha256:: Hash ) -> Option < Preimage32 > {
245
363
( * * self ) . lookup_sha256 ( h)
246
364
}
@@ -284,6 +402,16 @@ macro_rules! impl_tuple_satisfier {
284
402
None
285
403
}
286
404
405
+ fn lookup_schnorr_sig( & self , key: & Pk ) -> Option <BitcoinSchnorrSig > {
406
+ let & ( $( ref $ty, ) * ) = self ;
407
+ $(
408
+ if let Some ( result) = $ty. lookup_schnorr_sig( key) {
409
+ return Some ( result) ;
410
+ }
411
+ ) *
412
+ None
413
+ }
414
+
287
415
fn lookup_pkh_ec_sig(
288
416
& self ,
289
417
key_hash: & Pk :: Hash ,
@@ -297,6 +425,19 @@ macro_rules! impl_tuple_satisfier {
297
425
None
298
426
}
299
427
428
+ fn lookup_pkh_schnorr_sig(
429
+ & self ,
430
+ key_hash: & Pk :: Hash ,
431
+ ) -> Option <( bitcoin:: PublicKey , BitcoinSchnorrSig ) > {
432
+ let & ( $( ref $ty, ) * ) = self ;
433
+ $(
434
+ if let Some ( result) = $ty. lookup_pkh_schnorr_sig( key_hash) {
435
+ return Some ( result) ;
436
+ }
437
+ ) *
438
+ None
439
+ }
440
+
300
441
fn lookup_pkh_pk(
301
442
& self ,
302
443
key_hash: & Pk :: Hash ,
0 commit comments