cairo_vm/vm/errors/
hint_errors.rs

1// The `(*.0).0` syntax of thiserror falsely triggers this clippy warning
2#![allow(clippy::explicit_auto_deref)]
3
4use crate::stdlib::prelude::*;
5
6use thiserror_no_std::Error;
7
8use crate::Felt252;
9use num_bigint::{BigInt, BigUint};
10
11use crate::types::{
12    errors::math_errors::MathError,
13    relocatable::{MaybeRelocatable, Relocatable},
14};
15
16use super::{
17    exec_scope_errors::ExecScopeError, memory_errors::MemoryError, vm_errors::VirtualMachineError,
18};
19
20// For more info on #[error] syntax, see https://docs.rs/thiserror/latest/thiserror/#details
21#[derive(Debug, Error)]
22pub enum HintError {
23    #[error(transparent)]
24    FromScopeError(#[from] ExecScopeError),
25    #[error(transparent)]
26    Internal(#[from] VirtualMachineError),
27    #[error(transparent)]
28    Memory(#[from] MemoryError),
29    #[error(transparent)]
30    Math(#[from] MathError),
31    #[error("HintProcessor failed retrieve the compiled data necessary for hint execution")]
32    WrongHintData,
33    #[error("Unknown identifier {0}")]
34    UnknownIdentifier(Box<str>),
35    #[error("Expected ids.{} to be an Integer value", (*.0))]
36    IdentifierNotInteger(Box<str>),
37    #[error("Expected ids.{} to be a Relocatable value", (*.0))]
38    IdentifierNotRelocatable(Box<str>),
39    #[error("ids.{} has no member {} or it is of incorrect type", (*.0).0, (*.0).1)]
40    IdentifierHasNoMember(Box<(String, String)>),
41    #[error("Unknown identifier")]
42    UnknownIdentifierInternal,
43    #[error("Wrong identifier type")]
44    WrongIdentifierTypeInternal,
45    #[error("Hint Error: {0}")]
46    CustomHint(Box<str>),
47    #[error("Missing constant: {0}")]
48    MissingConstant(Box<&'static str>),
49    #[error("Fail to get constants for hint execution")]
50    FailedToGetConstant,
51    #[error("Arc too big, {} must be <= {} and {} <= {}", (*.0).0, (*.0).1, (*.0).2, (*.0).3)]
52    ArcTooBig(Box<(Felt252, Felt252, Felt252, Felt252)>),
53    #[error("Excluded is supposed to be 2, got {0}")]
54    ExcludedNot2(Box<Felt252>),
55    #[error("Value: {0} is outside of the range [0, 2**250)")]
56    ValueOutside250BitRange(Box<Felt252>),
57    #[error("Failed to get scope variables")]
58    ScopeError,
59    #[error("Variable {0} not present in current execution scope")]
60    VariableNotInScopeError(Box<str>),
61    #[error("DictManagerError: Tried to create tracker for a dictionary on segment: {0} when there is already a tracker for a dictionary on this segment")]
62    CantCreateDictionaryOnTakenSegment(isize),
63    #[error("Dict Error: No dict tracker found for segment {0}")]
64    NoDictTracker(isize),
65    #[error("Dict Error: No value found for key: {0}")]
66    NoValueForKey(Box<MaybeRelocatable>),
67    #[error("find_element(): No value found for key: {0}")]
68    NoValueForKeyFindElement(Box<Felt252>),
69    #[error("Assertion failed, a = {} % PRIME is not less than b = {} % PRIME", (*.0).0, (*.0).1)]
70    AssertLtFelt252(Box<(Felt252, Felt252)>),
71    #[error("find_element() can only be used with n_elms <= {}.\nGot: n_elms = {}", (*.0).0, (*.0).1)]
72    FindElemMaxSize(Box<(Felt252, Felt252)>),
73    #[error(
74        "Invalid index found in find_element_index. Index: {}.\nExpected key: {}, found_key {}", (*.0).0, (*.0).1, (*.0).2
75    )]
76    InvalidIndex(Box<(Felt252, Felt252, Felt252)>),
77    #[error("Found Key is None")]
78    KeyNotFound,
79    #[error("AP tracking data is None; could not apply correction to address")]
80    NoneApTrackingData,
81    #[error("Tracking groups should be the same, got {} and {}", (*.0).0, (*.0).0)]
82    InvalidTrackingGroup(Box<(usize, usize)>),
83    #[error("Expected relocatable for ap, got {0}")]
84    InvalidApValue(Box<MaybeRelocatable>),
85    #[error("Dict Error: Tried to create a dict without an initial dict")]
86    NoInitialDict,
87    #[error("squash_dict_inner fail: couldnt find key {0} in accesses_indices")]
88    NoKeyInAccessIndices(Box<Felt252>),
89    #[error("squash_dict_inner fail: local accessed_indices is empty")]
90    EmptyAccessIndices,
91    #[error("squash_dict_inner fail: local current_accessed_indices is empty")]
92    EmptyCurrentAccessIndices,
93    #[error("squash_dict_inner fail: local current_accessed_indices not empty, loop ended with remaining unaccounted elements")]
94    CurrentAccessIndicesNotEmpty,
95    #[error("Dict Error: Got the wrong value for dict_update, expected value: {}, got: {} for key: {}", (*.0).0, (*.0).1, (*.0).2)]
96    WrongPrevValue(Box<(MaybeRelocatable, MaybeRelocatable, MaybeRelocatable)>),
97    #[error("squash_dict_inner fail: Number of used accesses:{} doesnt match the lengh: {} of the access_indices at key: {}", (*.0).0, (*.0).1, (*.0).2)]
98    NumUsedAccessesAssertFail(Box<(Felt252, usize, Felt252)>),
99    #[error("squash_dict_inner fail: local keys is not empty")]
100    KeysNotEmpty,
101    #[error("squash_dict_inner fail: No keys left but remaining_accesses > 0")]
102    EmptyKeys,
103    #[error("squash_dict fail: Accesses array size must be divisible by DictAccess.SIZE")]
104    PtrDiffNotDivisibleByDictAccessSize,
105    #[error("squash_dict() can only be used with n_accesses<={}. ' \nGot: n_accesses={}", (*.0).0, (*.0).1)]
106    SquashDictMaxSizeExceeded(Box<(Felt252, Felt252)>),
107    #[error("squash_dict fail: n_accesses: {0} is too big to be converted into an iterator")]
108    NAccessesTooBig(Box<Felt252>),
109    #[error("Couldn't convert BigInt to usize")]
110    BigintToUsizeFail,
111    #[error("usort() can only be used with input_len<={}. Got: input_len={}.", (*.0).0, (*.0).1)]
112    UsortOutOfRange(Box<(u64, Felt252)>),
113    #[error("unexpected usort fail: positions_dict or key value pair not found")]
114    UnexpectedPositionsDictFail,
115    #[error("unexpected verify multiplicity fail: positions not found")]
116    PositionsNotFound,
117    #[error("unexpected verify multiplicity fail: positions length != 0")]
118    PositionsLengthNotZero,
119    #[error("unexpected verify multiplicity fail: couldn't pop positions")]
120    CouldntPopPositions,
121    #[error("unexpected verify multiplicity fail: last_pos not found")]
122    LastPosNotFound,
123    #[error("Set's starting point {} is bigger it's ending point {}", (*.0).0, (*.0).1)]
124    InvalidSetRange(Box<(Relocatable, Relocatable)>),
125    #[error("Failed to construct a fixed size array of size: {0}")]
126    FixedSizeArrayFail(usize),
127    #[error("{0}")]
128    AssertionFailed(Box<str>),
129    #[error("Wrong dict pointer supplied. Got {}, expected {}.", (*.0).0, (*.0).1)]
130    MismatchedDictPtr(Box<(Relocatable, Relocatable)>),
131    #[error("Integer must be postive or zero, got: {0}")]
132    SecpSplitNegative(Box<BigInt>),
133    #[error("Integer: {0} out of range")]
134    SecpSplitOutOfRange(Box<BigUint>),
135    #[error("verify_zero: Invalid input {0}")]
136    SecpVerifyZero(Box<BigInt>),
137    #[error("unsafe_keccak() can only be used with length<={}. Got: length={}", (*.0).0, (*.0).1)]
138    KeccakMaxSize(Box<(Felt252, Felt252)>),
139    #[error("Invalid word size: {0}")]
140    InvalidWordSize(Box<Felt252>),
141    #[error("Invalid input length, Got: length={0}")]
142    InvalidKeccakInputLength(Box<Felt252>),
143    #[error("assert_not_equal failed: {} =  {}", (*.0).0, (*.0).1)]
144    AssertNotEqualFail(Box<(MaybeRelocatable, MaybeRelocatable)>),
145    #[error("split_int(): value is out of range")]
146    SplitIntNotZero,
147    #[error("split_int(): Limb {0} is out of range.")]
148    SplitIntLimbOutOfRange(Box<Felt252>),
149    #[error("Expected size to be in the range from [0, 100), got: {0}")]
150    InvalidKeccakStateSizeFelt252s(Box<Felt252>),
151    #[error("Expected size to be in range from [0, 10), got: {0}")]
152    InvalidBlockSize(Box<Felt252>),
153    #[error("Couldn't convert BigInt to u32")]
154    BigintToU32Fail,
155    #[error("BigInt to BigUint failed, BigInt is negative")]
156    BigIntToBigUintFail,
157    #[error("BigUint to BigInt failed")]
158    BigUintToBigIntFail,
159    #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")]
160    ValueOutOfRange(Box<Felt252>),
161    #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")]
162    AssertNNValueOutOfRange(Box<Felt252>),
163    #[error("Assertion failed, {} % {} is equal to 0", (*.0).0, (*.0).1)]
164    AssertNotZero(Box<(Felt252, String)>),
165    #[error("Div out of range: 0 < {} <= {}", (*.0).0, (*.0).1)]
166    OutOfValidRange(Box<(Felt252, Felt252)>),
167    #[error("Value: {0} is outside valid range")]
168    ValueOutsideValidRange(Box<Felt252>),
169    #[error("Assertion failed, {}, is not less or equal to {}", (*.0).0, (*.0).1)]
170    NonLeFelt252(Box<(Felt252, Felt252)>),
171    #[error("Unknown Hint: {0}")]
172    UnknownHint(Box<str>),
173    #[error("Signature hint must point to the signature builtin segment, not {0}.")]
174    AddSignatureWrongEcdsaPtr(Box<Relocatable>),
175    #[error("Signature hint must point to the public key cell, not {0}.")]
176    AddSignatureNotAPublicKey(Box<Relocatable>),
177    #[error("random_ec_point: Could not find a point on the curve.")]
178    RandomEcPointNotOnCurve,
179    #[error("Invalid value for len. Got: {0}.")]
180    InvalidLenValue(Box<Felt252>),
181    #[error("recover_y: {0} does not represent the x coordinate of a point on the curve.")]
182    RecoverYPointNotOnCurve(Box<Felt252>),
183    #[error("Invalid value for {}. Got: {}. Expected: {}", (*.0).0, (*.0).1, (*.0).2)]
184    InvalidValue(Box<(&'static str, Felt252, Felt252)>),
185    #[error("Attempt to subtract with overflow: ids.m - 1")]
186    NPairBitsTooLowM,
187    #[error("{0}")]
188    SyscallError(Box<str>),
189    #[error("excess_balance_func: Failed to fetch {0} dictionary. It is either missing or has unexpected data types")]
190    ExcessBalanceFailedToFecthDict(Box<str>),
191    #[error("excess_balance_func: Key not found in {0} dictionary")]
192    ExcessBalanceKeyError(Box<str>),
193    #[error("excess_balance_func: Failed to calculate {0}")]
194    ExcessBalanceCalculationFailed(Box<str>),
195    #[error("generate_nibbles fail: tried to read from an empty list of nibbles")]
196    EmptyNibbles,
197    #[error("circuit evalution: {0}")]
198    CircuitEvaluationFailed(Box<str>),
199}
200
201#[cfg(test)]
202mod tests {
203    use super::*;
204    #[test]
205    fn test_multiple_members_variant_message_format() {
206        let a = Felt252::from(42);
207        let b = Felt252::from(53);
208        let string = "test";
209
210        let error_msg = HintError::InvalidValue(Box::new((string, a, b))).to_string();
211
212        let expected_msg = format!("Invalid value for {string}. Got: {a}. Expected: {b}");
213        assert_eq!(error_msg, expected_msg)
214    }
215
216    #[test]
217    fn test_single_felt_variant_message_format() {
218        let x = Felt252::from(15131);
219
220        let error_msg = HintError::InvalidKeccakStateSizeFelt252s(Box::new(x)).to_string();
221
222        let expected_msg = format!("Expected size to be in the range from [0, 100), got: {x}");
223        assert_eq!(error_msg, expected_msg)
224    }
225
226    #[test]
227    fn test_hint_error_size() {
228        let size = crate::stdlib::mem::size_of::<HintError>();
229        assert!(size <= 32, "{size}")
230    }
231}