Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hints): add NewHint#28 #989

Merged
merged 12 commits into from
Apr 15, 2023
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,42 @@

#### Upcoming Changes

* 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`
Expand Down
125 changes: 125 additions & 0 deletions cairo_programs/ed25519_ec.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
%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 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).
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_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);

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
);

return ();
}

func main{range_check_ptr: felt}() {
test_compute_double_slope();
test_compute_slope();

return ();
}
53 changes: 53 additions & 0 deletions cairo_programs/ed25519_field.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
%builtins range_check

// Source: https://github.com/NilFoundation/cairo-ed25519/blob/fee64a1a60b2e07b3b5c20df57f31d7ffcb29ac9/ed25519_field.cairo

from starkware.cairo.common.cairo_secp.bigint import BASE, BigInt3, UnreducedBigInt3, nondet_bigint3
from starkware.cairo.common.cairo_secp.constants import SECP_REM

func verify_zero{range_check_ptr}(val: UnreducedBigInt3) {
let x = val;
// Used just to import pack in scope
%{
from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack

value = pack(ids.x, PRIME) % SECP_P
%}
nondet_bigint3();

let q = [ap];
%{
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
%}
let q_biased = [ap + 1];
q_biased = q + 2 ** 127, ap++;
[range_check_ptr] = q_biased, ap++;

tempvar r1 = (val.d0 + q * SECP_REM) / BASE;
assert [range_check_ptr + 1] = r1 + 2 ** 127;

tempvar r2 = (val.d1 + r1) / BASE;
assert [range_check_ptr + 2] = r2 + 2 ** 127;

assert val.d2 = q * (BASE / 4) - r2;

let range_check_ptr = range_check_ptr + 3;
return ();
}

func test_verify_zero{range_check_ptr: felt}() {
let val = UnreducedBigInt3(0, 0, 0);

verify_zero(val);

return ();
}

func main{range_check_ptr: felt}() {
test_verify_zero();

return ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,9 @@ impl HintProcessor for BuiltinHintProcessor {
hint_code::BLAKE2S_COMPUTE => {
compute_blake2s(vm, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::VERIFY_ZERO => verify_zero(vm, &hint_data.ids_data, &hint_data.ap_tracking),
hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 => {
verify_zero(vm, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::NONDET_BIGINT3 => {
nondet_bigint3(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
}
Expand Down Expand Up @@ -353,12 +355,36 @@ 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::COMPUTE_SLOPE => {
compute_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,
&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)
}
Expand Down
25 changes: 24 additions & 1 deletion src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,17 @@ pub(crate) const NONDET_BIGINT3: &str = r#"from starkware.cairo.common.cairo_sec

segments.write_arg(ids.res.address_, split(value))"#;

pub(crate) const VERIFY_ZERO: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
pub(crate) const VERIFY_ZERO_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, 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"#;

pub(crate) const VERIFY_ZERO_V2: &str = r#"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"#;

pub(crate) const REDUCE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack

value = pack(ids.x, PRIME) % SECP_P"#;
Expand Down Expand Up @@ -455,6 +460,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

Expand All @@ -465,6 +478,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)
Expand Down