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

Secp p hints #275

Merged
merged 63 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
977ba29
Add ec hints
mmsc2 Sep 14, 2023
70a9db2
Implement hints
mmsc2 Sep 15, 2023
864b7b8
Add the hints to the processor
mmsc2 Sep 15, 2023
7df4192
Test pack86 function
mmsc2 Sep 15, 2023
1a66309
Test hint
mmsc2 Sep 15, 2023
91ffa57
Delete debug info, Test ec negative op
mmsc2 Sep 18, 2023
7bf1909
Second hint test
mmsc2 Sep 18, 2023
5d2d256
Merge main
mmsc2 Sep 18, 2023
a08c642
Test embedded hint
mmsc2 Sep 18, 2023
029fe50
Merge branch 'main' into EcHint
mmsc2 Sep 18, 2023
762a566
Merge branch 'main' into EcHint
mmsc2 Sep 18, 2023
6c6eed9
Change to Camel case
mmsc2 Sep 19, 2023
ec9345c
Implement slope hints
mmsc2 Sep 19, 2023
9d14678
Fix merge conflict
mmsc2 Sep 19, 2023
ff7fb50
Fix format
mmsc2 Sep 19, 2023
4e9afc5
Delete github conflict string
mmsc2 Sep 19, 2023
cc53b65
Tests hints
mmsc2 Sep 19, 2023
a0d269b
Tests hints slopes
mmsc2 Sep 19, 2023
c25e25c
Fix merge conflict
mmsc2 Sep 19, 2023
a27b814
Rename misleading name function
mmsc2 Sep 19, 2023
51fedf0
Merge branch 'main' into EcSlopeHint
mmsc2 Sep 19, 2023
9e39502
Fix function name
mmsc2 Sep 19, 2023
327299b
Fix format
mmsc2 Sep 19, 2023
0fdad83
Fix error in function call
mmsc2 Sep 19, 2023
ba81ca8
Merge branch 'main' into EcSlopeHint
entropidelic Sep 19, 2023
78dd5d0
Delete debug info
mmsc2 Sep 19, 2023
c023bea
Merge branch 'EcSlopeHint' of github.com:lambdaclass/cairo-vm.go into…
mmsc2 Sep 19, 2023
facfb8a
Delete unused import
mmsc2 Sep 19, 2023
f195395
Merge main
mmsc2 Sep 20, 2023
76c8b8b
Secp hints
mmsc2 Sep 20, 2023
2e1b1f9
Merge main
mmsc2 Sep 20, 2023
41c5e00
Secpr21
mmsc2 Sep 20, 2023
ed75168
Add it to the hint processor
mmsc2 Sep 20, 2023
e868fa0
Hints secp
mmsc2 Sep 20, 2023
b88e485
Merge main
mmsc2 Sep 20, 2023
efad459
bigint3 nondet
mmsc2 Sep 20, 2023
113bb9b
bigint bug fixed
mmsc2 Sep 20, 2023
c09d921
Zero verify
mmsc2 Sep 20, 2023
50994ad
Merge main
mmsc2 Sep 21, 2023
2216d94
Merge branch 'main' into SecpPHints
mmsc2 Sep 21, 2023
2d44427
Add hint to hint processor
mmsc2 Sep 21, 2023
d50207a
Mege main
mmsc2 Sep 21, 2023
c9f1709
Merge branch 'main' into SecpPHints
mmsc2 Sep 21, 2023
46e8bd6
Merge branch 'SecpPHints' of github.com:lambdaclass/cairo-vm.go into …
mmsc2 Sep 21, 2023
7720f42
Debug info
mmsc2 Sep 22, 2023
5775336
Merge main
mmsc2 Sep 22, 2023
5ce7e74
Prints
mmsc2 Sep 22, 2023
3cd665a
Merge branch 'SecpPHints' of github.com:lambdaclass/cairo-vm.go into …
mmsc2 Sep 22, 2023
c7faf9a
Merge branch 'SecpPHints' of github.com:lambdaclass/cairo-vm.go into …
mmsc2 Sep 22, 2023
3969b1b
Test verify with unit test
mmsc2 Sep 25, 2023
942c204
Debug unit test
mmsc2 Sep 25, 2023
ee521d0
Test verify zero with debug
mmsc2 Sep 25, 2023
621a616
Non det big 3 test
mmsc2 Sep 25, 2023
6d2cc54
Modify test to use ids manager
mmsc2 Sep 25, 2023
552715d
debug info
mmsc2 Sep 26, 2023
af1afcb
Fix broken test
mmsc2 Sep 26, 2023
b5f44e2
Move file from hints_utils and rename
mmsc2 Sep 26, 2023
6cfabdf
Delete debug
mmsc2 Sep 26, 2023
69d015e
Move integration test to cairo_run_test.go
mmsc2 Sep 26, 2023
6527b72
Return error of IdsData.Insert
mmsc2 Sep 26, 2023
2bcf015
Change to camel case
mmsc2 Sep 26, 2023
a09bda2
Fix merge conflict
mmsc2 Sep 26, 2023
d756a63
Delete merge characters
mmsc2 Sep 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ();
}
56 changes: 56 additions & 0 deletions pkg/hints/bigint_hint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package hints

