From d911f819604b34ab1dcd3569a38a42f36119d7e6 Mon Sep 17 00:00:00 2001 From: Michael de Hoog Date: Sun, 12 Jan 2025 15:20:31 -1000 Subject: [PATCH] Add Jovian activation configuration --- go.mod | 4 ++- go.sum | 4 +-- op-batcher/batcher/sync_actions.go | 2 +- op-chain-ops/genesis/config.go | 34 ++++++++++++++---- op-chain-ops/genesis/genesis.go | 1 + op-chain-ops/genesis/layer_two.go | 1 + op-chain-ops/interopgen/recipe.go | 2 ++ op-e2e/e2eutils/setup.go | 20 ++++++----- op-e2e/system/e2esys/setup.go | 2 ++ op-node/rollup/chain_spec.go | 7 ++++ op-node/rollup/chain_spec_test.go | 11 ++++-- op-node/rollup/superchain.go | 2 ++ op-node/rollup/types.go | 22 ++++++++++++ op-node/rollup/types_test.go | 17 +++++++-- op-service/eth/types.go | 35 ++++++++++--------- op-service/sources/types.go | 35 ++++++++++--------- op-wheel/commands.go | 3 ++ .../contracts-bedrock/scripts/L2Genesis.s.sol | 5 +++ .../scripts/deploy/DeployConfig.s.sol | 4 +++ .../scripts/libraries/Config.sol | 9 +++-- .../snapshots/semver-lock.json | 32 ++++++++++------- 21 files changed, 182 insertions(+), 70 deletions(-) diff --git a/go.mod b/go.mod index 9e6bfb4c301c1..7372545393e3d 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/fatih/color v1.18.0 github.com/fsnotify/fsnotify v1.8.0 github.com/go-task/slim-sprig/v3 v3.0.0 + github.com/golang-jwt/jwt/v4 v4.5.1 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/go-cmp v0.6.0 github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8 @@ -113,7 +114,6 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20241009165004-a3522334989c // indirect @@ -255,6 +255,8 @@ require ( replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101411.5-rc.1 +replace github.com/ethereum-optimism/superchain-registry/superchain => github.com/mdehoog/superchain-registry/superchain v0.0.0-20250112212108-52eef42cce64 + //replace github.com/ethereum/go-ethereum => ../go-ethereum // replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain diff --git a/go.sum b/go.sum index fcb7bcaf939cd..8cd91aebf01f1 100644 --- a/go.sum +++ b/go.sum @@ -192,8 +192,6 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= github.com/ethereum-optimism/op-geth v1.101411.5-rc.1 h1:8fhtAycm/+xugWev5jInUxgF0Wdc29PxSODZXca6Qi8= github.com/ethereum-optimism/op-geth v1.101411.5-rc.1/go.mod h1:n6VeI9cKFxmXCauD7Ji9lgTAg+2TYGLZu5AXgVJB4tk= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241213092551-33a63fce8214 h1:94dIMFDCafAQ3FCC1pryuhgfZc1jPoDwK4xSMOPshN8= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241213092551-33a63fce8214/go.mod h1:9feO8jcL5OZ1tvRjEfNAHz4Aggvd6373l+ZxmZZAyZs= github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= @@ -526,6 +524,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mdehoog/superchain-registry/superchain v0.0.0-20250112212108-52eef42cce64 h1:d3oeJzX40Omcv0QLdWwhqy/+UaomFz+jxehZczVKDHw= +github.com/mdehoog/superchain-registry/superchain v0.0.0-20250112212108-52eef42cce64/go.mod h1:9feO8jcL5OZ1tvRjEfNAHz4Aggvd6373l+ZxmZZAyZs= github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU= github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= diff --git a/op-batcher/batcher/sync_actions.go b/op-batcher/batcher/sync_actions.go index 76cdf846ad918..0e8555828b87e 100644 --- a/op-batcher/batcher/sync_actions.go +++ b/op-batcher/batcher/sync_actions.go @@ -33,7 +33,7 @@ func (s syncActions) String() string { // computeSyncActions determines the actions that should be taken based on the inputs provided. The inputs are the current // state of the batcher (blocks and channels), the new sync status, and the previous current L1 block. The actions are returned // in a struct specifying the number of blocks to prune, the number of channels to prune, whether to wait for node sync, the block -// range to load into the local state, and whether to clear the state entirely. Returns an boolean indicating if the sequencer is out of sync. +// range to load into the local state, and whether to clear the state entirely. Returns a boolean indicating if the sequencer is out of sync. func computeSyncActions[T channelStatuser](newSyncStatus eth.SyncStatus, prevCurrentL1 eth.L1BlockRef, blocks queue.Queue[*types.Block], channels []T, l log.Logger) (syncActions, bool) { // PART 1: Initial checks on the sync status diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index 5df3f4510feda..118f3dfc1e65b 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -348,6 +348,9 @@ type UpgradeScheduleDeployConfig struct { // L2GenesisIsthmusTimeOffset is the number of seconds after genesis block that the Isthmus hard fork activates. // Set it to 0 to activate at genesis. Nil to disable Isthmus. L2GenesisIsthmusTimeOffset *hexutil.Uint64 `json:"l2GenesisIsthmusTimeOffset,omitempty"` + // L2GenesisJovianTimeOffset is the number of seconds after genesis block that the Jovian hard fork activates. + // Set it to 0 to activate at genesis. Nil to disable Jovian. + L2GenesisJovianTimeOffset *hexutil.Uint64 `json:"l2GenesisJovianTimeOffset,omitempty"` // L2GenesisInteropTimeOffset is the number of seconds after genesis block that the Interop hard fork activates. // Set it to 0 to activate at genesis. Nil to disable Interop. L2GenesisInteropTimeOffset *hexutil.Uint64 `json:"l2GenesisInteropTimeOffset,omitempty"` @@ -390,6 +393,8 @@ func (d *UpgradeScheduleDeployConfig) ForkTimeOffset(fork rollup.ForkName) *uint return (*uint64)(d.L2GenesisHoloceneTimeOffset) case rollup.Isthmus: return (*uint64)(d.L2GenesisIsthmusTimeOffset) + case rollup.Jovian: + return (*uint64)(d.L2GenesisJovianTimeOffset) case rollup.Interop: return (*uint64)(d.L2GenesisInteropTimeOffset) default: @@ -415,6 +420,8 @@ func (d *UpgradeScheduleDeployConfig) SetForkTimeOffset(fork rollup.ForkName, of d.L2GenesisHoloceneTimeOffset = (*hexutil.Uint64)(offset) case rollup.Isthmus: d.L2GenesisIsthmusTimeOffset = (*hexutil.Uint64)(offset) + case rollup.Jovian: + d.L2GenesisJovianTimeOffset = (*hexutil.Uint64)(offset) case rollup.Interop: d.L2GenesisInteropTimeOffset = (*hexutil.Uint64)(offset) default: @@ -483,6 +490,10 @@ func (d *UpgradeScheduleDeployConfig) IsthmusTime(genesisTime uint64) *uint64 { return offsetToUpgradeTime(d.L2GenesisIsthmusTimeOffset, genesisTime) } +func (d *UpgradeScheduleDeployConfig) JovianTime(genesisTime uint64) *uint64 { + return offsetToUpgradeTime(d.L2GenesisJovianTimeOffset, genesisTime) +} + func (d *UpgradeScheduleDeployConfig) InteropTime(genesisTime uint64) *uint64 { return offsetToUpgradeTime(d.L2GenesisInteropTimeOffset, genesisTime) } @@ -516,6 +527,7 @@ func (d *UpgradeScheduleDeployConfig) forks() []Fork { {L2GenesisTimeOffset: d.L2GenesisGraniteTimeOffset, Name: string(L2AllocsGranite)}, {L2GenesisTimeOffset: d.L2GenesisHoloceneTimeOffset, Name: string(L2AllocsHolocene)}, {L2GenesisTimeOffset: d.L2GenesisIsthmusTimeOffset, Name: string(L2AllocsIsthmus)}, + {L2GenesisTimeOffset: d.L2GenesisJovianTimeOffset, Name: string(L2AllocsJovian)}, } } @@ -996,13 +1008,8 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Header, l2GenesisBlockHa Hash: l2GenesisBlockHash, Number: l2GenesisBlockNumber, }, - L2Time: l1StartBlock.Time, - SystemConfig: eth.SystemConfig{ - BatcherAddr: d.BatchSenderAddress, - Overhead: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(d.GasPriceOracleOverhead))), - Scalar: eth.Bytes32(d.FeeScalar()), - GasLimit: uint64(d.L2GenesisBlockGasLimit), - }, + L2Time: l1StartBlock.Time, + SystemConfig: d.GenesisSystemConfig(), }, BlockTime: d.L2BlockTime, MaxSequencerDrift: d.MaxSequencerDrift, @@ -1021,12 +1028,25 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Header, l2GenesisBlockHa GraniteTime: d.GraniteTime(l1StartTime), HoloceneTime: d.HoloceneTime(l1StartTime), IsthmusTime: d.IsthmusTime(l1StartTime), + JovianTime: d.JovianTime(l1StartTime), InteropTime: d.InteropTime(l1StartTime), ProtocolVersionsAddress: d.ProtocolVersionsProxy, AltDAConfig: altDA, }, nil } +// GenesisSystemConfig converts a DeployConfig to a eth.SystemConfig. If Ecotone is active at genesis, the +// Overhead value is considered a noop. +func (d *DeployConfig) GenesisSystemConfig() eth.SystemConfig { + cfg := eth.SystemConfig{ + BatcherAddr: d.BatchSenderAddress, + Overhead: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(d.GasPriceOracleOverhead))), + Scalar: d.FeeScalar(), + GasLimit: uint64(d.L2GenesisBlockGasLimit), + } + return cfg +} + // NewDeployConfig reads a config file given a path on the filesystem. func NewDeployConfig(path string) (*DeployConfig, error) { file, err := os.ReadFile(path) diff --git a/op-chain-ops/genesis/genesis.go b/op-chain-ops/genesis/genesis.go index 16f182ffbb47c..785e7acb21f5a 100644 --- a/op-chain-ops/genesis/genesis.go +++ b/op-chain-ops/genesis/genesis.go @@ -71,6 +71,7 @@ func NewL2Genesis(config *DeployConfig, l1StartHeader *types.Header) (*core.Gene GraniteTime: config.GraniteTime(l1StartTime), HoloceneTime: config.HoloceneTime(l1StartTime), IsthmusTime: config.IsthmusTime(l1StartTime), + JovianTime: config.JovianTime(l1StartTime), InteropTime: config.InteropTime(l1StartTime), Optimism: ¶ms.OptimismConfig{ EIP1559Denominator: eip1559Denom, diff --git a/op-chain-ops/genesis/layer_two.go b/op-chain-ops/genesis/layer_two.go index 1e3dd2281d174..264f9d27bd245 100644 --- a/op-chain-ops/genesis/layer_two.go +++ b/op-chain-ops/genesis/layer_two.go @@ -28,6 +28,7 @@ const ( L2AllocsGranite L2AllocsMode = "granite" L2AllocsHolocene L2AllocsMode = "holocene" L2AllocsIsthmus L2AllocsMode = "isthmus" + L2AllocsJovian L2AllocsMode = "jovian" ) var ( diff --git a/op-chain-ops/interopgen/recipe.go b/op-chain-ops/interopgen/recipe.go index e70c69e9f481a..a0f9688403b6b 100644 --- a/op-chain-ops/interopgen/recipe.go +++ b/op-chain-ops/interopgen/recipe.go @@ -234,6 +234,8 @@ func InteropL2DevConfig(l1ChainID, l2ChainID uint64, addrs devkeys.Addresses) (* L2GenesisFjordTimeOffset: new(hexutil.Uint64), L2GenesisGraniteTimeOffset: new(hexutil.Uint64), L2GenesisHoloceneTimeOffset: new(hexutil.Uint64), + L2GenesisIsthmusTimeOffset: new(hexutil.Uint64), + L2GenesisJovianTimeOffset: new(hexutil.Uint64), L2GenesisInteropTimeOffset: new(hexutil.Uint64), L1CancunTimeOffset: new(hexutil.Uint64), UseInterop: true, diff --git a/op-e2e/e2eutils/setup.go b/op-e2e/e2eutils/setup.go index dbc9ecea25b9c..f72b2de1b633b 100644 --- a/op-e2e/e2eutils/setup.go +++ b/op-e2e/e2eutils/setup.go @@ -6,7 +6,6 @@ import ( "path" "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -205,6 +204,8 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * FjordTime: deployConf.FjordTime(uint64(deployConf.L1GenesisBlockTimestamp)), GraniteTime: deployConf.GraniteTime(uint64(deployConf.L1GenesisBlockTimestamp)), HoloceneTime: deployConf.HoloceneTime(uint64(deployConf.L1GenesisBlockTimestamp)), + IsthmusTime: deployConf.IsthmusTime(uint64(deployConf.L1GenesisBlockTimestamp)), + JovianTime: deployConf.JovianTime(uint64(deployConf.L1GenesisBlockTimestamp)), InteropTime: deployConf.InteropTime(uint64(deployConf.L1GenesisBlockTimestamp)), AltDAConfig: pcfg, } @@ -226,16 +227,13 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * } func SystemConfigFromDeployConfig(deployConfig *genesis.DeployConfig) eth.SystemConfig { - return eth.SystemConfig{ - BatcherAddr: deployConfig.BatchSenderAddress, - Overhead: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(deployConfig.GasPriceOracleOverhead))), - Scalar: eth.Bytes32(deployConfig.FeeScalar()), - GasLimit: uint64(deployConfig.L2GenesisBlockGasLimit), - } + return deployConfig.GenesisSystemConfig() } func ApplyDeployConfigForks(deployConfig *genesis.DeployConfig) { - isHolocene := os.Getenv("OP_E2E_USE_HOLOCENE") == "true" + isJovian := os.Getenv("OP_E2E_USE_JOVIAN") == "true" + isIsthmus := isJovian || os.Getenv("OP_E2E_USE_ISTHMUS") == "true" + isHolocene := isIsthmus || os.Getenv("OP_E2E_USE_HOLOCENE") == "true" isGranite := isHolocene || os.Getenv("OP_E2E_USE_GRANITE") == "true" isFjord := isGranite || os.Getenv("OP_E2E_USE_FJORD") == "true" isEcotone := isFjord || os.Getenv("OP_E2E_USE_ECOTONE") == "true" @@ -255,6 +253,12 @@ func ApplyDeployConfigForks(deployConfig *genesis.DeployConfig) { if isHolocene { deployConfig.L2GenesisHoloceneTimeOffset = new(hexutil.Uint64) } + if isIsthmus { + deployConfig.L2GenesisIsthmusTimeOffset = new(hexutil.Uint64) + } + if isJovian { + deployConfig.L2GenesisJovianTimeOffset = new(hexutil.Uint64) + } // Canyon and lower is activated by default deployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64) deployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64) diff --git a/op-e2e/system/e2esys/setup.go b/op-e2e/system/e2esys/setup.go index a54a46d1e5db2..3810e572215f2 100644 --- a/op-e2e/system/e2esys/setup.go +++ b/op-e2e/system/e2esys/setup.go @@ -638,6 +638,8 @@ func (cfg SystemConfig) Start(t *testing.T, startOpts ...StartOption) (*System, FjordTime: cfg.DeployConfig.FjordTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), GraniteTime: cfg.DeployConfig.GraniteTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), HoloceneTime: cfg.DeployConfig.HoloceneTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), + IsthmusTime: cfg.DeployConfig.IsthmusTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), + JovianTime: cfg.DeployConfig.JovianTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy, AltDAConfig: rollupAltDAConfig, diff --git a/op-node/rollup/chain_spec.go b/op-node/rollup/chain_spec.go index 936bb2b17dfa3..80dcf14127aa7 100644 --- a/op-node/rollup/chain_spec.go +++ b/op-node/rollup/chain_spec.go @@ -42,6 +42,7 @@ const ( Granite ForkName = "granite" Holocene ForkName = "holocene" Isthmus ForkName = "isthmus" + Jovian ForkName = "jovian" Interop ForkName = "interop" // ADD NEW FORKS TO AllForks BELOW! None ForkName = "none" @@ -57,6 +58,7 @@ var AllForks = []ForkName{ Granite, Holocene, Isthmus, + Jovian, Interop, // ADD NEW FORKS HERE! } @@ -195,6 +197,9 @@ func (s *ChainSpec) CheckForkActivation(log log.Logger, block eth.L2BlockRef) { if s.config.IsIsthmus(block.Time) { s.currentFork = Isthmus } + if s.config.IsJovian(block.Time) { + s.currentFork = Jovian + } if s.config.IsInterop(block.Time) { s.currentFork = Interop } @@ -221,6 +226,8 @@ func (s *ChainSpec) CheckForkActivation(log log.Logger, block eth.L2BlockRef) { foundActivationBlock = s.config.IsHoloceneActivationBlock(block.Time) case Isthmus: foundActivationBlock = s.config.IsIsthmusActivationBlock(block.Time) + case Jovian: + foundActivationBlock = s.config.IsJovianActivationBlock(block.Time) case Interop: foundActivationBlock = s.config.IsInteropActivationBlock(block.Time) } diff --git a/op-node/rollup/chain_spec_test.go b/op-node/rollup/chain_spec_test.go index 4c466b4e261df..97c88e6ced4d1 100644 --- a/op-node/rollup/chain_spec_test.go +++ b/op-node/rollup/chain_spec_test.go @@ -47,6 +47,7 @@ var testConfig = Config{ GraniteTime: u64ptr(60), HoloceneTime: u64ptr(70), IsthmusTime: u64ptr(80), + JovianTime: u64ptr(90), InteropTime: nil, BatchInboxAddress: common.HexToAddress("0xff00000000000000000000000000000000000010"), DepositContractAddress: common.HexToAddress("0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"), @@ -191,10 +192,16 @@ func TestCheckForkActivation(t *testing.T) { expectedCurrentFork: Isthmus, expectedLog: "Detected hardfork activation block", }, + { + name: "Jovian activation", + block: eth.L2BlockRef{Time: 90, Number: 11, Hash: common.Hash{0xb}}, + expectedCurrentFork: Jovian, + expectedLog: "Detected hardfork activation block", + }, { name: "No more hardforks", - block: eth.L2BlockRef{Time: 700, Number: 11, Hash: common.Hash{0xb}}, - expectedCurrentFork: Isthmus, + block: eth.L2BlockRef{Time: 700, Number: 12, Hash: common.Hash{0xc}}, + expectedCurrentFork: Jovian, expectedLog: "", }, } diff --git a/op-node/rollup/superchain.go b/op-node/rollup/superchain.go index ef6ed1f51676b..c7b8a64dda517 100644 --- a/op-node/rollup/superchain.go +++ b/op-node/rollup/superchain.go @@ -92,6 +92,8 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) { FjordTime: chConfig.FjordTime, GraniteTime: chConfig.GraniteTime, HoloceneTime: chConfig.HoloceneTime, + IsthmusTime: chConfig.IsthmusTime, + JovianTime: chConfig.JovianTime, BatchInboxAddress: common.Address(chConfig.BatchInboxAddr), DepositContractAddress: common.Address(addrs.OptimismPortalProxy), L1SystemConfigAddress: common.Address(addrs.SystemConfigProxy), diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index 6201fc6be9c64..c895f77ed4fb3 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -124,6 +124,10 @@ type Config struct { // Active if IsthmusTime != nil && L2 block timestamp >= *IsthmusTime, inactive otherwise. IsthmusTime *uint64 `json:"isthmus_time,omitempty"` + // JovianTime sets the activation time of the Jovian network upgrade. + // Active if JovianTime != nil && L2 block timestamp >= *JovianTime, inactive otherwise. + JovianTime *uint64 `json:"jovian_time,omitempty"` + // InteropTime sets the activation time for an experimental feature-set, activated like a hardfork. // Active if InteropTime != nil && L2 block timestamp >= *InteropTime, inactive otherwise. InteropTime *uint64 `json:"interop_time,omitempty"` @@ -417,6 +421,11 @@ func (c *Config) IsIsthmus(timestamp uint64) bool { return c.IsthmusTime != nil && timestamp >= *c.IsthmusTime } +// IsJovian returns true if the Jovian hardfork is active at or past the given timestamp. +func (c *Config) IsJovian(timestamp uint64) bool { + return c.JovianTime != nil && timestamp >= *c.JovianTime +} + // IsInterop returns true if the Interop hardfork is active at or past the given timestamp. func (c *Config) IsInterop(timestamp uint64) bool { return c.InteropTime != nil && timestamp >= *c.InteropTime @@ -480,6 +489,14 @@ func (c *Config) IsIsthmusActivationBlock(l2BlockTime uint64) bool { !c.IsIsthmus(l2BlockTime-c.BlockTime) } +// IsJovianActivationBlock returns whether the specified block is the first block subject to the +// Jovian upgrade. +func (c *Config) IsJovianActivationBlock(l2BlockTime uint64) bool { + return c.IsJovian(l2BlockTime) && + l2BlockTime >= c.BlockTime && + !c.IsJovian(l2BlockTime-c.BlockTime) +} + func (c *Config) IsInteropActivationBlock(l2BlockTime uint64) bool { return c.IsInterop(l2BlockTime) && l2BlockTime >= c.BlockTime && @@ -503,6 +520,9 @@ func (c *Config) ActivateAtGenesis(hardfork ForkName) { case Interop: c.InteropTime = new(uint64) fallthrough + case Jovian: + c.JovianTime = new(uint64) + fallthrough case Isthmus: c.IsthmusTime = new(uint64) fallthrough @@ -646,6 +666,7 @@ func (c *Config) Description(l2Chains map[string]string) string { banner += fmt.Sprintf(" - Granite: %s\n", fmtForkTimeOrUnset(c.GraniteTime)) banner += fmt.Sprintf(" - Holocene: %s\n", fmtForkTimeOrUnset(c.HoloceneTime)) banner += fmt.Sprintf(" - Isthmus: %s\n", fmtForkTimeOrUnset(c.IsthmusTime)) + banner += fmt.Sprintf(" - Jovian: %s\n", fmtForkTimeOrUnset(c.JovianTime)) banner += fmt.Sprintf(" - Interop: %s\n", fmtForkTimeOrUnset(c.InteropTime)) // Report the protocol version banner += fmt.Sprintf("Node supports up to OP-Stack Protocol Version: %s\n", OPStackSupport) @@ -683,6 +704,7 @@ func (c *Config) LogDescription(log log.Logger, l2Chains map[string]string) { "granite_time", fmtForkTimeOrUnset(c.GraniteTime), "holocene_time", fmtForkTimeOrUnset(c.HoloceneTime), "isthmus_time", fmtForkTimeOrUnset(c.IsthmusTime), + "jovian_time", fmtForkTimeOrUnset(c.JovianTime), "interop_time", fmtForkTimeOrUnset(c.InteropTime), "alt_da", c.AltDAConfig != nil, ) diff --git a/op-node/rollup/types_test.go b/op-node/rollup/types_test.go index dc7b5ded16730..e6e8ca4fe2fda 100644 --- a/op-node/rollup/types_test.go +++ b/op-node/rollup/types_test.go @@ -185,7 +185,9 @@ func TestRandomConfigDescription(t *testing.T) { config.HoloceneTime = &h i := uint64(1677119341) config.IsthmusTime = &i - it := uint64(1677119342) + j := uint64(1677119342) + config.JovianTime = &j + it := uint64(1677119343) config.InteropTime = &it out := config.Description(nil) @@ -290,6 +292,15 @@ func TestActivations(t *testing.T) { return c.IsIsthmus(t) }, }, + { + name: "Jovian", + setUpgradeTime: func(t *uint64, c *Config) { + c.JovianTime = t + }, + checkEnabled: func(t uint64, c *Config) bool { + return c.IsJovian(t) + }, + }, { name: "Interop", setUpgradeTime: func(t *uint64, c *Config) { @@ -562,7 +573,8 @@ func TestConfig_Check(t *testing.T) { graniteTime := uint64(6) holoceneTime := uint64(7) isthmusTime := uint64(8) - interopTime := uint64(9) + jovianTime := uint64(9) + interopTime := uint64(10) cfg.RegolithTime = ®olithTime cfg.CanyonTime = &canyonTime cfg.DeltaTime = &deltaTime @@ -571,6 +583,7 @@ func TestConfig_Check(t *testing.T) { cfg.GraniteTime = &graniteTime cfg.HoloceneTime = &holoceneTime cfg.IsthmusTime = &isthmusTime + cfg.JovianTime = &jovianTime cfg.InteropTime = &interopTime }, expectedErr: nil, diff --git a/op-service/eth/types.go b/op-service/eth/types.go index 122e9a4df7833..b1a3b5998bede 100644 --- a/op-service/eth/types.go +++ b/op-service/eth/types.go @@ -231,6 +231,8 @@ type ExecutionPayload struct { BlobGasUsed *Uint64Quantity `json:"blobGasUsed,omitempty"` // Nil if not present (Bedrock, Canyon, Delta) ExcessBlobGas *Uint64Quantity `json:"excessBlobGas,omitempty"` + // Nil if not present (Bedrock, Canyon, Delta, Ecotone, Fjord, Granite, Holocene) + WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"` } func (payload *ExecutionPayload) ID() BlockID { @@ -307,22 +309,23 @@ func BlockAsPayload(bl *types.Block, shanghaiTime *uint64) (*ExecutionPayload, e } payload := &ExecutionPayload{ - ParentHash: bl.ParentHash(), - FeeRecipient: bl.Coinbase(), - StateRoot: Bytes32(bl.Root()), - ReceiptsRoot: Bytes32(bl.ReceiptHash()), - LogsBloom: Bytes256(bl.Bloom()), - PrevRandao: Bytes32(bl.MixDigest()), - BlockNumber: Uint64Quantity(bl.NumberU64()), - GasLimit: Uint64Quantity(bl.GasLimit()), - GasUsed: Uint64Quantity(bl.GasUsed()), - Timestamp: Uint64Quantity(bl.Time()), - ExtraData: bl.Extra(), - BaseFeePerGas: Uint256Quantity(*baseFee), - BlockHash: bl.Hash(), - Transactions: opaqueTxs, - ExcessBlobGas: (*Uint64Quantity)(bl.ExcessBlobGas()), - BlobGasUsed: (*Uint64Quantity)(bl.BlobGasUsed()), + ParentHash: bl.ParentHash(), + FeeRecipient: bl.Coinbase(), + StateRoot: Bytes32(bl.Root()), + ReceiptsRoot: Bytes32(bl.ReceiptHash()), + LogsBloom: Bytes256(bl.Bloom()), + PrevRandao: Bytes32(bl.MixDigest()), + BlockNumber: Uint64Quantity(bl.NumberU64()), + GasLimit: Uint64Quantity(bl.GasLimit()), + GasUsed: Uint64Quantity(bl.GasUsed()), + Timestamp: Uint64Quantity(bl.Time()), + ExtraData: bl.Extra(), + BaseFeePerGas: Uint256Quantity(*baseFee), + BlockHash: bl.Hash(), + Transactions: opaqueTxs, + ExcessBlobGas: (*Uint64Quantity)(bl.ExcessBlobGas()), + BlobGasUsed: (*Uint64Quantity)(bl.BlobGasUsed()), + WithdrawalsRoot: bl.WithdrawalsRoot(), } if shanghaiTime != nil && uint64(payload.Timestamp) >= *shanghaiTime { diff --git a/op-service/sources/types.go b/op-service/sources/types.go index 4177ac6668759..f31e88038a21b 100644 --- a/op-service/sources/types.go +++ b/op-service/sources/types.go @@ -223,23 +223,24 @@ func (block *RPCBlock) ExecutionPayloadEnvelope(trustCache bool) (*eth.Execution } payload := ð.ExecutionPayload{ - ParentHash: block.ParentHash, - FeeRecipient: block.Coinbase, - StateRoot: eth.Bytes32(block.Root), - ReceiptsRoot: eth.Bytes32(block.ReceiptHash), - LogsBloom: block.Bloom, - PrevRandao: eth.Bytes32(block.MixDigest), // mix-digest field is used for prevRandao post-merge - BlockNumber: block.Number, - GasLimit: block.GasLimit, - GasUsed: block.GasUsed, - Timestamp: block.Time, - ExtraData: eth.BytesMax32(block.Extra), - BaseFeePerGas: eth.Uint256Quantity(baseFee), - BlockHash: block.Hash, - Transactions: opaqueTxs, - Withdrawals: block.Withdrawals, - BlobGasUsed: block.BlobGasUsed, - ExcessBlobGas: block.ExcessBlobGas, + ParentHash: block.ParentHash, + FeeRecipient: block.Coinbase, + StateRoot: eth.Bytes32(block.Root), + ReceiptsRoot: eth.Bytes32(block.ReceiptHash), + LogsBloom: block.Bloom, + PrevRandao: eth.Bytes32(block.MixDigest), // mix-digest field is used for prevRandao post-merge + BlockNumber: block.Number, + GasLimit: block.GasLimit, + GasUsed: block.GasUsed, + Timestamp: block.Time, + ExtraData: eth.BytesMax32(block.Extra), + BaseFeePerGas: eth.Uint256Quantity(baseFee), + BlockHash: block.Hash, + Transactions: opaqueTxs, + Withdrawals: block.Withdrawals, + BlobGasUsed: block.BlobGasUsed, + ExcessBlobGas: block.ExcessBlobGas, + WithdrawalsRoot: block.WithdrawalsRoot, } return ð.ExecutionPayloadEnvelope{ diff --git a/op-wheel/commands.go b/op-wheel/commands.go index 521578a34cb6b..49232ed4fdec5 100644 --- a/op-wheel/commands.go +++ b/op-wheel/commands.go @@ -256,6 +256,9 @@ func rollupFromGethConfig(cfg *params.ChainConfig) *rollup.Config { CanyonTime: cfg.CanyonTime, EcotoneTime: cfg.EcotoneTime, GraniteTime: cfg.GraniteTime, + HoloceneTime: cfg.HoloceneTime, + IsthmusTime: cfg.IsthmusTime, + JovianTime: cfg.JovianTime, InteropTime: cfg.InteropTime, } } diff --git a/packages/contracts-bedrock/scripts/L2Genesis.s.sol b/packages/contracts-bedrock/scripts/L2Genesis.s.sol index 98edde181cc71..eb4c74ffee624 100644 --- a/packages/contracts-bedrock/scripts/L2Genesis.s.sol +++ b/packages/contracts-bedrock/scripts/L2Genesis.s.sol @@ -182,9 +182,14 @@ contract L2Genesis is Deployer { if (writeForkGenesisAllocs(_fork, Fork.HOLOCENE, _mode)) { return; } + if (writeForkGenesisAllocs(_fork, Fork.ISTHMUS, _mode)) { return; } + + if (writeForkGenesisAllocs(_fork, Fork.JOVIAN, _mode)) { + return; + } } function writeForkGenesisAllocs(Fork _latest, Fork _current, OutputMode _mode) internal returns (bool isLatest_) { diff --git a/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol index cf8e4d38739b3..89cfb716aa474 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol @@ -30,6 +30,8 @@ contract DeployConfig is Script { uint256 public l2GenesisFjordTimeOffset; uint256 public l2GenesisGraniteTimeOffset; uint256 public l2GenesisHoloceneTimeOffset; + uint256 public l2GenesisIsthmusTimeOffset; + uint256 public l2GenesisJovianTimeOffset; uint256 public maxSequencerDrift; uint256 public sequencerWindowSize; uint256 public channelTimeout; @@ -109,6 +111,8 @@ contract DeployConfig is Script { l2GenesisFjordTimeOffset = _readOr(_json, "$.l2GenesisFjordTimeOffset", NULL_OFFSET); l2GenesisGraniteTimeOffset = _readOr(_json, "$.l2GenesisGraniteTimeOffset", NULL_OFFSET); l2GenesisHoloceneTimeOffset = _readOr(_json, "$.l2GenesisHoloceneTimeOffset", NULL_OFFSET); + l2GenesisIsthmusTimeOffset = _readOr(_json, "$.l2GenesisIsthmusTimeOffset", NULL_OFFSET); + l2GenesisJovianTimeOffset = _readOr(_json, "$.l2GenesisJovianTimeOffset", NULL_OFFSET); maxSequencerDrift = stdJson.readUint(_json, "$.maxSequencerDrift"); sequencerWindowSize = stdJson.readUint(_json, "$.sequencerWindowSize"); diff --git a/packages/contracts-bedrock/scripts/libraries/Config.sol b/packages/contracts-bedrock/scripts/libraries/Config.sol index d00043e0e92e2..c4c893699db68 100644 --- a/packages/contracts-bedrock/scripts/libraries/Config.sol +++ b/packages/contracts-bedrock/scripts/libraries/Config.sol @@ -35,10 +35,11 @@ enum Fork { FJORD, GRANITE, HOLOCENE, - ISTHMUS + ISTHMUS, + JOVIAN } -Fork constant LATEST_FORK = Fork.ISTHMUS; +Fork constant LATEST_FORK = Fork.JOVIAN; library ForkUtils { function toString(Fork _fork) internal pure returns (string memory) { @@ -56,6 +57,8 @@ library ForkUtils { return "holocene"; } else if (_fork == Fork.ISTHMUS) { return "isthmus"; + } else if (_fork == Fork.JOVIAN) { + return "jovian"; } else { return "unknown"; } @@ -166,6 +169,8 @@ library Config { return Fork.HOLOCENE; } else if (forkHash == keccak256(bytes("isthmus"))) { return Fork.ISTHMUS; + } else if (forkHash == keccak256(bytes("jovian"))) { + return Fork.JOVIAN; } else { revert(string.concat("Config: unknown fork: ", forkStr)); } diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 81d746fa67767..e229dede1d8c1 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -20,12 +20,16 @@ "sourceCodeHash": "0xe0f5413e0a0a335016d773f02ef6bd25551416635981e83b7a4da601b9b65bc4" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0x7e533474310583593c2d57d30fcd1ec11e1568dbaaf37a2dd28c5cc574068bac", - "sourceCodeHash": "0xe67f0c01c9c9ba67d279304f9db84eebeb2e93d9f2728fea95c7a194f0ae338a" + "initCodeHash": "0xed1e7bfce7c8d19167427e7f0e64bd9a06f2472e02692346cbb770fdd6f57b9e", + "sourceCodeHash": "0xc53b468455c2e6f4cab1ffd46dab1d10494cf112ae2f4432bacd21d771ea1ed1" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x917b3b31a149b5aab96539208f4810d207875f6f2563a45c50ed13a7940066c0", - "sourceCodeHash": "0xae2fbe02c0f8685692babeed0252ae8a624dc6d3bfb082fc3807d7b84869004b" + "initCodeHash": "0x6496f675ecb21bbbc3a0a153e8f8ea421426ac0e6b85a12f4c180137eddfe57b", + "sourceCodeHash": "0xd10c5d59d03d4e36a3be0ae42ea71f188917b45aa1f6139c288e2644911dc6b5" + }, + "src/L1/OptimismPortalJovian.sol": { + "initCodeHash": "0xe9320dba29d18198f8456a4b74e6a6b7a0e72efff6590de5d6c7b6facf46b6ab", + "sourceCodeHash": "0x9fd9c247a1c988428ec39cfc8843dac1afd12f4e6c2639278a2c50299dde5357" }, "src/L1/ProtocolVersions.sol": { "initCodeHash": "0x0000ec89712d8b4609873f1ba76afffd4205bf9110818995c90134dbec12e91e", @@ -36,12 +40,16 @@ "sourceCodeHash": "0xafa784ea78818a382ff3a61e2d84be58c7978110c06b9273db68c0213ead02d3" }, "src/L1/SystemConfig.sol": { - "initCodeHash": "0xbb18eef17cdc1d0d307b0241e818820063e3ce3c7021ea3bb3a85ff6e79659e1", - "sourceCodeHash": "0x5d6a9ef41fed54479f742345368e693ec1fcabdb60118081c03fe9da3a5d27ed" + "initCodeHash": "0xd081fe793600dc44c9b60365368774929e8fe2a4194c991ddc6c42c8bc925d44", + "sourceCodeHash": "0xc0f84262fcfcf962fce6f023d434f92feafbf4b3a4463e8491d19de3415d3aea" }, "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x0d61e2a95122417e9bf074a8fc0bce6f2b03268985d09580a83099dc9016c72d", - "sourceCodeHash": "0x673ec83b89680b44945af89229b286f26df07a5938d497df5def47872d331cf3" + "initCodeHash": "0xd9520478fe88af6a8f04965a00c0f61283efc07447097b038581672b1ca0d369", + "sourceCodeHash": "0xc8dc21fd6d2a1e8745d160c781033f267a5663adf9ae3bde6a8c77ebc976cdd9" + }, + "src/L1/SystemConfigJovian.sol": { + "initCodeHash": "0xc56c85988424683a7d5240c2636a6064ab3cc7829a087743f32debb7c36caed3", + "sourceCodeHash": "0xb333712a798272cc836acca9e4e02235b3aec0b52d5c66831804bf551d0ef043" }, "src/L2/BaseFeeVault.sol": { "initCodeHash": "0xc403d4c555d8e69a2699e01d192ae7327136701fa02da10a6d75a584b3c364c9", @@ -60,12 +68,12 @@ "sourceCodeHash": "0x305c72d7be9149fce7095bd4641a1a19acada3126fbc43599f674cadbf6e7d6c" }, "src/L2/L1Block.sol": { - "initCodeHash": "0x22f9b9277e33dc27df8366c2dd6e8340d294947b57116db35c6d14c41225633f", - "sourceCodeHash": "0xffb6cf768097b2d6cb6ecb2d6463c176af9acd70415aa0d2e4f017758f737eee" + "initCodeHash": "0xd805575182901b29a2ef1f0b98f3870b49737a838b8f1a6816785c3f10b1a437", + "sourceCodeHash": "0x2e1d6ecf1dd483366e92dc4865c5b2042da7a8cf4ffdbc04c6f7d9adaef6f8cd" }, "src/L2/L1BlockInterop.sol": { - "initCodeHash": "0x67e99306d9a09cac587f65cfa2c0de55da9eca184fd1fc3f4b885d2c47114483", - "sourceCodeHash": "0x9493f90136917fc95d2ac942f061c1b9cffeff6d327afb46fe4e69784e7f2100" + "initCodeHash": "0x07e2bdbb1e0ba44486cecb2b2e9d4e5bfcb4a604a0d485f60cc4791955d65aa4", + "sourceCodeHash": "0x76183bbb4c04730c62f6d4340ceb9b1b2a3574d1a5d2bd28945c15e9288c0aa2" }, "src/L2/L1FeeVault.sol": { "initCodeHash": "0x6745b7be3895a5e8d373df0066d931bae29c47672ac46c2f5829bd0052cc6d9e",