Skip to content

Commit

Permalink
Cairo0 get point from x hint (#340)
Browse files Browse the repository at this point in the history
* Implement VerifyECDSASignature hint

* Fixed retrieving memory with signature via pointer

* Scooped out the deref from double deref in test cases

* Implement GetPointFromXHint

* Modify zerohint.go

* Add testcases to the hint

* Add final testcases

* Changes from merging main

* Remove faulty integration tests

* Changes named in the PR discussion

* Fixes after merge

* Fixes from conversation
  • Loading branch information
MaksymMalicki committed Apr 15, 2024
1 parent 1405ff0 commit d50bca6
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 5 deletions.
10 changes: 7 additions & 3 deletions pkg/hintrunner/utils/math_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ func AsInt(valueFelt *fp.Element) *big.Int {

var valueBig big.Int
valueFelt.BigInt(&valueBig)
return AsIntBig(&valueBig)
}

func AsIntBig(value *big.Int) *big.Int {
boundBig := new(big.Int).Div(fp.Modulus(), big.NewInt(2))

// val if val < prime // 2 else val - prime
if valueBig.Cmp(boundBig) == -1 {
return &valueBig
if value.Cmp(boundBig) == -1 {
return value
}
return new(big.Int).Sub(&valueBig, fp.Modulus())
return new(big.Int).Sub(value, fp.Modulus())
}
4 changes: 4 additions & 0 deletions pkg/hintrunner/utils/secp_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func SecPPacked(limbs [3]*fp.Element) (*big.Int, error) {
return packedBig, nil
}

func GetBetaBig() *big.Int {
return big.NewInt(7)
}

func SecPSplit(num *big.Int) ([]*big.Int, error) {
// https://github.com/starkware-libs/cairo-lang/blob/efa9648f57568aad8f8a13fbf027d2de7c63c2c0/src/starkware/cairo/common/cairo_secp/secp_utils.py#L14

Expand Down
1 change: 1 addition & 0 deletions pkg/hintrunner/zero/hintcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const (

// ------ Signature hints related code ------
verifyECDSASignatureCode string = "ecdsa_builtin.add_signature(ids.ecdsa_ptr.address_, (ids.signature_r, ids.signature_s))"
getPointFromXCode string = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\nx_cube_int = pack(ids.x_cube, PRIME) % SECP_P\ny_square_int = (x_cube_int + ids.BETA) % SECP_P\ny = pow(y_square_int, (SECP_P + 1) // 4, SECP_P)\nif ids.v % 2 == y % 2:\nvalue = y\nelse:\nvalue = (-y) % SECP_P"
importSecp256R1PCode string = "from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P"
verifyZeroCode string = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME"

Expand Down
2 changes: 2 additions & 0 deletions pkg/hintrunner/zero/zerohint.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64
// Signature hints
case verifyECDSASignatureCode:
return createVerifyECDSASignatureHinter(resolver)
case getPointFromXCode:
return createGetPointFromXHinter(resolver)
case importSecp256R1PCode:
return createImportSecp256R1PHinter()
case verifyZeroCode:
Expand Down
85 changes: 83 additions & 2 deletions pkg/hintrunner/zero/zerohint_signatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package zero

import (
"fmt"
"math/big"

"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/utils"
secp_utils "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/utils"
VM "github.com/NethermindEth/cairo-vm-go/pkg/vm"
"github.com/NethermindEth/cairo-vm-go/pkg/vm/builtins"
"github.com/consensys/gnark-crypto/ecc/stark-curve/fp"
)

func newVerifyECDSASignatureHinter(ecdsaPtr, signature_r, signature_s hinter.ResOperander) hinter.Hinter {
Expand Down Expand Up @@ -52,12 +54,91 @@ func createVerifyECDSASignatureHinter(resolver hintReferenceResolver) (hinter.Hi
return newVerifyECDSASignatureHinter(ecdsaPtr, signature_r, signature_s), nil
}

func newGetPointFromXHinter(xCube, v hinter.ResOperander) hinter.Hinter {
return &GenericZeroHinter{
Name: "VerifyECDSASignature",
Op: func(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
//> from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
//> x_cube_int = pack(ids.x_cube, PRIME) % SECP_P
//> y_square_int = (x_cube_int + ids.BETA) % SECP_P
//> y = pow(y_square_int, (SECP_P + 1) // 4, SECP_P)
//> if ids.v % 2 == y % 2:
//> value = y
//> else:
//> value = (-y) % SECP_P
xCubeAddr, err := xCube.GetAddress(vm)
if err != nil {
return err
}

xCubeMemoryValues, err := hinter.GetConsecutiveValues(vm, xCubeAddr, 3)
if err != nil {
return err
}
v, err := hinter.ResolveAsFelt(vm, v)
if err != nil {
return err
}

//> from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
secpBig, _ := secp_utils.GetSecPBig()

//> x_cube_int = pack(ids.x_cube, PRIME) % SECP_P
var xCubeValues [3]*fp.Element
for i := 0; i < 3; i++ {
xCubeValues[i], err = xCubeMemoryValues[i].FieldElement()
if err != nil {
return err
}
}
xCubeIntBig, err := secp_utils.SecPPacked(xCubeValues)
if err != nil {
return err
}
xCubeIntBig.Mod(xCubeIntBig, secpBig)

//> y_square_int = (x_cube_int + ids.BETA) % SECP_P
ySquareIntBig := new(big.Int).Add(xCubeIntBig, secp_utils.GetBetaBig())
ySquareIntBig.Mod(ySquareIntBig, secpBig)

//> y = pow(y_square_int, (SECP_P + 1) // 4, SECP_P)
exponent := new(big.Int).Div(new(big.Int).Add(secpBig, big.NewInt(1)), big.NewInt(4))
y := new(big.Int).Exp(ySquareIntBig, exponent, secpBig)
vBig := v.BigInt(new(big.Int))

//> if ids.v % 2 == y % 2:
//> value = y
//> else:
//> value = (-y) % SECP_P
value := new(big.Int)
if vBig.Bit(0) == y.Bit(0) {
value.Set(y)
} else {
value.Mod(value.Neg(y), secpBig)
}
return ctx.ScopeManager.AssignVariable("value", value)
},
}
}

func createGetPointFromXHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
xCube, err := resolver.GetResOperander("x_cube")
if err != nil {
return nil, err
}
v, err := resolver.GetResOperander("v")
if err != nil {
return nil, err
}
return newGetPointFromXHinter(xCube, v), nil
}

func newImportSecp256R1PHinter() hinter.Hinter {
return &GenericZeroHinter{
Name: "Secp256R1",
Op: func(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
//> from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P
SECP256R1_PBig, ok := utils.GetSecp256R1_P()
SECP256R1_PBig, ok := secp_utils.GetSecp256R1_P()
if !ok {
return fmt.Errorf("SECP256R1_P failed.")
}
Expand Down
51 changes: 51 additions & 0 deletions pkg/hintrunner/zero/zerohint_signatures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
"github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet"
"github.com/NethermindEth/cairo-vm-go/pkg/utils"
"github.com/stretchr/testify/require"
)

Expand All @@ -26,6 +27,56 @@ func TestSignatures(t *testing.T) {
},
},
},
"GetPointFromX": {
{
//> if v % 2 == y % 2
operanders: []*hintOperander{
{Name: "xCube.d0", Kind: apRelative, Value: &utils.FeltZero},
{Name: "xCube.d1", Kind: apRelative, Value: &utils.FeltZero},
{Name: "xCube.d2", Kind: apRelative, Value: &utils.FeltZero},
{Name: "v", Kind: apRelative, Value: &utils.FeltZero},
},
ctxInit: func(ctx *hinter.HintRunnerContext) {
ctx.ScopeManager.EnterScope(map[string]any{})
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newGetPointFromXHinter(ctx.operanders["xCube.d0"], ctx.operanders["v"])
},
check: varValueInScopeEquals("value", bigIntString("64828261740814840065360381756190772627110652128289340260788836867053167272156", 10)),
},
// if v % 2 != y % 2:
{
operanders: []*hintOperander{
{Name: "xCube.d0", Kind: apRelative, Value: &utils.FeltOne},
{Name: "xCube.d1", Kind: apRelative, Value: &utils.FeltOne},
{Name: "xCube.d2", Kind: apRelative, Value: &utils.FeltZero},
{Name: "v", Kind: apRelative, Value: &utils.FeltZero},
},
ctxInit: func(ctx *hinter.HintRunnerContext) {
ctx.ScopeManager.EnterScope(map[string]any{})
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newGetPointFromXHinter(ctx.operanders["xCube.d0"], ctx.operanders["v"])
},
check: varValueInScopeEquals("value", bigIntString("3754707778961574900176639079436749683878498834289427635045629810524611907876", 10)),
},
// values are 2**86 BASE
{
operanders: []*hintOperander{
{Name: "xCube.d0", Kind: apRelative, Value: feltString("77371252455336267181195264")},
{Name: "xCube.d1", Kind: apRelative, Value: feltString("77371252455336267181195264")},
{Name: "xCube.d2", Kind: apRelative, Value: feltString("77371252455336267181195264")},
{Name: "v", Kind: apRelative, Value: feltString("77371252455336267181195264")},
},
ctxInit: func(ctx *hinter.HintRunnerContext) {
ctx.ScopeManager.EnterScope(map[string]any{})
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newGetPointFromXHinter(ctx.operanders["xCube.d0"], ctx.operanders["v"])
},
check: varValueInScopeEquals("value", bigIntString("64330220386510520462271671435567806262107470356169873352512014089172394266548", 10)),
},
},
"ImportSecp256R1P": {
{
operanders: []*hintOperander{},
Expand Down
1 change: 1 addition & 0 deletions pkg/hintrunner/zero/zerohint_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package zero

import (
"fmt"

"math/big"
"testing"

Expand Down

0 comments on commit d50bca6

Please sign in to comment.