import (
"errors"
"math/big"

. "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils"
"github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks"
. "github.com/lambdaclass/cairo-vm.go/pkg/types"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm"
"github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)

/*
Implements hint:
%{
from starkware.cairo.common.cairo_secp.secp_utils import split

segments.write_arg(ids.res.address_, split(value))
%}
*/

func NondetBigInt3(virtual_machine VirtualMachine, execScopes ExecutionScopes, idsData IdsManager) error {
resRelloc, err := idsData.GetAddr("res", &virtual_machine)
if err != nil {
return err
}

valueUncast, err := execScopes.Get("value")
if err != nil {
return err
}
value, ok := valueUncast.(big.Int)
if !ok {
return errors.New("Could not cast value into big int")
}

bigint3Split, err := Bigint3Split(value)
if err != nil {
return err
}

arg := make([]memory.MaybeRelocatable, 0)

for i := 0; i < 3; i++ {
m := memory.NewMaybeRelocatableFelt(lambdaworks.FeltFromBigInt(&bigint3Split[i]))
arg = append(arg, *m)
}

_, loadErr := virtual_machine.Segments.LoadData(resRelloc, &arg)
if loadErr != nil {
return loadErr
}

return nil
}
75 changes: 75 additions & 0 deletions pkg/hints/bigint_hint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package hints_test

import (
"math/big"
"testing"

. "github.com/lambdaclass/cairo-vm.go/pkg/hints"
. "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_codes"
. "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils"
"github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks"
. "github.com/lambdaclass/cairo-vm.go/pkg/types"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)

func TestNonDetBigInt3Ok(t *testing.T) {
vm := NewVirtualMachine()

vm.Segments.AddSegment()
vm.Segments.AddSegment()
vm.Segments.AddSegment()

vm.RunContext.Pc = NewRelocatable(0, 0)
vm.RunContext.Ap = NewRelocatable(1, 6)
vm.RunContext.Fp = NewRelocatable(1, 6)

value, _ := new(big.Int).SetString("7737125245533626718119526477371252455336267181195264773712524553362", 10)
execScopes := NewExecutionScopes()

execScopes.AssignOrUpdateVariable("value", *value)

idsManager := SetupIdsForTest(
map[string][]*MaybeRelocatable{
"res": {nil},
},
vm,
)

hintProcessor := CairoVmHintProcessor{}
hintData := any(HintData{
Ids: idsManager,
Code: NONDET_BIGINT3_V1,
})
err := hintProcessor.ExecuteHint(vm, &hintData, nil, execScopes)
if err != nil {
t.Errorf("Non Det Big Int 3 hint test failed with error: %s", err)
} else {
valueInStruct0, err := idsManager.GetStructFieldFelt("res", 0, vm)
expected0 := lambdaworks.FeltFromDecString("773712524553362")
if err != nil {
t.Errorf("error fetching from ids manager : %s", err)
}
if valueInStruct0 != expected0 {
t.Errorf(" Incorrect field value %s, expected %s", valueInStruct0.ToBigInt().Text(10), expected0.ToBigInt().Text(10))
}

valueInStruct1, err := idsManager.GetStructFieldFelt("res", 1, vm)
expected1 := lambdaworks.FeltFromDecString("57408430697461422066401280")
if err != nil {
t.Errorf("error fetching from ids manager : %s", err)
}
if valueInStruct1 != expected1 {
t.Errorf(" Incorrect field value %s, expected %s", valueInStruct1.ToBigInt().Text(10), expected1.ToBigInt().Text(10))
}

valueInStruct2, err := idsManager.GetStructFieldFelt("res", 2, vm)
expected2 := lambdaworks.FeltFromDecString("1292469707114105")
if err != nil {
t.Errorf("error fetching from ids manager : %s", err)
}
if valueInStruct2 != expected2 {
t.Errorf(" Incorrect field value %s, expected %s", valueInStruct2.ToBigInt().Text(10), expected2.ToBigInt().Text(10))
}
}
}
Loading
Loading