diff --git a/CHANGELOG.md b/CHANGELOG.md index 0beebbbdb2..4ed480ad3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -367,6 +367,15 @@ %} ``` +* Add missing hint on vrf.json lib [#1050](https://github.com/lambdaclass/cairo-rs/pull/1050): + + `BuiltinHintProcessor` now supports the following hint: + + ```python + sum_low = ids.a.low + ids.b.low + ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 + ``` + * Add missing hint on uint256_improvements lib [#1016](https://github.com/lambdaclass/cairo-rs/pull/1016): `BuiltinHintProcessor` now supports the following hint: diff --git a/cairo_programs/fq.cairo b/cairo_programs/fq.cairo index d1b12d71fa..01eac26c91 100644 --- a/cairo_programs/fq.cairo +++ b/cairo_programs/fq.cairo @@ -155,18 +155,9 @@ namespace fq { alloc_locals; local res: Uint256; local carry_low: felt; - // unused. added to use UINT256_ADD - local carry_high: felt; - // this hint is not implemented: - // %{ - // sum_low = ids.a.low + ids.b.low - // ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 - // %} %{ sum_low = ids.a.low + ids.b.low ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 - sum_high = ids.a.high + ids.b.high + ids.carry_low - ids.carry_high = 1 if sum_high >= ids.SHIFT else 0 %} // changed hint, no carry_high assert carry_low * carry_low = carry_low; diff --git a/cairo_programs/fq_test.cairo b/cairo_programs/fq_test.cairo index bbdc8227fa..4a82fc5c08 100644 --- a/cairo_programs/fq_test.cairo +++ b/cairo_programs/fq_test.cairo @@ -2,6 +2,30 @@ from cairo_programs.fq import fq, Uint256, Uint512 +func test_add{range_check_ptr}() { + let a = Uint256(346, 0); + let b = Uint256(213, 0); + + let res = fq.add(a, b); + + assert res = Uint256(559, 0); + + let a = Uint256( + 154693353187447763037373048681595478410, 49972746532502551770198072697358847685 + ); + let b = Uint256( + 103510830969771876705678198448587782120, 321696934602460025966614305804515599536 + ); + + let res = fq.add(a, b); + + assert res = Uint256( + 258204184157219639743051247130183260530, 371669681134962577736812378501874447221 + ); + + return (); +} + func test_u512_unsigned_div_rem{range_check_ptr}() { let x = Uint512(26362362, 32523523, 135525, 15521); let div = Uint256(1, 0); @@ -58,6 +82,7 @@ func test_div{range_check_ptr}() { } func main{range_check_ptr}() { + test_add(); test_u512_unsigned_div_rem(); test_div(); diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index a230508d84..ee203eabf6 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -362,7 +362,12 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::DICT_SQUASH_UPDATE_PTR => { dict_squash_update_ptr(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::UINT256_ADD => uint256_add(vm, &hint_data.ids_data, &hint_data.ap_tracking), + hint_code::UINT256_ADD => { + uint256_add(vm, &hint_data.ids_data, &hint_data.ap_tracking, false) + } + hint_code::UINT256_ADD_LOW => { + uint256_add(vm, &hint_data.ids_data, &hint_data.ap_tracking, true) + } hint_code::UINT128_ADD => uint128_add(vm, &hint_data.ids_data, &hint_data.ap_tracking), hint_code::UINT256_SUB => uint256_sub(vm, &hint_data.ids_data, &hint_data.ap_tracking), hint_code::SPLIT_64 => split_64(vm, &hint_data.ids_data, &hint_data.ap_tracking), diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index b24c811511..b50b55cb45 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -301,6 +301,9 @@ ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 sum_high = ids.a.high + ids.b.high + ids.carry_low ids.carry_high = 1 if sum_high >= ids.SHIFT else 0"#; +pub const UINT256_ADD_LOW: &str = r#"sum_low = ids.a.low + ids.b.low +ids.carry_low = 1 if sum_low >= ids.SHIFT else 0"#; + pub const UINT128_ADD: &str = r#"res = ids.a + ids.b ids.carry = 1 if res >= ids.SHIFT else 0"#; @@ -1153,6 +1156,7 @@ from starkware.python.math_utils import div_mod, safe_div a = pack(ids.a, PRIME) b = pack(ids.b, PRIME) value = res = a - b"#; + pub const EC_RECOVER_PRODUCT_MOD: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack from starkware.python.math_utils import div_mod, safe_div diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 067b643986..947f8c48bc 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -100,38 +100,48 @@ impl<'a> From for Uint256<'a> { } /* -Implements hint: +Implements hints: %{ sum_low = ids.a.low + ids.b.low ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 sum_high = ids.a.high + ids.b.high + ids.carry_low ids.carry_high = 1 if sum_high >= ids.SHIFT else 0 %} +%{ + sum_low = ids.a.low + ids.b.low + ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 +%} */ pub fn uint256_add( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, + low_only: bool, ) -> Result<(), HintError> { let shift = Felt252::new(1_u32) << 128_u32; let a = Uint256::from_var_name("a", vm, ids_data, ap_tracking)?; let b = Uint256::from_var_name("b", vm, ids_data, ap_tracking)?; let a_low = a.low.as_ref(); - let a_high = a.high.as_ref(); let b_low = b.low.as_ref(); - let b_high = b.high.as_ref(); // Main logic // sum_low = ids.a.low + ids.b.low // ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 - // sum_high = ids.a.high + ids.b.high + ids.carry_low - // ids.carry_high = 1 if sum_high >= ids.SHIFT else 0 - let carry_low = Felt252::from((a_low + b_low >= shift) as u8); - let carry_high = Felt252::from((a_high + b_high + &carry_low >= shift) as u8); - insert_value_from_var_name("carry_high", carry_high, vm, ids_data, ap_tracking)?; + if !low_only { + let a_high = a.high.as_ref(); + let b_high = b.high.as_ref(); + + // Main logic + // sum_high = ids.a.high + ids.b.high + ids.carry_low + // ids.carry_high = 1 if sum_high >= ids.SHIFT else 0 + let carry_high = Felt252::from((a_high + b_high + &carry_low >= shift) as u8); + + insert_value_from_var_name("carry_high", carry_high, vm, ids_data, ap_tracking)?; + } + insert_value_from_var_name("carry_low", carry_low, vm, ids_data, ap_tracking) } @@ -508,6 +518,28 @@ mod tests { check_memory![vm.segments.memory, ((1, 12), 0), ((1, 13), 1)]; } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_uint256_add_low_only_ok() { + let hint_code = + "sum_low = ids.a.low + ids.b.low\nids.carry_low = 1 if sum_low >= ids.SHIFT else 0"; + let mut vm = vm_with_range_check!(); + //Initialize fp + vm.run_context.fp = 10; + //Create hint_data + let ids_data = non_continuous_ids_data![("a", -6), ("b", -4), ("carry_low", 2)]; + vm.segments = segments![ + ((1, 4), 2), + ((1, 5), 3), + ((1, 6), 4), + ((1, 7), ("340282366920938463463374607431768211455", 10)) + ]; + //Execute the hint + assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(())); + //Check hint memory inserts + check_memory![vm.segments.memory, ((1, 12), 0)]; + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_uint128_add_ok() { diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 7c269b5983..fb22225411 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -846,7 +846,7 @@ fn assert_le_felt_old() { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn cairo_run_fq_test() { let program_data = include_bytes!("../../cairo_programs/fq_test.json"); - run_program_simple_with_memory_holes(program_data.as_slice(), 122); + run_program_simple_with_memory_holes(program_data.as_slice(), 120); } #[test]