diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a0c85a88c..975332f2a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,58 @@ * 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 [#990](https://github.com/lambdaclass/cairo-rs/pull/990): + + `BuiltinHintProcessor` now supports the following hint: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + + slope = pack(ids.slope, PRIME) + x = pack(ids.point.x, PRIME) + y = pack(ids.point.y, PRIME) + + value = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P + ``` + +* Add missing hint on cairo_secp lib [#989](https://github.com/lambdaclass/cairo-rs/pull/989): + + `BuiltinHintProcessor` now supports the following hint: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import SECP_P + 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 [#986](https://github.com/lambdaclass/cairo-rs/pull/986): + + `BuiltinHintProcessor` now supports the following hint: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack + from starkware.python.math_utils import div_mod + + # Compute the slope. + x = pack(ids.pt.x, PRIME) + y = pack(ids.pt.y, PRIME) + value = slope = div_mod(3 * x ** 2, 2 * y, SECP_P) + ``` + +* Add missing hint on cairo_secp lib [#984](https://github.com/lambdaclass/cairo-rs/pull/984): + + `BuiltinHintProcessor` now supports the following hint: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack + from starkware.python.math_utils import div_mod + + # Compute the slope. + x0 = pack(ids.pt0.x, PRIME) + y0 = pack(ids.pt0.y, PRIME) + x1 = pack(ids.pt1.x, PRIME) + y1 = pack(ids.pt1.y, PRIME) + value = slope = div_mod(y0 - y1, x0 - x1, SECP_P) + ``` + #### [0.3.0-rc1] - 2023-04-13 * Derive Deserialize for ExecutionResources [#922](https://github.com/lambdaclass/cairo-rs/pull/922) * Remove builtin names from VirtualMachine.builtin_runners [#921](https://github.com/lambdaclass/cairo-rs/pull/921) @@ -57,22 +109,6 @@ * after each step * ExecutionResource operations: add and substract [#774](https://github.com/lambdaclass/cairo-rs/pull/774), multiplication [#908](https://github.com/lambdaclass/cairo-rs/pull/908) , and `AddAssign` [#914](https://github.com/lambdaclass/cairo-rs/pull/914) - -* Add missing hint on cairo_secp lib [#984]: - - `BuiltinHintProcessor` now supports the following hint: - ```python - from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack - from starkware.python.math_utils import div_mod - - # Compute the slope. - x0 = pack(ids.pt0.x, PRIME) - y0 = pack(ids.pt0.y, PRIME) - x1 = pack(ids.pt1.x, PRIME) - y1 = pack(ids.pt1.y, PRIME) - value = slope = div_mod(y0 - y1, x0 - x1, SECP_P) - ``` - * Implement hints on uint384 lib (Part 2) [#971](https://github.com/lambdaclass/cairo-rs/pull/971) `BuiltinHintProcessor` now supports the following hint: @@ -224,69 +260,6 @@ Used by the common library function `uint256_mul_div_mod` -* Add missing hint on cairo_secp lib [#986]: - - `BuiltinHintProcessor` now supports the following hint: - ```python - from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack - from starkware.python.math_utils import div_mod - - # Compute the slope. - x = pack(ids.pt.x, PRIME) - y = pack(ids.pt.y, PRIME) - value = slope = div_mod(3 * x ** 2, 2 * y, SECP_P) - ``` - -* Add missing hint on cairo_secp lib [#984]: - `BuiltinHintProcessor` now supports the following hint: - ```python - from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack - from starkware.python.math_utils import div_mod - - # Compute the slope. - x0 = pack(ids.pt0.x, PRIME) - y0 = pack(ids.pt0.y, PRIME) - x1 = pack(ids.pt1.x, PRIME) - y1 = pack(ids.pt1.y, PRIME) - value = slope = div_mod(y0 - y1, x0 - x1, SECP_P) - ``` - -* Add missing hint on cairo_secp lib [#989]: - - `BuiltinHintProcessor` now supports the following hint: - ```python - from starkware.cairo.common.cairo_secp.secp_utils import SECP_P - 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 [#986]: - `BuiltinHintProcessor` now supports the following hint: - ```python - from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack - from starkware.python.math_utils import div_mod - - # Compute the slope. - x = pack(ids.pt.x, PRIME) - y = pack(ids.pt.y, PRIME) - value = slope = div_mod(3 * x ** 2, 2 * y, SECP_P) - ``` - -* Add missing hint on cairo_secp lib [#984]: - `BuiltinHintProcessor` now supports the following hint: - ```python - from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack - from starkware.python.math_utils import div_mod - - # Compute the slope. - x0 = pack(ids.pt0.x, PRIME) - y0 = pack(ids.pt0.y, PRIME) - x1 = pack(ids.pt1.x, PRIME) - y1 = pack(ids.pt1.y, PRIME) - value = slope = div_mod(y0 - y1, x0 - x1, SECP_P) - ``` - * Move `Memory` into `MemorySegmentManager` [#830](https://github.com/lambdaclass/cairo-rs/pull/830) * Structural changes: * Remove `memory: Memory` field from `VirtualMachine` diff --git a/cairo_programs/efficient_secp256r1_ec.cairo b/cairo_programs/efficient_secp256r1_ec.cairo new file mode 100644 index 0000000000..dcfc588f14 --- /dev/null +++ b/cairo_programs/efficient_secp256r1_ec.cairo @@ -0,0 +1,83 @@ +%builtins range_check + +// Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/ec.cairo#L127 + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3 +from starkware.cairo.common.cairo_secp.ec import EcPoint, compute_doubling_slope +from starkware.cairo.common.cairo_secp.field import ( + is_zero, + unreduced_mul, + unreduced_sqr, + verify_zero, +) + +// Computes the addition of a given point to itself. +// +// Arguments: +// point - the point to operate on. +// +// Returns: +// res - a point representing point + point. +func ec_double{range_check_ptr}(point: EcPoint) -> (res: EcPoint) { + // The zero point. + if (point.x.d0 == 0) { + if (point.x.d1 == 0) { + if (point.x.d2 == 0) { + return (res=point); + } + } + } + + let (slope: BigInt3) = compute_doubling_slope(point); + let (slope_sqr: UnreducedBigInt3) = unreduced_sqr(slope); + + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + + slope = pack(ids.slope, PRIME) + x = pack(ids.point.x, PRIME) + y = pack(ids.point.y, PRIME) + + value = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P + %} + let (new_x: BigInt3) = nondet_bigint3(); + + %{ value = new_y = (slope * (x - new_x) - y) % SECP_P %} + let (new_y: BigInt3) = nondet_bigint3(); + verify_zero( + UnreducedBigInt3( + d0=slope_sqr.d0 - new_x.d0 - 2 * point.x.d0, + d1=slope_sqr.d1 - new_x.d1 - 2 * point.x.d1, + d2=slope_sqr.d2 - new_x.d2 - 2 * point.x.d2, + ), + ); + + let (x_diff_slope: UnreducedBigInt3) = unreduced_mul( + BigInt3(d0=point.x.d0 - new_x.d0, d1=point.x.d1 - new_x.d1, d2=point.x.d2 - new_x.d2), slope + ); + verify_zero( + UnreducedBigInt3( + d0=x_diff_slope.d0 - point.y.d0 - new_y.d0, + d1=x_diff_slope.d1 - point.y.d1 - new_y.d1, + d2=x_diff_slope.d2 - point.y.d2 - new_y.d2, + ), + ); + + return (res=EcPoint(new_x, new_y)); +} + +func main{range_check_ptr: felt}() { + let x = BigInt3(235, 522, 111); + let y = BigInt3(1323, 15124, 796759); + + let point = EcPoint(x, y); + + let (res) = ec_double(point); + + assert res = EcPoint( + BigInt3(64960503569511978748964127, 74077005698377320581054215, 17246103581201827820088765), + BigInt3(13476289913106792137931934, 29193128211607101710049068, 18079689234850912663169436), + ); + + 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 31aa8e2aa8..58fc12429d 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 @@ -390,7 +390,7 @@ impl HintProcessor for BuiltinHintProcessor { "pt0", "pt1", ), - hint_code::EC_DOUBLE_ASSIGN_NEW_X => { + hint_code::EC_DOUBLE_ASSIGN_NEW_X_V1 | hint_code::EC_DOUBLE_ASSIGN_NEW_X_V2 => { ec_double_assign_new_x(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } hint_code::EC_DOUBLE_ASSIGN_NEW_Y => ec_double_assign_new_y(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 6f4d3b5d53..1b6e765eb2 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -497,7 +497,15 @@ x1 = pack(ids.pt1.x, PRIME) y1 = pack(ids.pt1.y, PRIME) value = slope = div_mod(y0 - y1, x0 - x1, SECP_P)"#; -pub const EC_DOUBLE_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const EC_DOUBLE_ASSIGN_NEW_X_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack + +slope = pack(ids.slope, PRIME) +x = pack(ids.point.x, PRIME) +y = pack(ids.point.y, PRIME) + +value = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P"#; + +pub const EC_DOUBLE_ASSIGN_NEW_X_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack slope = pack(ids.slope, PRIME) x = pack(ids.point.x, PRIME) 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 9c7dfe74f8..049c721d54 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -504,64 +504,67 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_ec_double_assign_new_x_ok() { - let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nslope = pack(ids.slope, PRIME)\nx = pack(ids.point.x, PRIME)\ny = pack(ids.point.y, PRIME)\n\nvalue = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P"; - let mut vm = vm_with_range_check!(); - - //Insert ids.point and ids.slope into memory - vm.segments = segments![ - ((1, 0), 134), - ((1, 1), 5123), - ((1, 2), 140), - ((1, 3), 1232), - ((1, 4), 4652), - ((1, 5), 720), - ((1, 6), 44186171158942157784255469_i128), - ((1, 7), 54173758974262696047492534_i128), - ((1, 8), 8106299688661572814170174_i128) - ]; - - //Initialize fp - vm.run_context.fp = 10; - let ids_data = HashMap::from([ - ("point".to_string(), HintReference::new_simple(-10)), - ("slope".to_string(), HintReference::new_simple(-4)), - ]); - let mut exec_scopes = ExecutionScopes::new(); - - //Execute the hint - assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); - - check_scope!( - &exec_scopes, - [ - ( - "slope", - bigint_str!( - "48526828616392201132917323266456307435009781900148206102108934970258721901549" - ) - ), - ( - "x", - bigint_str!("838083498911032969414721426845751663479194726707495046") - ), - ( - "y", - bigint_str!("4310143708685312414132851373791311001152018708061750480") - ), - ( - "value", - bigint_str!( - "59479631769792988345961122678598249997181612138456851058217178025444564264149" - ) - ), - ( - "new_x", - bigint_str!( - "59479631769792988345961122678598249997181612138456851058217178025444564264149" - ) - ) - ] - ); + let hint_codes = vec!["from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nslope = pack(ids.slope, PRIME)\nx = pack(ids.point.x, PRIME)\ny = pack(ids.point.y, PRIME)\n\nvalue = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P", "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nslope = pack(ids.slope, PRIME)\nx = pack(ids.point.x, PRIME)\ny = pack(ids.point.y, PRIME)\n\nvalue = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P"]; + + for hint_code in hint_codes { + let mut vm = vm_with_range_check!(); + + //Insert ids.point and ids.slope into memory + vm.segments = segments![ + ((1, 0), 134), + ((1, 1), 5123), + ((1, 2), 140), + ((1, 3), 1232), + ((1, 4), 4652), + ((1, 5), 720), + ((1, 6), 44186171158942157784255469_i128), + ((1, 7), 54173758974262696047492534_i128), + ((1, 8), 8106299688661572814170174_i128) + ]; + + //Initialize fp + vm.run_context.fp = 10; + let ids_data = HashMap::from([ + ("point".to_string(), HintReference::new_simple(-10)), + ("slope".to_string(), HintReference::new_simple(-4)), + ]); + let mut exec_scopes = ExecutionScopes::new(); + + //Execute the hint + assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); + + check_scope!( + &exec_scopes, + [ + ( + "slope", + bigint_str!( + "48526828616392201132917323266456307435009781900148206102108934970258721901549" + ) + ), + ( + "x", + bigint_str!("838083498911032969414721426845751663479194726707495046") + ), + ( + "y", + bigint_str!("4310143708685312414132851373791311001152018708061750480") + ), + ( + "value", + bigint_str!( + "59479631769792988345961122678598249997181612138456851058217178025444564264149" + ) + ), + ( + "new_x", + bigint_str!( + "59479631769792988345961122678598249997181612138456851058217178025444564264149" + ) + ) + ] + ); + } } #[test] diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 54ddd004b7..ef2da718e2 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1308,3 +1308,10 @@ fn cairo_run_ed25519_ec() { let program_data = include_bytes!("../../cairo_programs/ed25519_ec.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_efficient_secp256r1_ec() { + let program_data = include_bytes!("../../cairo_programs/efficient_secp256r1_ec.json"); + run_program_simple(program_data.as_slice()); +}