diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 55839c55..1f41bfa3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: '1.21' cache: false - name: golangci-lint uses: golangci/golangci-lint-action@v3 @@ -27,7 +27,7 @@ jobs: # Require: The version of golangci-lint to use. # When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version. # When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit. - version: v1.53.3 + version: v1.55.2 # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 1ef9abe7..a8e009f9 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.20" + go-version: "1.21" - name: Build run: make build diff --git a/Makefile b/Makefile index 79269ac4..d3c129ac 100644 --- a/Makefile +++ b/Makefile @@ -41,31 +41,29 @@ integration: @echo "Running integration tests..." @$(MAKE) build @if [ $$? -eq 0 ]; then \ - if [ ! -d ./rust_vm_bin ]; then \ - mkdir -p ./rust_vm_bin; \ + if [ ! -d rust_vm_bin ]; then \ + mkdir -p rust_vm_bin; \ fi; \ - if [ ! -d ./rust_vm_bin/cairo ]; then \ - mkdir -p ./rust_vm_bin/cairo; \ + if [ ! -d rust_vm_bin/cairo ]; then \ + mkdir -p rust_vm_bin/cairo-lang; \ fi; \ - if [ ! -f ./rust_vm_bin/cairo/cairo-compile ] || [ ! -f ./rust_vm_bin/cairo/sierra-compile-json ] || [ ! -d ./rust_vm_bin/corelib ]; then \ - cd ./rust_vm_bin/cairo; \ + if [ ! -f ./rust_vm_bin/cairo-lang/cairo-compile ] || [ ! -f ./rust_vm_bin/cairo-lang/sierra-compile-json ] || [ ! -d rust_vm_bin/corelib ]; then \ + cd rust_vm_bin; \ git clone --single-branch --branch feat/main-casm-json --depth=1 https://github.com/zmalatrax/cairo.git; \ - mv cairo/corelib ../../rust_vm_bin/; \ - cd cairo/crates/bin && \ - cargo build --release --bin cairo-compile --bin sierra-compile-json && \ - cd ../../../; \ - mv cairo/target/release/cairo-compile cairo/target/release/sierra-compile-json ../cairo/ && \ - rm -rf ./cairo; \ + mv cairo/corelib .; \ + cd cairo/crates/bin && cargo build --release --bin cairo-compile --bin sierra-compile-json && cd ../../../; \ + mv cairo/target/release/cairo-compile cairo/target/release/sierra-compile-json cairo-lang; \ + rm -rf cairo; \ + cd ../; \ fi; \ - if [ ! -f ./rust_vm_bin/cairo/cairo1-run ] || [ ! -f ./rust_vm_bin/cairo-vm-cli ]; then \ - cd ./rust_vm_bin; \ - git clone https://github.com/lambdaclass/cairo-vm.git && \ - cd cairo-vm/; \ - cargo build --release --bin cairo-vm-cli --bin cairo1-run; \ - mv cairo-vm/target/release/cairo1-run ./cairo/ && \ - mv cairo-vm/target/release/cairo-vm-cli ../rust_vm_bin/ && \ + if [ ! -f ./rust_vm_bin/cairo-lang/cairo1-run ] || [ ! -f ./rust_vm_bin/cairo-vm-cli ]; then \ + cd rust_vm_bin; \ + git clone https://github.com/lambdaclass/cairo-vm.git; \ + cd cairo-vm && cargo build --release --bin cairo-vm-cli --bin cairo1-run && cd ../; \ + mv cairo-vm/target/release/cairo1-run cairo-lang;\ + mv cairo-vm/target/release/cairo-vm-cli . ; \ rm -rf cairo-vm; \ - cd ../../; \ + cd ../; \ fi; \ go test ./integration_tests/... -v; \ else \ diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 082c3643..151b4a28 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -12,6 +12,7 @@ import ( "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" zero "github.com/NethermindEth/cairo-vm-go/pkg/parsers/zero" "github.com/NethermindEth/cairo-vm-go/pkg/runner" + "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" "github.com/urfave/cli/v2" ) @@ -26,6 +27,8 @@ func main() { var layoutName string var airPublicInputLocation string var airPrivateInputLocation string + var args string + var availableGas uint64 app := &cli.App{ Name: "cairo-vm", Usage: "A cairo virtual machine", @@ -122,7 +125,7 @@ func main() { if proofmode { runnerMode = runner.ProofModeCairo0 } - return runVM(*program, proofmode, maxsteps, entrypointOffset, collectTrace, traceLocation, buildMemory, memoryLocation, layoutName, airPublicInputLocation, airPrivateInputLocation, hints, runnerMode) + return runVM(*program, proofmode, maxsteps, entrypointOffset, collectTrace, traceLocation, buildMemory, memoryLocation, layoutName, airPublicInputLocation, airPrivateInputLocation, hints, runnerMode, nil) }, }, { @@ -191,6 +194,18 @@ func main() { Required: false, Destination: &airPrivateInputLocation, }, + &cli.StringFlag{ + Name: "args", + Usage: "input arguments for the `main` function in the cairo progran", + Required: false, + Destination: &args, + }, + &cli.Uint64Flag{ + Name: "available_gas", + Usage: "available gas for the VM execution", + Required: false, + Destination: &availableGas, + }, }, Action: func(ctx *cli.Context) error { pathToFile := ctx.Args().Get(0) @@ -210,7 +225,19 @@ func main() { if proofmode { runnerMode = runner.ProofModeCairo1 } - return runVM(program, proofmode, maxsteps, entrypointOffset, collectTrace, traceLocation, buildMemory, memoryLocation, layoutName, airPublicInputLocation, airPrivateInputLocation, hints, runnerMode) + userArgs, err := starknet.ParseCairoProgramArgs(args) + if err != nil { + return fmt.Errorf("cannot parse args: %w", err) + } + if availableGas > 0 { + // The first argument is the available gas + availableGasArg := starknet.CairoFuncArgs{ + Single: new(fp.Element).SetUint64(availableGas), + Array: nil, + } + userArgs = append([]starknet.CairoFuncArgs{availableGasArg}, userArgs...) + } + return runVM(program, proofmode, maxsteps, entrypointOffset, collectTrace, traceLocation, buildMemory, memoryLocation, layoutName, airPublicInputLocation, airPrivateInputLocation, hints, runnerMode, userArgs) }, }, }, @@ -236,9 +263,10 @@ func runVM( airPrivateInputLocation string, hints map[uint64][]hinter.Hinter, runnerMode runner.RunnerMode, + userArgs []starknet.CairoFuncArgs, ) error { fmt.Println("Running....") - runner, err := runner.NewRunner(&program, hints, runnerMode, collectTrace, maxsteps, layoutName) + runner, err := runner.NewRunner(&program, hints, runnerMode, collectTrace, maxsteps, layoutName, userArgs) if err != nil { return fmt.Errorf("cannot create runner: %w", err) } diff --git a/integration_tests/cairo_1_programs/dict_with_struct.cairo b/integration_tests/cairo_1_programs/dict_with_struct__small.cairo similarity index 100% rename from integration_tests/cairo_1_programs/dict_with_struct.cairo rename to integration_tests/cairo_1_programs/dict_with_struct__small.cairo diff --git a/integration_tests/cairo_1_programs/dictionaries.cairo b/integration_tests/cairo_1_programs/dictionaries__small.cairo similarity index 100% rename from integration_tests/cairo_1_programs/dictionaries.cairo rename to integration_tests/cairo_1_programs/dictionaries__small.cairo diff --git a/integration_tests/cairo_1_programs/sample.cairo b/integration_tests/cairo_1_programs/sample__small.cairo similarity index 100% rename from integration_tests/cairo_1_programs/sample.cairo rename to integration_tests/cairo_1_programs/sample__small.cairo diff --git a/integration_tests/cairo_vm_test.go b/integration_tests/cairo_vm_test.go index 4c940cc1..c38a14cf 100644 --- a/integration_tests/cairo_vm_test.go +++ b/integration_tests/cairo_vm_test.go @@ -459,16 +459,18 @@ func runVm(path, layout string, zero bool) (time.Duration, string, string, strin } args := []string{ cliCommand, - "--proofmode", + // "--proofmode", "--tracefile", traceOutput, "--memoryfile", memoryOutput, "--layout", layout, - path, } - + if !zero { + args = append(args, "--available_gas", "9999999") + } + args = append(args, path) cmd := exec.Command( "../bin/cairo-vm", args..., diff --git a/pkg/hintrunner/core/hint.go b/pkg/hintrunner/core/hint.go index 3efa7a9f..202c6891 100644 --- a/pkg/hintrunner/core/hint.go +++ b/pkg/hintrunner/core/hint.go @@ -1929,3 +1929,38 @@ func (hint *FieldSqrt) Execute(vm *VM.VirtualMachine, _ *hinter.HintRunnerContex return vm.Memory.WriteToAddress(&sqrtAddr, &sqrtVal) } + +type ExternalWriteArgsToMemory struct{} + +func (hint *ExternalWriteArgsToMemory) String() string { + return "ExternalWriteToMemory" +} + +func (hint *ExternalWriteArgsToMemory) Execute(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error { + userArgsVar, err := ctx.ScopeManager.GetVariableValue("userArgs") + if err != nil { + return fmt.Errorf("get user args: %v", err) + } + userArgs, ok := userArgsVar.([]starknet.CairoFuncArgs) + if !ok { + return fmt.Errorf("expected user args to be a list of CairoFuncArgs") + } + for _, arg := range userArgs { + if arg.Single != nil { + mv := mem.MemoryValueFromFieldElement(arg.Single) + err := vm.Memory.Write(1, vm.Context.Ap, &mv) + if err != nil { + return fmt.Errorf("write single arg: %v", err) + } + } else if arg.Array != nil { + arrayBase := vm.Memory.AllocateEmptySegment() + mv := mem.MemoryValueFromMemoryAddress(&arrayBase) + err := vm.Memory.Write(1, vm.Context.Ap, &mv) + if err != nil { + return fmt.Errorf("write array base: %v", err) + } + // TODO: Implement array writing + } + } + return nil +} diff --git a/pkg/hintrunner/hintrunner.go b/pkg/hintrunner/hintrunner.go index f8e54ebb..c1a209e7 100644 --- a/pkg/hintrunner/hintrunner.go +++ b/pkg/hintrunner/hintrunner.go @@ -4,6 +4,7 @@ import ( "fmt" h "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" + "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet" VM "github.com/NethermindEth/cairo-vm-go/pkg/vm" ) @@ -14,11 +15,18 @@ type HintRunner struct { hints map[uint64][]h.Hinter } -func NewHintRunner(hints map[uint64][]h.Hinter) HintRunner { +func NewHintRunner(hints map[uint64][]h.Hinter, userArgs []starknet.CairoFuncArgs) HintRunner { + context := *h.InitializeDefaultContext() + if userArgs != nil { + err := context.ScopeManager.AssignVariable("userArgs", userArgs) + if err != nil { + panic(fmt.Errorf("assign userArgs: %v", err)) + } + } return HintRunner{ // Context for certain hints that require it. Each manager is // initialized only when required by the hint - context: *h.InitializeDefaultContext(), + context: context, hints: hints, } } diff --git a/pkg/hintrunner/hintrunner_test.go b/pkg/hintrunner/hintrunner_test.go index 0e057de9..c3cbbd5e 100644 --- a/pkg/hintrunner/hintrunner_test.go +++ b/pkg/hintrunner/hintrunner_test.go @@ -20,7 +20,7 @@ func TestExistingHint(t *testing.T) { hr := NewHintRunner(map[uint64][]hinter.Hinter{ 10: {&allocHint}, - }) + }, nil) vm.Context.Pc = memory.MemoryAddress{ SegmentIndex: 0, @@ -44,7 +44,7 @@ func TestNoHint(t *testing.T) { hr := NewHintRunner(map[uint64][]hinter.Hinter{ 10: {&allocHint}, - }) + }, nil) vm.Context.Pc = memory.MemoryAddress{ SegmentIndex: 0, diff --git a/pkg/parsers/starknet/args.go b/pkg/parsers/starknet/args.go new file mode 100644 index 00000000..0e7d2845 --- /dev/null +++ b/pkg/parsers/starknet/args.go @@ -0,0 +1,56 @@ +package starknet + +import ( + "fmt" + "regexp" + "strings" + + "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" +) + +type CairoFuncArgs struct { + Single *fp.Element + Array []fp.Element +} + +func ParseCairoProgramArgs(input string) ([]CairoFuncArgs, error) { + re := regexp.MustCompile(`\[[^\]]*\]|\S+`) + tokens := re.FindAllString(input, -1) + var result []CairoFuncArgs + + parseValueToFelt := func(token string) (*fp.Element, error) { + felt, err := new(fp.Element).SetString(token) + if err != nil { + return nil, fmt.Errorf("invalid felt value: %v", err) + } + return felt, nil + } + + for _, token := range tokens { + if single, err := parseValueToFelt(token); err == nil { + result = append(result, CairoFuncArgs{ + Single: single, + Array: nil, + }) + } else if strings.HasPrefix(token, "[") && strings.HasSuffix(token, "]") { + arrayStr := strings.Trim(token, "[]") + arrayElements := strings.Fields(arrayStr) + array := make([]fp.Element, len(arrayElements)) + for i, element := range arrayElements { + single, err := parseValueToFelt(element) + if err != nil { + return nil, fmt.Errorf("invalid felt value in array: %v", err) + } + array[i] = *single + } + result = append(result, CairoFuncArgs{ + Single: nil, + Array: array, + }) + } else { + return nil, fmt.Errorf("invalid token: %s", token) + } + } + + return result, nil +} diff --git a/pkg/parsers/starknet/args_test.go b/pkg/parsers/starknet/args_test.go new file mode 100644 index 00000000..f6bdd6f9 --- /dev/null +++ b/pkg/parsers/starknet/args_test.go @@ -0,0 +1,115 @@ +package starknet + +import ( + "fmt" + "testing" + + "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseStarknetProgramArgs(t *testing.T) { + testCases := []struct { + name string + args string + expected []CairoFuncArgs + err error + }{ + { + name: "single arg", + args: "1", + expected: []CairoFuncArgs{ + { + Single: new(fp.Element).SetUint64(1), + Array: nil, + }, + }, + err: nil, + }, + { + name: "single array arg", + args: "[1 2 3 4]", + expected: []CairoFuncArgs{ + { + Single: nil, + Array: []fp.Element{ + *new(fp.Element).SetUint64(1), + *new(fp.Element).SetUint64(2), + *new(fp.Element).SetUint64(3), + *new(fp.Element).SetUint64(4), + }, + }, + }, + }, + { + name: "nested array arg", + args: "[1 [2 3 4]]", + expected: nil, + err: fmt.Errorf("invalid felt value in array: invalid felt value: Element.SetString failed -> can't parse number into a big.Int [2"), + }, + { + name: "mixed args", + args: "1 [2 3 4] 5 [6 7 8] [1] 9 9 [12341341234 0]", + expected: []CairoFuncArgs{ + { + Single: new(fp.Element).SetUint64(1), + Array: nil, + }, + { + Single: nil, + Array: []fp.Element{ + *new(fp.Element).SetUint64(2), + *new(fp.Element).SetUint64(3), + *new(fp.Element).SetUint64(4), + }, + }, + { + Single: new(fp.Element).SetUint64(5), + Array: nil, + }, + { + Single: nil, + Array: []fp.Element{ + *new(fp.Element).SetUint64(6), + *new(fp.Element).SetUint64(7), + *new(fp.Element).SetUint64(8), + }, + }, + { + Single: nil, + Array: []fp.Element{ + *new(fp.Element).SetUint64(1), + }, + }, + { + Single: new(fp.Element).SetUint64(9), + Array: nil, + }, + { + Single: new(fp.Element).SetUint64(9), + Array: nil, + }, + { + Single: nil, + Array: []fp.Element{ + *new(fp.Element).SetUint64(12341341234), + *new(fp.Element).SetUint64(0), + }, + }, + }, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + args, err := ParseCairoProgramArgs(testCase.args) + if testCase.err != nil { + require.Error(t, err) + assert.Equal(t, testCase.err.Error(), err.Error()) + return + } + require.NoError(t, err) + assert.Equal(t, testCase.expected, args) + }) + } +} diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index bac6daee..f3228b17 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -42,8 +42,8 @@ type Runner struct { type CairoRunner struct{} // Creates a new Runner of a Cairo Zero program -func NewRunner(program *Program, hints map[uint64][]hinter.Hinter, runnerMode RunnerMode, collectTrace bool, maxsteps uint64, layoutName string) (Runner, error) { - hintrunner := hintrunner.NewHintRunner(hints) +func NewRunner(program *Program, hints map[uint64][]hinter.Hinter, runnerMode RunnerMode, collectTrace bool, maxsteps uint64, layoutName string, userArgs []starknet.CairoFuncArgs) (Runner, error) { + hintrunner := hintrunner.NewHintRunner(hints, userArgs) layout, err := builtins.GetLayout(layoutName) if err != nil { return Runner{}, err @@ -67,22 +67,25 @@ func AssembleProgram(cairoProgram *starknet.StarknetProgram) (Program, map[uint6 if err != nil { return Program{}, nil, fmt.Errorf("cannot load program: %w", err) } - entryCodeInstructions, err := GetEntryCodeInstructions(mainFunc, false, 0) + hints, err := core.GetCairoHints(cairoProgram) + if err != nil { + return Program{}, nil, fmt.Errorf("cannot get hints: %w", err) + } + entryCodeInstructions, entryCodeHints, err := GetEntryCodeInstructions(mainFunc, false) if err != nil { return Program{}, nil, fmt.Errorf("cannot load entry code instructions: %w", err) } program.Bytecode = append(entryCodeInstructions, program.Bytecode...) program.Bytecode = append(program.Bytecode, GetFooterInstructions()...) - hints, err := core.GetCairoHints(cairoProgram) - if err != nil { - return Program{}, nil, fmt.Errorf("cannot get hints: %w", err) - } offset := uint64(len(entryCodeInstructions)) shiftedHintsMap := make(map[uint64][]hinter.Hinter) for key, value := range hints { shiftedHintsMap[key+offset] = value } + for key, hint := range entryCodeHints { + shiftedHintsMap[key] = hint + } return *program, shiftedHintsMap, nil } @@ -115,10 +118,6 @@ func (runner *Runner) RunEntryPoint(pc uint64) error { if err != nil { return err } - err = runner.loadArguments(uint64(0), uint64(8979879877)) - if err != nil { - return err - } if err := runner.RunUntilPc(&end); err != nil { return err } @@ -136,10 +135,6 @@ func (runner *Runner) Run() error { return fmt.Errorf("initializing main entry point: %w", err) } - err = runner.loadArguments(uint64(0), uint64(8979879877)) - if err != nil { - return err - } err = runner.RunUntilPc(&end) if err != nil { return err @@ -181,10 +176,8 @@ func (runner *Runner) initializeMainEntrypoint() (mem.MemoryAddress, error) { case ExecutionMode, ProofModeCairo1: returnFp := memory.AllocateEmptySegment() mvReturnFp := mem.MemoryValueFromMemoryAddress(&returnFp) - mainPCOffset, ok := runner.program.Entrypoints["main"] - if !ok { - return mem.UnknownAddress, errors.New("can't find an entrypoint for main") - } + // In Cairo mainPCOffset is equal to the offset of program segment base + mainPCOffset := uint64(0) if runner.runnerMode == ExecutionMode { return runner.initializeEntrypoint(mainPCOffset, nil, &mvReturnFp, memory, stack, 0) } else { @@ -281,7 +274,16 @@ func (runner *Runner) initializeVm( return err } } - + // Write builtins costs segment address to the end of the program segment + if runner.runnerMode == ProofModeCairo1 || runner.runnerMode == ExecutionMode { + builtinsCostSegmentAddress := memory.AllocateEmptySegment() + mv := mem.MemoryValueFromMemoryAddress(&builtinsCostSegmentAddress) + programSegment := memory.Segments[vm.ProgramSegment] + err := memory.Write(0, programSegment.Len(), &mv) + if err != nil { + return err + } + } initialFp := offset + uint64(len(stack)) + cairo1FpOffset var err error // initialize vm @@ -296,12 +298,6 @@ func (runner *Runner) initializeVm( return err } -func (runner *Runner) loadArguments(args, initialGas uint64) error { - mv := mem.MemoryValueFromUint(initialGas) - runner.vm.Memory.Segments[vm.ExecutionSegment].Write(runner.vm.Context.Ap+1, &mv) - return nil -} - // run until the program counter equals the `pc` parameter func (runner *Runner) RunUntilPc(pc *mem.MemoryAddress) error { for !runner.vm.Context.Pc.Equal(pc) { @@ -506,11 +502,11 @@ func (ctx *InlineCasmContext) AddInlineCASM(code string) { ctx.currentCodeOffset += int(total_size) } -func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeForProof bool, initialGas uint64) ([]*fp.Element, error) { +func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeForProof bool) ([]*fp.Element, map[uint64][]hinter.Hinter, error) { paramTypes := function.InputArgs apOffset := 0 builtinOffset := 3 - + codeOffset := uint64(function.Offset) builtinsOffsetsMap := map[builtins.BuiltinType]int{} emulatedBuiltins := map[builtins.BuiltinType]struct{}{ builtins.SystemType: {}, @@ -539,7 +535,7 @@ func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeFo } apOffset += paramsSize usedArgs := 0 - + var hints map[uint64][]hinter.Hinter for _, builtin := range function.Builtins { if offset, isBuiltin := builtinsOffsetsMap[builtin]; isBuiltin { ctx.AddInlineCASM( @@ -561,11 +557,12 @@ func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeFo ) apOffset += 1 } else if builtin == builtins.GasBuiltinType { - ctx.AddInlineCASM( - ` - ap += 1; - `, - ) + hints = map[uint64][]hinter.Hinter{ + uint64(ctx.currentCodeOffset): { + &core.ExternalWriteArgsToMemory{}, + }, + } + ctx.AddInlineCASM("ap += 1;") apOffset += 1 usedArgs += 1 } @@ -580,10 +577,13 @@ func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeFo usedArgs += param.Size } } - ctx.AddInlineCASM(fmt.Sprintf("call rel %d;", apOffset+1)) - ctx.AddInlineCASM("ret;") - - return ctx.instructions, nil + _, endInstructionsSize, err := assembler.CasmToBytecode("call rel 0; ret;") + if err != nil { + return nil, nil, err + } + totalSize := uint64(endInstructionsSize) + uint64(codeOffset) + ctx.AddInlineCASM(fmt.Sprintf("call rel %d; ret;", int(totalSize))) + return ctx.instructions, hints, nil } func GetFooterInstructions() []*fp.Element { diff --git a/pkg/runner/runner_benchmark_test.go b/pkg/runner/runner_benchmark_test.go index d86be979..64bc7b87 100644 --- a/pkg/runner/runner_benchmark_test.go +++ b/pkg/runner/runner_benchmark_test.go @@ -233,7 +233,7 @@ func BenchmarkRunnerWithFibonacci(b *testing.B) { panic(err) } - runner, err := NewRunner(program, hints, ProofModeCairo0, false, math.MaxUint64, "plain") + runner, err := NewRunner(program, hints, ProofModeCairo0, false, math.MaxUint64, "plain", nil) if err != nil { panic(err) } diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 8c876d64..f94834cf 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -27,7 +27,7 @@ func TestSimpleProgram(t *testing.T) { `) hints := make(map[uint64][]hinter.Hinter) - runner, err := NewRunner(program, hints, ExecutionMode, false, math.MaxUint64, "plain") + runner, err := NewRunner(program, hints, ExecutionMode, false, math.MaxUint64, "plain", nil) require.NoError(t, err) endPc, err := runner.initializeMainEntrypoint() @@ -74,7 +74,7 @@ func TestStepLimitExceeded(t *testing.T) { `) hints := make(map[uint64][]hinter.Hinter) - runner, err := NewRunner(program, hints, ExecutionMode, false, 3, "plain") + runner, err := NewRunner(program, hints, ExecutionMode, false, 3, "plain", nil) require.NoError(t, err) endPc, err := runner.initializeMainEntrypoint() @@ -133,7 +133,7 @@ func TestStepLimitExceededProofMode(t *testing.T) { // when maxstep = 6, it fails executing the extra step required by proof mode // when maxstep = 7, it fails trying to get the trace to be a power of 2 hints := make(map[uint64][]hinter.Hinter) - runner, err := NewRunner(program, hints, ProofModeCairo0, false, uint64(maxstep), "plain") + runner, err := NewRunner(program, hints, ProofModeCairo0, false, uint64(maxstep), "plain", nil) require.NoError(t, err) err = runner.Run() @@ -436,7 +436,7 @@ func createRunner(code string, layoutName string, builtins ...builtins.BuiltinTy program := createProgramWithBuiltins(code, builtins...) hints := make(map[uint64][]hinter.Hinter) - runner, err := NewRunner(program, hints, ExecutionMode, false, math.MaxUint64, layoutName) + runner, err := NewRunner(program, hints, ExecutionMode, false, math.MaxUint64, layoutName, nil) if err != nil { panic(err) } diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 65c6ab8e..7673f6ac 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -91,6 +91,14 @@ type VirtualMachine struct { RcLimitsMax uint16 } +func (vm *VirtualMachine) PrintMemory() { + for i := range vm.Memory.Segments { + for j, cell := range vm.Memory.Segments[i].Data { + fmt.Printf("%d:%d %s\n", i, j, cell) + } + } +} + // NewVirtualMachine creates a VM from the program bytecode using a specified config. func NewVirtualMachine( initialContext Context, memory *mem.Memory, config VirtualMachineConfig,