1use std::fmt::{self, Display, Formatter};
23use std::iter;
24
25use amplify::{ByteArray, Bytes32StrRev, Wrapper};
26use commit_verify::{DigestExt, Sha256};
27use secp256k1::{ecdsa, schnorr};
28
29use crate::{NonStandardValue, ScriptBytes, ScriptPubkey, WitnessScript, LIB_NAME_BITCOIN};
30
31#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Display, Default)]
32#[derive(StrictType, StrictEncode, StrictDecode)]
33#[strict_type(lib = LIB_NAME_BITCOIN, tags = repr, into_u8, try_from_u8)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
35#[display(uppercase)]
36#[repr(u8)]
37pub enum SighashFlag {
38 #[default]
40 All = 0x01,
41 None = 0x02,
43 Single = 0x03,
49}
50
51#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Default)]
52#[derive(StrictType, StrictEncode, StrictDecode)]
53#[strict_type(lib = LIB_NAME_BITCOIN)]
54#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
55pub struct SighashType {
56 pub flag: SighashFlag,
57 pub anyone_can_pay: bool,
58}
59
60impl SighashType {
61 pub const fn all() -> Self {
62 SighashType {
63 flag: SighashFlag::All,
64 anyone_can_pay: false,
65 }
66 }
67 pub const fn none() -> Self {
68 SighashType {
69 flag: SighashFlag::None,
70 anyone_can_pay: false,
71 }
72 }
73 pub const fn single() -> Self {
74 SighashType {
75 flag: SighashFlag::Single,
76 anyone_can_pay: false,
77 }
78 }
79
80 pub const fn all_anyone_can_pay() -> Self {
81 SighashType {
82 flag: SighashFlag::All,
83 anyone_can_pay: true,
84 }
85 }
86 pub const fn none_anyone_can_pay() -> Self {
87 SighashType {
88 flag: SighashFlag::None,
89 anyone_can_pay: true,
90 }
91 }
92 pub const fn single_anyone_can_pay() -> Self {
93 SighashType {
94 flag: SighashFlag::Single,
95 anyone_can_pay: true,
96 }
97 }
98
99 pub fn from_consensus_u32(n: u32) -> SighashType {
109 let mask = 0x1f | 0x80;
114 let (flag, anyone_can_pay) = match n & mask {
115 0x01 => (SighashFlag::All, false),
117 0x02 => (SighashFlag::None, false),
118 0x03 => (SighashFlag::Single, false),
119 0x81 => (SighashFlag::All, true),
120 0x82 => (SighashFlag::None, true),
121 0x83 => (SighashFlag::Single, true),
122 x if x & 0x80 == 0x80 => (SighashFlag::All, true),
124 _ => (SighashFlag::All, false),
125 };
126 SighashType {
127 flag,
128 anyone_can_pay,
129 }
130 }
131
132 pub fn from_standard_u32(n: u32) -> Result<SighashType, NonStandardValue<u32>> {
138 let (flag, anyone_can_pay) = match n {
139 0x01 => (SighashFlag::All, false),
141 0x02 => (SighashFlag::None, false),
142 0x03 => (SighashFlag::Single, false),
143 0x81 => (SighashFlag::All, true),
144 0x82 => (SighashFlag::None, true),
145 0x83 => (SighashFlag::Single, true),
146 non_standard => return Err(NonStandardValue::with(non_standard, "SighashType")),
147 };
148 Ok(SighashType {
149 flag,
150 anyone_can_pay,
151 })
152 }
153
154 #[inline]
159 pub const fn into_consensus_u32(self) -> u32 { self.into_consensus_u8() as u32 }
160
161 #[inline]
166 pub const fn to_consensus_u32(&self) -> u32 { self.into_consensus_u32() }
167
168 pub const fn into_consensus_u8(self) -> u8 {
169 let flag = self.flag as u8;
170 let mask = (self.anyone_can_pay as u8) << 7;
171 flag | mask
172 }
173
174 pub const fn to_consensus_u8(self) -> u8 {
175 let flag = self.flag as u8;
176 let mask = (self.anyone_can_pay as u8) << 7;
177 flag | mask
178 }
179}
180
181impl Display for SighashType {
182 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
183 Display::fmt(&self.flag, f)?;
184 if self.anyone_can_pay {
185 f.write_str(" | ANYONECANPAY")?;
186 }
187 Ok(())
188 }
189}
190
191#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
192#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
193#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
194#[strict_type(lib = LIB_NAME_BITCOIN)]
195#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
196pub struct Sighash(
197 #[from]
198 #[from([u8; 32])]
199 pub Bytes32StrRev,
200);
201
202impl From<Sighash> for [u8; 32] {
203 fn from(value: Sighash) -> Self { value.0.into_inner() }
204}
205
206impl From<Sighash> for secp256k1::Message {
207 fn from(sighash: Sighash) -> Self { secp256k1::Message::from_digest(sighash.to_byte_array()) }
208}
209
210impl Sighash {
211 pub fn engine() -> Sha256 { Sha256::default() }
212
213 pub fn from_engine(engine: Sha256) -> Self {
214 let mut engine2 = Sha256::default();
215 engine2.input_raw(&engine.finish());
216 Self(engine2.finish().into())
217 }
218}
219
220#[derive(Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
222#[wrapper(Deref, AsSlice, Hex)]
223#[wrapper_mut(DerefMut, AsSliceMut)]
224pub struct ScriptCode(ScriptBytes);
225
226impl ScriptCode {
227 pub fn with_p2sh_wpkh(script_pubkey: &ScriptPubkey) -> Self { Self::with_p2wpkh(script_pubkey) }
228
229 pub fn with_p2wpkh(script_pubkey: &ScriptPubkey) -> Self {
230 let mut pubkey_hash = [0u8; 20];
231 pubkey_hash.copy_from_slice(&script_pubkey[2..22]);
232 let script_code = ScriptPubkey::p2pkh(pubkey_hash);
233 ScriptCode(script_code.into_inner())
234 }
235
236 pub fn with_p2sh_wsh(witness_script: &WitnessScript) -> Self {
237 Self::with_p2wsh(witness_script)
238 }
239
240 pub fn with_p2wsh(witness_script: &WitnessScript) -> Self {
241 ScriptCode(witness_script.to_inner())
243 }
244
245 #[inline]
246 pub fn as_script_bytes(&self) -> &ScriptBytes { &self.0 }
247}
248
249#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)]
251#[display(doc_comments)]
252pub enum SigError {
253 #[display(inner)]
255 #[from]
256 SighashType(NonStandardValue<u32>),
257
258 EmptySignature,
260
261 DerEncoding,
263
264 Bip340Encoding(usize),
266
267 InvalidSignature,
269}
270
271#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
272#[derive(StrictType)]
273#[strict_type(lib = LIB_NAME_BITCOIN)]
274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
275pub struct LegacySig {
276 pub sig: ecdsa::Signature,
278 pub sighash_type: SighashType,
280}
281
282impl LegacySig {
283 pub fn sighash_all(sig: ecdsa::Signature) -> LegacySig {
285 LegacySig {
286 sig,
287 sighash_type: SighashType::all(),
288 }
289 }
290
291 pub fn from_bytes(bytes: &[u8]) -> Result<Self, SigError> {
294 let (hash_ty, sig) = bytes.split_last().ok_or(SigError::EmptySignature)?;
295 let sighash_type = SighashType::from_standard_u32(*hash_ty as u32)?;
296 let sig = ecdsa::Signature::from_der(sig).map_err(|_| SigError::DerEncoding)?;
297 Ok(LegacySig { sig, sighash_type })
298 }
299
300 pub fn to_vec(self) -> Vec<u8> {
304 self.sig
305 .serialize_der()
306 .into_iter()
307 .chain(iter::once(self.sighash_type.into_consensus_u8()))
308 .collect()
309 }
310}
311
312#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
313#[derive(StrictType)]
314#[strict_type(lib = LIB_NAME_BITCOIN)]
315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
316pub struct Bip340Sig {
317 pub sig: schnorr::Signature,
319 pub sighash_type: Option<SighashType>,
321}
322
323impl Bip340Sig {
324 pub fn sighash_default(sig: schnorr::Signature) -> Self {
326 Bip340Sig {
327 sig,
328 sighash_type: None,
329 }
330 }
331
332 pub fn from_bytes(bytes: &[u8]) -> Result<Self, SigError> {
335 let (hash_ty, sig) = match bytes.len() {
336 0 => return Err(SigError::EmptySignature),
337 64 => (None, bytes),
338 65 => (Some(bytes[64] as u32), &bytes[..64]),
339 invalid => return Err(SigError::Bip340Encoding(invalid)),
340 };
341 let sighash_type = hash_ty.map(SighashType::from_standard_u32).transpose()?;
342 let sig = schnorr::Signature::from_slice(sig).map_err(|_| SigError::InvalidSignature)?;
343 Ok(Bip340Sig { sig, sighash_type })
344 }
345
346 pub fn to_vec(self) -> Vec<u8> {
350 let mut ser = Vec::<u8>::with_capacity(65);
351 ser.extend_from_slice(&self.sig[..]);
352 if let Some(sighash_type) = self.sighash_type {
353 ser.push(sighash_type.into_consensus_u8())
354 }
355 ser
356 }
357}
358
359mod _strict_encode {
360 use std::io;
361
362 use amplify::confinement::TinyBlob;
363 use amplify::hex::FromHex;
364 use amplify::Bytes64;
365 use strict_encoding::{
366 DecodeError, ReadStruct, StrictDecode, StrictDumb, StrictEncode, TypedRead, TypedWrite,
367 WriteStruct,
368 };
369
370 use super::*;
371
372 impl StrictDumb for LegacySig {
373 fn strict_dumb() -> Self {
374 Self {
375 sig: ecdsa::Signature::from_der(&Vec::<u8>::from_hex(
376 "304402206fa6c164fb89906e2e1d291cc5461ceadf0f115c6b71e58f87482c94d512c3630220\
377 0ab641f3ece1d77f13ad2d8910cb7abd5a9b85f0f9036317dbb1470f22e7714c").unwrap()
378 ).expect("hardcoded signature"),
379 sighash_type: default!(),
380 }
381 }
382 }
383
384 impl StrictEncode for LegacySig {
385 fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
386 writer.write_struct::<Self>(|w| {
387 Ok(w.write_field(
388 fname!("sig"),
389 &TinyBlob::try_from(self.sig.serialize_der().to_vec())
390 .expect("invalid signature"),
391 )?
392 .write_field(fname!("sighash_type"), &self.sighash_type)?
393 .complete())
394 })
395 }
396 }
397
398 impl StrictDecode for LegacySig {
399 fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
400 reader.read_struct(|r| {
401 let bytes: TinyBlob = r.read_field(fname!("sig"))?;
402 let sig = ecdsa::Signature::from_der(bytes.as_slice()).map_err(|_| {
403 DecodeError::DataIntegrityError(s!("invalid signature DER encoding"))
404 })?;
405 let sighash_type = r.read_field(fname!("sighash_type"))?;
406 Ok(Self { sig, sighash_type })
407 })
408 }
409 }
410
411 impl StrictDumb for Bip340Sig {
412 fn strict_dumb() -> Self {
413 Bip340Sig::from_bytes(&Vec::<u8>::from_hex(
414 "a12b3f4c224619d7834f0bad0a598b79111ba08146ae1205f3e6220a132aef0ed8290379624db643\
415 e6b861d8dcd37b406a11f91a51bf5a6cdf9b3c9b772f67c301"
416 ).unwrap())
417 .expect("hardcoded signature")
418 }
419 }
420
421 impl StrictEncode for Bip340Sig {
422 fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
423 writer.write_struct::<Self>(|w| {
424 Ok(w.write_field(fname!("sig"), &Bytes64::from(*self.sig.as_ref()))?
425 .write_field(fname!("sighash_type"), &self.sighash_type)?
426 .complete())
427 })
428 }
429 }
430
431 impl StrictDecode for Bip340Sig {
432 fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
433 reader.read_struct(|r| {
434 let bytes: Bytes64 = r.read_field(fname!("sig"))?;
435 let sig = schnorr::Signature::from_slice(bytes.as_slice()).map_err(|_| {
436 DecodeError::DataIntegrityError(format!(
437 "invalid signature BIP340 encoding '{bytes:x}'"
438 ))
439 })?;
440 let sighash_type = r.read_field(fname!("sighash_type"))?;
441 Ok(Self { sig, sighash_type })
442 })
443 }
444 }
445}