diff --git a/pkg/runners/cairo_runner.go b/pkg/runners/cairo_runner.go index 53354130..5e3564fb 100644 --- a/pkg/runners/cairo_runner.go +++ b/pkg/runners/cairo_runner.go @@ -228,11 +228,18 @@ func (r *CairoRunner) RunUntilPC(end memory.Relocatable, hintProcessor vm.HintPr return err } constants := r.Program.ExtractConstants() - for r.Vm.RunContext.Pc != end { + for r.Vm.RunContext.Pc != end && + (r.Vm.RunResources == nil || !r.Vm.RunResources.Consumed()) { err := r.Vm.Step(hintProcessor, &hintDataMap, &constants, &r.execScopes) if err != nil { return err } + if r.Vm.RunResources != nil { + r.Vm.RunResources.ConsumeStep() + } + } + if r.Vm.RunContext.Pc != end { + return errors.New("Could not reach the end of the program. RunResources has no remaining steps.") } return nil } @@ -588,7 +595,8 @@ If `verifySecure` is set to true, [verifySecureRunner] will be called to run ext `programSegmentSize` is only used by the [verifySecureRunner] function and will be ignored if `verifySecure` is set to false. Each arg can be either MaybeRelocatable, []MaybeRelocatable or [][]MaybeRelocatable */ -func (runner *CairoRunner) RunFromEntrypoint(entrypoint uint, args []any, hintProcessor vm.HintProcessor, verifySecure bool, programSegmentSize *uint) error { +func (runner *CairoRunner) RunFromEntrypoint(entrypoint uint, args []any, hintProcessor vm.HintProcessor, runResources *vm.RunResources, verifySecure bool, programSegmentSize *uint) error { + runner.Vm.RunResources = runResources stack := make([]memory.MaybeRelocatable, 0) for _, arg := range args { val, err := runner.Vm.Segments.GenArg(arg) diff --git a/pkg/runners/cairo_runner_test.go b/pkg/runners/cairo_runner_test.go index 0f5f34c6..8ca5ae54 100644 --- a/pkg/runners/cairo_runner_test.go +++ b/pkg/runners/cairo_runner_test.go @@ -743,7 +743,7 @@ func TestRunFromEntryPointFibonacci(t *testing.T) { runner.InitializeBuiltins() runner.InitializeSegments() - err := runner.RunFromEntrypoint(uint(entrypoint), args, &hintProcessor, true, nil) + err := runner.RunFromEntrypoint(uint(entrypoint), args, &hintProcessor, nil, true, nil) if err != nil { t.Errorf("Running fib entrypoint failed with error %s", err.Error()) @@ -759,3 +759,27 @@ func TestRunFromEntryPointFibonacci(t *testing.T) { } } + +func TestRunFromEntryPointFibonacciNotEnoughSteps(t *testing.T) { + compiledProgram, _ := parser.Parse("../../cairo_programs/fibonacci.json") + programJson := vm.DeserializeProgramJson(compiledProgram) + + entrypoint := programJson.Identifiers["__main__.fib"].PC + args := []any{ + *memory.NewMaybeRelocatableFelt(lambdaworks.FeltOne()), + *memory.NewMaybeRelocatableFelt(lambdaworks.FeltOne()), + *memory.NewMaybeRelocatableFelt(lambdaworks.FeltFromUint(10)), + } + runner, _ := runners.NewCairoRunner(programJson, "all_cairo", false) + hintProcessor := hints.CairoVmHintProcessor{} + + runner.InitializeBuiltins() + runner.InitializeSegments() + runResources := vm.NewRunResources(2) + err := runner.RunFromEntrypoint(uint(entrypoint), args, &hintProcessor, &runResources, true, nil) + + if err == nil { + t.Errorf("Running fib entrypoint should have failed") + } + +} diff --git a/pkg/vm/run_resources.go b/pkg/vm/run_resources.go new file mode 100644 index 00000000..e9da4247 --- /dev/null +++ b/pkg/vm/run_resources.go @@ -0,0 +1,23 @@ +package vm + +type RunResources struct { + nSteps *uint +} + +func NewRunResources(nSteps uint) RunResources { + return RunResources{nSteps: &nSteps} +} + +func (r *RunResources) Consumed() bool { + return r.nSteps != nil && *r.nSteps == 0 +} + +func (r *RunResources) ConsumeStep() { + if r.nSteps != nil && *r.nSteps != 0 { + *r.nSteps-- + } +} + +func (r *RunResources) GetNSteps() *uint { + return r.nSteps +} diff --git a/pkg/vm/vm_core.go b/pkg/vm/vm_core.go index c5cb69b1..7bbe3547 100644 --- a/pkg/vm/vm_core.go +++ b/pkg/vm/vm_core.go @@ -35,6 +35,7 @@ type VirtualMachine struct { RunFinished bool RcLimitsMin *int RcLimitsMax *int + RunResources *RunResources } func NewVirtualMachine() *VirtualMachine {