1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
//! The types of errors that might occur throughout state read execution.
pub use crate::constraint::error::{StackError, StackResult};
#[doc(inline)]
use crate::{
asm::{self, Word},
constraint, Gas,
};
use thiserror::Error;
/// Shorthand for a `Result` where the error type is a `StateReadError`.
pub type StateReadResult<T, E> = Result<T, StateReadError<E>>;
/// Shorthand for a `Result` where the error type is an `OpError`.
pub type OpResult<T, E> = Result<T, OpError<E>>;
/// Shorthand for a `Result` where the error type is an `OpSyncError`.
pub type OpSyncResult<T> = Result<T, OpSyncError>;
/// Shorthand for a `Result` where the error type is an `OpAsyncError`.
pub type OpAsyncResult<T, E> = Result<T, OpAsyncError<E>>;
/// Shorthand for a `Result` where the error type is a `StateSlotsError`.
pub type StateSlotsResult<T> = Result<T, StateSlotsError>;
/// State read execution failure.
#[derive(Debug, Error)]
pub enum StateReadError<E> {
/// The operation at the specified index failed.
#[error("operation at index {0} failed: {1}")]
Op(usize, OpError<E>),
/// The program counter is out of range.
#[error("program counter {0} out of range (note: programs must end with `Halt`)")]
PcOutOfRange(usize),
}
/// An individual operation failed during state read execution.
#[derive(Debug, Error)]
pub enum OpError<E> {
/// A synchronous operation failed.
#[error("synchronous operation failed: {0}")]
Sync(#[from] OpSyncError),
/// An asynchronous operation failed.
#[error("asynchronous operation failed: {0}")]
Async(#[from] OpAsyncError<E>),
/// An error occurred while parsing an operation from bytes.
#[error("bytecode error: {0}")]
FromBytes(#[from] asm::FromBytesError),
/// The total gas limit was exceeded.
#[error("{0}")]
OutOfGas(#[from] OutOfGasError),
}
/// The gas cost of performing an operation would exceed the gas limit.
#[derive(Debug, Error)]
#[error(
"operation cost would exceed gas limit\n \
spent: {spent} gas\n \
op cost: {op_gas} gas\n \
limit: {limit} gas"
)]
pub struct OutOfGasError {
/// Total spent prior to the operation that would exceed the limit.
pub spent: Gas,
/// The gas required for the operation that failed.
pub op_gas: Gas,
/// The total gas limit that would be exceeded.
pub limit: Gas,
}
/// A synchronous operation failed.
#[derive(Debug, Error)]
pub enum OpSyncError {
/// An error occurred during a `Constraint` operation.
#[error("constraint operation error: {0}")]
Constraint(#[from] constraint::error::OpError),
/// An error occurred during a `TotalControlFlow` operation.
#[error("control flow operation error: {0}")]
TotalControlFlow(#[from] ControlFlowError),
/// An error occurred during a `StateSlots` operation.
#[error("state slots operation error: {0}")]
StateSlots(#[from] StateSlotsError),
/// The next program counter would overflow.
#[error("the next program counter would overflow")]
PcOverflow,
}
/// A synchronous operation failed.
#[derive(Debug, Error)]
pub enum OpAsyncError<E> {
/// An error occurred during a `StateRead` operation.
#[error("state read operation error: {0}")]
StateRead(E),
/// A `StateSlots` access related error occurred.
#[error("state slots error: {0}")]
Memory(#[from] StateSlotsError),
/// An error occurred during a `Stack` operation.
#[error("stack operation error: {0}")]
Stack(#[from] StackError),
/// The next program counter would overflow.
#[error("the next program counter would overflow")]
PcOverflow,
}
/// Errors occuring during `TotalControlFlow` operation.
#[derive(Debug, Error)]
pub enum ControlFlowError {
/// A `JumpIf` operation encountered an invalid condition.
///
/// Condition values must be 0 (false) or 1 (true).
#[error("invalid condition value {0}, expected 0 (false) or 1 (true)")]
InvalidJumpIfCondition(Word),
}
/// Errors occuring during `StateSlots` operation.
#[derive(Debug, Error)]
pub enum StateSlotsError {
/// Attempted to access a state slot index that was out of bounds.
#[error("index out of bounds")]
IndexOutOfBounds,
/// An operation would have caused state slots to overflow.
#[error("operation would cause state slots to overflow")]
Overflow,
}
impl<E> From<core::convert::Infallible> for OpError<E> {
fn from(err: core::convert::Infallible) -> Self {
match err {}
}
}
impl From<StackError> for OpSyncError {
fn from(err: StackError) -> Self {
OpSyncError::Constraint(err.into())
}
}