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

Assorted hints2 #305

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
140 changes: 137 additions & 3 deletions pkg/hints/bigint_hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (

. "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/math_utils"
. "github.com/lambdaclass/cairo-vm.go/pkg/types"
. "github.com/lambdaclass/cairo-vm.go/pkg/utils"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm"
"github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)
Expand All @@ -20,8 +22,8 @@ Implements hint:
%}
*/

func NondetBigInt3(virtual_machine VirtualMachine, execScopes ExecutionScopes, idsData IdsManager) error {
resRelloc, err := idsData.GetAddr("res", &virtual_machine)
func NondetBigInt3(vm VirtualMachine, execScopes ExecutionScopes, idsData IdsManager) error {
resRelloc, err := idsData.GetAddr("res", &vm)
if err != nil {
return err
}
Expand All @@ -47,10 +49,142 @@ func NondetBigInt3(virtual_machine VirtualMachine, execScopes ExecutionScopes, i
arg = append(arg, *m)
}

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

return nil
}

/// Implements hint:
/// ```python
/// k = safe_div(res * y - x, p)
/// value = k if k > 0 else 0 - k
/// ids.flag = 1 if k > 0 else 0
/// ```

func SafeDivBigint(vm *VirtualMachine, execScopes *ExecutionScopes, idsData IdsManager) error {
resUncast, err := execScopes.Get("res")
if err != nil {
return err
}
res, ok := resUncast.(big.Int)
if !ok {
return errors.New("Could not cast res value in SafeDivBigint")
}

yUncast, err := execScopes.Get("y")
if err != nil {
return err
}
y, ok := yUncast.(big.Int)
if !ok {
return errors.New("Could not cast y value in SafeDivBigint")
}

xUncast, err := execScopes.Get("x")
if err != nil {
return err
}
x, ok := xUncast.(big.Int)
if !ok {
return errors.New("Could not cast x value in SafeDivBigint")
}

pUncast, err := execScopes.Get("p")
if err != nil {
return err
}
p, ok := pUncast.(big.Int)
if !ok {
return errors.New("Could not cast p value in SafeDivBigint")
}

param_x := new(big.Int).Mul(&res, &y)
param_x.Sub(param_x, &x)

k, err := SafeDivBig(param_x, &p)
if err != nil {
return err
}

var value big.Int
var flag lambdaworks.Felt

// check if k is positive
if k.Cmp(big.NewInt(0)) == 1 {
value = *k
flag = lambdaworks.FeltFromUint(1)
} else {
value = *new(big.Int).Neg(k)
flag = lambdaworks.FeltFromUint(0)
}

execScopes.AssignOrUpdateVariable("k", *k)
execScopes.AssignOrUpdateVariable("value", value)

val := memory.NewMaybeRelocatableFelt(flag)
idsData.Insert("flag", val, vm)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle this error


return nil
}

func calculateX(vm *VirtualMachine, idsData IdsManager) (big.Int, error) {
x_bigint5, err := LimbsFromVarName(5, "x", idsData, vm)
if err != nil {
return big.Int{}, err
}
// pack only takes the first three limbs
x0 := x_bigint5[0]
x1 := x_bigint5[1]
x2 := x_bigint5[2]

var limbs = []lambdaworks.Felt{x0, x1, x2}

x_lower := BigInt3{Limbs: limbs}
x_lower_bigint := x_lower.Pack86()

d3 := x_bigint5[3].ToSigned()
d4 := x_bigint5[4].ToSigned()

base := BASE()
d3.Mul(d3, base.Exp(&base, big.NewInt(3), nil))
d4.Mul(d4, base.Exp(&base, big.NewInt(4), nil))

x_lower_bigint.Add(&x_lower_bigint, d3)
x_lower_bigint.Add(&x_lower_bigint, d4)

return x_lower_bigint, nil
}

func bigintPackDivMod(vm *VirtualMachine, execScopes *ExecutionScopes, idsData IdsManager) error {

pUnpack, err := BigInt3FromVarName("P", idsData, vm)
if err != nil {
return err
}
p := pUnpack.Pack86()

x, err := calculateX(vm, idsData)
if err != nil {
return err
}
x1 := x

yUnpacked, err := BigInt3FromVarName("y", idsData, vm)
if err != nil {
return err
}
y := yUnpacked.Pack86()

res, _ := math_utils.DivMod(&x1, &y, &p)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont ignore the error


execScopes.AssignOrUpdateVariable("res", *res)
execScopes.AssignOrUpdateVariable("value", *res)
execScopes.AssignOrUpdateVariable("x", x)
execScopes.AssignOrUpdateVariable("y", y)
execScopes.AssignOrUpdateVariable("p", p)

return nil
}
178 changes: 178 additions & 0 deletions pkg/hints/bigint_hint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"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"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)

