Skip to content

Commit

Permalink
Cairo1 runner fixes (#675)
Browse files Browse the repository at this point in the history
* Fixes for the generation of entry code, fixes of hints parsing

* Add modifications to the runner

* Add fixes for the entrycode generation

* Refactor main CLI, offset the hints indexes by entry code size, load arguments and initial gas to the memory

* Add available gas and user args (#677)

* Add parsing logic for input user args

* Add flags for available gas, input user args, writing args to memory

* Fix unit tests for user arguments parsing

* Lint the PR

* Add user args to hint context

* Refactor the code

* Fix unconditional append of ExternalWriteArgsToMemory, bug fixes in integration tests

* Add fixes of the call size calculation and include ExternalWriteArgsToMemory hint when gas present

* Add layouts for integration tests

* Add error handling

* Fixes in entry code generation

* Address changes mentioned in a discussion

* Add comment regarding writing to memory in a hint for the future reference in the integration tests with args

* Changes in calculations of the initial PC offset, CALL opcode offset incremented by mainFuncOffset, writing user args to the AP in the hint

* Turn back VM config to private field

* Add error handling on assign of `userArgs` to the initial scope

* Lint project

* Bump go version from 1.20 -> 1.21 (#678)

* Bump go version from 1.20 -> 1.21

* Update golangci-lint

* Simplify the Makefile

* Correction in the makefile

* Fix the integration tests

* Fixes in the runner

* Fixes in the runner

* Fix the unit tests, uncomment pythonVm execution in integration tests, code cleanups

* Add writing tokens gas cost to memory

* Proper builtins initialization for cairo mode

* Address comments in the PR

* Removed systemtype from builtins
  • Loading branch information
MaksymMalicki authored Jan 10, 2025
1 parent f506eb5 commit 75ec869
Show file tree
Hide file tree
Showing 23 changed files with 558 additions and 194 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ 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
with:
# 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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ cov.out
cpu.out
*.test
integration_tests/BenchMarks.txt
integration_tests/list_tests_in_progress.txt
rust_vm_bin/

# Local Env Specific
Expand Down
38 changes: 18 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
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/ && \
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 \
Expand Down
53 changes: 35 additions & 18 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
"os"
"path/filepath"

"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"
"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 All @@ -27,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",
Expand Down Expand Up @@ -119,11 +121,11 @@ func main() {
if err != nil {
return fmt.Errorf("cannot load program: %w", err)
}
runnerMode := runner.ExecutionMode
runnerMode := runner.ExecutionModeZero
if proofmode {
runnerMode = runner.ProofModeCairo0
runnerMode = runner.ProofModeZero
}
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)
},
},
{
Expand Down Expand Up @@ -192,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)
Expand All @@ -203,25 +217,27 @@ func main() {
if err != nil {
return fmt.Errorf("cannot load program: %w", err)
}
hints, err := core.GetCairoHints(cairoProgram)
program, hints, err := runner.AssembleProgram(cairoProgram)
if err != nil {
return fmt.Errorf("cannot get hints: %w", err)
return fmt.Errorf("cannot assemble program: %w", err)
}
program, err := runner.LoadCairoProgram(cairoProgram)
if err != nil {
return fmt.Errorf("cannot load program: %w", err)
runnerMode := runner.ExecutionModeCairo
if proofmode {
runnerMode = runner.ProofModeCairo
}
entryCodeInstructions, err := runner.GetEntryCodeInstructions()
userArgs, err := starknet.ParseCairoProgramArgs(args)
if err != nil {
return fmt.Errorf("cannot load entry code instructions: %w", err)
return fmt.Errorf("cannot parse args: %w", err)
}
program.Bytecode = append(entryCodeInstructions, program.Bytecode...)
program.Bytecode = append(program.Bytecode, runner.GetFooterInstructions()...)
runnerMode := runner.ExecutionMode
if proofmode {
runnerMode = runner.ProofModeCairo1
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)
return runVM(program, proofmode, maxsteps, entrypointOffset, collectTrace, traceLocation, buildMemory, memoryLocation, layoutName, airPublicInputLocation, airPrivateInputLocation, hints, runnerMode, userArgs)
},
},
},
Expand All @@ -247,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)
}
Expand Down
54 changes: 32 additions & 22 deletions integration_tests/cairo_vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,40 +74,47 @@ func runAndTestFile(t *testing.T, path string, name string, benchmarkMap map[str
return
}
layout := getLayoutFromFileName(path)
rustVmFilePath := path
if zero {
rustVmFilePath = compiledOutput
}
elapsedRs, rsTraceFile, rsMemoryFile, err := runRustVm(rustVmFilePath, layout, zero)

elapsedGo, traceFile, memoryFile, _, err := runVm(compiledOutput, layout, zero)
if errorExpected {
// we let the code go on so that we can check if the go vm also raises an error
assert.Error(t, err, path)
writeToFile(path)
return
} else {
if err != nil {
t.Error(err)
writeToFile(path)
return
}
}

elapsedGo, traceFile, memoryFile, _, err := runVm(compiledOutput, layout, zero)
rustVmFilePath := path
if zero {
rustVmFilePath = compiledOutput
}
elapsedRs, rsTraceFile, rsMemoryFile, err := runRustVm(rustVmFilePath, layout, zero)
if errorExpected {
// we let the code go on so that we can check if the go vm also raises an error
assert.Error(t, err, path)
return
} else {
if err != nil {
t.Error(err)
writeToFile(path)
return
}
}

trace, memory, err := decodeProof(traceFile, memoryFile)
if err != nil {
t.Error(err)
writeToFile(path)
return
}
rsTrace, rsMemory, err := decodeProof(rsTraceFile, rsMemoryFile)
if err != nil {
t.Error(err)
writeToFile(path)
return
}

Expand Down Expand Up @@ -144,16 +151,6 @@ func runAndTestFile(t *testing.T, path string, name string, benchmarkMap map[str
return
}

if !assert.Equal(t, pyTrace, rsTrace) {
t.Logf("pytrace:\n%s\n", traceRepr(pyTrace))
t.Logf("rstrace:\n%s\n", traceRepr(rsTrace))
writeToFile(path)
}
if !assert.Equal(t, pyMemory, rsMemory) {
t.Logf("pymemory;\n%s\n", memoryRepr(pyMemory))
t.Logf("rsmemory;\n%s\n", memoryRepr(rsMemory))
writeToFile(path)
}
if !assert.Equal(t, pyTrace, trace) {
t.Logf("pytrace:\n%s\n", traceRepr(pyTrace))
t.Logf("trace:\n%s\n", traceRepr(trace))
Expand Down Expand Up @@ -329,7 +326,7 @@ func compileCairoCode(path string, zero bool) (string, error) {
}
} else {
sierraOutput := swapExtenstion(path, sierraSuffix)
cliCommand = "../rust_vm_bin/cairo/cairo-compile"
cliCommand = "../rust_vm_bin/cairo-lang/cairo-compile"
args = []string{
"--single-file",
path,
Expand All @@ -346,7 +343,7 @@ func compileCairoCode(path string, zero bool) (string, error) {
)
}

cliCommand = "../rust_vm_bin/cairo/sierra-compile-json"
cliCommand = "../rust_vm_bin/cairo-lang/sierra-compile-json"
args = []string{
sierraOutput,
compiledOutput,
Expand Down Expand Up @@ -420,7 +417,7 @@ func runRustVm(path, layout string, zero bool) (time.Duration, string, string, e
args = append(args, "--proof_mode")
}

binaryPath := "./../rust_vm_bin/cairo/cairo1-run"
binaryPath := "./../rust_vm_bin/cairo-lang/cairo1-run"
if zero {
binaryPath = "./../rust_vm_bin/cairo-vm-cli"
}
Expand Down Expand Up @@ -460,9 +457,22 @@ func runVm(path, layout string, zero bool) (time.Duration, string, string, strin
memoryOutput,
"--layout",
layout,
path,
}

if !zero {
args = []string{
cliCommand,
// "--proofmode",
"--tracefile",
traceOutput,
"--memoryfile",
memoryOutput,
"--layout",
layout,
"--available_gas",
"9999999",
}
}
args = append(args, path)
cmd := exec.Command(
"../bin/cairo-vm",
args...,
Expand Down
14 changes: 14 additions & 0 deletions pkg/hintrunner/core/cairo_hintparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,20 @@ func GetHintByName(hint starknet.Hint) (hinter.Hinter, error) {
quotient: parseCellRefer(args.Quotient),
remainder: parseCellRefer(args.Remainder),
}, nil
case starknet.Uint256InvModNName:
args := hint.Args.(*starknet.Uint256InvModN)
return &Uint256InvModN{
B0: parseResOperand(args.B0),
B1: parseResOperand(args.B1),
N0: parseResOperand(args.N0),
N1: parseResOperand(args.N1),
G0OrNoInv: parseCellRefer(args.G0OrNoInv),
G1Option: parseCellRefer(args.G1Option),
SOrR0: parseCellRefer(args.SOrR0),
SOrR1: parseCellRefer(args.SOrR1),
TOrK0: parseCellRefer(args.TOrK0),
TOrK1: parseCellRefer(args.TOrK1),
}, nil
case starknet.Uint256DivModName:
args := hint.Args.(*starknet.Uint256DivMod)
return &Uint256DivMod{
Expand Down
Loading

0 comments on commit 75ec869

Please sign in to comment.