Skip to content

Commit

Permalink
Almost all pass
Browse files Browse the repository at this point in the history
  • Loading branch information
MaksymMalicki committed Jan 13, 2025
1 parent 086011a commit fc09b66
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 47 deletions.
11 changes: 1 addition & 10 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ 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"
)

Expand Down Expand Up @@ -221,22 +220,14 @@ func main() {
if err != nil {
return fmt.Errorf("cannot parse args: %w", err)
}
program, hints, err := runner.AssembleProgram(cairoProgram, userArgs)
program, hints, userArgs, err := runner.AssembleProgram(cairoProgram, userArgs, availableGas)
if err != nil {
return fmt.Errorf("cannot assemble program: %w", err)
}
runnerMode := runner.ExecutionModeCairo
if proofmode {
runnerMode = runner.ProofModeCairo
}
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)
},
},
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Set to run some specific file tests (ex. fib.cairo,alloc.cairo)
INTEGRATION_TESTS_FILTERS=
INTEGRATION_TESTS_FILTERS=poseidon_pedersen__starknet.cairo
4 changes: 2 additions & 2 deletions integration_tests/cairo_vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ func TestCairoFiles(t *testing.T) {
// {"./cairo_zero_hint_tests/", true},
// {"./cairo_zero_file_tests/", true},
// {"./builtin_tests/", true},
// {"./cairo_1_programs/", false},
// {"./cairo_1_programs/dict_non_squashed", false},
{"./cairo_1_programs/", false},
{"./cairo_1_programs/dict_non_squashed", false},
{"./cairo_1_programs/with_input", false},
}

Expand Down
32 changes: 25 additions & 7 deletions pkg/hintrunner/core/hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -1938,29 +1938,47 @@ func (hint *ExternalWriteArgsToMemory) String() string {
}

