From 21e31bf5d817bf0493f4f5d86229eff52adfd505 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Wed, 26 Apr 2023 18:08:33 -0300 Subject: [PATCH 1/4] WIP cairo program --- cairo_programs/secp256r1_fast_ec_add.cairo | 194 +++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 cairo_programs/secp256r1_fast_ec_add.cairo diff --git a/cairo_programs/secp256r1_fast_ec_add.cairo b/cairo_programs/secp256r1_fast_ec_add.cairo new file mode 100644 index 0000000000..5e2bd56c51 --- /dev/null +++ b/cairo_programs/secp256r1_fast_ec_add.cairo @@ -0,0 +1,194 @@ +%builtins range_check + +// Source: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/ec.cairo#L188 + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul, UnreducedBigInt3 +from starkware.cairo.common.cairo_secp.field import verify_zero +from starkware.cairo.common.cairo_secp.ec import EcPoint + +// N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 +const N0 = 0x179e84f3b9cac2fc632551; +const N1 = 0x3ffffffffffef39beab69c; +const N2 = 0xffffffff00000000fffff; + +// Constants for unreduced_mul/sqr +const s2 = -2**76 - 2**12; +const s1 = -2**66 + 4; +const s0 = 2**56; + +const r2 = 2**54 - 2**22; +const r1 = -2**12; +const r0 = 4; + +func unreduced_mul(a: BigInt3, b: BigInt3) -> (res_low: UnreducedBigInt3) { + tempvar twice_d2 = a.d2*b.d2; + tempvar d1d2 = a.d2*b.d1 + a.d1*b.d2; + return ( + UnreducedBigInt3( + d0=a.d0*b.d0 + s0*twice_d2 + r0*d1d2, + d1=a.d1*b.d0 + a.d0*b.d1 + s1*twice_d2 + r1*d1d2, + d2=a.d2*b.d0 + a.d1*b.d1 + a.d0*b.d2 + s2*twice_d2 + r2*d1d2, + ), + ); +} + +func unreduced_sqr(a: BigInt3) -> (res_low: UnreducedBigInt3) { + tempvar twice_d2 = a.d2*a.d2; + tempvar twice_d1d2 = a.d2*a.d1 + a.d1*a.d2; + tempvar d1d0 = a.d1*a.d0; + return ( + UnreducedBigInt3( + d0=a.d0*a.d0 + s0*twice_d2 + r0*twice_d1d2, + d1=d1d0 + d1d0 + s1*twice_d2 + r1*twice_d1d2, + d2=a.d2*a.d0 + a.d1*a.d1 + a.d0*a.d2 + s2*twice_d2 + r2*twice_d1d2, + ), + ); +} + +// func verify_zero{range_check_ptr}(val: UnreducedBigInt3) { +// alloc_locals; +// local q; +// %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} +// %{ +// 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 +// %} + +// assert_165_bit(q + 2**164); +// // q in [-2**164, 2**164) + +// tempvar r1 = (val.d0 + q * SECP_REM0) / BASE; +// assert_165_bit(r1 + 2**164); +// // r1 in [-2**164, 2**164) also meaning +// // numerator divides BASE which is the case when val divides secp256r1 +// // so r1 * BASE = val.d0 + q*SECP_REM0 in the integers + +// tempvar r2 = (val.d1 + q * SECP_REM1 + r1) / BASE; +// assert_165_bit(r2 + 2**164); +// // r2 in [-2**164, 2**164) following the same reasoning +// // so r2 * BASE = val.d1 + q*SECP_REM1 + r1 in the integers +// // so r2 * BASE ** 2 = val.d1 * BASE + q*SECP_REM1 * BASE + r1 * BASE + +// assert val.d2 + q * SECP_REM2 = q * (BASE / 4) - r2; +// // both lhs and rhs are in (-2**250, 2**250) so assertion valid in the integers +// // multiply both sides by BASE**2 +// // val.d2*BASE**2 + q * SECP_REM2*BASE**2 +// // = q * (2**256) - val.d1 * BASE + q*SECP_REM1 * BASE + val.d0 + q*SECP_REM0 +// // collect val on one side and all the rest on the other => +// // val = q*(2**256 - SECP_REM) = q * secp256r1 = 0 mod secp256r1 + +// return (); +// } + +func compute_slope{range_check_ptr}(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(); + + let x_diff = BigInt3( + d0=point0.x.d0 - point1.x.d0, d1=point0.x.d1 - point1.x.d1, d2=point0.x.d2 - point1.x.d2 + ); + let (x_diff_slope: UnreducedBigInt3) = unreduced_mul(x_diff, slope); + verify_zero( + UnreducedBigInt3( + d0=x_diff_slope.d0 - point0.y.d0 + point1.y.d0, + d1=x_diff_slope.d1 - point0.y.d1 + point1.y.d1, + d2=x_diff_slope.d2 - point0.y.d2 + point1.y.d2, + ), + ); + + return (slope=slope); +} + +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.secp256r1_utils import SECP256R1_P as SECP_P %} + // Hint #21 + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + + 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 = BigInt3(1, 5, 10); + let y = BigInt3(2, 4, 20); + + let point_a = EcPoint(x, y); + let point_e = EcPoint( + BigInt3(55117564152931927789817182, 33048130247267262167865975, 14533608608654363688616034), + BigInt3(54056253314096377704781816, 68158355584365770862343034, 3052322168655618600739346), + ); + + // fast_ec_add + let (point_f) = fast_ec_add(point_a, point_e); + assert point_f = EcPoint( + BigInt3(69178603654448607465162296, 33667561357032241906559657, 11638763416304862662171381), + BigInt3(51035566479066641367474701, 39483223302560035063029418, 12190232481429041491400793), + ); + + return (); +} From 1aebc3ac1f4f7725513fb8775d666864553a24e8 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Thu, 27 Apr 2023 16:28:43 -0300 Subject: [PATCH 2/4] add hint #21 --- CHANGELOG.md | 15 +++ cairo_programs/secp256r1_fast_ec_add.cairo | 111 +++++++++++------- .../builtin_hint_processor_definition.rs | 7 +- .../builtin_hint_processor/hint_code.rs | 10 ++ .../builtin_hint_processor/secp/ec_utils.rs | 40 +++++++ src/tests/cairo_run_test.rs | 7 ++ 6 files changed, 148 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e0f90c404..d73a85bdab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ #### Upcoming Changes +* Add missing hint on cairo_secp lib [](): + `BuiltinHintProcessor` now supports the following hint: + + ```python + + from starkware.cairo.common.cairo_secp.secp_utils import pack + + 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 [#1052](https://github.com/lambdaclass/cairo-rs/pull/1052): `BuiltinHintProcessor` now supports the following hint: diff --git a/cairo_programs/secp256r1_fast_ec_add.cairo b/cairo_programs/secp256r1_fast_ec_add.cairo index 5e2bd56c51..3a4f09584e 100644 --- a/cairo_programs/secp256r1_fast_ec_add.cairo +++ b/cairo_programs/secp256r1_fast_ec_add.cairo @@ -3,7 +3,6 @@ // Source: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/ec.cairo#L188 from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul, UnreducedBigInt3 -from starkware.cairo.common.cairo_secp.field import verify_zero from starkware.cairo.common.cairo_secp.ec import EcPoint // N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 @@ -20,6 +19,38 @@ const r2 = 2**54 - 2**22; const r1 = -2**12; const r0 = 4; +// SECP_REM = 2**224 - 2**192 - 2**96 + 1 +const SECP_REM0 = 1; +const SECP_REM1 = -2**10; +const SECP_REM2 = 0xffffffff00000; + +func assert_165_bit{range_check_ptr}(value) { + const UPPER_BOUND = 2 ** 165; + const SHIFT = 2 ** 128; + const HIGH_BOUND = SHIFT - UPPER_BOUND / SHIFT; + + let low = [range_check_ptr]; + let high = [range_check_ptr + 1]; + + %{ + from starkware.cairo.common.math_utils import as_int + + # Correctness check. + value = as_int(ids.value, PRIME) % PRIME + assert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).' + + # Calculation for the assertion. + ids.high, ids.low = divmod(ids.value, ids.SHIFT) + %} + + assert [range_check_ptr + 2] = high + HIGH_BOUND; + + assert value = high * SHIFT + low; + + let range_check_ptr = range_check_ptr + 3; + return (); +} + func unreduced_mul(a: BigInt3, b: BigInt3) -> (res_low: UnreducedBigInt3) { tempvar twice_d2 = a.d2*b.d2; tempvar d1d2 = a.d2*b.d1 + a.d1*b.d2; @@ -45,43 +76,43 @@ func unreduced_sqr(a: BigInt3) -> (res_low: UnreducedBigInt3) { ); } -// func verify_zero{range_check_ptr}(val: UnreducedBigInt3) { -// alloc_locals; -// local q; -// %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} -// %{ -// 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 -// %} - -// assert_165_bit(q + 2**164); -// // q in [-2**164, 2**164) - -// tempvar r1 = (val.d0 + q * SECP_REM0) / BASE; -// assert_165_bit(r1 + 2**164); -// // r1 in [-2**164, 2**164) also meaning -// // numerator divides BASE which is the case when val divides secp256r1 -// // so r1 * BASE = val.d0 + q*SECP_REM0 in the integers - -// tempvar r2 = (val.d1 + q * SECP_REM1 + r1) / BASE; -// assert_165_bit(r2 + 2**164); -// // r2 in [-2**164, 2**164) following the same reasoning -// // so r2 * BASE = val.d1 + q*SECP_REM1 + r1 in the integers -// // so r2 * BASE ** 2 = val.d1 * BASE + q*SECP_REM1 * BASE + r1 * BASE - -// assert val.d2 + q * SECP_REM2 = q * (BASE / 4) - r2; -// // both lhs and rhs are in (-2**250, 2**250) so assertion valid in the integers -// // multiply both sides by BASE**2 -// // val.d2*BASE**2 + q * SECP_REM2*BASE**2 -// // = q * (2**256) - val.d1 * BASE + q*SECP_REM1 * BASE + val.d0 + q*SECP_REM0 -// // collect val on one side and all the rest on the other => -// // val = q*(2**256 - SECP_REM) = q * secp256r1 = 0 mod secp256r1 - -// return (); -// } +func verify_zero{range_check_ptr}(val: UnreducedBigInt3) { + alloc_locals; + local q; + %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} + %{ + 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 + %} + + assert_165_bit(q + 2**164); + // q in [-2**164, 2**164) + + tempvar r1 = (val.d0 + q * SECP_REM0) / BASE; + assert_165_bit(r1 + 2**164); + // r1 in [-2**164, 2**164) also meaning + // numerator divides BASE which is the case when val divides secp256r1 + // so r1 * BASE = val.d0 + q*SECP_REM0 in the integers + + tempvar r2 = (val.d1 + q * SECP_REM1 + r1) / BASE; + assert_165_bit(r2 + 2**164); + // r2 in [-2**164, 2**164) following the same reasoning + // so r2 * BASE = val.d1 + q*SECP_REM1 + r1 in the integers + // so r2 * BASE ** 2 = val.d1 * BASE + q*SECP_REM1 * BASE + r1 * BASE + + assert val.d2 + q * SECP_REM2 = q * (BASE / 4) - r2; + // both lhs and rhs are in (-2**250, 2**250) so assertion valid in the integers + // multiply both sides by BASE**2 + // val.d2*BASE**2 + q * SECP_REM2*BASE**2 + // = q * (2**256) - val.d1 * BASE + q*SECP_REM1 * BASE + val.d0 + q*SECP_REM0 + // collect val on one side and all the rest on the other => + // val = q*(2**256 - SECP_REM) = q * secp256r1 = 0 mod secp256r1 + + return (); +} func compute_slope{range_check_ptr}(point0: EcPoint, point1: EcPoint) -> (slope: BigInt3) { %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} @@ -186,8 +217,8 @@ func main{range_check_ptr}(){ // fast_ec_add let (point_f) = fast_ec_add(point_a, point_e); assert point_f = EcPoint( - BigInt3(69178603654448607465162296, 33667561357032241906559657, 11638763416304862662171381), - BigInt3(51035566479066641367474701, 39483223302560035063029418, 12190232481429041491400793), + BigInt3(49699015624329293412442365, 46510866771824701261167999, 1989434117861440887085793), + BigInt3(214124551187530669800637, 1052132420873960207582277, 4516480956028272815500807), ); 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 c3c9a2bcea..c2337c718a 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_mul_inner, - ec_negate_embedded_secp_p, ec_negate_import_secp_p, + compute_slope_and_assing_secp_p, compute_slope_x_mod_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}, }, @@ -490,6 +490,9 @@ impl HintProcessor for BuiltinHintProcessor { "point1", &SECP_P, ), + hint_code::SQUARE_SLOPE_X_MOD_P => { + compute_slope_x_mod_p(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) + } hint_code::COMPUTE_SLOPE_V2 => compute_slope_and_assing_secp_p( 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 612a88b690..93b0052a3a 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -1288,5 +1288,15 @@ ids.b_inverse_mod_p.high = b_inverse_mod_p_split[1]"#; pub const EC_RECOVER_PRODUCT_DIV_M: &str = "value = k = product // m"; +pub const SQUARE_SLOPE_X_MOD_P: &str = + "from starkware.cairo.common.cairo_secp.secp_utils import pack + +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"; + #[cfg(feature = "skip_next_instruction_hint")] pub const SKIP_NEXT_INSTRUCTION: &str = "skip_next_instruction()"; 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 51d977e156..6859f3b661 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -193,6 +193,46 @@ pub fn compute_slope( Ok(()) } +/* +Implements hint: +%{from starkware.cairo.common.cairo_secp.secp_utils import pack + +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 fn compute_slope_x_mod_p( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let secp_p = exec_scopes.get::("SECP_P")?; + let point0 = EcPoint::from_var_name("point0", vm, ids_data, ap_tracking)?; + let point1 = EcPoint::from_var_name("point1", vm, ids_data, ap_tracking)?; + + let slope = BigInt3::from_var_name("slope", 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 value = (slope.pow(2) - &x0 - &x1).mod_floor(&secp_p); + + exec_scopes.insert_value("slope", slope); + exec_scopes.insert_value("x0", x0); + exec_scopes.insert_value("x1", x1); + exec_scopes.insert_value("y0", y0); + exec_scopes.insert_value("value", value.clone()); + exec_scopes.insert_value("new_x", value); + + Ok(()) +} + /* Implements hint: %{ diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 9d8c6d4e41..a42212d77d 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -897,3 +897,10 @@ fn ec_double_assign_new_x_v3() { let program_data = include_bytes!("../../cairo_programs/ec_double_assign_new_x_v3.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn secp256r1_fast_ec_add() { + let program_data = include_bytes!("../../cairo_programs/secp256r1_fast_ec_add.json"); + run_program_simple(program_data.as_slice()); +} From dfe95351c4c45e02d0591abd8142f2215fdab986 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Thu, 27 Apr 2023 16:30:38 -0300 Subject: [PATCH 3/4] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d73a85bdab..f8b8a07fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ #### Upcoming Changes -* Add missing hint on cairo_secp lib [](): +* Add missing hint on cairo_secp lib [#1089](https://github.com/lambdaclass/cairo-rs/pull/1089): `BuiltinHintProcessor` now supports the following hint: ```python From 5c5b13f02c5263dad9ad6f94dc9a1a05ef288830 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Thu, 27 Apr 2023 18:56:15 -0300 Subject: [PATCH 4/4] add unit test --- .../builtin_hint_processor/secp/ec_utils.rs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) 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 822dec8276..9a1d3f1d11 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -1300,4 +1300,62 @@ mod tests { ) ); } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_square_slope_minus_xs_ok() { + let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nslope = pack(ids.slope, PRIME)\nx0 = pack(ids.point0.x, PRIME)\nx1 = pack(ids.point1.x, PRIME)\ny0 = pack(ids.point0.y, PRIME)\n\nvalue = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P"; + let mut vm = vm_with_range_check!(); + + //Insert ids.point0, ids.point1.x and ids.slope into memory + vm.segments = segments![ + //ids.point0 + ((1, 0), 89712), + ((1, 1), 56), + ((1, 2), 1233409), + ((1, 3), 980126), + ((1, 4), 10), + ((1, 5), 8793), + //ids.point0.x + ((1, 6), 1235216451), + ((1, 7), 5967), + ((1, 8), 2171381), + //ids.slope + ((1, 9), 67470097831679799377177424_i128), + ((1, 10), 43370026683122492246392730_i128), + ((1, 11), 16032182557092050689870202_i128) + ]; + + //Initialize run_context + run_context!(vm, 0, 20, 15); + + let ids_data = HashMap::from([ + ("point0".to_string(), HintReference::new_simple(-15)), + ("point1".to_string(), HintReference::new_simple(-9)), + ("slope".to_string(), HintReference::new_simple(-6)), + ]); + let mut exec_scopes = ExecutionScopes::new(); + exec_scopes.insert_value("SECP_P", SECP_P.clone()); + + //Execute the hint + assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); + + check_scope!( + &exec_scopes, + [ + ( + "value", + bigint_str!( + "8891838197222656627233627110766426698842623939023296165598688719819499152657" + ) + ), + ( + "new_x", + bigint_str!( + "8891838197222656627233627110766426698842623939023296165598688719819499152657" + ) + ) + ] + ); + } }