midnight_onchain_vm/
error.rs1use crate::vm::{MAX_LOG_SIZE, MAX_STACK_HEIGHT};
15use base_crypto::fab::{AlignedValue, InvalidBuiltinDecode};
16use derive_where::derive_where;
17use runtime_state::state::{CELL_BOUND, StateValue};
18use std::convert::Infallible;
19use std::error::Error;
20use std::fmt::{self, Display, Formatter};
21use storage::db::DB;
22
23#[derive_where(Debug, Clone, PartialEq, Eq)]
24pub enum OnchainProgramError<D: DB> {
25 RanOffStack,
26 RanPastProgramEnd,
27 ExpectedCell(StateValue<D>),
28 Decode(InvalidBuiltinDecode),
29 ArithmeticOverflow,
30 TooLongForEqual,
31 TypeError(String),
33 OutOfGas,
34 BoundsExceeded,
35 LogBoundExceeded,
36 InvalidArgs(String),
37 MissingKey,
38 CacheMiss,
39 AttemptedArrayDelete,
40 ReadMismatch {
41 expected: AlignedValue,
42 actual: AlignedValue,
43 },
44 CellBoundExceeded,
45 StackOverflow,
46}
47
48impl<D: DB> From<Infallible> for OnchainProgramError<D> {
49 fn from(err: Infallible) -> OnchainProgramError<D> {
50 match err {}
51 }
52}
53
54impl<D: DB> From<InvalidBuiltinDecode> for OnchainProgramError<D> {
55 fn from(err: InvalidBuiltinDecode) -> OnchainProgramError<D> {
56 OnchainProgramError::Decode(err)
57 }
58}
59
60impl<D: DB> Display for OnchainProgramError<D> {
61 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
62 use OnchainProgramError::*;
63 match self {
64 RanOffStack => write!(f, "ran off stack"),
65 RanPastProgramEnd => write!(f, "ran past end of program"),
66 ExpectedCell(state_value) => {
67 let descriptor = match state_value {
68 StateValue::Null => Some("null"),
69 StateValue::Cell(_) => Some("cell"),
70 StateValue::BoundedMerkleTree(_) => Some("bounded Merkle tree"),
71 StateValue::Map(_) => Some("map"),
72 StateValue::Array(_) => Some("array"),
73 _ => None,
74 };
75 match descriptor {
76 Some(d) => write!(f, "expected a cell, received {d}"),
77 None => write!(f, "bug found: unexpected state value"),
78 }
79 }
80 ArithmeticOverflow => write!(f, "arithmetic overflow"),
81 TooLongForEqual => write!(f, "data is too long for equality check"),
82 TypeError(msg) => write!(f, "invalid operation for type: {}", msg),
83 OutOfGas => write!(f, "ran out of gas budget"),
84 BoundsExceeded => write!(f, "exceeded structure bounds"),
85 InvalidArgs(msg) => write!(f, "invalid argument to primitive operation: {msg}"),
86 MissingKey => write!(f, "key not found"),
87 CacheMiss => write!(f, "value declared to be in cache wasn't"),
88 AttemptedArrayDelete => write!(f, "attempted to remove from an array type"),
89 ReadMismatch { expected, actual } => write!(
90 f,
91 "mismatch between expected ({expected:?}) and actual ({actual:?}) read"
92 ),
93 Decode(err) => err.fmt(f),
94 CellBoundExceeded => write!(f, "exceeded the maximum bound for cells: {CELL_BOUND}"),
95 LogBoundExceeded => write!(
96 f,
97 "exceeded the maximum bound for log instruction: {MAX_LOG_SIZE}"
98 ),
99 StackOverflow => write!(
100 f,
101 "exceeded the maximum bound for Impact stack: {MAX_STACK_HEIGHT}"
102 ),
103 }
104 }
105}
106
107impl<D: DB> Error for OnchainProgramError<D> {}