func (hint *ExternalWriteArgsToMemory) Execute(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
userArgsVar, err := ctx.ScopeManager.GetVariableValue("userArgs")
userArgs, err := hinter.GetVariableAs[[]starknet.CairoFuncArgs](&ctx.ScopeManager, "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")
apOffset, err := hinter.GetVariableAs[uint64](&ctx.ScopeManager, "apOffset")
if err != nil {
return fmt.Errorf("get ap offset: %v", err)
}
fmt.Println("apOffset", apOffset, "ap.offset", vm.Context.Ap)
apOffset += vm.Context.Ap
for _, arg := range userArgs {
if arg.Single != nil {
mv := mem.MemoryValueFromFieldElement(arg.Single)
err := vm.Memory.Write(1, vm.Context.Ap, &mv)
err := vm.Memory.Write(1, apOffset, &mv)
if err != nil {
return fmt.Errorf("write single arg: %v", err)
}
apOffset++
} else if arg.Array != nil {
arrayBase := vm.Memory.AllocateEmptySegment()
mv := mem.MemoryValueFromMemoryAddress(&arrayBase)
err := vm.Memory.Write(1, vm.Context.Ap, &mv)
err := vm.Memory.Write(1, apOffset, &mv)
if err != nil {
return fmt.Errorf("write array base: %v", err)
}
// TODO: Implement array writing
apOffset++
arrayEnd := arrayBase
for _, val := range arg.Array {
arrayEnd.Offset += 1
mv := mem.MemoryValueFromFieldElement(&val)
err := vm.Memory.Write(arrayEnd.SegmentIndex, arrayEnd.Offset, &mv)
if err != nil {
return fmt.Errorf("write array element: %v", err)
}
}
mv = mem.MemoryValueFromMemoryAddress(&arrayEnd)
err = vm.Memory.Write(1, apOffset, &mv)
if err != nil {
return fmt.Errorf("write array end: %v", err)
}
apOffset++
}
}
return nil
Expand Down
7 changes: 5 additions & 2 deletions pkg/hintrunner/hintrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ type HintRunner struct {
hints map[uint64][]h.Hinter
}

func NewHintRunner(hints map[uint64][]h.Hinter, userArgs []starknet.CairoFuncArgs) HintRunner {
func NewHintRunner(hints map[uint64][]h.Hinter, userArgs []starknet.CairoFuncArgs, writeApOffset uint64) HintRunner {
context := *h.InitializeDefaultContext()
if userArgs != nil {
err := context.ScopeManager.AssignVariable("userArgs", userArgs)
err := context.ScopeManager.AssignVariables(map[string]any{
"userArgs": userArgs,
"apOffset": writeApOffset,
})
// Error handling: this condition should never be true, since the context was initialized above
if err != nil {
panic(fmt.Errorf("assign userArgs: %v", err))
Expand Down
80 changes: 55 additions & 25 deletions pkg/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,20 @@ 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, userArgs []starknet.CairoFuncArgs) (Runner, error) {
hintrunner := hintrunner.NewHintRunner(hints, userArgs)
layout, err := builtins.GetLayout(layoutName)
if err != nil {
return Runner{}, err
}
writeApOffset := uint64(len(program.Builtins))
for _, builtin := range program.Builtins {
if builtin == builtins.SegmentArenaType {
writeApOffset += 3
}
if builtin == builtins.GasBuiltinType {
writeApOffset -= 1
}
}
hintrunner := hintrunner.NewHintRunner(hints, userArgs, writeApOffset)
return Runner{
program: program,
runnerMode: runnerMode,
Expand All @@ -59,10 +68,10 @@ func NewRunner(program *Program, hints map[uint64][]hinter.Hinter, runnerMode Ru
}, nil
}

func AssembleProgram(cairoProgram *starknet.StarknetProgram, userArgs []starknet.CairoFuncArgs) (Program, map[uint64][]hinter.Hinter, error) {
func AssembleProgram(cairoProgram *starknet.StarknetProgram, userArgs []starknet.CairoFuncArgs, availableGas uint64) (Program, map[uint64][]hinter.Hinter, []starknet.CairoFuncArgs, error) {
mainFunc, ok := cairoProgram.EntryPointsByFunction["main"]
if !ok {
return Program{}, nil, fmt.Errorf("cannot find main function")
return Program{}, nil, nil, fmt.Errorf("cannot find main function")
}
expectedArgsSize, actualArgsSize := 0, 0
for _, arg := range mainFunc.InputArgs {
Expand All @@ -76,19 +85,35 @@ func AssembleProgram(cairoProgram *starknet.StarknetProgram, userArgs []starknet
}
}
if expectedArgsSize != actualArgsSize {
return Program{}, nil, fmt.Errorf("missing arguments for main function")
return Program{}, nil, nil, fmt.Errorf("missing arguments for main function")
}
program, err := LoadCairoProgram(cairoProgram)
if err != nil {
return Program{}, nil, fmt.Errorf("cannot load program: %w", err)
return Program{}, nil, nil, fmt.Errorf("cannot load program: %w", err)
}
gotGasBuiltin := false
for _, b := range program.Builtins {
if b == builtins.GasBuiltinType {
gotGasBuiltin = true
break
}
}
if availableGas > 0 && gotGasBuiltin {
// The first argument is the available gas
availableGasArg := starknet.CairoFuncArgs{
Single: new(fp.Element).SetUint64(availableGas),
Array: nil,
}
userArgs = append([]starknet.CairoFuncArgs{availableGasArg}, userArgs...)
}
hints, err := core.GetCairoHints(cairoProgram)
if err != nil {
return Program{}, nil, fmt.Errorf("cannot get hints: %w", err)
return Program{}, nil, nil, fmt.Errorf("cannot get hints: %w", err)
}
entryCodeInstructions, entryCodeHints, err := GetEntryCodeInstructions(mainFunc, false)

entryCodeInstructions, entryCodeHints, err := GetEntryCodeInstructions(mainFunc, gotGasBuiltin)
if err != nil {
return Program{}, nil, fmt.Errorf("cannot load entry code instructions: %w", err)
return Program{}, nil, nil, fmt.Errorf("cannot load entry code instructions: %w", err)
}
program.Bytecode = append(entryCodeInstructions, program.Bytecode...)
program.Bytecode = append(program.Bytecode, GetFooterInstructions()...)
Expand All @@ -101,7 +126,7 @@ func AssembleProgram(cairoProgram *starknet.StarknetProgram, userArgs []starknet
for key, hint := range entryCodeHints {
shiftedHintsMap[key] = hint
}
return *program, shiftedHintsMap, nil
return *program, shiftedHintsMap, userArgs, nil
}

// RunEntryPoint is like Run, but it executes the program starting from the given PC offset.
Expand Down Expand Up @@ -329,7 +354,12 @@ func (runner *Runner) initializeVm(

// run until the program counter equals the `pc` parameter
func (runner *Runner) RunUntilPc(pc *mem.MemoryAddress) error {
// runner.vm.PrintMemory()
for !runner.vm.Context.Pc.Equal(pc) {
fmt.Println("pc", runner.vm.Context.Pc, "ap", runner.vm.Context.Ap, "fp", runner.vm.Context.Fp)
if runner.vm.Context.Pc.Offset == 102 {
runner.vm.PrintMemory()
}
if runner.steps() >= runner.maxsteps {
return fmt.Errorf(
"pc %s step %d: max step limit exceeded (%d)",
Expand Down Expand Up @@ -531,7 +561,7 @@ func (ctx *InlineCasmContext) AddInlineCASM(code string) {
ctx.currentCodeOffset += int(total_size)
}

func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeForProof bool) ([]*fp.Element, map[uint64][]hinter.Hinter, error) {
func GetEntryCodeInstructions(function starknet.EntryPointByFunction, gotGasBuiltin bool) ([]*fp.Element, map[uint64][]hinter.Hinter, error) {
paramTypes := function.InputArgs
apOffset := 0
builtinOffset := 3
Expand Down Expand Up @@ -594,8 +624,6 @@ func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeFo
paramsSize += param.Size
}
apOffset += paramsSize
usedArgs := 0

for _, builtin := range function.Builtins {
if offset, isBuiltin := builtinsOffsetsMap[builtin]; isBuiltin {
ctx.AddInlineCASM(
Expand All @@ -608,22 +636,24 @@ func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeFo
fmt.Sprintf("[ap + 0] = [ap - %d] + 3, ap++;", offset),
)
apOffset += 1
} else if builtin == builtins.GasBuiltinType {
hints[uint64(ctx.currentCodeOffset)] = []hinter.Hinter{
&core.ExternalWriteArgsToMemory{},
}
ctx.AddInlineCASM("ap += 1;")
apOffset += 1
usedArgs += 1
}
}
offset := apOffset - usedArgs

if gotGasBuiltin {
ctx.AddInlineCASM("ap += 1;")
apOffset += 1

Check failure on line 644 in pkg/runner/runner.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to apOffset (ineffassign)
}

for _, param := range paramTypes {
for i := 0; i < param.Size; i++ {
ctx.AddInlineCASM(
fmt.Sprintf("[ap + 0] = [ap - %d], ap++;", offset),
)
}
ctx.AddInlineCASM(
fmt.Sprintf("ap+=%d;", param.Size),
)
}

if gotGasBuiltin || paramsSize > 0 {
hints[uint64(0)] = append(hints[uint64(0)], []hinter.Hinter{
&core.ExternalWriteArgsToMemory{},
}...)
}

_, endInstructionsSize, err := assembler.CasmToBytecode("call rel 0; ret;")
Expand Down

0 comments on commit fc09b66

Please sign in to comment.