bitcoin/blockdata/script/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Bitcoin scripts.
4//!
5//! *[See also the `Script` type](Script).*
6//!
7//! This module provides the structures and functions needed to support scripts.
8//!
9//! <details>
10//! <summary>What is Bitcoin script</summary>
11//!
12//! Scripts define Bitcoin's digital signature scheme: a signature is formed
13//! from a script (the second half of which is defined by a coin to be spent,
14//! and the first half provided by the spending transaction), and is valid iff
15//! the script leaves `TRUE` on the stack after being evaluated. Bitcoin's
16//! script is a stack-based assembly language similar in spirit to [Forth].
17//!
18//! Script is represented as a sequence of bytes on the wire, each byte representing an operation,
19//! or data to be pushed on the stack.
20//!
21//! See [Bitcoin Wiki: Script][wiki-script] for more information.
22//!
23//! [Forth]: https://en.wikipedia.org/wiki/Forth_(programming_language)
24//!
25//! [wiki-script]: https://en.bitcoin.it/wiki/Script
26//! </details>
27//!
28//! In this library we chose to keep the byte representation in memory and decode opcodes only when
29//! processing the script. This is similar to Rust choosing to represent strings as UTF-8-encoded
30//! bytes rather than slice of `char`s. In both cases the individual items can have different sizes
31//! and forcing them to be larger would waste memory and, in case of Bitcoin script, even some
32//! performance (forcing allocations).
33//!
34//! ## `Script` vs `ScriptBuf` vs `Builder`
35//!
36//! These are the most important types in this module and they are quite similar, so it may seem
37//! confusing what the differences are. `Script` is an unsized type much like `str` or `Path` are
38//! and `ScriptBuf` is an owned counterpart to `Script` just like `String` is an owned counterpart
39//! to `str`.
40//!
41//! However it is common to construct an owned script and then pass it around. For this case a
42//! builder API is more convenient. To support this we provide `Builder` type which is very similar
43//! to `ScriptBuf` but its methods take `self` instead of `&mut self` and return `Self`. It also
44//! contains a cache that may make some modifications faster. This cache is usually not needed
45//! outside of creating the script.
46//!
47//! At the time of writing there's only one operation using the cache - `push_verify`, so the cache
48//! is minimal but we may extend it in the future if needed.
49
50mod borrowed;
51mod builder;
52mod instruction;
53mod owned;
54mod push_bytes;
55#[cfg(test)]
56mod tests;
57pub mod witness_program;
58pub mod witness_version;
59
60use alloc::rc::Rc;
61#[cfg(any(not(rust_v_1_60), target_has_atomic = "ptr"))]
62use alloc::sync::Arc;
63use core::cmp::Ordering;
64use core::fmt;
65use core::ops::{Deref, DerefMut};
66
67use hashes::{hash160, sha256};
68use io::{Read, Write};
69
70use crate::blockdata::opcodes::all::*;
71use crate::blockdata::opcodes::{self, Opcode};
72use crate::consensus::{encode, Decodable, Encodable};
73use crate::internal_macros::impl_asref_push_bytes;
74use crate::prelude::*;
75use crate::OutPoint;
76
77#[rustfmt::skip]                // Keep public re-exports separate.
78#[doc(inline)]
79pub use self::{
80    borrowed::*,
81    builder::*,
82    instruction::*,
83    owned::*,
84    push_bytes::*,
85};
86
87hashes::hash_newtype! {
88    /// A hash of Bitcoin Script bytecode.
89    pub struct ScriptHash(hash160::Hash);
90    /// SegWit version of a Bitcoin Script bytecode hash.
91    pub struct WScriptHash(sha256::Hash);
92}
93impl_asref_push_bytes!(ScriptHash, WScriptHash);
94
95impl From<ScriptBuf> for ScriptHash {
96    fn from(script: ScriptBuf) -> ScriptHash { script.script_hash() }
97}
98
99impl From<&ScriptBuf> for ScriptHash {
100    fn from(script: &ScriptBuf) -> ScriptHash { script.script_hash() }
101}
102
103impl From<&Script> for ScriptHash {
104    fn from(script: &Script) -> ScriptHash { script.script_hash() }
105}
106
107impl From<ScriptBuf> for WScriptHash {
108    fn from(script: ScriptBuf) -> WScriptHash { script.wscript_hash() }
109}
110
111impl From<&ScriptBuf> for WScriptHash {
112    fn from(script: &ScriptBuf) -> WScriptHash { script.wscript_hash() }
113}
114
115impl From<&Script> for WScriptHash {
116    fn from(script: &Script) -> WScriptHash { script.wscript_hash() }
117}
118
119/// Encodes an integer in script(minimal CScriptNum) format.
120///
121/// Writes bytes into the buffer and returns the number of bytes written.
122///
123/// Note that `write_scriptint`/`read_scriptint` do not roundtrip if the value written requires
124/// more than 4 bytes, this is in line with Bitcoin Core (see [`CScriptNum::serialize`]).
125///
126/// [`CScriptNum::serialize`]: <https://github.com/bitcoin/bitcoin/blob/8ae2808a4354e8dcc697f76bacc5e2f2befe9220/src/script/script.h#L345>
127pub fn write_scriptint(out: &mut [u8; 8], n: i64) -> usize {
128    let mut len = 0;
129    if n == 0 {
130        return len;
131    }
132
133    let neg = n < 0;
134
135    let mut abs = n.unsigned_abs();
136    while abs > 0xFF {
137        out[len] = (abs & 0xFF) as u8;
138        len += 1;
139        abs >>= 8;
140    }
141    // If the number's value causes the sign bit to be set, we need an extra
142    // byte to get the correct value and correct sign bit
143    if abs & 0x80 != 0 {
144        out[len] = abs as u8;
145        len += 1;
146        out[len] = if neg { 0x80u8 } else { 0u8 };
147        len += 1;
148    }
149    // Otherwise we just set the sign bit ourselves
150    else {
151        abs |= if neg { 0x80 } else { 0 };
152        out[len] = abs as u8;
153        len += 1;
154    }
155    len
156}
157
158/// Decodes an integer in script(minimal CScriptNum) format.
159///
160/// Notice that this fails on overflow: the result is the same as in
161/// bitcoind, that only 4-byte signed-magnitude values may be read as
162/// numbers. They can be added or subtracted (and a long time ago,
163/// multiplied and divided), and this may result in numbers which
164/// can't be written out in 4 bytes or less. This is ok! The number
165/// just can't be read as a number again.
166/// This is a bit crazy and subtle, but it makes sense: you can load
167/// 32-bit numbers and do anything with them, which back when mult/div
168/// was allowed, could result in up to a 64-bit number. We don't want
169/// overflow since that's surprising --- and we don't want numbers that
170/// don't fit in 64 bits (for efficiency on modern processors) so we
171/// simply say, anything in excess of 32 bits is no longer a number.
172/// This is basically a ranged type implementation.
173///
174/// This code is based on the `CScriptNum` constructor in Bitcoin Core (see `script.h`).
175pub fn read_scriptint(v: &[u8]) -> Result<i64, Error> {
176    let last = match v.last() {
177        Some(last) => last,
178        None => return Ok(0),
179    };
180    if v.len() > 4 {
181        return Err(Error::NumericOverflow);
182    }
183    // Comment and code copied from Bitcoin Core:
184    // https://github.com/bitcoin/bitcoin/blob/447f50e4aed9a8b1d80e1891cda85801aeb80b4e/src/script/script.h#L247-L262
185    // If the most-significant-byte - excluding the sign bit - is zero
186    // then we're not minimal. Note how this test also rejects the
187    // negative-zero encoding, 0x80.
188    if (*last & 0x7f) == 0 {
189        // One exception: if there's more than one byte and the most
190        // significant bit of the second-most-significant-byte is set
191        // it would conflict with the sign bit. An example of this case
192        // is +-255, which encode to 0xff00 and 0xff80 respectively.
193        // (big-endian).
194        if v.len() <= 1 || (v[v.len() - 2] & 0x80) == 0 {
195            return Err(Error::NonMinimalPush);
196        }
197    }
198
199    Ok(scriptint_parse(v))
200}
201
202/// Decodes an integer in script format without non-minimal error.
203///
204/// The overflow error for slices over 4 bytes long is still there.
205/// See [`read_scriptint`] for a description of some subtleties of
206/// this function.
207pub fn read_scriptint_non_minimal(v: &[u8]) -> Result<i64, Error> {
208    if v.is_empty() {
209        return Ok(0);
210    }
211    if v.len() > 4 {
212        return Err(Error::NumericOverflow);
213    }
214
215    Ok(scriptint_parse(v))
216}
217
218// Caller to guarantee that `v` is not empty.
219fn scriptint_parse(v: &[u8]) -> i64 {
220    let (mut ret, sh) = v.iter().fold((0, 0), |(acc, sh), n| (acc + ((*n as i64) << sh), sh + 8));
221    if v[v.len() - 1] & 0x80 != 0 {
222        ret &= (1 << (sh - 1)) - 1;
223        ret = -ret;
224    }
225    ret
226}
227
228/// Decodes a boolean.
229///
230/// This is like "`read_scriptint` then map 0 to false and everything
231/// else as true", except that the overflow rules don't apply.
232#[inline]
233pub fn read_scriptbool(v: &[u8]) -> bool {
234    match v.split_last() {
235        Some((last, rest)) => !((last & !0x80 == 0x00) && rest.iter().all(|&b| b == 0)),
236        None => false,
237    }
238}
239
240// We internally use implementation based on iterator so that it automatically advances as needed
241// Errors are same as above, just different type.
242fn read_uint_iter(data: &mut core::slice::Iter<'_, u8>, size: usize) -> Result<usize, UintError> {
243    if data.len() < size {
244        Err(UintError::EarlyEndOfScript)
245    } else if size > usize::from(u16::MAX / 8) {
246        // Casting to u32 would overflow
247        Err(UintError::NumericOverflow)
248    } else {
249        let mut ret = 0;
250        for (i, item) in data.take(size).enumerate() {
251            ret = usize::from(*item)
252                // Casting is safe because we checked above to not repeat the same check in a loop
253                .checked_shl((i * 8) as u32)
254                .ok_or(UintError::NumericOverflow)?
255                .checked_add(ret)
256                .ok_or(UintError::NumericOverflow)?;
257        }
258        Ok(ret)
259    }
260}
261
262fn opcode_to_verify(opcode: Option<Opcode>) -> Option<Opcode> {
263    opcode.and_then(|opcode| match opcode {
264        OP_EQUAL => Some(OP_EQUALVERIFY),
265        OP_NUMEQUAL => Some(OP_NUMEQUALVERIFY),
266        OP_CHECKSIG => Some(OP_CHECKSIGVERIFY),
267        OP_CHECKMULTISIG => Some(OP_CHECKMULTISIGVERIFY),
268        _ => None,
269    })
270}
271
272// We keep all the `Script` and `ScriptBuf` impls together since its easier to see side-by-side.
273
274impl From<ScriptBuf> for Box<Script> {
275    fn from(v: ScriptBuf) -> Self { v.into_boxed_script() }
276}
277
278impl From<ScriptBuf> for Cow<'_, Script> {
279    fn from(value: ScriptBuf) -> Self { Cow::Owned(value) }
280}
281
282impl<'a> From<Cow<'a, Script>> for ScriptBuf {
283    fn from(value: Cow<'a, Script>) -> Self {
284        match value {
285            Cow::Owned(owned) => owned,
286            Cow::Borrowed(borrwed) => borrwed.into(),
287        }
288    }
289}
290
291impl<'a> From<Cow<'a, Script>> for Box<Script> {
292    fn from(value: Cow<'a, Script>) -> Self {
293        match value {
294            Cow::Owned(owned) => owned.into(),
295            Cow::Borrowed(borrwed) => borrwed.into(),
296        }
297    }
298}
299
300impl<'a> From<&'a Script> for Box<Script> {
301    fn from(value: &'a Script) -> Self { value.to_owned().into() }
302}
303
304impl<'a> From<&'a Script> for ScriptBuf {
305    fn from(value: &'a Script) -> Self { value.to_owned() }
306}
307
308impl<'a> From<&'a Script> for Cow<'a, Script> {
309    fn from(value: &'a Script) -> Self { Cow::Borrowed(value) }
310}
311
312/// Note: This will fail to compile on old Rust for targets that don't support atomics
313#[cfg(any(not(rust_v_1_60), target_has_atomic = "ptr"))]
314impl<'a> From<&'a Script> for Arc<Script> {
315    fn from(value: &'a Script) -> Self {
316        let rw: *const [u8] = Arc::into_raw(Arc::from(&value.0));
317        // SAFETY: copied from `std`
318        // The pointer was just created from an Arc without deallocating
319        // Casting a slice to a transparent struct wrapping that slice is sound (same
320        // layout).
321        unsafe { Arc::from_raw(rw as *const Script) }
322    }
323}
324
325impl<'a> From<&'a Script> for Rc<Script> {
326    fn from(value: &'a Script) -> Self {
327        let rw: *const [u8] = Rc::into_raw(Rc::from(&value.0));
328        // SAFETY: copied from `std`
329        // The pointer was just created from an Rc without deallocating
330        // Casting a slice to a transparent struct wrapping that slice is sound (same
331        // layout).
332        unsafe { Rc::from_raw(rw as *const Script) }
333    }
334}
335
336impl From<Vec<u8>> for ScriptBuf {
337    fn from(v: Vec<u8>) -> Self { ScriptBuf(v) }
338}
339
340impl From<ScriptBuf> for Vec<u8> {
341    fn from(v: ScriptBuf) -> Self { v.0 }
342}
343
344impl AsRef<Script> for Script {
345    #[inline]
346    fn as_ref(&self) -> &Script { self }
347}
348
349impl AsRef<Script> for ScriptBuf {
350    fn as_ref(&self) -> &Script { self }
351}
352
353impl AsRef<[u8]> for Script {
354    #[inline]
355    fn as_ref(&self) -> &[u8] { self.as_bytes() }
356}
357
358impl AsRef<[u8]> for ScriptBuf {
359    fn as_ref(&self) -> &[u8] { self.as_bytes() }
360}
361
362impl AsMut<Script> for Script {
363    fn as_mut(&mut self) -> &mut Script { self }
364}
365
366impl AsMut<Script> for ScriptBuf {
367    fn as_mut(&mut self) -> &mut Script { self }
368}
369
370impl AsMut<[u8]> for Script {
371    #[inline]
372    fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
373}
374
375impl AsMut<[u8]> for ScriptBuf {
376    fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
377}
378
379impl fmt::Debug for Script {
380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
381        f.write_str("Script(")?;
382        self.fmt_asm(f)?;
383        f.write_str(")")
384    }
385}
386
387impl fmt::Debug for ScriptBuf {
388    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_script(), f) }
389}
390
391impl fmt::Display for Script {
392    #[inline]
393    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_asm(f) }
394}
395
396impl fmt::Display for ScriptBuf {
397    #[inline]
398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.as_script(), f) }
399}
400
401impl fmt::LowerHex for Script {
402    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403        fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
404    }
405}
406
407impl fmt::LowerHex for ScriptBuf {
408    #[inline]
409    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self.as_script(), f) }
410}
411
412impl fmt::UpperHex for Script {
413    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
414        fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
415    }
416}
417
418impl fmt::UpperHex for ScriptBuf {
419    #[inline]
420    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(self.as_script(), f) }
421}
422
423impl Deref for ScriptBuf {
424    type Target = Script;
425
426    fn deref(&self) -> &Self::Target { Script::from_bytes(&self.0) }
427}
428
429impl DerefMut for ScriptBuf {
430    fn deref_mut(&mut self) -> &mut Self::Target { Script::from_bytes_mut(&mut self.0) }
431}
432
433impl Borrow<Script> for ScriptBuf {
434    fn borrow(&self) -> &Script { self }
435}
436
437impl BorrowMut<Script> for ScriptBuf {
438    fn borrow_mut(&mut self) -> &mut Script { self }
439}
440
441impl PartialEq<ScriptBuf> for Script {
442    fn eq(&self, other: &ScriptBuf) -> bool { self.eq(other.as_script()) }
443}
444
445impl PartialEq<Script> for ScriptBuf {
446    fn eq(&self, other: &Script) -> bool { self.as_script().eq(other) }
447}
448
449impl PartialOrd<Script> for ScriptBuf {
450    fn partial_cmp(&self, other: &Script) -> Option<Ordering> {
451        self.as_script().partial_cmp(other)
452    }
453}
454
455impl PartialOrd<ScriptBuf> for Script {
456    fn partial_cmp(&self, other: &ScriptBuf) -> Option<Ordering> {
457        self.partial_cmp(other.as_script())
458    }
459}
460
461#[cfg(feature = "serde")]
462impl serde::Serialize for Script {
463    /// User-facing serialization for `Script`.
464    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
465    where
466        S: serde::Serializer,
467    {
468        if serializer.is_human_readable() {
469            serializer.collect_str(&format_args!("{:x}", self))
470        } else {
471            serializer.serialize_bytes(self.as_bytes())
472        }
473    }
474}
475
476/// Can only deserialize borrowed bytes.
477#[cfg(feature = "serde")]
478impl<'de> serde::Deserialize<'de> for &'de Script {
479    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
480    where
481        D: serde::Deserializer<'de>,
482    {
483        if deserializer.is_human_readable() {
484            use crate::serde::de::Error;
485
486            return Err(D::Error::custom(
487                "deserialization of `&Script` from human-readable formats is not possible",
488            ));
489        }
490
491        struct Visitor;
492        impl<'de> serde::de::Visitor<'de> for Visitor {
493            type Value = &'de Script;
494
495            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
496                formatter.write_str("borrowed bytes")
497            }
498
499            fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
500            where
501                E: serde::de::Error,
502            {
503                Ok(Script::from_bytes(v))
504            }
505        }
506        deserializer.deserialize_bytes(Visitor)
507    }
508}
509
510#[cfg(feature = "serde")]
511impl serde::Serialize for ScriptBuf {
512    /// User-facing serialization for `Script`.
513    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
514    where
515        S: serde::Serializer,
516    {
517        (**self).serialize(serializer)
518    }
519}
520
521#[cfg(feature = "serde")]
522impl<'de> serde::Deserialize<'de> for ScriptBuf {
523    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
524    where
525        D: serde::Deserializer<'de>,
526    {
527        use core::fmt::Formatter;
528
529        use hex::FromHex;
530
531        if deserializer.is_human_readable() {
532            struct Visitor;
533            impl<'de> serde::de::Visitor<'de> for Visitor {
534                type Value = ScriptBuf;
535
536                fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
537                    formatter.write_str("a script hex")
538                }
539
540                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
541                where
542                    E: serde::de::Error,
543                {
544                    let v = Vec::from_hex(v).map_err(E::custom)?;
545                    Ok(ScriptBuf::from(v))
546                }
547            }
548            deserializer.deserialize_str(Visitor)
549        } else {
550            struct BytesVisitor;
551
552            impl<'de> serde::de::Visitor<'de> for BytesVisitor {
553                type Value = ScriptBuf;
554
555                fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
556                    formatter.write_str("a script Vec<u8>")
557                }
558
559                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
560                where
561                    E: serde::de::Error,
562                {
563                    Ok(ScriptBuf::from(v.to_vec()))
564                }
565
566                fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
567                where
568                    E: serde::de::Error,
569                {
570                    Ok(ScriptBuf::from(v))
571                }
572            }
573            deserializer.deserialize_byte_buf(BytesVisitor)
574        }
575    }
576}
577
578impl Encodable for Script {
579    #[inline]
580    fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
581        crate::consensus::encode::consensus_encode_with_size(&self.0, w)
582    }
583}
584
585impl Encodable for ScriptBuf {
586    #[inline]
587    fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
588        self.0.consensus_encode(w)
589    }
590}
591
592impl Decodable for ScriptBuf {
593    #[inline]
594    fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
595        r: &mut R,
596    ) -> Result<Self, encode::Error> {
597        Ok(ScriptBuf(Decodable::consensus_decode_from_finite_reader(r)?))
598    }
599}
600
601/// Writes the assembly decoding of the script bytes to the formatter.
602pub(super) fn bytes_to_asm_fmt(script: &[u8], f: &mut dyn fmt::Write) -> fmt::Result {
603    // This has to be a macro because it needs to break the loop
604    macro_rules! read_push_data_len {
605        ($iter:expr, $len:literal, $formatter:expr) => {
606            match read_uint_iter($iter, $len) {
607                Ok(n) => {
608                    n
609                },
610                Err(UintError::EarlyEndOfScript) => {
611                    $formatter.write_str("<unexpected end>")?;
612                    break;
613                }
614                // We got the data in a slice which implies it being shorter than `usize::MAX`
615                // So if we got overflow, we can confidently say the number is higher than length of
616                // the slice even though we don't know the exact number. This implies attempt to push
617                // past end.
618                Err(UintError::NumericOverflow) => {
619                    $formatter.write_str("<push past end>")?;
620                    break;
621                }
622            }
623        }
624    }
625
626    let mut iter = script.iter();
627    // Was at least one opcode emitted?
628    let mut at_least_one = false;
629    // `iter` needs to be borrowed in `read_push_data_len`, so we have to use `while let` instead
630    // of `for`.
631    while let Some(byte) = iter.next() {
632        let opcode = Opcode::from(*byte);
633
634        let data_len = if let opcodes::Class::PushBytes(n) =
635            opcode.classify(opcodes::ClassifyContext::Legacy)
636        {
637            n as usize
638        } else {
639            match opcode {
640                OP_PUSHDATA1 => {
641                    // side effects: may write and break from the loop
642                    read_push_data_len!(&mut iter, 1, f)
643                }
644                OP_PUSHDATA2 => {
645                    // side effects: may write and break from the loop
646                    read_push_data_len!(&mut iter, 2, f)
647                }
648                OP_PUSHDATA4 => {
649                    // side effects: may write and break from the loop
650                    read_push_data_len!(&mut iter, 4, f)
651                }
652                _ => 0,
653            }
654        };
655
656        if at_least_one {
657            f.write_str(" ")?;
658        } else {
659            at_least_one = true;
660        }
661        // Write the opcode
662        if opcode == OP_PUSHBYTES_0 {
663            f.write_str("OP_0")?;
664        } else {
665            write!(f, "{:?}", opcode)?;
666        }
667        // Write any pushdata
668        if data_len > 0 {
669            f.write_str(" ")?;
670            if data_len <= iter.len() {
671                for ch in iter.by_ref().take(data_len) {
672                    write!(f, "{:02x}", ch)?;
673                }
674            } else {
675                f.write_str("<push past end>")?;
676                break;
677            }
678        }
679    }
680    Ok(())
681}
682
683/// Ways that a script might fail. Not everything is split up as
684/// much as it could be; patches welcome if more detailed errors
685/// would help you.
686#[derive(Debug, Clone, PartialEq, Eq)]
687#[non_exhaustive]
688pub enum Error {
689    /// Something did a non-minimal push; for more information see
690    /// <https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#push-operators>
691    NonMinimalPush,
692    /// Some opcode expected a parameter but it was missing or truncated.
693    EarlyEndOfScript,
694    /// Tried to read an array off the stack as a number when it was more than 4 bytes.
695    NumericOverflow,
696    /// Can not find the spent output.
697    UnknownSpentOutput(OutPoint),
698    /// Can not serialize the spending transaction.
699    Serialization,
700}
701
702internals::impl_from_infallible!(Error);
703
704impl fmt::Display for Error {
705    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
706        use Error::*;
707
708        match *self {
709            NonMinimalPush => f.write_str("non-minimal datapush"),
710            EarlyEndOfScript => f.write_str("unexpected end of script"),
711            NumericOverflow =>
712                f.write_str("numeric overflow (number on stack larger than 4 bytes)"),
713            UnknownSpentOutput(ref point) => write!(f, "unknown spent output: {}", point),
714            Serialization =>
715                f.write_str("can not serialize the spending transaction in Transaction::verify()"),
716        }
717    }
718}
719
720#[cfg(feature = "std")]
721impl std::error::Error for Error {
722    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
723        use Error::*;
724
725        match *self {
726            NonMinimalPush
727            | EarlyEndOfScript
728            | NumericOverflow
729            | UnknownSpentOutput(_)
730            | Serialization => None,
731        }
732    }
733}
734
735// Our internal error proves that we only return these two cases from `read_uint_iter`.
736// Since it's private we don't bother with trait impls besides From.
737enum UintError {
738    EarlyEndOfScript,
739    NumericOverflow,
740}
741
742internals::impl_from_infallible!(UintError);
743
744impl From<UintError> for Error {
745    fn from(error: UintError) -> Self {
746        match error {
747            UintError::EarlyEndOfScript => Error::EarlyEndOfScript,
748            UintError::NumericOverflow => Error::NumericOverflow,
749        }
750    }
751}