Skip to content

Commit

Permalink
Merge branch 'main' into feat(hint)/68-sha512_input
Browse files Browse the repository at this point in the history
  • Loading branch information
Oppen committed Apr 27, 2023
2 parents 97b4d96 + 0fad948 commit b5cc938
Show file tree
Hide file tree
Showing 12 changed files with 668 additions and 56 deletions.
42 changes: 41 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
%{ ids.full_word = int(ids.n_bytes >= 8) %}
```

* Add alternative hint code for nondet_bigint3 hint [#1071](https://github.com/lambdaclass/cairo-rs/pull/1071)

`BuiltinHintProcessor` now supports the following hint:

```python
%{
from starkware.cairo.common.cairo_secp.secp_utils import split
segments.write_arg(ids.res.address_, split(value))
%}
```

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

`BuiltinHintProcessor` now supports the following hint:
Expand All @@ -27,7 +38,7 @@
value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P
```

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

`BuiltinHintProcessor` now supports the following hint:

Expand Down Expand Up @@ -123,6 +134,8 @@ Add missing hint on vrf.json lib [#1053](https://github.com/lambdaclass/cairo-rs
segments.write_arg(ids.blake2s_ptr_end, padding)
%}

* Add `Program::iter_identifiers(&self) -> Iterator<Item = (&str, &Identifier)>` to get an iterator over the program's identifiers [#1079](https://github.com/lambdaclass/cairo-rs/pull/1079)

