1#![allow(clippy::explicit_auto_deref)]
3
4use crate::types::builtin_name::BuiltinName;
5use crate::{stdlib::prelude::*, Felt252};
6
7use thiserror::Error;
8
9use crate::{
10 types::{
11 errors::math_errors::MathError,
12 relocatable::{MaybeRelocatable, Relocatable},
13 },
14 vm::errors::{
15 exec_scope_errors::ExecScopeError, hint_errors::HintError, memory_errors::MemoryError,
16 runner_errors::RunnerError, trace_errors::TraceError,
17 },
18};
19
20pub const HINT_ERROR_STR: &str = "Got an exception while executing a hint: ";
21
22#[derive(Debug, Error)]
23pub enum VirtualMachineError {
24 #[error(transparent)]
25 RunnerError(#[from] RunnerError),
26 #[error(transparent)]
27 Memory(#[from] MemoryError),
28 #[error(transparent)]
29 Math(#[from] MathError),
30 #[error(transparent)]
31 TracerError(#[from] TraceError),
32 #[error(transparent)]
33 MainScopeError(#[from] ExecScopeError),
34 #[error(transparent)]
35 Other(anyhow::Error),
36 #[error("Instruction should be an int")]
37 InvalidInstructionEncoding,
38 #[error("Invalid op1_register value: {0}")]
39 InvalidOp1Reg(u128),
40 #[error("In immediate mode, off2 should be 1")]
41 ImmShouldBe1,
42 #[error("op0 must be known in double dereference")]
43 UnknownOp0,
44 #[error("Invalid ap_update value: {0}")]
45 InvalidApUpdate(u128),
46 #[error("Invalid pc_update value: {0}")]
47 InvalidPcUpdate(u128),
48 #[error("Res.UNCONSTRAINED cannot be used with ApUpdate.ADD")]
49 UnconstrainedResAdd,
50 #[error("Res.UNCONSTRAINED cannot be used with PcUpdate.JUMP")]
51 UnconstrainedResJump,
52 #[error("Res.UNCONSTRAINED cannot be used with PcUpdate.JUMP_REL")]
53 UnconstrainedResJumpRel,
54 #[error("Res.UNCONSTRAINED cannot be used with Opcode.ASSERT_EQ")]
55 UnconstrainedResAssertEq,
56 #[error("A relocatable value as Res cannot be used with PcUpdate.JUMP_REL")]
57 JumpRelNotInt,
58 #[error(
59 "Failed to compute Res.MUL: Could not complete computation of non pure values {} * {}", (*.0).0, (*.0).1
60 )]
61 ComputeResRelocatableMul(Box<(MaybeRelocatable, MaybeRelocatable)>),
62 #[error(
63 "Failed to compute operand, attempted to use {0} for an OpcodeExtension that is neither Stone nor QM31Operation"
64 )]
65 InvalidTypedOperationOpcodeExtension(Box<str>),
66 #[error("Couldn't compute operand {}. Unknown value for memory cell {}", (*.0).0, (*.0).1)]
67 FailedToComputeOperands(Box<(String, Relocatable)>),
68 #[error("An ASSERT_EQ instruction failed: {} != {}.", (*.0).0, (*.0).1)]
69 DiffAssertValues(Box<(MaybeRelocatable, MaybeRelocatable)>),
70 #[error("Call failed to write return-pc (inconsistent op0): {} != {}. Did you forget to increment ap?", (*.0).0, (*.0).1)]
71 CantWriteReturnPc(Box<(MaybeRelocatable, MaybeRelocatable)>),
72 #[error("Call failed to write return-fp (inconsistent dst): {} != {}. Did you forget to increment ap?", (*.0).0, (*.0).1)]
73 CantWriteReturnFp(Box<(MaybeRelocatable, MaybeRelocatable)>),
74 #[error("Couldn't get or load dst")]
75 NoDst,
76 #[error("Invalid res value: {0}")]
77 InvalidRes(u128),
78 #[error("Invalid opcode value: {0}")]
79 InvalidOpcode(u128),
80 #[error("Invalid opcode extension value: {0}")]
81 InvalidOpcodeExtension(u128),
82 #[error("Inconsistent auto-deduction for {}, expected {}, got {:?}", (*.0).0, (*.0).1, (*.0).2)]
83 InconsistentAutoDeduction(Box<(BuiltinName, MaybeRelocatable, Option<MaybeRelocatable>)>),
84 #[error("Expected output builtin to be present")]
85 NoOutputBuiltin,
86 #[error("Expected range_check builtin to be present")]
87 NoRangeCheckBuiltin,
88 #[error("Expected ecdsa builtin to be present")]
89 NoSignatureBuiltin,
90 #[error("Expected {0} to be present")]
91 NoModBuiltin(BuiltinName),
92 #[error("Failed to compare {} and {}, cant compare a relocatable to an integer value", (*.0).0, (*.0).1)]
93 DiffTypeComparison(Box<(MaybeRelocatable, MaybeRelocatable)>),
94 #[error("Failed to compare {} and {}, cant compare two relocatable values of different segment indexes", (*.0).0, (*.0).1)]
95 DiffIndexComp(Box<(Relocatable, Relocatable)>),
96 #[error("Expected integer, found: {0:?}")]
97 ExpectedIntAtRange(Box<Option<MaybeRelocatable>>),
98 #[error("Could not convert slice to array")]
99 SliceToArrayError,
100 #[error("Failed to compile hint: {0}")]
101 CompileHintFail(Box<str>),
102 #[error("op1_addr is Op1Addr.IMM, but no immediate was given")]
103 NoImm,
104 #[error("Execution reached the end of the program. Requested remaining steps: {0}.")]
105 EndOfProgram(usize),
106 #[error("Could not reach the end of the program. RunResources has no remaining steps.")]
107 UnfinishedExecution,
108 #[error("Current run is not finished")]
109 RunNotFinished,
110 #[error("{HINT_ERROR_STR}{}", (*.0).1)]
111 Hint(Box<(usize, HintError)>),
112 #[error("Unexpected Failure")]
113 Unexpected,
114 #[error("Out of bounds access to builtin segment")]
115 OutOfBoundsBuiltinSegmentAccess,
116 #[error("Out of bounds access to program segment")]
117 OutOfBoundsProgramSegmentAccess,
118 #[error("Security Error: Invalid Memory Value: temporary address not relocated: {0}")]
119 InvalidMemoryValueTemporaryAddress(Box<Relocatable>),
120 #[error("accessed_addresses is None.")]
121 MissingAccessedAddresses,
122 #[error("Failed to write the output builtin content")]
123 FailedToWriteOutput,
124 #[error("Failed to find index {0} in the vm's relocation table")]
125 RelocationNotFound(usize),
126 #[error("{} batch size is not {}", (*.0).0, (*.0).1)]
127 ModBuiltinBatchSize(Box<(BuiltinName, usize)>),
128 #[error("Initial FP should have been initialized")]
129 MissingInitialFp,
130 #[error("Return FP address should be in memory: {0}")]
131 MissingReturnFp(Box<Relocatable>),
132 #[error("Return FP { } should equal expected final FP { }", (*.0).0, (*.0).1)]
133 MismatchReturnFP(Box<(Relocatable, Relocatable)>),
134 #[error("Return FP { } offset should equal expected final FP { } offset", (*.0).0, (*.0).1)]
135 MismatchReturnFPOffset(Box<(Relocatable, Relocatable)>),
136 #[error("Return FP felt { } should equal expected final FP { } offset", (*.0).0, (*.0).1)]
137 MismatchReturnFPFelt(Box<(Felt252, Relocatable)>),
138 #[error("Blake2s opcode invalid operand: op{0} does not point to {1} u32 numbers.")]
139 Blake2sInvalidOperand(u8, u8),
140 #[error("Blake2s opcode invalid flags {0}")]
141 InvalidBlake2sFlags(u128),
142 #[error("QM31 add mul opcode invalid flags {0}")]
143 InvalidQM31AddMulFlags(u128),
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_vm_error_size() {
153 let size = crate::stdlib::mem::size_of::<VirtualMachineError>();
154 assert!(size <= 32, "{size}")
155 }
156}