miden_processor/
errors.rs

1use alloc::{boxed::Box, string::String};
2use core::error::Error;
3
4use miden_air::RowIndex;
5use vm_core::{
6    mast::{DecoratorId, MastNodeId},
7    stack::MIN_STACK_DEPTH,
8    utils::to_hex,
9};
10use winter_prover::{ProverError, math::FieldElement};
11
12use super::{
13    Digest, Felt, QuadFelt, Word,
14    crypto::MerkleError,
15    system::{FMP_MAX, FMP_MIN},
16};
17use crate::ContextId;
18
19// EXECUTION ERROR
20// ================================================================================================
21
22#[derive(Debug, thiserror::Error)]
23pub enum ExecutionError {
24    #[error("value for key {} not present in the advice map", to_hex(Felt::elements_as_bytes(.0)))]
25    AdviceMapKeyNotFound(Word),
26    #[error("value for key {} already present in the advice map", to_hex(Felt::elements_as_bytes(.0)))]
27    AdviceMapKeyAlreadyPresent(Word),
28    #[error("advice stack read failed at step {0}")]
29    AdviceStackReadFailed(RowIndex),
30    #[error("illegal use of instruction {0} while inside a syscall")]
31    CallInSyscall(&'static str),
32    #[error("instruction `caller` used outside of kernel context")]
33    CallerNotInSyscall,
34    #[error("external node with mast root {0} resolved to an external node")]
35    CircularExternalNode(Digest),
36    #[error("exceeded the allowed number of max cycles {0}")]
37    CycleLimitExceeded(u32),
38    #[error("decorator id {decorator_id} does not exist in MAST forest")]
39    DecoratorNotFoundInForest { decorator_id: DecoratorId },
40    #[error("division by zero at clock cycle {0}")]
41    DivideByZero(RowIndex),
42    #[error("failed to execute the dynamic code block provided by the stack with root {hex}; the block could not be found",
43      hex = to_hex(.0.as_bytes())
44    )]
45    DynamicNodeNotFound(Digest),
46    #[error("error during processing of event in on_event handler")]
47    EventError(#[source] Box<dyn Error + Send + Sync + 'static>),
48    #[error("failed to execute Ext2Intt operation: {0}")]
49    Ext2InttError(Ext2InttError),
50    #[error("assertion failed at clock cycle {clk} with error code {err_code}{}",
51      match err_msg {
52        Some(msg) => format!(": {msg}"),
53        None => "".into()
54      }
55    )]
56    FailedAssertion {
57        clk: RowIndex,
58        err_code: u32,
59        err_msg: Option<String>,
60    },
61    #[error(
62        "memory address {addr} in context {ctx} was read and written, or written twice, in the same clock cycle {clk}"
63    )]
64    IllegalMemoryAccess { ctx: ContextId, addr: u32, clk: Felt },
65    #[error(
66        "Updating FMP register from {0} to {1} failed because {1} is outside of {FMP_MIN}..{FMP_MAX}"
67    )]
68    InvalidFmpValue(Felt, Felt),
69    #[error("FRI domain segment value cannot exceed 3, but was {0}")]
70    InvalidFriDomainSegment(u64),
71    #[error("degree-respecting projection is inconsistent: expected {0} but was {1}")]
72    InvalidFriLayerFolding(QuadFelt, QuadFelt),
73    #[error(
74        "memory range start address cannot exceed end address, but was ({start_addr}, {end_addr})"
75    )]
76    InvalidMemoryRange { start_addr: u64, end_addr: u64 },
77    #[error("when returning from a call, stack depth must be {MIN_STACK_DEPTH}, but was {0}")]
78    InvalidStackDepthOnReturn(usize),
79    #[error(
80        "provided merkle tree {depth} is out of bounds and cannot be represented as an unsigned 8-bit integer"
81    )]
82    InvalidMerkleTreeDepth { depth: Felt },
83    #[error("provided node index {value} is out of bounds for a merkle tree node at depth {depth}")]
84    InvalidMerkleTreeNodeIndex { depth: Felt, value: Felt },
85    #[error("attempted to calculate integer logarithm with zero argument at clock cycle {0}")]
86    LogArgumentZero(RowIndex),
87    #[error("malformed signature key: {0}")]
88    MalformedSignatureKey(&'static str),
89    #[error(
90        "MAST forest in host indexed by procedure root {root_digest} doesn't contain that root"
91    )]
92    MalformedMastForestInHost { root_digest: Digest },
93    #[error("node id {node_id} does not exist in MAST forest")]
94    MastNodeNotFoundInForest { node_id: MastNodeId },
95    #[error("no MAST forest contains the procedure with root digest {root_digest}")]
96    NoMastForestWithProcedure { root_digest: Digest },
97    #[error("memory address cannot exceed 2^32 but was {0}")]
98    MemoryAddressOutOfBounds(u64),
99    #[error(
100        "word memory access at address {addr} in context {ctx} is unaligned at clock cycle {clk}"
101    )]
102    MemoryUnalignedWordAccess { addr: u32, ctx: ContextId, clk: Felt },
103    // Note: we need this version as well because to handle advice provider calls, which don't
104    // have access to the clock.
105    #[error("word access at memory address {addr} in context {ctx} is unaligned")]
106    MemoryUnalignedWordAccessNoClk { addr: u32, ctx: ContextId },
107    #[error("merkle path verification failed for value {value} at index {index} in the Merkle tree with root {root} (error code: {err_code})", 
108      value = to_hex(Felt::elements_as_bytes(value)),
109      root = to_hex(root.as_bytes()),
110    )]
111    MerklePathVerificationFailed {
112        value: Word,
113        index: Felt,
114        root: Digest,
115        err_code: u32,
116    },
117    #[error("advice provider Merkle store backend lookup failed")]
118    MerkleStoreLookupFailed(#[source] MerkleError),
119    #[error("advice provider Merkle store backend merge failed")]
120    MerkleStoreMergeFailed(#[source] MerkleError),
121    #[error("advice provider Merkle store backend update failed")]
122    MerkleStoreUpdateFailed(#[source] MerkleError),
123    #[error("an operation expected a binary value, but received {0}")]
124    NotBinaryValue(Felt),
125    #[error("an operation expected a u32 value, but received {0} (error code: {1})")]
126    NotU32Value(Felt, Felt),
127    #[error("stack should have at most {MIN_STACK_DEPTH} elements at the end of program execution, but had {} elements", MIN_STACK_DEPTH + .0)]
128    OutputStackOverflow(usize),
129    #[error("a program has already been executed in this process")]
130    ProgramAlreadyExecuted,
131    #[error("proof generation failed")]
132    ProverError(#[source] ProverError),
133    #[error("smt node {node_hex} not found", node_hex = to_hex(Felt::elements_as_bytes(.0)))]
134    SmtNodeNotFound(Word),
135    #[error("expected pre-image length of node {node_hex} to be a multiple of 8 but was {preimage_len}",
136      node_hex = to_hex(Felt::elements_as_bytes(.0)),
137      preimage_len = .1
138    )]
139    SmtNodePreImageNotValid(Word, usize),
140    #[error("syscall failed: procedure with root {hex} was not found in the kernel",
141      hex = to_hex(.0.as_bytes())
142    )]
143    SyscallTargetNotInKernel(Digest),
144}
145
146impl From<Ext2InttError> for ExecutionError {
147    fn from(value: Ext2InttError) -> Self {
148        Self::Ext2InttError(value)
149    }
150}
151
152// EXT2INTT ERROR
153// ================================================================================================
154
155#[derive(Debug, thiserror::Error)]
156pub enum Ext2InttError {
157    #[error("input domain size must be a power of two, but was {0}")]
158    DomainSizeNotPowerOf2(u64),
159    #[error("input domain size ({0} elements) is too small")]
160    DomainSizeTooSmall(u64),
161    #[error("address of the last input must be smaller than 2^32, but was {0}")]
162    InputEndAddressTooBig(u64),
163    #[error("input size must be smaller than 2^32, but was {0}")]
164    InputSizeTooBig(u64),
165    #[error("address of the first input must be smaller than 2^32, but was {0}")]
166    InputStartAddressTooBig(u64),
167    #[error("address of the first input is not word aligned: {0}")]
168    InputStartNotWordAligned(u64),
169    #[error("output size ({0}) cannot be greater than the input size ({1})")]
170    OutputSizeTooBig(usize, usize),
171    #[error("output size must be greater than 0")]
172    OutputSizeIsZero,
173    #[error("uninitialized memory at address {0}")]
174    UninitializedMemoryAddress(u32),
175}
176
177#[cfg(test)]
178mod error_assertions {
179    use super::*;
180
181    /// Asserts at compile time that the passed error has Send + Sync + 'static bounds.
182    fn _assert_error_is_send_sync_static<E: core::error::Error + Send + Sync + 'static>(_: E) {}
183
184    fn _assert_execution_error_bounds(err: ExecutionError) {
185        _assert_error_is_send_sync_static(err);
186    }
187}