Skip to content

Commit

Permalink
Implement FastEcAddAssignNewY hint (#334)
Browse files Browse the repository at this point in the history
* Implement EcNegate hint

* Implement NondetBigint3V1 hint

* Fix context usage + add some functions to return constants

* Add scope check test utils + usage

* More comments and tests

* More tests

* Clean up some code

* Implement FastEcAddAssignNewY hint

* Use FeltZero/FeltOne in tests

* Use FeltZero in tests

* Add secp util functions to clean up hint

* Make function private

* Moving comments around

* Fix import

* Make return simpler

* Comment test values

* Comment test values

* Simpler context init in tests

* Add GetVariableValueAsBigInt method to scope manager

* Simpler tests

* Remove duplicate test check

* Clean up scope usage

* Fetch SECP_P from scope in FastEcAddAssignNewY

---------

Co-authored-by: Carmen Cabrera <kr1000a@gmail.com>
  • Loading branch information
har777 and cicr99 committed Apr 8, 2024
1 parent 87bff04 commit bba16b0
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 3 deletions.
10 changes: 10 additions & 0 deletions pkg/hintrunner/hinter/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ func (sm *ScopeManager) AssignVariable(name string, value any) error {
return nil
}

func (sm *ScopeManager) AssignVariables(values map[string]any) error {
for name, value := range values {
err := sm.AssignVariable(name, value)
if err != nil {
return err
}
}
return nil
}

func (sm *ScopeManager) GetVariableValue(name string) (any, error) {
scope, err := sm.getCurrentScope()
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions pkg/hintrunner/zero/hintcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ const (
// ------ Usort hints related code ------

// ------ Elliptic Curve hints related code ------
ecNegateCode string = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\ny = pack(ids.point.y, PRIME) % SECP_P\n# The modulo operation in python always returns a nonnegative number.\nvalue = (-y) % SECP_P"
nondetBigint3V1Code string = "from starkware.cairo.common.cairo_secp.secp_utils import split\n\nsegments.write_arg(ids.res.address_, split(value))"
ecNegateCode string = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\ny = pack(ids.point.y, PRIME) % SECP_P\n# The modulo operation in python always returns a nonnegative number.\nvalue = (-y) % SECP_P"
nondetBigint3V1Code string = "from starkware.cairo.common.cairo_secp.secp_utils import split\n\nsegments.write_arg(ids.res.address_, split(value))"
fastEcAddAssignNewYCode string = "value = new_y = (slope * (x0 - new_x) - y0) % SECP_P"

// ------ Signature hints related code ------

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 @@ -112,6 +112,8 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64
return createEcNegateHinter(resolver)
case nondetBigint3V1Code:
return createNondetBigint3V1Hinter(resolver)
case fastEcAddAssignNewYCode:
return createFastEcAddAssignNewYHinter()
// Blake hints
case blake2sAddUint256BigendCode:
return createBlake2sAddUint256Hinter(resolver, true)
Expand Down
53 changes: 52 additions & 1 deletion pkg/hintrunner/zero/zerohint_ec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package zero

import (
"fmt"
"math/big"

"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
secp_utils "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/utils"
Expand Down Expand Up @@ -56,7 +57,7 @@ func newEcNegateHint(point hinter.ResOperander) hinter.Hinter {
yBig.Neg(yBig)
yBig.Mod(yBig, secPBig)

return ctx.ScopeManager.AssignVariable("value", yBig)
return ctx.ScopeManager.AssignVariables(map[string]any{"value": yBig, "SECP_P": secPBig})
},
}
}
Expand Down Expand Up @@ -122,3 +123,53 @@ func createNondetBigint3V1Hinter(resolver hintReferenceResolver) (hinter.Hinter,

return newNondetBigint3V1Hint(res), nil
}

func newFastEcAddAssignNewYHint() hinter.Hinter {
return &GenericZeroHinter{
Name: "FastEcAddAssignNewY",
Op: func(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
//> value = new_y = (slope * (x0 - new_x) - y0) % SECP_P

slopeBig, err := ctx.ScopeManager.GetVariableValueAsBigInt("slope")
if err != nil {
return err
}
x0Big, err := ctx.ScopeManager.GetVariableValueAsBigInt("x0")
if err != nil {
return err
}
new_xBig, err := ctx.ScopeManager.GetVariableValueAsBigInt("new_x")
if err != nil {
return err
}
y0Big, err := ctx.ScopeManager.GetVariableValueAsBigInt("y0")
if err != nil {
return err
}
secPBig, err := ctx.ScopeManager.GetVariableValueAsBigInt("SECP_P")
if err != nil {
return err
}

new_yBig := new(big.Int)
new_yBig.Sub(x0Big, new_xBig)
new_yBig.Mul(new_yBig, slopeBig)
new_yBig.Sub(new_yBig, y0Big)
new_yBig.Mod(new_yBig, secPBig)

valueBig := new(big.Int)
valueBig.Set(new_yBig)

err = ctx.ScopeManager.AssignVariable("new_y", new_yBig)
if err != nil {
return err
}

return ctx.ScopeManager.AssignVariable("value", valueBig)
},
}
}

func createFastEcAddAssignNewYHinter() (hinter.Hinter, error) {
return newFastEcAddAssignNewYHint(), nil
}
61 changes: 61 additions & 0 deletions pkg/hintrunner/zero/zerohint_ec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
secp_utils "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/utils"
"github.com/NethermindEth/cairo-vm-go/pkg/utils"
"github.com/consensys/gnark-crypto/ecc/stark-curve/fp"
)
Expand Down Expand Up @@ -341,5 +342,65 @@ func TestZeroHintEc(t *testing.T) {
check: consecutiveVarValueEquals("res", []*fp.Element{feltString("2"), feltString("2"), &utils.FeltZero}),
},
},
"FastEcAddAssignNewY": {
{
operanders: []*hintOperander{},
ctxInit: func(ctx *hinter.HintRunnerContext) {
slopeBig := big.NewInt(100)
x0Big := big.NewInt(20)
new_xBig := big.NewInt(10)
y0Big := big.NewInt(10)
secPBig, _ := secp_utils.GetSecPBig()

ctx.ScopeManager.EnterScope(map[string]any{"slope": slopeBig, "x0": x0Big, "new_x": new_xBig, "y0": y0Big, "SECP_P": secPBig})
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newFastEcAddAssignNewYHint()
},
check: allVarValueInScopeEquals(map[string]any{
"new_y": big.NewInt(990),
"value": big.NewInt(990),
}),
},
{
operanders: []*hintOperander{},
ctxInit: func(ctx *hinter.HintRunnerContext) {
slopeBig := big.NewInt(0)
x0Big := big.NewInt(20)
new_xBig := big.NewInt(10)
y0Big := big.NewInt(10)
secPBig, _ := secp_utils.GetSecPBig()

ctx.ScopeManager.EnterScope(map[string]any{"slope": slopeBig, "x0": x0Big, "new_x": new_xBig, "y0": y0Big, "SECP_P": secPBig})
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newFastEcAddAssignNewYHint()
},
check: allVarValueInScopeEquals(map[string]any{
"new_y": bigIntString("115792089237316195423570985008687907853269984665640564039457584007908834671653", 10),
"value": bigIntString("115792089237316195423570985008687907853269984665640564039457584007908834671653", 10),
}),
},
{
operanders: []*hintOperander{},
ctxInit: func(ctx *hinter.HintRunnerContext) {
// GetSecPBig() + 20
slopeBig := bigIntString("115792089237316195423570985008687907853269984665640564039457584007908834671683", 10)
x0Big := big.NewInt(200)
new_xBig := big.NewInt(199)
y0Big := big.NewInt(20)
secPBig, _ := secp_utils.GetSecPBig()

ctx.ScopeManager.EnterScope(map[string]any{"slope": slopeBig, "x0": x0Big, "new_x": new_xBig, "y0": y0Big, "SECP_P": secPBig})
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newFastEcAddAssignNewYHint()
},
check: allVarValueInScopeEquals(map[string]any{
"new_y": big.NewInt(0),
"value": big.NewInt(0),
}),
},
},
})
}
8 changes: 8 additions & 0 deletions pkg/hintrunner/zero/zerohint_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ func varValueInScopeEquals(varName string, expected any) func(t *testing.T, ctx
}
}

func allVarValueInScopeEquals(expectedValues map[string]any) func(t *testing.T, ctx *hintTestContext) {
return func(t *testing.T, ctx *hintTestContext) {
for varName, expected := range expectedValues {
varValueInScopeEquals(varName, expected)(t, ctx)
}
}
}

func errorTextContains(s string) func(t *testing.T, ctx *hintTestContext, err error) {
return func(t *testing.T, ctx *hintTestContext, err error) {
if err == nil {
Expand Down

0 comments on commit bba16b0

Please sign in to comment.