diff --git a/CHANGELOG.md b/CHANGELOG.md index 12d25961fc..19d9c96fce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -218,6 +218,33 @@ 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) + ``` + * 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/ed25519_ec.cairo b/cairo_programs/ed25519_ec.cairo index 61425dbb22..71c841cbd4 100644 --- a/cairo_programs/ed25519_ec.cairo +++ b/cairo_programs/ed25519_ec.cairo @@ -18,6 +18,37 @@ struct EcPoint { y: BigInt3, } +// Returns the slope of the elliptic curve at the given point. +// The slope is used to compute pt + pt. +// Assumption: pt != 0. +func compute_doubling_slope{range_check_ptr}(pt: EcPoint) -> (slope: BigInt3) { + // Note that y cannot be zero: assume that it is, then pt = -pt, so 2 * pt = 0, which + // contradicts the fact that the size of the curve is odd. + %{ + 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) + %} + let (slope: BigInt3) = nondet_bigint3(); + + let (x_sqr: UnreducedBigInt3) = unreduced_sqr(pt.x); + let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, pt.y); + + verify_zero( + UnreducedBigInt3( + d0=3 * x_sqr.d0 - 2 * slope_y.d0, + d1=3 * x_sqr.d1 - 2 * slope_y.d1, + d2=3 * x_sqr.d2 - 2 * slope_y.d2, + ), + ); + + return (slope=slope); +} + // 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). @@ -49,6 +80,22 @@ func compute_slope{range_check_ptr: felt}(pt0: EcPoint, pt1: EcPoint) -> (slope: return (slope=slope); } +func test_compute_double_slope{range_check_ptr: felt}() { + let x = BigInt3(d0=33, d1=24, d2=12412); + let y = BigInt3(d0=3232, d1=122, d2=31415); + + let pt = EcPoint(x=x, y=y); + + // Compute slope + let (slope) = compute_doubling_slope(pt); + + assert slope = BigInt3( + d0=56007611085086895200895667, d1=15076814030975805918069142, d2=6556143173243739984479201 + ); + + return (); +} + 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); @@ -71,6 +118,7 @@ func test_compute_slope{range_check_ptr: felt}() { } func main{range_check_ptr: felt}() { + test_compute_double_slope(); 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 f6db107dac..93fce74902 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 @@ -358,9 +358,20 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::EC_NEGATE => { ec_negate(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::EC_DOUBLE_SCOPE => { - compute_doubling_slope(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) - } + hint_code::EC_DOUBLE_SCOPE => compute_doubling_slope( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + "point", + ), + hint_code::EC_DOUBLE_SCOPE_WHITELIST => compute_doubling_slope( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + "pt", + ), hint_code::COMPUTE_SLOPE => compute_slope( 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 067d4d4b9d..9743b99f91 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -467,6 +467,14 @@ x = pack(ids.point.x, PRIME) y = pack(ids.point.y, PRIME) value = slope = ec_double_slope(point=(x, y), alpha=0, p=SECP_P)"#; +pub(crate) const EC_DOUBLE_SCOPE_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. +x = pack(ids.pt.x, PRIME) +y = pack(ids.pt.y, PRIME) +value = slope = div_mod(3 * x ** 2, 2 * y, SECP_P)"#; + pub(crate) const COMPUTE_SLOPE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack from starkware.python.math_utils import line_slope 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 d59da2c96d..9c7dfe74f8 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -84,9 +84,10 @@ pub fn compute_doubling_slope( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, + point_alias: &str, ) -> Result<(), HintError> { //ids.point - let point = EcPoint::from_var_name("point", vm, ids_data, ap_tracking)?; + let point = EcPoint::from_var_name(point_alias, vm, ids_data, ap_tracking)?; let value = ec_double_slope(&(pack(point.x), pack(point.y)), &BigInt::zero(), &SECP_P); exec_scopes.insert_value("value", value.clone()); @@ -357,6 +358,47 @@ mod tests { ); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_compute_doubling_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.\nx = pack(ids.pt.x, PRIME)\ny = pack(ids.pt.y, PRIME)\nvalue = slope = div_mod(3 * x ** 2, 2 * y, SECP_P)"; + let mut vm = vm_with_range_check!(); + vm.segments = segments![ + ((1, 0), 614323u64), + ((1, 1), 5456867u64), + ((1, 2), 101208u64), + ((1, 3), 773712524u64), + ((1, 4), 77371252u64), + ((1, 5), 5298795u64) + ]; + + //Initialize fp + vm.run_context.fp = 1; + + let ids_data = ids_data!["pt"]; + 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!( + "40442433062102151071094722250325492738932110061897694430475034100717288403728" + ) + ), + ( + "slope", + bigint_str!( + "40442433062102151071094722250325492738932110061897694430475034100717288403728" + ) + ) + ] + ); + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_compute_slope_ok() {