Commit 8d9287bc authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger: Deduplicate executor (#10785)

* challenger: Create generic vm executor and use for asterisc

* challenger: Move executor utils to vm package

* challenger: Switch cannon to use common vm executor.

* challenger: Use vm.Config to encapsulate Cannon config items.

* challenger: Rename to include Path

* challenger: Use vm.Config to encapsulate Asterisc config items.

* challenger: Remove unused interface

* challenger: Reduce amount of config passed to cannon/asterisc trace providers

* challenger: Remove Config from names

* challenger: Remove replaced cannon metrics
parent 48263376
...@@ -277,7 +277,7 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -277,7 +277,7 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-bin", "--asterisc-bin=./asterisc")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-bin", "--asterisc-bin=./asterisc"))
require.Equal(t, "./asterisc", cfg.AsteriscBin) require.Equal(t, "./asterisc", cfg.Asterisc.VmBin)
}) })
}) })
...@@ -292,7 +292,7 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -292,7 +292,7 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-server", "--asterisc-server=./op-program")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-server", "--asterisc-server=./op-program"))
require.Equal(t, "./op-program", cfg.AsteriscServer) require.Equal(t, "./op-program", cfg.Asterisc.Server)
}) })
}) })
...@@ -349,12 +349,12 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -349,12 +349,12 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestAsteriscSnapshotFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscSnapshotFreq-%v", traceType), func(t *testing.T) {
t.Run("UsesDefault", func(t *testing.T) { t.Run("UsesDefault", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType)) cfg := configForArgs(t, addRequiredArgs(traceType))
require.Equal(t, config.DefaultAsteriscSnapshotFreq, cfg.AsteriscSnapshotFreq) require.Equal(t, config.DefaultAsteriscSnapshotFreq, cfg.Asterisc.SnapshotFreq)
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType, "--asterisc-snapshot-freq=1234")) cfg := configForArgs(t, addRequiredArgs(traceType, "--asterisc-snapshot-freq=1234"))
require.Equal(t, uint(1234), cfg.AsteriscSnapshotFreq) require.Equal(t, uint(1234), cfg.Asterisc.SnapshotFreq)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
...@@ -366,12 +366,12 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -366,12 +366,12 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestAsteriscInfoFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscInfoFreq-%v", traceType), func(t *testing.T) {
t.Run("UsesDefault", func(t *testing.T) { t.Run("UsesDefault", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType)) cfg := configForArgs(t, addRequiredArgs(traceType))
require.Equal(t, config.DefaultAsteriscInfoFreq, cfg.AsteriscInfoFreq) require.Equal(t, config.DefaultAsteriscInfoFreq, cfg.Asterisc.InfoFreq)
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType, "--asterisc-info-freq=1234")) cfg := configForArgs(t, addRequiredArgs(traceType, "--asterisc-info-freq=1234"))
require.Equal(t, uint(1234), cfg.AsteriscInfoFreq) require.Equal(t, uint(1234), cfg.Asterisc.InfoFreq)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
...@@ -432,7 +432,7 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -432,7 +432,7 @@ func TestAsteriscRequiredArgs(t *testing.T) {
delete(args, "--game-factory-address") delete(args, "--game-factory-address")
args["--network"] = "op-sepolia" args["--network"] = "op-sepolia"
cfg := configForArgs(t, toArgList(args)) cfg := configForArgs(t, toArgList(args))
require.Equal(t, "op-sepolia", cfg.AsteriscNetwork) require.Equal(t, "op-sepolia", cfg.Asterisc.Network)
}) })
t.Run("MustNotSpecifyNetworkAndAsteriscNetwork", func(t *testing.T) { t.Run("MustNotSpecifyNetworkAndAsteriscNetwork", func(t *testing.T) {
...@@ -442,7 +442,7 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -442,7 +442,7 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-network", "--asterisc-network", testNetwork)) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-network", "--asterisc-network", testNetwork))
require.Equal(t, testNetwork, cfg.AsteriscNetwork) require.Equal(t, testNetwork, cfg.Asterisc.Network)
}) })
}) })
...@@ -453,7 +453,7 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -453,7 +453,7 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-network", "--asterisc-rollup-config=rollup.json", "--asterisc-l2-genesis=genesis.json")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-network", "--asterisc-rollup-config=rollup.json", "--asterisc-l2-genesis=genesis.json"))
require.Equal(t, "rollup.json", cfg.AsteriscRollupConfigPath) require.Equal(t, "rollup.json", cfg.Asterisc.RollupConfigPath)
}) })
}) })
...@@ -464,7 +464,7 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -464,7 +464,7 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-network", "--asterisc-rollup-config=rollup.json", "--asterisc-l2-genesis=genesis.json")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-network", "--asterisc-rollup-config=rollup.json", "--asterisc-l2-genesis=genesis.json"))
require.Equal(t, "genesis.json", cfg.AsteriscL2GenesisPath) require.Equal(t, "genesis.json", cfg.Asterisc.L2GenesisPath)
}) })
}) })
} }
...@@ -502,7 +502,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -502,7 +502,7 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-bin", "--cannon-bin=./cannon")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-bin", "--cannon-bin=./cannon"))
require.Equal(t, "./cannon", cfg.CannonBin) require.Equal(t, "./cannon", cfg.Cannon.VmBin)
}) })
}) })
...@@ -517,7 +517,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -517,7 +517,7 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-server", "--cannon-server=./op-program")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-server", "--cannon-server=./op-program"))
require.Equal(t, "./op-program", cfg.CannonServer) require.Equal(t, "./op-program", cfg.Cannon.Server)
}) })
}) })
...@@ -570,12 +570,12 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -570,12 +570,12 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestCannonSnapshotFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonSnapshotFreq-%v", traceType), func(t *testing.T) {
t.Run("UsesDefault", func(t *testing.T) { t.Run("UsesDefault", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType)) cfg := configForArgs(t, addRequiredArgs(traceType))
require.Equal(t, config.DefaultCannonSnapshotFreq, cfg.CannonSnapshotFreq) require.Equal(t, config.DefaultCannonSnapshotFreq, cfg.Cannon.SnapshotFreq)
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType, "--cannon-snapshot-freq=1234")) cfg := configForArgs(t, addRequiredArgs(traceType, "--cannon-snapshot-freq=1234"))
require.Equal(t, uint(1234), cfg.CannonSnapshotFreq) require.Equal(t, uint(1234), cfg.Cannon.SnapshotFreq)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
...@@ -587,12 +587,12 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -587,12 +587,12 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestCannonInfoFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonInfoFreq-%v", traceType), func(t *testing.T) {
t.Run("UsesDefault", func(t *testing.T) { t.Run("UsesDefault", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType)) cfg := configForArgs(t, addRequiredArgs(traceType))
require.Equal(t, config.DefaultCannonInfoFreq, cfg.CannonInfoFreq) require.Equal(t, config.DefaultCannonInfoFreq, cfg.Cannon.InfoFreq)
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(traceType, "--cannon-info-freq=1234")) cfg := configForArgs(t, addRequiredArgs(traceType, "--cannon-info-freq=1234"))
require.Equal(t, uint(1234), cfg.CannonInfoFreq) require.Equal(t, uint(1234), cfg.Cannon.InfoFreq)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
...@@ -653,7 +653,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -653,7 +653,7 @@ func TestCannonRequiredArgs(t *testing.T) {
delete(args, "--game-factory-address") delete(args, "--game-factory-address")
args["--network"] = "op-sepolia" args["--network"] = "op-sepolia"
cfg := configForArgs(t, toArgList(args)) cfg := configForArgs(t, toArgList(args))
require.Equal(t, "op-sepolia", cfg.CannonNetwork) require.Equal(t, "op-sepolia", cfg.Cannon.Network)
}) })
t.Run("MustNotSpecifyNetworkAndCannonNetwork", func(t *testing.T) { t.Run("MustNotSpecifyNetworkAndCannonNetwork", func(t *testing.T) {
...@@ -663,7 +663,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -663,7 +663,7 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-network", testNetwork)) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-network", testNetwork))
require.Equal(t, testNetwork, cfg.CannonNetwork) require.Equal(t, testNetwork, cfg.Cannon.Network)
}) })
}) })
...@@ -674,7 +674,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -674,7 +674,7 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json"))
require.Equal(t, "rollup.json", cfg.CannonRollupConfigPath) require.Equal(t, "rollup.json", cfg.Cannon.RollupConfigPath)
}) })
}) })
...@@ -685,7 +685,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -685,7 +685,7 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json"))
require.Equal(t, "genesis.json", cfg.CannonL2GenesisPath) require.Equal(t, "genesis.json", cfg.Cannon.L2GenesisPath)
}) })
}) })
} }
...@@ -729,7 +729,7 @@ func TestGameWindow(t *testing.T) { ...@@ -729,7 +729,7 @@ func TestGameWindow(t *testing.T) {
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--game-window=1m")) cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--game-window=1m"))
require.Equal(t, time.Duration(time.Minute), cfg.GameWindow) require.Equal(t, time.Minute, cfg.GameWindow)
}) })
t.Run("ParsesDefault", func(t *testing.T) { t.Run("ParsesDefault", func(t *testing.T) {
......
...@@ -8,12 +8,12 @@ import ( ...@@ -8,12 +8,12 @@ import (
"slices" "slices"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum-optimism/optimism/op-service/oppprof" "github.com/ethereum-optimism/optimism/op-service/oppprof"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
) )
var ( var (
...@@ -129,26 +129,14 @@ type Config struct { ...@@ -129,26 +129,14 @@ type Config struct {
L2Rpc string // L2 RPC Url L2Rpc string // L2 RPC Url
// Specific to the cannon trace provider // Specific to the cannon trace provider
CannonBin string // Path to the cannon executable to run when generating trace data Cannon vm.Config
CannonServer string // Path to the op-program executable that provides the pre-image oracle server
CannonAbsolutePreState string // File to load the absolute pre-state for Cannon traces from CannonAbsolutePreState string // File to load the absolute pre-state for Cannon traces from
CannonAbsolutePreStateBaseURL *url.URL // Base URL to retrieve absolute pre-states for Cannon traces from CannonAbsolutePreStateBaseURL *url.URL // Base URL to retrieve absolute pre-states for Cannon traces from
CannonNetwork string
CannonRollupConfigPath string
CannonL2GenesisPath string
CannonSnapshotFreq uint // Frequency of snapshots to create when executing cannon (in VM instructions)
CannonInfoFreq uint // Frequency of cannon progress log messages (in VM instructions)
// Specific to the asterisc trace provider // Specific to the asterisc trace provider
AsteriscBin string // Path to the asterisc executable to run when generating trace data Asterisc vm.Config
AsteriscServer string // Path to the op-program executable that provides the pre-image oracle server
AsteriscAbsolutePreState string // File to load the absolute pre-state for Asterisc traces from AsteriscAbsolutePreState string // File to load the absolute pre-state for Asterisc traces from
AsteriscAbsolutePreStateBaseURL *url.URL // Base URL to retrieve absolute pre-states for Asterisc traces from AsteriscAbsolutePreStateBaseURL *url.URL // Base URL to retrieve absolute pre-states for Asterisc traces from
AsteriscNetwork string
AsteriscRollupConfigPath string
AsteriscL2GenesisPath string
AsteriscSnapshotFreq uint // Frequency of snapshots to create when executing asterisc (in VM instructions)
AsteriscInfoFreq uint // Frequency of asterisc progress log messages (in VM instructions)
MaxPendingTx uint64 // Maximum number of pending transactions (0 == no limit) MaxPendingTx uint64 // Maximum number of pending transactions (0 == no limit)
...@@ -185,11 +173,23 @@ func NewConfig( ...@@ -185,11 +173,23 @@ func NewConfig(
Datadir: datadir, Datadir: datadir,
CannonSnapshotFreq: DefaultCannonSnapshotFreq, Cannon: vm.Config{
CannonInfoFreq: DefaultCannonInfoFreq, VmType: TraceTypeCannon.String(),
AsteriscSnapshotFreq: DefaultAsteriscSnapshotFreq, L1: l1EthRpc,
AsteriscInfoFreq: DefaultAsteriscInfoFreq, L1Beacon: l1BeaconApi,
GameWindow: DefaultGameWindow, L2: l2EthRpc,
SnapshotFreq: DefaultCannonSnapshotFreq,
InfoFreq: DefaultCannonInfoFreq,
},
Asterisc: vm.Config{
VmType: TraceTypeAsterisc.String(),
L1: l1EthRpc,
L1Beacon: l1BeaconApi,
L2: l2EthRpc,
SnapshotFreq: DefaultAsteriscSnapshotFreq,
InfoFreq: DefaultAsteriscInfoFreq,
},
GameWindow: DefaultGameWindow,
} }
} }
...@@ -223,28 +223,28 @@ func (c Config) Check() error { ...@@ -223,28 +223,28 @@ func (c Config) Check() error {
return ErrMaxConcurrencyZero return ErrMaxConcurrencyZero
} }
if c.TraceTypeEnabled(TraceTypeCannon) || c.TraceTypeEnabled(TraceTypePermissioned) { if c.TraceTypeEnabled(TraceTypeCannon) || c.TraceTypeEnabled(TraceTypePermissioned) {
if c.CannonBin == "" { if c.Cannon.VmBin == "" {
return ErrMissingCannonBin return ErrMissingCannonBin
} }
if c.CannonServer == "" { if c.Cannon.Server == "" {
return ErrMissingCannonServer return ErrMissingCannonServer
} }
if c.CannonNetwork == "" { if c.Cannon.Network == "" {
if c.CannonRollupConfigPath == "" { if c.Cannon.RollupConfigPath == "" {
return ErrMissingCannonRollupConfig return ErrMissingCannonRollupConfig
} }
if c.CannonL2GenesisPath == "" { if c.Cannon.L2GenesisPath == "" {
return ErrMissingCannonL2Genesis return ErrMissingCannonL2Genesis
} }
} else { } else {
if c.CannonRollupConfigPath != "" { if c.Cannon.RollupConfigPath != "" {
return ErrCannonNetworkAndRollupConfig return ErrCannonNetworkAndRollupConfig
} }
if c.CannonL2GenesisPath != "" { if c.Cannon.L2GenesisPath != "" {
return ErrCannonNetworkAndL2Genesis return ErrCannonNetworkAndL2Genesis
} }
if ch := chaincfg.ChainByName(c.CannonNetwork); ch == nil { if ch := chaincfg.ChainByName(c.Cannon.Network); ch == nil {
return fmt.Errorf("%w: %v", ErrCannonNetworkUnknown, c.CannonNetwork) return fmt.Errorf("%w: %v", ErrCannonNetworkUnknown, c.Cannon.Network)
} }
} }
if c.CannonAbsolutePreState == "" && c.CannonAbsolutePreStateBaseURL == nil { if c.CannonAbsolutePreState == "" && c.CannonAbsolutePreStateBaseURL == nil {
...@@ -253,36 +253,36 @@ func (c Config) Check() error { ...@@ -253,36 +253,36 @@ func (c Config) Check() error {
if c.CannonAbsolutePreState != "" && c.CannonAbsolutePreStateBaseURL != nil { if c.CannonAbsolutePreState != "" && c.CannonAbsolutePreStateBaseURL != nil {
return ErrCannonAbsolutePreStateAndBaseURL return ErrCannonAbsolutePreStateAndBaseURL
} }
if c.CannonSnapshotFreq == 0 { if c.Cannon.SnapshotFreq == 0 {
return ErrMissingCannonSnapshotFreq return ErrMissingCannonSnapshotFreq
} }
if c.CannonInfoFreq == 0 { if c.Cannon.InfoFreq == 0 {
return ErrMissingCannonInfoFreq return ErrMissingCannonInfoFreq
} }
} }
if c.TraceTypeEnabled(TraceTypeAsterisc) { if c.TraceTypeEnabled(TraceTypeAsterisc) {
if c.AsteriscBin == "" { if c.Asterisc.VmBin == "" {
return ErrMissingAsteriscBin return ErrMissingAsteriscBin
} }
if c.AsteriscServer == "" { if c.Asterisc.Server == "" {
return ErrMissingAsteriscServer return ErrMissingAsteriscServer
} }
if c.AsteriscNetwork == "" { if c.Asterisc.Network == "" {
if c.AsteriscRollupConfigPath == "" { if c.Asterisc.RollupConfigPath == "" {
return ErrMissingAsteriscRollupConfig return ErrMissingAsteriscRollupConfig
} }
if c.AsteriscL2GenesisPath == "" { if c.Asterisc.L2GenesisPath == "" {
return ErrMissingAsteriscL2Genesis return ErrMissingAsteriscL2Genesis
} }
} else { } else {
if c.AsteriscRollupConfigPath != "" { if c.Asterisc.RollupConfigPath != "" {
return ErrAsteriscNetworkAndRollupConfig return ErrAsteriscNetworkAndRollupConfig
} }
if c.AsteriscL2GenesisPath != "" { if c.Asterisc.L2GenesisPath != "" {
return ErrAsteriscNetworkAndL2Genesis return ErrAsteriscNetworkAndL2Genesis
} }
if ch := chaincfg.ChainByName(c.AsteriscNetwork); ch == nil { if ch := chaincfg.ChainByName(c.Asterisc.Network); ch == nil {
return fmt.Errorf("%w: %v", ErrAsteriscNetworkUnknown, c.AsteriscNetwork) return fmt.Errorf("%w: %v", ErrAsteriscNetworkUnknown, c.Asterisc.Network)
} }
} }
if c.AsteriscAbsolutePreState == "" && c.AsteriscAbsolutePreStateBaseURL == nil { if c.AsteriscAbsolutePreState == "" && c.AsteriscAbsolutePreStateBaseURL == nil {
...@@ -291,10 +291,10 @@ func (c Config) Check() error { ...@@ -291,10 +291,10 @@ func (c Config) Check() error {
if c.AsteriscAbsolutePreState != "" && c.AsteriscAbsolutePreStateBaseURL != nil { if c.AsteriscAbsolutePreState != "" && c.AsteriscAbsolutePreStateBaseURL != nil {
return ErrAsteriscAbsolutePreStateAndBaseURL return ErrAsteriscAbsolutePreStateAndBaseURL
} }
if c.AsteriscSnapshotFreq == 0 { if c.Asterisc.SnapshotFreq == 0 {
return ErrMissingAsteriscSnapshotFreq return ErrMissingAsteriscSnapshotFreq
} }
if c.AsteriscInfoFreq == 0 { if c.Asterisc.InfoFreq == 0 {
return ErrMissingAsteriscInfoFreq return ErrMissingAsteriscInfoFreq
} }
} }
......
...@@ -36,17 +36,17 @@ var cannonTraceTypes = []TraceType{TraceTypeCannon, TraceTypePermissioned} ...@@ -36,17 +36,17 @@ var cannonTraceTypes = []TraceType{TraceTypeCannon, TraceTypePermissioned}
var asteriscTraceTypes = []TraceType{TraceTypeAsterisc} var asteriscTraceTypes = []TraceType{TraceTypeAsterisc}
func applyValidConfigForCannon(cfg *Config) { func applyValidConfigForCannon(cfg *Config) {
cfg.CannonBin = validCannonBin cfg.Cannon.VmBin = validCannonBin
cfg.CannonServer = validCannonOpProgramBin cfg.Cannon.Server = validCannonOpProgramBin
cfg.CannonAbsolutePreStateBaseURL = validCannonAbsolutPreStateBaseURL cfg.CannonAbsolutePreStateBaseURL = validCannonAbsolutPreStateBaseURL
cfg.CannonNetwork = validCannonNetwork cfg.Cannon.Network = validCannonNetwork
} }
func applyValidConfigForAsterisc(cfg *Config) { func applyValidConfigForAsterisc(cfg *Config) {
cfg.AsteriscBin = validAsteriscBin cfg.Asterisc.VmBin = validAsteriscBin
cfg.AsteriscServer = validAsteriscOpProgramBin cfg.Asterisc.Server = validAsteriscOpProgramBin
cfg.AsteriscAbsolutePreStateBaseURL = validAsteriscAbsolutPreStateBaseURL cfg.AsteriscAbsolutePreStateBaseURL = validAsteriscAbsolutPreStateBaseURL
cfg.AsteriscNetwork = validAsteriscNetwork cfg.Asterisc.Network = validAsteriscNetwork
} }
func validConfig(traceType TraceType) Config { func validConfig(traceType TraceType) Config {
...@@ -115,13 +115,13 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -115,13 +115,13 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestCannonBinRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonBinRequired-%v", traceType), func(t *testing.T) {
config := validConfig(traceType) config := validConfig(traceType)
config.CannonBin = "" config.Cannon.VmBin = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonBin) require.ErrorIs(t, config.Check(), ErrMissingCannonBin)
}) })
t.Run(fmt.Sprintf("TestCannonServerRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonServerRequired-%v", traceType), func(t *testing.T) {
config := validConfig(traceType) config := validConfig(traceType)
config.CannonServer = "" config.Cannon.Server = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonServer) require.ErrorIs(t, config.Check(), ErrMissingCannonServer)
}) })
...@@ -162,7 +162,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -162,7 +162,7 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestCannonSnapshotFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonSnapshotFreq-%v", traceType), func(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) { t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.CannonSnapshotFreq = 0 cfg.Cannon.SnapshotFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq) require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq)
}) })
}) })
...@@ -170,46 +170,46 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -170,46 +170,46 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestCannonInfoFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonInfoFreq-%v", traceType), func(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) { t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.CannonInfoFreq = 0 cfg.Cannon.InfoFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingCannonInfoFreq) require.ErrorIs(t, cfg.Check(), ErrMissingCannonInfoFreq)
}) })
}) })
t.Run(fmt.Sprintf("TestCannonNetworkOrRollupConfigRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonNetworkOrRollupConfigRequired-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.CannonNetwork = "" cfg.Cannon.Network = ""
cfg.CannonRollupConfigPath = "" cfg.Cannon.RollupConfigPath = ""
cfg.CannonL2GenesisPath = "genesis.json" cfg.Cannon.L2GenesisPath = "genesis.json"
require.ErrorIs(t, cfg.Check(), ErrMissingCannonRollupConfig) require.ErrorIs(t, cfg.Check(), ErrMissingCannonRollupConfig)
}) })
t.Run(fmt.Sprintf("TestCannonNetworkOrL2GenesisRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonNetworkOrL2GenesisRequired-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.CannonNetwork = "" cfg.Cannon.Network = ""
cfg.CannonRollupConfigPath = "foo.json" cfg.Cannon.RollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = "" cfg.Cannon.L2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrMissingCannonL2Genesis) require.ErrorIs(t, cfg.Check(), ErrMissingCannonL2Genesis)
}) })
t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.CannonNetwork = validCannonNetwork cfg.Cannon.Network = validCannonNetwork
cfg.CannonRollupConfigPath = "foo.json" cfg.Cannon.RollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = "" cfg.Cannon.L2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndRollupConfig) require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndRollupConfig)
}) })
t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndL2Genesis-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndL2Genesis-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.CannonNetwork = validCannonNetwork cfg.Cannon.Network = validCannonNetwork
cfg.CannonRollupConfigPath = "" cfg.Cannon.RollupConfigPath = ""
cfg.CannonL2GenesisPath = "foo.json" cfg.Cannon.L2GenesisPath = "foo.json"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndL2Genesis) require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndL2Genesis)
}) })
t.Run(fmt.Sprintf("TestNetworkMustBeValid-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestNetworkMustBeValid-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.CannonNetwork = "unknown" cfg.Cannon.Network = "unknown"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown) require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown)
}) })
} }
...@@ -221,13 +221,13 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -221,13 +221,13 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestAsteriscBinRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscBinRequired-%v", traceType), func(t *testing.T) {
config := validConfig(traceType) config := validConfig(traceType)
config.AsteriscBin = "" config.Asterisc.VmBin = ""
require.ErrorIs(t, config.Check(), ErrMissingAsteriscBin) require.ErrorIs(t, config.Check(), ErrMissingAsteriscBin)
}) })
t.Run(fmt.Sprintf("TestAsteriscServerRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscServerRequired-%v", traceType), func(t *testing.T) {
config := validConfig(traceType) config := validConfig(traceType)
config.AsteriscServer = "" config.Asterisc.Server = ""
require.ErrorIs(t, config.Check(), ErrMissingAsteriscServer) require.ErrorIs(t, config.Check(), ErrMissingAsteriscServer)
}) })
...@@ -268,7 +268,7 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -268,7 +268,7 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestAsteriscSnapshotFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscSnapshotFreq-%v", traceType), func(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) { t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.AsteriscSnapshotFreq = 0 cfg.Asterisc.SnapshotFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscSnapshotFreq) require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscSnapshotFreq)
}) })
}) })
...@@ -276,46 +276,46 @@ func TestAsteriscRequiredArgs(t *testing.T) { ...@@ -276,46 +276,46 @@ func TestAsteriscRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestAsteriscInfoFreq-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscInfoFreq-%v", traceType), func(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) { t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.AsteriscInfoFreq = 0 cfg.Asterisc.InfoFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscInfoFreq) require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscInfoFreq)
}) })
}) })
t.Run(fmt.Sprintf("TestAsteriscNetworkOrRollupConfigRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscNetworkOrRollupConfigRequired-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.AsteriscNetwork = "" cfg.Asterisc.Network = ""
cfg.AsteriscRollupConfigPath = "" cfg.Asterisc.RollupConfigPath = ""
cfg.AsteriscL2GenesisPath = "genesis.json" cfg.Asterisc.L2GenesisPath = "genesis.json"
require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscRollupConfig) require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscRollupConfig)
}) })
t.Run(fmt.Sprintf("TestAsteriscNetworkOrL2GenesisRequired-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestAsteriscNetworkOrL2GenesisRequired-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.AsteriscNetwork = "" cfg.Asterisc.Network = ""
cfg.AsteriscRollupConfigPath = "foo.json" cfg.Asterisc.RollupConfigPath = "foo.json"
cfg.AsteriscL2GenesisPath = "" cfg.Asterisc.L2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscL2Genesis) require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscL2Genesis)
}) })
t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.AsteriscNetwork = validAsteriscNetwork cfg.Asterisc.Network = validAsteriscNetwork
cfg.AsteriscRollupConfigPath = "foo.json" cfg.Asterisc.RollupConfigPath = "foo.json"
cfg.AsteriscL2GenesisPath = "" cfg.Asterisc.L2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrAsteriscNetworkAndRollupConfig) require.ErrorIs(t, cfg.Check(), ErrAsteriscNetworkAndRollupConfig)
}) })
t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndL2Genesis-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndL2Genesis-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.AsteriscNetwork = validAsteriscNetwork cfg.Asterisc.Network = validAsteriscNetwork
cfg.AsteriscRollupConfigPath = "" cfg.Asterisc.RollupConfigPath = ""
cfg.AsteriscL2GenesisPath = "foo.json" cfg.Asterisc.L2GenesisPath = "foo.json"
require.ErrorIs(t, cfg.Check(), ErrAsteriscNetworkAndL2Genesis) require.ErrorIs(t, cfg.Check(), ErrAsteriscNetworkAndL2Genesis)
}) })
t.Run(fmt.Sprintf("TestNetworkMustBeValid-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestNetworkMustBeValid-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType) cfg := validConfig(traceType)
cfg.AsteriscNetwork = "unknown" cfg.Asterisc.Network = "unknown"
require.ErrorIs(t, cfg.Check(), ErrAsteriscNetworkUnknown) require.ErrorIs(t, cfg.Check(), ErrAsteriscNetworkUnknown)
}) })
} }
...@@ -404,9 +404,9 @@ func TestRequireConfigForMultipleTraceTypesForCannonAndAsterisc(t *testing.T) { ...@@ -404,9 +404,9 @@ func TestRequireConfigForMultipleTraceTypesForCannonAndAsterisc(t *testing.T) {
require.NoError(t, cfg.Check()) require.NoError(t, cfg.Check())
// Require cannon specific args // Require cannon specific args
cfg.CannonBin = "" cfg.Cannon.VmBin = ""
require.ErrorIs(t, cfg.Check(), ErrMissingCannonBin) require.ErrorIs(t, cfg.Check(), ErrMissingCannonBin)
cfg.CannonBin = validCannonBin cfg.Cannon.VmBin = validCannonBin
// Require asterisc specific args // Require asterisc specific args
cfg.AsteriscAbsolutePreState = "" cfg.AsteriscAbsolutePreState = ""
...@@ -415,9 +415,9 @@ func TestRequireConfigForMultipleTraceTypesForCannonAndAsterisc(t *testing.T) { ...@@ -415,9 +415,9 @@ func TestRequireConfigForMultipleTraceTypesForCannonAndAsterisc(t *testing.T) {
cfg.AsteriscAbsolutePreState = validAsteriscAbsolutPreState cfg.AsteriscAbsolutePreState = validAsteriscAbsolutPreState
// Require cannon specific args // Require cannon specific args
cfg.AsteriscServer = "" cfg.Asterisc.Server = ""
require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscServer) require.ErrorIs(t, cfg.Check(), ErrMissingAsteriscServer)
cfg.AsteriscServer = validAsteriscOpProgramBin cfg.Asterisc.Server = validAsteriscOpProgramBin
// Check final config is valid // Check final config is valid
require.NoError(t, cfg.Check()) require.NoError(t, cfg.Check())
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"slices" "slices"
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-service/flags" "github.com/ethereum-optimism/optimism/op-service/flags"
"github.com/ethereum-optimism/superchain-registry/superchain" "github.com/ethereum-optimism/superchain-registry/superchain"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -496,39 +497,53 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro ...@@ -496,39 +497,53 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro
if ctx.IsSet(flags.NetworkFlagName) { if ctx.IsSet(flags.NetworkFlagName) {
asteriscNetwork = ctx.String(flags.NetworkFlagName) asteriscNetwork = ctx.String(flags.NetworkFlagName)
} }
l1EthRpc := ctx.String(L1EthRpcFlag.Name)
l1Beacon := ctx.String(L1BeaconFlag.Name)
return &config.Config{ return &config.Config{
// Required Flags // Required Flags
L1EthRpc: ctx.String(L1EthRpcFlag.Name), L1EthRpc: l1EthRpc,
L1Beacon: ctx.String(L1BeaconFlag.Name), L1Beacon: l1Beacon,
TraceTypes: traceTypes, TraceTypes: traceTypes,
GameFactoryAddress: gameFactoryAddress, GameFactoryAddress: gameFactoryAddress,
GameAllowlist: allowedGames, GameAllowlist: allowedGames,
GameWindow: ctx.Duration(GameWindowFlag.Name), GameWindow: ctx.Duration(GameWindowFlag.Name),
MaxConcurrency: maxConcurrency, MaxConcurrency: maxConcurrency,
L2Rpc: l2Rpc, L2Rpc: l2Rpc,
MaxPendingTx: ctx.Uint64(MaxPendingTransactionsFlag.Name), MaxPendingTx: ctx.Uint64(MaxPendingTransactionsFlag.Name),
PollInterval: ctx.Duration(HTTPPollInterval.Name), PollInterval: ctx.Duration(HTTPPollInterval.Name),
AdditionalBondClaimants: claimants, AdditionalBondClaimants: claimants,
RollupRpc: ctx.String(RollupRpcFlag.Name), RollupRpc: ctx.String(RollupRpcFlag.Name),
CannonNetwork: cannonNetwork, Cannon: vm.Config{
CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name), VmType: config.TraceTypeCannon.String(),
CannonL2GenesisPath: ctx.String(CannonL2GenesisFlag.Name), L1: l1EthRpc,
CannonBin: ctx.String(CannonBinFlag.Name), L1Beacon: l1Beacon,
CannonServer: ctx.String(CannonServerFlag.Name), L2: l2Rpc,
CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name), VmBin: ctx.String(CannonBinFlag.Name),
CannonAbsolutePreStateBaseURL: cannonPrestatesURL, Server: ctx.String(CannonServerFlag.Name),
Datadir: ctx.String(DatadirFlag.Name), Network: cannonNetwork,
CannonSnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), RollupConfigPath: ctx.String(CannonRollupConfigFlag.Name),
CannonInfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), L2GenesisPath: ctx.String(CannonL2GenesisFlag.Name),
AsteriscNetwork: asteriscNetwork, SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name),
AsteriscRollupConfigPath: ctx.String(AsteriscRollupConfigFlag.Name), InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name),
AsteriscL2GenesisPath: ctx.String(AsteriscL2GenesisFlag.Name), },
AsteriscBin: ctx.String(AsteriscBinFlag.Name), CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name),
AsteriscServer: ctx.String(AsteriscServerFlag.Name), CannonAbsolutePreStateBaseURL: cannonPrestatesURL,
Datadir: ctx.String(DatadirFlag.Name),
Asterisc: vm.Config{
VmType: config.TraceTypeAsterisc.String(),
L1: l1EthRpc,
L1Beacon: l1Beacon,
L2: l2Rpc,
VmBin: ctx.String(AsteriscBinFlag.Name),
Server: ctx.String(AsteriscServerFlag.Name),
Network: asteriscNetwork,
RollupConfigPath: ctx.String(AsteriscRollupConfigFlag.Name),
L2GenesisPath: ctx.String(AsteriscL2GenesisFlag.Name),
SnapshotFreq: ctx.Uint(AsteriscSnapshotFreqFlag.Name),
InfoFreq: ctx.Uint(AsteriscInfoFreqFlag.Name),
},
AsteriscAbsolutePreState: ctx.String(AsteriscPreStateFlag.Name), AsteriscAbsolutePreState: ctx.String(AsteriscPreStateFlag.Name),
AsteriscAbsolutePreStateBaseURL: asteriscPreStatesURL, AsteriscAbsolutePreStateBaseURL: asteriscPreStatesURL,
AsteriscSnapshotFreq: ctx.Uint(AsteriscSnapshotFreqFlag.Name),
AsteriscInfoFreq: ctx.Uint(AsteriscInfoFreqFlag.Name),
TxMgrConfig: txMgrConfig, TxMgrConfig: txMgrConfig,
MetricsConfig: metricsConfig, MetricsConfig: metricsConfig,
PprofConfig: pprofConfig, PprofConfig: pprofConfig,
......
...@@ -254,7 +254,7 @@ func registerAsterisc( ...@@ -254,7 +254,7 @@ func registerAsterisc(
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get asterisc prestate: %w", err) return nil, fmt.Errorf("failed to get asterisc prestate: %w", err)
} }
accessor, err := outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg, l2Client, prestateProvider, asteriscPrestate, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock) accessor, err := outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.Asterisc, l2Client, prestateProvider, asteriscPrestate, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -349,7 +349,7 @@ func registerCannon( ...@@ -349,7 +349,7 @@ func registerCannon(
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get cannon prestate: %w", err) return nil, fmt.Errorf("failed to get cannon prestate: %w", err)
} }
accessor, err := outputs.NewOutputCannonTraceAccessor(logger, m, cfg, l2Client, prestateProvider, cannonPrestate, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock) accessor, err := outputs.NewOutputCannonTraceAccessor(logger, m, cfg.Cannon, l2Client, prestateProvider, cannonPrestate, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
package asterisc
import (
"context"
"fmt"
"math"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum/go-ethereum/log"
)
type Executor struct {
logger log.Logger
metrics AsteriscMetricer
l1 string
l1Beacon string
l2 string
inputs utils.LocalGameInputs
asterisc string
server string
network string
rollupConfig string
l2Genesis string
absolutePreState string
snapshotFreq uint
infoFreq uint
selectSnapshot utils.SnapshotSelect
cmdExecutor utils.CmdExecutor
}
func NewExecutor(logger log.Logger, m AsteriscMetricer, cfg *config.Config, prestate string, inputs utils.LocalGameInputs) *Executor {
return &Executor{
logger: logger,
metrics: m,
l1: cfg.L1EthRpc,
l1Beacon: cfg.L1Beacon,
l2: cfg.L2Rpc,
inputs: inputs,
asterisc: cfg.AsteriscBin,
server: cfg.AsteriscServer,
network: cfg.AsteriscNetwork,
rollupConfig: cfg.AsteriscRollupConfigPath,
l2Genesis: cfg.AsteriscL2GenesisPath,
absolutePreState: prestate,
snapshotFreq: cfg.AsteriscSnapshotFreq,
infoFreq: cfg.AsteriscInfoFreq,
selectSnapshot: utils.FindStartingSnapshot,
cmdExecutor: utils.RunCmd,
}
}
// GenerateProof executes asterisc to generate a proof at the specified trace index.
// The proof is stored at the specified directory.
func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) error {
return e.generateProof(ctx, dir, i, i)
}
// generateProof executes asterisc from the specified starting trace index until the end trace index.
// The proof is stored at the specified directory.
func (e *Executor) generateProof(ctx context.Context, dir string, begin uint64, end uint64, extraAsteriscArgs ...string) error {
snapshotDir := filepath.Join(dir, utils.SnapsDir)
start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin)
if err != nil {
return fmt.Errorf("find starting snapshot: %w", err)
}
proofDir := filepath.Join(dir, proofsDir)
dataDir := utils.PreimageDir(dir)
lastGeneratedState := filepath.Join(dir, utils.FinalState)
args := []string{
"run",
"--input", start,
"--output", lastGeneratedState,
"--meta", "",
"--info-at", "%" + strconv.FormatUint(uint64(e.infoFreq), 10),
"--proof-at", "=" + strconv.FormatUint(end, 10),
"--proof-fmt", filepath.Join(proofDir, "%d.json.gz"),
"--snapshot-at", "%" + strconv.FormatUint(uint64(e.snapshotFreq), 10),
"--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz"),
}
if end < math.MaxUint64 {
args = append(args, "--stop-at", "="+strconv.FormatUint(end+1, 10))
}
args = append(args, extraAsteriscArgs...)
args = append(args,
"--",
e.server, "--server",
"--l1", e.l1,
"--l1.beacon", e.l1Beacon,
"--l2", e.l2,
"--datadir", dataDir,
"--l1.head", e.inputs.L1Head.Hex(),
"--l2.head", e.inputs.L2Head.Hex(),
"--l2.outputroot", e.inputs.L2OutputRoot.Hex(),
"--l2.claim", e.inputs.L2Claim.Hex(),
"--l2.blocknumber", e.inputs.L2BlockNumber.Text(10),
)
if e.network != "" {
args = append(args, "--network", e.network)
}
if e.rollupConfig != "" {
args = append(args, "--rollup.config", e.rollupConfig)
}
if e.l2Genesis != "" {
args = append(args, "--l2.genesis", e.l2Genesis)
}
if err := os.MkdirAll(snapshotDir, 0755); err != nil {
return fmt.Errorf("could not create snapshot directory %v: %w", snapshotDir, err)
}
if err := os.MkdirAll(dataDir, 0755); err != nil {
return fmt.Errorf("could not create preimage cache directory %v: %w", dataDir, err)
}
if err := os.MkdirAll(proofDir, 0755); err != nil {
return fmt.Errorf("could not create proofs directory %v: %w", proofDir, err)
}
e.logger.Info("Generating trace", "proof", end, "cmd", e.asterisc, "args", strings.Join(args, ", "))
execStart := time.Now()
err = e.cmdExecutor(ctx, e.logger.New("proof", end), e.asterisc, args...)
e.metrics.RecordAsteriscExecutionTime(time.Since(execStart).Seconds())
return err
}
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore" "github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
...@@ -19,15 +20,6 @@ import ( ...@@ -19,15 +20,6 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
const (
proofsDir = "proofs"
diskStateCache = "state.json.gz"
)
type AsteriscMetricer interface {
RecordAsteriscExecutionTime(t float64)
}
type AsteriscTraceProvider struct { type AsteriscTraceProvider struct {
logger log.Logger logger log.Logger
dir string dir string
...@@ -43,14 +35,14 @@ type AsteriscTraceProvider struct { ...@@ -43,14 +35,14 @@ type AsteriscTraceProvider struct {
lastStep uint64 lastStep uint64
} }
func NewTraceProvider(logger log.Logger, m AsteriscMetricer, cfg *config.Config, prestateProvider types.PrestateProvider, asteriscPrestate string, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *AsteriscTraceProvider { func NewTraceProvider(logger log.Logger, m vm.Metricer, cfg vm.Config, prestateProvider types.PrestateProvider, asteriscPrestate string, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *AsteriscTraceProvider {
return &AsteriscTraceProvider{ return &AsteriscTraceProvider{
logger: logger, logger: logger,
dir: dir, dir: dir,
prestate: asteriscPrestate, prestate: asteriscPrestate,
generator: NewExecutor(logger, m, cfg, asteriscPrestate, localInputs), generator: vm.NewExecutor(logger, m, cfg, asteriscPrestate, localInputs),
gameDepth: gameDepth, gameDepth: gameDepth,
preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(utils.PreimageDir(dir)).Get), preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get),
PrestateProvider: prestateProvider, PrestateProvider: prestateProvider,
} }
} }
...@@ -116,7 +108,7 @@ func (p *AsteriscTraceProvider) loadProof(ctx context.Context, i uint64) (*utils ...@@ -116,7 +108,7 @@ func (p *AsteriscTraceProvider) loadProof(ctx context.Context, i uint64) (*utils
if p.lastStep != 0 && i > p.lastStep { if p.lastStep != 0 && i > p.lastStep {
i = p.lastStep i = p.lastStep
} }
path := filepath.Join(p.dir, proofsDir, fmt.Sprintf("%d.json.gz", i)) path := filepath.Join(p.dir, utils.ProofsDir, fmt.Sprintf("%d.json.gz", i))
file, err := ioutil.OpenDecompressed(path) file, err := ioutil.OpenDecompressed(path)
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
if err := p.generator.GenerateProof(ctx, p.dir, i); err != nil { if err := p.generator.GenerateProof(ctx, p.dir, i); err != nil {
...@@ -167,7 +159,7 @@ func (p *AsteriscTraceProvider) loadProof(ctx context.Context, i uint64) (*utils ...@@ -167,7 +159,7 @@ func (p *AsteriscTraceProvider) loadProof(ctx context.Context, i uint64) (*utils
} }
func (c *AsteriscTraceProvider) finalState() (*VMState, error) { func (c *AsteriscTraceProvider) finalState() (*VMState, error) {
state, err := parseState(filepath.Join(c.dir, utils.FinalState)) state, err := parseState(filepath.Join(c.dir, vm.FinalState))
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot read final state: %w", err) return nil, fmt.Errorf("cannot read final state: %w", err)
} }
...@@ -180,21 +172,21 @@ type AsteriscTraceProviderForTest struct { ...@@ -180,21 +172,21 @@ type AsteriscTraceProviderForTest struct {
*AsteriscTraceProvider *AsteriscTraceProvider
} }
func NewTraceProviderForTest(logger log.Logger, m AsteriscMetricer, cfg *config.Config, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *AsteriscTraceProviderForTest { func NewTraceProviderForTest(logger log.Logger, m vm.Metricer, cfg *config.Config, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *AsteriscTraceProviderForTest {
p := &AsteriscTraceProvider{ p := &AsteriscTraceProvider{
logger: logger, logger: logger,
dir: dir, dir: dir,
prestate: cfg.AsteriscAbsolutePreState, prestate: cfg.AsteriscAbsolutePreState,
generator: NewExecutor(logger, m, cfg, cfg.AsteriscAbsolutePreState, localInputs), generator: vm.NewExecutor(logger, m, cfg.Asterisc, cfg.AsteriscAbsolutePreState, localInputs),
gameDepth: gameDepth, gameDepth: gameDepth,
preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(utils.PreimageDir(dir)).Get), preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get),
} }
return &AsteriscTraceProviderForTest{p} return &AsteriscTraceProviderForTest{p}
} }
func (p *AsteriscTraceProviderForTest) FindStep(ctx context.Context, start uint64, preimage utils.PreimageOpt) (uint64, error) { func (p *AsteriscTraceProviderForTest) FindStep(ctx context.Context, start uint64, preimage utils.PreimageOpt) (uint64, error) {
// Run asterisc to find the step that meets the preimage conditions // Run asterisc to find the step that meets the preimage conditions
if err := p.generator.(*Executor).generateProof(ctx, p.dir, start, math.MaxUint64, preimage()...); err != nil { if err := p.generator.(*vm.Executor).DoGenerateProof(ctx, p.dir, start, math.MaxUint64, preimage()...); err != nil {
return 0, fmt.Errorf("generate asterisc trace (until preimage read): %w", err) return 0, fmt.Errorf("generate asterisc trace (until preimage read): %w", err)
} }
// Load the step from the state asterisc finished with // Load the step from the state asterisc finished with
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
...@@ -205,12 +206,12 @@ func setupTestData(t *testing.T) (string, string) { ...@@ -205,12 +206,12 @@ func setupTestData(t *testing.T) (string, string) {
entries, err := testData.ReadDir(srcDir) entries, err := testData.ReadDir(srcDir)
require.NoError(t, err) require.NoError(t, err)
dataDir := t.TempDir() dataDir := t.TempDir()
require.NoError(t, os.Mkdir(filepath.Join(dataDir, proofsDir), 0o777)) require.NoError(t, os.Mkdir(filepath.Join(dataDir, utils.ProofsDir), 0o777))
for _, entry := range entries { for _, entry := range entries {
path := filepath.Join(srcDir, entry.Name()) path := filepath.Join(srcDir, entry.Name())
file, err := testData.ReadFile(path) file, err := testData.ReadFile(path)
require.NoErrorf(t, err, "reading %v", path) require.NoErrorf(t, err, "reading %v", path)
proofFile := filepath.Join(dataDir, proofsDir, entry.Name()+".gz") proofFile := filepath.Join(dataDir, utils.ProofsDir, entry.Name()+".gz")
err = ioutil.WriteCompressedBytes(proofFile, file, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644) err = ioutil.WriteCompressedBytes(proofFile, file, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644)
require.NoErrorf(t, err, "writing %v", path) require.NoErrorf(t, err, "writing %v", path)
} }
...@@ -241,7 +242,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64) ...@@ -241,7 +242,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64)
var err error var err error
if e.finalState != nil && e.finalState.Step <= i { if e.finalState != nil && e.finalState.Step <= i {
// Requesting a trace index past the end of the trace // Requesting a trace index past the end of the trace
proofFile = filepath.Join(dir, utils.FinalState) proofFile = filepath.Join(dir, vm.FinalState)
data, err = json.Marshal(e.finalState) data, err = json.Marshal(e.finalState)
if err != nil { if err != nil {
return err return err
...@@ -249,7 +250,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64) ...@@ -249,7 +250,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64)
return ioutil.WriteCompressedBytes(proofFile, data, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644) return ioutil.WriteCompressedBytes(proofFile, data, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644)
} }
if e.proof != nil { if e.proof != nil {
proofFile = filepath.Join(dir, proofsDir, fmt.Sprintf("%d.json.gz", i)) proofFile = filepath.Join(dir, utils.ProofsDir, fmt.Sprintf("%d.json.gz", i))
data, err = json.Marshal(e.proof) data, err = json.Marshal(e.proof)
if err != nil { if err != nil {
return err return err
......
package cannon
import (
"context"
"fmt"
"math"
"math/big"
"os"
"path/filepath"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
const execTestCannonPrestate = "/foo/pre.json"
func TestGenerateProof(t *testing.T) {
input := "starting.json"
tempDir := t.TempDir()
dir := filepath.Join(tempDir, "gameDir")
cfg := config.NewConfig(common.Address{0xbb}, "http://localhost:8888", "http://localhost:9000", "http://localhost:9096", "http://localhost:9095", tempDir, config.TraceTypeCannon)
cfg.L2Rpc = "http://localhost:9999"
prestate := "pre.json"
cfg.CannonBin = "./bin/cannon"
cfg.CannonServer = "./bin/op-program"
cfg.CannonSnapshotFreq = 500
cfg.CannonInfoFreq = 900
inputs := utils.LocalGameInputs{
L1Head: common.Hash{0x11},
L2Head: common.Hash{0x22},
L2OutputRoot: common.Hash{0x33},
L2Claim: common.Hash{0x44},
L2BlockNumber: big.NewInt(3333),
}
captureExec := func(t *testing.T, cfg config.Config, proofAt uint64) (string, string, map[string]string) {
m := &cannonDurationMetrics{}
executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, &cfg, prestate, inputs)
executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) {
return input, nil
}
var binary string
var subcommand string
args := make(map[string]string)
executor.cmdExecutor = func(ctx context.Context, l log.Logger, b string, a ...string) error {
binary = b
subcommand = a[0]
for i := 1; i < len(a); {
if a[i] == "--" {
// Skip over the divider between cannon and server program
i += 1
continue
}
args[a[i]] = a[i+1]
i += 2
}
return nil
}
err := executor.GenerateProof(context.Background(), dir, proofAt)
require.NoError(t, err)
require.Equal(t, 1, m.executionTimeRecordCount, "Should record cannon execution time")
return binary, subcommand, args
}
t.Run("Network", func(t *testing.T) {
cfg.CannonNetwork = "mainnet"
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = ""
binary, subcommand, args := captureExec(t, cfg, 150_000_000)
require.DirExists(t, filepath.Join(dir, utils.PreimagesDir))
require.DirExists(t, filepath.Join(dir, utils.ProofsDir))
require.DirExists(t, filepath.Join(dir, utils.SnapsDir))
require.Equal(t, cfg.CannonBin, binary)
require.Equal(t, "run", subcommand)
require.Equal(t, input, args["--input"])
require.Contains(t, args, "--meta")
require.Equal(t, "", args["--meta"])
require.Equal(t, filepath.Join(dir, utils.FinalState), args["--output"])
require.Equal(t, "=150000000", args["--proof-at"])
require.Equal(t, "=150000001", args["--stop-at"])
require.Equal(t, "%500", args["--snapshot-at"])
require.Equal(t, "%900", args["--info-at"])
// Slight quirk of how we pair off args
// The server binary winds up as the key and the first arg --server as the value which has no value
// Then everything else pairs off correctly again
require.Equal(t, "--server", args[cfg.CannonServer])
require.Equal(t, cfg.L1EthRpc, args["--l1"])
require.Equal(t, cfg.L1Beacon, args["--l1.beacon"])
require.Equal(t, cfg.L2Rpc, args["--l2"])
require.Equal(t, filepath.Join(dir, utils.PreimagesDir), args["--datadir"])
require.Equal(t, filepath.Join(dir, utils.ProofsDir, "%d.json.gz"), args["--proof-fmt"])
require.Equal(t, filepath.Join(dir, utils.SnapsDir, "%d.json.gz"), args["--snapshot-fmt"])
require.Equal(t, cfg.CannonNetwork, args["--network"])
require.NotContains(t, args, "--rollup.config")
require.NotContains(t, args, "--l2.genesis")
// Local game inputs
require.Equal(t, inputs.L1Head.Hex(), args["--l1.head"])
require.Equal(t, inputs.L2Head.Hex(), args["--l2.head"])
require.Equal(t, inputs.L2OutputRoot.Hex(), args["--l2.outputroot"])
require.Equal(t, inputs.L2Claim.Hex(), args["--l2.claim"])
require.Equal(t, "3333", args["--l2.blocknumber"])
})
t.Run("RollupAndGenesis", func(t *testing.T) {
cfg.CannonNetwork = ""
cfg.CannonRollupConfigPath = "rollup.json"
cfg.CannonL2GenesisPath = "genesis.json"
_, _, args := captureExec(t, cfg, 150_000_000)
require.NotContains(t, args, "--network")
require.Equal(t, cfg.CannonRollupConfigPath, args["--rollup.config"])
require.Equal(t, cfg.CannonL2GenesisPath, args["--l2.genesis"])
})
t.Run("NoStopAtWhenProofIsMaxUInt", func(t *testing.T) {
cfg.CannonNetwork = "mainnet"
cfg.CannonRollupConfigPath = "rollup.json"
cfg.CannonL2GenesisPath = "genesis.json"
_, _, args := captureExec(t, cfg, math.MaxUint64)
// stop-at would need to be one more than the proof step which would overflow back to 0
// so expect that it will be omitted. We'll ultimately want cannon to execute until the program exits.
require.NotContains(t, args, "--stop-at")
})
}
func TestRunCmdLogsOutput(t *testing.T) {
bin := "/bin/echo"
if _, err := os.Stat(bin); err != nil {
t.Skip(bin, " not available", err)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
logger, logs := testlog.CaptureLogger(t, log.LevelInfo)
err := utils.RunCmd(ctx, logger, bin, "Hello World")
require.NoError(t, err)
levelFilter := testlog.NewLevelFilter(log.LevelInfo)
msgFilter := testlog.NewMessageFilter("Hello World")
require.NotNil(t, logs.FindLog(levelFilter, msgFilter))
}
func TestFindStartingSnapshot(t *testing.T) {
logger := testlog.Logger(t, log.LevelInfo)
withSnapshots := func(t *testing.T, files ...string) string {
dir := t.TempDir()
for _, file := range files {
require.NoError(t, os.WriteFile(fmt.Sprintf("%v/%v", dir, file), nil, 0o644))
}
return dir
}
t.Run("UsePrestateWhenSnapshotsDirDoesNotExist", func(t *testing.T) {
dir := t.TempDir()
snapshot, err := utils.FindStartingSnapshot(logger, filepath.Join(dir, "doesNotExist"), execTestCannonPrestate, 1200)
require.NoError(t, err)
require.Equal(t, execTestCannonPrestate, snapshot)
})
t.Run("UsePrestateWhenSnapshotsDirEmpty", func(t *testing.T) {
dir := withSnapshots(t)
snapshot, err := utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 1200)
require.NoError(t, err)
require.Equal(t, execTestCannonPrestate, snapshot)
})
t.Run("UsePrestateWhenNoSnapshotBeforeTraceIndex", func(t *testing.T) {
dir := withSnapshots(t, "100.json", "200.json")
snapshot, err := utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 99)
require.NoError(t, err)
require.Equal(t, execTestCannonPrestate, snapshot)
snapshot, err = utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 100)
require.NoError(t, err)
require.Equal(t, execTestCannonPrestate, snapshot)
})
t.Run("UseClosestAvailableSnapshot", func(t *testing.T) {
dir := withSnapshots(t, "100.json.gz", "123.json.gz", "250.json.gz")
snapshot, err := utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 101)
require.NoError(t, err)
require.Equal(t, filepath.Join(dir, "100.json.gz"), snapshot)
snapshot, err = utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 123)
require.NoError(t, err)
require.Equal(t, filepath.Join(dir, "100.json.gz"), snapshot)
snapshot, err = utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 124)
require.NoError(t, err)
require.Equal(t, filepath.Join(dir, "123.json.gz"), snapshot)
snapshot, err = utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 256)
require.NoError(t, err)
require.Equal(t, filepath.Join(dir, "250.json.gz"), snapshot)
})
t.Run("IgnoreDirectories", func(t *testing.T) {
dir := withSnapshots(t, "100.json.gz")
require.NoError(t, os.Mkdir(filepath.Join(dir, "120.json.gz"), 0o777))
snapshot, err := utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 150)
require.NoError(t, err)
require.Equal(t, filepath.Join(dir, "100.json.gz"), snapshot)
})
t.Run("IgnoreUnexpectedFiles", func(t *testing.T) {
dir := withSnapshots(t, ".file", "100.json.gz", "foo", "bar.json.gz")
snapshot, err := utils.FindStartingSnapshot(logger, dir, execTestCannonPrestate, 150)
require.NoError(t, err)
require.Equal(t, filepath.Join(dir, "100.json.gz"), snapshot)
})
}
type cannonDurationMetrics struct {
metrics.NoopMetricsImpl
executionTimeRecordCount int
}
func (c *cannonDurationMetrics) RecordCannonExecutionTime(_ float64) {
c.executionTimeRecordCount++
}
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore" "github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
...@@ -22,10 +23,6 @@ import ( ...@@ -22,10 +23,6 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
) )
type CannonMetricer interface {
RecordCannonExecutionTime(t float64)
}
type CannonTraceProvider struct { type CannonTraceProvider struct {
logger log.Logger logger log.Logger
dir string dir string
...@@ -41,14 +38,14 @@ type CannonTraceProvider struct { ...@@ -41,14 +38,14 @@ type CannonTraceProvider struct {
lastStep uint64 lastStep uint64
} }
func NewTraceProvider(logger log.Logger, m CannonMetricer, cfg *config.Config, prestateProvider types.PrestateProvider, prestate string, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProvider { func NewTraceProvider(logger log.Logger, m vm.Metricer, cfg vm.Config, prestateProvider types.PrestateProvider, prestate string, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProvider {
return &CannonTraceProvider{ return &CannonTraceProvider{
logger: logger, logger: logger,
dir: dir, dir: dir,
prestate: prestate, prestate: prestate,
generator: NewExecutor(logger, m, cfg, prestate, localInputs), generator: vm.NewExecutor(logger, m, cfg, prestate, localInputs),
gameDepth: gameDepth, gameDepth: gameDepth,
preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(utils.PreimageDir(dir)).Get), preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get),
PrestateProvider: prestateProvider, PrestateProvider: prestateProvider,
} }
} }
...@@ -170,7 +167,7 @@ func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*utils.P ...@@ -170,7 +167,7 @@ func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*utils.P
} }
func (c *CannonTraceProvider) finalState() (*mipsevm.State, error) { func (c *CannonTraceProvider) finalState() (*mipsevm.State, error) {
state, err := parseState(filepath.Join(c.dir, utils.FinalState)) state, err := parseState(filepath.Join(c.dir, vm.FinalState))
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot read final state: %w", err) return nil, fmt.Errorf("cannot read final state: %w", err)
} }
...@@ -183,21 +180,21 @@ type CannonTraceProviderForTest struct { ...@@ -183,21 +180,21 @@ type CannonTraceProviderForTest struct {
*CannonTraceProvider *CannonTraceProvider
} }
func NewTraceProviderForTest(logger log.Logger, m CannonMetricer, cfg *config.Config, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProviderForTest { func NewTraceProviderForTest(logger log.Logger, m vm.Metricer, cfg *config.Config, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProviderForTest {
p := &CannonTraceProvider{ p := &CannonTraceProvider{
logger: logger, logger: logger,
dir: dir, dir: dir,
prestate: cfg.CannonAbsolutePreState, prestate: cfg.CannonAbsolutePreState,
generator: NewExecutor(logger, m, cfg, cfg.CannonAbsolutePreState, localInputs), generator: vm.NewExecutor(logger, m, cfg.Cannon, cfg.CannonAbsolutePreState, localInputs),
gameDepth: gameDepth, gameDepth: gameDepth,
preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(utils.PreimageDir(dir)).Get), preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get),
} }
return &CannonTraceProviderForTest{p} return &CannonTraceProviderForTest{p}
} }
func (p *CannonTraceProviderForTest) FindStep(ctx context.Context, start uint64, preimage utils.PreimageOpt) (uint64, error) { func (p *CannonTraceProviderForTest) FindStep(ctx context.Context, start uint64, preimage utils.PreimageOpt) (uint64, error) {
// Run cannon to find the step that meets the preimage conditions // Run cannon to find the step that meets the preimage conditions
if err := p.generator.(*Executor).generateProof(ctx, p.dir, start, math.MaxUint64, preimage()...); err != nil { if err := p.generator.(*vm.Executor).DoGenerateProof(ctx, p.dir, start, math.MaxUint64, preimage()...); err != nil {
return 0, fmt.Errorf("generate cannon trace (until preimage read): %w", err) return 0, fmt.Errorf("generate cannon trace (until preimage read): %w", err)
} }
// Load the step from the state cannon finished with // Load the step from the state cannon finished with
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
...@@ -257,7 +258,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64) ...@@ -257,7 +258,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64)
var err error var err error
if e.finalState != nil && e.finalState.Step <= i { if e.finalState != nil && e.finalState.Step <= i {
// Requesting a trace index past the end of the trace // Requesting a trace index past the end of the trace
proofFile = filepath.Join(dir, utils.FinalState) proofFile = filepath.Join(dir, vm.FinalState)
data, err = json.Marshal(e.finalState) data, err = json.Marshal(e.finalState)
if err != nil { if err != nil {
return err return err
......
...@@ -5,12 +5,12 @@ import ( ...@@ -5,12 +5,12 @@ import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/asterisc" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/asterisc"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
...@@ -21,7 +21,7 @@ import ( ...@@ -21,7 +21,7 @@ import (
func NewOutputAsteriscTraceAccessor( func NewOutputAsteriscTraceAccessor(
logger log.Logger, logger log.Logger,
m metrics.Metricer, m metrics.Metricer,
cfg *config.Config, cfg vm.Config,
l2Client utils.L2HeaderSource, l2Client utils.L2HeaderSource,
prestateProvider types.PrestateProvider, prestateProvider types.PrestateProvider,
asteriscPrestate string, asteriscPrestate string,
......
...@@ -5,12 +5,12 @@ import ( ...@@ -5,12 +5,12 @@ import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
...@@ -21,7 +21,7 @@ import ( ...@@ -21,7 +21,7 @@ import (
func NewOutputCannonTraceAccessor( func NewOutputCannonTraceAccessor(
logger log.Logger, logger log.Logger,
m metrics.Metricer, m metrics.Metricer,
cfg *config.Config, cfg vm.Config,
l2Client utils.L2HeaderSource, l2Client utils.L2HeaderSource,
prestateProvider types.PrestateProvider, prestateProvider types.PrestateProvider,
cannonPrestate string, cannonPrestate string,
......
package cannon package vm
import ( import (
"context" "context"
...@@ -10,89 +10,88 @@ import ( ...@@ -10,89 +10,88 @@ import (
"strings" "strings"
"time" "time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
type Metricer interface {
RecordVmExecutionTime(vmType string, t time.Duration)
}
type Config struct {
VmType string
L1 string
L1Beacon string
L2 string
VmBin string // Path to the vm executable to run when generating trace data
Server string // Path to the executable that provides the pre-image oracle server
Network string
RollupConfigPath string
L2GenesisPath string
SnapshotFreq uint // Frequency of snapshots to create when executing (in VM instructions)
InfoFreq uint // Frequency of progress log messages (in VM instructions)
}
type Executor struct { type Executor struct {
cfg Config
logger log.Logger logger log.Logger
metrics CannonMetricer metrics Metricer
l1 string
l1Beacon string
l2 string
inputs utils.LocalGameInputs
cannon string
server string
network string
rollupConfig string
l2Genesis string
absolutePreState string absolutePreState string
snapshotFreq uint inputs utils.LocalGameInputs
infoFreq uint selectSnapshot SnapshotSelect
selectSnapshot utils.SnapshotSelect cmdExecutor CmdExecutor
cmdExecutor utils.CmdExecutor
} }
func NewExecutor(logger log.Logger, m CannonMetricer, cfg *config.Config, prestate string, inputs utils.LocalGameInputs) *Executor { func NewExecutor(logger log.Logger, m Metricer, cfg Config, prestate string, inputs utils.LocalGameInputs) *Executor {
return &Executor{ return &Executor{
cfg: cfg,
logger: logger, logger: logger,
metrics: m, metrics: m,
l1: cfg.L1EthRpc,
l1Beacon: cfg.L1Beacon,
l2: cfg.L2Rpc,
inputs: inputs, inputs: inputs,
cannon: cfg.CannonBin,
server: cfg.CannonServer,
network: cfg.CannonNetwork,
rollupConfig: cfg.CannonRollupConfigPath,
l2Genesis: cfg.CannonL2GenesisPath,
absolutePreState: prestate, absolutePreState: prestate,
snapshotFreq: cfg.CannonSnapshotFreq, selectSnapshot: FindStartingSnapshot,
infoFreq: cfg.CannonInfoFreq, cmdExecutor: RunCmd,
selectSnapshot: utils.FindStartingSnapshot,
cmdExecutor: utils.RunCmd,
} }
} }
// GenerateProof executes cannon to generate a proof at the specified trace index. // GenerateProof executes vm to generate a proof at the specified trace index.
// The proof is stored at the specified directory. // The proof is stored at the specified directory.
func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) error { func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) error {
return e.generateProof(ctx, dir, i, i) return e.DoGenerateProof(ctx, dir, i, i)
} }
// generateProof executes cannon from the specified starting trace index until the end trace index. // DoGenerateProof executes vm from the specified starting trace index until the end trace index.
// The proof is stored at the specified directory. // The proof is stored at the specified directory.
func (e *Executor) generateProof(ctx context.Context, dir string, begin uint64, end uint64, extraCannonArgs ...string) error { func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64, end uint64, extraVmArgs ...string) error {
snapshotDir := filepath.Join(dir, utils.SnapsDir) snapshotDir := filepath.Join(dir, SnapsDir)
start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin) start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin)
if err != nil { if err != nil {
return fmt.Errorf("find starting snapshot: %w", err) return fmt.Errorf("find starting snapshot: %w", err)
} }
proofDir := filepath.Join(dir, utils.ProofsDir) proofDir := filepath.Join(dir, utils.ProofsDir)
dataDir := utils.PreimageDir(dir) dataDir := PreimageDir(dir)
lastGeneratedState := filepath.Join(dir, utils.FinalState) lastGeneratedState := filepath.Join(dir, FinalState)
args := []string{ args := []string{
"run", "run",
"--input", start, "--input", start,
"--output", lastGeneratedState, "--output", lastGeneratedState,
"--meta", "", "--meta", "",
"--info-at", "%" + strconv.FormatUint(uint64(e.infoFreq), 10), "--info-at", "%" + strconv.FormatUint(uint64(e.cfg.InfoFreq), 10),
"--proof-at", "=" + strconv.FormatUint(end, 10), "--proof-at", "=" + strconv.FormatUint(end, 10),
"--proof-fmt", filepath.Join(proofDir, "%d.json.gz"), "--proof-fmt", filepath.Join(proofDir, "%d.json.gz"),
"--snapshot-at", "%" + strconv.FormatUint(uint64(e.snapshotFreq), 10), "--snapshot-at", "%" + strconv.FormatUint(uint64(e.cfg.SnapshotFreq), 10),
"--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz"), "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz"),
} }
if end < math.MaxUint64 { if end < math.MaxUint64 {
args = append(args, "--stop-at", "="+strconv.FormatUint(end+1, 10)) args = append(args, "--stop-at", "="+strconv.FormatUint(end+1, 10))
} }
args = append(args, extraCannonArgs...) args = append(args, extraVmArgs...)
args = append(args, args = append(args,
"--", "--",
e.server, "--server", e.cfg.Server, "--server",
"--l1", e.l1, "--l1", e.cfg.L1,
"--l1.beacon", e.l1Beacon, "--l1.beacon", e.cfg.L1Beacon,
"--l2", e.l2, "--l2", e.cfg.L2,
"--datadir", dataDir, "--datadir", dataDir,
"--l1.head", e.inputs.L1Head.Hex(), "--l1.head", e.inputs.L1Head.Hex(),
"--l2.head", e.inputs.L2Head.Hex(), "--l2.head", e.inputs.L2Head.Hex(),
...@@ -100,14 +99,14 @@ func (e *Executor) generateProof(ctx context.Context, dir string, begin uint64, ...@@ -100,14 +99,14 @@ func (e *Executor) generateProof(ctx context.Context, dir string, begin uint64,
"--l2.claim", e.inputs.L2Claim.Hex(), "--l2.claim", e.inputs.L2Claim.Hex(),
"--l2.blocknumber", e.inputs.L2BlockNumber.Text(10), "--l2.blocknumber", e.inputs.L2BlockNumber.Text(10),
) )
if e.network != "" { if e.cfg.Network != "" {
args = append(args, "--network", e.network) args = append(args, "--network", e.cfg.Network)
} }
if e.rollupConfig != "" { if e.cfg.RollupConfigPath != "" {
args = append(args, "--rollup.config", e.rollupConfig) args = append(args, "--rollup.config", e.cfg.RollupConfigPath)
} }
if e.l2Genesis != "" { if e.cfg.L2GenesisPath != "" {
args = append(args, "--l2.genesis", e.l2Genesis) args = append(args, "--l2.genesis", e.cfg.L2GenesisPath)
} }
if err := os.MkdirAll(snapshotDir, 0755); err != nil { if err := os.MkdirAll(snapshotDir, 0755); err != nil {
...@@ -119,9 +118,9 @@ func (e *Executor) generateProof(ctx context.Context, dir string, begin uint64, ...@@ -119,9 +118,9 @@ func (e *Executor) generateProof(ctx context.Context, dir string, begin uint64,
if err := os.MkdirAll(proofDir, 0755); err != nil { if err := os.MkdirAll(proofDir, 0755); err != nil {
return fmt.Errorf("could not create proofs directory %v: %w", proofDir, err) return fmt.Errorf("could not create proofs directory %v: %w", proofDir, err)
} }
e.logger.Info("Generating trace", "proof", end, "cmd", e.cannon, "args", strings.Join(args, ", ")) e.logger.Info("Generating trace", "proof", end, "cmd", e.cfg.VmBin, "args", strings.Join(args, ", "))
execStart := time.Now() execStart := time.Now()
err = e.cmdExecutor(ctx, e.logger.New("proof", end), e.cannon, args...) err = e.cmdExecutor(ctx, e.logger.New("proof", end), e.cfg.VmBin, args...)
e.metrics.RecordCannonExecutionTime(time.Since(execStart).Seconds()) e.metrics.RecordVmExecutionTime(e.cfg.VmType, time.Since(execStart))
return err return err
} }
package asterisc package vm
import ( import (
"context" "context"
...@@ -6,8 +6,8 @@ import ( ...@@ -6,8 +6,8 @@ import (
"math/big" "math/big"
"path/filepath" "path/filepath"
"testing" "testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
...@@ -20,13 +20,18 @@ func TestGenerateProof(t *testing.T) { ...@@ -20,13 +20,18 @@ func TestGenerateProof(t *testing.T) {
input := "starting.json" input := "starting.json"
tempDir := t.TempDir() tempDir := t.TempDir()
dir := filepath.Join(tempDir, "gameDir") dir := filepath.Join(tempDir, "gameDir")
cfg := config.NewConfig(common.Address{0xbb}, "http://localhost:8888", "http://localhost:9000", "http://localhost:9096", "http://localhost:9095", tempDir, config.TraceTypeAsterisc) cfg := Config{
cfg.L2Rpc = "http://localhost:9999" VmType: "test",
L1: "http://localhost:8888",
L1Beacon: "http://localhost:9000",
L2: "http://localhost:9999",
VmBin: "./bin/testvm",
Server: "./bin/testserver",
Network: "op-test",
SnapshotFreq: 500,
InfoFreq: 900,
}
prestate := "pre.json" prestate := "pre.json"
cfg.AsteriscBin = "./bin/asterisc"
cfg.AsteriscServer = "./bin/op-program"
cfg.AsteriscSnapshotFreq = 500
cfg.AsteriscInfoFreq = 900
inputs := utils.LocalGameInputs{ inputs := utils.LocalGameInputs{
L1Head: common.Hash{0x11}, L1Head: common.Hash{0x11},
...@@ -35,9 +40,9 @@ func TestGenerateProof(t *testing.T) { ...@@ -35,9 +40,9 @@ func TestGenerateProof(t *testing.T) {
L2Claim: common.Hash{0x44}, L2Claim: common.Hash{0x44},
L2BlockNumber: big.NewInt(3333), L2BlockNumber: big.NewInt(3333),
} }
captureExec := func(t *testing.T, cfg config.Config, proofAt uint64) (string, string, map[string]string) { captureExec := func(t *testing.T, cfg Config, proofAt uint64) (string, string, map[string]string) {
m := &asteriscDurationMetrics{} m := &stubVmMetrics{}
executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, &cfg, prestate, inputs) executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, cfg, prestate, inputs)
executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) { executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) {
return input, nil return input, nil
} }
...@@ -49,7 +54,7 @@ func TestGenerateProof(t *testing.T) { ...@@ -49,7 +54,7 @@ func TestGenerateProof(t *testing.T) {
subcommand = a[0] subcommand = a[0]
for i := 1; i < len(a); { for i := 1; i < len(a); {
if a[i] == "--" { if a[i] == "--" {
// Skip over the divider between asterisc and server program // Skip over the divider between vm and server program
i += 1 i += 1
continue continue
} }
...@@ -60,24 +65,24 @@ func TestGenerateProof(t *testing.T) { ...@@ -60,24 +65,24 @@ func TestGenerateProof(t *testing.T) {
} }
err := executor.GenerateProof(context.Background(), dir, proofAt) err := executor.GenerateProof(context.Background(), dir, proofAt)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, m.executionTimeRecordCount, "Should record asterisc execution time") require.Equal(t, 1, m.executionTimeRecordCount, "Should record vm execution time")
return binary, subcommand, args return binary, subcommand, args
} }
t.Run("Network", func(t *testing.T) { t.Run("Network", func(t *testing.T) {
cfg.AsteriscNetwork = "mainnet" cfg.Network = "mainnet"
cfg.AsteriscRollupConfigPath = "" cfg.RollupConfigPath = ""
cfg.AsteriscL2GenesisPath = "" cfg.L2GenesisPath = ""
binary, subcommand, args := captureExec(t, cfg, 150_000_000) binary, subcommand, args := captureExec(t, cfg, 150_000_000)
require.DirExists(t, filepath.Join(dir, utils.PreimagesDir)) require.DirExists(t, filepath.Join(dir, PreimagesDir))
require.DirExists(t, filepath.Join(dir, proofsDir)) require.DirExists(t, filepath.Join(dir, utils.ProofsDir))
require.DirExists(t, filepath.Join(dir, utils.SnapsDir)) require.DirExists(t, filepath.Join(dir, SnapsDir))
require.Equal(t, cfg.AsteriscBin, binary) require.Equal(t, cfg.VmBin, binary)
require.Equal(t, "run", subcommand) require.Equal(t, "run", subcommand)
require.Equal(t, input, args["--input"]) require.Equal(t, input, args["--input"])
require.Contains(t, args, "--meta") require.Contains(t, args, "--meta")
require.Equal(t, "", args["--meta"]) require.Equal(t, "", args["--meta"])
require.Equal(t, filepath.Join(dir, utils.FinalState), args["--output"]) require.Equal(t, filepath.Join(dir, FinalState), args["--output"])
require.Equal(t, "=150000000", args["--proof-at"]) require.Equal(t, "=150000000", args["--proof-at"])
require.Equal(t, "=150000001", args["--stop-at"]) require.Equal(t, "=150000001", args["--stop-at"])
require.Equal(t, "%500", args["--snapshot-at"]) require.Equal(t, "%500", args["--snapshot-at"])
...@@ -85,14 +90,14 @@ func TestGenerateProof(t *testing.T) { ...@@ -85,14 +90,14 @@ func TestGenerateProof(t *testing.T) {
// Slight quirk of how we pair off args // Slight quirk of how we pair off args
// The server binary winds up as the key and the first arg --server as the value which has no value // The server binary winds up as the key and the first arg --server as the value which has no value
// Then everything else pairs off correctly again // Then everything else pairs off correctly again
require.Equal(t, "--server", args[cfg.AsteriscServer]) require.Equal(t, "--server", args[cfg.Server])
require.Equal(t, cfg.L1EthRpc, args["--l1"]) require.Equal(t, cfg.L1, args["--l1"])
require.Equal(t, cfg.L1Beacon, args["--l1.beacon"]) require.Equal(t, cfg.L1Beacon, args["--l1.beacon"])
require.Equal(t, cfg.L2Rpc, args["--l2"]) require.Equal(t, cfg.L2, args["--l2"])
require.Equal(t, filepath.Join(dir, utils.PreimagesDir), args["--datadir"]) require.Equal(t, filepath.Join(dir, PreimagesDir), args["--datadir"])
require.Equal(t, filepath.Join(dir, proofsDir, "%d.json.gz"), args["--proof-fmt"]) require.Equal(t, filepath.Join(dir, utils.ProofsDir, "%d.json.gz"), args["--proof-fmt"])
require.Equal(t, filepath.Join(dir, utils.SnapsDir, "%d.json.gz"), args["--snapshot-fmt"]) require.Equal(t, filepath.Join(dir, SnapsDir, "%d.json.gz"), args["--snapshot-fmt"])
require.Equal(t, cfg.AsteriscNetwork, args["--network"]) require.Equal(t, cfg.Network, args["--network"])
require.NotContains(t, args, "--rollup.config") require.NotContains(t, args, "--rollup.config")
require.NotContains(t, args, "--l2.genesis") require.NotContains(t, args, "--l2.genesis")
...@@ -105,19 +110,19 @@ func TestGenerateProof(t *testing.T) { ...@@ -105,19 +110,19 @@ func TestGenerateProof(t *testing.T) {
}) })
t.Run("RollupAndGenesis", func(t *testing.T) { t.Run("RollupAndGenesis", func(t *testing.T) {
cfg.AsteriscNetwork = "" cfg.Network = ""
cfg.AsteriscRollupConfigPath = "rollup.json" cfg.RollupConfigPath = "rollup.json"
cfg.AsteriscL2GenesisPath = "genesis.json" cfg.L2GenesisPath = "genesis.json"
_, _, args := captureExec(t, cfg, 150_000_000) _, _, args := captureExec(t, cfg, 150_000_000)
require.NotContains(t, args, "--network") require.NotContains(t, args, "--network")
require.Equal(t, cfg.AsteriscRollupConfigPath, args["--rollup.config"]) require.Equal(t, cfg.RollupConfigPath, args["--rollup.config"])
require.Equal(t, cfg.AsteriscL2GenesisPath, args["--l2.genesis"]) require.Equal(t, cfg.L2GenesisPath, args["--l2.genesis"])
}) })
t.Run("NoStopAtWhenProofIsMaxUInt", func(t *testing.T) { t.Run("NoStopAtWhenProofIsMaxUInt", func(t *testing.T) {
cfg.AsteriscNetwork = "mainnet" cfg.Network = "mainnet"
cfg.AsteriscRollupConfigPath = "rollup.json" cfg.RollupConfigPath = "rollup.json"
cfg.AsteriscL2GenesisPath = "genesis.json" cfg.L2GenesisPath = "genesis.json"
_, _, args := captureExec(t, cfg, math.MaxUint64) _, _, args := captureExec(t, cfg, math.MaxUint64)
// stop-at would need to be one more than the proof step which would overflow back to 0 // stop-at would need to be one more than the proof step which would overflow back to 0
// so expect that it will be omitted. We'll ultimately want asterisc to execute until the program exits. // so expect that it will be omitted. We'll ultimately want asterisc to execute until the program exits.
...@@ -125,11 +130,11 @@ func TestGenerateProof(t *testing.T) { ...@@ -125,11 +130,11 @@ func TestGenerateProof(t *testing.T) {
}) })
} }
type asteriscDurationMetrics struct { type stubVmMetrics struct {
metrics.NoopMetricsImpl metrics.NoopMetricsImpl
executionTimeRecordCount int executionTimeRecordCount int
} }
func (c *asteriscDurationMetrics) RecordAsteriscExecutionTime(_ float64) { func (c *stubVmMetrics) RecordVmExecutionTime(_ string, _ time.Duration) {
c.executionTimeRecordCount++ c.executionTimeRecordCount++
} }
package utils package vm
import ( import (
"context" "context"
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
"regexp" "regexp"
"strconv" "strconv"
oplog "github.com/ethereum-optimism/optimism/op-service/log" log2 "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
...@@ -31,10 +31,10 @@ func PreimageDir(dir string) string { ...@@ -31,10 +31,10 @@ func PreimageDir(dir string) string {
func RunCmd(ctx context.Context, l log.Logger, binary string, args ...string) error { func RunCmd(ctx context.Context, l log.Logger, binary string, args ...string) error {
cmd := exec.CommandContext(ctx, binary, args...) cmd := exec.CommandContext(ctx, binary, args...)
stdOut := oplog.NewWriter(l, log.LevelInfo) stdOut := log2.NewWriter(l, log.LevelInfo)
defer stdOut.Close() defer stdOut.Close()
// Keep stdErr at info level because FPVM uses stderr for progress messages // Keep stdErr at info level because FPVM uses stderr for progress messages
stdErr := oplog.NewWriter(l, log.LevelInfo) stdErr := log2.NewWriter(l, log.LevelInfo)
defer stdErr.Close() defer stdErr.Close()
cmd.Stdout = stdOut cmd.Stdout = stdOut
cmd.Stderr = stdErr cmd.Stderr = stdErr
......
...@@ -2,6 +2,7 @@ package metrics ...@@ -2,6 +2,7 @@ package metrics
import ( import (
"io" "io"
"time"
"github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-service/httputil"
"github.com/ethereum-optimism/optimism/op-service/sources/caching" "github.com/ethereum-optimism/optimism/op-service/sources/caching"
...@@ -37,8 +38,7 @@ type Metricer interface { ...@@ -37,8 +38,7 @@ type Metricer interface {
RecordGameStep() RecordGameStep()
RecordGameMove() RecordGameMove()
RecordGameL2Challenge() RecordGameL2Challenge()
RecordCannonExecutionTime(t float64) RecordVmExecutionTime(vmType string, t time.Duration)
RecordAsteriscExecutionTime(t float64)
RecordClaimResolutionTime(t float64) RecordClaimResolutionTime(t float64)
RecordGameActTime(t float64) RecordGameActTime(t float64)
...@@ -88,10 +88,9 @@ type Metrics struct { ...@@ -88,10 +88,9 @@ type Metrics struct {
steps prometheus.Counter steps prometheus.Counter
l2Challenges prometheus.Counter l2Challenges prometheus.Counter
claimResolutionTime prometheus.Histogram claimResolutionTime prometheus.Histogram
gameActTime prometheus.Histogram gameActTime prometheus.Histogram
cannonExecutionTime prometheus.Histogram vmExecutionTime *prometheus.HistogramVec
asteriscExecutionTime prometheus.Histogram
trackedGames prometheus.GaugeVec trackedGames prometheus.GaugeVec
inflightGames prometheus.Gauge inflightGames prometheus.Gauge
...@@ -152,14 +151,6 @@ func NewMetrics() *Metrics { ...@@ -152,14 +151,6 @@ func NewMetrics() *Metrics {
Name: "l2_challenges", Name: "l2_challenges",
Help: "Number of L2 challenges made by the challenge agent", Help: "Number of L2 challenges made by the challenge agent",
}), }),
cannonExecutionTime: factory.NewHistogram(prometheus.HistogramOpts{
Namespace: Namespace,
Name: "cannon_execution_time",
Help: "Time (in seconds) to execute cannon",
Buckets: append(
[]float64{1.0, 10.0},
prometheus.ExponentialBuckets(30.0, 2.0, 14)...),
}),
claimResolutionTime: factory.NewHistogram(prometheus.HistogramOpts{ claimResolutionTime: factory.NewHistogram(prometheus.HistogramOpts{
Namespace: Namespace, Namespace: Namespace,
Name: "claim_resolution_time", Name: "claim_resolution_time",
...@@ -174,14 +165,14 @@ func NewMetrics() *Metrics { ...@@ -174,14 +165,14 @@ func NewMetrics() *Metrics {
[]float64{1.0, 2.0, 5.0, 10.0}, []float64{1.0, 2.0, 5.0, 10.0},
prometheus.ExponentialBuckets(30.0, 2.0, 14)...), prometheus.ExponentialBuckets(30.0, 2.0, 14)...),
}), }),
asteriscExecutionTime: factory.NewHistogram(prometheus.HistogramOpts{ vmExecutionTime: factory.NewHistogramVec(prometheus.HistogramOpts{
Namespace: Namespace, Namespace: Namespace,
Name: "asterisc_execution_time", Name: "asterisc_execution_time",
Help: "Time (in seconds) to execute asterisc", Help: "Time (in seconds) to execute asterisc",
Buckets: append( Buckets: append(
[]float64{1.0, 10.0}, []float64{1.0, 10.0},
prometheus.ExponentialBuckets(30.0, 2.0, 14)...), prometheus.ExponentialBuckets(30.0, 2.0, 14)...),
}), }, []string{"vm"}),
bondClaimFailures: factory.NewCounter(prometheus.CounterOpts{ bondClaimFailures: factory.NewCounter(prometheus.CounterOpts{
Namespace: Namespace, Namespace: Namespace,
Name: "claim_failures", Name: "claim_failures",
...@@ -278,12 +269,8 @@ func (m *Metrics) RecordBondClaimed(amount uint64) { ...@@ -278,12 +269,8 @@ func (m *Metrics) RecordBondClaimed(amount uint64) {
m.bondsClaimed.Add(float64(amount)) m.bondsClaimed.Add(float64(amount))
} }
func (m *Metrics) RecordCannonExecutionTime(t float64) { func (m *Metrics) RecordVmExecutionTime(vmType string, dur time.Duration) {
m.cannonExecutionTime.Observe(t) m.vmExecutionTime.WithLabelValues(vmType).Observe(dur.Seconds())
}
func (m *Metrics) RecordAsteriscExecutionTime(t float64) {
m.asteriscExecutionTime.Observe(t)
} }
func (m *Metrics) RecordClaimResolutionTime(t float64) { func (m *Metrics) RecordClaimResolutionTime(t float64) {
......
...@@ -2,6 +2,7 @@ package metrics ...@@ -2,6 +2,7 @@ package metrics
import ( import (
"io" "io"
"time"
contractMetrics "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" contractMetrics "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -37,10 +38,9 @@ func (*NoopMetricsImpl) RecordPreimageChallengeFailed() {} ...@@ -37,10 +38,9 @@ func (*NoopMetricsImpl) RecordPreimageChallengeFailed() {}
func (*NoopMetricsImpl) RecordBondClaimFailed() {} func (*NoopMetricsImpl) RecordBondClaimFailed() {}
func (*NoopMetricsImpl) RecordBondClaimed(uint64) {} func (*NoopMetricsImpl) RecordBondClaimed(uint64) {}
func (*NoopMetricsImpl) RecordCannonExecutionTime(t float64) {} func (*NoopMetricsImpl) RecordVmExecutionTime(_ string, _ time.Duration) {}
func (*NoopMetricsImpl) RecordAsteriscExecutionTime(t float64) {} func (*NoopMetricsImpl) RecordClaimResolutionTime(t float64) {}
func (*NoopMetricsImpl) RecordClaimResolutionTime(t float64) {} func (*NoopMetricsImpl) RecordGameActTime(t float64) {}
func (*NoopMetricsImpl) RecordGameActTime(t float64) {}
func (*NoopMetricsImpl) RecordGamesStatus(inProgress, defenderWon, challengerWon int) {} func (*NoopMetricsImpl) RecordGamesStatus(inProgress, defenderWon, challengerWon int) {}
......
...@@ -102,22 +102,22 @@ func FindMonorepoRoot(t *testing.T) string { ...@@ -102,22 +102,22 @@ func FindMonorepoRoot(t *testing.T) string {
func applyCannonConfig(c *config.Config, t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis) { func applyCannonConfig(c *config.Config, t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis) {
require := require.New(t) require := require.New(t)
root := FindMonorepoRoot(t) root := FindMonorepoRoot(t)
c.CannonBin = root + "cannon/bin/cannon" c.Cannon.VmBin = root + "cannon/bin/cannon"
c.CannonServer = root + "op-program/bin/op-program" c.Cannon.Server = root + "op-program/bin/op-program"
c.CannonAbsolutePreState = root + "op-program/bin/prestate.json" c.CannonAbsolutePreState = root + "op-program/bin/prestate.json"
c.CannonSnapshotFreq = 10_000_000 c.Cannon.SnapshotFreq = 10_000_000
genesisBytes, err := json.Marshal(l2Genesis) genesisBytes, err := json.Marshal(l2Genesis)
require.NoError(err, "marshall l2 genesis config") require.NoError(err, "marshall l2 genesis config")
genesisFile := filepath.Join(c.Datadir, "l2-genesis.json") genesisFile := filepath.Join(c.Datadir, "l2-genesis.json")
require.NoError(os.WriteFile(genesisFile, genesisBytes, 0o644)) require.NoError(os.WriteFile(genesisFile, genesisBytes, 0o644))
c.CannonL2GenesisPath = genesisFile c.Cannon.L2GenesisPath = genesisFile
rollupBytes, err := json.Marshal(rollupCfg) rollupBytes, err := json.Marshal(rollupCfg)
require.NoError(err, "marshall rollup config") require.NoError(err, "marshall rollup config")
rollupFile := filepath.Join(c.Datadir, "rollup.json") rollupFile := filepath.Join(c.Datadir, "rollup.json")
require.NoError(os.WriteFile(rollupFile, rollupBytes, 0o644)) require.NoError(os.WriteFile(rollupFile, rollupBytes, 0o644))
c.CannonRollupConfigPath = rollupFile c.Cannon.RollupConfigPath = rollupFile
} }
func WithCannon(t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis) Option { func WithCannon(t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis) Option {
...@@ -177,12 +177,12 @@ func NewChallengerConfig(t *testing.T, sys EndpointProvider, l2NodeName string, ...@@ -177,12 +177,12 @@ func NewChallengerConfig(t *testing.T, sys EndpointProvider, l2NodeName string,
require.NotEmpty(t, cfg.TxMgrConfig.PrivateKey, "Missing private key for TxMgrConfig") require.NotEmpty(t, cfg.TxMgrConfig.PrivateKey, "Missing private key for TxMgrConfig")
require.NoError(t, cfg.Check(), "op-challenger config should be valid") require.NoError(t, cfg.Check(), "op-challenger config should be valid")
if cfg.CannonBin != "" { if cfg.Cannon.VmBin != "" {
_, err := os.Stat(cfg.CannonBin) _, err := os.Stat(cfg.Cannon.VmBin)
require.NoError(t, err, "cannon should be built. Make sure you've run make cannon-prestate") require.NoError(t, err, "cannon should be built. Make sure you've run make cannon-prestate")
} }
if cfg.CannonServer != "" { if cfg.Cannon.Server != "" {
_, err := os.Stat(cfg.CannonServer) _, err := os.Stat(cfg.Cannon.Server)
require.NoError(t, err, "op-program should be built. Make sure you've run make cannon-prestate") require.NoError(t, err, "op-program should be built. Make sure you've run make cannon-prestate")
} }
if cfg.CannonAbsolutePreState != "" { if cfg.CannonAbsolutePreState != "" {
......
...@@ -62,7 +62,7 @@ func (g *OutputCannonGameHelper) CreateHonestActor(ctx context.Context, l2Node s ...@@ -62,7 +62,7 @@ func (g *OutputCannonGameHelper) CreateHonestActor(ctx context.Context, l2Node s
prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock)
l1Head := g.GetL1Head(ctx) l1Head := g.GetL1Head(ctx)
accessor, err := outputs.NewOutputCannonTraceAccessor( accessor, err := outputs.NewOutputCannonTraceAccessor(
logger, metrics.NoopMetrics, cfg, l2Client, prestateProvider, cfg.CannonAbsolutePreState, rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) logger, metrics.NoopMetrics, cfg.Cannon, l2Client, prestateProvider, cfg.CannonAbsolutePreState, rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock)
g.Require.NoError(err, "Failed to create output cannon trace accessor") g.Require.NoError(err, "Failed to create output cannon trace accessor")
return NewOutputHonestHelper(g.T, g.Require, &g.OutputGameHelper, g.Game, accessor) return NewOutputHonestHelper(g.T, g.Require, &g.OutputGameHelper, g.Game, accessor)
} }
......
...@@ -10,8 +10,8 @@ import ( ...@@ -10,8 +10,8 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-challenger/metrics"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e" op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
...@@ -147,7 +147,7 @@ func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs uti ...@@ -147,7 +147,7 @@ func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs uti
cannonOpts(&cfg) cannonOpts(&cfg)
logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon") logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon")
executor := cannon.NewExecutor(logger, metrics.NoopMetrics, &cfg, cfg.CannonAbsolutePreState, inputs) executor := vm.NewExecutor(logger, metrics.NoopMetrics, cfg.Cannon, cfg.CannonAbsolutePreState, inputs)
t.Log("Running cannon") t.Log("Running cannon")
err := executor.GenerateProof(ctx, proofsDir, math.MaxUint) err := executor.GenerateProof(ctx, proofsDir, math.MaxUint)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment