Skip to content

Commit

Permalink
pkg/hintrunner/zero: add unit tests for the existing Cairo0 hints
Browse files Browse the repository at this point in the history
Also split hint constructor and Cairo0 hint wrapper code
to make unit testing easier.
  • Loading branch information
quasilyte committed Feb 21, 2024
1 parent acba30e commit 43efa71
Show file tree
Hide file tree
Showing 5 changed files with 650 additions and 208 deletions.
208 changes: 0 additions & 208 deletions pkg/hintrunner/zero/zerohint.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import (
"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/core"
"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
zero "github.com/NethermindEth/cairo-vm-go/pkg/parsers/zero"
"github.com/NethermindEth/cairo-vm-go/pkg/utils"
VM "github.com/NethermindEth/cairo-vm-go/pkg/vm"
"github.com/NethermindEth/cairo-vm-go/pkg/vm/memory"
"github.com/consensys/gnark-crypto/ecc/stark-curve/fp"
)

// GenericZeroHinter wraps an adhoc Cairo0 inline (pythonic) hint implementation.
Expand Down Expand Up @@ -84,95 +81,6 @@ func CreateAllocSegmentHinter(resolver hintReferenceResolver) (hinter.Hinter, er
return &core.AllocSegment{Dst: hinter.ApCellRef(0)}, nil
}

func createIsLeFeltHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
argA, err := resolver.GetResOperander("a")
if err != nil {
return nil, err
}
argB, err := resolver.GetResOperander("b")
if err != nil {
return nil, err
}

h := &GenericZeroHinter{
Name: "IsLeFelt",
Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
//> memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1
apAddr := vm.Context.AddressAp()

a, err := argA.Resolve(vm)
if err != nil {
return err
}
aFelt, err := a.FieldElement()
if err != nil {
return err
}
b, err := argB.Resolve(vm)
if err != nil {
return err
}
bFelt, err := b.FieldElement()
if err != nil {
return err
}

var v memory.MemoryValue
if utils.FeltLe(aFelt, bFelt) {
v = memory.MemoryValueFromFieldElement(&utils.FeltZero)
} else {
v = memory.MemoryValueFromFieldElement(&utils.FeltOne)
}
return vm.Memory.WriteToAddress(&apAddr, &v)
},
}
return h, nil
}

func createAssertLtFeltHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
argA, err := resolver.GetResOperander("a")
if err != nil {
return nil, err
}
argB, err := resolver.GetResOperander("b")
if err != nil {
return nil, err
}

h := &GenericZeroHinter{
Name: "AssertLtFelt",
Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
//> from starkware.cairo.common.math_utils import assert_integer
//> assert_integer(ids.a)
//> assert_integer(ids.b)
//> assert (ids.a % PRIME) < (ids.b % PRIME),
//> f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'
a, err := argA.Resolve(vm)
if err != nil {
return err
}
aFelt, err := a.FieldElement()
if err != nil {
return err
}
b, err := argB.Resolve(vm)
if err != nil {
return err
}
bFelt, err := b.FieldElement()
if err != nil {
return err
}

if !utils.FeltLt(aFelt, bFelt) {
return fmt.Errorf("a = %v is not less than b = %v", aFelt, bFelt)
}
return nil
},
}
return h, nil
}

func createTestAssignHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
arg, err := resolver.GetReference("a")
if err != nil {
Expand All @@ -198,122 +106,6 @@ func createTestAssignHinter(resolver hintReferenceResolver) (hinter.Hinter, erro
return h, nil
}

func createAssertLeFeltHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
a, err := resolver.GetResOperander("a")
if err != nil {
return nil, err
}
b, err := resolver.GetResOperander("b")
if err != nil {
return nil, err
}
rangeCheckPtr, err := resolver.GetResOperander("range_check_ptr")
if err != nil {
return nil, err
}

h := &core.AssertLeFindSmallArc{
A: a,
B: b,
RangeCheckPtr: rangeCheckPtr,
}
return h, nil
}

func createAssertLeFeltExcluded0Hinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
return &core.AssertLeIsFirstArcExcluded{SkipExcludeAFlag: hinter.ApCellRef(0)}, nil
}

func createAssertLeFeltExcluded1Hinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
return &core.AssertLeIsSecondArcExcluded{SkipExcludeBMinusA: hinter.ApCellRef(0)}, nil
}

func createAssertLeFeltExcluded2Hinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
// This hint is Cairo0-specific.
// It only does a python-scoped variable named "excluded" assert.
// We store that variable inside a hinter context.
h := &GenericZeroHinter{
Name: "AssertLeFeltExcluded2",
Op: func(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
if ctx.ExcludedArc != 2 {
return fmt.Errorf("assertion `excluded == 2` failed")
}
return nil
},
}
return h, nil
}

func createIsNNHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
argA, err := resolver.GetResOperander("a")
if err != nil {
return nil, err
}

h := &GenericZeroHinter{
Name: "IsNN",
Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
apAddr := vm.Context.AddressAp()
//> memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1
a, err := argA.Resolve(vm)
if err != nil {
return err
}
// aFelt is already modulo PRIME, no need to adjust it.
aFelt, err := a.FieldElement()
if err != nil {
return err
}
// range_check_builtin.bound is utils.FeltMax128 (1 << 128).
var v memory.MemoryValue
if utils.FeltLt(aFelt, &utils.FeltMax128) {
v = memory.MemoryValueFromFieldElement(&utils.FeltZero)
} else {
v = memory.MemoryValueFromFieldElement(&utils.FeltOne)
}
return vm.Memory.WriteToAddress(&apAddr, &v)
},
}
return h, nil
}

func createIsNNOutOfRangeHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
// This hint is executed for the negative values.
// If the value was non-negative, it's usually handled by the IsNN hint.

argA, err := resolver.GetResOperander("a")
if err != nil {
return nil, err
}

h := &GenericZeroHinter{
Name: "IsNNOutOfRange",
Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
apAddr := vm.Context.AddressAp()
//> memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1
a, err := argA.Resolve(vm)
if err != nil {
return err
}
aFelt, err := a.FieldElement()
if err != nil {
return err
}
var lhs fp.Element
lhs.Sub(&utils.FeltZero, aFelt) //> -ids.a
lhs.Sub(&lhs, &utils.FeltOne)
var v memory.MemoryValue
if utils.FeltLt(aFelt, &utils.FeltMax128) {
v = memory.MemoryValueFromFieldElement(&utils.FeltZero)
} else {
v = memory.MemoryValueFromFieldElement(&utils.FeltOne)
}
return vm.Memory.WriteToAddress(&apAddr, &v)
},
}
return h, nil
}

func getParameters(zeroProgram *zero.ZeroProgram, hint zero.Hint, hintPC uint64) (hintReferenceResolver, error) {
resolver := NewReferenceResolver()

Expand Down
Loading

0 comments on commit 43efa71

Please sign in to comment.