Skip to content

Commit

Permalink
feat(hints): add NewHint#61 (#1056)
Browse files Browse the repository at this point in the history
* Add integration tests

* Implement hint

* Update CHANGELOG.md

* Add unit test

* remove prints from cairo program

* cargo fmt

---------

Co-authored-by: Mario Rugiero <[email protected]>
Co-authored-by: Mario Rugiero <[email protected]>
  • Loading branch information
3 people authored Apr 26, 2023
1 parent 1feaba0 commit 0cbc70d
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 20 deletions.
25 changes: 21 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,24 @@
* Optimizations for hash builtin [#1029](https://github.com/lambdaclass/cairo-rs/pull/1029):
* Track the verified addresses by offset in a `Vec<bool>` rather than storing the address in a `Vec<Relocatable>`

* Add missing hint on vrf.json lib [#1035](https://github.com/lambdaclass/cairo-rs/pull/1035):
* Add missing hint on vrf.json whitelist [#1056](https://github.com/lambdaclass/cairo-rs/pull/1056):

`BuiltinHintProcessor` now supports the following hint:

```python
%{
from starkware.python.math_utils import ec_double_slope
from starkware.cairo.common.cairo_secp.secp_utils import pack
SECP_P = 2**255-19

# Compute the slope.
x = pack(ids.point.x, PRIME)
y = pack(ids.point.y, PRIME)
value = slope = ec_double_slope(point=(x, y), alpha=42204101795669822316448953119945047945709099015225996174933988943478124189485, p=SECP_P)
%}
```

* Add missing hint on vrf.json whitelist [#1035](https://github.com/lambdaclass/cairo-rs/pull/1035):

`BuiltinHintProcessor` now supports the following hint:

Expand All @@ -251,7 +268,7 @@
%}
```

* Add missing hint on vrf.json lib [#1035](https://github.com/lambdaclass/cairo-rs/pull/1035):
* Add missing hint on vrf.json whitelist [#1035](https://github.com/lambdaclass/cairo-rs/pull/1035):

`BuiltinHintProcessor` now supports the following hint:

Expand All @@ -266,7 +283,7 @@
%}
```

* Add missing hint on vrf.json lib [#1000](https://github.com/lambdaclass/cairo-rs/pull/1000):
* Add missing hint on vrf.json whitelist [#1000](https://github.com/lambdaclass/cairo-rs/pull/1000):

`BuiltinHintProcessor` now supports the following hint:

Expand Down Expand Up @@ -494,7 +511,7 @@

_Note: this hint is similar to the one in #983, but with some trailing whitespace removed_

* Add missing hint on vrf.json lib [#1030](https://github.com/lambdaclass/cairo-rs/pull/1030):
* Add missing hint on vrf.json whitelist [#1030](https://github.com/lambdaclass/cairo-rs/pull/1030):

`BuiltinHintProcessor` now supports the following hint:

Expand Down
100 changes: 100 additions & 0 deletions cairo_programs/compute_doubling_slope_v2.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@

from starkware.cairo.common.cairo_secp.bigint import (
BigInt3,
UnreducedBigInt3,
nondet_bigint3,
)

from cairo_programs.compute_slope_v2 import verify_zero

const BASE = 2 ** 86;
const SECP_REM = 19;

struct EcPoint {
x: BigInt3,
y: BigInt3,
}

func unreduced_mul(a: BigInt3, b: BigInt3) -> (res_low: UnreducedBigInt3) {
// The result of the product is:
// sum_{i, j} a.d_i * b.d_j * BASE**(i + j)
// Since we are computing it mod secp256k1_prime, we replace the term
// a.d_i * b.d_j * BASE**(i + j)
// where i + j >= 3 with
// a.d_i * b.d_j * BASE**(i + j - 3) * 4 * SECP_REM
// since BASE ** 3 = 4 * SECP_REM (mod secp256k1_prime).
return (
UnreducedBigInt3(
d0=a.d0 * b.d0 + (a.d1 * b.d2 + a.d2 * b.d1) * (8 * SECP_REM),
d1=a.d0 * b.d1 + a.d1 * b.d0 + (a.d2 * b.d2) * (8 * SECP_REM),
d2=a.d0 * b.d2 + a.d1 * b.d1 + a.d2 * b.d0),
);
}

// Computes the square of a big integer, given in BigInt3 representation, modulo the
// secp256k1 prime.
//
// Has the same guarantees as in unreduced_mul(a, a).
func unreduced_sqr(a: BigInt3) -> (res_low: UnreducedBigInt3) {
tempvar twice_d0 = a.d0 * 2;
return (
UnreducedBigInt3(
d0=a.d0 * a.d0 + (a.d1 * a.d2) * (2 * 8 * SECP_REM),
d1=twice_d0 * a.d1 + (a.d2 * a.d2) * (8 * SECP_REM),
d2=twice_d0 * a.d2 + a.d1 * a.d1),
);
}


// Computes the slope of the elliptic curve at a given point.
// The slope is used to compute point + point.
//
// Arguments:
// point - the point to operate on.
//
// Returns:
// slope - the slope of the curve at point, in BigInt3 representation.
//
// Assumption: point != 0.

func compute_doubling_slope{range_check_ptr}(point: EcPoint) -> (slope: BigInt3) {
alloc_locals;
// Note that y cannot be zero: assume that it is, then point = -point, so 2 * point = 0, which
// contradicts the fact that the size of the curve is odd.
%{
from starkware.python.math_utils import ec_double_slope
from starkware.cairo.common.cairo_secp.secp_utils import pack
SECP_P = 2**255-19
# Compute the slope.
x = pack(ids.point.x, PRIME)
y = pack(ids.point.y, PRIME)
value = slope = ec_double_slope(point=(x, y), alpha=42204101795669822316448953119945047945709099015225996174933988943478124189485, p=SECP_P)
%}
let (slope: BigInt3) = nondet_bigint3();
// let alpha = Uint256(
// 143186476941636880901214103594843510573, 124026708105846590725274683684370988502
// );
let (x_sqr: UnreducedBigInt3) = unreduced_sqr(point.x);
let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, point.y);
let to_assert = UnreducedBigInt3(
d0=3 * x_sqr.d0 - 2 * slope_y.d0 + 44933163489768861888943917,
d1=3 * x_sqr.d1 - 2 * slope_y.d1 + 5088459194227531129123890,
d2=3 * x_sqr.d2 - 2 * slope_y.d2 + 7050102118787810395887998,
);
// let to_assert256 = bigint_to_uint256(to_assert);
// %{ print_u_256_info(ids.to_assert256, 'to_assert') %}

verify_zero(to_assert);

return (slope=slope);
}


func main{range_check_ptr}() {
let point_1 = EcPoint(BigInt3(512, 2412, 133), BigInt3(64, 0, 6546));

let (slope) = compute_doubling_slope(point_1);
assert slope = BigInt3(50745345459537348646984154, 66221251087242098185359002 ,8063180118678125382645462);
return ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ use super::{
ec_recover_sub_a_b,
},
field_arithmetic::uint384_div,
secp::ec_utils::{ec_negate_embedded_secp_p, ec_negate_import_secp_p},
secp::{
ec_utils::{compute_slope_and_assing_secp_p, ec_double_assign_new_y},
secp_utils::{SECP_P, SECP_P_V2},
ec_utils::{
compute_slope_and_assing_secp_p, ec_double_assign_new_y, ec_negate_embedded_secp_p,
ec_negate_import_secp_p,
},
secp_utils::{ALPHA, ALPHA_V2, SECP_P, SECP_P_V2},
},
vrf::{
fq::{inv_mod_p_uint256, uint512_unsigned_div_rem},
inv_mod_p_uint512::inv_mod_p_uint512,
},
vrf::fq::inv_mod_p_uint256,
vrf::{fq::uint512_unsigned_div_rem, inv_mod_p_uint512::inv_mod_p_uint512},
};
use crate::hint_processor::builtin_hint_processor::secp::ec_utils::ec_double_assign_new_x;
use crate::{
Expand Down Expand Up @@ -452,19 +456,32 @@ impl HintProcessor for BuiltinHintProcessor {
&hint_data.ids_data,
&hint_data.ap_tracking,
),
hint_code::EC_DOUBLE_SCOPE => compute_doubling_slope(
hint_code::EC_DOUBLE_SCOPE_V1 => compute_doubling_slope(
vm,
exec_scopes,
&hint_data.ids_data,
&hint_data.ap_tracking,
"point",
&SECP_P,
&ALPHA,
),
hint_code::EC_DOUBLE_SCOPE_V2 => compute_doubling_slope(
vm,
exec_scopes,
&hint_data.ids_data,
&hint_data.ap_tracking,
"point",
&SECP_P_V2,
&ALPHA_V2,
),
hint_code::EC_DOUBLE_SCOPE_WHITELIST => compute_doubling_slope(
vm,
exec_scopes,
&hint_data.ids_data,
&hint_data.ap_tracking,
"pt",
&SECP_P,
&ALPHA,
),
hint_code::COMPUTE_SLOPE_V1 => compute_slope_and_assing_secp_p(
vm,
Expand Down
12 changes: 11 additions & 1 deletion src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,14 +612,23 @@ y = pack(ids.point.y, PRIME) % SECP_P
# The modulo operation in python always returns a nonnegative number.
value = (-y) % SECP_P"#;

pub const EC_DOUBLE_SCOPE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
pub const EC_DOUBLE_SCOPE_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
from starkware.python.math_utils import ec_double_slope
# Compute the slope.
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 const EC_DOUBLE_SCOPE_V2: &str = r#"from starkware.python.math_utils import ec_double_slope
from starkware.cairo.common.cairo_secp.secp_utils import pack
SECP_P = 2**255-19
# Compute the slope.
x = pack(ids.point.x, PRIME)
y = pack(ids.point.y, PRIME)
value = slope = ec_double_slope(point=(x, y), alpha=42204101795669822316448953119945047945709099015225996174933988943478124189485, p=SECP_P)"#;

pub 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
Expand Down Expand Up @@ -657,6 +666,7 @@ 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)"#;

pub const IMPORT_SECP256R1_P: &str =
"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P";

Expand Down
53 changes: 47 additions & 6 deletions src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,14 @@ pub fn compute_doubling_slope(
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
point_alias: &str,
secp_p: &BigInt,
alpha: &BigInt,
) -> Result<(), HintError> {
exec_scopes.insert_value("SECP_P", SECP_P.clone());
exec_scopes.insert_value("SECP_P", secp_p.clone());
//ids.point
let point = EcPoint::from_var_name(point_alias, vm, ids_data, ap_tracking)?;

let value = ec_double_slope(
&(point.x.pack86(), point.y.pack86()),
&BigInt::zero(),
&SECP_P,
);
let value = ec_double_slope(&(point.x.pack86(), point.y.pack86()), alpha, secp_p);
exec_scopes.insert_value("value", value.clone());
exec_scopes.insert_value("slope", value);
Ok(())
Expand Down Expand Up @@ -416,6 +414,7 @@ pub fn n_pair_bits(
mod tests {
use super::*;
use crate::hint_processor::builtin_hint_processor::hint_code;
use crate::hint_processor::builtin_hint_processor::secp::secp_utils::SECP_P_V2;
use crate::stdlib::string::ToString;

use crate::{
Expand Down Expand Up @@ -525,6 +524,48 @@ mod tests {
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_ec_double_scope_v2_hint_ok() {
let hint_code = hint_code::EC_DOUBLE_SCOPE_V2;
let mut vm = vm_with_range_check!();
vm.segments = segments![
((1, 0), 512),
((1, 1), 2412),
((1, 2), 133),
((1, 3), 64),
((1, 4), 0),
((1, 5), 6546)
];

//Initialize fp
vm.run_context.fp = 1;

let ids_data = ids_data!["point"];
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!(
"48268701472940295594394094960749868325610234644833445333946260403470540790234"
)
),
(
"slope",
bigint_str!(
"48268701472940295594394094960749868325610234644833445333946260403470540790234"
)
),
("SECP_P", SECP_P_V2.clone())
]
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_compute_doubling_slope_wdivmod_ok() {
Expand Down
8 changes: 8 additions & 0 deletions src/hint_processor/builtin_hint_processor/secp/secp_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ lazy_static! {
"57896044618658097711785492504343953926634992332820282019728792003956564819949"
)
.unwrap();

pub(crate) static ref ALPHA: BigInt = BigInt::zero();

pub(crate) static ref ALPHA_V2: BigInt = BigInt::from_str(
"42204101795669822316448953119945047945709099015225996174933988943478124189485"
)
.unwrap();

// BASE = 2**86
pub(crate) static ref BASE: BigUint = BigUint::from_str(
"77371252455336267181195264"
Expand Down
13 changes: 10 additions & 3 deletions src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,13 @@ fn cairo_run_fq_test() {
run_program_simple_with_memory_holes(program_data.as_slice(), 120);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_run_ec_negate() {
let program_data = include_bytes!("../../cairo_programs/ec_negate.json");
run_program_simple_with_memory_holes(program_data.as_slice(), 0);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_run_compute_slope_v2_test() {
Expand All @@ -865,7 +872,7 @@ fn cairo_run_compute_slope_v2_test() {

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_run_ec_negate() {
let program_data = include_bytes!("../../cairo_programs/ec_negate.json");
run_program_simple_with_memory_holes(program_data.as_slice(), 0);
fn cairo_run_compute_doubling_slope_v2_test() {
let program_data = include_bytes!("../../cairo_programs/compute_doubling_slope_v2.json");
run_program_simple(program_data.as_slice());
}

0 comments on commit 0cbc70d

Please sign in to comment.