bc/
sigtypes.rs

1// Bitcoin protocol consensus library.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved.
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22use 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    /// 0x1: Sign all outputs.
43    #[default]
44    All = 0x01,
45    /// 0x2: Sign no outputs --- anyone can choose the destination.
46    None = 0x02,
47    /// 0x3: Sign the output whose index matches this input's index. If none
48    /// exists, sign the hash
49    /// `0000000000000000000000000000000000000000000000000000000000000001`.
50    /// (This rule is probably an unintentional C++ism, but it's consensus, so
51    /// we have to follow it.)
52    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    /// Creates a [`SighashType`] from a raw `u32`.
108    ///
109    /// **Note**: this replicates consensus behaviour, for current standardness
110    /// rules correctness you probably want [`Self::from_standard_u32`].
111    ///
112    /// This might cause unexpected behavior because it does not roundtrip. That
113    /// is, `LegacySighashType::from_consensus(n) as u32 != n` for
114    /// non-standard values of `n`. While verifying signatures, the user
115    /// should retain the `n` and use it compute the signature hash message.
116    pub fn from_consensus_u32(n: u32) -> SighashType {
117        // In Bitcoin Core, the SignatureHash function will mask the (int32) value with
118        // 0x1f to (apparently) deactivate ACP when checking for SINGLE and NONE bits.
119        // We however want to be matching also against on ACP-masked ALL, SINGLE, and
120        // NONE. So here we re-activate ACP.
121        let mask = 0x1f | 0x80;
122        let (flag, anyone_can_pay) = match n & mask {
123            // "real" sighashes
124            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            // catchalls
131            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    /// Creates a [`SighashType`] from a raw `u32`.
141    ///
142    /// # Errors
143    ///
144    /// If `n` is a non-standard sighash value.
145    pub fn from_standard_u32(n: u32) -> Result<SighashType, NonStandardValue<u32>> {
146        let (flag, anyone_can_pay) = match n {
147            // Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198
148            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    /// Converts [`SighashType`] to a `u32` sighash flag.
163    ///
164    /// The returned value is guaranteed to be a valid according to standardness
165    /// rules.
166    #[inline]
167    pub const fn into_consensus_u32(self) -> u32 { self.into_consensus_u8() as u32 }
168
169    /// Converts [`SighashType`] to a `u32` sighash flag.
170    ///
171    /// The returned value is guaranteed to be a valid according to standardness
172    /// rules.
173    #[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/// Type used for generating sighash in SegWit signing
233#[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        // TODO: Parse instructions and check for the presence of OP_CODESEPARATOR
254        ScriptCode(witness_script.to_inner())
255    }
256
257    #[inline]
258    pub fn as_script_bytes(&self) -> &ScriptBytes { &self.0 }
259}
260
261/// An ECDSA signature-related error.
262#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)]
263#[display(doc_comments)]
264pub enum SigError {
265    /// Non-standard sighash type.
266    #[display(inner)]
267    #[from]
268    SighashType(NonStandardValue<u32>),
269
270    /// empty signature.
271    EmptySignature,
272
273    /// invalid signature DER encoding.
274    DerEncoding,
275
276    /// invalid BIP340 signature length ({0}).
277    Bip340Encoding(usize),
278
279    /// invalid BIP340 signature.
280    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    /// The underlying ECDSA Signature
293    pub sig: ecdsa::Signature,
294    /// The corresponding hash type
295    pub sighash_type: SighashType,
296}
297
298impl LegacySig {
299    /// Constructs an ECDSA bitcoin signature for [`SighashType::All`].
300    pub fn sighash_all(sig: ecdsa::Signature) -> LegacySig {
301        LegacySig {
302            sig,
303            sighash_type: SighashType::all(),
304        }
305    }
306
307    /// Deserializes from slice following the standardness rules for
308    /// [`SighashType`].
309    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    /// Serializes an Legacy signature (inner secp256k1 signature in DER format)
317    /// into `Vec`.
318    // TODO: add support to serialize to a writer to SerializedSig
319    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    /// The underlying ECDSA Signature
339    pub sig: schnorr::Signature,
340    /// The corresponding hash type
341    pub sighash_type: Option<SighashType>,
342}
343
344impl Bip340Sig {
345    /// Constructs an ECDSA bitcoin signature for [`SighashType::All`].
346    pub fn sighash_default(sig: schnorr::Signature) -> Self {
347        Bip340Sig {
348            sig,
349            sighash_type: None,
350        }
351    }
352
353    /// Deserializes from slice following the standardness rules for
354    /// [`SighashType`].
355    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    /// Serializes an ECDSA signature (inner secp256k1 signature in DER format)
368    /// into `Vec`.
369    // TODO: add support to serialize to a writer to SerializedSig
370    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}