Skip to content

Commit

Permalink
cannon: Add support for --type mt to enable multithreaded cannon
Browse files Browse the repository at this point in the history
  • Loading branch information
ajsutton committed Aug 9, 2024
1 parent bf4693e commit 81d683b
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 7 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ cannon-prestate: op-program cannon ## Generates prestate using cannon and op-pro
mv op-program/bin/0.json op-program/bin/prestate-proof.json
.PHONY: cannon-prestate

cannon-prestate-mt: op-program cannon ## Generates prestate using cannon and op-program in the multithreaded cannon format
./cannon/bin/cannon load-elf --type mt --path op-program/bin/op-program-client.elf --out op-program/bin/prestate-mt.json --meta op-program/bin/meta-mt.json
./cannon/bin/cannon run --type mt --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-mt.json --meta op-program/bin/meta-mt.json --proof-fmt 'op-program/bin/%d-mt.json' --output ""
mv op-program/bin/0-mt.json op-program/bin/prestate-proof-mt.json
.PHONY: cannon-prestate

mod-tidy: ## Cleans up unused dependencies in Go modules
# Below GOPRIVATE line allows mod-tidy to be run immediately after
# releasing new versions. This bypasses the Go modules proxy, which
Expand Down
33 changes: 31 additions & 2 deletions cannon/cmd/load_elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"debug/elf"
"fmt"

"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded"
"github.com/urfave/cli/v2"

"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
Expand All @@ -12,6 +14,12 @@ import (
)

