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