diff --git a/pkg/hints/ec_hint.go b/pkg/hints/ec_hint.go index 8c83ff07..922711f2 100644 --- a/pkg/hints/ec_hint.go +++ b/pkg/hints/ec_hint.go @@ -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" ) @@ -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 { @@ -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 } @@ -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) } /* @@ -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 } diff --git a/pkg/hints/ec_hint_test.go b/pkg/hints/ec_hint_test.go index 8cd486aa..4e5e0fbc 100644 --- a/pkg/hints/ec_hint_test.go +++ b/pkg/hints/ec_hint_test.go @@ -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) @@ -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") + } + } +} diff --git a/pkg/hints/hint_codes/ec_op_hints.go b/pkg/hints/hint_codes/ec_op_hints.go index c2092a7f..254720c5 100644 --- a/pkg/hints/hint_codes/ec_op_hints.go +++ b/pkg/hints/hint_codes/ec_op_hints.go @@ -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)" diff --git a/pkg/hints/hint_processor.go b/pkg/hints/hint_processor.go index 75cbc952..df610ea5 100644 --- a/pkg/hints/hint_processor.go +++ b/pkg/hints/hint_processor.go @@ -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: diff --git a/pkg/hints/hint_utils/secp_utils.go b/pkg/hints/hint_utils/secp_utils.go new file mode 100644 index 00000000..d7c9955b --- /dev/null +++ b/pkg/hints/hint_utils/secp_utils.go @@ -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 +}