From 61324829fce901d5d4753ccd80b6d85d33315d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= Date: Thu, 13 Apr 2023 17:08:41 -0300 Subject: [PATCH 1/5] Add `COMPUTE_SLOPE_WHITELIST` hint --- cairo_programs/ed25519_ec.cairo | 75 +++++++++++++++++++ .../builtin_hint_processor_definition.rs | 19 ++++- .../builtin_hint_processor/hint_code.rs | 10 +++ .../builtin_hint_processor/secp/ec_utils.rs | 57 +++++++++++++- src/tests/cairo_run_test.rs | 7 ++ 5 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 cairo_programs/ed25519_ec.cairo diff --git a/cairo_programs/ed25519_ec.cairo b/cairo_programs/ed25519_ec.cairo new file mode 100644 index 0000000000..4f6e6b5527 --- /dev/null +++ b/cairo_programs/ed25519_ec.cairo @@ -0,0 +1,75 @@ +%builtins range_check + +// Source: https://github.com/NilFoundation/cairo-ed25519/blob/fee64a1a60b2e07b3b5c20df57f31d7ffcb29ac9/ed25519_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, +) + +// Represents a point on the elliptic curve. +// The zero point is represented using pt.x=0, as there is no point on the curve with this x value. +struct EcPoint { + x: BigInt3, + y: BigInt3, +} + +// 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}(pt0: EcPoint, pt1: EcPoint) -> (slope: BigInt3) { + %{ + 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) + %} + let (slope) = nondet_bigint3(); + + let x_diff = BigInt3(d0=pt0.x.d0 - pt1.x.d0, d1=pt0.x.d1 - pt1.x.d1, d2=pt0.x.d2 - pt1.x.d2); + let (x_diff_slope: UnreducedBigInt3) = unreduced_mul(x_diff, slope); + + verify_zero( + UnreducedBigInt3( + d0=x_diff_slope.d0 - pt0.y.d0 + pt1.y.d0, + d1=x_diff_slope.d1 - pt0.y.d1 + pt1.y.d1, + d2=x_diff_slope.d2 - pt0.y.d2 + pt1.y.d2, + ), + ); + + 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 = BigInt3( + d0=39919528597790922692721903, d1=31451568879578276714332055, d2=6756007504256943629292535 + ); +} + +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 535db3b7ec..89770142c3 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 @@ -356,9 +356,22 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::EC_DOUBLE_SCOPE => { compute_doubling_slope(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::COMPUTE_SLOPE => { - compute_slope(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) - } + hint_code::COMPUTE_SLOPE => compute_slope( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + "point0", + "point1", + ), + hint_code::COMPUTE_SLOPE_WHITELIST => compute_slope( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + "pt0", + "pt1", + ), hint_code::EC_DOUBLE_ASSIGN_NEW_X => { ec_double_assign_new_x(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index aa0472104f..88fb0f7125 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -465,6 +465,16 @@ 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(crate) 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 + +# 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)"#; + pub(crate) const EC_DOUBLE_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack slope = pack(ids.slope, 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 cd41607005..d59da2c96d 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -113,11 +113,13 @@ pub fn compute_slope( 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", vm, ids_data, ap_tracking)?; + let point0 = EcPoint::from_var_name(point0_alias, vm, ids_data, ap_tracking)?; //ids.point1 - let point1 = EcPoint::from_var_name("point1", vm, ids_data, ap_tracking)?; + let point1 = EcPoint::from_var_name(point1_alias, vm, ids_data, ap_tracking)?; let value = line_slope( &(pack(point0.x), pack(point0.y)), @@ -406,6 +408,57 @@ mod tests { ); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_compute_slope_wdivmod_ok() { + let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\nfrom starkware.python.math_utils import div_mod\n\n# Compute the slope.\nx0 = pack(ids.pt0.x, PRIME)\ny0 = pack(ids.pt0.y, PRIME)\nx1 = pack(ids.pt1.x, PRIME)\ny1 = pack(ids.pt1.y, PRIME)\nvalue = slope = div_mod(y0 - y1, x0 - x1, SECP_P)"; + let mut vm = vm_with_range_check!(); + + // Insert ids.pt0 and ids.pt1 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), 156), + ((1, 7), 6545), + ((1, 8), 100010), + ((1, 9), 1123), + ((1, 10), 1325), + ((1, 11), 910) + ]; + + // Initialize fp + vm.run_context.fp = 14; + let ids_data = HashMap::from([ + ("pt0".to_string(), HintReference::new_simple(-14)), + ("pt1".to_string(), HintReference::new_simple(-8)), + ]); + 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, + [ + ( + "value", + bigint_str!( + "41419765295989780131385135514529906223027172305400087935755859001910844026631" + ) + ), + ( + "slope", + bigint_str!( + "41419765295989780131385135514529906223027172305400087935755859001910844026631" + ) + ) + ] + ); + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_ec_double_assign_new_x_ok() { diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 9c12f8b0e3..22eb20e22c 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1280,3 +1280,10 @@ fn cairo_run_is_quad_residue_test() { let program_data = include_bytes!("../../cairo_programs/is_quad_residue_test.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_ed25519_ec() { + let program_data = include_bytes!("../../cairo_programs/ed25519_ec.json"); + run_program_simple(program_data.as_slice()); +} From aaa202b0713d62cd36484479b058e41a46cf234a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= Date: Thu, 13 Apr 2023 17:54:33 -0300 Subject: [PATCH 2/5] Update changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1c8956cac..e7d339ccc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ #### Upcoming Changes +* 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` From 6e54f1da8362aed6b9c119880ef1d33222dcdedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= Date: Thu, 13 Apr 2023 18:09:30 -0300 Subject: [PATCH 3/5] Fix: add missing return to cairo program --- cairo_programs/ed25519_ec.cairo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cairo_programs/ed25519_ec.cairo b/cairo_programs/ed25519_ec.cairo index 4f6e6b5527..61425dbb22 100644 --- a/cairo_programs/ed25519_ec.cairo +++ b/cairo_programs/ed25519_ec.cairo @@ -66,6 +66,8 @@ func test_compute_slope{range_check_ptr: felt}() { assert slope = BigInt3( d0=39919528597790922692721903, d1=31451568879578276714332055, d2=6756007504256943629292535 ); + + return (); } func main{range_check_ptr: felt}() { From 9103741faeea9b3456ae9d60f971a40e70db2fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <47506558+MegaRedHand@users.noreply.github.com> Date: Thu, 13 Apr 2023 18:53:32 -0300 Subject: [PATCH 4/5] Separate changelog item and description Co-authored-by: fmoletta <99273364+fmoletta@users.noreply.github.com> --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7d339ccc9..e57bdd6bde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ #### Upcoming Changes * 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 b66127fbddb95f8acbf687a8bdccecb7b0e9a89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= Date: Fri, 14 Apr 2023 15:06:20 -0300 Subject: [PATCH 5/5] Format --- src/tests/cairo_run_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 6368ed8598..c153ea0af1 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1287,7 +1287,7 @@ fn cairo_run_uint384() { let program_data = include_bytes!("../../cairo_programs/uint384.json"); run_program_simple(program_data.as_slice()); } - + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn cairo_run_ed25519_ec() {