Skip to main content

midnight_onchain_vm/
error.rs

1// This file is part of midnight-ledger.
2// Copyright (C) 2025 Midnight Foundation
3// SPDX-License-Identifier: Apache-2.0
4// Licensed under the Apache License, Version 2.0 (the "License");
5// You may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14use 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    /// Type error with description.
32    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> {}