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