From 9783cecd3bfa7a02c619debb9235e3ba05a4f2a4 Mon Sep 17 00:00:00 2001 From: MaksymMalicki Date: Mon, 12 Aug 2024 20:36:46 -0600 Subject: [PATCH 1/5] Implement hint map --- cmd/cairo/main.go | 52 ++++ pkg/hintrunner/core/cairo_hintparser.go | 280 +++++++++++++++++++++ pkg/hintrunner/core/hint.go | 28 ++- pkg/hintrunner/core/hint_benchmark_test.go | 4 +- pkg/hintrunner/core/hint_test.go | 4 +- pkg/parsers/starknet/hint.go | 7 + 6 files changed, 369 insertions(+), 6 deletions(-) create mode 100644 cmd/cairo/main.go create mode 100644 pkg/hintrunner/core/cairo_hintparser.go diff --git a/cmd/cairo/main.go b/cmd/cairo/main.go new file mode 100644 index 000000000..3d475f5b5 --- /dev/null +++ b/cmd/cairo/main.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "os" + + "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/core" + "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" + "github.com/urfave/cli/v2" +) + +func main() { + app := &cli.App{ + Name: "cairo-vm", + Usage: "A cairo virtual machine", + EnableBashCompletion: true, + Suggest: true, + DefaultCommand: "help", + Commands: []*cli.Command{ + { + Name: "run", + Usage: "runs a cairo zero compiled file", + Flags: []cli.Flag{}, + Action: func(ctx *cli.Context) error { + pathToFile := ctx.Args().Get(0) + fmt.Println(pathToFile) + if pathToFile == "" { + return fmt.Errorf("path to cairo file not set") + } + + fmt.Printf("Loading program at %s\n", pathToFile) + + cairoZeroJson, err := starknet.StarknetProgramFromFile(pathToFile) + if err != nil { + return fmt.Errorf("cannot load program: %w", err) + } + cairoHints, err := core.GetCairoHints(cairoZeroJson) + if err != nil { + return fmt.Errorf("cannot get hints: %w", err) + } + fmt.Println(cairoHints) + return nil + }, + }, + }, + } + + if err := app.Run(os.Args); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/pkg/hintrunner/core/cairo_hintparser.go b/pkg/hintrunner/core/cairo_hintparser.go new file mode 100644 index 000000000..e79eea97d --- /dev/null +++ b/pkg/hintrunner/core/cairo_hintparser.go @@ -0,0 +1,280 @@ +package core + +import ( + "fmt" + + "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" + "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" + "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" +) + +func parseCellRefer(cr starknet.CellRef) hinter.CellRefer { + switch cr.Register { + case starknet.AP: + return hinter.ApCellRef(cr.Offset) + case starknet.FP: + return hinter.FpCellRef(cr.Offset) + } + return nil +} + +func parseDeref(ro starknet.ResOperand) hinter.Deref { + cr := parseCellRefer(ro.ResOperand.(*starknet.Deref).Deref) + return hinter.Deref{ + Deref: cr, + } +} + +func parseDoubleDeref(ro starknet.ResOperand) hinter.DoubleDeref { + dd := ro.ResOperand.(*starknet.DoubleDeref) + offset := int16(dd.Inner.Offset) + cr := parseCellRefer(dd.Inner.CellRef) + deref := hinter.Deref{ + Deref: cr, + } + return hinter.DoubleDeref{ + Offset: offset, + Deref: deref, + } +} + +func parseImmediate(ro starknet.ResOperand) hinter.Immediate { + val := ro.ResOperand.(*starknet.Immediate).Immediate + valFelt := new(fp.Element).SetBigInt(val) + return hinter.Immediate(*valFelt) +} + +func parseBinOp(ro starknet.ResOperand) hinter.BinaryOp { + binOp := ro.ResOperand.(*starknet.BinOp).BinOp + a := parseCellRefer(binOp.A) + var b hinter.ResOperander = nil + switch binOp.B.Inner.(type) { + case starknet.Deref: + b = &hinter.Deref{ + Deref: parseCellRefer(binOp.B.Inner.(*starknet.Deref).Deref), + } + case starknet.Immediate: + val := binOp.B.Inner.(*starknet.Immediate).Immediate + valFelt := new(fp.Element).SetBigInt(val) + b = hinter.Immediate(*valFelt) + } + var operation hinter.Operator = 0 + switch binOp.Op { + case starknet.Add: + operation = hinter.Add + case starknet.Mul: + operation = hinter.Add + } + return hinter.BinaryOp{ + Operator: operation, + Lhs: a, + Rhs: b, + } +} + +func parseResOperand(ro starknet.ResOperand) hinter.ResOperander { + switch ro.Name { + case starknet.DerefName: + return parseDeref(ro) + case starknet.DoubleDerefName: + return parseDoubleDeref(ro) + case starknet.ImmediateName: + return parseImmediate(ro) + case starknet.BinOpName: + return parseBinOp(ro) + } + return nil +} + +func GetHintByName(hint starknet.Hint) (hinter.Hinter, error) { + switch hint.Name { + case starknet.AllocSegmentName: + args := hint.Args.(*starknet.AllocSegment) + return &AllocSegment{ + Dst: parseCellRefer(args.Dst), + }, nil + case starknet.TestLessThanName: + args := hint.Args.(*starknet.TestLessThan) + return &TestLessThan{ + lhs: parseResOperand(args.Lhs), + rhs: parseResOperand(args.Rhs), + dst: parseCellRefer(args.Dst), + }, nil + case starknet.TestLessThanOrEqualName: + args := hint.Args.(*starknet.TestLessThanOrEqual) + return &TestLessThanOrEqual{ + lhs: parseResOperand(args.Lhs), + rhs: parseResOperand(args.Rhs), + dst: parseCellRefer(args.Dst), + }, nil + case starknet.LinearSplitName: + args := hint.Args.(*starknet.LinearSplit) + return &LinearSplit{ + value: parseResOperand(args.Value), + scalar: parseResOperand(args.Scalar), + maxX: parseResOperand(args.MaxX), + x: parseCellRefer(args.X), + y: parseCellRefer(args.Y), + }, nil + case starknet.WideMul128Name: + args := hint.Args.(*starknet.WideMul128) + return &WideMul128{ + lhs: parseResOperand(args.Lhs), + rhs: parseResOperand(args.Rhs), + high: parseCellRefer(args.High), + low: parseCellRefer(args.Low), + }, nil + case starknet.DivModName: + args := hint.Args.(*starknet.DivMod) + return &DivMod{ + lhs: parseResOperand(args.Lhs), + rhs: parseResOperand(args.Rhs), + quotient: parseCellRefer(args.Quotient), + remainder: parseCellRefer(args.Remainder), + }, nil + case starknet.Uint256DivModName: + args := hint.Args.(*starknet.Uint256DivMod) + return &Uint256DivMod{ + dividend0: parseResOperand(args.Dividend0), + dividend1: parseResOperand(args.Dividend1), + divisor0: parseResOperand(args.Divisor0), + divisor1: parseResOperand(args.Divisor1), + quotient0: parseCellRefer(args.Quotient0), + quotient1: parseCellRefer(args.Quotient1), + remainder0: parseCellRefer(args.Remainder0), + remainder1: parseCellRefer(args.Remainder1), + }, nil + case starknet.DebugPrintName: + args := hint.Args.(*starknet.DebugPrint) + return &DebugPrint{ + start: parseResOperand(args.Start), + end: parseResOperand(args.End), + }, nil + case starknet.SquareRootName: + args := hint.Args.(*starknet.SquareRoot) + return &SquareRoot{ + value: parseResOperand(args.Value), + dst: parseCellRefer(args.Dst), + }, nil + case starknet.Uint256SquareRootName: + args := hint.Args.(*starknet.Uint256SquareRoot) + return &Uint256SquareRoot{ + valueLow: parseResOperand(args.ValueLow), + valueHigh: parseResOperand(args.ValueHigh), + sqrt0: parseCellRefer(args.Sqrt0), + sqrt1: parseCellRefer(args.Sqrt1), + remainderLow: parseCellRefer(args.RemainderLow), + remainderHigh: parseCellRefer(args.RemainderHigh), + sqrtMul2MinusRemainderGeU128: parseCellRefer(args.SqrtMul2MinusRemainderGeU128), + }, nil + case starknet.AllocFelt252DictName: + args := hint.Args.(*starknet.AllocFelt252Dict) + return &AllocFelt252Dict{ + SegmentArenaPtr: parseResOperand(args.SegmentArenaPtr), + }, nil + case starknet.Felt252DictEntryInitName: + args := hint.Args.(*starknet.Felt252DictEntryInit) + return &Felt252DictEntryInit{ + DictPtr: parseResOperand(args.DictPtr), + Key: parseResOperand(args.Key), + }, nil + case starknet.Felt252DictEntryUpdateName: + args := hint.Args.(*starknet.Felt252DictEntryUpdate) + return &Felt252DictEntryUpdate{ + DictPtr: parseResOperand(args.DictPtr), + Value: parseResOperand(args.Value), + }, nil + case starknet.GetSegmentArenaIndexName: + args := hint.Args.(*starknet.GetSegmentArenaIndex) + return &GetSegmentArenaIndex{ + DictEndPtr: parseResOperand(args.DictEndPtr), + DictIndex: parseCellRefer(args.DictIndex), + }, nil + case starknet.InitSquashDataName: + args := hint.Args.(*starknet.InitSquashData) + return &InitSquashData{ + DictAccesses: parseResOperand(args.DictAccesses), + NumAccesses: parseResOperand(args.NAccesses), + BigKeys: parseCellRefer(args.BigKeys), + FirstKey: parseCellRefer(args.FirstKey), + }, nil + case starknet.GetCurrentAccessIndexName: + args := hint.Args.(*starknet.GetCurrentAccessIndex) + return &GetCurrentAccessIndex{ + RangeCheckPtr: parseResOperand(args.RangeCheckPtr), + }, nil + case starknet.ShouldSkipSquashLoopName: + args := hint.Args.(*starknet.ShouldSkipSquashLoop) + return &ShouldSkipSquashLoop{ + ShouldSkipLoop: parseCellRefer(args.ShouldSkipLoop), + }, nil + case starknet.GetCurrentAccessDeltaName: + args := hint.Args.(*starknet.GetCurrentAccessDelta) + return &GetCurrentAccessDelta{ + IndexDeltaMinusOne: parseCellRefer(args.IndexDeltaMinus1), + }, nil + case starknet.ShouldContinueSquashLoopName: + args := hint.Args.(*starknet.ShouldContinueSquashLoop) + return &ShouldContinueSquashLoop{ + ShouldContinue: parseCellRefer(args.ShouldContinue), + }, nil + case starknet.GetNextDictKeyName: + args := hint.Args.(*starknet.GetNextDictKey) + return &GetNextDictKey{ + NextKey: parseCellRefer(args.NextKey), + }, nil + case starknet.Uint512DivModByUint256Name: + args := hint.Args.(*starknet.Uint512DivModByUint256) + return &Uint512DivModByUint256{ + dividend0: parseResOperand(args.Dividend0), + dividend1: parseResOperand(args.Dividend1), + dividend2: parseResOperand(args.Dividend2), + dividend3: parseResOperand(args.Dividend3), + divisor0: parseResOperand(args.Divisor0), + divisor1: parseResOperand(args.Divisor1), + quotient0: parseCellRefer(args.Quotient0), + quotient1: parseCellRefer(args.Quotient1), + quotient2: parseCellRefer(args.Quotient2), + quotient3: parseCellRefer(args.Quotient3), + remainder0: parseCellRefer(args.Remainder0), + remainder1: parseCellRefer(args.Remainder1), + }, nil + case starknet.AllocConstantSizeName: + args := hint.Args.(*starknet.AllocConstantSize) + return &AllocConstantSize{ + Dst: parseCellRefer(args.Dst), + Size: parseResOperand(args.Size), + }, nil + case starknet.AssertLeFindSmallArcsName: + args := hint.Args.(*starknet.AssertLeFindSmallArcs) + return &AssertLeFindSmallArc{ + A: parseResOperand(args.A), + B: parseResOperand(args.B), + RangeCheckPtr: parseResOperand(args.RangeCheckPtr), + }, nil + case starknet.AssertLeIsFirstArcExcludedName: + args := hint.Args.(*starknet.AssertLeIsFirstArcExcluded) + return &AssertLeIsFirstArcExcluded{ + SkipExcludeAFlag: parseCellRefer(args.SkipExcludeAFlag), + }, nil + case starknet.AssertLeIsSecondArcExcludedName: + args := hint.Args.(*starknet.AssertLeIsSecondArcExcluded) + return &AssertLeIsSecondArcExcluded{ + SkipExcludeBMinusA: parseCellRefer(args.SkipExcludeBMinusA), + }, nil + case starknet.RandomEcPointName: + args := hint.Args.(*starknet.RandomEcPoint) + return &RandomEcPoint{ + x: parseCellRefer(args.X), + y: parseCellRefer(args.Y), + }, nil + case starknet.FieldSqrtName: + args := hint.Args.(*starknet.FieldSqrt) + return &FieldSqrt{ + val: parseResOperand(args.Val), + sqrt: parseCellRefer(args.Sqrt), + }, nil + default: + return nil, fmt.Errorf("unknown hint: %v", hint.Name) + } +} diff --git a/pkg/hintrunner/core/hint.go b/pkg/hintrunner/core/hint.go index 3146d4e51..ca15f2b57 100644 --- a/pkg/hintrunner/core/hint.go +++ b/pkg/hintrunner/core/hint.go @@ -9,12 +9,28 @@ import ( "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" u "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/utils" + "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" "github.com/NethermindEth/cairo-vm-go/pkg/utils" VM "github.com/NethermindEth/cairo-vm-go/pkg/vm" mem "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" f "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" ) +func GetCairoHints(cairoProgramJson *starknet.StarknetProgram) (map[uint64][]hinter.Hinter, error) { + hints := make(map[uint64][]hinter.Hinter) + for _, hintsList := range cairoProgramJson.Hints { + for _, hint := range hintsList.Hints { + processedHint, err := GetHintByName(hint) + if err != nil { + return nil, err + } + hints[hintsList.Index] = append(hints[hintsList.Index], processedHint) + } + } + + return hints, nil +} + type AllocSegment struct { Dst hinter.CellRefer } @@ -148,6 +164,10 @@ type LinearSplit struct { y hinter.CellRefer } +func (hint LinearSplit) String() string { + return "LinearSplit" +} + func (hint LinearSplit) Execute(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error { value, err := hint.value.Resolve(vm) if err != nil { @@ -506,6 +526,10 @@ type DebugPrint struct { end hinter.ResOperander } +func (hint DebugPrint) String() string { + return "DebugPrint" +} + func (hint DebugPrint) Execute(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error { start, err := hint.start.Resolve(vm) if err != nil { @@ -1502,7 +1526,7 @@ func (hint *RandomEcPoint) String() string { return "RandomEc" } -func (hint *RandomEcPoint) Execute(vm *VM.VirtualMachine) error { +func (hint *RandomEcPoint) Execute(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error { // Keep sampling a random field element `X` until `X^3 + X + beta` is a quadratic residue. // Starkware's elliptic curve Beta value https://docs.starkware.co/starkex/crypto/stark-curve.html @@ -1561,7 +1585,7 @@ func (hint *FieldSqrt) String() string { return "FieldSqrt" } -func (hint *FieldSqrt) Execute(vm *VM.VirtualMachine) error { +func (hint *FieldSqrt) Execute(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error { val, err := hint.val.Resolve(vm) if err != nil { return fmt.Errorf("resolve val operand %s: %v", hint.val, err) diff --git a/pkg/hintrunner/core/hint_benchmark_test.go b/pkg/hintrunner/core/hint_benchmark_test.go index c70fccd90..5032645fc 100644 --- a/pkg/hintrunner/core/hint_benchmark_test.go +++ b/pkg/hintrunner/core/hint_benchmark_test.go @@ -410,7 +410,7 @@ func BenchmarkRandomEcPoint(b *testing.B) { y: hinter.ApCellRef(1), } - err := hint.Execute(vm) + err := hint.Execute(vm, nil) if err != nil { b.Error(err) break @@ -433,7 +433,7 @@ func BenchmarkFieldSqrt(b *testing.B) { sqrt: hinter.ApCellRef(0), } - err := hint.Execute(vm) + err := hint.Execute(vm, nil) if err != nil { b.Error(err) break diff --git a/pkg/hintrunner/core/hint_test.go b/pkg/hintrunner/core/hint_test.go index a431d21cc..3b4730258 100644 --- a/pkg/hintrunner/core/hint_test.go +++ b/pkg/hintrunner/core/hint_test.go @@ -1069,7 +1069,7 @@ func TestRandomEcPoint(t *testing.T) { y: hinter.ApCellRef(1), } - err := hint.Execute(vm) + err := hint.Execute(vm, nil) require.NoError(t, err) expectedX := mem.MemoryValueFromFieldElement( @@ -1116,7 +1116,7 @@ func TestFieldSqrt(t *testing.T) { sqrt: hinter.ApCellRef(0), } - err := hint.Execute(vm) + err := hint.Execute(vm, nil) require.NoError(t, err) require.Equal( diff --git a/pkg/parsers/starknet/hint.go b/pkg/parsers/starknet/hint.go index 40d90e801..263e3d5d1 100644 --- a/pkg/parsers/starknet/hint.go +++ b/pkg/parsers/starknet/hint.go @@ -284,6 +284,7 @@ const ( type Operand interface{} type ResOperand struct { + Name ResOperandName ResOperand Operand `validate:"required"` } @@ -296,16 +297,21 @@ func (ro *ResOperand) UnmarshalJSON(data []byte) error { } var op any + var name ResOperandName for k := range resOp { switch ResOperandName(k) { case DerefName: op = &Deref{} + name = DerefName case DoubleDerefName: op = &DoubleDeref{} + name = DoubleDerefName case ImmediateName: op = &Immediate{} + name = ImmediateName case BinOpName: op = &BinOp{} + name = BinOpName default: return fmt.Errorf("unknown res operand %s", k) } @@ -317,6 +323,7 @@ func (ro *ResOperand) UnmarshalJSON(data []byte) error { } ro.ResOperand = op + ro.Name = name return nil } From 491745cf361e85e06e21a281628b5c071da7c89b Mon Sep 17 00:00:00 2001 From: MaksymMalicki Date: Wed, 14 Aug 2024 14:01:40 -0600 Subject: [PATCH 2/5] Remove main cli, read cairo version --- cmd/cairo/main.go | 52 ---------------------- cmd/cli/main.go | 38 ++++++++++------ pkg/parsers/cairo_version/cairo_version.go | 30 +++++++++++++ 3 files changed, 55 insertions(+), 65 deletions(-) delete mode 100644 cmd/cairo/main.go create mode 100644 pkg/parsers/cairo_version/cairo_version.go diff --git a/cmd/cairo/main.go b/cmd/cairo/main.go deleted file mode 100644 index 3d475f5b5..000000000 --- a/cmd/cairo/main.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/core" - "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" - "github.com/urfave/cli/v2" -) - -func main() { - app := &cli.App{ - Name: "cairo-vm", - Usage: "A cairo virtual machine", - EnableBashCompletion: true, - Suggest: true, - DefaultCommand: "help", - Commands: []*cli.Command{ - { - Name: "run", - Usage: "runs a cairo zero compiled file", - Flags: []cli.Flag{}, - Action: func(ctx *cli.Context) error { - pathToFile := ctx.Args().Get(0) - fmt.Println(pathToFile) - if pathToFile == "" { - return fmt.Errorf("path to cairo file not set") - } - - fmt.Printf("Loading program at %s\n", pathToFile) - - cairoZeroJson, err := starknet.StarknetProgramFromFile(pathToFile) - if err != nil { - return fmt.Errorf("cannot load program: %w", err) - } - cairoHints, err := core.GetCairoHints(cairoZeroJson) - if err != nil { - return fmt.Errorf("cannot get hints: %w", err) - } - fmt.Println(cairoHints) - return nil - }, - }, - }, - } - - if err := app.Run(os.Args); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 4e1ed773a..d6d7af8ab 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -5,7 +5,11 @@ import ( "math" "os" + "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/core" + "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" hintrunner "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/zero" + cairoversion "github.com/NethermindEth/cairo-vm-go/pkg/parsers/cairo_version" + "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" zero "github.com/NethermindEth/cairo-vm-go/pkg/parsers/zero" runnerzero "github.com/NethermindEth/cairo-vm-go/pkg/runners/zero" "github.com/urfave/cli/v2" @@ -90,28 +94,36 @@ func main() { if pathToFile == "" { return fmt.Errorf("path to cairo file not set") } - - fmt.Printf("Loading program at %s\n", pathToFile) - content, err := os.ReadFile(pathToFile) + cairoVersion, err := cairoversion.GetCairoVersion(pathToFile) if err != nil { - return fmt.Errorf("cannot load program: %w", err) + return fmt.Errorf("cannot get cairo version: %w", err) } - - cairoZeroJson, err := zero.ZeroProgramFromJSON(content) + fmt.Printf("Loading program at %s\n", pathToFile) + zeroProgram, err := zero.ZeroProgramFromFile(pathToFile) if err != nil { return fmt.Errorf("cannot load program: %w", err) } - program, err := runnerzero.LoadCairoZeroProgram(cairoZeroJson) - if err != nil { - return fmt.Errorf("cannot load program: %w", err) + var hints map[uint64][]hinter.Hinter + if cairoVersion > 0 { + cairoProgram, err := starknet.StarknetProgramFromFile(pathToFile) + if err != nil { + return fmt.Errorf("cannot load program: %w", err) + } + hints, err = core.GetCairoHints(cairoProgram) + if err != nil { + return fmt.Errorf("cannot get hints: %w", err) + } + } else { + hints, err = hintrunner.GetZeroHints(zeroProgram) + if err != nil { + return fmt.Errorf("cannot create hints: %w", err) + } } - - hints, err := hintrunner.GetZeroHints(cairoZeroJson) + program, err := runnerzero.LoadCairoZeroProgram(zeroProgram) if err != nil { - return fmt.Errorf("cannot create hints: %w", err) + return fmt.Errorf("cannot load program: %w", err) } - fmt.Println("Running....") runner, err := runnerzero.NewRunner(program, hints, proofmode, collectTrace, maxsteps, layoutName) if err != nil { diff --git a/pkg/parsers/cairo_version/cairo_version.go b/pkg/parsers/cairo_version/cairo_version.go new file mode 100644 index 000000000..c17104e3c --- /dev/null +++ b/pkg/parsers/cairo_version/cairo_version.go @@ -0,0 +1,30 @@ +package cairoversion + +import ( + "encoding/json" + "os" + "strconv" + "strings" +) + +type CairoVersion struct { + Version string `json:"compiler_version"` +} + +func GetCairoVersion(pathToFile string) (uint8, error) { + content, err := os.ReadFile(pathToFile) + if err != nil { + return 0, err + } + cv := CairoVersion{} + err = json.Unmarshal(content, &cv) + if err != nil { + return 0, err + } + firstNumberStr := strings.Split(cv.Version, ".")[0] + firstNumber, err := strconv.ParseUint(firstNumberStr, 10, 8) + if err != nil { + return 0, err + } + return uint8(firstNumber), nil +} From 978bf7edb3688164e93cd6ecf11389a13edef305 Mon Sep 17 00:00:00 2001 From: MaksymMalicki Date: Tue, 20 Aug 2024 10:43:37 -0600 Subject: [PATCH 3/5] Add unit tests --- pkg/hintrunner/core/cairo_hintparser.go | 4 +- pkg/hintrunner/core/cairo_hintparser_test.go | 432 +++++++++++++++++++ pkg/parsers/starknet/hint.go | 2 +- 3 files changed, 435 insertions(+), 3 deletions(-) create mode 100644 pkg/hintrunner/core/cairo_hintparser_test.go diff --git a/pkg/hintrunner/core/cairo_hintparser.go b/pkg/hintrunner/core/cairo_hintparser.go index e79eea97d..300af1b13 100644 --- a/pkg/hintrunner/core/cairo_hintparser.go +++ b/pkg/hintrunner/core/cairo_hintparser.go @@ -49,11 +49,11 @@ func parseBinOp(ro starknet.ResOperand) hinter.BinaryOp { a := parseCellRefer(binOp.A) var b hinter.ResOperander = nil switch binOp.B.Inner.(type) { - case starknet.Deref: + case *starknet.Deref: b = &hinter.Deref{ Deref: parseCellRefer(binOp.B.Inner.(*starknet.Deref).Deref), } - case starknet.Immediate: + case *starknet.Immediate: val := binOp.B.Inner.(*starknet.Immediate).Immediate valFelt := new(fp.Element).SetBigInt(val) b = hinter.Immediate(*valFelt) diff --git a/pkg/hintrunner/core/cairo_hintparser_test.go b/pkg/hintrunner/core/cairo_hintparser_test.go new file mode 100644 index 000000000..24ada4028 --- /dev/null +++ b/pkg/hintrunner/core/cairo_hintparser_test.go @@ -0,0 +1,432 @@ +package core + +import ( + "testing" + + "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" + "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" + "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" + "github.com/stretchr/testify/require" +) + +func TestCairoHintParser(t *testing.T) { + type testSetType struct { + CairoProgramString []byte + ExpectedHintMap map[uint64][]hinter.Hinter + } + + testSet := []testSetType{ + { + CairoProgramString: []byte(` + { + "hints": [ + [ + 2, + [ + { + "AllocFelt252Dict": { + "segment_arena_ptr": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 13, + [ + { + "AllocFelt252Dict": { + "segment_arena_ptr": { + "BinOp": { + "op": "Add", + "a": { + "register": "FP", + "offset": -4 + }, + "b": { + "Immediate": "0x3" + } + } + } + } + } + ] + ], + [ + 46, + [ + { + "Felt252DictEntryInit": { + "dict_ptr": { + "Deref": { + "register": "FP", + "offset": 2 + } + }, + "key": { + "Deref": { + "register": "AP", + "offset": -1 + } + } + } + } + ] + ], + [ + 49, + [ + { + "Felt252DictEntryUpdate": { + "dict_ptr": { + "BinOp": { + "op": "Add", + "a": { + "register": "FP", + "offset": 2 + }, + "b": { + "Immediate": "0x3" + } + } + }, + "value": { + "Deref": { + "register": "AP", + "offset": -1 + } + } + } + } + ] + ], + [ + 104, + [ + { + "GetSegmentArenaIndex": { + "dict_end_ptr": { + "Deref": { + "register": "FP", + "offset": -3 + } + }, + "dict_index": { + "register": "FP", + "offset": 0 + } + } + } + ] + ], + [ + 145, + [ + { + "AllocSegment": { + "dst": { + "register": "FP", + "offset": 3 + } + } + } + ] + ], + [ + 153, + [ + { + "InitSquashData": { + "dict_accesses": { + "Deref": { + "register": "FP", + "offset": -4 + } + }, + "ptr_diff": { + "Deref": { + "register": "FP", + "offset": 0 + } + }, + "n_accesses": { + "Deref": { + "register": "AP", + "offset": -1 + } + }, + "big_keys": { + "register": "FP", + "offset": 2 + }, + "first_key": { + "register": "FP", + "offset": 1 + } + } + } + ] + ], + [ + 172, + [ + { + "GetCurrentAccessIndex": { + "range_check_ptr": { + "Deref": { + "register": "FP", + "offset": -9 + } + } + } + } + ] + ], + [ + 185, + [ + { + "ShouldSkipSquashLoop": { + "should_skip_loop": { + "register": "AP", + "offset": -4 + } + } + } + ] + ], + [ + 187, + [ + { + "GetCurrentAccessDelta": { + "index_delta_minus1": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 198, + [ + { + "ShouldContinueSquashLoop": { + "should_continue": { + "register": "AP", + "offset": -4 + } + } + } + ] + ], + [ + 212, + [ + { + "GetNextDictKey": { + "next_key": { + "register": "FP", + "offset": 0 + } + } + } + ] + ], + [ + 231, + [ + { + "AssertLeFindSmallArcs": { + "range_check_ptr": { + "BinOp": { + "op": "Add", + "a": { + "register": "AP", + "offset": -4 + }, + "b": { + "Immediate": "0x1" + } + } + }, + "a": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "b": { + "Deref": { + "register": "FP", + "offset": 0 + } + } + } + } + ] + ], + [ + 243, + [ + { + "AssertLeIsFirstArcExcluded": { + "skip_exclude_a_flag": { + "register": "AP", + "offset": 0 + } + } + } + ] + ], + [ + 255, + [ + { + "AssertLeIsSecondArcExcluded": { + "skip_exclude_b_minus_a": { + "register": "AP", + "offset": 0 + } + } + } + ] + ] + ] + } + `), + ExpectedHintMap: map[uint64][]hinter.Hinter{ + 2: { + &AllocFelt252Dict{ + SegmentArenaPtr: hinter.Deref{ + Deref: hinter.FpCellRef(-4), + }, + }, + }, + 13: { + &AllocFelt252Dict{ + SegmentArenaPtr: hinter.BinaryOp{ + Operator: hinter.Add, + Lhs: hinter.FpCellRef(-4), + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), + }, + }, + }, + 46: { + &Felt252DictEntryInit{ + DictPtr: hinter.Deref{ + Deref: hinter.FpCellRef(2), + }, + Key: hinter.Deref{ + Deref: hinter.ApCellRef(-1), + }, + }, + }, + 49: { + &Felt252DictEntryUpdate{ + DictPtr: hinter.BinaryOp{ + Operator: hinter.Add, + Lhs: hinter.FpCellRef(2), + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), + }, + Value: hinter.Deref{ + Deref: hinter.ApCellRef(-1), + }, + }, + }, + 104: { + &GetSegmentArenaIndex{ + DictEndPtr: hinter.Deref{ + Deref: hinter.FpCellRef(-3), + }, + DictIndex: hinter.FpCellRef(0), + }, + }, + 145: { + &AllocSegment{ + Dst: hinter.FpCellRef(3), + }, + }, + 153: { + &InitSquashData{ + DictAccesses: hinter.Deref{ + Deref: hinter.FpCellRef(-4), + }, + NumAccesses: hinter.Deref{ + Deref: hinter.ApCellRef(-1), + }, + BigKeys: hinter.FpCellRef(2), + FirstKey: hinter.FpCellRef(1), + }, + }, + 172: { + &GetCurrentAccessIndex{ + RangeCheckPtr: hinter.Deref{ + Deref: hinter.FpCellRef(-9), + }, + }, + }, + 185: { + &ShouldSkipSquashLoop{ + ShouldSkipLoop: hinter.ApCellRef(-4), + }, + }, + 187: { + &GetCurrentAccessDelta{ + IndexDeltaMinusOne: hinter.ApCellRef(0), + }, + }, + 198: { + &ShouldContinueSquashLoop{ + ShouldContinue: hinter.ApCellRef(-4), + }, + }, + 212: { + &GetNextDictKey{ + NextKey: hinter.FpCellRef(0), + }, + }, + 231: { + &AssertLeFindSmallArc{ + RangeCheckPtr: hinter.BinaryOp{ + Operator: hinter.Add, + Lhs: hinter.ApCellRef(-4), + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(1)), + }, + A: hinter.Deref{ + Deref: hinter.FpCellRef(-6), + }, + B: hinter.Deref{ + Deref: hinter.FpCellRef(0), + }, + }, + }, + 243: { + &AssertLeIsFirstArcExcluded{ + SkipExcludeAFlag: hinter.ApCellRef(0), + }, + }, + 255: { + &AssertLeIsSecondArcExcluded{ + SkipExcludeBMinusA: hinter.ApCellRef(0), + }, + }, + }, + }, + } + + for _, test := range testSet { + starknetProgram, err := starknet.StarknetProgramFromJSON(test.CairoProgramString) + require.NoError(t, err) + output, err := GetCairoHints(starknetProgram) + require.NoError(t, err) + + require.Equal(t, test.ExpectedHintMap, output, "Hint maps do not match") + + } +} diff --git a/pkg/parsers/starknet/hint.go b/pkg/parsers/starknet/hint.go index 7d6f92655..9f6e62499 100644 --- a/pkg/parsers/starknet/hint.go +++ b/pkg/parsers/starknet/hint.go @@ -191,7 +191,7 @@ type ShouldSkipSquashLoop struct { } type GetCurrentAccessDelta struct { - IndexDeltaMinus1 CellRef `json:"index_delta_minus_1" validate:"required"` + IndexDeltaMinus1 CellRef `json:"index_delta_minus1" validate:"required"` } type ShouldContinueSquashLoop struct { From 931aed105a7932a2018c4a9b6d509c044678ad0b Mon Sep 17 00:00:00 2001 From: MaksymMalicki Date: Tue, 20 Aug 2024 10:54:13 -0600 Subject: [PATCH 4/5] Fix unit tests after main merge --- pkg/hintrunner/core/cairo_hintparser.go | 4 +++- pkg/hintrunner/core/cairo_hintparser_test.go | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pkg/hintrunner/core/cairo_hintparser.go b/pkg/hintrunner/core/cairo_hintparser.go index 300af1b13..e6c38fb7d 100644 --- a/pkg/hintrunner/core/cairo_hintparser.go +++ b/pkg/hintrunner/core/cairo_hintparser.go @@ -46,7 +46,9 @@ func parseImmediate(ro starknet.ResOperand) hinter.Immediate { func parseBinOp(ro starknet.ResOperand) hinter.BinaryOp { binOp := ro.ResOperand.(*starknet.BinOp).BinOp - a := parseCellRefer(binOp.A) + a := hinter.Deref{ + Deref: parseCellRefer(binOp.A), + } var b hinter.ResOperander = nil switch binOp.B.Inner.(type) { case *starknet.Deref: diff --git a/pkg/hintrunner/core/cairo_hintparser_test.go b/pkg/hintrunner/core/cairo_hintparser_test.go index 24ada4028..ff0ae02f7 100644 --- a/pkg/hintrunner/core/cairo_hintparser_test.go +++ b/pkg/hintrunner/core/cairo_hintparser_test.go @@ -312,8 +312,10 @@ func TestCairoHintParser(t *testing.T) { &AllocFelt252Dict{ SegmentArenaPtr: hinter.BinaryOp{ Operator: hinter.Add, - Lhs: hinter.FpCellRef(-4), - Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), + Lhs: hinter.Deref{ + Deref: hinter.FpCellRef(-4), + }, + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), }, }, }, @@ -331,8 +333,10 @@ func TestCairoHintParser(t *testing.T) { &Felt252DictEntryUpdate{ DictPtr: hinter.BinaryOp{ Operator: hinter.Add, - Lhs: hinter.FpCellRef(2), - Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), + Lhs: hinter.Deref{ + Deref: hinter.FpCellRef(2), + }, + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), }, Value: hinter.Deref{ Deref: hinter.ApCellRef(-1), @@ -395,8 +399,10 @@ func TestCairoHintParser(t *testing.T) { &AssertLeFindSmallArc{ RangeCheckPtr: hinter.BinaryOp{ Operator: hinter.Add, - Lhs: hinter.ApCellRef(-4), - Rhs: hinter.Immediate(*new(fp.Element).SetInt64(1)), + Lhs: hinter.Deref{ + Deref: hinter.ApCellRef(-4), + }, + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(1)), }, A: hinter.Deref{ Deref: hinter.FpCellRef(-6), From cafebe713b31291f2cf19502e1da6d2d55d53e86 Mon Sep 17 00:00:00 2001 From: MaksymMalicki Date: Tue, 20 Aug 2024 13:52:17 -0600 Subject: [PATCH 5/5] Remove unnecesary loop from test --- pkg/hintrunner/core/cairo_hintparser_test.go | 650 +++++++++---------- 1 file changed, 320 insertions(+), 330 deletions(-) diff --git a/pkg/hintrunner/core/cairo_hintparser_test.go b/pkg/hintrunner/core/cairo_hintparser_test.go index ff0ae02f7..2fe10c093 100644 --- a/pkg/hintrunner/core/cairo_hintparser_test.go +++ b/pkg/hintrunner/core/cairo_hintparser_test.go @@ -10,429 +10,419 @@ import ( ) func TestCairoHintParser(t *testing.T) { - type testSetType struct { - CairoProgramString []byte - ExpectedHintMap map[uint64][]hinter.Hinter - } - - testSet := []testSetType{ - { - CairoProgramString: []byte(` - { - "hints": [ + t.Run("TestCairoHintParser", func(t *testing.T) { + cairoProgramString := []byte(` + { + "hints": [ + [ + 2, + [ + { + "AllocFelt252Dict": { + "segment_arena_ptr": { + "Deref": { + "register": "FP", + "offset": -4 + } + } + } + } + ] + ], + [ + 13, [ - 2, - [ - { - "AllocFelt252Dict": { - "segment_arena_ptr": { - "Deref": { + { + "AllocFelt252Dict": { + "segment_arena_ptr": { + "BinOp": { + "op": "Add", + "a": { "register": "FP", "offset": -4 + }, + "b": { + "Immediate": "0x3" } } } } - ] - ], + } + ] + ], + [ + 46, [ - 13, - [ - { - "AllocFelt252Dict": { - "segment_arena_ptr": { - "BinOp": { - "op": "Add", - "a": { - "register": "FP", - "offset": -4 - }, - "b": { - "Immediate": "0x3" - } - } + { + "Felt252DictEntryInit": { + "dict_ptr": { + "Deref": { + "register": "FP", + "offset": 2 + } + }, + "key": { + "Deref": { + "register": "AP", + "offset": -1 } } } - ] - ], + } + ] + ], + [ + 49, [ - 46, - [ - { - "Felt252DictEntryInit": { - "dict_ptr": { - "Deref": { + { + "Felt252DictEntryUpdate": { + "dict_ptr": { + "BinOp": { + "op": "Add", + "a": { "register": "FP", "offset": 2 - } - }, - "key": { - "Deref": { - "register": "AP", - "offset": -1 + }, + "b": { + "Immediate": "0x3" } } - } - } - ] - ], - [ - 49, - [ - { - "Felt252DictEntryUpdate": { - "dict_ptr": { - "BinOp": { - "op": "Add", - "a": { - "register": "FP", - "offset": 2 - }, - "b": { - "Immediate": "0x3" - } - } - }, - "value": { - "Deref": { - "register": "AP", - "offset": -1 - } + }, + "value": { + "Deref": { + "register": "AP", + "offset": -1 } } } - ] - ], + } + ] + ], + [ + 104, [ - 104, - [ - { - "GetSegmentArenaIndex": { - "dict_end_ptr": { - "Deref": { - "register": "FP", - "offset": -3 - } - }, - "dict_index": { + { + "GetSegmentArenaIndex": { + "dict_end_ptr": { + "Deref": { "register": "FP", - "offset": 0 + "offset": -3 } + }, + "dict_index": { + "register": "FP", + "offset": 0 } } - ] - ], + } + ] + ], + [ + 145, [ - 145, - [ - { - "AllocSegment": { - "dst": { - "register": "FP", - "offset": 3 - } + { + "AllocSegment": { + "dst": { + "register": "FP", + "offset": 3 } } - ] - ], + } + ] + ], + [ + 153, [ - 153, - [ - { - "InitSquashData": { - "dict_accesses": { - "Deref": { - "register": "FP", - "offset": -4 - } - }, - "ptr_diff": { - "Deref": { - "register": "FP", - "offset": 0 - } - }, - "n_accesses": { - "Deref": { - "register": "AP", - "offset": -1 - } - }, - "big_keys": { + { + "InitSquashData": { + "dict_accesses": { + "Deref": { "register": "FP", - "offset": 2 - }, - "first_key": { + "offset": -4 + } + }, + "ptr_diff": { + "Deref": { "register": "FP", - "offset": 1 + "offset": 0 + } + }, + "n_accesses": { + "Deref": { + "register": "AP", + "offset": -1 } + }, + "big_keys": { + "register": "FP", + "offset": 2 + }, + "first_key": { + "register": "FP", + "offset": 1 } } - ] - ], + } + ] + ], + [ + 172, [ - 172, - [ - { - "GetCurrentAccessIndex": { - "range_check_ptr": { - "Deref": { - "register": "FP", - "offset": -9 - } + { + "GetCurrentAccessIndex": { + "range_check_ptr": { + "Deref": { + "register": "FP", + "offset": -9 } } } - ] - ], + } + ] + ], + [ + 185, [ - 185, - [ - { - "ShouldSkipSquashLoop": { - "should_skip_loop": { - "register": "AP", - "offset": -4 - } + { + "ShouldSkipSquashLoop": { + "should_skip_loop": { + "register": "AP", + "offset": -4 } } - ] - ], + } + ] + ], + [ + 187, [ - 187, - [ - { - "GetCurrentAccessDelta": { - "index_delta_minus1": { - "register": "AP", - "offset": 0 - } + { + "GetCurrentAccessDelta": { + "index_delta_minus1": { + "register": "AP", + "offset": 0 } } - ] - ], + } + ] + ], + [ + 198, [ - 198, - [ - { - "ShouldContinueSquashLoop": { - "should_continue": { - "register": "AP", - "offset": -4 - } + { + "ShouldContinueSquashLoop": { + "should_continue": { + "register": "AP", + "offset": -4 } } - ] - ], + } + ] + ], + [ + 212, [ - 212, - [ - { - "GetNextDictKey": { - "next_key": { - "register": "FP", - "offset": 0 - } + { + "GetNextDictKey": { + "next_key": { + "register": "FP", + "offset": 0 } } - ] - ], + } + ] + ], + [ + 231, [ - 231, - [ - { - "AssertLeFindSmallArcs": { - "range_check_ptr": { - "BinOp": { - "op": "Add", - "a": { - "register": "AP", - "offset": -4 - }, - "b": { - "Immediate": "0x1" - } - } - }, - "a": { - "Deref": { - "register": "FP", - "offset": -6 - } - }, - "b": { - "Deref": { - "register": "FP", - "offset": 0 + { + "AssertLeFindSmallArcs": { + "range_check_ptr": { + "BinOp": { + "op": "Add", + "a": { + "register": "AP", + "offset": -4 + }, + "b": { + "Immediate": "0x1" } } + }, + "a": { + "Deref": { + "register": "FP", + "offset": -6 + } + }, + "b": { + "Deref": { + "register": "FP", + "offset": 0 + } } } - ] - ], + } + ] + ], + [ + 243, [ - 243, - [ - { - "AssertLeIsFirstArcExcluded": { - "skip_exclude_a_flag": { - "register": "AP", - "offset": 0 - } + { + "AssertLeIsFirstArcExcluded": { + "skip_exclude_a_flag": { + "register": "AP", + "offset": 0 } } - ] - ], + } + ] + ], + [ + 255, [ - 255, - [ - { - "AssertLeIsSecondArcExcluded": { - "skip_exclude_b_minus_a": { - "register": "AP", - "offset": 0 - } + { + "AssertLeIsSecondArcExcluded": { + "skip_exclude_b_minus_a": { + "register": "AP", + "offset": 0 } } - ] + } ] ] - } - `), - ExpectedHintMap: map[uint64][]hinter.Hinter{ - 2: { - &AllocFelt252Dict{ - SegmentArenaPtr: hinter.Deref{ + ] + } + `) + expectedHintMap := map[uint64][]hinter.Hinter{ + 2: { + &AllocFelt252Dict{ + SegmentArenaPtr: hinter.Deref{ + Deref: hinter.FpCellRef(-4), + }, + }, + }, + 13: { + &AllocFelt252Dict{ + SegmentArenaPtr: hinter.BinaryOp{ + Operator: hinter.Add, + Lhs: hinter.Deref{ Deref: hinter.FpCellRef(-4), }, + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), }, }, - 13: { - &AllocFelt252Dict{ - SegmentArenaPtr: hinter.BinaryOp{ - Operator: hinter.Add, - Lhs: hinter.Deref{ - Deref: hinter.FpCellRef(-4), - }, - Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), - }, + }, + 46: { + &Felt252DictEntryInit{ + DictPtr: hinter.Deref{ + Deref: hinter.FpCellRef(2), + }, + Key: hinter.Deref{ + Deref: hinter.ApCellRef(-1), }, }, - 46: { - &Felt252DictEntryInit{ - DictPtr: hinter.Deref{ + }, + 49: { + &Felt252DictEntryUpdate{ + DictPtr: hinter.BinaryOp{ + Operator: hinter.Add, + Lhs: hinter.Deref{ Deref: hinter.FpCellRef(2), }, - Key: hinter.Deref{ - Deref: hinter.ApCellRef(-1), - }, + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), }, - }, - 49: { - &Felt252DictEntryUpdate{ - DictPtr: hinter.BinaryOp{ - Operator: hinter.Add, - Lhs: hinter.Deref{ - Deref: hinter.FpCellRef(2), - }, - Rhs: hinter.Immediate(*new(fp.Element).SetInt64(3)), - }, - Value: hinter.Deref{ - Deref: hinter.ApCellRef(-1), - }, + Value: hinter.Deref{ + Deref: hinter.ApCellRef(-1), }, }, - 104: { - &GetSegmentArenaIndex{ - DictEndPtr: hinter.Deref{ - Deref: hinter.FpCellRef(-3), - }, - DictIndex: hinter.FpCellRef(0), + }, + 104: { + &GetSegmentArenaIndex{ + DictEndPtr: hinter.Deref{ + Deref: hinter.FpCellRef(-3), }, + DictIndex: hinter.FpCellRef(0), }, - 145: { - &AllocSegment{ - Dst: hinter.FpCellRef(3), - }, + }, + 145: { + &AllocSegment{ + Dst: hinter.FpCellRef(3), }, - 153: { - &InitSquashData{ - DictAccesses: hinter.Deref{ - Deref: hinter.FpCellRef(-4), - }, - NumAccesses: hinter.Deref{ - Deref: hinter.ApCellRef(-1), - }, - BigKeys: hinter.FpCellRef(2), - FirstKey: hinter.FpCellRef(1), + }, + 153: { + &InitSquashData{ + DictAccesses: hinter.Deref{ + Deref: hinter.FpCellRef(-4), }, - }, - 172: { - &GetCurrentAccessIndex{ - RangeCheckPtr: hinter.Deref{ - Deref: hinter.FpCellRef(-9), - }, + NumAccesses: hinter.Deref{ + Deref: hinter.ApCellRef(-1), }, + BigKeys: hinter.FpCellRef(2), + FirstKey: hinter.FpCellRef(1), }, - 185: { - &ShouldSkipSquashLoop{ - ShouldSkipLoop: hinter.ApCellRef(-4), + }, + 172: { + &GetCurrentAccessIndex{ + RangeCheckPtr: hinter.Deref{ + Deref: hinter.FpCellRef(-9), }, }, - 187: { - &GetCurrentAccessDelta{ - IndexDeltaMinusOne: hinter.ApCellRef(0), - }, + }, + 185: { + &ShouldSkipSquashLoop{ + ShouldSkipLoop: hinter.ApCellRef(-4), }, - 198: { - &ShouldContinueSquashLoop{ - ShouldContinue: hinter.ApCellRef(-4), - }, + }, + 187: { + &GetCurrentAccessDelta{ + IndexDeltaMinusOne: hinter.ApCellRef(0), }, - 212: { - &GetNextDictKey{ - NextKey: hinter.FpCellRef(0), - }, + }, + 198: { + &ShouldContinueSquashLoop{ + ShouldContinue: hinter.ApCellRef(-4), }, - 231: { - &AssertLeFindSmallArc{ - RangeCheckPtr: hinter.BinaryOp{ - Operator: hinter.Add, - Lhs: hinter.Deref{ - Deref: hinter.ApCellRef(-4), - }, - Rhs: hinter.Immediate(*new(fp.Element).SetInt64(1)), - }, - A: hinter.Deref{ - Deref: hinter.FpCellRef(-6), - }, - B: hinter.Deref{ - Deref: hinter.FpCellRef(0), + }, + 212: { + &GetNextDictKey{ + NextKey: hinter.FpCellRef(0), + }, + }, + 231: { + &AssertLeFindSmallArc{ + RangeCheckPtr: hinter.BinaryOp{ + Operator: hinter.Add, + Lhs: hinter.Deref{ + Deref: hinter.ApCellRef(-4), }, + Rhs: hinter.Immediate(*new(fp.Element).SetInt64(1)), }, - }, - 243: { - &AssertLeIsFirstArcExcluded{ - SkipExcludeAFlag: hinter.ApCellRef(0), + A: hinter.Deref{ + Deref: hinter.FpCellRef(-6), }, - }, - 255: { - &AssertLeIsSecondArcExcluded{ - SkipExcludeBMinusA: hinter.ApCellRef(0), + B: hinter.Deref{ + Deref: hinter.FpCellRef(0), }, }, }, - }, - } + 243: { + &AssertLeIsFirstArcExcluded{ + SkipExcludeAFlag: hinter.ApCellRef(0), + }, + }, + 255: { + &AssertLeIsSecondArcExcluded{ + SkipExcludeBMinusA: hinter.ApCellRef(0), + }, + }, + } - for _, test := range testSet { - starknetProgram, err := starknet.StarknetProgramFromJSON(test.CairoProgramString) + starknetProgram, err := starknet.StarknetProgramFromJSON(cairoProgramString) require.NoError(t, err) output, err := GetCairoHints(starknetProgram) require.NoError(t, err) - require.Equal(t, test.ExpectedHintMap, output, "Hint maps do not match") - - } + require.Equal(t, expectedHintMap, output, "Hint maps do not match") + }) }