From ce75d9aacb7d59b0e7e4321a00ae75d9454f4781 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Fri, 21 Apr 2023 16:08:23 -0300 Subject: [PATCH] Newhint#20 and Newhint#16: add COMPUTE_SLOPE_SECP256R1 and IMPORT_SECP256R1_P (#1014) * add newhint#20 * add slope_compute program * format * fix hint#16 string * WIP * WIP add SECP_P to exec_scopes * WIP add SECP_P to exec_scope * add newhint#16 and newhint#20 * update changelog * use BigUint for SECP256R1_N and SECP256R1_ALPHA * refactor compute_slope --- CHANGELOG.md | 17 ++++++ cairo_programs/secp256r1_slope.cairo | 60 +++++++++++++++++++ .../builtin_hint_processor_definition.rs | 20 +++++-- .../builtin_hint_processor/hint_code.rs | 12 ++++ .../builtin_hint_processor/secp/ec_utils.rs | 36 ++++++++++- .../builtin_hint_processor/secp/secp_utils.rs | 18 +++++- src/tests/cairo_run_test.rs | 7 +++ 7 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 cairo_programs/secp256r1_slope.cairo diff --git a/CHANGELOG.md b/CHANGELOG.md index 23858c7600..a79eae1236 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -218,6 +218,23 @@ * BugFix: Add missing `\n` character after traceback lines when the filename is missing ("Unknown Location") * 0.11 Support + * Add missing hints [#1014](https://github.com/lambdaclass/cairo-rs/pull/1014): + `BuiltinHintProcessor` now supports the following hints: + ```python + from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P + ``` + and: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import line_slope + + # Compute the slope. + x0 = pack(ids.point0.x, PRIME) + y0 = pack(ids.point0.y, PRIME) + x1 = pack(ids.point1.x, PRIME) + y1 = pack(ids.point1.y, PRIME) + value = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P) + ``` * Add missing hints on cairo_secp lib [#991](https://github.com/lambdaclass/cairo-rs/pull/991): `BuiltinHintProcessor` now supports the following hints: ```python diff --git a/cairo_programs/secp256r1_slope.cairo b/cairo_programs/secp256r1_slope.cairo new file mode 100644 index 0000000000..15bc98a6cd --- /dev/null +++ b/cairo_programs/secp256r1_slope.cairo @@ -0,0 +1,60 @@ +%builtins range_check + +// Source: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/ec.cairo + +from starkware.cairo.common.serialize import serialize_word +from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3 +from starkware.cairo.common.cairo_secp.field import ( + is_zero, + unreduced_mul, + unreduced_sqr, + verify_zero, +) +from starkware.cairo.common.cairo_secp.ec import EcPoint + + +// Returns the slope of the line connecting the two given points. +// The slope is used to compute pt0 + pt1. +// Assumption: pt0.x != pt1.x (mod secp256k1_prime). +func compute_slope{range_check_ptr: felt}(point0: EcPoint, point1: EcPoint) -> (slope: BigInt3) { + %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import line_slope + + # Compute the slope. + x0 = pack(ids.point0.x, PRIME) + y0 = pack(ids.point0.y, PRIME) + x1 = pack(ids.point1.x, PRIME) + y1 = pack(ids.point1.y, PRIME) + value = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P) + %} + let (slope) = nondet_bigint3(); + + return (slope=slope); +} + + +func test_compute_slope{range_check_ptr: felt}() { + let x0 = BigInt3(d0=1, d1=5, d2=10); + let y0 = BigInt3(d0=2, d1=4, d2=20); + + let pt0 = EcPoint(x=x0, y=y0); + + let x1 = BigInt3(d0=3, d1=3, d2=3); + let y1 = BigInt3(d0=3, d1=5, d2=22); + + let pt1 = EcPoint(x=x1, y=y1); + + // Compute slope + let (slope) = compute_slope(pt0, pt1); + + assert slope = slope; + return (); +} + +func main{range_check_ptr: felt}(){ + test_compute_slope(); + + 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 ea49e3b71d..a41c5d8d21 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 @@ -31,9 +31,10 @@ use crate::{ secp::{ bigint_utils::{bigint_to_uint256, hi_max_bitlen, nondet_bigint3}, ec_utils::{ - compute_doubling_slope, compute_slope, di_bit, ec_double_assign_new_x, - ec_double_assign_new_y, ec_mul_inner, ec_negate, fast_ec_add_assign_new_x, - fast_ec_add_assign_new_y, quad_bit, + compute_doubling_slope, compute_slope, compute_slope_secp_p, di_bit, + ec_double_assign_new_x, ec_double_assign_new_y, ec_mul_inner, ec_negate, + fast_ec_add_assign_new_x, fast_ec_add_assign_new_y, import_secp256r1_p, + quad_bit, }, field_utils::{ is_zero_assign_scope_variables, is_zero_assign_scope_variables_external_const, @@ -413,7 +414,7 @@ impl HintProcessor for BuiltinHintProcessor { &hint_data.ap_tracking, "pt", ), - hint_code::COMPUTE_SLOPE => compute_slope( + hint_code::COMPUTE_SLOPE => compute_slope_secp_p( vm, exec_scopes, &hint_data.ids_data, @@ -421,7 +422,16 @@ impl HintProcessor for BuiltinHintProcessor { "point0", "point1", ), - hint_code::COMPUTE_SLOPE_WHITELIST => compute_slope( + hint_code::COMPUTE_SLOPE_SECP256R1 => compute_slope( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + "point0", + "point1", + ), + hint_code::IMPORT_SECP256R1_P => import_secp256r1_p(exec_scopes), + hint_code::COMPUTE_SLOPE_WHITELIST => compute_slope_secp_p( vm, exec_scopes, &hint_data.ids_data, diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 070e18e602..264c428ce8 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -552,6 +552,18 @@ x1 = pack(ids.point1.x, PRIME) y1 = pack(ids.point1.y, PRIME) value = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P)"#; +pub const COMPUTE_SLOPE_SECP256R1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack +from starkware.python.math_utils import line_slope + +# Compute the slope. +x0 = pack(ids.point0.x, PRIME) +y0 = pack(ids.point0.y, PRIME) +x1 = pack(ids.point1.x, PRIME) +y1 = pack(ids.point1.y, PRIME) +value = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P)"#; +pub const IMPORT_SECP256R1_P: &str = + "from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P"; + pub const COMPUTE_SLOPE_WHITELIST: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack 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 4e26682cb3..036f6e1359 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -23,6 +23,8 @@ use num_bigint::BigInt; use num_integer::Integer; use num_traits::{One, ToPrimitive, Zero}; +use super::secp_utils::SECP256R1_P; + #[derive(Debug, PartialEq)] struct EcPoint<'a> { x: BigInt3<'a>, @@ -113,7 +115,7 @@ Implements hint: value = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P) %} */ -pub fn compute_slope( +pub fn compute_slope_secp_p( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, @@ -122,15 +124,35 @@ pub fn compute_slope( point1_alias: &str, ) -> Result<(), HintError> { exec_scopes.insert_value("SECP_P", SECP_P.clone()); + compute_slope( + vm, + exec_scopes, + ids_data, + ap_tracking, + point0_alias, + point1_alias, + ) +} + +pub fn compute_slope( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + point0_alias: &str, + point1_alias: &str, +) -> Result<(), HintError> { //ids.point0 let point0 = EcPoint::from_var_name(point0_alias, vm, ids_data, ap_tracking)?; //ids.point1 let point1 = EcPoint::from_var_name(point1_alias, vm, ids_data, ap_tracking)?; + let secp_p: BigInt = exec_scopes.get("SECP_P")?; + let value = line_slope( &(pack(point0.x), pack(point0.y)), &(pack(point1.x), pack(point1.y)), - &SECP_P, + &secp_p, ); exec_scopes.insert_value("value", value.clone()); exec_scopes.insert_value("slope", value); @@ -273,6 +295,16 @@ pub fn ec_mul_inner( insert_value_into_ap(vm, scalar) } +/* +Implements hint: +%{ +from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P +%} +*/ +pub fn import_secp256r1_p(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { + exec_scopes.insert_value("SECP_P", SECP256R1_P.clone()); + Ok(()) +} /* Implements hint: %{ diff --git a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs index fc0411bc13..32d72e9c2c 100644 --- a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs @@ -39,8 +39,22 @@ lazy_static! { // N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 pub(crate) static ref N: BigInt = BigInt::from_str( "115792089237316195423570985008687907852837564279074904382605163141518161494337" - ) -.unwrap(); + ).unwrap(); +} +// Constants in package "starkware.cairo.common.cairo_secp.secp256r1_utils" +lazy_static! { + //SECP256R1_P = 2**256 - 2**224 + 2**192 + 2**96 - 1 + pub(crate) static ref SECP256R1_P: BigInt = BigInt::from_str( + "115792089210356248762697446949407573530086143415290314195533631308867097853951" + ).unwrap(); + //SECP256R1_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 + pub(crate) static ref SECP256R1_N: BigUint = BigUint::from_str( + "115792089210356248762697446949407573529996955224135760342422259061068512044369" + ).unwrap(); + //SECP256R1_ALPHA = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC + pub(crate) static ref SECP256R1_ALPHA: BigUint = BigUint::from_str( + "115792089210356248762697446949407573530086143415290314195533631308867097853948" + ).unwrap(); } /* diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 406b878ecd..f459764fb8 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -736,6 +736,13 @@ fn efficient_secp256r1_ec() { run_program_simple(program_data.as_slice()); } +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_secp256r1_slope() { + let program_data = include_bytes!("../../cairo_programs/secp256r1_slope.json"); + run_program_simple(program_data.as_slice()); +} + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn garaga() {