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(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
35#[display(uppercase)]
36#[repr(u8)]
37pub enum SighashFlag {
38    /// 0x1: Sign all outputs.
39    #[default]
40    All = 0x01,
41    /// 0x2: Sign no outputs --- anyone can choose the destination.
42    None = 0x02,
43    /// 0x3: Sign the output whose index matches this input's index. If none
44    /// exists, sign the hash
45    /// `0000000000000000000000000000000000000000000000000000000000000001`.
46    /// (This rule is probably an unintentional C++ism, but it's consensus, so
47    /// we have to follow it.)
48    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    /// Creates a [`SighashType`] from a raw `u32`.
100    ///
101    /// **Note**: this replicates consensus behaviour, for current standardness
102    /// rules correctness you probably want [`Self::from_standard_u32`].
103    ///
104    /// This might cause unexpected behavior because it does not roundtrip. That
105    /// is, `LegacySighashType::from_consensus(n) as u32 != n` for
106    /// non-standard values of `n`. While verifying signatures, the user
107    /// should retain the `n` and use it compute the signature hash message.
108    pub fn from_consensus_u32(n: u32) -> SighashType {
109        // In Bitcoin Core, the SignatureHash function will mask the (int32) value with
110        // 0x1f to (apparently) deactivate ACP when checking for SINGLE and NONE bits.
111        // We however want to be matching also against on ACP-masked ALL, SINGLE, and
112        // NONE. So here we re-activate ACP.
113        let mask = 0x1f | 0x80;
114        let (flag, anyone_can_pay) = match n & mask {
115            // "real" sighashes
116            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            // catchalls
123            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    /// Creates a [`SighashType`] from a raw `u32`.
133    ///
134    /// # Errors
135    ///
136    /// If `n` is a non-standard sighash value.
137    pub fn from_standard_u32(n: u32) -> Result<SighashType, NonStandardValue<u32>> {
138        let (flag, anyone_can_pay) = match n {
139            // Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198
140            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    /// Converts [`SighashType`] to a `u32` sighash flag.
155    ///
156    /// The returned value is guaranteed to be a valid according to standardness
157    /// rules.
158    #[inline]
159    pub const fn into_consensus_u32(self) -> u32 { self.into_consensus_u8() as u32 }
160
161    /// Converts [`SighashType`] to a `u32` sighash flag.
162    ///
163    /// The returned value is guaranteed to be a valid according to standardness
164    /// rules.
165    #[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/// Type used for generating sighash in SegWit signing
221#[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        // TODO: Parse instructions and check for the presence of OP_CODESEPARATOR
242        ScriptCode(witness_script.to_inner())
243    }
244
245    #[inline]
246    pub fn as_script_bytes(&self) -> &ScriptBytes { &self.0 }
247}
248
249/// An ECDSA signature-related error.
250#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)]
251#[display(doc_comments)]
252pub enum SigError {
253    /// Non-standard sighash type.
254    #[display(inner)]
255    #[from]
256    SighashType(NonStandardValue<u32>),
257
258    /// empty signature.
259    EmptySignature,
260
261    /// invalid signature DER encoding.
262    DerEncoding,
263
264    /// invalid BIP340 signature length ({0}).
265    Bip340Encoding(usize),
266
267    /// invalid BIP340 signature.
268    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    /// The underlying ECDSA Signature
277    pub sig: ecdsa::Signature,
278    /// The corresponding hash type
279    pub sighash_type: SighashType,
280}
281
282impl LegacySig {
283    /// Constructs an ECDSA bitcoin signature for [`SighashType::All`].
284    pub fn sighash_all(sig: ecdsa::Signature) -> LegacySig {
285        LegacySig {
286            sig,
287            sighash_type: SighashType::all(),
288        }
289    }
290
291    /// Deserializes from slice following the standardness rules for
292    /// [`SighashType`].
293    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    /// Serializes an Legacy signature (inner secp256k1 signature in DER format)
301    /// into `Vec`.
302    // TODO: add support to serialize to a writer to SerializedSig
303    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    /// The underlying ECDSA Signature
319    pub sig: schnorr::Signature,
320    /// The corresponding hash type
321    pub sighash_type: Option<SighashType>,
322}
323
324impl Bip340Sig {
325    /// Constructs an ECDSA bitcoin signature for [`SighashType::All`].
326    pub fn sighash_default(sig: schnorr::Signature) -> Self {
327        Bip340Sig {
328            sig,
329            sighash_type: None,
330        }
331    }
332
333    /// Deserializes from slice following the standardness rules for
334    /// [`SighashType`].
335    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    /// Serializes an ECDSA signature (inner secp256k1 signature in DER format)
348    /// into `Vec`.
349    // TODO: add support to serialize to a writer to SerializedSig
350    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}