From fe781fda111393fb22bcd190e2136ad3a52339e1 Mon Sep 17 00:00:00 2001 From: Mario Rugiero Date: Wed, 19 Apr 2023 11:45:19 -0300 Subject: [PATCH 1/2] perf: bump starknet-crypto version (#1011) The new release includes an optimization for the ECDSA signature verification that makes it take 85% less time. --- CHANGELOG.md | 3 +++ Cargo.lock | 4 ++-- Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c624546ac0..c360bdc47c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ #### Upcoming Changes +* Update `starknet-crypto` to version `0.4.3` [#1011](https://github.com/lambdaclass/cairo-rs/pull/1011) + * The new version carries an 85% reduction in execution time for ECDSA signature verification + * BREAKING CHANGE: refactor `Program` to optimize `Program::clone` [#999](https://github.com/lambdaclass/cairo-rs/pull/999) * Breaking change: many fields that were (unnecessarily) public become hidden by the refactor. diff --git a/Cargo.lock b/Cargo.lock index 0900d49658..5512e91856 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1430,9 +1430,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "starknet-crypto" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d49eb65d58fa98a164ad2cd4d04775885386b83bdad6060f168a38ede77c9aed" +checksum = "8802a516a2556b2ddb9630898d2c8387d928a3e603799b8b2a7dc4018b852c8f" dependencies = [ "crypto-bigint", "hex", diff --git a/Cargo.toml b/Cargo.toml index 007a7ecfd1..e00bd25125 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ hex = { version = "0.4.3", default-features = false } bincode = { version = "2.0.0-rc.2", tag = "v2.0.0-rc.2", git = "https://github.com/bincode-org/bincode.git", default-features = false, features = [ "serde", ] } -starknet-crypto = { version = "0.4.2", default-features = false, features = [ +starknet-crypto = { version = "0.4.3", default-features = false, features = [ "signature-display", "alloc", ] } From a19958960e65f8098ff3592253ffd8610ee469a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <47506558+MegaRedHand@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:44:01 -0300 Subject: [PATCH 2/2] feat(hints): add NewHint#22 (#1003) * Add NewHint#22 * Update changelog * Remove unused import * Use constant and add NOTE comment --- CHANGELOG.md | 10 +++ cairo_programs/is_zero_pack.cairo | 49 ++++++++++ .../builtin_hint_processor_definition.rs | 8 +- .../builtin_hint_processor/hint_code.rs | 4 + .../builtin_hint_processor/secp/ec_utils.rs | 11 ++- .../secp/field_utils.rs | 89 +++++++++++-------- .../builtin_hint_processor/secp/signature.rs | 2 +- src/tests/cairo_run_test.rs | 7 ++ 8 files changed, 137 insertions(+), 43 deletions(-) create mode 100644 cairo_programs/is_zero_pack.cairo diff --git a/CHANGELOG.md b/CHANGELOG.md index c360bdc47c..abfd0a8fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,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 [#1003](https://github.com/lambdaclass/cairo-rs/pull/1003): + + `BuiltinHintProcessor` now supports the following hint: + + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + + x = pack(ids.x, PRIME) % SECP_P + ``` + * Add missing hint on cairo_secp lib [#996](https://github.com/lambdaclass/cairo-rs/pull/996): `BuiltinHintProcessor` now supports the following hint: diff --git a/cairo_programs/is_zero_pack.cairo b/cairo_programs/is_zero_pack.cairo new file mode 100644 index 0000000000..9b79126418 --- /dev/null +++ b/cairo_programs/is_zero_pack.cairo @@ -0,0 +1,49 @@ +%builtins range_check + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3 +from starkware.cairo.common.cairo_secp.field import unreduced_mul, verify_zero + +func is_zero_pack{range_check_ptr}(x: BigInt3) -> (res: felt) { + // just to import SECP_P + %{ + from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack + + value = pack(ids.x, PRIME) % SECP_P + %} + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + + 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); + + let (res: felt) = is_zero_pack(zero); + assert res = 1; + + let one = BigInt3(1, 0, 0); + + let (res: felt) = is_zero_pack(one); + assert res = 0; + + let secp256k1_prime = BigInt3( + 77371252455336262886226991, 77371252455336267181195263, 19342813113834066795298815 + ); + + let (res: felt) = is_zero_pack(secp256k1_prime); + assert res = 1; + + return (); +} + +func main{range_check_ptr}() -> () { + test_is_zero_pack(); + + 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 76db67251d..69e0618f84 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 @@ -35,7 +35,7 @@ use crate::{ }, field_utils::{ is_zero_assign_scope_variables, is_zero_assign_scope_variables_external_const, - is_zero_nondet, is_zero_pack, reduce, verify_zero, + is_zero_nondet, is_zero_pack, is_zero_pack_external_secp, reduce, verify_zero, verify_zero_with_external_const, }, signature::{ @@ -351,6 +351,12 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::IS_ZERO_PACK => { is_zero_pack(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } + hint_code::IS_ZERO_PACK_EXTERNAL_SECP => is_zero_pack_external_secp( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + ), 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::IS_ZERO_ASSIGN_SCOPE_VARS_EXTERNAL_SECP => { diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 2e14f1ca65..b1698eb051 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -436,6 +436,10 @@ pub const IS_ZERO_PACK: &str = r#"from starkware.cairo.common.cairo_secp.secp_ut x = pack(ids.x, PRIME) % SECP_P"#; +pub const IS_ZERO_PACK_EXTERNAL_SECP: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack + +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 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 dc5822d28f..cbcdc37bf0 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,4 @@ use crate::{ - any_box, hint_processor::{ builtin_hint_processor::{ hint_utils::{ @@ -59,7 +58,7 @@ pub fn ec_negate( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + exec_scopes.insert_value("SECP_P", 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)?; @@ -88,7 +87,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())); + exec_scopes.insert_value("SECP_P", SECP_P.clone()); //ids.point let point = EcPoint::from_var_name(point_alias, vm, ids_data, ap_tracking)?; @@ -120,7 +119,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())); + exec_scopes.insert_value("SECP_P", SECP_P.clone()); //ids.point0 let point0 = EcPoint::from_var_name(point0_alias, vm, ids_data, ap_tracking)?; //ids.point1 @@ -154,7 +153,7 @@ pub fn ec_double_assign_new_x( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + exec_scopes.insert_value("SECP_P", SECP_P.clone()); //ids.slope let slope = BigInt3::from_var_name("slope", vm, ids_data, ap_tracking)?; //ids.point @@ -213,7 +212,7 @@ pub fn fast_ec_add_assign_new_x( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + exec_scopes.insert_value("SECP_P", 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 7bbb604700..e321801b9a 100644 --- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -1,13 +1,17 @@ -use crate::any_box; -use crate::stdlib::{collections::HashMap, prelude::*}; - use crate::{ hint_processor::{ - builtin_hint_processor::hint_utils::{insert_value_from_var_name, insert_value_into_ap}, + builtin_hint_processor::{ + hint_utils::{insert_value_from_var_name, insert_value_into_ap}, + secp::{ + bigint_utils::BigInt3, + secp_utils::{pack, SECP_P}, + }, + }, hint_processor_definition::HintReference, }, math_utils::div_mod, serde::deserialize_program::ApTracking, + stdlib::{collections::HashMap, prelude::*}, types::exec_scope::ExecutionScopes, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; @@ -16,9 +20,6 @@ use num_bigint::BigInt; use num_integer::Integer; use num_traits::{One, Zero}; -use super::secp_utils::SECP_P; -use super::{bigint_utils::BigInt3, secp_utils::pack}; - /* Implements hint: %{ @@ -35,7 +36,7 @@ pub fn verify_zero( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + exec_scopes.insert_value("SECP_P", 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() { @@ -85,7 +86,7 @@ pub fn reduce( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + exec_scopes.insert_value("SECP_P", 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(()) @@ -105,13 +106,26 @@ pub fn is_zero_pack( ids_data: &HashMap, ap_tracking: &ApTracking, ) -> Result<(), HintError> { - exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + exec_scopes.insert_value("SECP_P", 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); Ok(()) } +pub fn is_zero_pack_external_secp( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let secp_p = exec_scopes.get_ref("SECP_P")?; + 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); + Ok(()) +} + /* Implements hint: in .cairo program @@ -145,7 +159,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())); + exec_scopes.insert_value("SECP_P", SECP_P.clone()); //Get `x` variable from vm scope let x = exec_scopes.get::("x")?; @@ -370,36 +384,41 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_is_zero_pack_ok() { - let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nx = pack(ids.x, PRIME) % SECP_P"; - let mut vm = vm_with_range_check!(); - - //Initialize fp - vm.run_context.fp = 15; - - //Create hint data - let ids_data = HashMap::from([("x".to_string(), HintReference::new_simple(-5))]); - //Insert ids.x.d0, ids.x.d1, ids.x.d2 into memory - vm.segments = segments![ - ((1, 10), 232113757366008801543585_i128), - ((1, 11), 232113757366008801543585_i128), - ((1, 12), 232113757366008801543585_i128) + let mut exec_scopes = ExecutionScopes::new(); + let hint_codes = vec![ + hint_code::IS_ZERO_PACK, + // NOTE: this one requires IS_ZERO_ASSIGN_SCOPE_VARS to execute first. + hint_code::IS_ZERO_PACK_EXTERNAL_SECP, ]; + for hint_code in hint_codes { + let mut vm = vm_with_range_check!(); - let mut exec_scopes = ExecutionScopes::new(); + //Initialize fp + vm.run_context.fp = 15; - //Execute the hint - assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); + //Create hint data + let ids_data = HashMap::from([("x".to_string(), HintReference::new_simple(-5))]); + //Insert ids.x.d0, ids.x.d1, ids.x.d2 into memory + vm.segments = segments![ + ((1, 10), 232113757366008801543585_i128), + ((1, 11), 232113757366008801543585_i128), + ((1, 12), 232113757366008801543585_i128) + ]; - //Check 'x' is defined in the vm scope - check_scope!( - &exec_scopes, - [( - "x", - bigint_str!( + //Execute the hint + assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); + + //Check 'x' is defined in the vm scope + check_scope!( + &exec_scopes, + [( + "x", + bigint_str!( "1389505070847794345082847096905107459917719328738389700703952672838091425185" ) - )] - ); + )] + ); + } } #[test] diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 54b13b0bf4..c4086fc99e 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -109,7 +109,7 @@ pub fn get_point_from_x( ap_tracking: &ApTracking, constants: &HashMap, ) -> Result<(), HintError> { - exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone())); + exec_scopes.insert_value("SECP_P", SECP_P.clone()); #[allow(deprecated)] let beta = constants .get(BETA) diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 4e42fe4b4b..216b2b8597 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1343,3 +1343,10 @@ fn cairo_run_is_zero() { let program_data = include_bytes!("../../cairo_programs/is_zero.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_is_zero_pack() { + let program_data = include_bytes!("../../cairo_programs/is_zero_pack.json"); + run_program_simple(program_data.as_slice()); +}