From 696e0f912ab948245b754e25e3a91eee8901e2a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Fri, 14 Apr 2023 17:30:16 -0300 Subject: [PATCH 01/13] Add NewHint#26 --- cairo_programs/ed25519_field.cairo | 54 +++++++++++++++++++ .../builtin_hint_processor_definition.rs | 2 +- .../builtin_hint_processor/hint_code.rs | 6 +++ .../secp/field_utils.rs | 53 ++++++++---------- 4 files changed, 82 insertions(+), 33 deletions(-) diff --git a/cairo_programs/ed25519_field.cairo b/cairo_programs/ed25519_field.cairo index 955de5f811..95c6db2b65 100644 --- a/cairo_programs/ed25519_field.cairo +++ b/cairo_programs/ed25519_field.cairo @@ -51,6 +51,51 @@ func verify_zero{range_check_ptr}(val: UnreducedBigInt3) { return (); } +// Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/ec.cairo#L106 +func verify_zero_alt{range_check_ptr}(val: UnreducedBigInt3) { + let x = val; + // Used just to import pack in scope + %{ + from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack + + value = pack(ids.x, PRIME) % SECP_P + %} + nondet_bigint3(); + + let q = [ap]; + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + + 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++; + + tempvar r1 = (val.d0 + q * SECP_REM) / BASE; + assert [range_check_ptr + 1] = r1 + 2 ** 127; + // This implies r1 * BASE = val.d0 + q * SECP_REM (as integers). + + tempvar r2 = (val.d1 + r1) / BASE; + assert [range_check_ptr + 2] = r2 + 2 ** 127; + // This implies r2 * BASE = val.d1 + r1 (as integers). + // Therefore, r2 * BASE**2 = val.d1 * BASE + r1 * BASE. + + assert val.d2 = q * (BASE / 4) - r2; + // This implies 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). + + let range_check_ptr = range_check_ptr + 3; + return (); +} + func test_verify_zero{range_check_ptr: felt}() { let val = UnreducedBigInt3(0, 0, 0); @@ -59,8 +104,17 @@ func test_verify_zero{range_check_ptr: felt}() { return (); } +func test_verify_zero_alt{range_check_ptr: felt}() { + let val = UnreducedBigInt3(0, 0, 0); + + verify_zero_alt(val); + + return (); +} + func main{range_check_ptr: felt}() { test_verify_zero(); + test_verify_zero_alt(); 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 58fc12429d..d97bbc37c9 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 @@ -249,7 +249,7 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::BLAKE2S_COMPUTE => { compute_blake2s(vm, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 => { + hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 | hint_code::VERIFY_ZERO_V3 => { verify_zero(vm, &hint_data.ids_data, &hint_data.ap_tracking) } hint_code::NONDET_BIGINT3 => { diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 1b6e765eb2..43ecf97c4e 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -392,6 +392,12 @@ 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"#; +pub const VERIFY_ZERO_V3: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack + +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"#; + pub const REDUCE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack value = pack(ids.x, PRIME) % SECP_P"#; diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs index 9ee1a3598b..57d4c1c654 100644 --- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -154,38 +154,27 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_verify_zero_ok() { - let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME"; - let mut vm = vm_with_range_check!(); - //Initialize run_context - run_context!(vm, 0, 9, 9); - //Create hint data - let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)]; - vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)]; - //Execute the hint - assert_matches!( - run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()), - Ok(()) - ); - //Check hint memory inserts - //ids.q - check_memory![vm.segments.memory, ((1, 9), 0)]; - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn run_verify_zero_without_pack_ok() { - let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME"; - let mut vm = vm_with_range_check!(); - //Initialize run_context - run_context!(vm, 0, 9, 9); - //Create hint data - let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)]; - vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)]; - //Execute the hint - assert!(run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()).is_ok()); - //Check hint memory inserts - //ids.q - check_memory![vm.segments.memory, ((1, 9), 0)]; + let hint_codes = vec![ + "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME", + "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME", + "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME", + ]; + for hint_code in hint_codes { + let mut vm = vm_with_range_check!(); + //Initialize run_context + run_context!(vm, 0, 9, 9); + //Create hint data + let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)]; + vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)]; + //Execute the hint + assert_matches!( + run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()), + Ok(()) + ); + //Check hint memory inserts + //ids.q + check_memory![vm.segments.memory, ((1, 9), 0)]; + } } #[test] From b384db90372c75f275161f59430e6f1b39e8b715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Fri, 14 Apr 2023 17:36:05 -0300 Subject: [PATCH 02/13] Update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b23d95862..f457ed627a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,16 @@ * Added dynamic layout [#879](https://github.com/lambdaclass/cairo-rs/pull/879) * `get_segment_size` was exposed [#934](https://github.com/lambdaclass/cairo-rs/pull/934) +* Add missing hint on cairo_secp lib [#992](https://github.com/lambdaclass/cairo-rs/pull/992): + + `BuiltinHintProcessor` now supports the following hint: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + + 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 + ``` * Add missing hint on cairo_secp lib [#990](https://github.com/lambdaclass/cairo-rs/pull/990): From 5ed4c05587c6de2bc2c363e2a22867f62d66dd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 11:11:46 -0300 Subject: [PATCH 03/13] Change assert_matches for assert + is_ok --- .../builtin_hint_processor/secp/field_utils.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs index 57d4c1c654..9a80da4aaf 100644 --- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -167,10 +167,7 @@ mod tests { let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)]; vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)]; //Execute the hint - assert_matches!( - run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()), - Ok(()) - ); + assert!(run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()).is_ok()); //Check hint memory inserts //ids.q check_memory![vm.segments.memory, ((1, 9), 0)]; From 67477d98ed9f1a55104c7ca8154988092ed12e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 15:06:42 -0300 Subject: [PATCH 04/13] Get and insert SECP_P from scope where applicable --- cairo_programs/ed25519_field.cairo | 2 +- .../builtin_hint_processor_definition.rs | 26 +++++---- .../builtin_hint_processor/hint_code.rs | 2 +- .../builtin_hint_processor/secp/ec_utils.rs | 8 ++- .../secp/field_utils.rs | 57 ++++++++++++++++++- .../builtin_hint_processor/secp/signature.rs | 2 + 6 files changed, 82 insertions(+), 15 deletions(-) diff --git a/cairo_programs/ed25519_field.cairo b/cairo_programs/ed25519_field.cairo index 95c6db2b65..cf5ddb06bd 100644 --- a/cairo_programs/ed25519_field.cairo +++ b/cairo_programs/ed25519_field.cairo @@ -54,7 +54,7 @@ func verify_zero{range_check_ptr}(val: UnreducedBigInt3) { // Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/ec.cairo#L106 func verify_zero_alt{range_check_ptr}(val: UnreducedBigInt3) { let x = val; - // Used just to import pack in scope + // Used just to import SECP_P in scope %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack 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 d97bbc37c9..267c102085 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 @@ -1,5 +1,3 @@ -use crate::stdlib::{any::Any, collections::HashMap, prelude::*, rc::Rc}; - use crate::{ hint_processor::{ builtin_hint_processor::{ @@ -14,6 +12,7 @@ use crate::{ default_dict_new, dict_new, dict_read, dict_squash_copy_dict, dict_squash_update_ptr, dict_update, dict_write, }, + ec_utils::{chained_ec_op_random_ec_point_hint, random_ec_point_hint, recover_y_hint}, find_element_hint::{find_element, search_sorted_lower}, hint_code, keccak_utils::{ @@ -36,7 +35,7 @@ use crate::{ }, field_utils::{ is_zero_assign_scope_variables, is_zero_nondet, is_zero_pack, reduce, - verify_zero, + verify_zero, verify_zero_with_external_const, }, signature::{div_mod_n_packed_divmod, div_mod_n_safe_div, get_point_from_x}, }, @@ -55,6 +54,10 @@ use crate::{ split_64, uint256_add, uint256_mul_div_mod, uint256_signed_nn, uint256_sqrt, uint256_unsigned_div_rem, }, + uint384::{ + add_no_uint384_check, uint384_signed_nn, uint384_split_128, uint384_sqrt, + uint384_unsigned_div_rem, uint384_unsigned_div_rem_expanded, + }, usort::{ usort_body, usort_enter_scope, verify_multiplicity_assert, verify_multiplicity_body, verify_usort, @@ -63,6 +66,7 @@ use crate::{ hint_processor_definition::{HintProcessor, HintReference}, }, serde::deserialize_program::ApTracking, + stdlib::{any::Any, collections::HashMap, prelude::*, rc::Rc}, types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; @@ -71,12 +75,6 @@ use felt::Felt252; #[cfg(feature = "skip_next_instruction_hint")] use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction; -use super::ec_utils::{chained_ec_op_random_ec_point_hint, random_ec_point_hint, recover_y_hint}; -use super::uint384::{ - add_no_uint384_check, uint384_signed_nn, uint384_split_128, uint384_sqrt, - uint384_unsigned_div_rem, uint384_unsigned_div_rem_expanded, -}; - pub struct HintProcessorData { pub code: String, pub ap_tracking: ApTracking, @@ -249,9 +247,15 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::BLAKE2S_COMPUTE => { compute_blake2s(vm, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 | hint_code::VERIFY_ZERO_V3 => { - verify_zero(vm, &hint_data.ids_data, &hint_data.ap_tracking) + hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 => { + verify_zero(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } + hint_code::VERIFY_ZERO_EXTERNAL_SECP => verify_zero_with_external_const( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + ), hint_code::NONDET_BIGINT3 => { nondet_bigint3(vm, exec_scopes, &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 43ecf97c4e..ae32aef132 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -392,7 +392,7 @@ 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"#; -pub const VERIFY_ZERO_V3: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack +pub const VERIFY_ZERO_EXTERNAL_SECP: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack 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}." diff --git a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs index 049c721d54..dc5822d28f 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -1,5 +1,5 @@ -use crate::stdlib::{collections::HashMap, ops::BitAnd, prelude::*}; use crate::{ + any_box, hint_processor::{ builtin_hint_processor::{ hint_utils::{ @@ -11,6 +11,7 @@ use crate::{ }, math_utils::{ec_double_slope, line_slope}, serde::deserialize_program::ApTracking, + stdlib::{collections::HashMap, ops::BitAnd, prelude::*}, types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; @@ -58,6 +59,7 @@ pub fn ec_negate( ids_data: &HashMap<String, HintReference>, ap_tracking: &ApTracking, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); //ids.point let point_y = (get_relocatable_from_var_name("point", vm, ids_data, ap_tracking)? + 3i32)?; let y_bigint3 = BigInt3::from_base_addr(point_y, "point.y", vm)?; @@ -86,6 +88,7 @@ pub fn compute_doubling_slope( ap_tracking: &ApTracking, point_alias: &str, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); //ids.point let point = EcPoint::from_var_name(point_alias, vm, ids_data, ap_tracking)?; @@ -117,6 +120,7 @@ pub fn compute_slope( point0_alias: &str, point1_alias: &str, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); //ids.point0 let point0 = EcPoint::from_var_name(point0_alias, vm, ids_data, ap_tracking)?; //ids.point1 @@ -150,6 +154,7 @@ pub fn ec_double_assign_new_x( ids_data: &HashMap<String, HintReference>, ap_tracking: &ApTracking, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); //ids.slope let slope = BigInt3::from_var_name("slope", vm, ids_data, ap_tracking)?; //ids.point @@ -208,6 +213,7 @@ pub fn fast_ec_add_assign_new_x( ids_data: &HashMap<String, HintReference>, ap_tracking: &ApTracking, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); //ids.slope let slope = BigInt3::from_var_name("slope", vm, ids_data, ap_tracking)?; //ids.point0 diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs index 9a80da4aaf..c9beb022ff 100644 --- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -1,3 +1,4 @@ +use crate::any_box; use crate::stdlib::{collections::HashMap, prelude::*}; use crate::{ @@ -30,9 +31,11 @@ Implements hint: */ pub fn verify_zero( vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, ids_data: &HashMap<String, HintReference>, ap_tracking: &ApTracking, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); let val = pack(BigInt3::from_var_name("val", vm, ids_data, ap_tracking)?); let (q, r) = val.div_rem(&SECP_P); if !r.is_zero() { @@ -42,6 +45,32 @@ pub fn verify_zero( insert_value_from_var_name("q", Felt252::new(q), vm, ids_data, ap_tracking) } +/* +Implements hint: +%{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + + 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 +%} +*/ +pub fn verify_zero_with_external_const( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap<String, HintReference>, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let secp_p = exec_scopes.get_ref("SECP_P")?; + let val = pack(BigInt3::from_var_name("val", vm, ids_data, ap_tracking)?); + let (q, r) = val.div_rem(&secp_p); + if !r.is_zero() { + return Err(HintError::SecpVerifyZero(val)); + } + + insert_value_from_var_name("q", Felt252::new(q), vm, ids_data, ap_tracking) +} + /* Implements hint: %{ @@ -56,6 +85,7 @@ pub fn reduce( ids_data: &HashMap<String, HintReference>, ap_tracking: &ApTracking, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); let value = pack(BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?); exec_scopes.insert_value("value", value.mod_floor(&SECP_P)); Ok(()) @@ -75,6 +105,8 @@ pub fn is_zero_pack( ids_data: &HashMap<String, HintReference>, ap_tracking: &ApTracking, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + let x_packed = pack(BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?); let x = x_packed.mod_floor(&SECP_P); exec_scopes.insert_value("x", x); @@ -114,6 +146,7 @@ Implements hint: %} */ pub fn is_zero_assign_scope_variables(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); //Get `x` variable from vm scope let x = exec_scopes.get::<BigInt>("x")?; @@ -157,7 +190,6 @@ mod tests { let hint_codes = vec![ "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME", "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME", - "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME", ]; for hint_code in hint_codes { let mut vm = vm_with_range_check!(); @@ -174,6 +206,29 @@ mod tests { } } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_verify_zero_with_external_const_ok() { + let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME"; + let mut vm = vm_with_range_check!(); + //Initialize run_context + run_context!(vm, 0, 9, 9); + //Create hint data + let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)]; + vm.segments = segments![((1, 4), 55), ((1, 5), 0), ((1, 6), 0)]; + + let new_secp_p = 55; + + let mut exec_scopes = ExecutionScopes::new(); + exec_scopes.assign_or_update_variable("SECP_P", any_box!(bigint!(new_secp_p))); + + //Execute the hint + assert!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes).is_ok()); + //Check hint memory inserts + //ids.q + check_memory![vm.segments.memory, ((1, 9), 1)]; + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_verify_zero_error() { diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 1f65e56e85..224b9dd171 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -1,3 +1,4 @@ +use crate::any_box; use crate::stdlib::{collections::HashMap, ops::Shr, prelude::*}; use crate::{ @@ -83,6 +84,7 @@ pub fn get_point_from_x( ap_tracking: &ApTracking, constants: &HashMap<String, Felt252>, ) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); #[allow(deprecated)] let beta = constants .get(BETA) From 3b7b8c0fd8173e8ffd01fc933e1b9d5d3d7c1f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 15:28:14 -0300 Subject: [PATCH 05/13] Add NewHint#25 --- cairo_programs/div_mod_n.cairo | 117 ++++++++++++++++++ .../builtin_hint_processor_definition.rs | 5 +- .../builtin_hint_processor/hint_code.rs | 3 + .../builtin_hint_processor/secp/signature.rs | 21 ++-- src/tests/cairo_run_test.rs | 7 ++ 5 files changed, 142 insertions(+), 11 deletions(-) create mode 100644 cairo_programs/div_mod_n.cairo diff --git a/cairo_programs/div_mod_n.cairo b/cairo_programs/div_mod_n.cairo new file mode 100644 index 0000000000..13a16d0e2e --- /dev/null +++ b/cairo_programs/div_mod_n.cairo @@ -0,0 +1,117 @@ +%builtins range_check + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul +from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2 + +// Computes a * b^(-1) modulo the size of the elliptic curve (N). +// +// Prover assumptions: +// * All the limbs of a are in the range (-2 ** 210.99, 2 ** 210.99). +// * All the limbs of b are in the range (-2 ** 124.99, 2 ** 124.99). +// * b is in the range [0, 2 ** 256). +// +// Soundness assumptions: +// * The limbs of a are in the range (-2 ** 249, 2 ** 249). +// * The limbs of b are in the range (-2 ** 159.83, 2 ** 159.83). +func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { + // just used to import N + %{ + from starkware.cairo.common.cairo_secp.secp_utils import N, pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + %} + let (res) = nondet_bigint3(); + + %{ value = k_plus_one = safe_div(res * b - a, N) + 1 %} + let (k_plus_one) = nondet_bigint3(); + let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2); + + let (res_b) = bigint_mul(res, b); + let n = BigInt3(N0, N1, N2); + let (k_n) = bigint_mul(k, n); + + // We should now have res_b = k_n + a. Since the numbers are in unreduced form, + // we should handle the carry. + + tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE; + assert [range_check_ptr + 0] = carry1 + 2 ** 127; + + tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE; + assert [range_check_ptr + 1] = carry2 + 2 ** 127; + + tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE; + assert [range_check_ptr + 2] = carry3 + 2 ** 127; + + tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE; + assert [range_check_ptr + 3] = carry4 + 2 ** 127; + + assert res_b.d4 - k_n.d4 + carry4 = 0; + + let range_check_ptr = range_check_ptr + 4; + + return (res=res); +} + +func div_mod_n_alt{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + %} + let (res) = nondet_bigint3(); + + %{ value = k_plus_one = safe_div(res * b - a, N) + 1 %} + let (k_plus_one) = nondet_bigint3(); + let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2); + + let (res_b) = bigint_mul(res, b); + let n = BigInt3(N0, N1, N2); + let (k_n) = bigint_mul(k, n); + + tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE; + assert [range_check_ptr + 0] = carry1 + 2 ** 127; + + tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE; + assert [range_check_ptr + 1] = carry2 + 2 ** 127; + + tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE; + assert [range_check_ptr + 2] = carry3 + 2 ** 127; + + tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE; + assert [range_check_ptr + 3] = carry4 + 2 ** 127; + + assert res_b.d4 - k_n.d4 + carry4 = 0; + + let range_check_ptr = range_check_ptr + 4; + + return (res=res); +} + +func test_div_mod_n{range_check_ptr: felt}() { + let a: BigInt3 = BigInt3(100, 99, 98); + let b: BigInt3 = BigInt3(10, 9, 8); + + let (res) = div_mod_n(a, b); + + assert res = BigInt3( + 3413472211745629263979533, 17305268010345238170172332, 11991751872105858217578135 + ); + + // let (res_alt) = div_mod_n_alt(a, b); + + // assert res_alt = res; + + return (); +} + +func main{range_check_ptr: felt}() { + test_div_mod_n(); + + 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 7383370e99..3c1f9edbf8 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 @@ -356,7 +356,8 @@ impl HintProcessor for BuiltinHintProcessor { &hint_data.ids_data, &hint_data.ap_tracking, ), - hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b"), + hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b", 0), + hint_code::DIV_MOD_N_SAFE_DIV_PLUS_ONE => div_mod_n_safe_div(exec_scopes, "a", "b", 1), hint_code::GET_POINT_FROM_X => get_point_from_x( vm, exec_scopes, @@ -493,7 +494,7 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::PACK_MODN_DIV_MODN => { pack_modn_div_modn(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::XS_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "x", "s"), + hint_code::XS_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "x", "s", 0), hint_code::UINT384_UNSIGNED_DIV_REM => { uint384_unsigned_div_rem(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 6131ead533..c71dfc2ea9 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -449,6 +449,9 @@ value = res = div_mod(a, b, N)"#; pub const DIV_MOD_N_SAFE_DIV: &str = r#"value = k = safe_div(res * b - a, N)"#; +pub const DIV_MOD_N_SAFE_DIV_PLUS_ONE: &str = + r#"value = k_plus_one = safe_div(res * b - a, N) + 1"#; + pub const GET_POINT_FROM_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack x_cube_int = pack(ids.x_cube, PRIME) % SECP_P diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 84dd9e5979..41ed5f436e 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -1,7 +1,5 @@ -use crate::any_box; -use crate::stdlib::{collections::HashMap, ops::Shr, prelude::*}; - use crate::{ + any_box, hint_processor::{ builtin_hint_processor::{ hint_utils::get_integer_from_var_name, @@ -11,10 +9,11 @@ use crate::{ }, math_utils::{div_mod, safe_div_bigint}, serde::deserialize_program::ApTracking, + stdlib::{collections::HashMap, ops::Shr, prelude::*}, types::exec_scope::ExecutionScopes, - vm::errors::hint_errors::HintError, - vm::vm_core::VirtualMachine, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; +use core::ops::Add; use felt::Felt252; use num_bigint::BigInt; use num_integer::Integer; @@ -55,12 +54,13 @@ pub fn div_mod_n_safe_div( exec_scopes: &mut ExecutionScopes, a_alias: &str, b_alias: &str, + to_add: u64, ) -> Result<(), HintError> { let a = exec_scopes.get_ref::<BigInt>(a_alias)?; let b = exec_scopes.get_ref::<BigInt>(b_alias)?; let res = exec_scopes.get_ref::<BigInt>("res")?; - let value = safe_div_bigint(&(res * b - a), &N)?; + let value = safe_div_bigint(&(res * b - a), &N)?.add(to_add); exec_scopes.insert_value("value", value); Ok(()) @@ -178,7 +178,9 @@ mod tests { let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)]; let mut exec_scopes = ExecutionScopes::new(); assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); - assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b"), Ok(())); + + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(())); + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 1), Ok(())); } #[test] @@ -193,7 +195,8 @@ mod tests { div_mod_n_safe_div( &mut exec_scopes, "a", - "b" + "b", + 0, ), Err( HintError::Math(MathError::SafeDivFailBigInt( @@ -290,6 +293,6 @@ mod tests { let ids_data = non_continuous_ids_data![("x", -3), ("s", 0)]; let mut exec_scopes = ExecutionScopes::new(); assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); - assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s"), Ok(())); + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s", 0), Ok(())); } } diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 9429dd94ae..465d51e8f0 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1322,3 +1322,10 @@ fn cairo_run_efficient_secp256r1_ec() { let program_data = include_bytes!("../../cairo_programs/efficient_secp256r1_ec.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_div_mod_n() { + let program_data = include_bytes!("../../cairo_programs/div_mod_n.json"); + run_program_simple(program_data.as_slice()); +} From f30f2c9c5499579c7249360f980b4d0810097cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Fri, 14 Apr 2023 19:02:12 -0300 Subject: [PATCH 06/13] Add NewHint#24 --- cairo_programs/div_mod_n.cairo | 7 +++- .../builtin_hint_processor_definition.rs | 14 ++++--- .../builtin_hint_processor/hint_code.rs | 9 ++++- .../builtin_hint_processor/secp/signature.rs | 37 +++++++++++-------- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/cairo_programs/div_mod_n.cairo b/cairo_programs/div_mod_n.cairo index 13a16d0e2e..ed1c4692c8 100644 --- a/cairo_programs/div_mod_n.cairo +++ b/cairo_programs/div_mod_n.cairo @@ -3,6 +3,8 @@ from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2 +// Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/signature.cairo + // Computes a * b^(-1) modulo the size of the elliptic curve (N). // // Prover assumptions: @@ -103,9 +105,10 @@ func test_div_mod_n{range_check_ptr: felt}() { 3413472211745629263979533, 17305268010345238170172332, 11991751872105858217578135 ); - // let (res_alt) = div_mod_n_alt(a, b); + // test alternative hint + let (res_alt) = div_mod_n_alt(a, b); - // assert res_alt = res; + assert res_alt = res; 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 3c1f9edbf8..4f84a1c851 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 @@ -350,12 +350,14 @@ impl HintProcessor for BuiltinHintProcessor { } hint_code::IS_ZERO_NONDET => is_zero_nondet(vm, exec_scopes), hint_code::IS_ZERO_ASSIGN_SCOPE_VARS => is_zero_assign_scope_variables(exec_scopes), - hint_code::DIV_MOD_N_PACKED_DIVMOD => div_mod_n_packed_divmod( - vm, - exec_scopes, - &hint_data.ids_data, - &hint_data.ap_tracking, - ), + hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 | hint_code::DIV_MOD_N_PACKED_DIVMOD_V2 => { + div_mod_n_packed_divmod( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + ) + } hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b", 0), hint_code::DIV_MOD_N_SAFE_DIV_PLUS_ONE => div_mod_n_safe_div(exec_scopes, "a", "b", 1), hint_code::GET_POINT_FROM_X => get_point_from_x( diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index c71dfc2ea9..c4731a4d48 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -440,7 +440,14 @@ from starkware.python.math_utils import div_mod value = x_inv = div_mod(1, x, SECP_P)"#; -pub const DIV_MOD_N_PACKED_DIVMOD: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack +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 + +a = pack(ids.a, PRIME) +b = pack(ids.b, PRIME) +value = res = div_mod(a, b, N)"#; + +pub const DIV_MOD_N_PACKED_DIVMOD_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack from starkware.python.math_utils import div_mod, safe_div a = pack(ids.a, PRIME) diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 41ed5f436e..96929c7295 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -163,24 +163,29 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn safe_div_ok() { - let hint_code = hint_code::DIV_MOD_N_PACKED_DIVMOD; - let mut vm = vm!(); - - vm.segments = segments![ - ((1, 0), 15), - ((1, 1), 3), - ((1, 2), 40), - ((1, 3), 0), - ((1, 4), 10), - ((1, 5), 1) + let hint_codes = vec![ + hint_code::DIV_MOD_N_PACKED_DIVMOD_V1, + hint_code::DIV_MOD_N_PACKED_DIVMOD_V2, ]; - vm.run_context.fp = 3; - let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)]; - let mut exec_scopes = ExecutionScopes::new(); - assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); + for hint_code in hint_codes { + let mut vm = vm!(); + + vm.segments = segments![ + ((1, 0), 15), + ((1, 1), 3), + ((1, 2), 40), + ((1, 3), 0), + ((1, 4), 10), + ((1, 5), 1) + ]; + vm.run_context.fp = 3; + let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)]; + let mut exec_scopes = ExecutionScopes::new(); + assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); - assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(())); - assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 1), Ok(())); + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(())); + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 1), Ok(())); + } } #[test] From ccd5fdf0fdac195489694ca9f350e3928e7b1c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Fri, 14 Apr 2023 19:06:20 -0300 Subject: [PATCH 07/13] Update changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a09ff06ad4..e6e11d7e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,22 @@ * Added dynamic layout [#879](https://github.com/lambdaclass/cairo-rs/pull/879) * `get_segment_size` was exposed [#934](https://github.com/lambdaclass/cairo-rs/pull/934) +* Add missing hints on cairo_secp lib [#994](https://github.com/lambdaclass/cairo-rs/pull/994):: + + `BuiltinHintProcessor` now supports the following hints: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + ``` + + ```python + value = k_plus_one = safe_div(res * b - a, N) + 1 + ``` + * Add missing hint on cairo_secp lib [#992](https://github.com/lambdaclass/cairo-rs/pull/992): `BuiltinHintProcessor` now supports the following hint: From 72070025295bc408628088a67a5355c286824c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 15:33:29 -0300 Subject: [PATCH 08/13] Appease clippy --- src/hint_processor/builtin_hint_processor/secp/field_utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs index c9beb022ff..cf9afb1d68 100644 --- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -63,7 +63,7 @@ pub fn verify_zero_with_external_const( ) -> Result<(), HintError> { let secp_p = exec_scopes.get_ref("SECP_P")?; let val = pack(BigInt3::from_var_name("val", vm, ids_data, ap_tracking)?); - let (q, r) = val.div_rem(&secp_p); + let (q, r) = val.div_rem(secp_p); if !r.is_zero() { return Err(HintError::SecpVerifyZero(val)); } From 6f25f00151ef87a41d50d837c814a905cfaaeb9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 15:36:47 -0300 Subject: [PATCH 09/13] Rename hint codes --- .../builtin_hint_processor_definition.rs | 15 +++++++-------- .../builtin_hint_processor/hint_code.rs | 2 +- .../builtin_hint_processor/secp/signature.rs | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) 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 4f84a1c851..b1b6a114b8 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 @@ -350,14 +350,13 @@ impl HintProcessor for BuiltinHintProcessor { } hint_code::IS_ZERO_NONDET => is_zero_nondet(vm, exec_scopes), hint_code::IS_ZERO_ASSIGN_SCOPE_VARS => is_zero_assign_scope_variables(exec_scopes), - hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 | hint_code::DIV_MOD_N_PACKED_DIVMOD_V2 => { - div_mod_n_packed_divmod( - vm, - exec_scopes, - &hint_data.ids_data, - &hint_data.ap_tracking, - ) - } + hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 + | hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N => div_mod_n_packed_divmod( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + ), hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b", 0), hint_code::DIV_MOD_N_SAFE_DIV_PLUS_ONE => div_mod_n_safe_div(exec_scopes, "a", "b", 1), hint_code::GET_POINT_FROM_X => get_point_from_x( diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index c4731a4d48..872a6ec5cf 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -447,7 +447,7 @@ a = pack(ids.a, PRIME) b = pack(ids.b, PRIME) value = res = div_mod(a, b, N)"#; -pub const DIV_MOD_N_PACKED_DIVMOD_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack +pub const DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack from starkware.python.math_utils import div_mod, safe_div a = pack(ids.a, PRIME) diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 96929c7295..403def8ba1 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -165,7 +165,7 @@ mod tests { fn safe_div_ok() { let hint_codes = vec![ hint_code::DIV_MOD_N_PACKED_DIVMOD_V1, - hint_code::DIV_MOD_N_PACKED_DIVMOD_V2, + hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N, ]; for hint_code in hint_codes { let mut vm = vm!(); From 6006cbc884179bbf43fb7a727c19d9a5010df193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 15:43:11 -0300 Subject: [PATCH 10/13] Get or insert N from scope --- .../builtin_hint_processor_definition.rs | 11 ++++++-- .../builtin_hint_processor/secp/signature.rs | 25 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) 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 b1b6a114b8..9a68a9cf96 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 @@ -78,6 +78,8 @@ use felt::Felt252; #[cfg(feature = "skip_next_instruction_hint")] use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction; +use super::secp::signature::div_mod_n_packed_external_n; + pub struct HintProcessorData { pub code: String, pub ap_tracking: ApTracking, @@ -350,8 +352,13 @@ impl HintProcessor for BuiltinHintProcessor { } hint_code::IS_ZERO_NONDET => is_zero_nondet(vm, exec_scopes), hint_code::IS_ZERO_ASSIGN_SCOPE_VARS => is_zero_assign_scope_variables(exec_scopes), - hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 - | hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N => div_mod_n_packed_divmod( + hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 => div_mod_n_packed_divmod( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + ), + hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N => div_mod_n_packed_external_n( vm, exec_scopes, &hint_data.ids_data, diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 403def8ba1..4b8af9a0dd 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -31,16 +31,17 @@ a = pack(ids.a, PRIME) b = pack(ids.b, PRIME) value = res = div_mod(a, b, N) */ -pub fn div_mod_n_packed_divmod( +pub fn div_mod_n_packed( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, ids_data: &HashMap<String, HintReference>, ap_tracking: &ApTracking, + n: &BigInt, ) -> Result<(), HintError> { let a = pack(BigInt3::from_var_name("a", vm, ids_data, ap_tracking)?); let b = pack(BigInt3::from_var_name("b", vm, ids_data, ap_tracking)?); - let value = div_mod(&a, &b, &N); + let value = div_mod(&a, &b, n); exec_scopes.insert_value("a", a); exec_scopes.insert_value("b", b); exec_scopes.insert_value("value", value.clone()); @@ -48,6 +49,26 @@ pub fn div_mod_n_packed_divmod( Ok(()) } +pub fn div_mod_n_packed_divmod( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap<String, HintReference>, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("N", any_box!(N.clone())); + div_mod_n_packed(vm, exec_scopes, ids_data, ap_tracking, &N) +} + +pub fn div_mod_n_packed_external_n( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap<String, HintReference>, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let n = exec_scopes.get::<BigInt>("N")?; + div_mod_n_packed(vm, exec_scopes, ids_data, ap_tracking, &n) +} + // Implements hint: // value = k = safe_div(res * b - a, N) pub fn div_mod_n_safe_div( From e8afdabe7b93c6f3746a7f43a155a1a81bddcf22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 15:45:24 -0300 Subject: [PATCH 11/13] Change test contract --- cairo_programs/div_mod_n.cairo | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cairo_programs/div_mod_n.cairo b/cairo_programs/div_mod_n.cairo index ed1c4692c8..4dbe3c8290 100644 --- a/cairo_programs/div_mod_n.cairo +++ b/cairo_programs/div_mod_n.cairo @@ -16,7 +16,6 @@ from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2 // * The limbs of a are in the range (-2 ** 249, 2 ** 249). // * The limbs of b are in the range (-2 ** 159.83, 2 ** 159.83). func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { - // just used to import N %{ from starkware.cairo.common.cairo_secp.secp_utils import N, pack from starkware.python.math_utils import div_mod, safe_div @@ -58,6 +57,16 @@ func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { } func div_mod_n_alt{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { + // just used to import N + %{ + from starkware.cairo.common.cairo_secp.secp_utils import N, pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + %} + %{ from starkware.cairo.common.cairo_secp.secp_utils import pack from starkware.python.math_utils import div_mod, safe_div From e82a5bd294588ba42dd5ae7e3db5494fbf032abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 16:07:32 -0300 Subject: [PATCH 12/13] Fix test --- src/hint_processor/builtin_hint_processor/secp/signature.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 4b8af9a0dd..24789e256c 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -184,6 +184,10 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn safe_div_ok() { + // "import N" + let mut exec_scopes = ExecutionScopes::new(); + exec_scopes.assign_or_update_variable("N", any_box!(N.clone())); + let hint_codes = vec![ hint_code::DIV_MOD_N_PACKED_DIVMOD_V1, hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N, From 79169989164de0d8e9e6c5d42253a61a2373932c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com> Date: Mon, 17 Apr 2023 16:09:08 -0300 Subject: [PATCH 13/13] Fix test (for real this time) --- src/hint_processor/builtin_hint_processor/secp/signature.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 24789e256c..54b13b0bf4 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -205,7 +205,7 @@ mod tests { ]; vm.run_context.fp = 3; let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)]; - let mut exec_scopes = ExecutionScopes::new(); + assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(()));