From 4bc7c54e7380d7a2b9314c33bdec43fa93a167e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20Centeno?= Date: Fri, 28 Apr 2023 16:08:59 -0300 Subject: [PATCH] Feat(hints) 55, 56 & 57 (#1077) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Skeleton + hint55 implementation * Refactor * Implement hint66 * Hint 57 * Appease clippy * Fix: change SECP_P_V2 instead of SECP_P * Add integration tests Also renamed: - `ASSIGN_PACK_MOD_SECP_PRIME_TO_X` -> `IS_ZERO_PACK_ED25519` - `ASSIGN_PACK_MOD_SECP_PRIME_TO_VALUE` -> `REDUCE_ED25519` - `ASSIGN_DIV_MOD_1_X_SECP_PRIME_TO_X_INV_AND_VALUE` -> `IS_ZERO_PACK_ED25519` * Update changelog * Insert SECP_P to exec_scopes, and rename functions * Add call to `test_reduce_ed25519` on reduce.cairo Co-authored-by: fmoletta <99273364+fmoletta@users.noreply.github.com> * Apply changes requesed by @fmoletta - fix: `test_reduce_ed25519` wasn't being called in main of reduce.cairo - don't call `add_segments` macro when using `segments` - use `check_scope` instead of manual `assert_eq`s - change `run_program_simple_with_memory_holes(..., 0)` -> `run_program_simple` * Use `scope` macro instead of manual build Also allow trailing commas in `scope` macro * Add missing `check_scope` * Allow use of `scope` macro without args * Change `assert_matches`+`Ok` for `assert`+`is_ok` * Fix: remove unused import --------- Co-authored-by: Tomás Co-authored-by: Tomás <47506558+MegaRedHand@users.noreply.github.com> Co-authored-by: fmoletta <99273364+fmoletta@users.noreply.github.com> Co-authored-by: Pedro Fontana --- CHANGELOG.md | 25 +++ cairo_programs/is_zero.cairo | 94 +++++++++ cairo_programs/is_zero_pack.cairo | 35 ++++ cairo_programs/reduce.cairo | 89 ++++++++ .../builtin_hint_processor_definition.rs | 10 + .../builtin_hint_processor/hint_code.rs | 15 ++ .../builtin_hint_processor/vrf/mod.rs | 1 + .../builtin_hint_processor/vrf/pack.rs | 196 ++++++++++++++++++ src/tests/cairo_run_test.rs | 11 +- src/utils.rs | 3 +- 10 files changed, 476 insertions(+), 3 deletions(-) create mode 100644 cairo_programs/reduce.cairo create mode 100644 src/hint_processor/builtin_hint_processor/vrf/pack.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index ada91a5a94..ac650ef5e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -120,6 +120,31 @@ x = pack(ids.x, PRIME) % SECP_P %} +* Add missing hints `NewHint#55`, `NewHint#56`, and `NewHint#57` [#1077](https://github.com/lambdaclass/cairo-rs/issues/1077) + + `BuiltinHintProcessor` now supports the following hints: + + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P=2**255-19 + + x = pack(ids.x, PRIME) % SECP_P + ``` + + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P=2**255-19 + + value = pack(ids.x, PRIME) % SECP_P + ``` + + ```python + SECP_P=2**255-19 + from starkware.python.math_utils import div_mod + + value = x_inv = div_mod(1, x, SECP_P) + ``` + * Implement hint for `starkware.cairo.common.cairo_keccak.keccak._copy_inputs` as described by whitelist `starknet/security/whitelists/cairo_keccak.json` [#1058](https://github.com/lambdaclass/cairo-rs/pull/1058) `BuiltinHintProcessor` now supports the following hint: diff --git a/cairo_programs/is_zero.cairo b/cairo_programs/is_zero.cairo index 88d3551d13..4d2a2c3bd4 100644 --- a/cairo_programs/is_zero.cairo +++ b/cairo_programs/is_zero.cairo @@ -3,6 +3,49 @@ from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3 from starkware.cairo.common.cairo_secp.field import unreduced_mul, verify_zero +const BASE = 2 ** 86; +const SECP_REM = 19; + +func verify_zero_ed25519{range_check_ptr}(val: UnreducedBigInt3) { + let q = [ap]; + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P = 2**255-19 + to_assert = pack(ids.val, PRIME) + q, r = divmod(pack(ids.val, PRIME), SECP_P) + assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." + ids.q = q % PRIME + %} + let q_biased = [ap + 1]; + q_biased = q + 2 ** 127, ap++; + [range_check_ptr] = q_biased, ap++; + // This implies that q is in the range [-2**127, 2**127). + + tempvar r1 = (val.d0 + q * SECP_REM) / BASE; + assert [range_check_ptr + 1] = r1 + 2 ** 127; + // This implies that r1 is in the range [-2**127, 2**127). + // Therefore, r1 * BASE is in the range [-2**213, 2**213). + // By the soundness assumption, val.d0 is in the range (-2**250, 2**250). + // This implies that r1 * BASE = val.d0 + q * SECP_REM (as integers). + + tempvar r2 = (val.d1 + r1) / BASE; + assert [range_check_ptr + 2] = r2 + 2 ** 127; + // Similarly, this implies that r2 * BASE = val.d1 + r1 (as integers). + // Therefore, r2 * BASE**2 = val.d1 * BASE + r1 * BASE. + + assert val.d2 = q * (BASE / 8) - r2; + // Similarly, this implies that q * BASE / 4 = val.d2 + r2 (as integers). + // Therefore, + // q * BASE**3 / 4 = val.d2 * BASE**2 + r2 * BASE ** 2 = + // val.d2 * BASE**2 + val.d1 * BASE + r1 * BASE = + // val.d2 * BASE**2 + val.d1 * BASE + val.d0 + q * SECP_REM = + // val + q * SECP_REM. + // Hence, val = q * (BASE**3 / 4 - SECP_REM) = q * (2**256 - SECP_REM) = q * secp256k1_prime. + + let range_check_ptr = range_check_ptr + 3; + return (); +} + // Returns 1 if x == 0 (mod secp256k1_prime), and 0 otherwise. // // Completeness assumption: x's limbs are in the range (-BASE, 2*BASE). @@ -86,6 +129,36 @@ func is_zero_v2_pack{range_check_ptr}(x: BigInt3) -> (res: felt) { return (res=0); } +// Returns 1 if x == 0 (mod Ed25519 prime), and 0 otherwise. +// +// Completeness assumption: x's limbs are in the range (-BASE, 2*BASE). +// Soundness assumption: x's limbs are in the range (-2**107.49, 2**107.49). +func is_zero_ed25519{range_check_ptr}(x: BigInt3) -> (res: felt) { + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P=2**255-19 + + x = pack(ids.x, PRIME) % SECP_P + %} + if (nondet %{ x == 0 %} != 0) { + verify_zero_ed25519(UnreducedBigInt3(d0=x.d0, d1=x.d1, d2=x.d2)); + return (res=1); + } + + %{ + SECP_P=2**255-19 + from starkware.python.math_utils import div_mod + + value = x_inv = div_mod(1, x, SECP_P) + %} + let (x_inv) = nondet_bigint3(); + let (x_x_inv) = unreduced_mul(x, x_inv); + + // Check that x * x_inv = 1 to verify that x != 0. + verify_zero_ed25519(UnreducedBigInt3(d0=x_x_inv.d0 - 1, d1=x_x_inv.d1, d2=x_x_inv.d2)); + return (res=0); +} + func test_is_zero{range_check_ptr}() -> () { let zero = BigInt3(0, 0, 0); @@ -149,11 +222,32 @@ func test_is_zero_v2_pack{range_check_ptr}() -> () { return (); } +func test_is_zero_ed25519{range_check_ptr}() -> () { + let zero = BigInt3(0, 0, 0); + + let (res: felt) = is_zero_ed25519(zero); + assert res = 1; + + let one = BigInt3(1, 0, 0); + + let (res: felt) = is_zero_ed25519(one); + assert res = 0; + + let ed25519_prime = BigInt3( + 77371252455336267181195245, 77371252455336267181195263, 9671406556917033397649407 + ); + + let (res: felt) = is_zero_ed25519(ed25519_prime); + assert res = 1; + + return (); +} func main{range_check_ptr}() -> () { test_is_zero(); test_is_zero_alt(); test_is_zero_v2_pack(); + test_is_zero_ed25519(); return (); } diff --git a/cairo_programs/is_zero_pack.cairo b/cairo_programs/is_zero_pack.cairo index 8ffb5132c0..b49745aa9f 100644 --- a/cairo_programs/is_zero_pack.cairo +++ b/cairo_programs/is_zero_pack.cairo @@ -38,6 +38,19 @@ func is_zero_pack_v2{range_check_ptr}(x: BigInt3) -> (res: felt) { return (res=0); } +func is_zero_pack_ed25519{range_check_ptr}(x: BigInt3) -> (res: felt) { + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P=2**255-19 + + x = pack(ids.x, PRIME) % SECP_P + %} + if (nondet %{ x == 0 %} != 0) { + return (res=1); + } + return (res=0); +} + func test_is_zero_pack{range_check_ptr}() -> () { let zero = BigInt3(0, 0, 0); @@ -80,9 +93,31 @@ func test_is_zero_pack_v2{range_check_ptr}() -> () { return (); } +func test_is_zero_pack_ed25519{range_check_ptr}() -> () { + let zero = BigInt3(0, 0, 0); + + let (res: felt) = is_zero_pack_ed25519(zero); + assert res = 1; + + let one = BigInt3(1, 0, 0); + + let (res: felt) = is_zero_pack_ed25519(one); + assert res = 0; + + let ed25519_prime = BigInt3( + 77371252455336267181195245, 77371252455336267181195263, 9671406556917033397649407 + ); + + let (res: felt) = is_zero_pack_ed25519(ed25519_prime); + assert res = 1; + + return (); +} + func main{range_check_ptr}() -> () { test_is_zero_pack(); test_is_zero_pack_v2(); + test_is_zero_pack_ed25519(); return (); } diff --git a/cairo_programs/reduce.cairo b/cairo_programs/reduce.cairo new file mode 100644 index 0000000000..b78e91c9d4 --- /dev/null +++ b/cairo_programs/reduce.cairo @@ -0,0 +1,89 @@ +%builtins range_check + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3 + +const BASE = 2 ** 86; +const SECP_REM = 19; + +func verify_zero{range_check_ptr}(val: UnreducedBigInt3) { + let q = [ap]; + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P = 2**255-19 + to_assert = pack(ids.val, PRIME) + q, r = divmod(pack(ids.val, PRIME), SECP_P) + assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." + ids.q = q % PRIME + %} + let q_biased = [ap + 1]; + q_biased = q + 2 ** 127, ap++; + [range_check_ptr] = q_biased, ap++; + // This implies that q is in the range [-2**127, 2**127). + + tempvar r1 = (val.d0 + q * SECP_REM) / BASE; + assert [range_check_ptr + 1] = r1 + 2 ** 127; + // This implies that r1 is in the range [-2**127, 2**127). + // Therefore, r1 * BASE is in the range [-2**213, 2**213). + // By the soundness assumption, val.d0 is in the range (-2**250, 2**250). + // This implies that r1 * BASE = val.d0 + q * SECP_REM (as integers). + + tempvar r2 = (val.d1 + r1) / BASE; + assert [range_check_ptr + 2] = r2 + 2 ** 127; + // Similarly, this implies that r2 * BASE = val.d1 + r1 (as integers). + // Therefore, r2 * BASE**2 = val.d1 * BASE + r1 * BASE. + + assert val.d2 = q * (BASE / 8) - r2; + // Similarly, this implies that q * BASE / 4 = val.d2 + r2 (as integers). + // Therefore, + // q * BASE**3 / 4 = val.d2 * BASE**2 + r2 * BASE ** 2 = + // val.d2 * BASE**2 + val.d1 * BASE + r1 * BASE = + // val.d2 * BASE**2 + val.d1 * BASE + val.d0 + q * SECP_REM = + // val + q * SECP_REM. + // Hence, val = q * (BASE**3 / 4 - SECP_REM) = q * (2**256 - SECP_REM) = q * secp256k1_prime. + + let range_check_ptr = range_check_ptr + 3; + return (); +} + +// Receives an unreduced number, and returns a number that is equal to the original number mod +// Ed25519 prime and in reduced form (meaning every limb is in the range [0, BASE)). +// +// Completeness assumption: x's limbs are in the range (-2**210.99, 2**210.99). +// Soundness assumption: x's limbs are in the range (-2**249.99, 2**249.99). +func reduce_ed25519{range_check_ptr}(x: UnreducedBigInt3) -> (reduced_x: BigInt3) { + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P=2**255-19 + + value = pack(ids.x, PRIME) % SECP_P + %} + let (reduced_x: BigInt3) = nondet_bigint3(); + + verify_zero( + UnreducedBigInt3(d0=x.d0 - reduced_x.d0, d1=x.d1 - reduced_x.d1, d2=x.d2 - reduced_x.d2) + ); + return (reduced_x=reduced_x); +} + +func test_reduce_ed25519{range_check_ptr}() { + let x = UnreducedBigInt3(0, 0, 0); + let (res) = reduce_ed25519(x); + assert res = BigInt3(0, 0, 0); + + let x = UnreducedBigInt3( + 1113660525233188137217661511617697775365785011829423399545361443, + 1243997169368861650657124871657865626433458458266748922940703512, + 1484456708474143440067316914074363277495967516029110959982060577, + ); + let (res) = reduce_ed25519(x); + assert res = BigInt3( + 42193159084937489098474581, 19864776835133205750023223, 916662843592479469328893 + ); + + return (); +} + +func main{range_check_ptr}() { + test_reduce_ed25519(); + return (); +} 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 0943da7610..281aaea402 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 @@ -16,6 +16,7 @@ use super::{ vrf::{ fq::{inv_mod_p_uint256, uint512_unsigned_div_rem}, inv_mod_p_uint512::inv_mod_p_uint512, + pack::*, }, }; use crate::hint_processor::builtin_hint_processor::secp::ec_utils::ec_double_assign_new_x; @@ -312,6 +313,9 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::REDUCE => { reduce(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } + hint_code::REDUCE_ED25519 => { + ed25519_reduce(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) + } hint_code::BLAKE2S_FINALIZE | hint_code::BLAKE2S_FINALIZE_V2 => { finalize_blake2s(vm, &hint_data.ids_data, &hint_data.ap_tracking) } @@ -420,10 +424,16 @@ impl HintProcessor for BuiltinHintProcessor { &hint_data.ap_tracking, ) } + hint_code::IS_ZERO_PACK_ED25519 => { + ed25519_is_zero_pack(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) + } hint_code::IS_ZERO_ASSIGN_SCOPE_VARS => is_zero_assign_scope_variables(exec_scopes), hint_code::IS_ZERO_ASSIGN_SCOPE_VARS_EXTERNAL_SECP => { is_zero_assign_scope_variables_external_const(exec_scopes) } + hint_code::IS_ZERO_ASSIGN_SCOPE_VARS_ED25519 => { + ed25519_is_zero_assign_scope_vars(exec_scopes) + } hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 => div_mod_n_packed_divmod( vm, exec_scopes, diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 237e167488..5a8c04df5c 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -536,6 +536,11 @@ pub const REDUCE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils im value = pack(ids.x, PRIME) % SECP_P"#; +pub const REDUCE_ED25519: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack +SECP_P=2**255-19 + +value = pack(ids.x, PRIME) % SECP_P"#; + pub const UNSAFE_KECCAK: &str = r#"from eth_hash.auto import keccak data, length = ids.data, ids.length @@ -581,6 +586,11 @@ x = pack(ids.x, PRIME) % SECP_P"#; pub const IS_ZERO_PACK_EXTERNAL_SECP_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack x = pack(ids.x, PRIME) % SECP_P"#; +pub const IS_ZERO_PACK_ED25519: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack +SECP_P=2**255-19 + +x = pack(ids.x, PRIME) % SECP_P"#; + pub const IS_ZERO_ASSIGN_SCOPE_VARS: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P from starkware.python.math_utils import div_mod @@ -590,6 +600,11 @@ pub const IS_ZERO_ASSIGN_SCOPE_VARS_EXTERNAL_SECP: &str = r#"from starkware.pyth value = x_inv = div_mod(1, x, SECP_P)"#; +pub const IS_ZERO_ASSIGN_SCOPE_VARS_ED25519: &str = r#"SECP_P=2**255-19 +from starkware.python.math_utils import div_mod + +value = x_inv = div_mod(1, x, SECP_P)"#; + pub const DIV_MOD_N_PACKED_DIVMOD_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack from starkware.python.math_utils import div_mod, safe_div diff --git a/src/hint_processor/builtin_hint_processor/vrf/mod.rs b/src/hint_processor/builtin_hint_processor/vrf/mod.rs index fbf90b7f9e..6521fb6204 100644 --- a/src/hint_processor/builtin_hint_processor/vrf/mod.rs +++ b/src/hint_processor/builtin_hint_processor/vrf/mod.rs @@ -1,2 +1,3 @@ pub mod fq; pub mod inv_mod_p_uint512; +pub mod pack; diff --git a/src/hint_processor/builtin_hint_processor/vrf/pack.rs b/src/hint_processor/builtin_hint_processor/vrf/pack.rs new file mode 100644 index 0000000000..65ebbceac0 --- /dev/null +++ b/src/hint_processor/builtin_hint_processor/vrf/pack.rs @@ -0,0 +1,196 @@ +use num_bigint::BigInt; +use num_integer::Integer; +use num_traits::One; + +use crate::hint_processor::builtin_hint_processor::secp::bigint_utils::BigInt3; +use crate::hint_processor::builtin_hint_processor::secp::secp_utils::SECP_P_V2; +use crate::hint_processor::hint_processor_definition::HintReference; +use crate::math_utils::div_mod; +use crate::serde::deserialize_program::ApTracking; +use crate::stdlib::collections::HashMap; +use crate::stdlib::prelude::String; +use crate::types::exec_scope::ExecutionScopes; +use crate::vm::errors::hint_errors::HintError; +use crate::vm::vm_core::VirtualMachine; + +/// Implements hint: +/// ```python +/// from starkware.cairo.common.cairo_secp.secp_utils import pack +/// SECP_P=2**255-19 +/// +/// x = pack(ids.x, PRIME) % SECP_P +/// ``` +pub fn ed25519_is_zero_pack( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let x = BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?.pack86(); + exec_scopes.insert_value("x", x.mod_floor(&SECP_P_V2)); + exec_scopes.insert_value("SECP_P", SECP_P_V2.clone()); + + Ok(()) +} + +/// Implements hint: +/// ```python +/// from starkware.cairo.common.cairo_secp.secp_utils import pack +/// SECP_P=2**255-19 +/// +/// value = pack(ids.x, PRIME) % SECP_P +/// ``` +pub fn ed25519_reduce( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let x = BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?.pack86(); + exec_scopes.insert_value("value", x.mod_floor(&SECP_P_V2)); + exec_scopes.insert_value("SECP_P", SECP_P_V2.clone()); + + Ok(()) +} + +/// Implements hint: +/// ```python +/// SECP_P=2**255-19 +/// from starkware.python.math_utils import div_mod +/// +/// value = x_inv = div_mod(1, x, SECP_P) +/// ``` +pub fn ed25519_is_zero_assign_scope_vars( + exec_scopes: &mut ExecutionScopes, +) -> Result<(), HintError> { + let x = exec_scopes.get::("x")?; + let x_inv = div_mod(&BigInt::one(), &x, &SECP_P_V2); + exec_scopes.insert_value("x_inv", x_inv.clone()); + exec_scopes.insert_value("value", x_inv); + exec_scopes.insert_value("SECP_P", SECP_P_V2.clone()); + + Ok(()) +} + +#[cfg(test)] +mod test { + use crate::any_box; + use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; + use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; + use crate::hint_processor::builtin_hint_processor::hint_code; + use crate::hint_processor::builtin_hint_processor::secp::secp_utils::SECP_P_V2; + use crate::hint_processor::hint_processor_definition::HintProcessor; + use crate::hint_processor::hint_processor_definition::HintReference; + use crate::stdlib::collections::HashMap; + use crate::types::exec_scope::ExecutionScopes; + use crate::utils::test_utils::*; + use crate::vm::vm_core::VirtualMachine; + use num_bigint::BigInt; + use num_traits::One; + use num_traits::Zero; + + static SECP_P_D0: i128 = 77371252455336267181195245_i128; + static SECP_P_D1: i128 = 77371252455336267181195263_i128; + static SECP_P_D2: i128 = 9671406556917033397649407_i128; + + fn assert_is_zero_pack_ed25519_equals(x_d0: i128, x_d1: i128, x_d2: i128, expected: BigInt) { + let ids_data = non_continuous_ids_data![("x", 0)]; + + let mut vm = vm!(); + vm.run_context.fp = 0; + + vm.segments = segments![((1, 0), x_d0), ((1, 1), x_d1), ((1, 2), x_d2)]; + + let mut exec_scopes = scope![]; + assert!(run_hint!( + vm, + ids_data, + hint_code::IS_ZERO_PACK_ED25519, + &mut exec_scopes + ) + .is_ok()); + + check_scope!( + &exec_scopes, + [("x", expected), ("SECP_P", SECP_P_V2.clone())] + ); + } + + fn assert_reduce_ed25519_equals(x_d0: i128, x_d1: i128, x_d2: i128, expected: BigInt) { + let ids_data = non_continuous_ids_data![("x", 0)]; + + let mut vm = vm!(); + vm.run_context.fp = 0; + + vm.segments = segments![((1, 0), x_d0), ((1, 1), x_d1), ((1, 2), x_d2)]; + + let mut exec_scopes = scope![]; + + assert!(run_hint!(vm, ids_data, hint_code::REDUCE_ED25519, &mut exec_scopes).is_ok()); + + check_scope!( + &exec_scopes, + [("value", expected), ("SECP_P", SECP_P_V2.clone())] + ); + } + + #[test] + fn test_is_zero_pack_ed25519_with_zero() { + assert_is_zero_pack_ed25519_equals(0, 0, 0, BigInt::zero()); + } + + #[test] + fn test_is_zero_pack_ed25519_with_secp_prime_minus_one() { + assert_is_zero_pack_ed25519_equals( + SECP_P_D0 - 1, + SECP_P_D1, + SECP_P_D2, + SECP_P_V2.clone() - 1, + ); + } + + #[test] + fn test_is_zero_pack_ed25519_with_secp_prime() { + assert_is_zero_pack_ed25519_equals(SECP_P_D0, SECP_P_D1, SECP_P_D2, BigInt::zero()); + } + + #[test] + fn test_reduce_ed25519_with_zero() { + assert_reduce_ed25519_equals(0, 0, 0, BigInt::zero()); + } + + #[test] + fn test_reduce_ed25519_with_prime_minus_one() { + assert_reduce_ed25519_equals(SECP_P_D0 - 1, SECP_P_D1, SECP_P_D2, SECP_P_V2.clone() - 1); + } + + #[test] + fn test_reduce_ed25519_with_prime() { + assert_reduce_ed25519_equals(SECP_P_D0, SECP_P_D1, SECP_P_D2, BigInt::zero()); + } + + #[test] + fn test_is_zero_assign_scope_vars_ed25519_with_one() { + let mut vm = vm!(); + vm.run_context.fp = 0; + + let mut exec_scopes = scope![("x", BigInt::one())]; + + assert!(run_hint!( + vm, + HashMap::default(), + hint_code::IS_ZERO_ASSIGN_SCOPE_VARS_ED25519, + &mut exec_scopes + ) + .is_ok()); + + check_scope!( + &exec_scopes, + [ + ("x_inv", BigInt::one()), + ("value", BigInt::one()), + ("SECP_P", SECP_P_V2.clone()) + ] + ); + } +} diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index c0480f8ad2..e9990af76e 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -874,7 +874,7 @@ fn cairo_run_fq_test() { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn cairo_run_ec_negate() { let program_data = include_bytes!("../../cairo_programs/ec_negate.json"); - run_program_simple_with_memory_holes(program_data.as_slice(), 0); + run_program_simple(program_data.as_slice()); } #[test] @@ -944,7 +944,7 @@ fn ec_double_v4() { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn cairo_run_ec_double_slope() { let program_data = include_bytes!("../../cairo_programs/ec_double_slope.json"); - run_program_simple_with_memory_holes(program_data.as_slice(), 0); + run_program_simple(program_data.as_slice()); } #[test] @@ -960,3 +960,10 @@ fn cairo_run_sha256_test() { let program_data = include_bytes!("../../cairo_programs/sha256_test.json"); run_program_simple_with_memory_holes(program_data.as_slice(), 923); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_reduce() { + let program_data = include_bytes!("../../cairo_programs/reduce.json"); + run_program_simple(program_data.as_slice()); +} diff --git a/src/utils.rs b/src/utils.rs index 28a06d431b..210f70840d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -433,7 +433,8 @@ pub mod test_utils { pub(crate) use check_scope; macro_rules! scope { - ( $( ($name: expr, $val: expr)),* ) => { + () => { ExecutionScopes::new() }; + ( $( ($name: expr, $val: expr)),* $(,)? ) => { { let mut exec_scopes = ExecutionScopes::new(); $(