* Implement hint on `assert_le_felt` for versions 0.6.0 and 0.8.2 [#1047](https://github.com/lambdaclass/cairo-rs/pull/1047):

`BuiltinHintProcessor` now supports the following hints:
Expand Down Expand Up @@ -362,6 +375,19 @@ Add missing hint on vrf.json lib [#1053](https://github.com/lambdaclass/cairo-rs
* Remove duplicated tests in cairo_run_test
* BREAKING CHANGE: `MemorySegmentManager.get_memory_holes` now also receives the amount of builtins in the vm. Signature is now `pub fn get_memory_holes(&self, builtin_count: usize) -> Result<usize, MemoryError>`

* Add missing hints on cairo_secp lib [#1026](https://github.com/lambdaclass/cairo-rs/pull/1026):

`BuiltinHintProcessor` now supports the following hints:

```python
from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA
```
and:

```python
from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N
```

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

`BuiltinHintProcessor` now supports the following hint:
Expand Down Expand Up @@ -412,6 +438,20 @@ Add missing hint on vrf.json lib [#1053](https://github.com/lambdaclass/cairo-rs
ids.flag = 1 if k > 0 else 0
```

* Add missing hint on cairo_secp lib [#1057](https://github.com/lambdaclass/cairo-rs/pull/1057):

`BuiltinHintProcessor` now supports the following hint:

```python
from starkware.cairo.common.cairo_secp.secp_utils import 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=ALPHA, p=SECP_P)
```

* Add missing hint on uint256_improvements lib [#1025](https://github.com/lambdaclass/cairo-rs/pull/1025):

`BuiltinHintProcessor` now supports the following hint:
Expand Down
212 changes: 212 additions & 0 deletions cairo_programs/ec_double_slope.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
%builtins range_check

// Source: https://github.com/rdubois-crypto/efficient-secp256r1/blob/4b74807c5e91f1ed4cb00a1c973be05c63986e61/src/secp256r1/ec.cairo
from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3
from starkware.cairo.common.cairo_secp.ec import EcPoint

// src.secp256r1.constants
// SECP_REM is defined by the equation:
// secp256r1_prime = 2 ** 256 - SECP_REM.
const SECP_REM = 2 ** 224 - 2 ** 192 - 2 ** 96 + 1;

const BASE = 2 ** 86;

// A = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
const A0 = 0x3ffffffffffffffffffffc;
const A1 = 0x3ff;
const A2 = 0xffffffff0000000100000;

// Constants for unreduced_mul/sqr
const s2 = (-(2 ** 76)) - 2 ** 12;
const s1 = (-(2 ** 66)) + 4;
const s0 = 2 ** 56;

const r2 = 2 ** 54 - 2 ** 22;
const r1 = -(2 ** 12);
const r0 = 4;

// src.secp256r1.field
// Adapt from starkware.cairo.common.math's assert_250_bit
func assert_165_bit{range_check_ptr}(value) {
const UPPER_BOUND = 2 ** 165;
const SHIFT = 2 ** 128;
const HIGH_BOUND = UPPER_BOUND / SHIFT;

let low = [range_check_ptr];
let high = [range_check_ptr + 1];

%{
from starkware.cairo.common.math_utils import as_int

# Correctness check.
value = as_int(ids.value, PRIME) % PRIME
assert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'

# Calculation for the assertion.
ids.high, ids.low = divmod(ids.value, ids.SHIFT)
%}

assert [range_check_ptr + 2] = HIGH_BOUND - 1 - high;

assert value = high * SHIFT + low;

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

// src.secp256r1.field
// Computes the multiplication of two big integers, given in BigInt3 representation, modulo the
// secp256r1 prime.
//
// Arguments:
// x, y - the two BigInt3 to operate on.
//
// Returns:
// x * y in an UnreducedBigInt3 representation (the returned limbs may be above 3 * BASE).
//
// This means that if unreduced_mul is called on the result of nondet_bigint3, or the difference
// between two such results, we have:
// Soundness guarantee: the limbs are in the range ().
// Completeness guarantee: the limbs are in the range ().
func unreduced_mul(a: BigInt3, b: BigInt3) -> (res_low: UnreducedBigInt3) {
tempvar twice_d2 = a.d2 * b.d2;
tempvar d1d2 = a.d2 * b.d1 + a.d1 * b.d2;
return (
UnreducedBigInt3(
d0=a.d0 * b.d0 + s0 * twice_d2 + r0 * d1d2,
d1=a.d1 * b.d0 + a.d0 * b.d1 + s1 * twice_d2 + r1 * d1d2,
d2=a.d2 * b.d0 + a.d1 * b.d1 + a.d0 * b.d2 + s2 * twice_d2 + r2 * d1d2,
),
);
}

// src.secp256r1.field
// Computes the square of a big integer, given in BigInt3 representation, modulo the
// secp256r1 prime.
//
// Has the same guarantees as in unreduced_mul(a, a).
func unreduced_sqr(a: BigInt3) -> (res_low: UnreducedBigInt3) {
tempvar twice_d2 = a.d2 * a.d2;
tempvar twice_d1d2 = a.d2 * a.d1 + a.d1 * a.d2;
tempvar d1d0 = a.d1 * a.d0;
return (
UnreducedBigInt3(
d0=a.d0 * a.d0 + s0 * twice_d2 + r0 * twice_d1d2,
d1=d1d0 + d1d0 + s1 * twice_d2 + r1 * twice_d1d2,
d2=a.d2 * a.d0 + a.d1 * a.d1 + a.d0 * a.d2 + s2 * twice_d2 + r2 * twice_d1d2,
),
);
}

// src.secp256r1.field
// Verifies that the given unreduced value is equal to zero modulo the secp256r1 prime.
//
// Completeness assumption: val's limbs are in the range (-2**210.99, 2**210.99).
// Soundness assumption: val's limbs are in the range (-2**250, 2**250).
func verify_zero{range_check_ptr}(val: UnreducedBigInt3) {
alloc_locals;
local q;
// local q_sign;
let q_sign = 1;
// original:
// %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP256R1_P as SECP_P %}
// %{
// from starkware.cairo.common.cairo_secp.secp_utils import 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}."
// if q >= 0:
// ids.q = q % PRIME
// ids.q_sign = 1
// else:
// ids.q = (0-q) % PRIME
// ids.q_sign = -1 % PRIME
// %}
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %}
%{
from starkware.cairo.common.cairo_secp.secp_utils import 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
%}
// assert_250_bit(q); // 256K steps
// assert_le_felt(q, 2**165); // 275K steps
assert_165_bit(q);
assert q_sign * (val.d2 + val.d1 / BASE + val.d0 / BASE ** 2) = q * (
(BASE / 4) - SECP_REM / BASE ** 2
);
// Multiply by BASE**2 both sides:
// (q_sign) * val = q * (BASE**3 / 4 - SECP_REM)
// = q * (2**256 - SECP_REM) = q * secp256r1_prime = 0 mod secp256r1_prime
return ();
}

// 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) {
// 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.
// originals:
// %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP256R1_P as SECP_P %}
// %{ from starkware.cairo.common.cairo_secp.secp_utils import SECP256R1_ALPHA as ALPHA %}
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %}
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA %}
%{
from starkware.cairo.common.cairo_secp.secp_utils import 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=ALPHA, p=SECP_P)
%}
let (slope: BigInt3) = nondet_bigint3();

let (x_sqr: UnreducedBigInt3) = unreduced_sqr(point.x);
let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, point.y);
verify_zero(
UnreducedBigInt3(
d0=3 * x_sqr.d0 + A0 - 2 * slope_y.d0,
d1=3 * x_sqr.d1 + A1 - 2 * slope_y.d1,
d2=3 * x_sqr.d2 + A2 - 2 * slope_y.d2,
),
);

return (slope=slope);
}

func test_doubling_slope{range_check_ptr}() {
let point = EcPoint(BigInt3(614323, 5456867, 101208), BigInt3(773712524, 77371252, 5298795));

let (slope) = compute_doubling_slope(point);

assert slope = BigInt3(
64081873649130491683833713, 34843994309543177837008178, 16548672716077616016846383
);

let point = EcPoint(
BigInt3(51215, 36848548548458, 634734734), BigInt3(26362, 263724839599, 901297012)
);

let (slope) = compute_doubling_slope(point);

assert slope = BigInt3(
71848883893335852660776740, 75644451964360469099209675, 547087410329256463669633
);

return ();
}

func main{range_check_ptr}() {
test_doubling_slope();
return ();
}
45 changes: 45 additions & 0 deletions cairo_programs/nondet_bigint3_v2.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
%builtins range_check

from starkware.cairo.common.cairo_secp.bigint import BigInt3, BASE

// Hint arguments: value.
func nondet_bigint3{range_check_ptr}() -> (res: BigInt3) {
// The result should be at the end of the stack after the function returns.
let res: BigInt3 = [cast(ap + 5, BigInt3*)];
%{
from starkware.cairo.common.cairo_secp.secp_utils import split
segments.write_arg(ids.res.address_, split(value))
%}
// The maximal possible sum of the limbs, assuming each of them is in the range [0, BASE).
const MAX_SUM = 3 * (BASE - 1);
assert [range_check_ptr] = MAX_SUM - (res.d0 + res.d1 + res.d2);

// Prepare the result at the end of the stack.
tempvar range_check_ptr = range_check_ptr + 4;
[range_check_ptr - 3] = res.d0, ap++;
[range_check_ptr - 2] = res.d1, ap++;
[range_check_ptr - 1] = res.d2, ap++;
static_assert &res + BigInt3.SIZE == ap;
return (res=res);
}

func main{range_check_ptr}() {
alloc_locals;
// Take these hints from div_mod_n just to have a value in scope
local a: BigInt3 = BigInt3(1,2,3);
local b: BigInt3 = BigInt3(4,5,6);
%{
from starkware.cairo.common.cairo_secp.secp_utils import N, pack
from starkware.python.math_utils import div_mod, safe_div

a = pack(ids.a, PRIME)
b = pack(ids.b, PRIME)
value = res = div_mod(a, b, N)
%}
let (r) = nondet_bigint3();
assert r.d0 = 46511138620617205537268188;
assert r.d1 = 26286155657000021849694253;
assert r.d2 = 3102515549921694024741409;
return();
}

Loading

0 comments on commit b5cc938

Please sign in to comment.