var (
LoadELFType = &cli.StringFlag{
Name: "type",
Usage: "VM type to create state for. Options are 'cannon' (default), 'mt'",
Value: "cannon",
Required: false,
}
LoadELFPathFlag = &cli.PathFlag{
Name: "path",
Usage: "Path to 32-bit big-endian MIPS ELF file",
Expand Down Expand Up @@ -39,6 +47,26 @@ var (
)

func LoadELF(ctx *cli.Context) error {
var createInitialState func(f *elf.File) (mipsevm.FPVMState, error)
var writeState func(path string, state mipsevm.FPVMState) error

if ctx.String("type") == "cannon" {
createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) {
return program.LoadELF(f, singlethreaded.CreateInitialState)
}
writeState = func(path string, state mipsevm.FPVMState) error {
return jsonutil.WriteJSON[*singlethreaded.State](path, state.(*singlethreaded.State), OutFilePerm)
}
} else if ctx.String("type") == "mt" {
createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) {
return program.LoadELF(f, multithreaded.CreateInitialState)
}
writeState = func(path string, state mipsevm.FPVMState) error {
return jsonutil.WriteJSON[*multithreaded.State](path, state.(*multithreaded.State), OutFilePerm)
}
} else {
return fmt.Errorf("invalid VM type: %s", ctx.String("type"))
}
elfPath := ctx.Path(LoadELFPathFlag.Name)
elfProgram, err := elf.Open(elfPath)
if err != nil {
Expand All @@ -47,7 +75,7 @@ func LoadELF(ctx *cli.Context) error {
if elfProgram.Machine != elf.EM_MIPS {
return fmt.Errorf("ELF is not big-endian MIPS R3000, but got %q", elfProgram.Machine.String())
}
state, err := program.LoadELF(elfProgram, singlethreaded.CreateInitialState)
state, err := createInitialState(elfProgram)
if err != nil {
return fmt.Errorf("failed to load ELF data into VM state: %w", err)
}
Expand All @@ -71,7 +99,7 @@ func LoadELF(ctx *cli.Context) error {
if err := jsonutil.WriteJSON[*program.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta, OutFilePerm); err != nil {
return fmt.Errorf("failed to output metadata: %w", err)
}
return jsonutil.WriteJSON[*singlethreaded.State](ctx.Path(LoadELFOutFlag.Name), state, OutFilePerm)
return writeState(ctx.Path(LoadELFOutFlag.Name), state)
}

var LoadELFCommand = &cli.Command{
Expand All @@ -80,6 +108,7 @@ var LoadELFCommand = &cli.Command{
Description: "Load ELF file into Cannon JSON state, optionally patch out functions",
Action: LoadELF,
Flags: []cli.Flag{
LoadELFType,
LoadELFPathFlag,
LoadELFPatchFlag,
LoadELFOutFlag,
Expand Down
28 changes: 24 additions & 4 deletions cannon/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

"github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
Expand All @@ -25,10 +26,9 @@ import (

var (
RunType = &cli.StringFlag{
Name: "type",
Usage: "VM type to run. Options are 'cannon' (default)",
Value: "cannon",
// TODO(client-pod#903): This should be required once we have additional vm types
Name: "type",
Usage: "VM type to run. Options are 'cannon' (default), 'mt'",
Value: "cannon",
Required: false,
}
RunInputFlag = &cli.PathFlag{
Expand Down Expand Up @@ -261,6 +261,7 @@ var _ mipsevm.PreimageOracle = (*ProcessPreimageOracle)(nil)
type VMType string

var cannonVMType VMType = "cannon"
var mtVMType VMType = "mt"

func Run(ctx *cli.Context) error {
if ctx.Bool(RunPProfCPU.Name) {
Expand All @@ -270,6 +271,8 @@ func Run(ctx *cli.Context) error {
var vmType VMType
if vmTypeStr := ctx.String(RunType.Name); vmTypeStr == string(cannonVMType) {
vmType = cannonVMType
} else if vmTypeStr == string(mtVMType) {
vmType = mtVMType
} else {
return fmt.Errorf("unknown VM type %q", vmType)
}
Expand Down Expand Up @@ -366,6 +369,7 @@ func Run(ctx *cli.Context) error {
var vm mipsevm.FPVM
var debugProgram bool
if vmType == cannonVMType {
l.Info("Using cannon VM")
cannon, err := singlethreaded.NewInstrumentedStateFromFile(ctx.Path(RunInputFlag.Name), po, outLog, errLog, meta)
if err != nil {
return err
Expand All @@ -380,6 +384,22 @@ func Run(ctx *cli.Context) error {
}
}
vm = cannon
} else if vmType == mtVMType {
l.Info("Using cannon multithreaded VM")
cannon, err := multithreaded.NewInstrumentedStateFromFile(ctx.Path(RunInputFlag.Name), po, outLog, errLog, l)
if err != nil {
return err
}
debugProgram = ctx.Bool(RunDebugFlag.Name)
if debugProgram {
if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" {
return fmt.Errorf("cannot enable debug mode without a metadata file")
}
if err := cannon.InitDebug(meta); err != nil {
return fmt.Errorf("failed to initialize debug mode: %w", err)
}
}
vm = cannon
} else {
return fmt.Errorf("unknown VM type %q", vmType)
}
Expand Down
20 changes: 19 additions & 1 deletion cannon/cmd/witness.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import (
"fmt"
"os"

"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded"
"github.com/urfave/cli/v2"

"github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
)

var (
WitnessType = &cli.StringFlag{
Name: "type",
Usage: "VM type to create state for. Options are 'cannon' (default), 'mt'",
Value: "cannon",
Required: false,
}
WitnessInputFlag = &cli.PathFlag{
Name: "input",
Usage: "path of input JSON state.",
Expand All @@ -27,10 +35,19 @@ var (
func Witness(ctx *cli.Context) error {
input := ctx.Path(WitnessInputFlag.Name)
output := ctx.Path(WitnessOutputFlag.Name)
state, err := jsonutil.LoadJSON[singlethreaded.State](input)
var state mipsevm.FPVMState
var err error
if ctx.String("type") == "cannon" {
state, err = jsonutil.LoadJSON[singlethreaded.State](input)
} else if ctx.String("type") == "mt" {
state, err = jsonutil.LoadJSON[multithreaded.State](input)
} else {
return fmt.Errorf("invalid VM type: %s", ctx.String("type"))
}
if err != nil {
return fmt.Errorf("invalid input state (%v): %w", input, err)
}

witness, h := state.EncodeWitness()
if output != "" {
if err := os.WriteFile(output, witness, 0755); err != nil {
Expand All @@ -47,6 +64,7 @@ var WitnessCommand = &cli.Command{
Description: "Convert a Cannon JSON state into a binary witness. The hash of the witness is written to stdout",
Action: Witness,
Flags: []cli.Flag{
WitnessType,
WitnessInputFlag,
WitnessOutputFlag,
},
Expand Down

0 comments on commit 81d683b

Please sign in to comment.