diff --git a/CHANGELOG.md b/CHANGELOG.md index ab458d240a..3e0f90c404 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ #### Upcoming Changes +* Add missing hint on vrf.json lib [#1052](https://github.com/lambdaclass/cairo-rs/pull/1052): + + `BuiltinHintProcessor` now supports the following hint: + + ```python + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P = 2**255-19 + + slope = pack(ids.slope, PRIME) + x0 = pack(ids.point0.x, PRIME) + x1 = pack(ids.point1.x, PRIME) + y0 = pack(ids.point0.y, PRIME) + + value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P + ``` + Add missing hint on vrf.json lib [#1053](https://github.com/lambdaclass/cairo-rs/pull/1053): `BuiltinHintProcessor` now supports the following hint: diff --git a/cairo_programs/fast_ec_add_v2.cairo b/cairo_programs/fast_ec_add_v2.cairo new file mode 100644 index 0000000000..d67dc708e4 --- /dev/null +++ b/cairo_programs/fast_ec_add_v2.cairo @@ -0,0 +1,101 @@ + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, UnreducedBigInt3 +from starkware.cairo.common.cairo_secp.field import ( + is_zero, + unreduced_sqr, +) +from cairo_programs.compute_slope_v2 import compute_slope, EcPoint, verify_zero, unreduced_mul +// Computes the addition of two given points. +// +// Arguments: +// point0, point1 - the points to operate on. +// +// Returns: +// res - the sum of the two points (point0 + point1). +// +// Assumption: point0.x != point1.x (however, point0 = point1 = 0 is allowed). +// Note that this means that the function cannot be used if point0 = point1 != 0 +// (use ec_double() in this case) or point0 = -point1 != 0 (the result is 0 in this case). +func fast_ec_add{range_check_ptr}(point0: EcPoint, point1: EcPoint) -> (res: EcPoint) { + // Check whether point0 is the zero point. + if (point0.x.d0 == 0) { + if (point0.x.d1 == 0) { + if (point0.x.d2 == 0) { + return (res=point1); + } + } + } + + // Check whether point1 is the zero point. + if (point1.x.d0 == 0) { + if (point1.x.d1 == 0) { + if (point1.x.d2 == 0) { + return (res=point0); + } + } + } + + let (slope: BigInt3) = compute_slope(point0, point1); + let (slope_sqr: UnreducedBigInt3) = unreduced_sqr(slope); + + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P = 2**255-19 + + slope = pack(ids.slope, PRIME) + x0 = pack(ids.point0.x, PRIME) + x1 = pack(ids.point1.x, PRIME) + y0 = pack(ids.point0.y, PRIME) + + value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P + %} + let (new_x: BigInt3) = nondet_bigint3(); + + %{ value = new_y = (slope * (x0 - new_x) - y0) % SECP_P %} + let (new_y: BigInt3) = nondet_bigint3(); + + verify_zero( + UnreducedBigInt3( + d0=slope_sqr.d0 - new_x.d0 - point0.x.d0 - point1.x.d0, + d1=slope_sqr.d1 - new_x.d1 - point0.x.d1 - point1.x.d1, + d2=slope_sqr.d2 - new_x.d2 - point0.x.d2 - point1.x.d2, + ), + ); + + let (x_diff_slope: UnreducedBigInt3) = unreduced_mul( + BigInt3(d0=point0.x.d0 - new_x.d0, d1=point0.x.d1 - new_x.d1, d2=point0.x.d2 - new_x.d2), + slope, + ); + + verify_zero( + UnreducedBigInt3( + d0=x_diff_slope.d0 - point0.y.d0 - new_y.d0, + d1=x_diff_slope.d1 - point0.y.d1 - new_y.d1, + d2=x_diff_slope.d2 - point0.y.d2 - new_y.d2, + ), + ); + + return (res=EcPoint(new_x, new_y)); +} + +func main{range_check_ptr}() { + let x_0 = BigInt3(1,2,3); + let y_0 = BigInt3(4,5,6); + let p_0 = EcPoint(x_0, y_0); + + let x_1 = BigInt3(7,8,9); + let y_1 = BigInt3(10,11,12); + let p_1 = EcPoint(x_1, y_1); + + let (r) = fast_ec_add(p_0, p_1); + + assert r.x.d0 = 77371252455336267181195238; + assert r.x.d1 = 77371252455336267181195253; + assert r.x.d2 = 9671406556917033397649395; + + assert r.y.d0 = 4; + assert r.y.d1 = 7; + assert r.y.d2 = 9; + + 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 000a125433..c3c9a2bcea 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 @@ -6,8 +6,8 @@ use super::{ field_arithmetic::{u256_get_square_root, u384_get_square_root, uint384_div}, secp::{ ec_utils::{ - compute_slope_and_assing_secp_p, ec_double_assign_new_y, ec_negate_embedded_secp_p, - ec_negate_import_secp_p, + compute_slope_and_assing_secp_p, ec_double_assign_new_y, ec_mul_inner, + ec_negate_embedded_secp_p, ec_negate_import_secp_p, }, secp_utils::{ALPHA, ALPHA_V2, SECP_P, SECP_P_V2}, }, @@ -51,9 +51,8 @@ use crate::{ secp::{ bigint_utils::{bigint_to_uint256, hi_max_bitlen, nondet_bigint3}, ec_utils::{ - compute_doubling_slope, compute_slope, di_bit, ec_mul_inner, - fast_ec_add_assign_new_x, fast_ec_add_assign_new_y, import_secp256r1_p, - quad_bit, + compute_doubling_slope, compute_slope, di_bit, 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, @@ -576,6 +575,14 @@ impl HintProcessor for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, + &SECP_P, + ), + hint_code::FAST_EC_ADD_ASSIGN_NEW_X_V2 => fast_ec_add_assign_new_x( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + &SECP_P_V2, ), hint_code::FAST_EC_ADD_ASSIGN_NEW_Y => fast_ec_add_assign_new_y(exec_scopes), hint_code::EC_MUL_INNER => { diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 666282aee7..612a88b690 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -796,6 +796,16 @@ y0 = pack(ids.point0.y, PRIME) value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P"#; +pub const FAST_EC_ADD_ASSIGN_NEW_X_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack +SECP_P = 2**255-19 + +slope = pack(ids.slope, PRIME) +x0 = pack(ids.point0.x, PRIME) +x1 = pack(ids.point1.x, PRIME) +y0 = pack(ids.point0.y, PRIME) + +value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P"#; + pub const FAST_EC_ADD_ASSIGN_NEW_Y: &str = r#"value = new_y = (slope * (x0 - new_x) - y0) % SECP_P"#; 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 64bd962360..51d977e156 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -271,8 +271,9 @@ pub fn fast_ec_add_assign_new_x( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, + secp_p: &BigInt, ) -> Result<(), HintError> { - exec_scopes.insert_value("SECP_P", 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 @@ -280,12 +281,12 @@ pub fn fast_ec_add_assign_new_x( //ids.point1.x let point1 = EcPoint::from_var_name("point1", vm, ids_data, ap_tracking)?; - let slope = slope.pack86(); - let x0 = point0.x.pack86(); - let x1 = point1.x.pack86(); - let y0 = point0.y.pack86(); + let slope = slope.pack86().mod_floor(secp_p); + let x0 = point0.x.pack86().mod_floor(secp_p); + let x1 = point1.x.pack86().mod_floor(secp_p); + let y0 = point0.y.pack86().mod_floor(secp_p); - let value = (&slope * &slope - &x0 - &x1).mod_floor(&SECP_P); + let value = (&slope * &slope - &x0 - &x1).mod_floor(secp_p); //Assign variables to vm scope exec_scopes.insert_value("slope", slope); exec_scopes.insert_value("x0", x0); @@ -302,13 +303,14 @@ Implements hint: */ pub fn fast_ec_add_assign_new_y(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { //Get variables from vm scope - let (slope, x0, new_x, y0) = ( + let (slope, x0, new_x, y0, secp_p) = ( exec_scopes.get::("slope")?, exec_scopes.get::("x0")?, exec_scopes.get::("new_x")?, exec_scopes.get::("y0")?, + exec_scopes.get::("SECP_P")?, ); - let value = (slope * (x0 - new_x) - y0).mod_floor(&SECP_P); + let value = (slope * (x0 - new_x) - y0).mod_floor(&secp_p); exec_scopes.insert_value("value", value.clone()); exec_scopes.insert_value("new_y", value); @@ -968,7 +970,8 @@ mod tests { ( "y0", bigint_str!("4310143708685312414132851373791311001152018708061750480") - ) + ), + ("SECP_P", (*SECP_P).clone()) ]; //Execute the 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 d2d3888cd2..155b9f4976 100644 --- a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs @@ -27,7 +27,6 @@ lazy_static! { "115792089237316195423570985008687907853269984665640564039457584007908834671663" ) .unwrap(); - //SECP_P_V2 = 2**255-19 pub(crate) static ref SECP_P_V2: BigInt = BigInt::from_str( "57896044618658097711785492504343953926634992332820282019728792003956564819949" diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 3b4b1a2701..9d8c6d4e41 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -884,6 +884,13 @@ fn cairo_run_compute_doubling_slope_v2_test() { run_program_simple(program_data.as_slice()); } +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn fast_ec_add_v2() { + let program_data = include_bytes!("../../cairo_programs/fast_ec_add_v2.json"); + run_program_simple(program_data.as_slice()); +} + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn ec_double_assign_new_x_v3() {