Commit a40a8771 authored by OptimismBot's avatar OptimismBot Committed by GitHub

Merge pull request #6634 from ethereum-optimism/aj/cannon-network

op-challenger: Pass through network config to cannon
parents 1f352768 4de5ad9a
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -15,6 +16,8 @@ import ( ...@@ -15,6 +16,8 @@ import (
var ( var (
l1EthRpc = "http://example.com:8545" l1EthRpc = "http://example.com:8545"
gameAddressValue = "0xaa00000000000000000000000000000000000000" gameAddressValue = "0xaa00000000000000000000000000000000000000"
cannonNetwork = chaincfg.AvailableNetworks()[0]
otherCannonNetwork = chaincfg.AvailableNetworks()[1]
cannonBin = "./bin/cannon" cannonBin = "./bin/cannon"
cannonServer = "./bin/op-program" cannonServer = "./bin/op-program"
cannonPreState = "./pre.json" cannonPreState = "./pre.json"
...@@ -226,6 +229,67 @@ func TestCannonSnapshotFreq(t *testing.T) { ...@@ -226,6 +229,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", cannonNetwork, "--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", otherCannonNetwork))
require.Equal(t, otherCannonNetwork, 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) { func verifyArgsInvalid(t *testing.T, messageContains string, cliArgs []string) {
_, _, err := runWithArgs(cliArgs) _, _, err := runWithArgs(cliArgs)
require.ErrorContains(t, err, messageContains) require.ErrorContains(t, err, messageContains)
...@@ -273,6 +337,7 @@ func requiredArgs(traceType config.TraceType) map[string]string { ...@@ -273,6 +337,7 @@ func requiredArgs(traceType config.TraceType) map[string]string {
case config.TraceTypeAlphabet: case config.TraceTypeAlphabet:
args["--alphabet"] = alphabetTrace args["--alphabet"] = alphabetTrace
case config.TraceTypeCannon: case config.TraceTypeCannon:
args["--cannon-network"] = cannonNetwork
args["--cannon-bin"] = cannonBin args["--cannon-bin"] = cannonBin
args["--cannon-server"] = cannonServer args["--cannon-server"] = cannonServer
args["--cannon-prestate"] = cannonPreState args["--cannon-prestate"] = cannonPreState
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
...@@ -18,8 +19,12 @@ var ( ...@@ -18,8 +19,12 @@ var (
ErrMissingAlphabetTrace = errors.New("missing alphabet trace") ErrMissingAlphabetTrace = errors.New("missing alphabet trace")
ErrMissingL1EthRPC = errors.New("missing l1 eth rpc url") ErrMissingL1EthRPC = errors.New("missing l1 eth rpc url")
ErrMissingGameAddress = errors.New("missing game address") ErrMissingGameAddress = errors.New("missing game address")
ErrMissingPreimageOracleAddress = errors.New("missing pre-image oracle address")
ErrMissingCannonSnapshotFreq = errors.New("missing cannon snapshot freq") 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 type TraceType string
...@@ -73,6 +78,9 @@ type Config struct { ...@@ -73,6 +78,9 @@ type Config struct {
CannonBin string // Path to the cannon executable to run when generating trace data 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 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
CannonNetwork string
CannonRollupConfigPath string
CannonL2GenesisPath string
CannonDatadir string // Cannon Data Directory CannonDatadir string // Cannon Data Directory
CannonL2 string // L2 RPC Url CannonL2 string // L2 RPC Url
CannonSnapshotFreq uint // Frequency of snapshots to create when executing cannon (in VM instructions) CannonSnapshotFreq uint // Frequency of snapshots to create when executing cannon (in VM instructions)
...@@ -119,6 +127,24 @@ func (c Config) Check() error { ...@@ -119,6 +127,24 @@ func (c Config) Check() error {
if c.CannonServer == "" { if c.CannonServer == "" {
return ErrMissingCannonServer 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 == "" { if c.CannonAbsolutePreState == "" {
return ErrMissingCannonAbsolutePreState return ErrMissingCannonAbsolutePreState
} }
......
...@@ -14,6 +14,7 @@ var ( ...@@ -14,6 +14,7 @@ var (
validAlphabetTrace = "abcdefgh" validAlphabetTrace = "abcdefgh"
validCannonBin = "./bin/cannon" validCannonBin = "./bin/cannon"
validCannonOpProgramBin = "./bin/op-program" validCannonOpProgramBin = "./bin/op-program"
validCannonNetwork = "mainnet"
validCannonAbsolutPreState = "pre.json" validCannonAbsolutPreState = "pre.json"
validCannonDatadir = "/tmp/cannon" validCannonDatadir = "/tmp/cannon"
validCannonL2 = "http://localhost:9545" validCannonL2 = "http://localhost:9545"
...@@ -32,6 +33,7 @@ func validConfig(traceType TraceType) Config { ...@@ -32,6 +33,7 @@ func validConfig(traceType TraceType) Config {
cfg.CannonAbsolutePreState = validCannonAbsolutPreState cfg.CannonAbsolutePreState = validCannonAbsolutPreState
cfg.CannonDatadir = validCannonDatadir cfg.CannonDatadir = validCannonDatadir
cfg.CannonL2 = validCannonL2 cfg.CannonL2 = validCannonL2
cfg.CannonNetwork = validCannonNetwork
} }
return cfg return cfg
} }
...@@ -110,3 +112,41 @@ func TestCannonSnapshotFreq(t *testing.T) { ...@@ -110,3 +112,41 @@ func TestCannonSnapshotFreq(t *testing.T) {
require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq) 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)
}
...@@ -4,11 +4,13 @@ import ( ...@@ -4,11 +4,13 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv" "strconv"
"strings"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
oplog "github.com/ethereum-optimism/optimism/op-service/log" oplog "github.com/ethereum-optimism/optimism/op-service/log"
...@@ -17,7 +19,7 @@ import ( ...@@ -17,7 +19,7 @@ import (
const ( const (
snapsDir = "snapshots" snapsDir = "snapshots"
preimagesDir = "snapshots" preimagesDir = "preimages"
) )
var snapshotNameRegexp = regexp.MustCompile(`^[0-9]+\.json$`) var snapshotNameRegexp = regexp.MustCompile(`^[0-9]+\.json$`)
...@@ -32,6 +34,9 @@ type Executor struct { ...@@ -32,6 +34,9 @@ type Executor struct {
inputs localGameInputs inputs localGameInputs
cannon string cannon string
server string server string
network string
rollupConfig string
l2Genesis string
absolutePreState string absolutePreState string
dataDir string dataDir string
snapshotFreq uint snapshotFreq uint
...@@ -47,6 +52,9 @@ func NewExecutor(logger log.Logger, cfg *config.Config, inputs localGameInputs) ...@@ -47,6 +52,9 @@ func NewExecutor(logger log.Logger, cfg *config.Config, inputs localGameInputs)
inputs: inputs, inputs: inputs,
cannon: cfg.CannonBin, cannon: cfg.CannonBin,
server: cfg.CannonServer, server: cfg.CannonServer,
network: cfg.CannonNetwork,
rollupConfig: cfg.CannonRollupConfigPath,
l2Genesis: cfg.CannonL2GenesisPath,
absolutePreState: cfg.CannonAbsolutePreState, absolutePreState: cfg.CannonAbsolutePreState,
dataDir: cfg.CannonDatadir, dataDir: cfg.CannonDatadir,
snapshotFreq: cfg.CannonSnapshotFreq, snapshotFreq: cfg.CannonSnapshotFreq,
...@@ -69,12 +77,11 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro ...@@ -69,12 +77,11 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro
"--output", filepath.Join(dir, "out.json"), "--output", filepath.Join(dir, "out.json"),
"--meta", "", "--meta", "",
"--proof-at", "=" + strconv.FormatUint(i, 10), "--proof-at", "=" + strconv.FormatUint(i, 10),
"--stop-at", "=" + strconv.FormatUint(i+1, 10),
"--proof-fmt", filepath.Join(proofDir, "%d.json"), "--proof-fmt", filepath.Join(proofDir, "%d.json"),
"--snapshot-at", "%" + strconv.FormatUint(uint64(e.snapshotFreq), 10), "--snapshot-at", "%" + strconv.FormatUint(uint64(e.snapshotFreq), 10),
"--snapshot-fmt", filepath.Join(snapshotDir, "%d.json"), "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json"),
"--", "--",
e.server, e.server, "--server",
"--l1", e.l1, "--l1", e.l1,
"--l2", e.l2, "--l2", e.l2,
"--datadir", dataDir, "--datadir", dataDir,
...@@ -84,6 +91,18 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro ...@@ -84,6 +91,18 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro
"--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 i < math.MaxUint64 {
args = append(args, "--stop-at", "="+strconv.FormatUint(i+1, 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 { if err := os.MkdirAll(snapshotDir, 0755); err != nil {
return fmt.Errorf("could not create snapshot directory %v: %w", snapshotDir, err) return fmt.Errorf("could not create snapshot directory %v: %w", snapshotDir, err)
...@@ -94,7 +113,7 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro ...@@ -94,7 +113,7 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro
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", i, "cmd", e.cannon, "args", args) e.logger.Info("Generating trace", "proof", i, "cmd", e.cannon, "args", strings.Join(args, ", "))
return e.cmdExecutor(ctx, e.logger.New("proof", i), e.cannon, args...) return e.cmdExecutor(ctx, e.logger.New("proof", i), e.cannon, args...)
} }
...@@ -102,7 +121,8 @@ func runCmd(ctx context.Context, l log.Logger, binary string, args ...string) er ...@@ -102,7 +121,8 @@ func runCmd(ctx context.Context, l log.Logger, binary string, args ...string) er
cmd := exec.CommandContext(ctx, binary, args...) cmd := exec.CommandContext(ctx, binary, args...)
stdOut := oplog.NewWriter(l, log.LvlInfo) stdOut := oplog.NewWriter(l, log.LvlInfo)
defer stdOut.Close() defer stdOut.Close()
stdErr := oplog.NewWriter(l, log.LvlError) // Keep stdErr at info level because cannon uses stderr for progress messages
stdErr := oplog.NewWriter(l, log.LvlInfo)
defer stdErr.Close() defer stdErr.Close()
cmd.Stdout = stdOut cmd.Stdout = stdOut
cmd.Stderr = stdErr cmd.Stderr = stdErr
...@@ -123,17 +143,17 @@ func findStartingSnapshot(logger log.Logger, snapDir string, absolutePreState st ...@@ -123,17 +143,17 @@ func findStartingSnapshot(logger log.Logger, snapDir string, absolutePreState st
bestSnap := uint64(0) bestSnap := uint64(0)
for _, entry := range entries { for _, entry := range entries {
if entry.IsDir() { if entry.IsDir() {
logger.Warn("Unexpected directory in snapshots dir: %v/%v", snapDir, entry.Name()) logger.Warn("Unexpected directory in snapshots dir", "parent", snapDir, "child", entry.Name())
continue continue
} }
name := entry.Name() name := entry.Name()
if !snapshotNameRegexp.MatchString(name) { if !snapshotNameRegexp.MatchString(name) {
logger.Warn("Unexpected file in snapshots dir: %v/%v", snapDir, entry.Name()) logger.Warn("Unexpected file in snapshots dir", "parent", snapDir, "child", entry.Name())
continue continue
} }
index, err := strconv.ParseUint(name[0:len(name)-len(".json")], 10, 64) index, err := strconv.ParseUint(name[0:len(name)-len(".json")], 10, 64)
if err != nil { if err != nil {
logger.Error("Unable to parse trace index of snapshot file: %v/%v", snapDir, entry.Name()) logger.Error("Unable to parse trace index of snapshot file", "parent", snapDir, "child", entry.Name())
continue continue
} }
if index > bestSnap && index < traceIndex { if index > bestSnap && index < traceIndex {
......
...@@ -3,6 +3,7 @@ package cannon ...@@ -3,6 +3,7 @@ package cannon
import ( import (
"context" "context"
"fmt" "fmt"
"math"
"math/big" "math/big"
"os" "os"
"path/filepath" "path/filepath"
...@@ -35,49 +36,90 @@ func TestGenerateProof(t *testing.T) { ...@@ -35,49 +36,90 @@ func TestGenerateProof(t *testing.T) {
l2Claim: common.Hash{0x44}, l2Claim: common.Hash{0x44},
l2BlockNumber: big.NewInt(3333), l2BlockNumber: big.NewInt(3333),
} }
captureExec := func(cfg config.Config, proofAt uint64) (string, string, map[string]string) {
executor := NewExecutor(testlog.Logger(t, log.LvlInfo), &cfg, inputs) executor := NewExecutor(testlog.Logger(t, log.LvlInfo), &cfg, 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
} }
var binary string var binary string
var subcommand string var subcommand string
args := make(map[string]string) args := make(map[string]string)
executor.cmdExecutor = func(ctx context.Context, l log.Logger, b string, a ...string) error { executor.cmdExecutor = func(ctx context.Context, l log.Logger, b string, a ...string) error {
binary = b binary = b
subcommand = a[0] subcommand = a[0]
for i := 1; i < len(a); i += 2 { for i := 1; i < len(a); {
args[a[i]] = a[i+1] 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
} }
return nil err := executor.GenerateProof(context.Background(), cfg.CannonDatadir, proofAt)
require.NoError(t, err)
return binary, subcommand, args
} }
err := executor.GenerateProof(context.Background(), cfg.CannonDatadir, 150_000_000)
require.NoError(t, err) t.Run("Network", func(t *testing.T) {
require.DirExists(t, filepath.Join(cfg.CannonDatadir, preimagesDir)) cfg.CannonNetwork = "mainnet"
require.DirExists(t, filepath.Join(cfg.CannonDatadir, proofsDir)) cfg.CannonRollupConfigPath = ""
require.DirExists(t, filepath.Join(cfg.CannonDatadir, snapsDir)) cfg.CannonL2GenesisPath = ""
require.Equal(t, cfg.CannonBin, binary) binary, subcommand, args := captureExec(cfg, 150_000_000)
require.Equal(t, "run", subcommand) require.DirExists(t, filepath.Join(cfg.CannonDatadir, preimagesDir))
require.Equal(t, input, args["--input"]) require.DirExists(t, filepath.Join(cfg.CannonDatadir, proofsDir))
require.Contains(t, args, "--meta") require.DirExists(t, filepath.Join(cfg.CannonDatadir, snapsDir))
require.Equal(t, "", args["--meta"]) require.Equal(t, cfg.CannonBin, binary)
require.Equal(t, filepath.Join(cfg.CannonDatadir, "out.json"), args["--output"]) require.Equal(t, "run", subcommand)
require.Equal(t, "=150000000", args["--proof-at"]) require.Equal(t, input, args["--input"])
require.Equal(t, "=150000001", args["--stop-at"]) require.Contains(t, args, "--meta")
require.Equal(t, "%500", args["--snapshot-at"]) require.Equal(t, "", args["--meta"])
require.Equal(t, cfg.CannonServer, args["--"]) require.Equal(t, filepath.Join(cfg.CannonDatadir, "out.json"), args["--output"])
require.Equal(t, cfg.L1EthRpc, args["--l1"]) require.Equal(t, "=150000000", args["--proof-at"])
require.Equal(t, cfg.CannonL2, args["--l2"]) require.Equal(t, "=150000001", args["--stop-at"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, preimagesDir), args["--datadir"]) require.Equal(t, "%500", args["--snapshot-at"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, proofsDir, "%d.json"), args["--proof-fmt"]) // Slight quirk of how we pair off args
require.Equal(t, filepath.Join(cfg.CannonDatadir, snapsDir, "%d.json"), args["--snapshot-fmt"]) // 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
// Local game inputs require.Equal(t, "--server", args[cfg.CannonServer])
require.Equal(t, inputs.l1Head.Hex(), args["--l1.head"]) require.Equal(t, cfg.L1EthRpc, args["--l1"])
require.Equal(t, inputs.l2Head.Hex(), args["--l2.head"]) require.Equal(t, cfg.CannonL2, args["--l2"])
require.Equal(t, inputs.l2OutputRoot.Hex(), args["--l2.outputroot"]) require.Equal(t, filepath.Join(cfg.CannonDatadir, preimagesDir), args["--datadir"])
require.Equal(t, inputs.l2Claim.Hex(), args["--l2.claim"]) require.Equal(t, filepath.Join(cfg.CannonDatadir, proofsDir, "%d.json"), args["--proof-fmt"])
require.Equal(t, "3333", args["--l2.blocknumber"]) 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, 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(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) { func TestRunCmdLogsOutput(t *testing.T) {
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
opservice "github.com/ethereum-optimism/optimism/op-service" opservice "github.com/ethereum-optimism/optimism/op-service"
openum "github.com/ethereum-optimism/optimism/op-service/enum" openum "github.com/ethereum-optimism/optimism/op-service/enum"
oplog "github.com/ethereum-optimism/optimism/op-service/log" oplog "github.com/ethereum-optimism/optimism/op-service/log"
...@@ -58,6 +59,21 @@ var ( ...@@ -58,6 +59,21 @@ var (
Usage: "Correct Alphabet Trace (alphabet trace type only)", Usage: "Correct Alphabet Trace (alphabet trace type only)",
EnvVars: prefixEnvVars("ALPHABET"), 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{ CannonBinFlag = &cli.StringFlag{
Name: "cannon-bin", Name: "cannon-bin",
Usage: "Path to cannon executable to use when generating trace data (cannon trace type only)", Usage: "Path to cannon executable to use when generating trace data (cannon trace type only)",
...@@ -103,6 +119,9 @@ var requiredFlags = []cli.Flag{ ...@@ -103,6 +119,9 @@ var requiredFlags = []cli.Flag{
// optionalFlags is a list of unchecked cli flags // optionalFlags is a list of unchecked cli flags
var optionalFlags = []cli.Flag{ var optionalFlags = []cli.Flag{
AlphabetFlag, AlphabetFlag,
CannonNetworkFlag,
CannonRollupConfigFlag,
CannonL2GenesisFlag,
CannonBinFlag, CannonBinFlag,
CannonServerFlag, CannonServerFlag,
CannonPreStateFlag, CannonPreStateFlag,
...@@ -130,6 +149,14 @@ func CheckRequired(ctx *cli.Context) error { ...@@ -130,6 +149,14 @@ func CheckRequired(ctx *cli.Context) error {
gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name))) gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
switch gameType { switch gameType {
case config.TraceTypeCannon: 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) { if !ctx.IsSet(CannonBinFlag.Name) {
return fmt.Errorf("flag %s is required", CannonBinFlag.Name) return fmt.Errorf("flag %s is required", CannonBinFlag.Name)
} }
...@@ -175,6 +202,9 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) { ...@@ -175,6 +202,9 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
TraceType: traceTypeFlag, TraceType: traceTypeFlag,
GameAddress: dgfAddress, GameAddress: dgfAddress,
AlphabetTrace: ctx.String(AlphabetFlag.Name), 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), CannonBin: ctx.String(CannonBinFlag.Name),
CannonServer: ctx.String(CannonServerFlag.Name), CannonServer: ctx.String(CannonServerFlag.Name),
CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name), CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name),
......
...@@ -2,16 +2,21 @@ package disputegame ...@@ -2,16 +2,21 @@ package disputegame
import ( import (
"context" "context"
"encoding/json"
"os"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/core"
) )
type CannonGameHelper struct { type CannonGameHelper struct {
FaultGameHelper FaultGameHelper
} }
func (g *CannonGameHelper) StartChallenger(ctx context.Context, l1Endpoint string, l2Endpoint string, name string, options ...challenger.Option) *challenger.Helper { func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{ opts := []challenger.Option{
func(c *config.Config) { func(c *config.Config) {
c.GameAddress = g.addr c.GameAddress = g.addr
...@@ -24,6 +29,18 @@ func (g *CannonGameHelper) StartChallenger(ctx context.Context, l1Endpoint strin ...@@ -24,6 +29,18 @@ func (g *CannonGameHelper) StartChallenger(ctx context.Context, l1Endpoint strin
c.CannonServer = "../op-program/bin/op-program" c.CannonServer = "../op-program/bin/op-program"
c.CannonAbsolutePreState = "../op-program/bin/prestate.json" c.CannonAbsolutePreState = "../op-program/bin/prestate.json"
c.CannonSnapshotFreq = config.DefaultCannonSnapshotFreq c.CannonSnapshotFreq = config.DefaultCannonSnapshotFreq
genesisBytes, err := json.Marshal(l2Genesis)
g.require.NoError(err, "marshall l2 genesis config")
genesisFile := filepath.Join(c.CannonDatadir, "l2-genesis.json")
g.require.NoError(os.WriteFile(genesisFile, genesisBytes, 0644))
c.CannonL2GenesisPath = genesisFile
rollupBytes, err := json.Marshal(rollupCfg)
g.require.NoError(err, "marshall rollup config")
rollupFile := filepath.Join(c.CannonDatadir, "rollup.json")
g.require.NoError(os.WriteFile(rollupFile, rollupBytes, 0644))
c.CannonRollupConfigPath = rollupFile
}, },
} }
opts = append(opts, options...) opts = append(opts, options...)
......
...@@ -156,7 +156,7 @@ func TestCannonDisputeGame(t *testing.T) { ...@@ -156,7 +156,7 @@ func TestCannonDisputeGame(t *testing.T) {
game := disputeGameFactory.StartCannonGame(ctx, common.Hash{0xaa}) game := disputeGameFactory.StartCannonGame(ctx, common.Hash{0xaa})
require.NotNil(t, game) require.NotNil(t, game)
game.StartChallenger(ctx, sys.NodeEndpoint("l1"), sys.NodeEndpoint("sequencer"), "Challenger", func(c *config.Config) { game.StartChallenger(ctx, sys.RollupConfig, sys.L2GenesisCfg, sys.NodeEndpoint("l1"), sys.NodeEndpoint("sequencer"), "Challenger", func(c *config.Config) {
c.AgreeWithProposedOutput = true // Agree with the proposed output, so disagree with the root claim c.AgreeWithProposedOutput = true // Agree with the proposed output, so disagree with the root claim
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Alice) c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Alice)
}) })
...@@ -173,8 +173,10 @@ func TestCannonDisputeGame(t *testing.T) { ...@@ -173,8 +173,10 @@ func TestCannonDisputeGame(t *testing.T) {
func startFaultDisputeSystem(t *testing.T) (*System, *ethclient.Client) { func startFaultDisputeSystem(t *testing.T) (*System, *ethclient.Client) {
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
delete(cfg.Nodes, "verifier") delete(cfg.Nodes, "verifier")
cfg.DeployConfig.SequencerWindowSize = 4
cfg.DeployConfig.FinalizationPeriodSeconds = 2
cfg.SupportL1TimeTravel = true cfg.SupportL1TimeTravel = true
cfg.DeployConfig.L2OutputOracleSubmissionInterval = 2 cfg.DeployConfig.L2OutputOracleSubmissionInterval = 1
cfg.NonFinalizedProposals = true // Submit output proposals asap cfg.NonFinalizedProposals = true // Submit output proposals asap
sys, err := cfg.Start() sys, err := cfg.Start()
require.NoError(t, err, "Error starting up system") require.NoError(t, err, "Error starting up system")
......
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