diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index 0c611a5d8d35..42036ba372e9 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -2,8 +2,10 @@ package rollup import ( "context" + "encoding/json" "errors" "fmt" + "io" "math/big" "time" @@ -649,6 +651,15 @@ func (c *Config) LogDescription(log log.Logger, l2Chains map[string]string) { ) } +func (c *Config) ParseRollupConfig(in io.Reader) error { + dec := json.NewDecoder(in) + dec.DisallowUnknownFields() + if err := dec.Decode(c); err != nil { + return fmt.Errorf("failed to decode rollup config: %w", err) + } + return nil +} + func fmtForkTimeOrUnset(v *uint64) string { if v == nil { return "(not configured)" diff --git a/op-program/Makefile b/op-program/Makefile index 80ad1e3bf580..bb5a0fa59ac4 100644 --- a/op-program/Makefile +++ b/op-program/Makefile @@ -51,7 +51,7 @@ test: verify-sepolia: op-program-host op-program-client env GO111MODULE=on go run ./verify/sepolia/cmd/sepolia.go --l1 $$SEPOLIA_L1URL --l1.beacon $$SEPOLIA_BEACON_URL --l2 $$SEPOLIA_L2URL --datadir /tmp/test-sepolia -verify-devnet: +verify-devnet: op-program-host op-program-client env GO111MODULE=on go run ./verify/devnet/cmd/devnet.go --l1 http://localhost:8545 --l1.beacon http://localhost:5052 --l2 http://localhost:9545 --datadir /tmp/test-devnet capture-mainnet-genesis: op-program-host op-program-client diff --git a/op-program/chainconfig/chaincfg.go b/op-program/chainconfig/chaincfg.go index 513d6d2a2ef8..839207299a5c 100644 --- a/op-program/chainconfig/chaincfg.go +++ b/op-program/chainconfig/chaincfg.go @@ -37,13 +37,10 @@ func rollupConfigByChainID(chainID uint64, customChainFS embed.FS) (*rollup.Conf } else if err != nil { return nil, fmt.Errorf("failed to get rollup config for chain ID %d: %w", chainID, err) } - dec := json.NewDecoder(file) - dec.DisallowUnknownFields() + defer file.Close() + var customRollupConfig rollup.Config - if err := dec.Decode(&customRollupConfig); err != nil { - return nil, fmt.Errorf("failed to parse rollup config for chain ID %d: %w", chainID, err) - } - return &customRollupConfig, nil + return &customRollupConfig, customRollupConfig.ParseRollupConfig(file) } func ChainConfigByChainID(chainID uint64) (*params.ChainConfig, error) { diff --git a/op-program/host/config/config.go b/op-program/host/config/config.go index c04f959a8b7d..bb9f9d868e45 100644 --- a/op-program/host/config/config.go +++ b/op-program/host/config/config.go @@ -6,11 +6,12 @@ import ( "fmt" "os" "slices" + "strconv" "github.com/ethereum-optimism/optimism/op-node/chaincfg" + "github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/host/types" - opnode "github.com/ethereum-optimism/optimism/op-node" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-program/host/flags" "github.com/ethereum-optimism/optimism/op-service/sources" @@ -146,10 +147,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { if err := flags.CheckRequired(ctx); err != nil { return nil, err } - rollupCfg, err := opnode.NewRollupConfigFromCLI(log, ctx) - if err != nil { - return nil, err - } + l2Head := common.HexToHash(ctx.String(flags.L2Head.Name)) if l2Head == (common.Hash{}) { return nil, ErrInvalidL2Head @@ -171,27 +169,46 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { if l1Head == (common.Hash{}) { return nil, ErrInvalidL1Head } - l2GenesisPath := ctx.String(flags.L2GenesisPath.Name) + + var err error + var rollupCfg *rollup.Config var l2ChainConfig *params.ChainConfig var isCustomConfig bool - if l2GenesisPath == "" { - networkName := ctx.String(flags.Network.Name) - ch := chaincfg.ChainByName(networkName) - if ch == nil { - return nil, fmt.Errorf("flag %s is required for network %s", flags.L2GenesisPath.Name, networkName) + networkName := ctx.String(flags.Network.Name) + if networkName != "" { + var chainID uint64 + if chainID, err = strconv.ParseUint(networkName, 10, 64); err != nil { + ch := chaincfg.ChainByName(networkName) + if ch == nil { + return nil, fmt.Errorf("invalid network: %q", networkName) + } + chainID = ch.ChainID } - cfg, err := params.LoadOPStackChainConfig(ch.ChainID) + + l2ChainConfig, err = chainconfig.ChainConfigByChainID(chainID) if err != nil { - return nil, fmt.Errorf("failed to load chain config for chain %d: %w", ch.ChainID, err) + return nil, fmt.Errorf("failed to load chain config for chain %d: %w", chainID, err) + } + rollupCfg, err = chainconfig.RollupConfigByChainID(chainID) + if err != nil { + return nil, fmt.Errorf("failed to load rollup config for chain %d: %w", chainID, err) } - l2ChainConfig = cfg } else { + l2GenesisPath := ctx.String(flags.L2GenesisPath.Name) l2ChainConfig, err = loadChainConfigFromGenesis(l2GenesisPath) + if err != nil { + return nil, fmt.Errorf("invalid genesis: %w", err) + } + + rollupConfigPath := ctx.String(flags.RollupConfig.Name) + rollupCfg, err = loadRollupConfig(rollupConfigPath) + if err != nil { + return nil, fmt.Errorf("invalid rollup config: %w", err) + } + isCustomConfig = true } - if err != nil { - return nil, fmt.Errorf("invalid genesis: %w", err) - } + dbFormat := types.DataFormat(ctx.String(flags.DataFormat.Name)) if !slices.Contains(types.SupportedDataFormats, dbFormat) { return nil, fmt.Errorf("invalid %w: %v", ErrInvalidDataFormat, dbFormat) @@ -229,3 +246,14 @@ func loadChainConfigFromGenesis(path string) (*params.ChainConfig, error) { } return genesis.Config, nil } + +func loadRollupConfig(rollupConfigPath string) (*rollup.Config, error) { + file, err := os.Open(rollupConfigPath) + if err != nil { + return nil, fmt.Errorf("failed to read rollup config: %w", err) + } + defer file.Close() + + var rollupConfig rollup.Config + return &rollupConfig, rollupConfig.ParseRollupConfig(file) +} diff --git a/op-program/host/flags/flags.go b/op-program/host/flags/flags.go index 5eb633c7202f..15489cf22c94 100644 --- a/op-program/host/flags/flags.go +++ b/op-program/host/flags/flags.go @@ -158,6 +158,9 @@ func CheckRequired(ctx *cli.Context) error { if network == "" && ctx.String(L2GenesisPath.Name) == "" { return fmt.Errorf("flag %s is required for custom networks", L2GenesisPath.Name) } + if ctx.String(L2GenesisPath.Name) != "" && network != "" { + return fmt.Errorf("cannot specify both %s and %s", L2GenesisPath.Name, Network.Name) + } for _, flag := range requiredFlags { if !ctx.IsSet(flag.Names()[0]) { return fmt.Errorf("flag %s is required", flag.Names()[0]) diff --git a/op-program/verify/devnet/cmd/devnet.go b/op-program/verify/devnet/cmd/devnet.go index f955debc5c0e..4ec63bf50bc1 100644 --- a/op-program/verify/devnet/cmd/devnet.go +++ b/op-program/verify/devnet/cmd/devnet.go @@ -43,8 +43,8 @@ func main() { os.Exit(2) } - // Apply the custom configs by running op-program in the same process - runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "", 901, true) + // Apply the custom configs by running op-program + runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "901", 901, false) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Failed to create runner: %v\n", err.Error()) os.Exit(1)