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