Commit cbd17dcb authored by Adrian Sutton's avatar Adrian Sutton

op-challenger: Pass through network config to cannon

parent ec6dc47b
......@@ -15,6 +15,7 @@ import (
var (
l1EthRpc = "http://example.com:8545"
gameAddressValue = "0xaa00000000000000000000000000000000000000"
cannonNetwork = "mainnet"
cannonBin = "./bin/cannon"
cannonServer = "./bin/op-program"
cannonPreState = "./pre.json"
......@@ -226,6 +227,67 @@ func TestCannonSnapshotFreq(t *testing.T) {
})
}
func TestRequireEitherCannonNetworkOrRollupAndGenesis(t *testing.T) {
verifyArgsInvalid(
t,
"flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required",
addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network"))
verifyArgsInvalid(
t,
"flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required",
addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-rollup-config=rollup.json"))
verifyArgsInvalid(
t,
"flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required",
addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-l2-genesis=gensis.json"))
}
func TestMustNotSpecifyNetworkAndRollup(t *testing.T) {
verifyArgsInvalid(
t,
"flag cannon-network can not be used with cannon-rollup-config and cannon-l2-genesis",
addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network",
"--cannon-network=mainnet", "--cannon-rollup-config=rollup.json"))
}
func TestCannonNetwork(t *testing.T) {
t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) {
configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-network"))
})
t.Run("NotRequiredWhenRollupAndGenesIsSpecified", func(t *testing.T) {
configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network",
"--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json"))
})
t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-network=goerli"))
require.Equal(t, "goerli", cfg.CannonNetwork)
})
}
func TestCannonRollupConfig(t *testing.T) {
t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) {
configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-rollup-config"))
})
t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json"))
require.Equal(t, "rollup.json", cfg.CannonRollupConfigPath)
})
}
func TestCannonL2Genesis(t *testing.T) {
t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) {
configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-l2-genesis"))
})
t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json"))
require.Equal(t, "genesis.json", cfg.CannonL2GenesisPath)
})
}
func verifyArgsInvalid(t *testing.T, messageContains string, cliArgs []string) {
_, _, err := runWithArgs(cliArgs)
require.ErrorContains(t, err, messageContains)
......@@ -273,6 +335,7 @@ func requiredArgs(traceType config.TraceType) map[string]string {
case config.TraceTypeAlphabet:
args["--alphabet"] = alphabetTrace
case config.TraceTypeCannon:
args["--cannon-network"] = cannonNetwork
args["--cannon-bin"] = cannonBin
args["--cannon-server"] = cannonServer
args["--cannon-prestate"] = cannonPreState
......
......@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
)
......@@ -18,8 +19,12 @@ var (
ErrMissingAlphabetTrace = errors.New("missing alphabet trace")
ErrMissingL1EthRPC = errors.New("missing l1 eth rpc url")
ErrMissingGameAddress = errors.New("missing game address")
ErrMissingPreimageOracleAddress = errors.New("missing pre-image oracle address")
ErrMissingCannonSnapshotFreq = errors.New("missing cannon snapshot freq")
ErrMissingCannonRollupConfig = errors.New("missing cannon network or rollup config path")
ErrMissingCannonL2Genesis = errors.New("missing cannon network or l2 genesis path")
ErrCannonNetworkAndRollupConfig = errors.New("only specify one of network or rollup config path")
ErrCannonNetworkAndL2Genesis = errors.New("only specify one of network or l2 genesis path")
ErrCannonNetworkUnknown = errors.New("unknown cannon network")
)
type TraceType string
......@@ -73,6 +78,9 @@ type Config struct {
CannonBin string // Path to the cannon executable to run when generating trace data
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
CannonNetwork string
CannonRollupConfigPath string
CannonL2GenesisPath string
CannonDatadir string // Cannon Data Directory
CannonL2 string // L2 RPC Url
CannonSnapshotFreq uint // Frequency of snapshots to create when executing cannon (in VM instructions)
......@@ -119,6 +127,24 @@ func (c Config) Check() error {
if c.CannonServer == "" {
return ErrMissingCannonServer
}
if c.CannonNetwork == "" {
if c.CannonRollupConfigPath == "" {
return ErrMissingCannonRollupConfig
}
if c.CannonL2GenesisPath == "" {
return ErrMissingCannonL2Genesis
}
} else {
if c.CannonRollupConfigPath != "" {
return ErrCannonNetworkAndRollupConfig
}
if c.CannonL2GenesisPath != "" {
return ErrCannonNetworkAndL2Genesis
}
if _, ok := chaincfg.NetworksByName[c.CannonNetwork]; !ok {
return fmt.Errorf("%w: %v", ErrCannonNetworkUnknown, c.CannonNetwork)
}
}
if c.CannonAbsolutePreState == "" {
return ErrMissingCannonAbsolutePreState
}
......
......@@ -14,6 +14,7 @@ var (
validAlphabetTrace = "abcdefgh"
validCannonBin = "./bin/cannon"
validCannonOpProgramBin = "./bin/op-program"
validCannonNetwork = "mainnet"
validCannonAbsolutPreState = "pre.json"
validCannonDatadir = "/tmp/cannon"
validCannonL2 = "http://localhost:9545"
......@@ -32,6 +33,7 @@ func validConfig(traceType TraceType) Config {
cfg.CannonAbsolutePreState = validCannonAbsolutPreState
cfg.CannonDatadir = validCannonDatadir
cfg.CannonL2 = validCannonL2
cfg.CannonNetwork = validCannonNetwork
}
return cfg
}
......@@ -110,3 +112,41 @@ func TestCannonSnapshotFreq(t *testing.T) {
require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq)
})
}
func TestCannonNetworkOrRollupConfigRequired(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = ""
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = "genesis.json"
require.ErrorIs(t, cfg.Check(), ErrMissingCannonRollupConfig)
}
func TestCannonNetworkOrL2GenesisRequired(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = ""
cfg.CannonRollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrMissingCannonL2Genesis)
}
func TestMustNotSpecifyNetworkAndRollup(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = validCannonNetwork
cfg.CannonRollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndRollupConfig)
}
func TestMustNotSpecifyNetworkAndL2Genesis(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = validCannonNetwork
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = "foo.json"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndL2Genesis)
}
func TestNetworkMustBeValid(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = "unknown"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown)
}
......@@ -32,6 +32,9 @@ type Executor struct {
inputs localGameInputs
cannon string
server string
network string
rollupConfig string
l2Genesis string
absolutePreState string
dataDir string
snapshotFreq uint
......@@ -47,6 +50,9 @@ func NewExecutor(logger log.Logger, cfg *config.Config, inputs localGameInputs)
inputs: inputs,
cannon: cfg.CannonBin,
server: cfg.CannonServer,
network: cfg.CannonNetwork,
rollupConfig: cfg.CannonRollupConfigPath,
l2Genesis: cfg.CannonL2GenesisPath,
absolutePreState: cfg.CannonAbsolutePreState,
dataDir: cfg.CannonDatadir,
snapshotFreq: cfg.CannonSnapshotFreq,
......@@ -84,6 +90,15 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro
"--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)
......
......@@ -35,49 +35,71 @@ func TestGenerateProof(t *testing.T) {
l2Claim: common.Hash{0x44},
l2BlockNumber: big.NewInt(3333),
}
executor := NewExecutor(testlog.Logger(t, log.LvlInfo), &cfg, 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); i += 2 {
args[a[i]] = a[i+1]
captureExec := func(cfg config.Config) (string, string, map[string]string) {
executor := NewExecutor(testlog.Logger(t, log.LvlInfo), &cfg, 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); i += 2 {
args[a[i]] = a[i+1]
}
return nil
}
return nil
err := executor.GenerateProof(context.Background(), cfg.CannonDatadir, 150_000_000)
require.NoError(t, err)
return binary, subcommand, args
}
err := executor.GenerateProof(context.Background(), cfg.CannonDatadir, 150_000_000)
require.NoError(t, err)
require.DirExists(t, filepath.Join(cfg.CannonDatadir, preimagesDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, proofsDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, 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(cfg.CannonDatadir, "out.json"), 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, cfg.CannonServer, args["--"])
require.Equal(t, cfg.L1EthRpc, args["--l1"])
require.Equal(t, cfg.CannonL2, args["--l2"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, preimagesDir), args["--datadir"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, proofsDir, "%d.json"), args["--proof-fmt"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, snapsDir, "%d.json"), args["--snapshot-fmt"])
// 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("Network", func(t *testing.T) {
cfg.CannonNetwork = "mainnet"
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = ""
binary, subcommand, args := captureExec(cfg)
require.DirExists(t, filepath.Join(cfg.CannonDatadir, preimagesDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, proofsDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, 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(cfg.CannonDatadir, "out.json"), 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, cfg.CannonServer, args["--"])
require.Equal(t, cfg.L1EthRpc, args["--l1"])
require.Equal(t, cfg.CannonL2, args["--l2"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, preimagesDir), args["--datadir"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, proofsDir, "%d.json"), args["--proof-fmt"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, snapsDir, "%d.json"), 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(cfg)
require.NotContains(t, args, "--network")
require.Equal(t, cfg.CannonRollupConfigPath, args["--rollup.config"])
require.Equal(t, cfg.CannonL2GenesisPath, args["--l2.genesis"])
})
}
func TestRunCmdLogsOutput(t *testing.T) {
......
......@@ -5,6 +5,7 @@ import (
"strings"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
opservice "github.com/ethereum-optimism/optimism/op-service"
openum "github.com/ethereum-optimism/optimism/op-service/enum"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
......@@ -58,6 +59,21 @@ var (
Usage: "Correct Alphabet Trace (alphabet trace type only)",
EnvVars: prefixEnvVars("ALPHABET"),
}
CannonNetworkFlag = &cli.StringFlag{
Name: "cannon-network",
Usage: fmt.Sprintf("Predefined network selection. Available networks: %s (cannon trace type only)", strings.Join(chaincfg.AvailableNetworks(), ", ")),
EnvVars: prefixEnvVars("CANNON_NETWORK"),
}
CannonRollupConfigFlag = &cli.StringFlag{
Name: "cannon-rollup-config",
Usage: "Rollup chain parameters (cannon trace type only)",
EnvVars: prefixEnvVars("CANNON_ROLLUP_CONFIG"),
}
CannonL2GenesisFlag = &cli.StringFlag{
Name: "cannon-l2-genesis",
Usage: "Path to the op-geth genesis file (cannon trace type only)",
EnvVars: prefixEnvVars("CANNON_L2_GENESIS"),
}
CannonBinFlag = &cli.StringFlag{
Name: "cannon-bin",
Usage: "Path to cannon executable to use when generating trace data (cannon trace type only)",
......@@ -103,6 +119,9 @@ var requiredFlags = []cli.Flag{
// optionalFlags is a list of unchecked cli flags
var optionalFlags = []cli.Flag{
AlphabetFlag,
CannonNetworkFlag,
CannonRollupConfigFlag,
CannonL2GenesisFlag,
CannonBinFlag,
CannonServerFlag,
CannonPreStateFlag,
......@@ -130,6 +149,14 @@ func CheckRequired(ctx *cli.Context) error {
gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
switch gameType {
case config.TraceTypeCannon:
if !ctx.IsSet(CannonNetworkFlag.Name) && !(ctx.IsSet(CannonRollupConfigFlag.Name) && ctx.IsSet(CannonL2GenesisFlag.Name)) {
return fmt.Errorf("flag %v or %v and %v is required",
CannonNetworkFlag.Name, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name)
}
if ctx.IsSet(CannonNetworkFlag.Name) && (ctx.IsSet(CannonRollupConfigFlag.Name) || ctx.IsSet(CannonL2GenesisFlag.Name)) {
return fmt.Errorf("flag %v can not be used with %v and %v",
CannonNetworkFlag.Name, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name)
}
if !ctx.IsSet(CannonBinFlag.Name) {
return fmt.Errorf("flag %s is required", CannonBinFlag.Name)
}
......@@ -175,6 +202,9 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
TraceType: traceTypeFlag,
GameAddress: dgfAddress,
AlphabetTrace: ctx.String(AlphabetFlag.Name),
CannonNetwork: ctx.String(CannonNetworkFlag.Name),
CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name),
CannonL2GenesisPath: ctx.String(CannonL2GenesisFlag.Name),
CannonBin: ctx.String(CannonBinFlag.Name),
CannonServer: ctx.String(CannonServerFlag.Name),
CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name),
......
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