Skip to main content

mini_bitcoin_script/
error.rs

1/// All error conditions that can arise during script parsing or execution.
2#[derive(Debug, Clone, PartialEq, Eq)]
3pub enum ScriptError {
4    /// Stack had fewer elements than the operation required.
5    StackUnderflow,
6
7    /// Script byte stream ended mid-instruction.
8    UnexpectedEndOfScript,
9
10    /// A push-data length field is malformed or exceeds remaining bytes.
11    InvalidPushData,
12
13    /// An opcode byte is valid in Bitcoin but not implemented by this engine.
14    UnsupportedOpcode(u8),
15
16    /// OP_VERIFY, OP_EQUALVERIFY, or OP_CHECKSIGVERIFY consumed a false value.
17    VerifyFailed,
18
19    /// Execution completed but the stack is empty or the top element is false.
20    ScriptFailed,
21
22    /// OP_RETURN was encountered. The script is provably unspendable.
23    OpReturnEncountered,
24
25    /// OP_IF / OP_NOTIF / OP_ELSE / OP_ENDIF are not properly balanced.
26    UnbalancedConditional,
27
28    /// A hex string could not be decoded (odd length or invalid character).
29    InvalidHex,
30}
31
32impl std::fmt::Display for ScriptError {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        match self {
35            ScriptError::StackUnderflow => {
36                write!(f, "stack underflow: not enough elements on the stack")
37            }
38            ScriptError::UnexpectedEndOfScript => {
39                write!(f, "unexpected end of script")
40            }
41            ScriptError::InvalidPushData => {
42                write!(f, "invalid push data encoding")
43            }
44            ScriptError::UnsupportedOpcode(b) => {
45                write!(f, "unsupported opcode: 0x{b:02x}")
46            }
47            ScriptError::VerifyFailed => {
48                write!(f, "verify failed: top stack element is false")
49            }
50            ScriptError::ScriptFailed => {
51                write!(f, "script failed: final stack state is false")
52            }
53            ScriptError::OpReturnEncountered => {
54                write!(f, "OP_RETURN encountered: script is unspendable")
55            }
56            ScriptError::UnbalancedConditional => {
57                write!(f, "unbalanced conditional: mismatched IF/ELSE/ENDIF")
58            }
59            ScriptError::InvalidHex => {
60                write!(f, "invalid hex string")
61            }
62        }
63    }
64}
65
66impl std::error::Error for ScriptError {}