Skip to content

Commit

Permalink
Ec slope hint (#257)
Browse files Browse the repository at this point in the history
* Add ec hints

* Implement hints

* Add the hints to the processor

* Test pack86 function

* Test hint

* Delete debug info, Test ec negative op

* Second hint test

* Test embedded hint

* Change to Camel case

* Implement slope hints

* Fix format

* Delete github conflict string

* Tests hints

* Tests hints slopes

* Rename misleading name function

* Fix function name

* Fix error in function call

* Delete debug info

* Delete unused import

* Change name convention

* Change naming convention

* Fix naming convention in variables

---------

Co-authored-by: Mariano A. Nicolini <[email protected]>
  • Loading branch information
mmsc2 and entropidelic authored Sep 21, 2023
1 parent 1cdb017 commit 102682a
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 28 deletions.
145 changes: 120 additions & 25 deletions pkg/hints/ec_hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"errors"
"math/big"

"github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils"
"github.com/lambdaclass/cairo-vm.go/pkg/builtins"
. "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/types"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm"
"github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)

Expand All @@ -31,10 +32,10 @@ func (val *BigInt3) Pack86() big.Int {
return *sum
}

func BigInt3FromBaseAddr(addr memory.Relocatable, virtual_machine vm.VirtualMachine) (BigInt3, error) {
func BigInt3FromBaseAddr(addr memory.Relocatable, vm VirtualMachine) (BigInt3, error) {
limbs := make([]lambdaworks.Felt, 0)
for i := 0; i < 3; i++ {
felt, err := virtual_machine.Segments.Memory.GetFelt(addr.AddUint(uint(i)))
felt, err := vm.Segments.Memory.GetFelt(addr.AddUint(uint(i)))
if err == nil {
limbs = append(limbs, felt)
} else {
Expand All @@ -44,18 +45,18 @@ func BigInt3FromBaseAddr(addr memory.Relocatable, virtual_machine vm.VirtualMach
return BigInt3{Limbs: limbs}, nil
}

func BigInt3FromVarName(name string, virtual_machine vm.VirtualMachine, ids_data hint_utils.IdsManager) (EcPoint, error) {
point_addr, err := ids_data.GetAddr(name, &virtual_machine)
func EcPointFromVarName(name string, vm VirtualMachine, idsData IdsManager) (EcPoint, error) {
pointAddr, err := idsData.GetAddr(name, &vm)
if err != nil {
return EcPoint{}, err
}

x, err := BigInt3FromBaseAddr(point_addr, virtual_machine)
x, err := BigInt3FromBaseAddr(pointAddr, vm)
if err != nil {
return EcPoint{}, err
}

y, err := BigInt3FromBaseAddr(point_addr.AddUint(3), virtual_machine)
y, err := BigInt3FromBaseAddr(pointAddr.AddUint(3), vm)
if err != nil {
return EcPoint{}, err
}
Expand All @@ -66,34 +67,34 @@ func BigInt3FromVarName(name string, virtual_machine vm.VirtualMachine, ids_data
/*
Implements main logic for `EC_NEGATE` and `EC_NEGATE_EMBEDDED_SECP` hints
*/
func ecNegate(virtual_machine vm.VirtualMachine, exec_scopes types.ExecutionScopes, ids_data hint_utils.IdsManager, secp_p big.Int) error {
point, err := ids_data.GetRelocatable("point", &virtual_machine)
func ecNegate(vm VirtualMachine, execScopes ExecutionScopes, idsData IdsManager, secpP big.Int) error {
point, err := idsData.GetRelocatable("point", &vm)
if err != nil {
return err
}

point_y, err := point.AddInt(3)
pointY, err := point.AddInt(3)
if err != nil {
return err
}

y_bigint3, err := BigInt3FromBaseAddr(point_y, virtual_machine)
yBigint3, err := BigInt3FromBaseAddr(pointY, vm)
if err != nil {
return err
}

y := y_bigint3.Pack86()
y := yBigint3.Pack86()
value := new(big.Int).Neg(&y)
value.Mod(value, &secp_p)
value.Mod(value, &secpP)

exec_scopes.AssignOrUpdateVariable("value", value)
exec_scopes.AssignOrUpdateVariable("SECP_P", secp_p)
execScopes.AssignOrUpdateVariable("value", value)
execScopes.AssignOrUpdateVariable("SECP_P", secpP)
return nil
}

func ecNegateImportSecpP(virtual_machine vm.VirtualMachine, exec_scopes types.ExecutionScopes, ids_data hint_utils.IdsManager) error {
secp_p, _ := new(big.Int).SetString("115792089237316195423570985008687907853269984665640564039457584007908834671663", 10)
return ecNegate(virtual_machine, exec_scopes, ids_data, *secp_p)
func ecNegateImportSecpP(vm VirtualMachine, execScopes ExecutionScopes, idsData IdsManager) error {
secpP, _ := new(big.Int).SetString("115792089237316195423570985008687907853269984665640564039457584007908834671663", 10)
return ecNegate(vm, execScopes, idsData, *secpP)
}

/*
Expand All @@ -108,9 +109,103 @@ Implements hint:
%}
*/

func ecNegateEmbeddedSecpP(virtual_machine vm.VirtualMachine, exec_scopes types.ExecutionScopes, ids_data hint_utils.IdsManager) error {
secp_p := big.NewInt(1)
secp_p.Lsh(secp_p, 255)
secp_p.Sub(secp_p, big.NewInt(19))
return ecNegate(virtual_machine, exec_scopes, ids_data, *secp_p)
func ecNegateEmbeddedSecpP(vm VirtualMachine, execScopes ExecutionScopes, idsData IdsManager) error {
SecpP := big.NewInt(1)
SecpP.Lsh(SecpP, 255)
SecpP.Sub(SecpP, big.NewInt(19))
return ecNegate(vm, execScopes, idsData, *SecpP)
}

/*
Implements hint:
%{
from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, 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=0, p=SECP_P)
%}
*/
func computeDoublingSlope(vm VirtualMachine, execScopes ExecutionScopes, idsData IdsManager, pointAlias string, SecpP big.Int, alpha big.Int) error {
execScopes.AssignOrUpdateVariable("SECP_P", SecpP)

point, err := EcPointFromVarName(pointAlias, vm, idsData)
if err != nil {
return err
}

x := point.X.Pack86()
y := point.Y.Pack86()
doublePoint := builtins.DoublePointB{X: x, Y: y}

value, err := builtins.EcDoubleSlope(doublePoint, alpha, SecpP)
if err != nil {
return err
}

execScopes.AssignOrUpdateVariable("value", value)
execScopes.AssignOrUpdateVariable("slope", value)

return nil
}

/*
Implements hint:
%{
from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
from starkware.python.math_utils import line_slope
# Compute the slope.
x0 = pack(ids.point0.x, PRIME)
y0 = pack(ids.point0.y, PRIME)
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)
%}
*/

func computeSlopeAndAssingSecpP(vm VirtualMachine, execScopes ExecutionScopes, idsData IdsManager, point0Alias string, point1Alias string, secpP big.Int) error {
execScopes.AssignOrUpdateVariable("SECP_P", secpP)
return computeSlope(vm, execScopes, idsData, point0Alias, point1Alias)
}

func computeSlope(vm VirtualMachine, execScopes ExecutionScopes, idsData IdsManager, point0Alias string, point1Alias string) error {
point0, err := EcPointFromVarName(point0Alias, vm, idsData)
if err != nil {
return err
}
point1, err := EcPointFromVarName(point1Alias, vm, idsData)
if err != nil {
return err
}

secpP, err := execScopes.Get("SECP_P")
if err != nil {
return err
}
secp := secpP.(big.Int)

// build partial sum
x0 := point0.X.Pack86()
y0 := point0.Y.Pack86()
point_a := builtins.PartialSumB{X: x0, Y: y0}

// build double point
x1 := point1.X.Pack86()
y1 := point1.Y.Pack86()
point_b := builtins.DoublePointB{X: x1, Y: y1}

value, err := builtins.LineSlope(point_a, point_b, secp)
if err != nil {
return err
}

execScopes.AssignOrUpdateVariable("value", value)
execScopes.AssignOrUpdateVariable("slope", value)

return nil
}
112 changes: 109 additions & 3 deletions pkg/hints/ec_hint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ func TestRunEcNegateOk(t *testing.T) {
Ids: idsManager,
Code: EC_NEGATE,
})
exec_scopes := types.NewExecutionScopes()
err := hintProcessor.ExecuteHint(vm, &hintData, nil, exec_scopes)
execScopes := types.NewExecutionScopes()
err := hintProcessor.ExecuteHint(vm, &hintData, nil, execScopes)
if err != nil {
t.Errorf("Ec Negative hint test failed with error %s", err)
} else {
// Check ids.is_positive
value, err := exec_scopes.Get("value")
value, err := execScopes.Get("value")
val := value.(*big.Int)
expected, _ := new(big.Int).SetString("115792089237316195423569751828682367333329274433232027476421668138471189901786", 10)

Expand Down Expand Up @@ -128,3 +128,109 @@ func TestRunEcEmbeddedSecpOk(t *testing.T) {
}

}

func TestComputeDoublingSlopeOk(t *testing.T) {
vm := NewVirtualMachine()
vm.Segments.AddSegment()
vm.Segments.AddSegment()

vm.RunContext.Fp = NewRelocatable(1, 1)

idsManager := SetupIdsForTest(
map[string][]*MaybeRelocatable{
"point": {
NewMaybeRelocatableFelt(FeltFromUint64(614323)),
NewMaybeRelocatableFelt(FeltFromUint64(5456867)),
NewMaybeRelocatableFelt(FeltFromUint64(101208)),
NewMaybeRelocatableFelt(FeltFromUint64(773712524)),
NewMaybeRelocatableFelt(FeltFromUint64(77371252)),
NewMaybeRelocatableFelt(FeltFromUint64(5298795)),
},
},
vm,
)

hintProcessor := CairoVmHintProcessor{}
hintData := any(HintData{
Ids: idsManager,
Code: EC_DOUBLE_SLOPE_V1,
})

exec_scopes := types.NewExecutionScopes()
err := hintProcessor.ExecuteHint(vm, &hintData, nil, exec_scopes)
if err != nil {
t.Errorf("EC_DOUBLE_SLOPE_V1 hint test failed with error %s", err)
} else {
value, _ := exec_scopes.Get("value")
val := value.(big.Int)

slope_res, _ := exec_scopes.Get("slope")
slope := slope_res.(big.Int)

// expected values
expectedVal, _ := new(big.Int).SetString("40442433062102151071094722250325492738932110061897694430475034100717288403728", 10)

expectedSlope, _ := new(big.Int).SetString("40442433062102151071094722250325492738932110061897694430475034100717288403728", 10)

if expectedVal.Cmp(&val) != 0 || expectedSlope.Cmp(&slope) != 0 {
t.Errorf("EC_DOUBLE_SLOPE_V1 hint test incorrect value for exec_scopes.value or exec_scopes.slope")
}
}
}

func TestRunComputeSlopeOk(t *testing.T) {
vm := NewVirtualMachine()
vm.Segments.AddSegment()
vm.Segments.AddSegment()

vm.RunContext.Fp = NewRelocatable(1, 14)

idsManager := SetupIdsForTest(
map[string][]*MaybeRelocatable{
"point0": {
NewMaybeRelocatableFelt(FeltFromUint64(134)),
NewMaybeRelocatableFelt(FeltFromUint64(5123)),
NewMaybeRelocatableFelt(FeltFromUint64(140)),
NewMaybeRelocatableFelt(FeltFromUint64(1232)),
NewMaybeRelocatableFelt(FeltFromUint64(4652)),
NewMaybeRelocatableFelt(FeltFromUint64(720)),
},
"point1": {
NewMaybeRelocatableFelt(FeltFromUint64(156)),
NewMaybeRelocatableFelt(FeltFromUint64(6545)),
NewMaybeRelocatableFelt(FeltFromUint64(100010)),
NewMaybeRelocatableFelt(FeltFromUint64(1123)),
NewMaybeRelocatableFelt(FeltFromUint64(1325)),
NewMaybeRelocatableFelt(FeltFromUint64(910)),
},
},
vm,
)

hintProcessor := CairoVmHintProcessor{}
hintData := any(HintData{
Ids: idsManager,
Code: COMPUTE_SLOPE_V1,
})

execScopes := types.NewExecutionScopes()
err := hintProcessor.ExecuteHint(vm, &hintData, nil, execScopes)
if err != nil {
t.Errorf("EC_DOUBLE_SLOPE_V1 hint test failed with error %s", err)
} else {
value, _ := execScopes.Get("value")
val := value.(big.Int)

slope_res, _ := execScopes.Get("slope")
slope := slope_res.(big.Int)

// expected values
expectedVal, _ := new(big.Int).SetString("41419765295989780131385135514529906223027172305400087935755859001910844026631", 10)

expectedSlope, _ := new(big.Int).SetString("41419765295989780131385135514529906223027172305400087935755859001910844026631", 10)

if expectedVal.Cmp(&val) != 0 || expectedSlope.Cmp(&slope) != 0 {
t.Errorf("EC_DOUBLE_SLOPE_V1 hint test incorrect value for exec_scopes.value or exec_scopes.slope")
}
}
}
2 changes: 2 additions & 0 deletions pkg/hints/hint_codes/ec_op_hints.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ package hint_codes

const EC_NEGATE = "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"
const EC_NEGATE_EMBEDDED_SECP = "from starkware.cairo.common.cairo_secp.secp_utils import pack\nSECP_P = 2**255-19\n\ny = pack(ids.point.y, PRIME) % SECP_P\n# The modulo operation in python always returns a nonnegative number.\nvalue = (-y) % SECP_P"
const EC_DOUBLE_SLOPE_V1 = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\nfrom starkware.python.math_utils import ec_double_slope\n\n# Compute the slope.\nx = pack(ids.point.x, PRIME)\ny = pack(ids.point.y, PRIME)\nvalue = slope = ec_double_slope(point=(x, y), alpha=0, p=SECP_P)"
const COMPUTE_SLOPE_V1 = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\nfrom starkware.python.math_utils import line_slope\n\n# Compute the slope.\nx0 = pack(ids.point0.x, PRIME)\ny0 = pack(ids.point0.y, PRIME)\nx1 = pack(ids.point1.x, PRIME)\ny1 = pack(ids.point1.y, PRIME)\nvalue = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P)"
4 changes: 4 additions & 0 deletions pkg/hints/hint_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any,
return memset_step_loop(data.Ids, vm, execScopes, "continue_loop")
case VM_ENTER_SCOPE:
return vm_enter_scope(execScopes)
case COMPUTE_SLOPE_V1:
return computeSlopeAndAssingSecpP(*vm, *execScopes, data.Ids, "point0", "point1", SECP_P())
case EC_DOUBLE_SLOPE_V1:
return computeDoublingSlope(*vm, *execScopes, data.Ids, "point", SECP_P(), ALPHA())
case UNSAFE_KECCAK:
return unsafeKeccak(data.Ids, vm, *execScopes)
case UNSAFE_KECCAK_FINALIZE:
Expand Down
13 changes: 13 additions & 0 deletions pkg/hints/hint_utils/secp_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package hint_utils

import "math/big"

func SECP_P() big.Int {
secpP, _ := new(big.Int).SetString("115792089237316195423570985008687907853269984665640564039457584007908834671663", 10)
return *secpP
}

func ALPHA() big.Int {
alpha := big.NewInt(0)
return *alpha
}

0 comments on commit 102682a

Please sign in to comment.