Skip to content

Commit

Permalink
feat(hints): Implement NewHint#63 & NewHint#65 (lambdaclass#1047)
Browse files Browse the repository at this point in the history
* Implement hint

* Add integration test + update changelog

* Add unit test

* Remaneme hint

* Implement v0.8 hint

* Integration test

* Update changelog

* Add unit test

---------

Co-authored-by: Mario Rugiero <mario.rugiero@lambdaclass.com>
  • Loading branch information
2 people authored and kariy committed Jun 23, 2023
1 parent 59198bb commit 5a3d1b8
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 0 deletions.
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,39 @@

#### Upcoming Changes


* Implement hint on `assert_le_felt` for versions 0.6.0 and 0.8.2 [#1047](https://github.com/lambdaclass/cairo-rs/pull/1047):

`BuiltinHintProcessor` now supports the following hints:

```python

%{
from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert_integer(ids.b)
assert (ids.a % PRIME) <= (ids.b % PRIME), \
f'a = {ids.a % PRIME} is not less than or equal to b = {ids.b % PRIME}.'
%}

```

```python

%{
from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert_integer(ids.b)
a = ids.a % PRIME
b = ids.b % PRIME
assert a <= b, f'a = {a} is not less than or equal to b = {b}.'

ids.small_inputs = int(
a < range_check_builtin.bound and (b - a) < range_check_builtin.bound)
%}

```

* Implement hint on ec_recover.json whitelist [#1038](https://github.com/lambdaclass/cairo-rs/pull/1038):

`BuiltinHintProcessor` now supports the following hint:
Expand Down
68 changes: 68 additions & 0 deletions cairo_programs/assert_le_felt_old.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
%builtins range_check
from starkware.cairo.common.math import split_felt, assert_le, assert_nn_le

// Asserts that the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than
// or equal to that of b.
// See split_felt() for more details.
func assert_le_felt_v_0_6{range_check_ptr}(a, b) {
%{
from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert_integer(ids.b)
assert (ids.a % PRIME) <= (ids.b % PRIME), \
f'a = {ids.a % PRIME} is not less than or equal to b = {ids.b % PRIME}.'
%}
alloc_locals;
let (local a_high, local a_low) = split_felt(a);
let (b_high, b_low) = split_felt(b);

if (a_high == b_high) {
assert_le(a_low, b_low);
return ();
}
assert_le(a_high, b_high);
return ();
}

// Asserts that the unsigned integer lift (as a number in the range [0, PRIME)) of a is lower than
// or equal to that of b.
// See split_felt() for more details.
@known_ap_change
func assert_le_felt_v_0_8{range_check_ptr}(a, b) {
alloc_locals;
local small_inputs;
%{
from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert_integer(ids.b)
a = ids.a % PRIME
b = ids.b % PRIME
assert a <= b, f'a = {a} is not less than or equal to b = {b}.'

ids.small_inputs = int(
a < range_check_builtin.bound and (b - a) < range_check_builtin.bound)
%}
if (small_inputs != 0) {
assert_nn_le(a, b);
ap += 33;
return ();
}

let (local a_high, local a_low) = split_felt(a);
let (b_high, b_low) = split_felt(b);

if (a_high == b_high) {
assert_le(a_low, b_low);
return ();
}

assert_le(a_high, b_high);
return ();
}

func main{range_check_ptr}() {
assert_le_felt_v_0_6(7, 17);
assert_le_felt_v_0_8(6, 16);
assert_le_felt_v_0_8(5, -15);
return();
}
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,12 @@ impl HintProcessor for BuiltinHintProcessor {
hint_code::EC_RECOVER_SUB_A_B => {
ec_recover_sub_a_b(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::ASSERT_LE_FELT_V_0_6 => {
assert_le_felt_v_0_6(vm, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::ASSERT_LE_FELT_V_0_8 => {
assert_le_felt_v_0_8(vm, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::EC_RECOVER_PRODUCT_MOD => {
ec_recover_product_mod(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
}
Expand Down
18 changes: 18 additions & 0 deletions src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ memory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = (
memory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = (
divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH))"#;

pub const ASSERT_LE_FELT_V_0_6: &str =
"from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert_integer(ids.b)
assert (ids.a % PRIME) <= (ids.b % PRIME), \\
f'a = {ids.a % PRIME} is not less than or equal to b = {ids.b % PRIME}.'";

pub const ASSERT_LE_FELT_V_0_8: &str =
"from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert_integer(ids.b)
a = ids.a % PRIME
b = ids.b % PRIME
assert a <= b, f'a = {a} is not less than or equal to b = {b}.'
ids.small_inputs = int(
a < range_check_builtin.bound and (b - a) < range_check_builtin.bound)";

pub const ASSERT_LE_FELT_EXCLUDED_0: &str = "memory[ap] = 1 if excluded != 0 else 0";
pub const ASSERT_LE_FELT_EXCLUDED_1: &str = "memory[ap] = 1 if excluded != 1 else 0";
pub const ASSERT_LE_FELT_EXCLUDED_2: &str = "assert excluded == 2";
Expand Down
73 changes: 73 additions & 0 deletions src/hint_processor/builtin_hint_processor/math_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,47 @@ pub fn assert_le_felt(
Ok(())
}

pub fn assert_le_felt_v_0_6(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let a = &get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
let b = &get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;

if a.as_ref() > b.as_ref() {
return Err(HintError::NonLeFelt252(
a.clone().into_owned(),
b.clone().into_owned(),
));
}
Ok(())
}

pub fn assert_le_felt_v_0_8(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let a = &get_integer_from_var_name("a", vm, ids_data, ap_tracking)?;
let b = &get_integer_from_var_name("b", vm, ids_data, ap_tracking)?;

if a.as_ref() > b.as_ref() {
return Err(HintError::NonLeFelt252(
a.clone().into_owned(),
b.clone().into_owned(),
));
}
let bound = vm
.get_range_check_builtin()?
._bound
.clone()
.unwrap_or_default();
let small_inputs =
Felt252::from((a.as_ref() < &bound && b.as_ref() - a.as_ref() < bound) as u8);
insert_value_from_var_name("small_inputs", small_inputs, vm, ids_data, ap_tracking)
}

pub fn assert_le_felt_excluded_2(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
let excluded: Felt252 = exec_scopes.get("excluded")?;

Expand Down Expand Up @@ -2001,6 +2042,38 @@ mod tests {
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_is_assert_le_felt_v_0_6_assertion_fail() {
let mut vm = vm_with_range_check!();
vm.set_fp(2);
vm.segments = segments![((1, 0), 17), ((1, 1), 7)];
//Initialize ap
//Create ids_data & hint_data
let ids_data = ids_data!["a", "b"];
//Execute the hint
assert_matches!(
run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT_V_0_6),
Err(HintError::NonLeFelt252(a, b)) if a == 17_u32.into() && b == 7_u32.into()
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_is_assert_le_felt_v_0_8_assertion_fail() {
let mut vm = vm_with_range_check!();
vm.set_fp(2);
vm.segments = segments![((1, 0), 17), ((1, 1), 7)];
//Initialize ap
//Create ids_data & hint_data
let ids_data = ids_data!["a", "b"];
//Execute the hint
assert_matches!(
run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT_V_0_8),
Err(HintError::NonLeFelt252(a, b)) if a == 17_u32.into() && b == 7_u32.into()
);
}

#[cfg(not(target_arch = "wasm32"))]
proptest! {
#[test]
Expand Down
7 changes: 7 additions & 0 deletions src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,13 @@ fn cairo_run_inv_mod_p_uint512() {
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn assert_le_felt_old() {
let program_data = include_bytes!("../../cairo_programs/assert_le_felt_old.json");
run_program_simple_with_memory_holes(program_data.as_slice(), 35);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_run_fq_test() {
Expand Down

0 comments on commit 5a3d1b8

Please sign in to comment.