1use std::fmt::{self, Display, Formatter};
23use std::iter;
24
25use amplify::{ByteArray, Bytes32, 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 Bytes32,
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 .iter()
307 .copied()
308 .chain(iter::once(self.sighash_type.into_consensus_u8()))
309 .collect()
310 }
311}
312
313#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
314#[derive(StrictType)]
315#[strict_type(lib = LIB_NAME_BITCOIN)]
316#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
317pub struct Bip340Sig {
318 pub sig: schnorr::Signature,
320 pub sighash_type: Option<SighashType>,
322}
323
324impl Bip340Sig {
325 pub fn sighash_default(sig: schnorr::Signature) -> Self {
327 Bip340Sig {
328 sig,
329 sighash_type: None,
330 }
331 }
332
333 pub fn from_bytes(bytes: &[u8]) -> Result<Self, SigError> {
336 let (hash_ty, sig) = match bytes.len() {
337 0 => return Err(SigError::EmptySignature),
338 64 => (None, bytes),
339 65 => (Some(bytes[64] as u32), &bytes[..64]),
340 invalid => return Err(SigError::Bip340Encoding(invalid)),
341 };
342 let sighash_type = hash_ty.map(SighashType::from_standard_u32).transpose()?;
343 let sig = schnorr::Signature::from_slice(sig).map_err(|_| SigError::InvalidSignature)?;
344 Ok(Bip340Sig { sig, sighash_type })
345 }
346
347 pub fn to_vec(self) -> Vec<u8> {
351 let mut ser = Vec::<u8>::with_capacity(65);
352 ser.extend_from_slice(&self.sig[..]);
353 if let Some(sighash_type) = self.sighash_type {
354 ser.push(sighash_type.into_consensus_u8())
355 }
356 ser
357 }
358}
359
360mod _strict_encode {
361 use std::io;
362
363 use amplify::confinement::TinyBlob;
364 use amplify::hex::FromHex;
365 use amplify::Bytes64;
366 use strict_encoding::{
367 DecodeError, ReadStruct, StrictDecode, StrictDumb, StrictEncode, TypedRead, TypedWrite,
368 WriteStruct,
369 };
370
371 use super::*;
372
373 impl StrictDumb for LegacySig {
374 fn strict_dumb() -> Self {
375 Self {
376 sig: ecdsa::Signature::from_der(&Vec::<u8>::from_hex(
377 "304402206fa6c164fb89906e2e1d291cc5461ceadf0f115c6b71e58f87482c94d512c3630220\
378 0ab641f3ece1d77f13ad2d8910cb7abd5a9b85f0f9036317dbb1470f22e7714c").unwrap()
379 ).expect("hardcoded signature"),
380 sighash_type: default!(),
381 }
382 }
383 }
384
385 impl StrictEncode for LegacySig {
386 fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
387 writer.write_struct::<Self>(|w| {
388 Ok(w.write_field(
389 fname!("sig"),
390 &TinyBlob::try_from(self.sig.serialize_der().to_vec())
391 .expect("invalid signature"),
392 )?
393 .write_field(fname!("sighash_type"), &self.sighash_type)?
394 .complete())
395 })
396 }
397 }
398
399 impl StrictDecode for LegacySig {
400 fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
401 reader.read_struct(|r| {
402 let bytes: TinyBlob = r.read_field(fname!("sig"))?;
403 let sig = ecdsa::Signature::from_der(bytes.as_slice()).map_err(|_| {
404 DecodeError::DataIntegrityError(s!("invalid signature DER encoding"))
405 })?;
406 let sighash_type = r.read_field(fname!("sighash_type"))?;
407 Ok(Self { sig, sighash_type })
408 })
409 }
410 }
411
412 impl StrictDumb for Bip340Sig {
413 fn strict_dumb() -> Self {
414 Bip340Sig::from_bytes(&Vec::<u8>::from_hex(
415 "a12b3f4c224619d7834f0bad0a598b79111ba08146ae1205f3e6220a132aef0ed8290379624db643\
416 e6b861d8dcd37b406a11f91a51bf5a6cdf9b3c9b772f67c301"
417 ).unwrap())
418 .expect("hardcoded signature")
419 }
420 }
421
422 impl StrictEncode for Bip340Sig {
423 fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
424 writer.write_struct::<Self>(|w| {
425 Ok(w.write_field(fname!("sig"), &Bytes64::from(*self.sig.as_ref()))?
426 .write_field(fname!("sighash_type"), &self.sighash_type)?
427 .complete())
428 })
429 }
430 }
431
432 impl StrictDecode for Bip340Sig {
433 fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
434 reader.read_struct(|r| {
435 let bytes: Bytes64 = r.read_field(fname!("sig"))?;
436 let sig = schnorr::Signature::from_slice(bytes.as_slice()).map_err(|_| {
437 DecodeError::DataIntegrityError(format!(
438 "invalid signature BIP340 encoding '{bytes:x}'"
439 ))
440 })?;
441 let sighash_type = r.read_field(fname!("sighash_type"))?;
442 Ok(Self { sig, sighash_type })
443 })
444 }
445 }
446}