From b21ac42bc721257aa6637f6d029c1da559e3068b Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 4 Oct 2023 14:03:56 +0200 Subject: [PATCH 1/2] superchain: beta feature flag for overriding chain-config with superchain-registry --- cmd/geth/main.go | 1 + cmd/utils/flags.go | 6 ++++++ core/gen_genesis.go | 30 +++++++++++++++--------------- core/genesis.go | 18 +++++++++++++++++- core/superchain_test.go | 34 ++++++++++++++++++++++++++++++++++ eth/backend.go | 1 + eth/ethconfig/config.go | 3 +++ eth/ethconfig/gen_config.go | 6 ++++++ 8 files changed, 83 insertions(+), 16 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 8836a3ad30..27142cd136 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -153,6 +153,7 @@ var ( utils.RollupDisableTxPoolGossipFlag, utils.RollupComputePendingBlock, utils.RollupHaltOnIncompatibleProtocolVersionFlag, + utils.RollupSuperchainUpgradesFlag, configFileFlag, }, utils.NetworkFlags, utils.DatabasePathFlags) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b4f6703a59..92bae84e19 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -918,6 +918,11 @@ var ( Usage: "Opt-in option to halt on incompatible protocol version requirements of the given level (major/minor/patch/none), as signaled through the Engine API by the rollup node", Category: flags.RollupCategory, } + RollupSuperchainUpgradesFlag = &cli.BoolFlag{ + Name: "beta.rollup.superchain-upgrades", + Usage: "Beta feature: apply superchain-registry config changes to the local chain-configuration", + Category: flags.EthCategory, + } // Metrics flags MetricsEnabledFlag = &cli.BoolFlag{ @@ -1884,6 +1889,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { cfg.RollupDisableTxPoolGossip = ctx.Bool(RollupDisableTxPoolGossipFlag.Name) cfg.RollupDisableTxPoolAdmission = cfg.RollupSequencerHTTP != "" && !ctx.Bool(RollupEnableTxPoolAdmissionFlag.Name) cfg.RollupHaltOnIncompatibleProtocolVersion = ctx.String(RollupHaltOnIncompatibleProtocolVersionFlag.Name) + cfg.ApplySuperchainUpgrades = ctx.Bool(RollupSuperchainUpgradesFlag.Name) // Override any default configs for hard coded networks. switch { case ctx.Bool(MainnetFlag.Name): diff --git a/core/gen_genesis.go b/core/gen_genesis.go index c36c0506f7..bd2a069b54 100644 --- a/core/gen_genesis.go +++ b/core/gen_genesis.go @@ -18,22 +18,22 @@ var _ = (*genesisSpecMarshaling)(nil) // MarshalJSON marshals as JSON. func (g Genesis) MarshalJSON() ([]byte, error) { type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce math.HexOrDecimal64 `json:"nonce"` - Timestamp math.HexOrDecimal64 `json:"timestamp"` - ExtraData hexutil.Bytes `json:"extraData"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash common.Hash `json:"mixHash"` - Coinbase common.Address `json:"coinbase"` - Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` - Number math.HexOrDecimal64 `json:"number"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + Config *params.ChainConfig `json:"config"` + Nonce math.HexOrDecimal64 `json:"nonce"` + Timestamp math.HexOrDecimal64 `json:"timestamp"` + ExtraData hexutil.Bytes `json:"extraData"` + GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + Mixhash common.Hash `json:"mixHash"` + Coinbase common.Address `json:"coinbase"` + Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` + Number math.HexOrDecimal64 `json:"number"` + GasUsed math.HexOrDecimal64 `json:"gasUsed"` + ParentHash common.Hash `json:"parentHash"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` - StateHash *common.Hash `json:"stateHash,omitempty"` + StateHash *common.Hash `json:"stateHash,omitempty"` } var enc Genesis enc.Config = g.Config @@ -78,7 +78,7 @@ func (g *Genesis) UnmarshalJSON(input []byte) error { BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` - StateHash *common.Hash `json:"stateHash,omitempty"` + StateHash *common.Hash `json:"stateHash,omitempty"` } var dec Genesis if err := json.Unmarshal(input, &dec); err != nil { diff --git a/core/genesis.go b/core/genesis.go index 8f77110db9..2b5e0c2dfd 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -25,6 +25,8 @@ import ( "math/big" "strings" + "github.com/ethereum-optimism/superchain-registry/superchain" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" @@ -288,7 +290,8 @@ type ChainOverrides struct { OverrideCancun *uint64 OverrideVerkle *uint64 // optimism - OverrideOptimismCanyon *uint64 + OverrideOptimismCanyon *uint64 + ApplySuperchainUpgrades bool } // SetupGenesisBlock writes or updates the genesis block in db. @@ -314,6 +317,19 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen } applyOverrides := func(config *params.ChainConfig) { if config != nil { + // If applying the superchain-registry to a known OP-Stack chain, + // then override the local chain-config with that from the registry. + if overrides != nil && overrides.ApplySuperchainUpgrades && config.IsOptimism() && config.ChainID != nil && genesis.Config.ChainID.IsUint64() { + if _, ok := superchain.OPChains[config.ChainID.Uint64()]; ok { + conf, err := params.LoadOPStackChainConfig(config.ChainID.Uint64()) + if err != nil { + log.Warn("failed to load chain config from superchain-registry, skipping override", "err", err, "chain_id", config.ChainID) + } else { + *config = *conf + } + } + } + if config.IsOptimism() && config.ChainID != nil && config.ChainID.Cmp(big.NewInt(params.OPGoerliChainID)) == 0 { // Apply Optimism Goerli regolith time config.RegolithTime = ¶ms.OptimismGoerliRegolithTime diff --git a/core/superchain_test.go b/core/superchain_test.go index fa3246250a..936b344c30 100644 --- a/core/superchain_test.go +++ b/core/superchain_test.go @@ -4,6 +4,9 @@ import ( "testing" "github.com/ethereum-optimism/superchain-registry/superchain" + + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/trie" ) func TestOPStackGenesis(t *testing.T) { @@ -15,3 +18,34 @@ func TestOPStackGenesis(t *testing.T) { t.Logf("chain: %d, genesis block hash: %s", id, gen.ToBlock().Hash()) } } + +func TestRegistryChainConfigOverride(t *testing.T) { + db := rawdb.NewMemoryDatabase() + genesis, err := LoadOPStackGenesis(10) + if err != nil { + t.Fatal(err) + } + if genesis.Config.RegolithTime == nil { + t.Fatal("expected non-nil regolith time") + } + genesis.Config.RegolithTime = nil + + // initialize the DB + tdb := trie.NewDatabase(db, newDbConfig(rawdb.PathScheme)) + genesis.MustCommit(db, tdb) + bl := genesis.ToBlock() + rawdb.WriteCanonicalHash(db, bl.Hash(), 0) + rawdb.WriteBlock(db, bl) + + // create chain config, even with incomplete genesis input: the chain config should be corrected + chainConfig, _, err := SetupGenesisBlockWithOverride(db, tdb, genesis, &ChainOverrides{ + ApplySuperchainUpgrades: true, + }) + if err != nil { + t.Fatal(err) + } + // check if we have a corrected chain config + if chainConfig.RegolithTime == nil { + t.Fatal("expected regolith time to be corrected, but time is still nil") + } +} diff --git a/eth/backend.go b/eth/backend.go index 25e2c3e811..18082ad19d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -215,6 +215,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if config.OverrideOptimismCanyon != nil { overrides.OverrideOptimismCanyon = config.OverrideOptimismCanyon } + overrides.ApplySuperchainUpgrades = config.ApplySuperchainUpgrades eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory) if err != nil { return nil, err diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 40f21b749e..ad6fd31079 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -170,6 +170,9 @@ type Config struct { OverrideOptimismCanyon *uint64 `toml:",omitempty"` + // ApplySuperchainUpgrades requests the node to load chain-configuration from the superchain-registry. + ApplySuperchainUpgrades bool `toml:",omitempty"` + RollupSequencerHTTP string RollupHistoricalRPC string RollupHistoricalRPCTimeout time.Duration diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index dea5a74282..27ade8781d 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -57,6 +57,7 @@ func (c Config) MarshalTOML() (interface{}, error) { OverrideCancun *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` OverrideOptimismCanyon *uint64 `toml:",omitempty"` + ApplySuperchainUpgrades bool `toml:",omitempty"` RollupSequencerHTTP string RollupHistoricalRPC string RollupHistoricalRPCTimeout time.Duration @@ -105,6 +106,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.OverrideCancun = c.OverrideCancun enc.OverrideVerkle = c.OverrideVerkle enc.OverrideOptimismCanyon = c.OverrideOptimismCanyon + enc.ApplySuperchainUpgrades = c.ApplySuperchainUpgrades enc.RollupSequencerHTTP = c.RollupSequencerHTTP enc.RollupHistoricalRPC = c.RollupHistoricalRPC enc.RollupHistoricalRPCTimeout = c.RollupHistoricalRPCTimeout @@ -157,6 +159,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { OverrideCancun *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` OverrideOptimismCanyon *uint64 `toml:",omitempty"` + ApplySuperchainUpgrades *bool `toml:",omitempty"` RollupSequencerHTTP *string RollupHistoricalRPC *string RollupHistoricalRPCTimeout *time.Duration @@ -288,6 +291,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.OverrideOptimismCanyon != nil { c.OverrideOptimismCanyon = dec.OverrideOptimismCanyon } + if dec.ApplySuperchainUpgrades != nil { + c.ApplySuperchainUpgrades = *dec.ApplySuperchainUpgrades + } if dec.RollupSequencerHTTP != nil { c.RollupSequencerHTTP = *dec.RollupSequencerHTTP } From 80ac0fae240653d410f88a1f26b248b67d502d68 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 4 Oct 2023 18:12:36 +0200 Subject: [PATCH 2/2] core: test regolith time in genesis setup from superchain-registry --- core/superchain_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/superchain_test.go b/core/superchain_test.go index 936b344c30..9959374bdd 100644 --- a/core/superchain_test.go +++ b/core/superchain_test.go @@ -28,6 +28,7 @@ func TestRegistryChainConfigOverride(t *testing.T) { if genesis.Config.RegolithTime == nil { t.Fatal("expected non-nil regolith time") } + expectedRegolithTime := *genesis.Config.RegolithTime genesis.Config.RegolithTime = nil // initialize the DB @@ -47,5 +48,7 @@ func TestRegistryChainConfigOverride(t *testing.T) { // check if we have a corrected chain config if chainConfig.RegolithTime == nil { t.Fatal("expected regolith time to be corrected, but time is still nil") + } else if *chainConfig.RegolithTime != expectedRegolithTime { + t.Fatalf("expected regolith time to be %d, but got %d", expectedRegolithTime, *chainConfig.RegolithTime) } }