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#[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 #[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#[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 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}