Expand Down Expand Up @@ -73,3 +74,180 @@ func TestNonDetBigInt3Ok(t *testing.T) {
}
}
}

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

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

execScopes := NewExecutionScopes()

res, _ := new(big.Int).SetString("109567829260688255124154626727441144629993228404337546799996747905569082729709", 10)
x, _ := new(big.Int).SetString("91414600319290532004473480113251693728834511388719905794310982800988866814583", 10)
y, _ := new(big.Int).SetString("38047400353360331012910998489219098987968251547384484838080352663220422975266", 10)
p, _ := new(big.Int).SetString("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10)

execScopes.AssignOrUpdateVariable("res", *res)
execScopes.AssignOrUpdateVariable("x", *x)
execScopes.AssignOrUpdateVariable("y", *y)
execScopes.AssignOrUpdateVariable("p", *p)

vm.RunContext.Fp = NewRelocatable(1, 0)
idsManager := SetupIdsForTest(
map[string][]*MaybeRelocatable{
"flag": {nil},
},
vm,
)

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

err := hintProcessor.ExecuteHint(vm, &hintData, nil, execScopes)

if err != nil {
t.Errorf("Safe Big int div hint test failed with error: %s", err)
} else {
expectedK, _ := new(big.Int).SetString("36002209591245282109880156842267569109802494162594623391338581162816748840003", 10)
expectedVal, _ := new(big.Int).SetString("36002209591245282109880156842267569109802494162594623391338581162816748840003", 10)

kUncast, err := execScopes.Get("k")
if err != nil {
t.Errorf("%s", err)
}
k, _ := kUncast.(big.Int)

valUncast, err := execScopes.Get("value")
if err != nil {
t.Errorf("%s", err)
}
value, _ := valUncast.(big.Int)

if expectedK.Cmp(&k) != 0 {
t.Errorf("incorrect K value expected: %s, got: %s", expectedK.Text(10), k.Text(10))
}

if expectedVal.Cmp(&value) != 0 {
t.Errorf("incorrect value expected: %s, got: %s", expectedVal.Text(10), value.Text(10))
}

// check memory
addr := memory.NewRelocatable(1, 0)
val, _ := vm.Segments.Memory.GetFelt(addr)

if val != lambdaworks.FeltFromUint(1) {
t.Errorf("incorrect value fetched from memory")
}
}
}

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

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

vm.RunContext.Fp = NewRelocatable(1, 0)
idsManager := SetupIdsForTest(
map[string][]*MaybeRelocatable{
"x": {
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0x38a23ca66202c8c2a72277")),
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0x6730e765376ff17ea8385")),
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0xca1ad489ab60ea581e6c1")),
NewMaybeRelocatableFelt(lambdaworks.FeltFromUint(0)),
NewMaybeRelocatableFelt(lambdaworks.FeltFromUint(0)),
},
"y": {
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0x20a4b46d3c5e24cda81f22")),
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0x967bf895824330d4273d0")),
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0x541e10c21560da25ada4c")),
},
"P": {
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0x8a03bbfd25e8cd0364141")),
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0x3ffffffffffaeabb739abd")),
NewMaybeRelocatableFelt(lambdaworks.FeltFromHex("0xfffffffffffffffffffff")),
},
},
vm,
)

execScopes := NewExecutionScopes()

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

err := hintProcessor.ExecuteHint(vm, &hintData, nil, execScopes)

