Commit 94056b99 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger, op-program: Require specific opt-in to use the custom config...

op-challenger, op-program: Require specific opt-in to use the custom config chain ID indicator (#13217)

* op-challenger: Support --cannon-l2-chain-id to pass chain ID through to op-program.

* op-program: Default to assuming configs are available in client.

Provide a --l2.custom flag to set the chain ID to the custom chain indicator so the client will load configs via the preimage oracle.
Since loading configs via the preimage oracle doesn't work on-chain, this is a safer and simpler default now that op-program can be built
with custom configs embedded.

* op-challenger: Switch to custom L2 flag instead of specifying chain ID

* op-challenger: Fix boolean option in op-program execution.

* op-e2e: Set custom L2 flag in precompiles test
parent a88f6398
...@@ -765,7 +765,7 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -765,7 +765,7 @@ func TestCannonRequiredArgs(t *testing.T) {
t.Run(fmt.Sprintf("TestMustNotSpecifyCannonNetworkAndRollup-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestMustNotSpecifyCannonNetworkAndRollup-%v", traceType), func(t *testing.T) {
verifyArgsInvalid( verifyArgsInvalid(
t, t,
"flag cannon-network can not be used with cannon-rollup-config and cannon-l2-genesis", "flag cannon-network can not be used with cannon-rollup-config, cannon-l2-genesis or cannon-l2-custom",
addRequiredArgsExcept(traceType, "--cannon-network", addRequiredArgsExcept(traceType, "--cannon-network",
"--cannon-network", cannonNetwork, "--cannon-rollup-config=rollup.json")) "--cannon-network", cannonNetwork, "--cannon-rollup-config=rollup.json"))
}) })
...@@ -777,9 +777,10 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -777,9 +777,10 @@ func TestCannonRequiredArgs(t *testing.T) {
args["--network"] = cannonNetwork args["--network"] = cannonNetwork
args["--cannon-rollup-config"] = "rollup.json" args["--cannon-rollup-config"] = "rollup.json"
args["--cannon-l2-genesis"] = "gensis.json" args["--cannon-l2-genesis"] = "gensis.json"
args["--cannon-l2-custom"] = "true"
verifyArgsInvalid( verifyArgsInvalid(
t, t,
"flag network can not be used with cannon-rollup-config and cannon-l2-genesis", "flag network can not be used with cannon-rollup-config, cannon-l2-genesis or cannon-l2-custom",
toArgList(args)) toArgList(args))
}) })
...@@ -813,6 +814,14 @@ func TestCannonRequiredArgs(t *testing.T) { ...@@ -813,6 +814,14 @@ func TestCannonRequiredArgs(t *testing.T) {
}) })
}) })
t.Run(fmt.Sprintf("TestSetCannonL2ChainId-%v", traceType), func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network",
"--cannon-rollup-config=rollup.json",
"--cannon-l2-genesis=genesis.json",
"--cannon-l2-custom"))
require.True(t, cfg.Cannon.L2Custom)
})
t.Run(fmt.Sprintf("TestCannonRollupConfig-%v", traceType), func(t *testing.T) { t.Run(fmt.Sprintf("TestCannonRollupConfig-%v", traceType), func(t *testing.T) {
t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) {
configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--cannon-rollup-config")) configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--cannon-rollup-config"))
......
...@@ -115,6 +115,14 @@ var ( ...@@ -115,6 +115,14 @@ var (
Usage: fmt.Sprintf("Deprecated: Use %v instead", flags.NetworkFlagName), Usage: fmt.Sprintf("Deprecated: Use %v instead", flags.NetworkFlagName),
EnvVars: prefixEnvVars("CANNON_NETWORK"), EnvVars: prefixEnvVars("CANNON_NETWORK"),
} }
CannonL2CustomFlag = &cli.BoolFlag{
Name: "cannon-l2-custom",
Usage: "Notify the op-program host that the L2 chain uses custom config to be loaded via the preimage oracle. " +
"WARNING: This is incompatible with on-chain testing and must only be used for testing purposes.",
EnvVars: prefixEnvVars("CANNON_L2_CUSTOM"),
Value: false,
Hidden: true,
}
CannonRollupConfigFlag = &cli.StringFlag{ CannonRollupConfigFlag = &cli.StringFlag{
Name: "cannon-rollup-config", Name: "cannon-rollup-config",
Usage: "Rollup chain parameters (cannon trace type only)", Usage: "Rollup chain parameters (cannon trace type only)",
...@@ -249,6 +257,7 @@ var optionalFlags = []cli.Flag{ ...@@ -249,6 +257,7 @@ var optionalFlags = []cli.Flag{
AdditionalBondClaimants, AdditionalBondClaimants,
GameAllowlistFlag, GameAllowlistFlag,
CannonNetworkFlag, CannonNetworkFlag,
CannonL2CustomFlag,
CannonRollupConfigFlag, CannonRollupConfigFlag,
CannonL2GenesisFlag, CannonL2GenesisFlag,
CannonBinFlag, CannonBinFlag,
...@@ -296,14 +305,17 @@ func CheckCannonFlags(ctx *cli.Context) error { ...@@ -296,14 +305,17 @@ func CheckCannonFlags(ctx *cli.Context) error {
CannonNetworkFlag.Name, flags.NetworkFlagName, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name) CannonNetworkFlag.Name, flags.NetworkFlagName, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name)
} }
if ctx.IsSet(flags.NetworkFlagName) && if ctx.IsSet(flags.NetworkFlagName) &&
(ctx.IsSet(CannonRollupConfigFlag.Name) || ctx.IsSet(CannonL2GenesisFlag.Name)) { (ctx.IsSet(CannonRollupConfigFlag.Name) || ctx.IsSet(CannonL2GenesisFlag.Name) || ctx.Bool(CannonL2CustomFlag.Name)) {
return fmt.Errorf("flag %v can not be used with %v and %v", return fmt.Errorf("flag %v can not be used with %v, %v or %v",
flags.NetworkFlagName, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name) flags.NetworkFlagName, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name, CannonL2CustomFlag.Name)
} }
if ctx.IsSet(CannonNetworkFlag.Name) && if ctx.IsSet(CannonNetworkFlag.Name) &&
(ctx.IsSet(CannonRollupConfigFlag.Name) || ctx.IsSet(CannonL2GenesisFlag.Name)) { (ctx.IsSet(CannonRollupConfigFlag.Name) || ctx.IsSet(CannonL2GenesisFlag.Name) || ctx.Bool(CannonL2CustomFlag.Name)) {
return fmt.Errorf("flag %v can not be used with %v and %v", return fmt.Errorf("flag %v can not be used with %v, %v or %v",
CannonNetworkFlag.Name, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name) CannonNetworkFlag.Name, CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name, CannonL2CustomFlag.Name)
}
if ctx.Bool(CannonL2CustomFlag.Name) && !(ctx.IsSet(CannonRollupConfigFlag.Name) && ctx.IsSet(CannonL2GenesisFlag.Name)) {
return fmt.Errorf("flag %v and %v must be set when %v is true", CannonRollupConfigFlag.Name, CannonL2GenesisFlag.Name, CannonL2CustomFlag.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)
...@@ -563,6 +575,7 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro ...@@ -563,6 +575,7 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro
VmBin: ctx.String(CannonBinFlag.Name), VmBin: ctx.String(CannonBinFlag.Name),
Server: ctx.String(CannonServerFlag.Name), Server: ctx.String(CannonServerFlag.Name),
Network: cannonNetwork, Network: cannonNetwork,
L2Custom: ctx.Bool(CannonL2CustomFlag.Name),
RollupConfigPath: ctx.String(CannonRollupConfigFlag.Name), RollupConfigPath: ctx.String(CannonRollupConfigFlag.Name),
L2GenesisPath: ctx.String(CannonL2GenesisFlag.Name), L2GenesisPath: ctx.String(CannonL2GenesisFlag.Name),
SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name),
......
...@@ -41,6 +41,7 @@ type Config struct { ...@@ -41,6 +41,7 @@ type Config struct {
L2 string L2 string
Server string // Path to the executable that provides the pre-image oracle server Server string // Path to the executable that provides the pre-image oracle server
Network string Network string
L2Custom bool
RollupConfigPath string RollupConfigPath string
L2GenesisPath string L2GenesisPath string
} }
......
...@@ -54,5 +54,8 @@ func (s *OpProgramServerExecutor) OracleCommand(cfg Config, dataDir string, inpu ...@@ -54,5 +54,8 @@ func (s *OpProgramServerExecutor) OracleCommand(cfg Config, dataDir string, inpu
logLevel = "CRIT" logLevel = "CRIT"
} }
args = append(args, "--log.level", logLevel) args = append(args, "--log.level", logLevel)
if cfg.L2Custom {
args = append(args, "--l2.custom")
}
return args, nil return args, nil
} }
...@@ -19,6 +19,12 @@ func TestOpProgramFillHostCommand(t *testing.T) { ...@@ -19,6 +19,12 @@ func TestOpProgramFillHostCommand(t *testing.T) {
toPairs := func(args []string) map[string]string { toPairs := func(args []string) map[string]string {
pairs := make(map[string]string, len(args)/2) pairs := make(map[string]string, len(args)/2)
for i := 0; i < len(args); i += 2 { for i := 0; i < len(args); i += 2 {
// l2.custom is a boolean flag so can't accept a value after a space
if args[i] == "--l2.custom" {
pairs[args[i]] = "true"
i--
continue
}
pairs[args[i]] = args[i+1] pairs[args[i]] = args[i+1]
} }
return pairs return pairs
...@@ -72,6 +78,13 @@ func TestOpProgramFillHostCommand(t *testing.T) { ...@@ -72,6 +78,13 @@ func TestOpProgramFillHostCommand(t *testing.T) {
require.Equal(t, "op-test", pairs["--network"]) require.Equal(t, "op-test", pairs["--network"])
}) })
t.Run("WithL2ChainID", func(t *testing.T) {
pairs := oracleCommand(t, log.LvlInfo, func(c *Config) {
c.L2Custom = true
})
require.Equal(t, "true", pairs["--l2.custom"])
})
t.Run("WithRollupConfigPath", func(t *testing.T) { t.Run("WithRollupConfigPath", func(t *testing.T) {
pairs := oracleCommand(t, log.LvlInfo, func(c *Config) { pairs := oracleCommand(t, log.LvlInfo, func(c *Config) {
c.RollupConfigPath = "rollup.config.json" c.RollupConfigPath = "rollup.config.json"
......
...@@ -190,6 +190,7 @@ func NewChallengerConfig(t *testing.T, sys EndpointProvider, l2NodeName string, ...@@ -190,6 +190,7 @@ func NewChallengerConfig(t *testing.T, sys EndpointProvider, l2NodeName string,
l1Endpoint := sys.NodeEndpoint("l1").RPC() l1Endpoint := sys.NodeEndpoint("l1").RPC()
l1Beacon := sys.L1BeaconEndpoint().RestHTTP() l1Beacon := sys.L1BeaconEndpoint().RestHTTP()
cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, sys.RollupEndpoint(l2NodeName).RPC(), sys.NodeEndpoint(l2NodeName).RPC(), t.TempDir()) cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, sys.RollupEndpoint(l2NodeName).RPC(), sys.NodeEndpoint(l2NodeName).RPC(), t.TempDir())
cfg.Cannon.L2Custom = true
// The devnet can't set the absolute prestate output root because the contracts are deployed in L1 genesis // The devnet can't set the absolute prestate output root because the contracts are deployed in L1 genesis
// before the L2 genesis is known. // before the L2 genesis is known.
cfg.AllowInvalidPrestate = true cfg.AllowInvalidPrestate = true
......
...@@ -269,6 +269,7 @@ func runCannon(t *testing.T, ctx context.Context, sys *e2esys.System, inputs uti ...@@ -269,6 +269,7 @@ func runCannon(t *testing.T, ctx context.Context, sys *e2esys.System, inputs uti
dir := t.TempDir() dir := t.TempDir()
proofsDir := filepath.Join(dir, "cannon-proofs") proofsDir := filepath.Join(dir, "cannon-proofs")
cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, rollupEndpoint, l2Endpoint, dir) cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, rollupEndpoint, l2Endpoint, dir)
cfg.Cannon.L2Custom = true
cannonOpts(&cfg) cannonOpts(&cfg)
logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon") logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon")
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/host/config" "github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/host/types" "github.com/ethereum-optimism/optimism/op-program/host/types"
oplog "github.com/ethereum-optimism/optimism/op-service/log" oplog "github.com/ethereum-optimism/optimism/op-service/log"
...@@ -160,6 +161,30 @@ func TestL2Genesis(t *testing.T) { ...@@ -160,6 +161,30 @@ func TestL2Genesis(t *testing.T) {
}) })
} }
func TestL2ChainID(t *testing.T) {
t.Run("DefaultToNetworkChainID", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg("--network", "op-mainnet"))
require.Equal(t, uint64(10), cfg.L2ChainID)
})
t.Run("DefaultToGenesisChainID", func(t *testing.T) {
rollupCfgFile := writeValidRollupConfig(t)
genesisFile := writeValidGenesis(t)
cfg := configForArgs(t, addRequiredArgsExcept("--network", "--rollup.config", rollupCfgFile, "--l2.genesis", genesisFile))
require.Equal(t, l2GenesisConfig.ChainID.Uint64(), cfg.L2ChainID)
})
t.Run("OverrideToCustomIndicator", func(t *testing.T) {
rollupCfgFile := writeValidRollupConfig(t)
genesisFile := writeValidGenesis(t)
cfg := configForArgs(t, addRequiredArgsExcept("--network",
"--rollup.config", rollupCfgFile,
"--l2.genesis", genesisFile,
"--l2.custom"))
require.Equal(t, client.CustomChainIDIndicator, cfg.L2ChainID)
})
}
func TestL2Head(t *testing.T) { func TestL2Head(t *testing.T) {
t.Run("Required", func(t *testing.T) { t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag l2.head is required", addRequiredArgsExcept("--l2.head")) verifyArgsInvalid(t, "flag l2.head is required", addRequiredArgsExcept("--l2.head"))
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/host/types" "github.com/ethereum-optimism/optimism/op-program/host/types"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
...@@ -37,7 +38,8 @@ var ( ...@@ -37,7 +38,8 @@ var (
) )
type Config struct { type Config struct {
Rollup *rollup.Config L2ChainID uint64
Rollup *rollup.Config
// DataDir is the directory to read/write pre-image data from/to. // DataDir is the directory to read/write pre-image data from/to.
// If not set, an in-memory key-value store is used and fetching data must be enabled // If not set, an in-memory key-value store is used and fetching data must be enabled
DataDir string DataDir string
...@@ -75,9 +77,6 @@ type Config struct { ...@@ -75,9 +77,6 @@ type Config struct {
// ServerMode indicates that the program should run in pre-image server mode and wait for requests. // ServerMode indicates that the program should run in pre-image server mode and wait for requests.
// No client program is run. // No client program is run.
ServerMode bool ServerMode bool
// IsCustomChainConfig indicates that the program uses a custom chain configuration
IsCustomChainConfig bool
} }
func (c *Config) Check() error { func (c *Config) Check() error {
...@@ -131,19 +130,23 @@ func NewConfig( ...@@ -131,19 +130,23 @@ func NewConfig(
l2Claim common.Hash, l2Claim common.Hash,
l2ClaimBlockNum uint64, l2ClaimBlockNum uint64,
) *Config { ) *Config {
_, err := params.LoadOPStackChainConfig(l2Genesis.ChainID.Uint64()) l2ChainID := l2Genesis.ChainID.Uint64()
isCustomConfig := err != nil _, err := params.LoadOPStackChainConfig(l2ChainID)
if err != nil {
// Unknown chain ID so assume it is custom
l2ChainID = client.CustomChainIDIndicator
}
return &Config{ return &Config{
Rollup: rollupCfg, L2ChainID: l2ChainID,
L2ChainConfig: l2Genesis, Rollup: rollupCfg,
L1Head: l1Head, L2ChainConfig: l2Genesis,
L2Head: l2Head, L1Head: l1Head,
L2OutputRoot: l2OutputRoot, L2Head: l2Head,
L2Claim: l2Claim, L2OutputRoot: l2OutputRoot,
L2ClaimBlockNumber: l2ClaimBlockNum, L2Claim: l2Claim,
L1RPCKind: sources.RPCKindStandard, L2ClaimBlockNumber: l2ClaimBlockNum,
IsCustomChainConfig: isCustomConfig, L1RPCKind: sources.RPCKindStandard,
DataFormat: types.DataFormatDirectory, DataFormat: types.DataFormatDirectory,
} }
} }
...@@ -177,7 +180,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { ...@@ -177,7 +180,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
var err error var err error
var rollupCfg *rollup.Config var rollupCfg *rollup.Config
var l2ChainConfig *params.ChainConfig var l2ChainConfig *params.ChainConfig
var isCustomConfig bool var l2ChainID uint64
networkName := ctx.String(flags.Network.Name) networkName := ctx.String(flags.Network.Name)
if networkName != "" { if networkName != "" {
var chainID uint64 var chainID uint64
...@@ -197,6 +200,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { ...@@ -197,6 +200,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load rollup config for chain %d: %w", chainID, err) return nil, fmt.Errorf("failed to load rollup config for chain %d: %w", chainID, err)
} }
l2ChainID = chainID
} else { } else {
l2GenesisPath := ctx.String(flags.L2GenesisPath.Name) l2GenesisPath := ctx.String(flags.L2GenesisPath.Name)
l2ChainConfig, err = loadChainConfigFromGenesis(l2GenesisPath) l2ChainConfig, err = loadChainConfigFromGenesis(l2GenesisPath)
...@@ -210,7 +214,11 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { ...@@ -210,7 +214,11 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
return nil, fmt.Errorf("invalid rollup config: %w", err) return nil, fmt.Errorf("invalid rollup config: %w", err)
} }
isCustomConfig = true l2ChainID = l2ChainConfig.ChainID.Uint64()
if ctx.Bool(flags.L2Custom.Name) {
log.Warn("Using custom chain configuration via preimage oracle. This is not compatible with on-chain execution.")
l2ChainID = client.CustomChainIDIndicator
}
} }
dbFormat := types.DataFormat(ctx.String(flags.DataFormat.Name)) dbFormat := types.DataFormat(ctx.String(flags.DataFormat.Name))
...@@ -218,24 +226,24 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { ...@@ -218,24 +226,24 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
return nil, fmt.Errorf("invalid %w: %v", ErrInvalidDataFormat, dbFormat) return nil, fmt.Errorf("invalid %w: %v", ErrInvalidDataFormat, dbFormat)
} }
return &Config{ return &Config{
Rollup: rollupCfg, L2ChainID: l2ChainID,
DataDir: ctx.String(flags.DataDir.Name), Rollup: rollupCfg,
DataFormat: dbFormat, DataDir: ctx.String(flags.DataDir.Name),
L2URL: ctx.String(flags.L2NodeAddr.Name), DataFormat: dbFormat,
L2ExperimentalURL: ctx.String(flags.L2NodeExperimentalAddr.Name), L2URL: ctx.String(flags.L2NodeAddr.Name),
L2ChainConfig: l2ChainConfig, L2ExperimentalURL: ctx.String(flags.L2NodeExperimentalAddr.Name),
L2Head: l2Head, L2ChainConfig: l2ChainConfig,
L2OutputRoot: l2OutputRoot, L2Head: l2Head,
L2Claim: l2Claim, L2OutputRoot: l2OutputRoot,
L2ClaimBlockNumber: l2ClaimBlockNum, L2Claim: l2Claim,
L1Head: l1Head, L2ClaimBlockNumber: l2ClaimBlockNum,
L1URL: ctx.String(flags.L1NodeAddr.Name), L1Head: l1Head,
L1BeaconURL: ctx.String(flags.L1BeaconAddr.Name), L1URL: ctx.String(flags.L1NodeAddr.Name),
L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name), L1BeaconURL: ctx.String(flags.L1BeaconAddr.Name),
L1RPCKind: sources.RPCProviderKind(ctx.String(flags.L1RPCProviderKind.Name)), L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name),
ExecCmd: ctx.String(flags.Exec.Name), L1RPCKind: sources.RPCProviderKind(ctx.String(flags.L1RPCProviderKind.Name)),
ServerMode: ctx.Bool(flags.Server.Name), ExecCmd: ctx.String(flags.Exec.Name),
IsCustomChainConfig: isCustomConfig, ServerMode: ctx.Bool(flags.Server.Name),
}, nil }, nil
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/host/types" "github.com/ethereum-optimism/optimism/op-program/host/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
...@@ -163,15 +164,15 @@ func TestRejectExecAndServerMode(t *testing.T) { ...@@ -163,15 +164,15 @@ func TestRejectExecAndServerMode(t *testing.T) {
require.ErrorIs(t, err, ErrNoExecInServerMode) require.ErrorIs(t, err, ErrNoExecInServerMode)
} }
func TestIsCustomChainConfig(t *testing.T) { func TestCustomL2ChainID(t *testing.T) {
t.Run("nonCustom", func(t *testing.T) { t.Run("nonCustom", func(t *testing.T) {
cfg := validConfig() cfg := validConfig()
require.Equal(t, cfg.IsCustomChainConfig, false) require.Equal(t, cfg.L2ChainID, validL2Genesis.ChainID.Uint64())
}) })
t.Run("custom", func(t *testing.T) { t.Run("custom", func(t *testing.T) {
customChainConfig := &params.ChainConfig{ChainID: big.NewInt(0x1212121212)} customChainConfig := &params.ChainConfig{ChainID: big.NewInt(0x1212121212)}
cfg := NewConfig(validRollupConfig, customChainConfig, validL1Head, validL2Head, validL2OutputRoot, validL2Claim, validL2ClaimBlockNum) cfg := NewConfig(validRollupConfig, customChainConfig, validL1Head, validL2Head, validL2OutputRoot, validL2Claim, validL2ClaimBlockNum)
require.Equal(t, cfg.IsCustomChainConfig, true) require.Equal(t, cfg.L2ChainID, client.CustomChainIDIndicator)
}) })
} }
......
...@@ -21,6 +21,14 @@ func prefixEnvVars(name string) []string { ...@@ -21,6 +21,14 @@ func prefixEnvVars(name string) []string {
} }
var ( var (
L2Custom = &cli.BoolFlag{
Name: "l2.custom",
Usage: "Override the L2 chain ID to the custom chain indicator for custom chain configuration not present in the client program. " +
"WARNING: This is not compatible with on-chain execution and must only be used for testing.",
EnvVars: prefixEnvVars("L2_CHAINID"),
Value: false,
Hidden: true,
}
RollupConfig = &cli.StringFlag{ RollupConfig = &cli.StringFlag{
Name: "rollup.config", Name: "rollup.config",
Usage: "Rollup chain parameters", Usage: "Rollup chain parameters",
...@@ -131,6 +139,7 @@ var requiredFlags = []cli.Flag{ ...@@ -131,6 +139,7 @@ var requiredFlags = []cli.Flag{
} }
var programFlags = []cli.Flag{ var programFlags = []cli.Flag{
L2Custom,
RollupConfig, RollupConfig,
Network, Network,
DataDir, DataDir,
...@@ -167,6 +176,9 @@ func CheckRequired(ctx *cli.Context) error { ...@@ -167,6 +176,9 @@ func CheckRequired(ctx *cli.Context) error {
if ctx.String(L2GenesisPath.Name) != "" && network != "" { if ctx.String(L2GenesisPath.Name) != "" && network != "" {
return fmt.Errorf("cannot specify both %s and %s", L2GenesisPath.Name, Network.Name) return fmt.Errorf("cannot specify both %s and %s", L2GenesisPath.Name, Network.Name)
} }
if ctx.Bool(L2Custom.Name) && rollupConfig == "" {
return fmt.Errorf("flag %s cannot be used with named networks", L2Custom.Name)
}
for _, flag := range requiredFlags { for _, flag := range requiredFlags {
if !ctx.IsSet(flag.Names()[0]) { if !ctx.IsSet(flag.Names()[0]) {
return fmt.Errorf("flag %s is required", flag.Names()[0]) return fmt.Errorf("flag %s is required", flag.Names()[0])
......
...@@ -38,22 +38,14 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) { ...@@ -38,22 +38,14 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
case l2ClaimBlockNumberKey: case l2ClaimBlockNumberKey:
return binary.BigEndian.AppendUint64(nil, s.config.L2ClaimBlockNumber), nil return binary.BigEndian.AppendUint64(nil, s.config.L2ClaimBlockNumber), nil
case l2ChainIDKey: case l2ChainIDKey:
// The CustomChainIDIndicator informs the client to rely on the L2ChainConfigKey to return binary.BigEndian.AppendUint64(nil, s.config.L2ChainID), nil
// read the chain config. Otherwise, it'll attempt to read a non-existent hardcoded chain config
var chainID uint64
if s.config.IsCustomChainConfig {
chainID = client.CustomChainIDIndicator
} else {
chainID = s.config.L2ChainConfig.ChainID.Uint64()
}
return binary.BigEndian.AppendUint64(nil, chainID), nil
case l2ChainConfigKey: case l2ChainConfigKey:
if !s.config.IsCustomChainConfig { if s.config.L2ChainID != client.CustomChainIDIndicator {
return nil, ErrNotFound return nil, ErrNotFound
} }
return json.Marshal(s.config.L2ChainConfig) return json.Marshal(s.config.L2ChainConfig)
case rollupKey: case rollupKey:
if !s.config.IsCustomChainConfig { if s.config.L2ChainID != client.CustomChainIDIndicator {
return nil, ErrNotFound return nil, ErrNotFound
} }
return json.Marshal(s.config.Rollup) return json.Marshal(s.config.Rollup)
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
preimage "github.com/ethereum-optimism/optimism/op-preimage" preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/host/config" "github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
...@@ -15,6 +16,7 @@ import ( ...@@ -15,6 +16,7 @@ import (
func TestLocalPreimageSource(t *testing.T) { func TestLocalPreimageSource(t *testing.T) {
cfg := &config.Config{ cfg := &config.Config{
L2ChainID: 86,
Rollup: chaincfg.OPSepolia(), Rollup: chaincfg.OPSepolia(),
L1Head: common.HexToHash("0x1111"), L1Head: common.HexToHash("0x1111"),
L2OutputRoot: common.HexToHash("0x2222"), L2OutputRoot: common.HexToHash("0x2222"),
...@@ -32,7 +34,7 @@ func TestLocalPreimageSource(t *testing.T) { ...@@ -32,7 +34,7 @@ func TestLocalPreimageSource(t *testing.T) {
{"L2OutputRoot", l2OutputRootKey, cfg.L2OutputRoot.Bytes()}, {"L2OutputRoot", l2OutputRootKey, cfg.L2OutputRoot.Bytes()},
{"L2Claim", l2ClaimKey, cfg.L2Claim.Bytes()}, {"L2Claim", l2ClaimKey, cfg.L2Claim.Bytes()},
{"L2ClaimBlockNumber", l2ClaimBlockNumberKey, binary.BigEndian.AppendUint64(nil, cfg.L2ClaimBlockNumber)}, {"L2ClaimBlockNumber", l2ClaimBlockNumberKey, binary.BigEndian.AppendUint64(nil, cfg.L2ClaimBlockNumber)},
{"L2ChainID", l2ChainIDKey, binary.BigEndian.AppendUint64(nil, cfg.L2ChainConfig.ChainID.Uint64())}, {"L2ChainID", l2ChainIDKey, binary.BigEndian.AppendUint64(nil, 86)},
{"Rollup", rollupKey, nil}, // Only available for custom chain configs {"Rollup", rollupKey, nil}, // Only available for custom chain configs
{"ChainConfig", l2ChainConfigKey, nil}, // Only available for custom chain configs {"ChainConfig", l2ChainConfigKey, nil}, // Only available for custom chain configs
{"Unknown", preimage.LocalIndexKey(1000).PreimageKey(), nil}, {"Unknown", preimage.LocalIndexKey(1000).PreimageKey(), nil},
...@@ -52,13 +54,13 @@ func TestLocalPreimageSource(t *testing.T) { ...@@ -52,13 +54,13 @@ func TestLocalPreimageSource(t *testing.T) {
func TestGetCustomChainConfigPreimages(t *testing.T) { func TestGetCustomChainConfigPreimages(t *testing.T) {
cfg := &config.Config{ cfg := &config.Config{
Rollup: chaincfg.OPSepolia(), Rollup: chaincfg.OPSepolia(),
IsCustomChainConfig: true, L2ChainID: client.CustomChainIDIndicator,
L1Head: common.HexToHash("0x1111"), L1Head: common.HexToHash("0x1111"),
L2OutputRoot: common.HexToHash("0x2222"), L2OutputRoot: common.HexToHash("0x2222"),
L2Claim: common.HexToHash("0x3333"), L2Claim: common.HexToHash("0x3333"),
L2ClaimBlockNumber: 1234, L2ClaimBlockNumber: 1234,
L2ChainConfig: params.SepoliaChainConfig, L2ChainConfig: params.SepoliaChainConfig,
} }
source := NewLocalPreimageSource(cfg) source := NewLocalPreimageSource(cfg)
actualRollup, err := source.Get(rollupKey) actualRollup, err := source.Get(rollupKey)
......
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