Commit 837eac37 authored by OptimismBot's avatar OptimismBot Committed by GitHub

Merge pull request #5534 from ethereum-optimism/aj/fpp-goerli-config

op-program: Embed goerli L2 chain config
parents 77bab8b9 9b85d9b4
...@@ -21,19 +21,20 @@ var ( ...@@ -21,19 +21,20 @@ var (
l2HeadValue = common.HexToHash("0x222222").Hex() l2HeadValue = common.HexToHash("0x222222").Hex()
l2ClaimValue = common.HexToHash("0x333333").Hex() l2ClaimValue = common.HexToHash("0x333333").Hex()
l2ClaimBlockNumber = uint64(1203) l2ClaimBlockNumber = uint64(1203)
l2Genesis = core.DefaultGoerliGenesisBlock() // Note: This is actually the L1 goerli genesis config. Just using it as an arbitrary, valid genesis config
l2GenesisConfig = l2Genesis.Config l2Genesis = core.DefaultGoerliGenesisBlock()
l2GenesisConfig = l2Genesis.Config
) )
func TestLogLevel(t *testing.T) { func TestLogLevel(t *testing.T) {
t.Run("RejectInvalid", func(t *testing.T) { t.Run("RejectInvalid", func(t *testing.T) {
verifyArgsInvalid(t, "unknown level: foo", addRequiredArgs(t, "--log.level=foo")) verifyArgsInvalid(t, "unknown level: foo", addRequiredArgs("--log.level=foo"))
}) })
for _, lvl := range []string{"trace", "debug", "info", "error", "crit"} { for _, lvl := range []string{"trace", "debug", "info", "error", "crit"} {
lvl := lvl lvl := lvl
t.Run("AcceptValid_"+lvl, func(t *testing.T) { t.Run("AcceptValid_"+lvl, func(t *testing.T) {
logger, _, err := runWithArgs(addRequiredArgs(t, "--log.level", lvl)) logger, _, err := runWithArgs(addRequiredArgs("--log.level", lvl))
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, logger) require.NotNil(t, logger)
}) })
...@@ -41,10 +42,10 @@ func TestLogLevel(t *testing.T) { ...@@ -41,10 +42,10 @@ func TestLogLevel(t *testing.T) {
} }
func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t)) cfg := configForArgs(t, addRequiredArgs())
defaultCfg := config.NewConfig( defaultCfg := config.NewConfig(
&chaincfg.Goerli, &chaincfg.Goerli,
l2GenesisConfig, config.OPGoerliChainConfig,
common.HexToHash(l1HeadValue), common.HexToHash(l1HeadValue),
common.HexToHash(l2HeadValue), common.HexToHash(l2HeadValue),
common.HexToHash(l2ClaimValue), common.HexToHash(l2ClaimValue),
...@@ -54,26 +55,22 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { ...@@ -54,26 +55,22 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
func TestNetwork(t *testing.T) { func TestNetwork(t *testing.T) {
t.Run("Unknown", func(t *testing.T) { t.Run("Unknown", func(t *testing.T) {
verifyArgsInvalid(t, "invalid network bar", replaceRequiredArg(t, "--network", "bar")) verifyArgsInvalid(t, "invalid network bar", replaceRequiredArg("--network", "bar"))
}) })
t.Run("Required", func(t *testing.T) { t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag rollup.config or network is required", addRequiredArgsExcept(t, "--network")) verifyArgsInvalid(t, "flag rollup.config or network is required", addRequiredArgsExcept("--network"))
}) })
t.Run("DisallowNetworkAndRollupConfig", func(t *testing.T) { t.Run("DisallowNetworkAndRollupConfig", func(t *testing.T) {
verifyArgsInvalid(t, "cannot specify both rollup.config and network", addRequiredArgs(t, "--rollup.config=foo")) verifyArgsInvalid(t, "cannot specify both rollup.config and network", addRequiredArgs("--rollup.config=foo"))
}) })
t.Run("RollupConfig", func(t *testing.T) { t.Run("RollupConfig", func(t *testing.T) {
dir := t.TempDir() configFile := writeValidRollupConfig(t)
configJson, err := json.Marshal(chaincfg.Goerli) genesisFile := writeValidGenesis(t)
require.NoError(t, err)
configFile := dir + "/config.json" cfg := configForArgs(t, addRequiredArgsExcept("--network", "--rollup.config", configFile, "--l2.genesis", genesisFile))
err = os.WriteFile(configFile, configJson, os.ModePerm)
require.NoError(t, err)
cfg := configForArgs(t, addRequiredArgsExcept(t, "--network", "--rollup.config", configFile))
require.Equal(t, chaincfg.Goerli, *cfg.Rollup) require.Equal(t, chaincfg.Goerli, *cfg.Rollup)
}) })
...@@ -81,7 +78,14 @@ func TestNetwork(t *testing.T) { ...@@ -81,7 +78,14 @@ func TestNetwork(t *testing.T) {
name := name name := name
expected := cfg expected := cfg
t.Run("Network_"+name, func(t *testing.T) { t.Run("Network_"+name, func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg(t, "--network", name)) args := replaceRequiredArg("--network", name)
if name == "beta-1" {
// No built-in config for beta-1 which is fine as it's no longer in use.
// Newly added named networks should hook up the L2 chain config
genesisFile := writeValidGenesis(t)
args = append(args, "--l2.genesis", genesisFile)
}
cfg := configForArgs(t, args)
require.Equal(t, expected, *cfg.Rollup) require.Equal(t, expected, *cfg.Rollup)
}) })
} }
...@@ -89,146 +93,158 @@ func TestNetwork(t *testing.T) { ...@@ -89,146 +93,158 @@ func TestNetwork(t *testing.T) {
func TestDataDir(t *testing.T) { func TestDataDir(t *testing.T) {
expected := "/tmp/mainTestDataDir" expected := "/tmp/mainTestDataDir"
cfg := configForArgs(t, addRequiredArgs(t, "--datadir", expected)) cfg := configForArgs(t, addRequiredArgs("--datadir", expected))
require.Equal(t, expected, cfg.DataDir) require.Equal(t, expected, cfg.DataDir)
} }
func TestL2(t *testing.T) { func TestL2(t *testing.T) {
expected := "https://example.com:8545" expected := "https://example.com:8545"
cfg := configForArgs(t, addRequiredArgs(t, "--l2", expected)) cfg := configForArgs(t, addRequiredArgs("--l2", expected))
require.Equal(t, expected, cfg.L2URL) require.Equal(t, expected, cfg.L2URL)
} }
func TestL2Genesis(t *testing.T) { func TestL2Genesis(t *testing.T) {
t.Run("Required", func(t *testing.T) { t.Run("RequiredWithCustomNetwork", func(t *testing.T) {
verifyArgsInvalid(t, "flag l2.genesis is required", addRequiredArgsExcept(t, "--l2.genesis")) rollupCfgFile := writeValidRollupConfig(t)
verifyArgsInvalid(t, "flag l2.genesis is required", addRequiredArgsExcept("--network", "--rollup.config", rollupCfgFile))
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg(t, "--l2.genesis", writeValidGenesis(t))) rollupCfgFile := writeValidRollupConfig(t)
genesisFile := writeValidGenesis(t)
cfg := configForArgs(t, addRequiredArgsExcept("--network", "--rollup.config", rollupCfgFile, "--l2.genesis", genesisFile))
require.Equal(t, l2GenesisConfig, cfg.L2ChainConfig) require.Equal(t, l2GenesisConfig, cfg.L2ChainConfig)
}) })
t.Run("NotRequiredForGoerli", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg("--network", "goerli"))
require.Equal(t, config.OPGoerliChainConfig, cfg.L2ChainConfig)
})
t.Run("RequiredForNamedNetworkWithNoL2ChainConfig", func(t *testing.T) {
verifyArgsInvalid(t, "flag l2.genesis is required", replaceRequiredArg("--network", "beta-1"))
})
} }
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(t, "--l2.head")) verifyArgsInvalid(t, "flag l2.head is required", addRequiredArgsExcept("--l2.head"))
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg(t, "--l2.head", l2HeadValue)) cfg := configForArgs(t, replaceRequiredArg("--l2.head", l2HeadValue))
require.Equal(t, common.HexToHash(l2HeadValue), cfg.L2Head) require.Equal(t, common.HexToHash(l2HeadValue), cfg.L2Head)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
verifyArgsInvalid(t, config.ErrInvalidL2Head.Error(), replaceRequiredArg(t, "--l2.head", "something")) verifyArgsInvalid(t, config.ErrInvalidL2Head.Error(), replaceRequiredArg("--l2.head", "something"))
}) })
} }
func TestL1Head(t *testing.T) { func TestL1Head(t *testing.T) {
t.Run("Required", func(t *testing.T) { t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag l1.head is required", addRequiredArgsExcept(t, "--l1.head")) verifyArgsInvalid(t, "flag l1.head is required", addRequiredArgsExcept("--l1.head"))
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg(t, "--l1.head", l1HeadValue)) cfg := configForArgs(t, replaceRequiredArg("--l1.head", l1HeadValue))
require.Equal(t, common.HexToHash(l1HeadValue), cfg.L1Head) require.Equal(t, common.HexToHash(l1HeadValue), cfg.L1Head)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
verifyArgsInvalid(t, config.ErrInvalidL1Head.Error(), replaceRequiredArg(t, "--l1.head", "something")) verifyArgsInvalid(t, config.ErrInvalidL1Head.Error(), replaceRequiredArg("--l1.head", "something"))
}) })
} }
func TestL1(t *testing.T) { func TestL1(t *testing.T) {
expected := "https://example.com:8545" expected := "https://example.com:8545"
cfg := configForArgs(t, addRequiredArgs(t, "--l1", expected)) cfg := configForArgs(t, addRequiredArgs("--l1", expected))
require.Equal(t, expected, cfg.L1URL) require.Equal(t, expected, cfg.L1URL)
} }
func TestL1TrustRPC(t *testing.T) { func TestL1TrustRPC(t *testing.T) {
t.Run("DefaultFalse", func(t *testing.T) { t.Run("DefaultFalse", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t)) cfg := configForArgs(t, addRequiredArgs())
require.False(t, cfg.L1TrustRPC) require.False(t, cfg.L1TrustRPC)
}) })
t.Run("Enabled", func(t *testing.T) { t.Run("Enabled", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t, "--l1.trustrpc")) cfg := configForArgs(t, addRequiredArgs("--l1.trustrpc"))
require.True(t, cfg.L1TrustRPC) require.True(t, cfg.L1TrustRPC)
}) })
t.Run("EnabledWithArg", func(t *testing.T) { t.Run("EnabledWithArg", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t, "--l1.trustrpc=true")) cfg := configForArgs(t, addRequiredArgs("--l1.trustrpc=true"))
require.True(t, cfg.L1TrustRPC) require.True(t, cfg.L1TrustRPC)
}) })
t.Run("Disabled", func(t *testing.T) { t.Run("Disabled", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t, "--l1.trustrpc=false")) cfg := configForArgs(t, addRequiredArgs("--l1.trustrpc=false"))
require.False(t, cfg.L1TrustRPC) require.False(t, cfg.L1TrustRPC)
}) })
} }
func TestL1RPCKind(t *testing.T) { func TestL1RPCKind(t *testing.T) {
t.Run("DefaultBasic", func(t *testing.T) { t.Run("DefaultBasic", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t)) cfg := configForArgs(t, addRequiredArgs())
require.Equal(t, sources.RPCKindBasic, cfg.L1RPCKind) require.Equal(t, sources.RPCKindBasic, cfg.L1RPCKind)
}) })
for _, kind := range sources.RPCProviderKinds { for _, kind := range sources.RPCProviderKinds {
t.Run(kind.String(), func(t *testing.T) { t.Run(kind.String(), func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t, "--l1.rpckind", kind.String())) cfg := configForArgs(t, addRequiredArgs("--l1.rpckind", kind.String()))
require.Equal(t, kind, cfg.L1RPCKind) require.Equal(t, kind, cfg.L1RPCKind)
}) })
} }
t.Run("RequireLowercase", func(t *testing.T) { t.Run("RequireLowercase", func(t *testing.T) {
verifyArgsInvalid(t, "rpc kind", addRequiredArgs(t, "--l1.rpckind", "AlChemY")) verifyArgsInvalid(t, "rpc kind", addRequiredArgs("--l1.rpckind", "AlChemY"))
}) })
t.Run("UnknownKind", func(t *testing.T) { t.Run("UnknownKind", func(t *testing.T) {
verifyArgsInvalid(t, "\"foo\"", addRequiredArgs(t, "--l1.rpckind", "foo")) verifyArgsInvalid(t, "\"foo\"", addRequiredArgs("--l1.rpckind", "foo"))
}) })
} }
func TestL2Claim(t *testing.T) { func TestL2Claim(t *testing.T) {
t.Run("Required", func(t *testing.T) { t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag l2.claim is required", addRequiredArgsExcept(t, "--l2.claim")) verifyArgsInvalid(t, "flag l2.claim is required", addRequiredArgsExcept("--l2.claim"))
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg(t, "--l2.claim", l2ClaimValue)) cfg := configForArgs(t, replaceRequiredArg("--l2.claim", l2ClaimValue))
require.EqualValues(t, common.HexToHash(l2ClaimValue), cfg.L2Claim) require.EqualValues(t, common.HexToHash(l2ClaimValue), cfg.L2Claim)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
verifyArgsInvalid(t, config.ErrInvalidL2Claim.Error(), replaceRequiredArg(t, "--l2.claim", "something")) verifyArgsInvalid(t, config.ErrInvalidL2Claim.Error(), replaceRequiredArg("--l2.claim", "something"))
}) })
} }
func TestL2BlockNumber(t *testing.T) { func TestL2BlockNumber(t *testing.T) {
t.Run("Required", func(t *testing.T) { t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag l2.blocknumber is required", addRequiredArgsExcept(t, "--l2.blocknumber")) verifyArgsInvalid(t, "flag l2.blocknumber is required", addRequiredArgsExcept("--l2.blocknumber"))
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg(t, "--l2.blocknumber", strconv.FormatUint(l2ClaimBlockNumber, 10))) cfg := configForArgs(t, replaceRequiredArg("--l2.blocknumber", strconv.FormatUint(l2ClaimBlockNumber, 10)))
require.EqualValues(t, l2ClaimBlockNumber, cfg.L2ClaimBlockNumber) require.EqualValues(t, l2ClaimBlockNumber, cfg.L2ClaimBlockNumber)
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
verifyArgsInvalid(t, "invalid value \"something\" for flag -l2.blocknumber", replaceRequiredArg(t, "--l2.blocknumber", "something")) verifyArgsInvalid(t, "invalid value \"something\" for flag -l2.blocknumber", replaceRequiredArg("--l2.blocknumber", "something"))
}) })
} }
func TestDetached(t *testing.T) { func TestDetached(t *testing.T) {
t.Run("DefaultFalse", func(t *testing.T) { t.Run("DefaultFalse", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t)) cfg := configForArgs(t, addRequiredArgs())
require.False(t, cfg.Detached) require.False(t, cfg.Detached)
}) })
t.Run("Enabled", func(t *testing.T) { t.Run("Enabled", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t, "--detached")) cfg := configForArgs(t, addRequiredArgs("--detached"))
require.True(t, cfg.Detached) require.True(t, cfg.Detached)
}) })
t.Run("EnabledWithArg", func(t *testing.T) { t.Run("EnabledWithArg", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t, "--detached=true")) cfg := configForArgs(t, addRequiredArgs("--detached=true"))
require.True(t, cfg.Detached) require.True(t, cfg.Detached)
}) })
t.Run("Disabled", func(t *testing.T) { t.Run("Disabled", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(t, "--detached=false")) cfg := configForArgs(t, addRequiredArgs("--detached=false"))
require.False(t, cfg.Detached) require.False(t, cfg.Detached)
}) })
} }
...@@ -256,35 +272,33 @@ func runWithArgs(cliArgs []string) (log.Logger, *config.Config, error) { ...@@ -256,35 +272,33 @@ func runWithArgs(cliArgs []string) (log.Logger, *config.Config, error) {
return logger, cfg, err return logger, cfg, err
} }
func addRequiredArgs(t *testing.T, args ...string) []string { func addRequiredArgs(args ...string) []string {
req := requiredArgs(t) req := requiredArgs()
combined := toArgList(req) combined := toArgList(req)
return append(combined, args...) return append(combined, args...)
} }
func addRequiredArgsExcept(t *testing.T, name string, optionalArgs ...string) []string { func addRequiredArgsExcept(name string, optionalArgs ...string) []string {
req := requiredArgs(t) req := requiredArgs()
delete(req, name) delete(req, name)
return append(toArgList(req), optionalArgs...) return append(toArgList(req), optionalArgs...)
} }
func replaceRequiredArg(t *testing.T, name string, value string) []string { func replaceRequiredArg(name string, value string) []string {
req := requiredArgs(t) req := requiredArgs()
req[name] = value req[name] = value
return toArgList(req) return toArgList(req)
} }
// requiredArgs returns map of argument names to values which are the minimal arguments required // requiredArgs returns map of argument names to values which are the minimal arguments required
// to create a valid Config // to create a valid Config
func requiredArgs(t *testing.T) map[string]string { func requiredArgs() map[string]string {
genesisFile := writeValidGenesis(t)
return map[string]string{ return map[string]string{
"--network": "goerli", "--network": "goerli",
"--l1.head": l1HeadValue, "--l1.head": l1HeadValue,
"--l2.head": l2HeadValue, "--l2.head": l2HeadValue,
"--l2.claim": l2ClaimValue, "--l2.claim": l2ClaimValue,
"--l2.blocknumber": strconv.FormatUint(l2ClaimBlockNumber, 10), "--l2.blocknumber": strconv.FormatUint(l2ClaimBlockNumber, 10),
"--l2.genesis": genesisFile,
} }
} }
...@@ -297,6 +311,15 @@ func writeValidGenesis(t *testing.T) string { ...@@ -297,6 +311,15 @@ func writeValidGenesis(t *testing.T) string {
return genesisFile return genesisFile
} }
func writeValidRollupConfig(t *testing.T) string {
dir := t.TempDir()
j, err := json.Marshal(chaincfg.Goerli)
require.NoError(t, err)
cfgFile := dir + "/rollup.json"
require.NoError(t, os.WriteFile(cfgFile, j, 0666))
return cfgFile
}
func toArgList(req map[string]string) []string { func toArgList(req map[string]string) []string {
var combined []string var combined []string
for name, value := range req { for name, value := range req {
......
package config
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
var OPGoerliChainConfig = &params.ChainConfig{
ChainID: big.NewInt(420),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: false,
EIP150Block: big.NewInt(0),
EIP150Hash: common.Hash{},
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(4061224),
ArrowGlacierBlock: big.NewInt(4061224),
GrayGlacierBlock: big.NewInt(4061224),
MergeNetsplitBlock: big.NewInt(4061224),
BedrockBlock: big.NewInt(4061224),
RegolithTime: &params.OptimismGoerliRegolithTime,
TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true,
Optimism: &params.OptimismConfig{
EIP1559Elasticity: 10,
EIP1559Denominator: 50,
},
}
var L2ChainConfigsByName = map[string]*params.ChainConfig{
"goerli": OPGoerliChainConfig,
}
...@@ -123,7 +123,16 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) { ...@@ -123,7 +123,16 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) {
return nil, ErrInvalidL1Head return nil, ErrInvalidL1Head
} }
l2GenesisPath := ctx.GlobalString(flags.L2GenesisPath.Name) l2GenesisPath := ctx.GlobalString(flags.L2GenesisPath.Name)
l2ChainConfig, err := loadChainConfigFromGenesis(l2GenesisPath) var l2ChainConfig *params.ChainConfig
if l2GenesisPath == "" {
networkName := ctx.GlobalString(flags.Network.Name)
l2ChainConfig = L2ChainConfigsByName[networkName]
if l2ChainConfig == nil {
return nil, fmt.Errorf("flag %s is required for network %s", flags.L2GenesisPath.Name, networkName)
}
} else {
l2ChainConfig, err = loadChainConfigFromGenesis(l2GenesisPath)
}
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid genesis: %w", err) return nil, fmt.Errorf("invalid genesis: %w", err)
} }
......
...@@ -96,13 +96,13 @@ var requiredFlags = []cli.Flag{ ...@@ -96,13 +96,13 @@ var requiredFlags = []cli.Flag{
L2Head, L2Head,
L2Claim, L2Claim,
L2BlockNumber, L2BlockNumber,
L2GenesisPath,
} }
var programFlags = []cli.Flag{ var programFlags = []cli.Flag{
RollupConfig, RollupConfig,
Network, Network,
DataDir, DataDir,
L2NodeAddr, L2NodeAddr,
L2GenesisPath,
L1NodeAddr, L1NodeAddr,
L1TrustRPC, L1TrustRPC,
L1RPCProviderKind, L1RPCProviderKind,
...@@ -124,6 +124,9 @@ func CheckRequired(ctx *cli.Context) error { ...@@ -124,6 +124,9 @@ func CheckRequired(ctx *cli.Context) error {
if rollupConfig != "" && network != "" { if rollupConfig != "" && network != "" {
return fmt.Errorf("cannot specify both %s and %s", RollupConfig.Name, Network.Name) return fmt.Errorf("cannot specify both %s and %s", RollupConfig.Name, Network.Name)
} }
if network == "" && ctx.GlobalString(L2GenesisPath.Name) == "" {
return fmt.Errorf("flag %s is required for custom networks", L2GenesisPath.Name)
}
for _, flag := range requiredFlags { for _, flag := range requiredFlags {
if !ctx.IsSet(flag.GetName()) { if !ctx.IsSet(flag.GetName()) {
return fmt.Errorf("flag %s is required", flag.GetName()) return fmt.Errorf("flag %s is required", flag.GetName())
......
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