if err != nil {
t.Errorf("BIGINT_PACK_DIV_MOD test failed with error: %s", err)
} else {
expected, _ := new(big.Int).SetString("109567829260688255124154626727441144629993228404337546799996747905569082729709", 10)
yExpected, _ := new(big.Int).SetString("38047400353360331012910998489219098987968251547384484838080352663220422975266", 10)
xExpected, _ := new(big.Int).SetString("91414600319290532004473480113251693728834511388719905794310982800988866814583", 10)
pExpected, _ := new(big.Int).SetString("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10)

// fetch values
resu, err := execScopes.Get("res")
if err != nil {
t.Errorf("BIGINT_PACK_DIV_MOD test failed with error: %s", err)
}
res := resu.(big.Int)

valu, err := execScopes.Get("value")
if err != nil {
t.Errorf("BIGINT_PACK_DIV_MOD test failed with error: %s", err)
}
value := valu.(big.Int)

yu, err := execScopes.Get("y")
if err != nil {
t.Errorf("BIGINT_PACK_DIV_MOD test failed with error: %s", err)
}
y := yu.(big.Int)

xu, err := execScopes.Get("x")
if err != nil {
t.Errorf("BIGINT_PACK_DIV_MOD test failed with error: %s", err)
}
x := xu.(big.Int)

pu, err := execScopes.Get("p")
if err != nil {
t.Errorf("BIGINT_PACK_DIV_MOD test failed with error: %s", err)
}
p := pu.(big.Int)

if res.Cmp(expected) != 0 {
t.Errorf("incorrect res expected: %s, got: %s", expected.Text(10), res.Text(10))
}
if value.Cmp(expected) != 0 {
t.Errorf("incorrect value expected: %s, got: %s", expected.Text(10), value.Text(10))
}
if y.Cmp(yExpected) != 0 {
t.Errorf("incorrect y expected: %s, got: %s", yExpected.Text(10), y.Text(10))
}
if x.Cmp(xExpected) != 0 {
t.Errorf("incorrect x expected: %s, got: %s", xExpected.Text(10), x.Text(10))
}
if p.Cmp(pExpected) != 0 {
t.Errorf("incorrect p expected: %s, got: %s", pExpected.Text(10), p.Text(10))
}
}
}
1 change: 0 additions & 1 deletion pkg/hints/ec_hint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,6 @@ func TestRunComputeSlopeV2Ok(t *testing.T) {
idsManager := SetupIdsForTest(
map[string][]*MaybeRelocatable{
"point0": {

NewMaybeRelocatableFelt(FeltFromUint64(512)),
NewMaybeRelocatableFelt(FeltFromUint64(2412)),
NewMaybeRelocatableFelt(FeltFromUint64(133)),
Expand Down
3 changes: 3 additions & 0 deletions pkg/hints/hint_codes/ec_op_hints.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ y0 = pack(ids.pt0.y, PRIME)
value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P"`

const FAST_EC_ADD_ASSIGN_NEW_Y = "value = new_y = (slope * (x0 - new_x) - y0) % SECP_P"

const BIGINT_SAFE_DIV = "k = safe_div(res * y - x, p)\nvalue = k if k > 0 else 0 - k\nids.flag = 1 if k > 0 else 0"
const BIGINT_PACK_DIV_MOD = "from starkware.cairo.common.cairo_secp.secp_utils import pack\nfrom starkware.cairo.common.math_utils import as_int\nfrom starkware.python.math_utils import div_mod, safe_div\n\np = pack(ids.P, PRIME)\nx = pack(ids.x, PRIME) + as_int(ids.x.d3, PRIME) * ids.BASE ** 3 + as_int(ids.x.d4, PRIME) * ids.BASE ** 4\ny = pack(ids.y, PRIME)\n\nvalue = res = div_mod(x, y, p)"
4 changes: 4 additions & 0 deletions pkg/hints/hint_codes/math_hint_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ const SPLIT_FELT = "from starkware.cairo.common.math_utils import assert_integer
const SPLIT_INT = "memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base\nassert res < ids.bound, f'split_int(): Limb {res} is out of range.'"

const SPLIT_INT_ASSERT_RANGE = "assert ids.value == 0, 'split_int(): value is out of range.'"

const ASSERT_LE_FELT_V_0_6 = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) <= (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than or equal to b = {ids.b % PRIME}.'"

const ASSERT_LE_FELT_V_0_8 = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\na = ids.a % PRIME\nb = ids.b % PRIME\nassert a <= b, f'a = {a} is not less than or equal to b = {b}.'\n\nids.small_inputs = int(\n a < range_check_builtin.bound and (b - a) < range_check_builtin.bound)"
8 changes: 8 additions & 0 deletions pkg/hints/hint_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,14 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any,
return fastEcAddAssignNewX(data.Ids, vm, execScopes, "pt0", "pt1", SECP_P())
case FAST_EC_ADD_ASSIGN_NEW_Y:
return fastEcAddAssignNewY(execScopes)
case BIGINT_SAFE_DIV:
return SafeDivBigint(vm, execScopes, data.Ids)
case BIGINT_PACK_DIV_MOD:
return bigintPackDivMod(vm, execScopes, data.Ids)
case ASSERT_LE_FELT_V_0_6:
return assertLeFeltV06(vm, data.Ids)
case ASSERT_LE_FELT_V_0_8:
return assertLeFeltV08(vm, data.Ids)
default:
return errors.Errorf("Unknown Hint: %s", data.Code)
}
Expand Down
Loading
Loading