1use crate::{
2 hint_processor::builtin_hint_processor::hint_utils::get_constant_from_var_name,
3 math_utils::signed_felt,
4 stdlib::{boxed::Box, collections::HashMap, prelude::*},
5 types::errors::math_errors::MathError,
6};
7use lazy_static::lazy_static;
8use num_traits::{Signed, Zero};
9
10use crate::utils::CAIRO_PRIME;
11
12use crate::Felt252;
13use crate::{
14 any_box,
15 hint_processor::{
16 builtin_hint_processor::hint_utils::{
17 get_integer_from_var_name, get_ptr_from_var_name, insert_value_from_var_name,
18 insert_value_into_ap,
19 },
20 hint_processor_definition::HintReference,
21 },
22 math_utils::{isqrt, pow2_const},
23 serde::deserialize_program::ApTracking,
24 types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable},
25 vm::{
26 errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
27 vm_core::VirtualMachine,
28 },
29};
30use num_bigint::{BigUint, Sign};
31use num_integer::Integer;
32use num_traits::One;
33
34use super::{
35 hint_utils::{get_maybe_relocatable_from_var_name, get_relocatable_from_var_name},
36 uint256_utils::Uint256,
37};
38
39const ADDR_BOUND: &str = "starkware.starknet.common.storage.ADDR_BOUND";
40
41pub fn is_nn(
43 vm: &mut VirtualMachine,
44 ids_data: &HashMap<String, HintReference>,
45 ap_tracking: &ApTracking,
46) -> Result<(), HintError> {
47 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
48 let range_check_bound = vm.get_range_check_builtin()?.bound();
49 insert_value_into_ap(vm, Felt252::from(a.as_ref() >= range_check_bound))
51}
52
53pub fn is_nn_out_of_range(
55 vm: &mut VirtualMachine,
56 ids_data: &HashMap<String, HintReference>,
57 ap_tracking: &ApTracking,
58) -> Result<(), HintError> {
59 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
60 let a = a.as_ref();
61 let range_check_bound = vm.get_range_check_builtin()?.bound();
62 insert_value_into_ap(vm, Felt252::from(-(a + 1) >= *range_check_bound))
64}
65pub fn assert_le_felt(
89 vm: &mut VirtualMachine,
90 exec_scopes: &mut ExecutionScopes,
91 ids_data: &HashMap<String, HintReference>,
92 ap_tracking: &ApTracking,
93 constants: &HashMap<String, Felt252>,
94) -> Result<(), HintError> {
95 const PRIME_OVER_3_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH";
96 const PRIME_OVER_2_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH";
97
98 let prime_over_3_high = constants
99 .get(PRIME_OVER_3_HIGH)
100 .ok_or_else(|| HintError::MissingConstant(Box::new(PRIME_OVER_3_HIGH)))?;
101 let prime_over_2_high = constants
102 .get(PRIME_OVER_2_HIGH)
103 .ok_or_else(|| HintError::MissingConstant(Box::new(PRIME_OVER_2_HIGH)))?;
104 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?.to_biguint();
105 let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?.to_biguint();
106 let range_check_ptr = get_ptr_from_var_name("range_check_ptr", vm, ids_data, ap_tracking)?;
107
108 let prime_div2 = prime_div_constant(2)?;
110 let prime_div3 = prime_div_constant(3)?;
111
112 if a > b {
113 return Err(HintError::NonLeFelt252(Box::new((
114 Felt252::from(&a),
115 Felt252::from(&b),
116 ))));
117 }
118
119 let arc1 = &b - &a;
120 let arc2 = &*CAIRO_PRIME - 1_u32 - &b;
121 let mut lengths_and_indices = [(&a, 0_i32), (&arc1, 1_i32), (&arc2, 2_i32)];
122 lengths_and_indices.sort();
123 if lengths_and_indices[0].0 > &prime_div3 || lengths_and_indices[1].0 > &prime_div2 {
125 return Err(HintError::ArcTooBig(Box::new((
126 Felt252::from(&lengths_and_indices[0].0.clone()),
127 Felt252::from(&prime_div2),
128 Felt252::from(&lengths_and_indices[1].0.clone()),
129 Felt252::from(&prime_div3),
130 ))));
131 }
132
133 let excluded = lengths_and_indices[2].1;
134 exec_scopes.assign_or_update_variable("excluded", any_box!(Felt252::from(excluded)));
135
136 let (q_0, r_0) = (lengths_and_indices[0].0).div_mod_floor(&prime_over_3_high.to_biguint());
137 let (q_1, r_1) = (lengths_and_indices[1].0).div_mod_floor(&prime_over_2_high.to_biguint());
138
139 vm.insert_value(range_check_ptr, Felt252::from(&r_0))?;
140 vm.insert_value((range_check_ptr + 1_i32)?, Felt252::from(&q_0))?;
141 vm.insert_value((range_check_ptr + 2_i32)?, Felt252::from(&r_1))?;
142 vm.insert_value((range_check_ptr + 3_i32)?, Felt252::from(&q_1))?;
143 Ok(())
144}
145
146pub fn assert_le_felt_v_0_6(
147 vm: &mut VirtualMachine,
148 ids_data: &HashMap<String, HintReference>,
149 ap_tracking: &ApTracking,
150) -> Result<(), HintError> {
151 let a = &get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
152 let b = &get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
153
154 if a > b {
155 return Err(HintError::NonLeFelt252(Box::new((*a, *b))));
156 }
157 Ok(())
158}
159
160pub fn assert_le_felt_v_0_8(
161 vm: &mut VirtualMachine,
162 ids_data: &HashMap<String, HintReference>,
163 ap_tracking: &ApTracking,
164) -> Result<(), HintError> {
165 let a = &get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
166 let b = &get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
167
168 if a > b {
169 return Err(HintError::NonLeFelt252(Box::new((*a, *b))));
170 }
171 let bound = vm.get_range_check_builtin()?.bound();
172 let small_inputs = Felt252::from((a < bound && b - a < *bound) as u8);
173 insert_value_from_var_name("small_inputs", small_inputs, vm, ids_data, ap_tracking)
174}
175
176pub fn assert_le_felt_excluded_2(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
177 let excluded: Felt252 = exec_scopes.get("excluded")?;
178
179 if excluded != Felt252::from(2_i32) {
180 Err(HintError::ExcludedNot2(Box::new(excluded)))
181 } else {
182 Ok(())
183 }
184}
185
186pub fn assert_le_felt_excluded_1(
187 vm: &mut VirtualMachine,
188 exec_scopes: &mut ExecutionScopes,
189) -> Result<(), HintError> {
190 let excluded: Felt252 = exec_scopes.get("excluded")?;
191
192 if excluded != Felt252::ONE {
193 insert_value_into_ap(vm, Felt252::ONE)
194 } else {
195 insert_value_into_ap(vm, Felt252::ZERO)
196 }
197}
198
199pub fn assert_le_felt_excluded_0(
200 vm: &mut VirtualMachine,
201 exec_scopes: &mut ExecutionScopes,
202) -> Result<(), HintError> {
203 let excluded: Felt252 = exec_scopes.get("excluded")?;
204
205 if !excluded.is_zero() {
206 insert_value_into_ap(vm, Felt252::ONE)
207 } else {
208 insert_value_into_ap(vm, Felt252::ZERO)
209 }
210}
211
212pub fn is_le_felt(
215 vm: &mut VirtualMachine,
216 ids_data: &HashMap<String, HintReference>,
217 ap_tracking: &ApTracking,
218) -> Result<(), HintError> {
219 let a_mod = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
220 let b_mod = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
221 let value = if a_mod > b_mod {
222 Felt252::ONE
223 } else {
224 Felt252::ZERO
225 };
226 insert_value_into_ap(vm, value)
227}
228
229pub fn assert_not_equal(
238 vm: &mut VirtualMachine,
239 ids_data: &HashMap<String, HintReference>,
240 ap_tracking: &ApTracking,
241) -> Result<(), HintError> {
242 let maybe_rel_a = get_maybe_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?;
243 let maybe_rel_b = get_maybe_relocatable_from_var_name("b", vm, ids_data, ap_tracking)?;
244 match (maybe_rel_a, maybe_rel_b) {
245 (MaybeRelocatable::Int(a), MaybeRelocatable::Int(b)) => {
246 if (a - b).is_zero() {
247 return Err(HintError::AssertNotEqualFail(Box::new((
248 MaybeRelocatable::Int(a),
249 MaybeRelocatable::Int(b),
250 ))));
251 };
252 Ok(())
253 }
254 (MaybeRelocatable::RelocatableValue(a), MaybeRelocatable::RelocatableValue(b)) => {
255 if a.segment_index != b.segment_index {
256 Err(VirtualMachineError::DiffIndexComp(Box::new((a, b))))?;
257 };
258 if a.offset == b.offset {
259 return Err(HintError::AssertNotEqualFail(Box::new((
260 MaybeRelocatable::RelocatableValue(a),
261 MaybeRelocatable::RelocatableValue(b),
262 ))));
263 };
264 Ok(())
265 }
266 (a, b) => Err(VirtualMachineError::DiffTypeComparison(Box::new((a, b))))?,
267 }
268}
269
270pub fn assert_nn(
277 vm: &mut VirtualMachine,
278 ids_data: &HashMap<String, HintReference>,
279 ap_tracking: &ApTracking,
280) -> Result<(), HintError> {
281 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
282 let range_check_builtin = vm.get_range_check_builtin()?;
283 if a.as_ref() >= range_check_builtin.bound() {
286 Err(HintError::AssertNNValueOutOfRange(Box::new(a)))
287 } else {
288 Ok(())
289 }
290}
291
292pub fn assert_not_zero(
299 vm: &mut VirtualMachine,
300 ids_data: &HashMap<String, HintReference>,
301 ap_tracking: &ApTracking,
302) -> Result<(), HintError> {
303 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
304 if value.is_zero() {
305 return Err(HintError::AssertNotZero(Box::new((
306 value,
307 crate::utils::PRIME_STR.to_string(),
308 ))));
309 };
310 Ok(())
311}
312
313pub fn split_int_assert_range(
315 vm: &mut VirtualMachine,
316 ids_data: &HashMap<String, HintReference>,
317 ap_tracking: &ApTracking,
318) -> Result<(), HintError> {
319 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
320 if !value.is_zero() {
322 return Err(HintError::SplitIntNotZero);
323 }
324 Ok(())
325}
326
327pub fn split_int(
330 vm: &mut VirtualMachine,
331 ids_data: &HashMap<String, HintReference>,
332 ap_tracking: &ApTracking,
333) -> Result<(), HintError> {
334 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
335 let base = get_integer_from_var_name("base", vm, ids_data, ap_tracking)?;
336 let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?;
337 let base = &base
338 .as_ref()
339 .try_into()
340 .map_err(|_| MathError::DividedByZero)?;
341 let bound = bound.as_ref();
342 let output = get_ptr_from_var_name("output", vm, ids_data, ap_tracking)?;
343 let res = value.mod_floor(base);
345 if &res > bound {
346 return Err(HintError::SplitIntLimbOutOfRange(Box::new(res)));
347 }
348 vm.insert_value(output, res).map_err(HintError::Memory)
349}
350
351pub fn is_positive(
355 vm: &mut VirtualMachine,
356 ids_data: &HashMap<String, HintReference>,
357 ap_tracking: &ApTracking,
358) -> Result<(), HintError> {
359 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
360 let value_as_int = signed_felt(value);
361 let range_check_builtin = vm.get_range_check_builtin()?;
362
363 let (sign, abs_value) = value_as_int.into_parts();
365 if abs_value >= range_check_builtin.bound().to_biguint() {
367 return Err(HintError::ValueOutsideValidRange(Box::new(value)));
368 }
369
370 let result = Felt252::from((sign == Sign::Plus) as u8);
371 insert_value_from_var_name("is_positive", result, vm, ids_data, ap_tracking)
372}
373
374pub fn split_felt(
384 vm: &mut VirtualMachine,
385 ids_data: &HashMap<String, HintReference>,
386 ap_tracking: &ApTracking,
387 constants: &HashMap<String, Felt252>,
388) -> Result<(), HintError> {
389 let assert = |b: bool, msg: &str| {
390 b.then_some(())
391 .ok_or_else(|| HintError::AssertionFailed(msg.to_string().into_boxed_str()))
392 };
393 let bound = pow2_const(128);
394 let max_high = get_constant_from_var_name("MAX_HIGH", constants)?;
395 let max_low = get_constant_from_var_name("MAX_LOW", constants)?;
396 assert(
397 max_high < &bound && max_low < &bound,
398 "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128",
399 )?;
400 assert(
401 Felt252::MAX == max_high * bound + max_low,
402 "assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW",
403 )?;
404 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
405 let value = value.as_ref();
406 let (high, low) = value.div_rem(&bound.try_into().unwrap());
411 insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?;
412 insert_value_from_var_name("low", low, vm, ids_data, ap_tracking)
413}
414
415pub fn sqrt(
421 vm: &mut VirtualMachine,
422 ids_data: &HashMap<String, HintReference>,
423 ap_tracking: &ApTracking,
424) -> Result<(), HintError> {
425 let mod_value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
426 if mod_value > pow2_const(250) {
428 return Err(HintError::ValueOutside250BitRange(Box::new(mod_value)));
429 }
431 insert_value_from_var_name(
432 "root",
433 Felt252::from(&isqrt(&mod_value.to_biguint())?),
434 vm,
435 ids_data,
436 ap_tracking,
437 )
438}
439
440pub fn signed_div_rem(
441 vm: &mut VirtualMachine,
442 ids_data: &HashMap<String, HintReference>,
443 ap_tracking: &ApTracking,
444) -> Result<(), HintError> {
445 let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?;
446 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
447 let value = value.as_ref();
448 let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?;
449 let builtin = vm.get_range_check_builtin()?;
450
451 let builtin_bound = builtin.bound();
452 if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? {
453 return Err(HintError::OutOfValidRange(Box::new((div, *builtin_bound))));
454 }
455 let builtin_bound_div_2 = builtin_bound.field_div(&Felt252::TWO.try_into().unwrap());
456 if bound > builtin_bound_div_2 {
457 return Err(HintError::OutOfValidRange(Box::new((
458 bound,
459 builtin_bound_div_2,
460 ))));
461 }
462
463 let int_value = signed_felt(*value);
464 let int_div = div.to_bigint();
465 let int_bound = bound.to_bigint();
466 let (q, r) = int_value.div_mod_floor(&int_div);
467
468 if int_bound.abs() < q.abs() {
469 return Err(HintError::OutOfValidRange(Box::new((
470 Felt252::from(&q),
471 bound,
472 ))));
473 }
474
475 let biased_q = q + int_bound;
476 insert_value_from_var_name("r", Felt252::from(&r), vm, ids_data, ap_tracking)?;
477 insert_value_from_var_name(
478 "biased_q",
479 Felt252::from(&biased_q),
480 vm,
481 ids_data,
482 ap_tracking,
483 )
484}
485
486pub fn unsigned_div_rem(
496 vm: &mut VirtualMachine,
497 ids_data: &HashMap<String, HintReference>,
498 ap_tracking: &ApTracking,
499) -> Result<(), HintError> {
500 let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?;
501 let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?;
502 let builtin_bound = vm.get_range_check_builtin()?.bound();
503
504 if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? {
506 return Err(HintError::OutOfValidRange(Box::new((div, *builtin_bound))));
507 }
508
509 let (q, r) = value.div_rem(&(div).try_into().map_err(|_| MathError::DividedByZero)?);
510 insert_value_from_var_name("r", r, vm, ids_data, ap_tracking)?;
511 insert_value_from_var_name("q", q, vm, ids_data, ap_tracking)
512}
513
514pub fn assert_250_bit(
521 vm: &mut VirtualMachine,
522 ids_data: &HashMap<String, HintReference>,
523 ap_tracking: &ApTracking,
524 constants: &HashMap<String, Felt252>,
525) -> Result<(), HintError> {
526 const UPPER_BOUND: &str = "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND";
527 const SHIFT: &str = "starkware.cairo.common.math.assert_250_bit.SHIFT";
528 let upper_bound = constants
530 .get(UPPER_BOUND)
531 .map_or_else(|| get_constant_from_var_name("UPPER_BOUND", constants), Ok)?;
532 let shift = constants
533 .get(SHIFT)
534 .map_or_else(|| get_constant_from_var_name("SHIFT", constants), Ok)?;
535 let value = Felt252::from(&signed_felt(get_integer_from_var_name(
536 "value",
537 vm,
538 ids_data,
539 ap_tracking,
540 )?));
541 if &value > upper_bound {
543 return Err(HintError::ValueOutside250BitRange(Box::new(value)));
544 }
545 let (high, low) = value.div_rem(&shift.try_into().map_err(|_| MathError::DividedByZero)?);
546 insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?;
547 insert_value_from_var_name("low", low, vm, ids_data, ap_tracking)
548}
549
550pub fn is_250_bits(
553 vm: &mut VirtualMachine,
554 ids_data: &HashMap<String, HintReference>,
555 ap_tracking: &ApTracking,
556) -> Result<(), HintError> {
557 let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?;
558
559 let is_250 = Felt252::from((addr.as_ref().bits() <= 250) as u8);
561
562 insert_value_from_var_name("is_250", is_250, vm, ids_data, ap_tracking)
563}
564
565pub fn is_addr_bounded(
577 vm: &mut VirtualMachine,
578 ids_data: &HashMap<String, HintReference>,
579 ap_tracking: &ApTracking,
580 constants: &HashMap<String, Felt252>,
581) -> Result<(), HintError> {
582 let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?;
583
584 let addr_bound = constants
585 .get(ADDR_BOUND)
586 .ok_or_else(|| HintError::MissingConstant(Box::new(ADDR_BOUND)))?
587 .to_biguint();
588
589 let lower_bound = BigUint::one() << 250_usize;
590 let upper_bound = BigUint::one() << 251_usize;
591
592 if !(lower_bound < addr_bound
597 && addr_bound <= upper_bound
598 && (&addr_bound << 1_usize) > *CAIRO_PRIME)
599 {
600 return Err(HintError::AssertionFailed(
601 "normalize_address() cannot be used with the current constants."
602 .to_string()
603 .into_boxed_str(),
604 ));
605 }
606
607 let is_small = Felt252::from((addr.as_ref() < &Felt252::from(&addr_bound)) as u8);
609
610 insert_value_from_var_name("is_small", is_small, vm, ids_data, ap_tracking)
611}
612
613pub fn assert_lt_felt(
624 vm: &mut VirtualMachine,
625 ids_data: &HashMap<String, HintReference>,
626 ap_tracking: &ApTracking,
627) -> Result<(), HintError> {
628 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
629 let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
630 if a >= b {
636 return Err(HintError::AssertLtFelt252(Box::new((a, b))));
637 };
638 Ok(())
639}
640
641pub fn is_quad_residue(
642 vm: &mut VirtualMachine,
643 ids_data: &HashMap<String, HintReference>,
644 ap_tracking: &ApTracking,
645) -> Result<(), HintError> {
646 let x = get_integer_from_var_name("x", vm, ids_data, ap_tracking)?;
647
648 if x.is_zero() || x == Felt252::ONE {
649 insert_value_from_var_name("y", *x.as_ref(), vm, ids_data, ap_tracking)
650 } else if x.pow_felt(&Felt252::MAX.div_rem(&Felt252::TWO.try_into().unwrap()).0) == Felt252::ONE
652 {
653 insert_value_from_var_name("y", x.sqrt().unwrap_or_default(), vm, ids_data, ap_tracking)
654 } else {
655 insert_value_from_var_name(
656 "y",
657 (x.field_div(&Felt252::THREE.try_into().unwrap()))
658 .sqrt()
659 .unwrap_or_default(),
660 vm,
661 ids_data,
662 ap_tracking,
663 )
664 }
665}
666
667fn div_prime_by_bound(bound: Felt252) -> Result<Felt252, VirtualMachineError> {
668 let prime: &BigUint = &CAIRO_PRIME;
669 let limit = prime / bound.to_biguint();
670 Ok(Felt252::from(&limit))
671}
672
673fn prime_div_constant(bound: u32) -> Result<BigUint, VirtualMachineError> {
674 let prime: &BigUint = &CAIRO_PRIME;
675 let limit = prime / bound;
676 Ok(limit)
677}
678
679pub fn a_b_bitand_1(
686 vm: &mut VirtualMachine,
687 ids_data: &HashMap<String, HintReference>,
688 ap_tracking: &ApTracking,
689) -> Result<(), HintError> {
690 let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
691 let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;
692 let two = Felt252::TWO.try_into().unwrap();
693 let a_lsb = a.mod_floor(&two);
694 let b_lsb = b.mod_floor(&two);
695 insert_value_from_var_name("a_lsb", a_lsb, vm, ids_data, ap_tracking)?;
696 insert_value_from_var_name("b_lsb", b_lsb, vm, ids_data, ap_tracking)
697}
698
699lazy_static! {
700 static ref SPLIT_XX_PRIME: BigUint = BigUint::parse_bytes(
701 b"57896044618658097711785492504343953926634992332820282019728792003956564819949",
702 10
703 )
704 .unwrap();
705 static ref II: BigUint = BigUint::parse_bytes(
706 b"19681161376707505956807079304988542015446066515923890162744021073123829784752",
707 10
708 )
709 .unwrap();
710}
711
712pub fn split_xx(
728 vm: &mut VirtualMachine,
729 ids_data: &HashMap<String, HintReference>,
730 ap_tracking: &ApTracking,
731) -> Result<(), HintError> {
732 let xx = Uint256::from_var_name("xx", vm, ids_data, ap_tracking)?;
733 let x_addr = get_relocatable_from_var_name("x", vm, ids_data, ap_tracking)?;
734 let xx: BigUint = xx.low.to_biguint() + (*xx.high * pow2_const(128)).to_biguint();
735 let mut x = xx.modpow(
736 &(&*SPLIT_XX_PRIME + 3_u32).div_floor(&BigUint::from(8_u32)),
737 &SPLIT_XX_PRIME,
738 );
739 if !(&x * &x - xx).mod_floor(&SPLIT_XX_PRIME).is_zero() {
740 x = (&x * &*II).mod_floor(&SPLIT_XX_PRIME)
741 };
742 if !x.mod_floor(&2_u32.into()).is_zero() {
743 x = &*SPLIT_XX_PRIME - x;
744 }
745
746 vm.insert_value(x_addr, Felt252::from(&(&x & &BigUint::from(u128::MAX))))?;
747 vm.insert_value((x_addr + 1)?, Felt252::from(&(x >> 128_u32)))?;
748
749 Ok(())
750}
751
752#[cfg(test)]
753mod tests {
754 use super::*;
755 use crate::{felt_hex, felt_str};
756 use core::ops::Neg;
757
758 use crate::{
759 any_box,
760 hint_processor::{
761 builtin_hint_processor::{
762 builtin_hint_processor_definition::{BuiltinHintProcessor, HintProcessorData},
763 hint_code,
764 },
765 hint_processor_definition::HintProcessorLogic,
766 },
767 relocatable,
768 types::exec_scope::ExecutionScopes,
769 types::relocatable::Relocatable,
770 utils::test_utils::*,
771 vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine},
772 };
773 use assert_matches::assert_matches;
774
775 #[cfg(not(target_arch = "wasm32"))]
776 use proptest::prelude::*;
777
778 #[cfg(target_arch = "wasm32")]
779 use wasm_bindgen_test::*;
780
781 #[test]
782 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
783 fn run_is_nn_hint_false() {
784 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
785 let mut vm = vm_with_range_check!();
786 vm.run_context.fp = 10;
788 vm.segments = segments![((1, 9), (-1))];
790 add_segments!(vm, 1);
791 let ids_data = ids_data!["a"];
793 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
795 check_memory![vm.segments.memory, ((1, 0), 1)];
797 }
798
799 #[test]
800 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
801 fn run_is_nn_hint_true() {
802 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
803 let mut vm = vm_with_range_check!();
804 vm.run_context.fp = 5;
806 vm.segments = segments![((1, 4), 1)];
808 add_segments!(vm, 1);
809 let ids_data = ids_data!["a"];
811 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
813 check_memory![vm.segments.memory, ((1, 0), 0)];
815 }
816
817 #[test]
818 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
819 fn run_is_nn_hint_true_border_case() {
822 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
823 let mut vm = vm_with_range_check!();
824 vm.run_context.fp = 5;
826 add_segments!(vm, 2);
828 vm.insert_value(
829 (1, 4).into(),
830 felt_str!(
831 "3618502788666131213697322783095070105623107215331596699973092056135872020480"
832 )
833 .neg(),
834 )
835 .unwrap();
836 let ids_data = ids_data!["a"];
838 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
840 check_memory![vm.segments.memory, ((1, 0), 0)];
842 }
843
844 #[test]
845 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
846 fn run_is_nn_hint_no_range_check_builtin() {
847 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
848 let mut vm = vm!();
849 vm.run_context.fp = 5;
851 vm.segments = segments![((1, 4), 1)];
853 let ids_data = ids_data!["a"];
855 assert_matches!(
857 run_hint!(vm, ids_data, hint_code),
858 Err(HintError::Internal(
859 VirtualMachineError::NoRangeCheckBuiltin
860 ))
861 );
862 }
863
864 #[test]
865 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
866 fn run_is_nn_hint_incorrect_ids() {
867 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
868 let mut vm = vm_with_range_check!();
869 add_segments!(vm, 2);
870 let ids_data = ids_data!["b"];
873 assert_matches!(
875 run_hint!(vm, ids_data, hint_code),
876 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
877 );
878 }
879
880 #[test]
881 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
882 fn run_is_nn_hint_cant_get_ids_from_memory() {
883 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
884 let mut vm = vm_with_range_check!();
885 add_segments!(vm, 2);
886 vm.run_context.fp = 5;
888 let ids_data = ids_data!["a"];
891 assert_matches!(
893 run_hint!(vm, ids_data, hint_code),
894 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
895 );
896 }
897
898 #[test]
899 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
900 fn run_is_nn_hint_ids_are_relocatable_values() {
901 let hint_code = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1";
902 let mut vm = vm_with_range_check!();
903 vm.run_context.fp = 5;
905 vm.segments = segments![((1, 4), (2, 3))];
907 let ids_data = ids_data!["a"];
909 assert_matches!(
911 run_hint!(vm, ids_data, hint_code),
912 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
913 );
914 }
915
916 #[test]
917 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
918 fn run_assert_le_felt_valid() {
919 let mut constants = HashMap::new();
920 constants.insert(
921 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
922 felt_hex!("4000000000000088000000000000001"),
923 );
924 constants.insert(
925 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
926 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
927 );
928 let mut vm = vm_with_range_check!();
929 let mut exec_scopes = scope![("excluded", 1)];
930 vm.run_context.fp = 3;
932 vm.segments = segments![((1, 0), 1), ((1, 1), 2), ((1, 2), (2, 0))];
934 add_segments!(vm, 1);
935 let ids_data = ids_data!["a", "b", "range_check_ptr"];
937 assert_matches!(
939 run_hint!(
940 vm,
941 ids_data,
942 hint_code::ASSERT_LE_FELT,
943 &mut exec_scopes,
944 &constants
945 ),
946 Ok(())
947 );
948 }
950
951 #[test]
952 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
953 fn is_le_felt_hint_true() {
954 let hint_code = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1";
955 let mut vm = vm_with_range_check!();
956 vm.run_context.fp = 10;
958 vm.segments = segments![((1, 8), 1), ((1, 9), 2)];
960 add_segments!(vm, 1);
961 let ids_data = ids_data!["a", "b"];
962 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
964 check_memory![vm.segments.memory, ((1, 0), 0)];
966 }
967
968 #[test]
969 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
970 fn run_is_le_felt_hint_inconsistent_memory() {
971 let hint_code = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1";
972 let mut vm = vm_with_range_check!();
973 vm.run_context.fp = 2;
975 vm.segments = segments![((1, 0), 1), ((1, 1), 2)];
976 let ids_data = ids_data!["a", "b"];
978 assert_matches!(
980 run_hint!(vm, ids_data, hint_code),
981 Err(HintError::Memory(
982 MemoryError::InconsistentMemory(bx)
983 )) if *bx == (Relocatable::from((1, 0)),
984 MaybeRelocatable::Int(Felt252::ONE),
985 MaybeRelocatable::Int(Felt252::ZERO))
986 );
987 }
988
989 #[test]
990 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
991 fn run_is_le_felt_hint_incorrect_ids() {
992 let hint_code = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1";
993 let mut vm = vm!();
994 vm.run_context.fp = 10;
995 vm.segments = segments![((1, 8), 1), ((1, 9), 2)];
996 let ids_data = ids_data!["a", "c"];
998 assert_matches!(
999 run_hint!(vm, ids_data, hint_code),
1000 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "b"
1001 );
1002 }
1003
1004 #[test]
1005 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1006 fn run_assert_nn_valid() {
1007 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1008 let mut vm = vm_with_range_check!();
1009 vm.run_context.fp = 1;
1011 vm.segments = segments![((1, 0), 1)];
1013 let ids_data = ids_data!["a"];
1015 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1017 }
1019
1020 #[test]
1021 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1022 fn run_assert_nn_invalid() {
1023 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1024 let mut vm = vm_with_range_check!();
1025 vm.run_context.fp = 1;
1027 vm.segments = segments![((1, 0), (-1))];
1029 let ids_data = ids_data!["a"];
1031 assert_matches!(
1033 run_hint!(vm, ids_data, hint_code),
1034 Err(HintError::AssertNNValueOutOfRange(bx)) if *bx == Felt252::from(-1)
1035 );
1036 }
1037
1038 #[test]
1039 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1040 fn run_assert_nn_incorrect_ids() {
1041 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1042 let mut vm = vm_with_range_check!();
1043 vm.run_context.fp = 4;
1045 vm.segments = segments![((1, 0), (-1))];
1047 let ids_data = ids_data!["incorrect_id"];
1048 assert_matches!(
1050 run_hint!(vm, ids_data, hint_code),
1051 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
1052 );
1053 }
1054
1055 #[test]
1056 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1057 fn run_assert_nn_a_is_not_integer() {
1058 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1059 let mut vm = vm_with_range_check!();
1060 vm.run_context.fp = 1;
1062 vm.segments = segments![((1, 0), (10, 10))];
1064 let ids_data = ids_data!["a"];
1065 assert_matches!(
1067 run_hint!(vm, ids_data, hint_code),
1068 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
1069 );
1070 }
1071
1072 #[test]
1073 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1074 fn run_assert_nn_no_range_check_builtin() {
1075 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1076 let mut vm = vm!();
1077 vm.run_context.fp = 1;
1079 vm.segments = segments![((1, 0), 1)];
1081 let ids_data = ids_data!["a"];
1082 assert_matches!(
1084 run_hint!(vm, ids_data, hint_code),
1085 Err(HintError::Internal(
1086 VirtualMachineError::NoRangeCheckBuiltin
1087 ))
1088 );
1089 }
1090
1091 #[test]
1092 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1093 fn run_assert_nn_reference_is_not_in_memory() {
1094 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'";
1095 let mut vm = vm_with_range_check!();
1096 add_segments!(vm, 1);
1097 vm.run_context.fp = 4;
1099 let ids_data = ids_data!["a"];
1100 assert_matches!(
1102 run_hint!(vm, ids_data, hint_code),
1103 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "a"
1104 );
1105 }
1106
1107 #[test]
1108 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1109 fn run_is_assert_le_felt_invalid() {
1110 let mut vm = vm_with_range_check!();
1111 let mut constants = HashMap::new();
1112 constants.insert(
1113 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
1114 felt_hex!("4000000000000088000000000000001"),
1115 );
1116 constants.insert(
1117 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
1118 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
1119 );
1120 let mut exec_scopes = scope![("excluded", Felt252::ONE)];
1121 vm.run_context.fp = 3;
1123 vm.segments = segments![((1, 0), 2), ((1, 1), 1), ((1, 2), (2, 0))];
1125 let ids_data = ids_data!["a", "b", "range_check_ptr"];
1126 add_segments!(vm, 1);
1127 assert_matches!(
1129 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants),
1130 Err(HintError::NonLeFelt252(bx)) if *bx == (Felt252::from(2), Felt252::ONE)
1131 );
1132 }
1133
1134 #[test]
1135 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1136 fn run_is_assert_le_felt_a_is_not_integer() {
1137 let mut vm = vm_with_range_check!();
1138 let mut constants = HashMap::new();
1139 constants.insert(
1140 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
1141 felt_hex!("4000000000000088000000000000001"),
1142 );
1143 constants.insert(
1144 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
1145 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
1146 );
1147 let mut exec_scopes = scope![("excluded", 1)];
1148 vm.run_context.fp = 3;
1150 vm.segments = segments![((1, 0), (1, 0)), ((1, 1), 1), ((1, 2), (2, 0))];
1152 let ids_data = ids_data!["a", "b", "range_check_ptr"];
1153 assert_matches!(
1155 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants),
1156 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
1157 );
1158 }
1159
1160 #[test]
1161 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1162 fn run_is_assert_le_felt_b_is_not_integer() {
1163 let mut vm = vm_with_range_check!();
1164 let mut constants = HashMap::new();
1165 constants.insert(
1166 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(),
1167 felt_hex!("4000000000000088000000000000001"),
1168 );
1169 constants.insert(
1170 "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(),
1171 felt_hex!("2AAAAAAAAAAAAB05555555555555556"),
1172 );
1173 let mut exec_scopes = scope![("excluded", 1)];
1174 vm.run_context.fp = 3;
1176 vm.segments = segments![((1, 0), 1), ((1, 1), (1, 0)), ((1, 2), (2, 0))];
1178 let ids_data = ids_data!["a", "b", "range_check_builtin"];
1179 assert_matches!(
1181 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants),
1182 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "b"
1183 );
1184 }
1185
1186 #[test]
1187 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1188 fn run_is_nn_hint_out_of_range_false() {
1189 let hint_code =
1190 "memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1";
1191 let mut vm = vm_with_range_check!();
1192 vm.run_context.fp = 5;
1194 vm.segments = segments![((1, 4), 2)];
1196 add_segments!(vm, 1);
1197 let ids_data = ids_data!["a"];
1199 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1201 check_memory![vm.segments.memory, ((1, 0), 1)];
1202 }
1203
1204 #[test]
1205 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1206 fn run_is_nn_hint_out_of_range_true() {
1207 let hint_code =
1208 "memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1";
1209 let mut vm = vm_with_range_check!();
1210 vm.run_context.fp = 5;
1212 vm.segments = segments![((1, 4), (-1))];
1214 add_segments!(vm, 1);
1215 let ids_data = ids_data!["a"];
1217 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1219 check_memory![vm.segments.memory, ((1, 0), 0)];
1220 }
1221 #[test]
1222 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1223 fn run_assert_not_equal_int_false() {
1224 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1225 let mut vm = vm!();
1226 vm.run_context.fp = 10;
1228 vm.segments = segments![((1, 8), 1), ((1, 9), 1)];
1230 let ids_data = ids_data!["a", "b"];
1231 assert_matches!(
1233 run_hint!(vm, ids_data, hint_code),
1234 Err(HintError::AssertNotEqualFail(bx))
1235 if *bx == (MaybeRelocatable::from(Felt252::ONE), MaybeRelocatable::from(Felt252::ONE))
1236 );
1237 }
1238
1239 #[test]
1240 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1241 fn run_assert_not_equal_int_true() {
1242 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1243 let mut vm = vm!();
1244 vm.run_context.fp = 10;
1246 vm.segments = segments![((1, 8), 1), ((1, 9), 3)];
1248 let ids_data = ids_data!["a", "b"];
1249 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1251 }
1252
1253 #[test]
1254 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1255 fn run_assert_not_equal_int_bignum_true() {
1256 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1257 let mut vm = vm!();
1258 add_segments!(vm, 2);
1259 vm.run_context.fp = 10;
1261 vm.segments = segments![
1263 ((1, 8), (-1)),
1264 (
1265 (1, 9),
1266 (
1267 "618502788666131213697322783095070105623107215331596699973092056135872020480",
1268 10
1269 )
1270 )
1271 ];
1272 let ids_data = ids_data!["a", "b"];
1273 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1275 }
1276
1277 #[test]
1278 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1279 fn run_assert_not_equal_relocatable_false() {
1280 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1281 let mut vm = vm!();
1282 vm.run_context.fp = 10;
1284 vm.segments = segments![((1, 8), (1, 0)), ((1, 9), (1, 0))];
1286 let ids_data = ids_data!["a", "b"];
1287 assert_matches!(
1289 run_hint!(vm, ids_data, hint_code),
1290 Err(HintError::AssertNotEqualFail(bx))
1291 if *bx == (MaybeRelocatable::from((1, 0)), MaybeRelocatable::from((1, 0)))
1292 );
1293 }
1294
1295 #[test]
1296 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1297 fn run_assert_not_equal_relocatable_true() {
1298 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1299 let mut vm = vm!();
1300 vm.run_context.fp = 10;
1302 vm.segments = segments![((1, 8), (0, 1)), ((1, 9), (0, 0))];
1304 let ids_data = ids_data!["a", "b"];
1305 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1307 }
1308
1309 #[test]
1310 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1311 fn run_assert_non_equal_relocatable_diff_index() {
1312 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1313 let mut vm = vm!();
1314 vm.run_context.fp = 10;
1316 vm.segments = segments![((1, 8), (2, 0)), ((1, 9), (1, 0))];
1318 let ids_data = ids_data!["a", "b"];
1319 assert_matches!(
1321 run_hint!(vm, ids_data, hint_code),
1322 Err(HintError::Internal(VirtualMachineError::DiffIndexComp(bx)))
1323 if *bx == (relocatable!(2, 0), relocatable!(1, 0))
1324 );
1325 }
1326
1327 #[test]
1328 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1329 fn run_assert_not_equal_relocatable_and_integer() {
1330 let hint_code = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'";
1331 let mut vm = vm!();
1332 vm.run_context.fp = 10;
1334 vm.segments = segments![((1, 8), (1, 0)), ((1, 9), 1)];
1336 let ids_data = ids_data!["a", "b"];
1337 assert_matches!(
1339 run_hint!(vm, ids_data, hint_code),
1340 Err(HintError::Internal(
1341 VirtualMachineError::DiffTypeComparison(bx)
1342 )) if *bx == (MaybeRelocatable::from((1, 0)), MaybeRelocatable::from(Felt252::ONE))
1343 );
1344 }
1345
1346 #[test]
1347 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1348 fn run_assert_not_zero_true() {
1349 let hint_code =
1350 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1351 let mut vm = vm!();
1352 vm.run_context.fp = 5;
1354 vm.segments = segments![((1, 4), 5)];
1356 let ids_data = ids_data!["value"];
1358
1359 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1360 }
1361
1362 #[test]
1363 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1364 fn run_assert_not_zero_false() {
1365 let hint_code =
1366 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1367 let mut vm = vm!();
1368 vm.run_context.fp = 5;
1370 vm.segments = segments![((1, 4), 0)];
1372 let ids_data = ids_data!["value"];
1374 assert_matches!(
1375 run_hint!(vm, ids_data, hint_code),
1376 Err(HintError::AssertNotZero(bx)) if *bx == (Felt252::ZERO, crate::utils::PRIME_STR.to_string())
1377 );
1378 }
1379
1380 #[test]
1381 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1382 fn run_assert_not_zero_incorrect_id() {
1383 let hint_code =
1384 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1385 let mut vm = vm!();
1386 vm.run_context.fp = 5;
1388 vm.segments = segments![((1, 4), 0)];
1390 let ids_data = ids_data!["incorrect_id"];
1392 assert_matches!(
1393 run_hint!(vm, ids_data, hint_code),
1394 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "value"
1395 );
1396 }
1397
1398 #[test]
1399 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1400 fn run_assert_not_zero_expected_integer_error() {
1401 let hint_code =
1402 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'";
1403 let mut vm = vm!();
1404 vm.run_context.fp = 5;
1406 vm.segments = segments![((1, 4), (1, 0))];
1408 let ids_data = ids_data!["value"];
1410 assert_matches!(
1411 run_hint!(vm, ids_data, hint_code),
1412 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value"
1413 );
1414 }
1415
1416 #[test]
1417 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1418 fn run_split_int_assertion_invalid() {
1419 let hint_code = "assert ids.value == 0, 'split_int(): value is out of range.'";
1420 let mut vm = vm!();
1421 vm.run_context.fp = 5;
1423 vm.segments = segments![((1, 4), 1)];
1425 let ids_data = ids_data!["value"];
1426 assert_matches!(
1428 run_hint!(vm, ids_data, hint_code),
1429 Err(HintError::SplitIntNotZero)
1430 );
1431 }
1432
1433 #[test]
1434 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1435 fn run_split_int_assertion_valid() {
1436 let hint_code = "assert ids.value == 0, 'split_int(): value is out of range.'";
1437 let mut vm = vm!();
1438 vm.run_context.fp = 5;
1440 vm.segments = segments![((1, 4), 0)];
1442 let ids_data = ids_data!["value"];
1443 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1445 }
1446
1447 #[test]
1448 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1449 fn run_split_int_valid() {
1450 let hint_code = "memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base\nassert res < ids.bound, f'split_int(): Limb {res} is out of range.'";
1451 let mut vm = vm!();
1452 vm.run_context.fp = 4;
1454 vm.segments = segments![((1, 0), (2, 0)), ((1, 1), 2), ((1, 2), 10), ((1, 3), 100)];
1456 add_segments!(vm, 2);
1457 let ids_data = ids_data!["output", "value", "base", "bound"];
1458 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1460 check_memory![vm.segments.memory, ((2, 0), 2)];
1461 }
1462
1463 #[test]
1464 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1465 fn run_split_int_invalid() {
1466 let hint_code = "memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base\nassert res < ids.bound, f'split_int(): Limb {res} is out of range.'";
1467 let mut vm = vm!();
1468 vm.run_context.fp = 4;
1470 vm.segments = segments![
1472 ((1, 0), (2, 0)),
1473 ((1, 1), 100),
1474 ((1, 2), 10000),
1475 ((1, 3), 10)
1476 ];
1477 add_segments!(vm, 2);
1478 let ids_data = ids_data!["output", "value", "base", "bound"];
1479 assert_matches!(
1481 run_hint!(vm, ids_data, hint_code),
1482 Err(HintError::SplitIntLimbOutOfRange(bx)) if *bx == Felt252::from(100)
1483 );
1484 }
1485
1486 #[test]
1487 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1488 fn run_is_positive_hint_true() {
1489 let hint_code =
1490 "from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1491 let mut vm = vm_with_range_check!();
1492 vm.run_context.fp = 2;
1494 vm.segments = segments![((1, 0), 250)];
1496 let ids_data = ids_data!["value", "is_positive"];
1499 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1501 check_memory![vm.segments.memory, ((1, 1), 1)];
1503 }
1504
1505 #[test]
1506 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1507 fn run_is_positive_hint_false() {
1508 let hint_code =
1509 "from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1510 let mut vm = vm_with_range_check!();
1511 vm.run_context.fp = 2;
1513 vm.segments = segments![((1, 0), (-250))];
1515 let ids_data = ids_data!["value", "is_positive"];
1517 run_hint!(vm, ids_data, hint_code).expect("Error while executing hint");
1519 check_memory![vm.segments.memory, ((1, 1), 0)];
1521 }
1522
1523 #[test]
1524 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1525 fn run_is_positive_hint_outside_valid_range() {
1526 let hint_code =
1527 "from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1528 let mut vm = vm_with_range_check!();
1529 vm.run_context.fp = 2;
1531 vm.segments = segments![(
1533 (1, 0),
1534 (
1535 "618502761706184546546682988428055018603476541694452277432519575032261771265",
1536 10
1537 )
1538 )];
1539 let ids_data = ids_data!["value", "is_positive"];
1541 assert_matches!(
1543 run_hint!(vm, ids_data, hint_code),
1544 Err(HintError::ValueOutsideValidRange(bx)) if *bx == felt_str!(
1545 "618502761706184546546682988428055018603476541694452277432519575032261771265"
1546 )
1547 );
1548 }
1549
1550 #[test]
1551 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1552 fn run_is_positive_hint_is_positive_not_empty() {
1553 let hint_code ="from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0";
1554 let mut vm = vm_with_range_check!();
1555 add_segments!(vm, 2);
1556 vm.run_context.fp = 2;
1558 vm.segments = segments![((1, 0), 2), ((1, 1), 4)];
1560 let ids_data = ids_data!["value", "is_positive"];
1561 assert_matches!(
1563 run_hint!(vm, ids_data, hint_code),
1564 Err(HintError::Memory(
1565 MemoryError::InconsistentMemory(bx)
1566 )) if *bx == (Relocatable::from((1, 1)),
1567 MaybeRelocatable::from(Felt252::from(4)),
1568 MaybeRelocatable::from(Felt252::ONE))
1569 );
1570 }
1571
1572 #[test]
1573 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1574 fn run_sqrt_valid() {
1575 let hint_code = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)";
1576 let mut vm = vm!();
1577 vm.run_context.fp = 2;
1579 vm.segments = segments![((1, 0), 81)];
1581 let ids_data = ids_data!["value", "root"];
1583 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1585 check_memory![vm.segments.memory, ((1, 1), 9)];
1587 }
1588
1589 #[test]
1590 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1591 fn run_sqrt_invalid_negative_number() {
1592 let hint_code = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)";
1593 let mut vm = vm!();
1594 vm.run_context.fp = 2;
1596 vm.segments = segments![((1, 0), (-81))];
1598 let ids_data = ids_data!["value", "root"];
1600 assert_matches!(
1602 run_hint!(vm, ids_data, hint_code),
1603 Err(HintError::ValueOutside250BitRange(bx)) if *bx == felt_str!(
1604 "3618502788666131213697322783095070105623107215331596699973092056135872020400"
1605 )
1606 );
1607 }
1608
1609 #[test]
1610 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1611 fn run_sqrt_invalid_mismatched_root() {
1612 let hint_code = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)";
1613 let mut vm = vm!();
1614 vm.run_context.fp = 2;
1616 vm.segments = segments![((1, 0), 81), ((1, 1), 7)];
1618 let ids_data = ids_data!["value", "root"];
1620 assert_matches!(
1622 run_hint!(vm, ids_data, hint_code),
1623 Err(HintError::Memory(
1624 MemoryError::InconsistentMemory(bx)
1625 )) if *bx == (Relocatable::from((1, 1)),
1626 MaybeRelocatable::from(Felt252::from(7)),
1627 MaybeRelocatable::from(Felt252::from(9)))
1628 );
1629 }
1630
1631 #[test]
1632 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1633 fn unsigned_div_rem_success() {
1634 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1635 let mut vm = vm_with_range_check!();
1636 vm.run_context.fp = 4;
1638 vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1640 let ids_data = ids_data!["r", "q", "div", "value"];
1642 assert!(run_hint!(vm, ids_data, hint_code).is_ok());
1644 check_memory![vm.segments.memory, ((1, 0), 2), ((1, 1), 1)];
1645 }
1646
1647 #[test]
1648 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1649 fn unsigned_div_rem_out_of_range() {
1650 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1651 let mut vm = vm_with_range_check!();
1652 vm.run_context.fp = 4;
1654 vm.segments = segments![((1, 2), (-5)), ((1, 3), 7)];
1656 let ids_data = ids_data!["r", "q", "div", "value"];
1658 assert_matches!(
1660 run_hint!(vm, ids_data, hint_code),
1661 Err(HintError::OutOfValidRange(bx))
1662 if *bx == (Felt252::from(-5), felt_str!("340282366920938463463374607431768211456"))
1663 )
1664 }
1665
1666 #[test]
1667 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1668 fn unsigned_div_rem_no_range_check_builtin() {
1669 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1670 let mut vm = vm!();
1671 vm.run_context.fp = 4;
1673 vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1675 let ids_data = ids_data!["r", "q", "div", "value"];
1677 assert_matches!(
1678 run_hint!(vm, ids_data, hint_code),
1679 Err(HintError::Internal(
1680 VirtualMachineError::NoRangeCheckBuiltin
1681 ))
1682 );
1683 }
1684
1685 #[test]
1686 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1687 fn unsigned_div_rem_inconsitent_memory() {
1688 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1689 let mut vm = vm_with_range_check!();
1690 vm.run_context.fp = 4;
1692 vm.segments = segments![((1, 0), 5), ((1, 2), 5), ((1, 3), 7)];
1694 let ids_data = ids_data!["r", "q", "div", "value"];
1696 assert_matches!(
1698 run_hint!(vm, ids_data, hint_code),
1699 Err(HintError::Memory(
1700 MemoryError::InconsistentMemory(bx)
1701 )) if *bx == (Relocatable::from((1, 0)),
1702 MaybeRelocatable::Int(Felt252::from(5)),
1703 MaybeRelocatable::Int(Felt252::from(2)))
1704 );
1705 }
1706
1707 #[test]
1708 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1709 fn unsigned_div_rem_incorrect_ids() {
1710 let hint_code = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\nids.q, ids.r = divmod(ids.value, ids.div)";
1711 let mut vm = vm_with_range_check!();
1712 vm.run_context.fp = 4;
1714 vm.segments = segments![((1, 2), 5), ((1, 3), 7)];
1716 let ids_data = ids_data!["a", "b", "iv", "vlue"];
1718 assert_matches!(
1720 run_hint!(vm, ids_data, hint_code),
1721 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "div"
1722 )
1723 }
1724
1725 #[test]
1726 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1727 fn signed_div_rem_success() {
1728 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1729 let mut vm = vm_with_range_check!();
1730 vm.run_context.fp = 6;
1732 vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1734 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1736 assert!(run_hint!(vm, ids_data, hint_code).is_ok());
1738 check_memory![vm.segments.memory, ((1, 0), 0), ((1, 1), 31)];
1739 }
1740
1741 #[test]
1742 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1743 fn signed_div_rem_negative_quotient() {
1744 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1745 let mut vm = vm_with_range_check!();
1746 vm.run_context.fp = 6;
1748 vm.segments = segments![((1, 3), 7), ((1, 4), (-10)), ((1, 5), 29)];
1750 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1752 assert!(run_hint!(vm, ids_data, hint_code).is_ok());
1754 check_memory![vm.segments.memory, ((1, 0), 4), ((1, 1), 27)];
1755 }
1756
1757 #[test]
1758 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1759 fn signed_div_rem_out_of_range() {
1760 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1761 let mut vm = vm_with_range_check!();
1762 vm.run_context.fp = 6;
1764 vm.segments = segments![((1, 3), (-5)), ((1, 4), 10), ((1, 5), 29)];
1766 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1768 assert_matches!(
1770 run_hint!(vm, ids_data, hint_code),
1771 Err(HintError::OutOfValidRange(bx))
1772 if *bx == (Felt252::from(-5), felt_str!("340282366920938463463374607431768211456"))
1773 )
1774 }
1775
1776 #[test]
1777 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1778 fn signed_div_rem_out_of_range_bound() {
1779 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1780 let mut vm = vm_with_range_check!();
1781 vm.run_context.fp = 6;
1783 let bound = vm.get_range_check_builtin().unwrap().bound();
1785 vm.segments = segments![((1, 3), (5)), ((1, 4), 10)];
1786 vm.insert_value((1, 5).into(), bound).unwrap();
1787 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1789 let builtin_bound = felt_str!("340282366920938463463374607431768211456");
1791 assert_matches!(
1792 run_hint!(vm, ids_data, hint_code),
1793 Err(HintError::OutOfValidRange(bx))
1794 if *bx == (*bound, builtin_bound.field_div(&Felt252::TWO.try_into().unwrap()))
1795 )
1796 }
1797
1798 #[test]
1799 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1800 fn signed_div_rem_no_range_check_builtin() {
1801 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1802 let mut vm = vm!();
1803 vm.run_context.fp = 6;
1805 vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1807 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1809 assert_matches!(
1810 run_hint!(vm, ids_data, hint_code),
1811 Err(HintError::Internal(
1812 VirtualMachineError::NoRangeCheckBuiltin
1813 ))
1814 );
1815 }
1816
1817 #[test]
1818 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1819 fn signed_div_rem_inconsitent_memory() {
1820 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1821 let mut vm = vm_with_range_check!();
1822 vm.run_context.fp = 6;
1824 vm.segments = segments![((1, 1), 10), ((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1826 let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"];
1828 assert_matches!(
1830 run_hint!(vm, ids_data, hint_code),
1831 Err(HintError::Memory(
1832 MemoryError::InconsistentMemory(bx)
1833 )) if *bx == (Relocatable::from((1, 1)),
1834 MaybeRelocatable::Int(Felt252::from(10)),
1835 MaybeRelocatable::Int(Felt252::from(31)))
1836 );
1837 }
1838
1839 #[test]
1840 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1841 fn signed_div_rem_incorrect_ids() {
1842 let hint_code = "from starkware.cairo.common.math_utils import as_int, assert_integer\n\nassert_integer(ids.div)\nassert 0 < ids.div <= PRIME // range_check_builtin.bound, \\\n f'div={hex(ids.div)} is out of the valid range.'\n\nassert_integer(ids.bound)\nassert ids.bound <= range_check_builtin.bound // 2, \\\n f'bound={hex(ids.bound)} is out of the valid range.'\n\nint_value = as_int(ids.value, PRIME)\nq, ids.r = divmod(int_value, ids.div)\n\nassert -ids.bound <= q < ids.bound, \\\n f'{int_value} / {ids.div} = {q} is out of the range [{-ids.bound}, {ids.bound}).'\n\nids.biased_q = q + ids.bound";
1843 let mut vm = vm_with_range_check!();
1844 vm.run_context.fp = 6;
1846 vm.segments = segments![((1, 3), 5), ((1, 4), 10), ((1, 5), 29)];
1848 let ids_data = ids_data!["r", "b", "r", "d", "v", "b"];
1850 assert_matches!(
1852 run_hint!(vm, ids_data, hint_code),
1853 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "div"
1854 )
1855 }
1856
1857 #[test]
1858 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1859 fn run_assert_250_bit_valid() {
1860 let hint_code = hint_code::ASSERT_250_BITS;
1861 let constants = HashMap::from([
1862 ("UPPER_BOUND".to_string(), Felt252::from(15)),
1863 ("SHIFT".to_string(), Felt252::from(5)),
1864 ]);
1865 let mut vm = vm!();
1866 vm.run_context.fp = 3;
1868 vm.segments = segments![((1, 0), 1)];
1870 let ids_data = ids_data!["value", "high", "low"];
1872 assert_matches!(
1874 run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants),
1875 Ok(())
1876 );
1877 check_memory![vm.segments.memory, ((1, 1), 0), ((1, 2), 1)];
1880 }
1881
1882 #[test]
1883 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1884 fn run_assert_250_bit_invalid() {
1885 let hint_code = hint_code::ASSERT_250_BITS;
1886 let constants = HashMap::from([
1887 ("UPPER_BOUND".to_string(), Felt252::from(15)),
1888 ("SHIFT".to_string(), Felt252::from(5)),
1889 ]);
1890 let mut vm = vm!();
1891 vm.run_context.fp = 3;
1893 vm.segments = segments![(
1896 (1, 0),
1897 (
1898 "3618502788666131106986593281521497120414687020801267626233049500247285301248",
1899 10
1900 )
1901 )];
1902 let ids_data = ids_data!["value", "high", "low"];
1904 assert_matches!(
1906 run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants),
1907 Err(HintError::ValueOutside250BitRange(bx)) if *bx == pow2_const(251)
1908 );
1909 }
1910
1911 #[test]
1912 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1913 fn run_is_250_bits_valid() {
1914 let hint_code = "ids.is_250 = 1 if ids.addr < 2**250 else 0";
1915 let mut vm = vm!();
1916 vm.run_context.fp = 2;
1918 vm.segments = segments![((1, 0), 1152251)];
1920 let ids_data = ids_data!["addr", "is_250"];
1922 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1924 check_memory![vm.segments.memory, ((1, 1), 1)];
1926 }
1927
1928 #[test]
1929 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1930 fn run_is_250_bits_invalid() {
1931 let hint_code = "ids.is_250 = 1 if ids.addr < 2**250 else 0";
1932 let mut vm = vm!();
1933 vm.run_context.fp = 2;
1935 vm.segments = segments![(
1938 (1, 0),
1939 (
1940 "3618502788666131106986593281521497120414687020801267626233049500247285301248",
1941 10
1942 )
1943 )];
1944 let ids_data = ids_data!["addr", "is_250"];
1946 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
1948 check_memory![vm.segments.memory, ((1, 1), 0)];
1950 }
1951
1952 #[test]
1953 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1954 fn run_is_addr_bounded_ok() {
1955 let hint_code = hint_code::IS_ADDR_BOUNDED;
1956 let mut vm = vm!();
1957 let addr_bound = felt_str!(
1958 "3618502788666131106986593281521497120414687020801267626233049500247285301000"
1959 );
1960 vm.run_context.fp = 2;
1962 vm.segments = segments![(
1964 (1, 0),
1965 (
1966 "1809251394333067160431340899751024102169435851563236335319518532916477952000",
1967 10
1968 )
1969 ),];
1970 let ids_data = ids_data!["addr", "is_small"];
1972 assert_matches!(
1974 run_hint!(
1975 vm,
1976 ids_data,
1977 hint_code,
1978 exec_scopes_ref!(),
1979 &[(ADDR_BOUND, addr_bound)]
1980 .into_iter()
1981 .map(|(k, v)| (k.to_string(), v))
1982 .collect()
1983 ),
1984 Ok(())
1985 );
1986 check_memory![vm.segments.memory, ((1, 1), 1)];
1988 }
1989
1990 #[test]
1991 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1992 fn run_is_addr_bounded_assert_fail() {
1993 let hint_code = hint_code::IS_ADDR_BOUNDED;
1994 let mut vm = vm!();
1995 let addr_bound = Felt252::ONE;
1996 vm.run_context.fp = 2;
1998 vm.segments = segments![(
2000 (1, 0),
2001 (
2002 "3618502788666131106986593281521497120414687020801267626233049500247285301000",
2003 10
2004 )
2005 ),];
2006 let ids_data = ids_data!["addr", "is_small"];
2008 assert_matches!(
2010 run_hint!(
2011 vm,
2012 ids_data,
2013 hint_code,
2014 exec_scopes_ref!(),
2015 &HashMap::from([(ADDR_BOUND.to_string(), addr_bound)])
2016 ),
2017 Err(HintError::AssertionFailed(bx))
2018 if bx.as_ref() == "normalize_address() cannot be used with the current constants."
2019 );
2020 }
2021
2022 #[test]
2023 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2024 fn run_is_addr_bounded_missing_const() {
2025 let hint_code = hint_code::IS_ADDR_BOUNDED;
2026 let mut vm = vm!();
2027 vm.run_context.fp = 2;
2029 vm.segments = segments![((1, 0), 0),];
2031 let ids_data = ids_data!["addr", "is_small"];
2033 assert_matches!(
2035 run_hint!(vm, ids_data, hint_code),
2036 Err(HintError::MissingConstant(bx)) if *bx == ADDR_BOUND
2037 );
2038 }
2039
2040 #[test]
2041 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2042 fn run_split_felt_ok() {
2043 let hint_code =
2044 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2045 let mut vm = vm_with_range_check!();
2046 vm.segments = segments![
2047 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2048 ((1, 4), (2, 0))
2049 ];
2050 add_segments!(vm, 1);
2051 vm.run_context.fp = 7;
2053 let ids_data = HashMap::from([
2055 ("value".to_string(), HintReference::new_simple(-4)),
2056 (
2057 "low".to_string(),
2058 HintReference::new(-3, 0, true, true, true),
2059 ),
2060 (
2061 "high".to_string(),
2062 HintReference::new(-3, 1, true, true, true),
2063 ),
2064 ]);
2065 assert_matches!(
2067 run_hint!(
2068 vm,
2069 ids_data,
2070 hint_code,
2071 exec_scopes_ref!(),
2072 &HashMap::from([
2073 ("MAX_LOW".to_string(), Felt252::ZERO),
2074 (
2075 "MAX_HIGH".to_string(),
2076 felt_str!("10633823966279327296825105735305134080")
2077 )
2078 ])
2079 ),
2080 Ok(())
2081 );
2082 check_memory![
2084 vm.segments.memory,
2085 ((2, 0), ("335438970432432812899076431678123043273", 10)),
2086 ((2, 1), 0)
2087 ];
2088 }
2089
2090 #[test]
2091 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2092 fn run_split_felt_incorrect_ids() {
2093 let hint_code =
2094 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2095 let mut vm = vm_with_range_check!();
2096 vm.segments = segments![
2097 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2098 ((1, 4), (2, 0))
2099 ];
2100 vm.run_context.fp = 7;
2102 let ids_data = ids_data!["low"];
2105 assert_matches!(
2107 run_hint!(
2108 vm,
2109 ids_data,
2110 hint_code,
2111 exec_scopes_ref!(),
2112 &HashMap::from([
2113 ("MAX_LOW".to_string(), Felt252::ZERO),
2114 (
2115 "MAX_HIGH".to_string(),
2116 felt_str!("10633823966279327296825105735305134080")
2117 )
2118 ])
2119 ),
2120 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "value"
2121 );
2122 }
2123
2124 #[test]
2125 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2126 fn run_split_felt_fails_first_insert() {
2127 let hint_code =
2128 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2129 let mut vm = vm_with_range_check!();
2130 vm.segments = segments![
2131 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2132 ((1, 4), (2, 0)),
2133 ((2, 0), 99)
2134 ];
2135 vm.run_context.fp = 7;
2137 let ids_data = HashMap::from([
2139 ("value".to_string(), HintReference::new_simple(-4)),
2140 (
2141 "low".to_string(),
2142 HintReference::new(-3, 0, true, true, true),
2143 ),
2144 (
2145 "high".to_string(),
2146 HintReference::new(-3, 1, true, true, true),
2147 ),
2148 ]);
2149
2150 assert_matches!(
2152 run_hint!(
2153 vm,
2154 ids_data,
2155 hint_code,
2156 exec_scopes_ref!(),
2157 &HashMap::from([
2158 ("MAX_LOW".to_string(), Felt252::ZERO),
2159 (
2160 "MAX_HIGH".to_string(),
2161 felt_str!("10633823966279327296825105735305134080")
2162 )
2163 ])
2164 ),
2165 Err(HintError::Memory(
2166 MemoryError::InconsistentMemory(bx)
2167 )) if *bx == (Relocatable::from((2, 0)),
2168 MaybeRelocatable::from(Felt252::from(99)),
2169 MaybeRelocatable::from(felt_str!("335438970432432812899076431678123043273")))
2170 );
2171 }
2172
2173 #[test]
2174 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2175 fn run_split_felt_fails_second_insert() {
2176 let hint_code =
2177 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2178 let mut vm = vm_with_range_check!();
2179 vm.segments = segments![
2180 ((1, 4), (2, 0)),
2181 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2182 ((2, 1), 99)
2183 ];
2184 add_segments!(vm, 1);
2185 vm.run_context.fp = 7;
2187 let ids_data = HashMap::from([
2189 ("value".to_string(), HintReference::new_simple(-4)),
2190 (
2191 "low".to_string(),
2192 HintReference::new(-3, 0, true, true, true),
2193 ),
2194 (
2195 "high".to_string(),
2196 HintReference::new(-3, 1, true, true, true),
2197 ),
2198 ]);
2199 assert_matches!(
2201 run_hint!(
2202 vm,
2203 ids_data,
2204 hint_code,
2205 exec_scopes_ref!(),
2206 &HashMap::from([
2207 ("MAX_LOW".to_string(), Felt252::ZERO),
2208 (
2209 "MAX_HIGH".to_string(),
2210 felt_str!("10633823966279327296825105735305134080")
2211 )
2212 ])
2213 ),
2214 Err(HintError::Memory(
2215 MemoryError::InconsistentMemory(bx)
2216 )) if *bx == (Relocatable::from((2, 1)),
2217 MaybeRelocatable::from(Felt252::from(99)),
2218 MaybeRelocatable::from(Felt252::from(0)))
2219 );
2220 }
2221
2222 #[test]
2223 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2224 fn run_split_felt_value_is_not_integer() {
2225 let hint_code =
2226 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2227 let mut vm = vm_with_range_check!();
2228 vm.segments = segments![((1, 3), (1, 0)), ((1, 4), (2, 0))];
2229 vm.run_context.fp = 7;
2231 let ids_data = HashMap::from([
2233 ("value".to_string(), HintReference::new_simple(-4)),
2234 (
2235 "low".to_string(),
2236 HintReference::new(-3, 0, true, true, true),
2237 ),
2238 (
2239 "high".to_string(),
2240 HintReference::new(-3, 1, true, true, true),
2241 ),
2242 ]);
2243 assert_matches!(
2245 run_hint!(
2246 vm,
2247 ids_data,
2248 hint_code,
2249 exec_scopes_ref!(),
2250 &HashMap::from([
2251 ("MAX_LOW".to_string(), Felt252::ZERO),
2252 (
2253 "MAX_HIGH".to_string(),
2254 felt_str!("10633823966279327296825105735305134080")
2255 )
2256 ])
2257 ),
2258 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value"
2259 );
2260 }
2261
2262 #[test]
2263 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2264 fn run_split_felt_no_constants() {
2265 let hint_code =
2266 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2267 let mut vm = vm_with_range_check!();
2268 vm.segments = segments![
2269 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2270 ((1, 4), (2, 0))
2271 ];
2272 add_segments!(vm, 1);
2273 vm.run_context.fp = 7;
2275 let ids_data = HashMap::from([
2277 ("value".to_string(), HintReference::new_simple(-4)),
2278 (
2279 "low".to_string(),
2280 HintReference::new(-3, 0, true, true, true),
2281 ),
2282 (
2283 "high".to_string(),
2284 HintReference::new(-3, 1, true, true, true),
2285 ),
2286 ]);
2287 assert_matches!(
2289 run_hint!(vm, ids_data, hint_code),
2290 Err(HintError::MissingConstant(x)) if (*x) == "MAX_HIGH"
2291 );
2292 }
2293
2294 #[test]
2295 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2296 fn run_split_felt_constants_over_128_bits() {
2297 let hint_code =
2298 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2299 let mut vm = vm_with_range_check!();
2300 vm.segments = segments![
2301 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2302 ((1, 4), (2, 0))
2303 ];
2304 add_segments!(vm, 1);
2305 vm.run_context.fp = 7;
2307 let ids_data = HashMap::from([
2309 ("value".to_string(), HintReference::new_simple(-4)),
2310 (
2311 "low".to_string(),
2312 HintReference::new(-3, 0, true, true, true),
2313 ),
2314 (
2315 "high".to_string(),
2316 HintReference::new(-3, 1, true, true, true),
2317 ),
2318 ]);
2319 assert_matches!(
2321 run_hint!(
2322 vm,
2323 ids_data,
2324 hint_code,
2325 exec_scopes_ref!(),
2326 &HashMap::from([
2327 ("MAX_LOW".to_string(), Felt252::from(-1)),
2328 (
2329 "MAX_HIGH".to_string(),
2330 Felt252::from(-1),
2331 )
2332 ])
2333 ),
2334 Err(HintError::AssertionFailed(x)) if &(*x) == "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128"
2335 );
2336 }
2337
2338 #[test]
2339 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2340 fn run_split_felt_wrong_constants() {
2341 let hint_code =
2342 "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128";
2343 let mut vm = vm_with_range_check!();
2344 vm.segments = segments![
2345 ((1, 3), ("335438970432432812899076431678123043273", 10)),
2346 ((1, 4), (2, 0))
2347 ];
2348 add_segments!(vm, 1);
2349 vm.run_context.fp = 7;
2351 let ids_data = HashMap::from([
2353 ("value".to_string(), HintReference::new_simple(-4)),
2354 (
2355 "low".to_string(),
2356 HintReference::new(-3, 0, true, true, true),
2357 ),
2358 (
2359 "high".to_string(),
2360 HintReference::new(-3, 1, true, true, true),
2361 ),
2362 ]);
2363 assert_matches!(
2365 run_hint!(
2366 vm,
2367 ids_data,
2368 hint_code,
2369 exec_scopes_ref!(),
2370 &HashMap::from([
2371 ("MAX_LOW".to_string(), Felt252::ZERO),
2372 (
2373 "MAX_HIGH".to_string(),
2374 Felt252::ZERO,
2375 )
2376 ])
2377 ),
2378 Err(HintError::AssertionFailed(x)) if &(*x) == "assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW"
2379 );
2380 }
2381
2382 #[test]
2383 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2384 fn run_assert_lt_felt_ok() {
2385 let hint_code =
2386 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2387 let mut vm = vm_with_range_check!();
2388 vm.run_context.fp = 3;
2390 vm.segments = segments![((1, 1), 1), ((1, 2), 2)];
2392 let ids_data = ids_data!["a", "b"];
2394 assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
2396 }
2397
2398 #[test]
2399 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2400 fn run_assert_lt_felt_assert_fails() {
2401 let hint_code =
2402 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2403 let mut vm = vm_with_range_check!();
2404 vm.run_context.fp = 3;
2406 vm.segments = segments![((1, 1), 3), ((1, 2), 2)];
2407 let ids_data = ids_data!["a", "b"];
2408 assert_matches!(
2410 run_hint!(vm, ids_data, hint_code),
2411 Err(HintError::AssertLtFelt252(bx)) if *bx == (Felt252::from(3), Felt252::from(2))
2412 );
2413 }
2414
2415 #[test]
2416 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2417 fn run_assert_lt_felt_incorrect_ids() {
2418 let hint_code =
2419 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2420 let mut vm = vm_with_range_check!();
2421 vm.run_context.fp = 3;
2423 vm.segments = segments![((1, 1), 1), ((1, 2), 2)];
2424 let ids_data = ids_data!["a"];
2426 assert_matches!(
2428 run_hint!(vm, ids_data, hint_code),
2429 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "b"
2430 );
2431 }
2432
2433 #[test]
2434 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2435 fn run_assert_lt_felt_a_is_not_integer() {
2436 let hint_code =
2437 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2438 let mut vm = vm_with_range_check!();
2439 vm.run_context.fp = 3;
2441 vm.segments = segments![((1, 1), (1, 0)), ((1, 2), 2)];
2442 let ids_data = ids_data!["a", "b"];
2443 assert_matches!(
2445 run_hint!(vm, ids_data, hint_code),
2446 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a"
2447 );
2448 }
2449
2450 #[test]
2451 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2452 fn run_assert_lt_felt_b_is_not_integer() {
2453 let hint_code =
2454 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2455 let mut vm = vm_with_range_check!();
2456 vm.run_context.fp = 3;
2458 vm.segments = segments![((1, 1), 1), ((1, 2), (1, 0))];
2459 let ids_data = ids_data!["a", "b"];
2460 assert_matches!(
2462 run_hint!(vm, ids_data, hint_code),
2463 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "b"
2464 );
2465 }
2466
2467 #[test]
2468 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2469 fn run_assert_lt_felt_ok_failed_to_get_ids() {
2470 let hint_code =
2471 "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'";
2472 let mut vm = vm_with_range_check!();
2473 vm.run_context.fp = 3;
2475 vm.segments = segments![((1, 1), 1)];
2477 let ids_data = ids_data!["a", "b"];
2478 assert_matches!(
2480 run_hint!(vm, ids_data, hint_code),
2481 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "b"
2482 );
2483 }
2484
2485 #[test]
2486 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2487 fn run_is_assert_le_felt_v_0_6_assertion_fail() {
2488 let mut vm = vm_with_range_check!();
2489 vm.set_fp(2);
2490 vm.segments = segments![((1, 0), 17), ((1, 1), 7)];
2491 let ids_data = ids_data!["a", "b"];
2494 assert_matches!(
2496 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT_V_0_6),
2497 Err(HintError::NonLeFelt252(bx)) if *bx == (17_u32.into(), 7_u32.into())
2498 );
2499 }
2500
2501 #[test]
2502 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2503 fn run_is_assert_le_felt_v_0_8_assertion_fail() {
2504 let mut vm = vm_with_range_check!();
2505 vm.set_fp(2);
2506 vm.segments = segments![((1, 0), 17), ((1, 1), 7)];
2507 let ids_data = ids_data!["a", "b"];
2510 assert_matches!(
2512 run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT_V_0_8),
2513 Err(HintError::NonLeFelt252(bx)) if *bx == (17_u32.into(), 7_u32.into())
2514 );
2515 }
2516
2517 #[cfg(not(target_arch = "wasm32"))]
2518 proptest! {
2519 #[test]
2520 fn run_is_quad_residue(ref x in "([1-9][0-9]*)") {
2522 let mut vm = vm!();
2523 vm.run_context.fp = 2;
2524 vm.segments = segments![((1, 1), (&x[..], 10))];
2525 let ids_data = ids_data!["y", "x"];
2526
2527 assert_matches!(run_hint!(vm, ids_data, hint_code::IS_QUAD_RESIDUE), Ok(()));
2528
2529 let x = felt_str!(x);
2530
2531 if x.is_zero() || x == Felt252::ONE {
2532 assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().as_ref(), &x);
2533 } else if x.pow_felt(&Felt252::MAX.field_div(&Felt252::TWO.try_into().unwrap())) == Felt252::ONE {
2534 assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), x.sqrt().unwrap());
2535 } else {
2536 assert_eq!(vm.get_integer(Relocatable::from((1, 0))).unwrap().into_owned(), (x.field_div(&(Felt252::from(3).try_into().unwrap())).sqrt().unwrap()));
2537 }
2538 }
2539 }
2540}