From bf196f97c4105fc94c3e92e198dbcb46da70c776 Mon Sep 17 00:00:00 2001 From: Sebastian Stammler Date: Mon, 3 Nov 2025 17:11:51 +0100 Subject: [PATCH 01/20] all: Move fork names into new op-core/forks package (#18121) --- .../testing/testlib/validators/forks.go | 32 ++--- .../testlib/validators/validators_test.go | 18 +-- .../tests/ecotone/fees_test.go | 4 +- .../tests/fjord/check_scripts_test.go | 4 +- op-acceptance-tests/tests/fjord/fees_test.go | 4 +- .../upgrade-singlechain/crossl2inbox_test.go | 4 +- .../tests/interop/upgrade/post_test.go | 14 +-- .../isthmus/erc20_bridge/erc20_bridge_test.go | 4 +- .../isthmus/operator_fee/operator_fee_test.go | 4 +- .../isthmus/pectra/pectra_features_test.go | 4 +- .../withdrawal_root/withdrawals_root_test.go | 4 +- .../tests/jovian/da_footprint_test.go | 4 +- .../tests/jovian/min_base_fee_test.go | 4 +- .../tests/jovian/operator_fee_test.go | 4 +- .../sync_tester/sync_tester_hfs/init_test.go | 4 +- .../sync_tester_hfs_ext_test.go | 48 ++++---- op-chain-ops/genesis/config.go | 45 +++---- op-chain-ops/genesis/config_test.go | 27 ++--- op-core/forks/forks.go | 72 ++++++++++++ op-deployer/pkg/deployer/standard/standard.go | 22 ++-- op-devstack/dsl/operator_fee.go | 4 +- op-devstack/dsl/validators.go | 21 ++-- op-devstack/presets/interop.go | 6 +- op-devstack/presets/jovian.go | 4 +- op-devstack/presets/simple_with_synctester.go | 4 +- op-devstack/sysgo/deployer.go | 7 +- op-e2e/actions/derivation/blocktime_test.go | 6 +- op-e2e/actions/helpers/env.go | 3 +- op-e2e/actions/helpers/l2_sequencer.go | 3 +- .../actions/proofs/activation_block_test.go | 8 +- op-e2e/actions/proofs/helpers/env.go | 3 +- op-e2e/actions/proofs/helpers/matrix.go | 20 ++-- .../actions/proofs/jovian_dafootprint_test.go | 8 +- .../actions/proofs/jovian_minbasefee_test.go | 10 +- .../operator_fee_fix_transition_test.go | 6 +- op-e2e/actions/proofs/system_config_test.go | 4 +- op-e2e/actions/upgrades/dencun_fork_test.go | 13 +-- op-e2e/actions/upgrades/ecotone_fork_test.go | 4 +- op-e2e/actions/upgrades/fjord_fork_test.go | 4 +- op-e2e/actions/upgrades/holocene_fork_test.go | 8 +- op-e2e/config/init.go | 4 +- op-e2e/e2eutils/intentbuilder/builder.go | 16 +-- op-e2e/e2eutils/intentbuilder/builder_test.go | 6 +- op-e2e/system/bridge/deposit_test.go | 4 +- .../attributes/engine_consolidate_test.go | 45 +++---- op-node/rollup/chain_spec.go | 110 +++++------------- op-node/rollup/chain_spec_test.go | 19 +-- op-node/rollup/derive/attributes_test.go | 11 +- op-node/rollup/derive/batch_mux.go | 5 +- op-node/rollup/derive/batch_mux_test.go | 5 +- op-node/rollup/derive/batches_test.go | 3 +- op-node/rollup/derive/channel_mux.go | 5 +- op-node/rollup/derive/channel_mux_test.go | 5 +- op-node/rollup/derive/frame_queue.go | 5 +- op-node/rollup/derive/l1_block_info_test.go | 27 ++--- op-node/rollup/derive/pipeline.go | 5 +- op-node/rollup/types.go | 83 ++++++------- op-node/rollup/types_test.go | 61 +++++----- op-program/Dockerfile.repro.dockerignore | 1 + op-program/Dockerfile.vmcompat.dockerignore | 1 + .../client/l2/engineapi/l2_engine_api_test.go | 4 +- .../op-stack-go/Dockerfile.dockerignore | 1 + 62 files changed, 466 insertions(+), 432 deletions(-) create mode 100644 op-core/forks/forks.go diff --git a/devnet-sdk/testing/testlib/validators/forks.go b/devnet-sdk/testing/testlib/validators/forks.go index f60dcaa2e73..2f762ff75e2 100644 --- a/devnet-sdk/testing/testlib/validators/forks.go +++ b/devnet-sdk/testing/testlib/validators/forks.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum-optimism/optimism/devnet-sdk/system" "github.com/ethereum-optimism/optimism/devnet-sdk/testing/systest" - "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum/go-ethereum/params" ) @@ -39,32 +39,32 @@ func getChainConfig(t systest.T, sys system.System, chainIdx uint64) (*params.Ch // IsForkActivated checks if a specific fork is activated at the given timestamp // based on the chain configuration. -func IsForkActivated(c *params.ChainConfig, forkName rollup.ForkName, timestamp uint64) (bool, error) { +func IsForkActivated(c *params.ChainConfig, forkName forks.Name, timestamp uint64) (bool, error) { if c == nil { return false, fmt.Errorf("provided chain config is nil") } switch forkName { - case rollup.Bedrock: + case forks.Bedrock: // Bedrock is activated based on block number, not timestamp return true, nil // Assuming bedrock is always active in the context of this validator - case rollup.Regolith: + case forks.Regolith: return c.IsOptimismRegolith(timestamp), nil - case rollup.Canyon: + case forks.Canyon: return c.IsOptimismCanyon(timestamp), nil - case rollup.Ecotone: + case forks.Ecotone: return c.IsOptimismEcotone(timestamp), nil - case rollup.Fjord: + case forks.Fjord: return c.IsOptimismFjord(timestamp), nil - case rollup.Granite: + case forks.Granite: return c.IsOptimismGranite(timestamp), nil - case rollup.Holocene: + case forks.Holocene: return c.IsOptimismHolocene(timestamp), nil - case rollup.Isthmus: + case forks.Isthmus: return c.IsOptimismIsthmus(timestamp), nil - case rollup.Jovian: + case forks.Jovian: return c.IsOptimismJovian(timestamp), nil - case rollup.Interop: + case forks.Interop: return c.IsInterop(timestamp), nil default: return false, fmt.Errorf("unknown fork name: %s", forkName) @@ -72,7 +72,7 @@ func IsForkActivated(c *params.ChainConfig, forkName rollup.ForkName, timestamp } // forkConfigValidator is a helper function that checks if a specific L2 chain meets a fork condition. -func forkConfigValidator(chainIdx uint64, forkName rollup.ForkName, shouldBeActive bool, forkConfigMarker interface{}) systest.PreconditionValidator { +func forkConfigValidator(chainIdx uint64, forkName forks.Name, shouldBeActive bool, forkConfigMarker interface{}) systest.PreconditionValidator { return func(t systest.T, sys system.System) (context.Context, error) { chainConfig, timestamp, err := getChainConfig(t, sys, chainIdx) if err != nil { @@ -105,7 +105,7 @@ type ChainConfigGetter = func(context.Context) *params.ChainConfig // AcquireForkConfig returns a ForkConfigGetter and a PreconditionValidator // that ensures a ForkConfig is available for the specified L2 chain. // The ForkConfig can be used to check if various forks are activated. -func acquireForkConfig(chainIdx uint64, forkName rollup.ForkName, shouldBeActive bool) (ChainConfigGetter, systest.PreconditionValidator) { +func acquireForkConfig(chainIdx uint64, forkName forks.Name, shouldBeActive bool) (ChainConfigGetter, systest.PreconditionValidator) { chainConfigMarker := new(byte) validator := forkConfigValidator(chainIdx, forkName, shouldBeActive, chainConfigMarker) return func(ctx context.Context) *params.ChainConfig { @@ -114,13 +114,13 @@ func acquireForkConfig(chainIdx uint64, forkName rollup.ForkName, shouldBeActive } // RequiresFork returns a validator that ensures a specific L2 chain has a specific fork activated. -func AcquireL2WithFork(chainIdx uint64, forkName rollup.ForkName) (ChainConfigGetter, systest.PreconditionValidator) { +func AcquireL2WithFork(chainIdx uint64, forkName forks.Name) (ChainConfigGetter, systest.PreconditionValidator) { return acquireForkConfig(chainIdx, forkName, true) } // RequiresNotFork returns a validator that ensures a specific L2 chain does not // have a specific fork activated. Will not work with the interop fork // specifically since interop is not an ordered release fork. -func AcquireL2WithoutFork(chainIdx uint64, forkName rollup.ForkName) (ChainConfigGetter, systest.PreconditionValidator) { +func AcquireL2WithoutFork(chainIdx uint64, forkName forks.Name) (ChainConfigGetter, systest.PreconditionValidator) { return acquireForkConfig(chainIdx, forkName, false) } diff --git a/devnet-sdk/testing/testlib/validators/validators_test.go b/devnet-sdk/testing/testlib/validators/validators_test.go index 17bc4829405..056999121a6 100644 --- a/devnet-sdk/testing/testlib/validators/validators_test.go +++ b/devnet-sdk/testing/testlib/validators/validators_test.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum-optimism/optimism/devnet-sdk/system" "github.com/ethereum-optimism/optimism/devnet-sdk/testing/systest" "github.com/ethereum-optimism/optimism/devnet-sdk/types" - "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -33,7 +33,7 @@ func TestValidators(t *testing.T) { t.Run("multiple validators", func(t *testing.T) { walletGetter1, validator1 := AcquireL2WalletWithFunds(0, types.NewBalance(big.NewInt(1))) walletGetter2, validator2 := AcquireL2WalletWithFunds(0, types.NewBalance(big.NewInt(10))) - chainConfigGetter, l2ForkValidator := AcquireL2WithFork(0, rollup.Isthmus) + chainConfigGetter, l2ForkValidator := AcquireL2WithFork(0, forks.Isthmus) // We create a system that has a low-level L1 chain and at least one wallet systestSystem := &mockSystem{ @@ -109,7 +109,7 @@ func TestValidators(t *testing.T) { } // Get the validator for requiring Isthmus fork to be active - chainConfigGetter, validator := AcquireL2WithFork(0, rollup.Isthmus) + chainConfigGetter, validator := AcquireL2WithFork(0, forks.Isthmus) systestT := systest.NewT(t) // Apply the validator @@ -119,7 +119,7 @@ func TestValidators(t *testing.T) { // Verify the chain config getter works chainConfig := chainConfigGetter(ctx) require.NotNil(t, chainConfig) - isActive, err := IsForkActivated(chainConfig, rollup.Isthmus, 100) + isActive, err := IsForkActivated(chainConfig, forks.Isthmus, 100) require.NoError(t, err) require.True(t, isActive) }) @@ -143,7 +143,7 @@ func TestValidators(t *testing.T) { } // Get the validator for requiring Isthmus fork to be active - _, validator := AcquireL2WithFork(0, rollup.Isthmus) + _, validator := AcquireL2WithFork(0, forks.Isthmus) systestT := systest.NewT(t) // Apply the validator - should fail since fork is not active @@ -171,7 +171,7 @@ func TestValidators(t *testing.T) { } // Get the validator for requiring Isthmus fork to not be active - chainConfigGetter, validator := AcquireL2WithoutFork(0, rollup.Isthmus) + chainConfigGetter, validator := AcquireL2WithoutFork(0, forks.Isthmus) systestT := systest.NewT(t) // Apply the validator @@ -181,7 +181,7 @@ func TestValidators(t *testing.T) { // Verify the chain config getter works chainConfig := chainConfigGetter(ctx) require.NotNil(t, chainConfig) - isActive, err := IsForkActivated(chainConfig, rollup.Isthmus, 100) + isActive, err := IsForkActivated(chainConfig, forks.Isthmus, 100) require.NoError(t, err) require.False(t, isActive) }) @@ -205,7 +205,7 @@ func TestValidators(t *testing.T) { } // Get the validator for requiring Isthmus fork to not be active - _, validator := AcquireL2WithoutFork(0, rollup.Isthmus) + _, validator := AcquireL2WithoutFork(0, forks.Isthmus) systestT := systest.NewT(t) // Apply the validator - should fail since fork is active @@ -221,7 +221,7 @@ func TestValidators(t *testing.T) { } // Try to get chain config for an invalid chain index - _, validator := AcquireL2WithFork(0, rollup.Isthmus) + _, validator := AcquireL2WithFork(0, forks.Isthmus) systestT := systest.NewT(t) // Apply the validator - should fail since chain index is out of range diff --git a/op-acceptance-tests/tests/ecotone/fees_test.go b/op-acceptance-tests/tests/ecotone/fees_test.go index 10852f673eb..eb8731587e2 100644 --- a/op-acceptance-tests/tests/ecotone/fees_test.go +++ b/op-acceptance-tests/tests/ecotone/fees_test.go @@ -4,10 +4,10 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -16,7 +16,7 @@ func TestFees(gt *testing.T) { sys := presets.NewMinimal(t) require := t.Require() - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Ecotone) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Ecotone) require.NoError(err, "Ecotone fork must be active for this test") alice := sys.FunderL2.NewFundedEOA(eth.OneTenthEther) diff --git a/op-acceptance-tests/tests/fjord/check_scripts_test.go b/op-acceptance-tests/tests/fjord/check_scripts_test.go index 649f4a5e9de..2572332b7df 100644 --- a/op-acceptance-tests/tests/fjord/check_scripts_test.go +++ b/op-acceptance-tests/tests/fjord/check_scripts_test.go @@ -7,10 +7,10 @@ import ( "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" txib "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" @@ -34,7 +34,7 @@ func TestCheckFjordScript(gt *testing.T) { require := t.Require() ctx := t.Ctx() - err := dsl.RequiresL2Fork(ctx, sys, 0, rollup.Fjord) + err := dsl.RequiresL2Fork(ctx, sys, 0, forks.Fjord) require.NoError(err) wallet := sys.FunderL2.NewFundedEOA(eth.OneThirdEther) diff --git a/op-acceptance-tests/tests/fjord/fees_test.go b/op-acceptance-tests/tests/fjord/fees_test.go index f661e17a6f2..980153c7f50 100644 --- a/op-acceptance-tests/tests/fjord/fees_test.go +++ b/op-acceptance-tests/tests/fjord/fees_test.go @@ -7,7 +7,7 @@ import ( dsl "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" txib "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" @@ -19,7 +19,7 @@ func TestFees(gt *testing.T) { require := t.Require() ctx := t.Ctx() - err := dsl.RequiresL2Fork(ctx, sys, 0, rollup.Fjord) + err := dsl.RequiresL2Fork(ctx, sys, 0, forks.Fjord) require.NoError(err) operatorFee := dsl.NewOperatorFee(t, sys.L2Chain, sys.L1EL) operatorFee.SetOperatorFee(100000000, 500) diff --git a/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go b/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go index 9ec7a9d787a..e579de1eff1 100644 --- a/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go +++ b/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go @@ -4,11 +4,11 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -22,7 +22,7 @@ func TestPostInbox(gt *testing.T) { require := t.Require() el := net.Escape().L2ELNode(match.FirstL2EL) - activationBlock := net.AwaitActivation(t, rollup.Interop) + activationBlock := net.AwaitActivation(t, forks.Interop) require.NotZero(activationBlock, "must not activate interop at genesis") pre := activationBlock.Number - 1 diff --git a/op-acceptance-tests/tests/interop/upgrade/post_test.go b/op-acceptance-tests/tests/interop/upgrade/post_test.go index 5e5ea29ae1e..faf69facfde 100644 --- a/op-acceptance-tests/tests/interop/upgrade/post_test.go +++ b/op-acceptance-tests/tests/interop/upgrade/post_test.go @@ -7,19 +7,19 @@ import ( "testing" "time" - stypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/interop" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" + stypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) func TestPostInbox(gt *testing.T) { @@ -28,7 +28,7 @@ func TestPostInbox(gt *testing.T) { sys := presets.NewSimpleInterop(t) devtest.RunParallel(t, sys.L2Networks(), func(t devtest.T, net *dsl.L2Network) { require := t.Require() - activationBlock := net.AwaitActivation(t, rollup.Interop) + activationBlock := net.AwaitActivation(t, forks.Interop) el := net.Escape().L2ELNode(match.FirstL2EL) implAddrBytes, err := el.EthClient().GetStorageAt(t.Ctx(), predeploys.CrossL2InboxAddr, @@ -96,7 +96,7 @@ func testSupervisorAnchorBlock(t devtest.T, sys *presets.SimpleInterop) { t.Gate().True(upgradeTime.Before(deadline), "test must not time out before upgrade happens") } - activationBlock := net.AwaitActivation(t, rollup.Interop) + activationBlock := net.AwaitActivation(t, forks.Interop) sys.Supervisor.WaitForL2HeadToAdvanceTo(net.ChainID(), stypes.CrossSafe, activationBlock) logger.Info("Validating anchor block timing", diff --git a/op-acceptance-tests/tests/isthmus/erc20_bridge/erc20_bridge_test.go b/op-acceptance-tests/tests/isthmus/erc20_bridge/erc20_bridge_test.go index 9667fcf4a52..dfc19986418 100644 --- a/op-acceptance-tests/tests/isthmus/erc20_bridge/erc20_bridge_test.go +++ b/op-acceptance-tests/tests/isthmus/erc20_bridge/erc20_bridge_test.go @@ -3,11 +3,11 @@ package erc20bridge import ( "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/dsl/contract" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txplan" @@ -18,7 +18,7 @@ func TestERC20Bridge(gt *testing.T) { sys := presets.NewMinimal(t) require := t.Require() - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Isthmus) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Isthmus) require.NoError(err, "Isthmus fork must be active for this test") // Create users with same identity on both chains diff --git a/op-acceptance-tests/tests/isthmus/operator_fee/operator_fee_test.go b/op-acceptance-tests/tests/isthmus/operator_fee/operator_fee_test.go index 856aebeba48..c56dd56ffa6 100644 --- a/op-acceptance-tests/tests/isthmus/operator_fee/operator_fee_test.go +++ b/op-acceptance-tests/tests/isthmus/operator_fee/operator_fee_test.go @@ -3,16 +3,16 @@ package operatorfee import ( "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" ) func TestOperatorFee(gt *testing.T) { t := devtest.SerialT(gt) sys := presets.NewMinimal(t) - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Isthmus) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Isthmus) t.Require().NoError(err, "Isthmus fork must be active for this test") dsl.RunOperatorFeeTest(t, sys.L2Chain, sys.L1EL, sys.FunderL1, sys.FunderL2) } diff --git a/op-acceptance-tests/tests/isthmus/pectra/pectra_features_test.go b/op-acceptance-tests/tests/isthmus/pectra/pectra_features_test.go index e06338176f5..669ff8bdcfa 100644 --- a/op-acceptance-tests/tests/isthmus/pectra/pectra_features_test.go +++ b/op-acceptance-tests/tests/isthmus/pectra/pectra_features_test.go @@ -6,10 +6,10 @@ import ( "encoding/binary" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/txplan" "github.com/ethereum/go-ethereum/common" @@ -31,7 +31,7 @@ func TestPectra(gt *testing.T) { sys := presets.NewMinimal(t) require := t.Require() - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Isthmus) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Isthmus) require.NoError(err, "Isthmus fork must be active for Pectra features") alice := sys.FunderL2.NewFundedEOA(eth.OneTenthEther) diff --git a/op-acceptance-tests/tests/isthmus/withdrawal_root/withdrawals_root_test.go b/op-acceptance-tests/tests/isthmus/withdrawal_root/withdrawals_root_test.go index 89135d003b0..739a5ecfadc 100644 --- a/op-acceptance-tests/tests/isthmus/withdrawal_root/withdrawals_root_test.go +++ b/op-acceptance-tests/tests/isthmus/withdrawal_root/withdrawals_root_test.go @@ -3,10 +3,10 @@ package withdrawal import ( "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -15,7 +15,7 @@ func TestWithdrawalRoot(gt *testing.T) { sys := presets.NewMinimal(t) require := sys.T.Require() - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Isthmus) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Isthmus) require.NoError(err, "Isthmus fork must be active for this test") secondCheck, err := dsl.CheckForChainFork(t.Ctx(), sys.L2Networks(), t.Logger()) diff --git a/op-acceptance-tests/tests/jovian/da_footprint_test.go b/op-acceptance-tests/tests/jovian/da_footprint_test.go index f309dba6d7f..b7f4d2c4b05 100644 --- a/op-acceptance-tests/tests/jovian/da_footprint_test.go +++ b/op-acceptance-tests/tests/jovian/da_footprint_test.go @@ -10,10 +10,10 @@ import ( "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/interop/loadtest" "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/txinclude" @@ -121,7 +121,7 @@ func TestDAFootprint(gt *testing.T) { sys := presets.NewMinimal(t) require := t.Require() - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Jovian) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Jovian) require.NoError(err, "Jovian fork must be active for this test") env := newDAFootprintEnv(t, sys.L2Chain, sys.L1EL, sys.L2EL) diff --git a/op-acceptance-tests/tests/jovian/min_base_fee_test.go b/op-acceptance-tests/tests/jovian/min_base_fee_test.go index 28080e893bf..3ba1401de74 100644 --- a/op-acceptance-tests/tests/jovian/min_base_fee_test.go +++ b/op-acceptance-tests/tests/jovian/min_base_fee_test.go @@ -4,10 +4,10 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "encoding/binary" @@ -122,7 +122,7 @@ func TestMinBaseFee(gt *testing.T) { sys := presets.NewMinimal(t) require := t.Require() - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Jovian) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Jovian) require.NoError(err, "Jovian fork must be active for this test") minBaseFee := newMinBaseFee(t, sys.L2Chain, sys.L1EL, sys.L2EL) diff --git a/op-acceptance-tests/tests/jovian/operator_fee_test.go b/op-acceptance-tests/tests/jovian/operator_fee_test.go index e2e9e046a4b..f26b551774a 100644 --- a/op-acceptance-tests/tests/jovian/operator_fee_test.go +++ b/op-acceptance-tests/tests/jovian/operator_fee_test.go @@ -3,16 +3,16 @@ package jovian import ( "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" - "github.com/ethereum-optimism/optimism/op-node/rollup" ) func TestOperatorFee(gt *testing.T) { t := devtest.SerialT(gt) sys := presets.NewMinimal(t) - err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, rollup.Jovian) + err := dsl.RequiresL2Fork(t.Ctx(), sys, 0, forks.Jovian) t.Require().NoError(err, "Jovian fork must be active for this test") dsl.RunOperatorFeeTest(t, sys.L2Chain, sys.L1EL, sys.FunderL1, sys.FunderL2) } diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs/init_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs/init_test.go index b209502c609..559f04bd796 100644 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs/init_test.go +++ b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs/init_test.go @@ -4,18 +4,18 @@ import ( "testing" bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/compat" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-devstack/stack" "github.com/ethereum-optimism/optimism/op-devstack/sysgo" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ) func TestMain(m *testing.M) { presets.DoMain(m, presets.WithSimpleWithSyncTester(), presets.WithCompatibleTypes(compat.SysGo), - presets.WithHardforkSequentialActivation(rollup.Bedrock, rollup.Jovian, 15), + presets.WithHardforkSequentialActivation(forks.Bedrock, forks.Jovian, 15), stack.MakeCommon(sysgo.WithBatcherOption(func(id stack.L2BatcherID, cfg *bss.CLIConfig) { // For supporting pre-delta batches cfg.BatchType = derive.SingularBatchType diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext/sync_tester_hfs_ext_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext/sync_tester_hfs_ext_test.go index ec6464500e1..6f411509690 100644 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext/sync_tester_hfs_ext_test.go +++ b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext/sync_tester_hfs_ext_test.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" @@ -17,7 +18,6 @@ import ( "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-devstack/sysgo" "github.com/ethereum-optimism/optimism/op-node/chaincfg" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" @@ -40,14 +40,14 @@ const ( var ( // Network upgrade block numbers for op-sepolia - networkUpgradeBlocks = map[rollup.ForkName]uint64{ - rollup.Canyon: 4089330, - rollup.Delta: 5700330, - rollup.Ecotone: 8366130, - rollup.Fjord: 12597930, - rollup.Granite: 15837930, - rollup.Holocene: 20415330, - rollup.Isthmus: 26551530, + networkUpgradeBlocks = map[forks.Name]uint64{ + forks.Canyon: 4089330, + forks.Delta: 5700330, + forks.Ecotone: 8366130, + forks.Fjord: 12597930, + forks.Granite: 15837930, + forks.Holocene: 20415330, + forks.Isthmus: 26551530, } // Load configuration from environment variables with defaults @@ -61,59 +61,59 @@ var ( ) func TestSyncTesterHFS_Canyon_CLSync(gt *testing.T) { - hfsExt(gt, rollup.Canyon, sync.CLSync) + hfsExt(gt, forks.Canyon, sync.CLSync) } func TestSyncTesterHFS_Canyon_ELSync(gt *testing.T) { - hfsExt(gt, rollup.Canyon, sync.ELSync) + hfsExt(gt, forks.Canyon, sync.ELSync) } func TestSyncTesterHFS_Delta_CLSync(gt *testing.T) { - hfsExt(gt, rollup.Delta, sync.CLSync) + hfsExt(gt, forks.Delta, sync.CLSync) } func TestSyncTesterHFS_Delta_ELSync(gt *testing.T) { - hfsExt(gt, rollup.Delta, sync.ELSync) + hfsExt(gt, forks.Delta, sync.ELSync) } func TestSyncTesterHFS_Ecotone_CLSync(gt *testing.T) { - hfsExt(gt, rollup.Ecotone, sync.CLSync) + hfsExt(gt, forks.Ecotone, sync.CLSync) } func TestSyncTesterHFS_Ecotone_ELSync(gt *testing.T) { - hfsExt(gt, rollup.Ecotone, sync.ELSync) + hfsExt(gt, forks.Ecotone, sync.ELSync) } func TestSyncTesterHFS_Fjord_CLSync(gt *testing.T) { - hfsExt(gt, rollup.Fjord, sync.CLSync) + hfsExt(gt, forks.Fjord, sync.CLSync) } func TestSyncTesterHFS_Fjord_ELSync(gt *testing.T) { - hfsExt(gt, rollup.Fjord, sync.ELSync) + hfsExt(gt, forks.Fjord, sync.ELSync) } func TestSyncTesterHFS_Granite_CLSync(gt *testing.T) { - hfsExt(gt, rollup.Granite, sync.CLSync) + hfsExt(gt, forks.Granite, sync.CLSync) } func TestSyncTesterHFS_Granite_ELSync(gt *testing.T) { - hfsExt(gt, rollup.Granite, sync.ELSync) + hfsExt(gt, forks.Granite, sync.ELSync) } func TestSyncTesterHFS_Holocene_CLSync(gt *testing.T) { - hfsExt(gt, rollup.Holocene, sync.CLSync) + hfsExt(gt, forks.Holocene, sync.CLSync) } func TestSyncTesterHFS_Holocene_ELSync(gt *testing.T) { - hfsExt(gt, rollup.Holocene, sync.ELSync) + hfsExt(gt, forks.Holocene, sync.ELSync) } func TestSyncTesterHFS_Isthmus_CLSync(gt *testing.T) { - hfsExt(gt, rollup.Isthmus, sync.CLSync) + hfsExt(gt, forks.Isthmus, sync.CLSync) } func TestSyncTesterHFS_Isthmus_ELSync(gt *testing.T) { - hfsExt(gt, rollup.Isthmus, sync.ELSync) + hfsExt(gt, forks.Isthmus, sync.ELSync) } // getEnvOrDefault returns the environment variable value or the default if not set @@ -215,7 +215,7 @@ func setupOrchestrator(gt *testing.T, t devtest.T, blk, targetBlock uint64, l2CL return orch.(*sysgo.Orchestrator) } -func hfsExt(gt *testing.T, upgradeName rollup.ForkName, l2CLSyncMode sync.Mode) { +func hfsExt(gt *testing.T, upgradeName forks.Name, l2CLSyncMode sync.Mode) { t := devtest.ParallelT(gt) l := t.Logger() diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index f2bedc0c699..99b07787624 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -18,6 +18,7 @@ import ( altda "github.com/ethereum-optimism/optimism/op-alt-da" "github.com/ethereum-optimism/optimism/op-chain-ops/addresses" + "github.com/ethereum-optimism/optimism/op-core/forks" opparams "github.com/ethereum-optimism/optimism/op-node/params" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -406,25 +407,25 @@ func offsetToUpgradeTime(offset *hexutil.Uint64, genesisTime uint64) *uint64 { func (d *UpgradeScheduleDeployConfig) ForkTimeOffset(fork rollup.ForkName) *uint64 { switch fork { - case rollup.Regolith: + case forks.Regolith: return (*uint64)(d.L2GenesisRegolithTimeOffset) - case rollup.Canyon: + case forks.Canyon: return (*uint64)(d.L2GenesisCanyonTimeOffset) - case rollup.Delta: + case forks.Delta: return (*uint64)(d.L2GenesisDeltaTimeOffset) - case rollup.Ecotone: + case forks.Ecotone: return (*uint64)(d.L2GenesisEcotoneTimeOffset) - case rollup.Fjord: + case forks.Fjord: return (*uint64)(d.L2GenesisFjordTimeOffset) - case rollup.Granite: + case forks.Granite: return (*uint64)(d.L2GenesisGraniteTimeOffset) - case rollup.Holocene: + case forks.Holocene: return (*uint64)(d.L2GenesisHoloceneTimeOffset) - case rollup.Isthmus: + case forks.Isthmus: return (*uint64)(d.L2GenesisIsthmusTimeOffset) - case rollup.Jovian: + case forks.Jovian: return (*uint64)(d.L2GenesisJovianTimeOffset) - case rollup.Interop: + case forks.Interop: return (*uint64)(d.L2GenesisInteropTimeOffset) default: panic(fmt.Sprintf("unknown fork: %s", fork)) @@ -433,32 +434,32 @@ func (d *UpgradeScheduleDeployConfig) ForkTimeOffset(fork rollup.ForkName) *uint func (d *UpgradeScheduleDeployConfig) SetForkTimeOffset(fork rollup.ForkName, offset *uint64) { switch fork { - case rollup.Regolith: + case forks.Regolith: d.L2GenesisRegolithTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Canyon: + case forks.Canyon: d.L2GenesisCanyonTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Delta: + case forks.Delta: d.L2GenesisDeltaTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Ecotone: + case forks.Ecotone: d.L2GenesisEcotoneTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Fjord: + case forks.Fjord: d.L2GenesisFjordTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Granite: + case forks.Granite: d.L2GenesisGraniteTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Holocene: + case forks.Holocene: d.L2GenesisHoloceneTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Isthmus: + case forks.Isthmus: d.L2GenesisIsthmusTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Jovian: + case forks.Jovian: d.L2GenesisJovianTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Interop: + case forks.Interop: d.L2GenesisInteropTimeOffset = (*hexutil.Uint64)(offset) default: panic(fmt.Sprintf("unknown fork: %s", fork)) } } -var scheduleableForks = rollup.ForksFrom(rollup.Regolith) +var scheduleableForks = forks.From(forks.Regolith) // ActivateForkAtOffset activates the given fork at the given offset. Previous forks are activated // at genesis and later forks are deactivated. @@ -466,7 +467,7 @@ var scheduleableForks = rollup.ForksFrom(rollup.Regolith) // ActivateForkAtOffset with the earliest fork and then SetForkTimeOffset to individually set later // forks. func (d *UpgradeScheduleDeployConfig) ActivateForkAtOffset(fork rollup.ForkName, offset uint64) { - if !rollup.IsValidFork(fork) || fork == rollup.Bedrock { + if !forks.IsValid(fork) || fork == forks.Bedrock { panic(fmt.Sprintf("invalid fork: %s", fork)) } ts := new(uint64) diff --git a/op-chain-ops/genesis/config_test.go b/op-chain-ops/genesis/config_test.go index 66ac9139c01..98fe0e1f9e2 100644 --- a/op-chain-ops/genesis/config_test.go +++ b/op-chain-ops/genesis/config_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/testlog" ) @@ -94,7 +95,7 @@ func TestForksCantActivateAtSamePostGenesisBlock(t *testing.T) { postGenesisOffset := uint64(1500) config := &UpgradeScheduleDeployConfig{} for _, fork := range config.forks() { - config.SetForkTimeOffset(rollup.ForkName(fork.Name), &postGenesisOffset) + config.SetForkTimeOffset(forks.Name(fork.Name), &postGenesisOffset) } err := config.Check(testlog.Logger(t, log.LevelDebug)) require.Error(t, err) @@ -153,7 +154,7 @@ func TestL1Deployments(t *testing.T) { // This test guarantees that getters and setters for all forks are present. func TestUpgradeScheduleDeployConfig_ForkGettersAndSetters(t *testing.T) { var d UpgradeScheduleDeployConfig - for i, fork := range rollup.ForksFrom(rollup.Regolith) { + for i, fork := range forks.From(forks.Regolith) { require.Nil(t, d.ForkTimeOffset(fork)) offset := uint64(i * 42) d.SetForkTimeOffset(fork, &offset) @@ -165,11 +166,11 @@ func TestUpgradeScheduleDeployConfig_ActivateForkAtOffset(t *testing.T) { var d UpgradeScheduleDeployConfig ts := uint64(42) t.Run("invalid", func(t *testing.T) { - require.Panics(t, func() { d.ActivateForkAtOffset(rollup.Bedrock, ts) }) + require.Panics(t, func() { d.ActivateForkAtOffset(forks.Bedrock, ts) }) }) t.Run("regolith", func(t *testing.T) { - d.ActivateForkAtOffset(rollup.Regolith, ts) + d.ActivateForkAtOffset(forks.Regolith, ts) require.EqualValues(t, &ts, d.L2GenesisRegolithTimeOffset) for _, fork := range scheduleableForks[1:] { require.Nil(t, d.ForkTimeOffset(fork)) @@ -177,7 +178,7 @@ func TestUpgradeScheduleDeployConfig_ActivateForkAtOffset(t *testing.T) { }) t.Run("ecotone", func(t *testing.T) { - d.ActivateForkAtOffset(rollup.Ecotone, ts) + d.ActivateForkAtOffset(forks.Ecotone, ts) require.EqualValues(t, &ts, d.L2GenesisEcotoneTimeOffset) for _, fork := range scheduleableForks[:3] { require.Zero(t, *d.ForkTimeOffset(fork)) @@ -201,14 +202,14 @@ func TestUpgradeScheduleDeployConfig_SolidityForkNumber(t *testing.T) { fork rollup.ForkName expected int64 }{ - {rollup.Delta, 1}, - {rollup.Ecotone, 2}, - {rollup.Fjord, 3}, - {rollup.Granite, 4}, - {rollup.Holocene, 5}, - {rollup.Isthmus, 6}, - {rollup.Jovian, 7}, - {rollup.Interop, 8}, + {forks.Delta, 1}, + {forks.Ecotone, 2}, + {forks.Fjord, 3}, + {forks.Granite, 4}, + {forks.Holocene, 5}, + {forks.Isthmus, 6}, + {forks.Jovian, 7}, + {forks.Interop, 8}, } for _, tt := range tests { var d UpgradeScheduleDeployConfig diff --git a/op-core/forks/forks.go b/op-core/forks/forks.go new file mode 100644 index 00000000000..0d2bd051c27 --- /dev/null +++ b/op-core/forks/forks.go @@ -0,0 +1,72 @@ +package forks + +import "fmt" + +// Name identifies a hardfork by name. +type Name string + +const ( + Bedrock Name = "bedrock" + Regolith Name = "regolith" + Canyon Name = "canyon" + Delta Name = "delta" + Ecotone Name = "ecotone" + Fjord Name = "fjord" + Granite Name = "granite" + Holocene Name = "holocene" + Isthmus Name = "isthmus" + Jovian Name = "jovian" + Interop Name = "interop" + // ADD NEW FORKS TO All BELOW! + None Name = "" +) + +// All lists all known forks in chronological order. +var All = []Name{ + Bedrock, + Regolith, + Canyon, + Delta, + Ecotone, + Fjord, + Granite, + Holocene, + Isthmus, + Jovian, + Interop, + // ADD NEW FORKS HERE! +} + +// Latest returns the most recent fork in All. +var Latest = All[len(All)-1] + +// From returns the list of forks starting from the provided fork, inclusive. +func From(start Name) []Name { + for i, f := range All { + if f == start { + return All[i:] + } + } + panic(fmt.Sprintf("invalid fork: %s", start)) +} + +var next = func() map[Name]Name { + m := make(map[Name]Name, len(All)) + for i, f := range All { + if i == len(All)-1 { + m[f] = None + break + } + m[f] = All[i+1] + } + return m +}() + +// IsValid returns true if the provided fork is a known fork. +func IsValid(f Name) bool { + _, ok := next[f] + return ok +} + +// Next returns the fork that follows the provided fork, or None if it is the last. +func Next(f Name) Name { return next[f] } diff --git a/op-deployer/pkg/deployer/standard/standard.go b/op-deployer/pkg/deployer/standard/standard.go index daa76d45a4d..6500558dc67 100644 --- a/op-deployer/pkg/deployer/standard/standard.go +++ b/op-deployer/pkg/deployer/standard/standard.go @@ -3,17 +3,15 @@ package standard import ( "fmt" - "github.com/ethereum/go-ethereum/common/hexutil" - - "github.com/ethereum-optimism/superchain-registry/validation" - - "github.com/ethereum/go-ethereum/superchain" - "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" - "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-core/forks" op_service "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/superchain-registry/validation" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/superchain" ) const ( @@ -180,13 +178,13 @@ func DefaultHardforkScheduleForTag(tag string) *genesis.UpgradeScheduleDeployCon case ContractsV160Tag, ContractsV170Beta1L2Tag: return sched case ContractsV180Tag, ContractsV200Tag, ContractsV300Tag: - sched.ActivateForkAtGenesis(rollup.Holocene) + sched.ActivateForkAtGenesis(forks.Holocene) case ContractsV400Tag, ContractsV410Tag: - sched.ActivateForkAtGenesis(rollup.Holocene) - sched.ActivateForkAtGenesis(rollup.Isthmus) + sched.ActivateForkAtGenesis(forks.Holocene) + sched.ActivateForkAtGenesis(forks.Isthmus) default: - sched.ActivateForkAtGenesis(rollup.Holocene) - sched.ActivateForkAtGenesis(rollup.Isthmus) + sched.ActivateForkAtGenesis(forks.Holocene) + sched.ActivateForkAtGenesis(forks.Isthmus) } return sched diff --git a/op-devstack/dsl/operator_fee.go b/op-devstack/dsl/operator_fee.go index a15f607dfde..486d04d28a0 100644 --- a/op-devstack/dsl/operator_fee.go +++ b/op-devstack/dsl/operator_fee.go @@ -5,9 +5,9 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" @@ -142,7 +142,7 @@ func (of *OperatorFee) ValidateTransactionFees(from *EOA, to *EOA, amount *big.I of.require.NoError(err) // Infer active fork from block info - isJovian := of.l2Network.IsForkActive(rollup.Jovian, info.Time()) + isJovian := of.l2Network.IsForkActive(forks.Jovian, info.Time()) // Verify GPO upgraded when jovian is active // We have nothing to assert when jovian is inactive because an isthmus L2 can diff --git a/op-devstack/dsl/validators.go b/op-devstack/dsl/validators.go index 94328e43336..5eec1ebb779 100644 --- a/op-devstack/dsl/validators.go +++ b/op-devstack/dsl/validators.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/params" @@ -22,26 +23,26 @@ func IsForkActivated(c *params.ChainConfig, forkName rollup.ForkName, timestamp } switch forkName { - case rollup.Bedrock: + case forks.Bedrock: // Bedrock is activated based on block number, not timestamp return true, nil // Assuming bedrock is always active in the context of this validator - case rollup.Regolith: + case forks.Regolith: return c.IsOptimismRegolith(timestamp), nil - case rollup.Canyon: + case forks.Canyon: return c.IsOptimismCanyon(timestamp), nil - case rollup.Ecotone: + case forks.Ecotone: return c.IsOptimismEcotone(timestamp), nil - case rollup.Fjord: + case forks.Fjord: return c.IsOptimismFjord(timestamp), nil - case rollup.Granite: + case forks.Granite: return c.IsOptimismGranite(timestamp), nil - case rollup.Holocene: + case forks.Holocene: return c.IsOptimismHolocene(timestamp), nil - case rollup.Isthmus: + case forks.Isthmus: return c.IsOptimismIsthmus(timestamp), nil - case rollup.Jovian: + case forks.Jovian: return c.IsOptimismJovian(timestamp), nil - case rollup.Interop: + case forks.Interop: return c.IsInterop(timestamp), nil default: return false, fmt.Errorf("unknown fork name: %s", forkName) diff --git a/op-devstack/presets/interop.go b/op-devstack/presets/interop.go index 0cfdfd32c45..c4589ec36d2 100644 --- a/op-devstack/presets/interop.go +++ b/op-devstack/presets/interop.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/dsl/proofs" @@ -14,7 +15,6 @@ import ( "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-devstack/sysgo" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/intentbuilder" - "github.com/ethereum-optimism/optimism/op-node/rollup" ) type SingleChainInterop struct { @@ -141,7 +141,7 @@ func WithUnscheduledInterop() stack.CommonOption { return stack.Combine( stack.MakeCommon(sysgo.WithDeployerOptions(func(p devtest.P, keys devkeys.Keys, builder intentbuilder.Builder) { for _, l2 := range builder.L2s() { - l2.WithForkAtOffset(rollup.Interop, nil) + l2.WithForkAtOffset(forks.Interop, nil) } })), stack.PostHydrate[stack.Orchestrator](func(sys stack.System) { @@ -175,7 +175,7 @@ func WithSuggestedInteropActivationOffset(offset uint64) stack.CommonOption { return stack.MakeCommon(sysgo.WithDeployerOptions( func(p devtest.P, keys devkeys.Keys, builder intentbuilder.Builder) { for _, l2Cfg := range builder.L2s() { - l2Cfg.WithForkAtOffset(rollup.Interop, &offset) + l2Cfg.WithForkAtOffset(forks.Interop, &offset) } }, )) diff --git a/op-devstack/presets/jovian.go b/op-devstack/presets/jovian.go index b0a96d76320..97c82807ee0 100644 --- a/op-devstack/presets/jovian.go +++ b/op-devstack/presets/jovian.go @@ -2,11 +2,11 @@ package presets import ( "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/stack" "github.com/ethereum-optimism/optimism/op-devstack/sysgo" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/intentbuilder" - "github.com/ethereum-optimism/optimism/op-node/rollup" ) // WithJovianAtGenesis configures all L2s to activate the Jovian fork at genesis in sysgo mode. @@ -14,7 +14,7 @@ func WithJovianAtGenesis() stack.CommonOption { return stack.MakeCommon(sysgo.WithDeployerOptions( func(p devtest.P, _ devkeys.Keys, builder intentbuilder.Builder) { for _, l2Cfg := range builder.L2s() { - l2Cfg.WithForkAtGenesis(rollup.Jovian) + l2Cfg.WithForkAtGenesis(forks.Jovian) } }, )) diff --git a/op-devstack/presets/simple_with_synctester.go b/op-devstack/presets/simple_with_synctester.go index 0afb33bcd30..b8c7950322b 100644 --- a/op-devstack/presets/simple_with_synctester.go +++ b/op-devstack/presets/simple_with_synctester.go @@ -1,13 +1,13 @@ package presets import ( + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/shim" "github.com/ethereum-optimism/optimism/op-devstack/stack" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-devstack/sysgo" - "github.com/ethereum-optimism/optimism/op-node/rollup" ) type SimpleWithSyncTester struct { @@ -43,6 +43,6 @@ func NewSimpleWithSyncTester(t devtest.T) *SimpleWithSyncTester { } } -func WithHardforkSequentialActivation(startFork, endFork rollup.ForkName, delta uint64) stack.CommonOption { +func WithHardforkSequentialActivation(startFork, endFork forks.Name, delta uint64) stack.CommonOption { return stack.MakeCommon(sysgo.WithDeployerOptions(sysgo.WithHardforkSequentialActivation(startFork, endFork, &delta))) } diff --git a/op-devstack/sysgo/deployer.go b/op-devstack/sysgo/deployer.go index 6f034002e5f..2db79a88575 100644 --- a/op-devstack/sysgo/deployer.go +++ b/op-devstack/sysgo/deployer.go @@ -13,6 +13,7 @@ import ( "github.com/holiman/uint256" "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/inspect" @@ -291,7 +292,7 @@ func WithDevFeatureEnabled(flag common.Hash) DeployerOption { func WithInteropAtGenesis() DeployerOption { return func(p devtest.P, keys devkeys.Keys, builder intentbuilder.Builder) { for _, l2Cfg := range builder.L2s() { - l2Cfg.WithForkAtGenesis(rollup.Interop) + l2Cfg.WithForkAtGenesis(forks.Interop) } } } @@ -300,13 +301,13 @@ func WithInteropAtGenesis() DeployerOption { // activate hardforks sequentially, starting from startFork and continuing // until (but not including) endFork. Each successive fork is scheduled at // an increasing offset. -func WithHardforkSequentialActivation(startFork, endFork rollup.ForkName, delta *uint64) DeployerOption { +func WithHardforkSequentialActivation(startFork, endFork forks.Name, delta *uint64) DeployerOption { return func(p devtest.P, keys devkeys.Keys, builder intentbuilder.Builder) { for _, l2Cfg := range builder.L2s() { l2Cfg.WithForkAtGenesis(startFork) activateWithOffset := false deactivate := false - for idx, refFork := range rollup.AllForks { + for idx, refFork := range forks.All { if deactivate || refFork == endFork { l2Cfg.WithForkAtOffset(refFork, nil) deactivate = true diff --git a/op-e2e/actions/derivation/blocktime_test.go b/op-e2e/actions/derivation/blocktime_test.go index bd5594864af..3f79652d658 100644 --- a/op-e2e/actions/derivation/blocktime_test.go +++ b/op-e2e/actions/derivation/blocktime_test.go @@ -4,10 +4,10 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -165,9 +165,9 @@ func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp.DeployConfig.SequencerWindowSize = 4 dp.DeployConfig.MaxSequencerDrift = 32 if deltaTimeOffset != nil { - dp.DeployConfig.ActivateForkAtOffset(rollup.Delta, uint64(*deltaTimeOffset)) + dp.DeployConfig.ActivateForkAtOffset(forks.Delta, uint64(*deltaTimeOffset)) } else { - dp.DeployConfig.ActivateForkAtGenesis(rollup.Canyon) + dp.DeployConfig.ActivateForkAtGenesis(forks.Canyon) } // TODO(client-pod#831): The Ecotone (and Fjord) activation blocks don't include user txs, // so disabling these forks for now. diff --git a/op-e2e/actions/helpers/env.go b/op-e2e/actions/helpers/env.go index 7aca1228a1d..ded94f31252 100644 --- a/op-e2e/actions/helpers/env.go +++ b/op-e2e/actions/helpers/env.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" e2ecfg "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -52,7 +53,7 @@ func WithActiveGenesisFork(fork rollup.ForkName) EnvOpt { // DefaultFork specifies the default fork to use when setting up the action test environment. // Currently manually set to Holocene. // Replace with `var DefaultFork = func() rollup.ForkName { return rollup.AllForks[len(rollup.AllForks)-1] }()` after Interop launch. -const DefaultFork = rollup.Holocene +const DefaultFork = forks.Holocene // SetupEnv sets up a default action test environment. If no fork is specified, the default fork as // specified by the package variable [defaultFork] is used. diff --git a/op-e2e/actions/helpers/l2_sequencer.go b/op-e2e/actions/helpers/l2_sequencer.go index 65c5933dddb..97d8100b1a5 100644 --- a/op-e2e/actions/helpers/l2_sequencer.go +++ b/op-e2e/actions/helpers/l2_sequencer.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/config" "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/ethereum-optimism/optimism/op-node/node/safedb" @@ -212,7 +213,7 @@ func (s *L2Sequencer) ActBuildL2ToTime(t Testing, target uint64) { } } -func (s *L2Sequencer) ActBuildL2ToFork(t Testing, fork rollup.ForkName) eth.L2BlockRef { +func (s *L2Sequencer) ActBuildL2ToFork(t Testing, fork forks.Name) eth.L2BlockRef { require.NotNil(t, s.RollupCfg.ActivationTime(fork), "cannot activate %s when it is not scheduled", fork) for !s.RollupCfg.IsForkActive(fork, s.L2Unsafe().Time) { s.ActL2EmptyBlock(t) diff --git a/op-e2e/actions/proofs/activation_block_test.go b/op-e2e/actions/proofs/activation_block_test.go index 2926aae6ff9..5aaabb3e125 100644 --- a/op-e2e/actions/proofs/activation_block_test.go +++ b/op-e2e/actions/proofs/activation_block_test.go @@ -4,9 +4,9 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/stretchr/testify/require" @@ -16,7 +16,7 @@ import ( ) type activationBlockTestCfg struct { - fork rollup.ForkName + fork forks.Name numUpgradeTxs int } @@ -26,8 +26,8 @@ func TestActivationBlockTxOmission(gt *testing.T) { matrix := helpers.NewMatrix[activationBlockTestCfg]() matrix.AddDefaultTestCasesWithName( - string(rollup.Jovian), - activationBlockTestCfg{fork: rollup.Jovian, numUpgradeTxs: 5}, + string(forks.Jovian), + activationBlockTestCfg{fork: forks.Jovian, numUpgradeTxs: 5}, helpers.NewForkMatrix(helpers.Isthmus), testActivationBlockTxOmission, ) diff --git a/op-e2e/actions/proofs/helpers/env.go b/op-e2e/actions/proofs/helpers/env.go index 6ac2fc39185..6872c1d0e1e 100644 --- a/op-e2e/actions/proofs/helpers/env.go +++ b/op-e2e/actions/proofs/helpers/env.go @@ -4,6 +4,7 @@ import ( "math/rand" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" e2ecfg "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-program/client/boot" @@ -48,7 +49,7 @@ func NewL2FaultProofEnv[c any](t helpers.Testing, testCfg *TestCfg[c], tp *e2eut if testCfg.Hardfork == nil { t.Fatalf("HF not set") } - dp.DeployConfig.ActivateForkAtGenesis(rollup.ForkName(testCfg.Hardfork.Name)) + dp.DeployConfig.ActivateForkAtGenesis(forks.Name(testCfg.Hardfork.Name)) for _, override := range deployConfigOverrides { override(dp.DeployConfig) diff --git a/op-e2e/actions/proofs/helpers/matrix.go b/op-e2e/actions/proofs/helpers/matrix.go index 025d8a96c45..b8bf9c6e1f9 100644 --- a/op-e2e/actions/proofs/helpers/matrix.go +++ b/op-e2e/actions/proofs/helpers/matrix.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-program/client/claim" "github.com/ethereum/go-ethereum/common" ) @@ -117,15 +117,15 @@ type ForkMatrix = []*Hardfork // Hardfork definitions var ( - Regolith = &Hardfork{Name: string(rollup.Regolith), Precedence: 1} - Canyon = &Hardfork{Name: string(rollup.Canyon), Precedence: 2} - Delta = &Hardfork{Name: string(rollup.Delta), Precedence: 3} - Ecotone = &Hardfork{Name: string(rollup.Ecotone), Precedence: 4} - Fjord = &Hardfork{Name: string(rollup.Fjord), Precedence: 5} - Granite = &Hardfork{Name: string(rollup.Granite), Precedence: 6} - Holocene = &Hardfork{Name: string(rollup.Holocene), Precedence: 7} - Isthmus = &Hardfork{Name: string(rollup.Isthmus), Precedence: 8} - Jovian = &Hardfork{Name: string(rollup.Jovian), Precedence: 9} + Regolith = &Hardfork{Name: string(forks.Regolith), Precedence: 1} + Canyon = &Hardfork{Name: string(forks.Canyon), Precedence: 2} + Delta = &Hardfork{Name: string(forks.Delta), Precedence: 3} + Ecotone = &Hardfork{Name: string(forks.Ecotone), Precedence: 4} + Fjord = &Hardfork{Name: string(forks.Fjord), Precedence: 5} + Granite = &Hardfork{Name: string(forks.Granite), Precedence: 6} + Holocene = &Hardfork{Name: string(forks.Holocene), Precedence: 7} + Isthmus = &Hardfork{Name: string(forks.Isthmus), Precedence: 8} + Jovian = &Hardfork{Name: string(forks.Jovian), Precedence: 9} ) var ( diff --git a/op-e2e/actions/proofs/jovian_dafootprint_test.go b/op-e2e/actions/proofs/jovian_dafootprint_test.go index b8ba00388a8..6bd159a7f93 100644 --- a/op-e2e/actions/proofs/jovian_dafootprint_test.go +++ b/op-e2e/actions/proofs/jovian_dafootprint_test.go @@ -6,10 +6,10 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -190,7 +190,7 @@ func Test_ProgramAction_JovianDAFootprint(gt *testing.T) { jovianAtGenesis := env.Sequencer.RollupCfg.IsJovian(env.Sequencer.RollupCfg.Genesis.L2Time) if !jovianAtGenesis { - env.Sequencer.ActBuildL2ToFork(t, rollup.Jovian) + env.Sequencer.ActBuildL2ToFork(t, forks.Jovian) } // We run three sub-steps. First, we test the default behavior. Then we update the scalar to @@ -213,10 +213,10 @@ func Test_ProgramAction_JovianDAFootprint(gt *testing.T) { genesisConfigFn helpers.DeployConfigOverride }{ "JovianAtGenesis": { - genesisConfigFn: func(dc *genesis.DeployConfig) { dc.ActivateForkAtGenesis(rollup.Jovian) }, + genesisConfigFn: func(dc *genesis.DeployConfig) { dc.ActivateForkAtGenesis(forks.Jovian) }, }, "JovianAfterGenesis": { - genesisConfigFn: func(dc *genesis.DeployConfig) { dc.ActivateForkAtOffset(rollup.Jovian, 4) }, + genesisConfigFn: func(dc *genesis.DeployConfig) { dc.ActivateForkAtOffset(forks.Jovian, 4) }, }, } diff --git a/op-e2e/actions/proofs/jovian_minbasefee_test.go b/op-e2e/actions/proofs/jovian_minbasefee_test.go index 967a54de8af..151e410ce24 100644 --- a/op-e2e/actions/proofs/jovian_minbasefee_test.go +++ b/op-e2e/actions/proofs/jovian_minbasefee_test.go @@ -5,10 +5,10 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -118,25 +118,25 @@ func Test_ProgramAction_JovianMinBaseFee(gt *testing.T) { }{ "JovianActivationAfterGenesis": { genesisConfigFn: func(dc *genesis.DeployConfig) { - dc.ActivateForkAtOffset(rollup.Jovian, 10) + dc.ActivateForkAtOffset(forks.Jovian, 10) }, minBaseFee: 0, }, "JovianActivationAtGenesisZeroMinBaseFee": { genesisConfigFn: func(dc *genesis.DeployConfig) { - dc.ActivateForkAtGenesis(rollup.Jovian) + dc.ActivateForkAtGenesis(forks.Jovian) }, minBaseFee: 0, }, "JovianActivationAtGenesisMinBaseFeeMedium": { genesisConfigFn: func(dc *genesis.DeployConfig) { - dc.ActivateForkAtGenesis(rollup.Jovian) + dc.ActivateForkAtGenesis(forks.Jovian) }, minBaseFee: 1_000_000_000, // 1 gwei }, "JovianActivationAtGenesisMinBaseFeeHigh": { genesisConfigFn: func(dc *genesis.DeployConfig) { - dc.ActivateForkAtGenesis(rollup.Jovian) + dc.ActivateForkAtGenesis(forks.Jovian) }, minBaseFee: 2_000_000_000, // 2 gwei }, diff --git a/op-e2e/actions/proofs/operator_fee_fix_transition_test.go b/op-e2e/actions/proofs/operator_fee_fix_transition_test.go index 24b2afba04d..a593797ddf9 100644 --- a/op-e2e/actions/proofs/operator_fee_fix_transition_test.go +++ b/op-e2e/actions/proofs/operator_fee_fix_transition_test.go @@ -5,10 +5,10 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -28,7 +28,7 @@ func Test_ProgramAction_OperatorFeeFixTransition(gt *testing.T) { t := actionsHelpers.NewDefaultTesting(gt) deployConfigOverrides := func(dp *genesis.DeployConfig) { - dp.ActivateForkAtOffset(rollup.Jovian, 15) + dp.ActivateForkAtOffset(forks.Jovian, 15) } testOperatorFeeScalar := uint32(345e6) @@ -140,7 +140,7 @@ func Test_ProgramAction_OperatorFeeFixTransition(gt *testing.T) { require.True(t, aliceFinalBalance.Cmp(aliceInitialBalance) < 0, "Alice's balance should decrease") // Now wind forward to jovian - unsafeL2Head = env.Sequencer.ActBuildL2ToFork(t, rollup.Jovian) + unsafeL2Head = env.Sequencer.ActBuildL2ToFork(t, forks.Jovian) // reset accounting aliceInitialBalance, _, _, _, operatorFeeVaultInitialBalance = getCurrentBalances(unsafeL2Head.Number) diff --git a/op-e2e/actions/proofs/system_config_test.go b/op-e2e/actions/proofs/system_config_test.go index a9e9ed33609..f24578c0bfb 100644 --- a/op-e2e/actions/proofs/system_config_test.go +++ b/op-e2e/actions/proofs/system_config_test.go @@ -8,10 +8,10 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -36,7 +36,7 @@ func testSystemConfigEarlyIsthmusUpgrade(gt *testing.T, testCfg *helpers.TestCfg t := actionsHelpers.NewDefaultTesting(gt) testSetup := func(dp *genesis.DeployConfig) { - dp.ActivateForkAtOffset(rollup.Isthmus, isthmusOffset) + dp.ActivateForkAtOffset(forks.Isthmus, isthmusOffset) } env := helpers.NewL2FaultProofEnv(t, testCfg, helpers.NewTestParams(), helpers.NewBatcherCfg(), testSetup) sequencer := env.Sequencer diff --git a/op-e2e/actions/upgrades/dencun_fork_test.go b/op-e2e/actions/upgrades/dencun_fork_test.go index 13c88fefc77..7c6a489dde6 100644 --- a/op-e2e/actions/upgrades/dencun_fork_test.go +++ b/op-e2e/actions/upgrades/dencun_fork_test.go @@ -4,18 +4,17 @@ import ( "context" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" - "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + transactions "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" - "github.com/ethereum-optimism/optimism/op-service/testlog" ) func TestDencunL1ForkAfterGenesis(gt *testing.T) { @@ -125,7 +124,7 @@ func TestDencunL2ForkAfterGenesis(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams()) require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset) // This test will fork on the second block - dp.DeployConfig.ActivateForkAtOffset(rollup.Ecotone, dp.DeployConfig.L2BlockTime*2) + dp.DeployConfig.ActivateForkAtOffset(forks.Ecotone, dp.DeployConfig.L2BlockTime*2) sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) diff --git a/op-e2e/actions/upgrades/ecotone_fork_test.go b/op-e2e/actions/upgrades/ecotone_fork_test.go index 09aa995fc36..9a326d0a427 100644 --- a/op-e2e/actions/upgrades/ecotone_fork_test.go +++ b/op-e2e/actions/upgrades/ecotone_fork_test.go @@ -5,6 +5,7 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/stretchr/testify/require" @@ -18,7 +19,6 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" @@ -50,7 +50,7 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset) // Activate all forks at genesis, and schedule Ecotone the block after - dp.DeployConfig.ActivateForkAtOffset(rollup.Ecotone, uint64(ecotoneOffset)) + dp.DeployConfig.ActivateForkAtOffset(forks.Ecotone, uint64(ecotoneOffset)) require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) diff --git a/op-e2e/actions/upgrades/fjord_fork_test.go b/op-e2e/actions/upgrades/fjord_fork_test.go index 24839388f1c..e7a4a8af8aa 100644 --- a/op-e2e/actions/upgrades/fjord_fork_test.go +++ b/op-e2e/actions/upgrades/fjord_fork_test.go @@ -16,9 +16,9 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/testlog" ) @@ -37,7 +37,7 @@ func TestFjordNetworkUpgradeTransactions(gt *testing.T) { // Activate all forks at genesis, and schedule Fjord the block after fjordOffset := uint64(2) - dp.DeployConfig.ActivateForkAtOffset(rollup.Fjord, fjordOffset) + dp.DeployConfig.ActivateForkAtOffset(forks.Fjord, fjordOffset) require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") diff --git a/op-e2e/actions/upgrades/holocene_fork_test.go b/op-e2e/actions/upgrades/holocene_fork_test.go index f2fca1d19b4..f7073415dcc 100644 --- a/op-e2e/actions/upgrades/holocene_fork_test.go +++ b/op-e2e/actions/upgrades/holocene_fork_test.go @@ -9,15 +9,15 @@ import ( "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/testlog" ) func TestHoloceneActivationAtGenesis(gt *testing.T) { t := helpers.NewDefaultTesting(gt) - env := helpers.SetupEnv(t, helpers.WithActiveGenesisFork(rollup.Holocene)) + env := helpers.SetupEnv(t, helpers.WithActiveGenesisFork(forks.Holocene)) // Start op-nodes env.Seq.ActL2PipelineFull(t) @@ -53,7 +53,7 @@ func TestHoloceneActivationAtGenesis(gt *testing.T) { func TestHoloceneLateActivationAndReset(gt *testing.T) { t := helpers.NewDefaultTesting(gt) holoceneOffset := uint64(24) - env := helpers.SetupEnv(t, helpers.WithActiveFork(rollup.Holocene, holoceneOffset)) + env := helpers.SetupEnv(t, helpers.WithActiveFork(forks.Holocene, holoceneOffset)) requireHoloceneTransformationLogs := func(role string, expNumLogs int) { recs := env.Logs.FindLogs(testlog.NewMessageContainsFilter("transforming to Holocene"), testlog.NewAttributesFilter("role", role)) @@ -135,7 +135,7 @@ func TestHoloceneLateActivationAndReset(gt *testing.T) { func TestHoloceneInvalidPayload(gt *testing.T) { t := helpers.NewDefaultTesting(gt) - env := helpers.SetupEnv(t, helpers.WithActiveGenesisFork(rollup.Holocene)) + env := helpers.SetupEnv(t, helpers.WithActiveGenesisFork(forks.Holocene)) ctx := context.Background() requireDepositOnlyLogs := func(role string, expNumLogs int) { diff --git a/op-e2e/config/init.go b/op-e2e/config/init.go index d13a87d90bb..48867df80a6 100644 --- a/op-e2e/config/init.go +++ b/op-e2e/config/init.go @@ -13,13 +13,13 @@ import ( "time" "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/inspect" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "golang.org/x/exp/maps" @@ -257,7 +257,7 @@ func initAllocType(root string, allocType AllocType) { } upgradeSchedule := new(genesis.UpgradeScheduleDeployConfig) - upgradeSchedule.ActivateForkAtGenesis(rollup.ForkName(mode)) + upgradeSchedule.ActivateForkAtGenesis(forks.Name(mode)) upgradeOverridesJSON, err := json.Marshal(upgradeSchedule) if err != nil { panic(fmt.Errorf("failed to marshal upgrade schedule: %w", err)) diff --git a/op-e2e/e2eutils/intentbuilder/builder.go b/op-e2e/e2eutils/intentbuilder/builder.go index a1946f98090..8a8ac2d54e5 100644 --- a/op-e2e/e2eutils/intentbuilder/builder.go +++ b/op-e2e/e2eutils/intentbuilder/builder.go @@ -14,10 +14,10 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/addresses" "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -91,8 +91,8 @@ type L2FeesConfigurator interface { } type L2HardforkConfigurator interface { - WithForkAtGenesis(fork rollup.ForkName) - WithForkAtOffset(fork rollup.ForkName, offset *uint64) + WithForkAtGenesis(fork forks.Name) + WithForkAtOffset(fork forks.Name, offset *uint64) } type Builder interface { @@ -431,10 +431,10 @@ func (c *l2Configurator) WithOperatorFeeConstant(value uint64) { c.builder.intent.Chains[c.chainIndex].OperatorFeeConstant = value } -func (c *l2Configurator) WithForkAtGenesis(fork rollup.ForkName) { +func (c *l2Configurator) WithForkAtGenesis(fork forks.Name) { var future bool - for _, refFork := range rollup.AllForks { - if refFork == rollup.Bedrock { + for _, refFork := range forks.All { + if refFork == forks.Bedrock { continue } @@ -450,8 +450,8 @@ func (c *l2Configurator) WithForkAtGenesis(fork rollup.ForkName) { } } -func (c *l2Configurator) WithForkAtOffset(fork rollup.ForkName, offset *uint64) { - require.True(c.t, rollup.IsValidFork(fork)) +func (c *l2Configurator) WithForkAtOffset(fork forks.Name, offset *uint64) { + require.True(c.t, forks.IsValid(fork)) key := fmt.Sprintf("l2Genesis%sTimeOffset", cases.Title(language.English).String(string(fork))) if offset == nil { diff --git a/op-e2e/e2eutils/intentbuilder/builder_test.go b/op-e2e/e2eutils/intentbuilder/builder_test.go index 7d8d9862c91..661091adc63 100644 --- a/op-e2e/e2eutils/intentbuilder/builder_test.go +++ b/op-e2e/e2eutils/intentbuilder/builder_test.go @@ -12,10 +12,10 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum-optimism/optimism/op-chain-ops/addresses" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -114,8 +114,8 @@ func TestBuilder(t *testing.T) { // Test L2HardforkConfigurator methods isthmusOffset := uint64(8000) - l2Config.WithForkAtGenesis(rollup.Holocene) - l2Config.WithForkAtOffset(rollup.Isthmus, &isthmusOffset) + l2Config.WithForkAtGenesis(forks.Holocene) + l2Config.WithForkAtOffset(forks.Isthmus, &isthmusOffset) // Build the intent intent, err := builder.Build() diff --git a/op-e2e/system/bridge/deposit_test.go b/op-e2e/system/bridge/deposit_test.go index a79147cee16..70d06c1c33b 100644 --- a/op-e2e/system/bridge/deposit_test.go +++ b/op-e2e/system/bridge/deposit_test.go @@ -8,7 +8,6 @@ import ( "time" op_e2e "github.com/ethereum-optimism/optimism/op-e2e" - "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/holiman/uint256" "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" @@ -16,6 +15,7 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -129,7 +129,7 @@ func TestMintCallToDelegatedAccount(t *testing.T) { op_e2e.InitParallel(t) cfg := e2esys.DefaultSystemConfig(t) cfg.DeployConfig = cfg.DeployConfig.Copy() - cfg.DeployConfig.ActivateForkAtGenesis(rollup.Isthmus) + cfg.DeployConfig.ActivateForkAtGenesis(forks.Isthmus) delete(cfg.Nodes, "verifier") sys, err := cfg.Start(t) require.NoError(t, err, "Error starting up system") diff --git a/op-node/rollup/attributes/engine_consolidate_test.go b/op-node/rollup/attributes/engine_consolidate_test.go index 702355ae0da..4094758c28f 100644 --- a/op-node/rollup/attributes/engine_consolidate_test.go +++ b/op-node/rollup/attributes/engine_consolidate_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" @@ -232,126 +233,126 @@ func TestAttributesMatch(t *testing.T) { }{ { args: bedrockArgs(), - rollupCfg: cfg(rollup.Bedrock), + rollupCfg: cfg(forks.Bedrock), desc: "validBedrockArgs", }, { args: bedrockArgs(), - rollupCfg: cfg(rollup.Canyon), + rollupCfg: cfg(forks.Canyon), err: ErrCanyonMustHaveWithdrawals.Error() + ": block", desc: "bedrockArgsPostCanyon", }, { args: canyonArgs(), - rollupCfg: cfg(rollup.Canyon), + rollupCfg: cfg(forks.Canyon), desc: "validCanyonArgs", }, { args: ecotoneArgs(), - rollupCfg: cfg(rollup.Ecotone), + rollupCfg: cfg(forks.Ecotone), desc: "validEcotoneArgs", }, { args: holoceneArgs(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), desc: "validholoceneArgs", }, { args: jovianArgs(), - rollupCfg: cfg(rollup.Jovian), + rollupCfg: cfg(forks.Jovian), desc: "validJovianArgs", }, { args: mismatchedParentHashArgs(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "parent hash field does not match", desc: "mismatchedParentHashArgs", }, { args: createMismatchedTimestamp(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "timestamp field does not match", desc: "createMismatchedTimestamp", }, { args: createMismatchedPrevRandao(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "random field does not match", desc: "createMismatchedPrevRandao", }, { args: createMismatchedTransactions(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "transaction count does not match", desc: "createMismatchedTransactions", }, { args: ecotoneNoParentBeaconBlockRoot(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "expected non-nil parent beacon block root", desc: "ecotoneNoParentBeaconBlockRoot", }, { args: ecotoneUnexpectedParentBeaconBlockRoot(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "expected nil parent beacon block root but got non-nil", desc: "ecotoneUnexpectedParentBeaconBlockRoot", }, { args: ecotoneMismatchParentBeaconBlockRoot(), - rollupCfg: cfg(rollup.Ecotone), + rollupCfg: cfg(forks.Ecotone), err: "parent beacon block root does not match", desc: "ecotoneMismatchParentBeaconBlockRoot", }, { args: ecotoneMismatchParentBeaconBlockRootPtr(), - rollupCfg: cfg(rollup.Ecotone), + rollupCfg: cfg(forks.Ecotone), desc: "ecotoneMismatchParentBeaconBlockRootPtr", }, { args: ecotoneNilParentBeaconBlockRoots(), - rollupCfg: cfg(rollup.Ecotone), + rollupCfg: cfg(forks.Ecotone), desc: "ecotoneNilParentBeaconBlockRoots", }, { args: createMismatchedGasLimit(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "gas limit does not match", desc: "createMismatchedGasLimit", }, { args: createNilGasLimit(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "expected gaslimit in attributes to not be nil", desc: "createNilGasLimit", }, { args: createMismatchedFeeRecipient(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "fee recipient data does not match", desc: "createMismatchedFeeRecipient", }, { args: createMismatchedEIP1559Params(), - rollupCfg: cfg(rollup.Holocene), + rollupCfg: cfg(forks.Holocene), err: "eip1559 parameters do not match", desc: "createMismatchedEIP1559Params", }, { args: jovianArgsMinBaseFeeMissingFromAttributes(), - rollupCfg: cfg(rollup.Jovian), + rollupCfg: cfg(forks.Jovian), err: "minBaseFee does not match", desc: "missingMinBaseFee", }, { args: jovianArgsMinBaseFeeMissingFromBlock(), - rollupCfg: cfg(rollup.Jovian), + rollupCfg: cfg(forks.Jovian), err: "invalid block extraData: MinBaseFee extraData should be 17 bytes, got 9", desc: "missingMinBaseFee", }, { args: jovianArgsInconsistentMinBaseFee(), - rollupCfg: cfg(rollup.Jovian), + rollupCfg: cfg(forks.Jovian), err: "minBaseFee does not match", desc: "inconsistentMinBaseFee", }, diff --git a/op-node/rollup/chain_spec.go b/op-node/rollup/chain_spec.go index e2a6ae44efc..9e432e21b71 100644 --- a/op-node/rollup/chain_spec.go +++ b/op-node/rollup/chain_spec.go @@ -1,9 +1,9 @@ package rollup import ( - "fmt" "math/big" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/params" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/log" @@ -30,66 +30,8 @@ const ( // ChainSpec instead of reading the rollup configuration field directly. const maxSequencerDriftFjord = 1800 -type ForkName string - -const ( - Bedrock ForkName = "bedrock" - Regolith ForkName = "regolith" - Canyon ForkName = "canyon" - Delta ForkName = "delta" - Ecotone ForkName = "ecotone" - Fjord ForkName = "fjord" - Granite ForkName = "granite" - Holocene ForkName = "holocene" - Isthmus ForkName = "isthmus" - Jovian ForkName = "jovian" - Interop ForkName = "interop" - // ADD NEW FORKS TO AllForks BELOW! - None ForkName = "" -) - -var AllForks = []ForkName{ - Bedrock, - Regolith, - Canyon, - Delta, - Ecotone, - Fjord, - Granite, - Holocene, - Isthmus, - Jovian, - Interop, - // ADD NEW FORKS HERE! -} - -var LatestFork = AllForks[len(AllForks)-1] - -func ForksFrom(fork ForkName) []ForkName { - for i, f := range AllForks { - if f == fork { - return AllForks[i:] - } - } - panic(fmt.Sprintf("invalid fork: %s", fork)) -} - -var nextFork = func() map[ForkName]ForkName { - m := make(map[ForkName]ForkName, len(AllForks)) - for i, f := range AllForks { - if i == len(AllForks)-1 { - m[f] = None - break - } - m[f] = AllForks[i+1] - } - return m -}() - -func IsValidFork(fork ForkName) bool { - _, ok := nextFork[fork] - return ok -} +// Legacy type alias kept temporarily for rollup internals; external code should use forks.Name directly. +type ForkName = forks.Name type ChainSpec struct { config *Config @@ -175,36 +117,36 @@ func (s *ChainSpec) MaxSequencerDrift(t uint64) uint64 { func (s *ChainSpec) CheckForkActivation(log log.Logger, block eth.L2BlockRef) { if s.currentFork == "" { // Initialize currentFork if it is not set yet - s.currentFork = Bedrock + s.currentFork = forks.Bedrock if s.config.IsRegolith(block.Time) { - s.currentFork = Regolith + s.currentFork = forks.Regolith } if s.config.IsCanyon(block.Time) { - s.currentFork = Canyon + s.currentFork = forks.Canyon } if s.config.IsDelta(block.Time) { - s.currentFork = Delta + s.currentFork = forks.Delta } if s.config.IsEcotone(block.Time) { - s.currentFork = Ecotone + s.currentFork = forks.Ecotone } if s.config.IsFjord(block.Time) { - s.currentFork = Fjord + s.currentFork = forks.Fjord } if s.config.IsGranite(block.Time) { - s.currentFork = Granite + s.currentFork = forks.Granite } if s.config.IsHolocene(block.Time) { - s.currentFork = Holocene + s.currentFork = forks.Holocene } if s.config.IsIsthmus(block.Time) { - s.currentFork = Isthmus + s.currentFork = forks.Isthmus } if s.config.IsJovian(block.Time) { - s.currentFork = Jovian + s.currentFork = forks.Jovian } if s.config.IsInterop(block.Time) { - s.currentFork = Interop + s.currentFork = forks.Interop } log.Info("Current hardfork version detected", "forkName", s.currentFork) return @@ -212,31 +154,31 @@ func (s *ChainSpec) CheckForkActivation(log log.Logger, block eth.L2BlockRef) { foundActivationBlock := false - switch nextFork[s.currentFork] { - case Regolith: + switch forks.Next(s.currentFork) { + case forks.Regolith: foundActivationBlock = s.config.IsRegolithActivationBlock(block.Time) - case Canyon: + case forks.Canyon: foundActivationBlock = s.config.IsCanyonActivationBlock(block.Time) - case Delta: + case forks.Delta: foundActivationBlock = s.config.IsDeltaActivationBlock(block.Time) - case Ecotone: + case forks.Ecotone: foundActivationBlock = s.config.IsEcotoneActivationBlock(block.Time) - case Fjord: + case forks.Fjord: foundActivationBlock = s.config.IsFjordActivationBlock(block.Time) - case Granite: + case forks.Granite: foundActivationBlock = s.config.IsGraniteActivationBlock(block.Time) - case Holocene: + case forks.Holocene: foundActivationBlock = s.config.IsHoloceneActivationBlock(block.Time) - case Isthmus: + case forks.Isthmus: foundActivationBlock = s.config.IsIsthmusActivationBlock(block.Time) - case Jovian: + case forks.Jovian: foundActivationBlock = s.config.IsJovianActivationBlock(block.Time) - case Interop: + case forks.Interop: foundActivationBlock = s.config.IsInteropActivationBlock(block.Time) } if foundActivationBlock { - s.currentFork = nextFork[s.currentFork] + s.currentFork = forks.Next(s.currentFork) log.Info("Detected hardfork activation block", "forkName", s.currentFork, "timestamp", block.Time, "blockNum", block.Number, "hash", block.Hash) } } diff --git a/op-node/rollup/chain_spec_test.go b/op-node/rollup/chain_spec_test.go index 02601a4d9d8..8e488665d15 100644 --- a/op-node/rollup/chain_spec_test.go +++ b/op-node/rollup/chain_spec_test.go @@ -5,6 +5,7 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" @@ -159,55 +160,55 @@ func TestCheckForkActivation(t *testing.T) { { name: "Regolith activation", block: eth.L2BlockRef{Time: 10, Number: 5, Hash: common.Hash{0x5}}, - expectedCurrentFork: Regolith, + expectedCurrentFork: forks.Regolith, expectedLog: "Detected hardfork activation block", }, { name: "Still Regolith", block: eth.L2BlockRef{Time: 11, Number: 6, Hash: common.Hash{0x6}}, - expectedCurrentFork: Regolith, + expectedCurrentFork: forks.Regolith, expectedLog: "", }, { name: "Canyon activation", block: eth.L2BlockRef{Time: 20, Number: 7, Hash: common.Hash{0x7}}, - expectedCurrentFork: Canyon, + expectedCurrentFork: forks.Canyon, expectedLog: "Detected hardfork activation block", }, { name: "Granite activation", block: eth.L2BlockRef{Time: 60, Number: 8, Hash: common.Hash{0x8}}, - expectedCurrentFork: Granite, + expectedCurrentFork: forks.Granite, expectedLog: "Detected hardfork activation block", }, { name: "Holocene activation", block: eth.L2BlockRef{Time: 70, Number: 9, Hash: common.Hash{0x9}}, - expectedCurrentFork: Holocene, + expectedCurrentFork: forks.Holocene, expectedLog: "Detected hardfork activation block", }, { name: "Isthmus activation", block: eth.L2BlockRef{Time: 80, Number: 10, Hash: common.Hash{0xa}}, - expectedCurrentFork: Isthmus, + expectedCurrentFork: forks.Isthmus, expectedLog: "Detected hardfork activation block", }, { name: "Jovian activation", block: eth.L2BlockRef{Time: 90, Number: 11, Hash: common.Hash{0xb}}, - expectedCurrentFork: Jovian, + expectedCurrentFork: forks.Jovian, expectedLog: "Detected hardfork activation block", }, { name: "Interop activation", block: eth.L2BlockRef{Time: 100, Number: 11, Hash: common.Hash{0xb}}, - expectedCurrentFork: Interop, + expectedCurrentFork: forks.Interop, expectedLog: "Detected hardfork activation block", }, { name: "No more hardforks", block: eth.L2BlockRef{Time: 700, Number: 12, Hash: common.Hash{0xc}}, - expectedCurrentFork: Interop, + expectedCurrentFork: forks.Interop, expectedLog: "", }, } diff --git a/op-node/rollup/derive/attributes_test.go b/op-node/rollup/derive/attributes_test.go index 5d1056b4622..744caec0313 100644 --- a/op-node/rollup/derive/attributes_test.go +++ b/op-node/rollup/derive/attributes_test.go @@ -8,6 +8,7 @@ import ( "math/rand" "testing" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" @@ -230,7 +231,7 @@ func TestPreparePayloadAttributes(t *testing.T) { require.NoError(t, err) // sets config to post-interop - cfg.ActivateAtGenesis(rollup.Interop) + cfg.ActivateAtGenesis(forks.Interop) seqNumber := uint64(0) epoch := l1Info.ID() @@ -271,7 +272,7 @@ func TestPreparePayloadAttributes(t *testing.T) { l1Info.InfoNum = l2Parent.L1Origin.Number // same origin again, so the sequence number is not reset // sets config to post-interop - cfg.ActivateAtGenesis(rollup.Interop) + cfg.ActivateAtGenesis(forks.Interop) seqNumber := l2Parent.SequenceNumber + 1 epoch := l1Info.ID() @@ -297,7 +298,7 @@ func TestPreparePayloadAttributes(t *testing.T) { t.Run("holocene 1559 params", func(t *testing.T) { cfg := mkCfg() - cfg.ActivateAtGenesis(rollup.Holocene) + cfg.ActivateAtGenesis(forks.Holocene) rng := rand.New(rand.NewSource(1234)) l1Fetcher := &testutils.MockL1Source{} defer l1Fetcher.AssertExpectations(t) @@ -382,7 +383,7 @@ func TestPreparePayloadAttributes(t *testing.T) { t.Run("interop", func(t *testing.T) { prepareActivationAttributes := func(t *testing.T, depSet depset.DependencySet) *eth.PayloadAttributes { cfg := mkCfg() - cfg.ActivateAtGenesis(rollup.Isthmus) + cfg.ActivateAtGenesis(forks.Isthmus) interopTime := uint64(1000) cfg.InteropTime = &interopTime rng := rand.New(rand.NewSource(1234)) @@ -444,7 +445,7 @@ func TestPreparePayloadAttributes(t *testing.T) { t.Run("minimum base fee param", func(t *testing.T) { cfg := mkCfg() - cfg.ActivateAtGenesis(rollup.Jovian) + cfg.ActivateAtGenesis(forks.Jovian) rng := rand.New(rand.NewSource(1234)) l1Fetcher := &testutils.MockL1Source{} defer l1Fetcher.AssertExpectations(t) diff --git a/op-node/rollup/derive/batch_mux.go b/op-node/rollup/derive/batch_mux.go index f5eeb95613c..e18fc69d232 100644 --- a/op-node/rollup/derive/batch_mux.go +++ b/op-node/rollup/derive/batch_mux.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/log" @@ -48,9 +49,9 @@ func (b *BatchMux) Reset(ctx context.Context, base eth.L1BlockRef, sysCfg eth.Sy return b.SingularBatchProvider.Reset(ctx, base, sysCfg) } -func (b *BatchMux) Transform(f rollup.ForkName) { +func (b *BatchMux) Transform(f forks.Name) { switch f { - case rollup.Holocene: + case forks.Holocene: b.TransformHolocene() } } diff --git a/op-node/rollup/derive/batch_mux_test.go b/op-node/rollup/derive/batch_mux_test.go index 2afc25a69dc..2cb82ec6fe6 100644 --- a/op-node/rollup/derive/batch_mux_test.go +++ b/op-node/rollup/derive/batch_mux_test.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" @@ -31,7 +32,7 @@ func TestBatchMux_LaterHolocene(t *testing.T) { require.IsType(t, new(BatchQueue), b.SingularBatchProvider) require.Equal(t, l1A, b.SingularBatchProvider.(*BatchQueue).origin) - b.Transform(rollup.Holocene) + b.Transform(forks.Holocene) require.IsType(t, new(BatchStage), b.SingularBatchProvider) require.Equal(t, l1A, b.SingularBatchProvider.(*BatchStage).origin) @@ -64,5 +65,5 @@ func TestBatchMux_ActiveHolocene(t *testing.T) { require.IsType(t, new(BatchStage), b.SingularBatchProvider) require.Equal(t, l1A, b.SingularBatchProvider.(*BatchStage).origin) - require.Panics(t, func() { b.Transform(rollup.Holocene) }) + require.Panics(t, func() { b.Transform(forks.Holocene) }) } diff --git a/op-node/rollup/derive/batches_test.go b/op-node/rollup/derive/batches_test.go index 3a668f66f52..ade8d9df4c3 100644 --- a/op-node/rollup/derive/batches_test.go +++ b/op-node/rollup/derive/batches_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" @@ -655,7 +656,7 @@ func TestValidBatch(t *testing.T) { // Add test cases for all forks from Jovian to assert that upgrade block must not contain user // txs. If a future fork should allow user txs in its upgrade block, it must be removed from // this list explicitly. - for _, fork := range rollup.ForksFrom(rollup.Jovian) { + for _, fork := range forks.From(forks.Jovian) { singularBatchTestCases = append(singularBatchTestCases, ValidBatchTestCase{ Name: fmt.Sprintf("user txs in %s upgrade block", fork), L1Blocks: []eth.L1BlockRef{l1A, l1B, l1C}, diff --git a/op-node/rollup/derive/channel_mux.go b/op-node/rollup/derive/channel_mux.go index 44246eeae39..c844cbd1e43 100644 --- a/op-node/rollup/derive/channel_mux.go +++ b/op-node/rollup/derive/channel_mux.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/log" @@ -52,9 +53,9 @@ func (c *ChannelMux) Reset(ctx context.Context, base eth.L1BlockRef, sysCfg eth. return c.RawChannelProvider.Reset(ctx, base, sysCfg) } -func (c *ChannelMux) Transform(f rollup.ForkName) { +func (c *ChannelMux) Transform(f forks.Name) { switch f { - case rollup.Holocene: + case forks.Holocene: c.TransformHolocene() } } diff --git a/op-node/rollup/derive/channel_mux_test.go b/op-node/rollup/derive/channel_mux_test.go index 59fd669922a..05ad2f0e8a6 100644 --- a/op-node/rollup/derive/channel_mux_test.go +++ b/op-node/rollup/derive/channel_mux_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -34,7 +35,7 @@ func TestChannelMux_LaterHolocene(t *testing.T) { require.Equal(t, io.EOF, err) require.IsType(t, new(ChannelBank), c.RawChannelProvider) - c.Transform(rollup.Holocene) + c.Transform(forks.Holocene) require.IsType(t, new(ChannelAssembler), c.RawChannelProvider) err = c.Reset(ctx, l1B, eth.SystemConfig{}) @@ -65,5 +66,5 @@ func TestChannelMux_ActiveHolocene(t *testing.T) { require.Equal(t, io.EOF, err) require.IsType(t, new(ChannelAssembler), c.RawChannelProvider) - require.Panics(t, func() { c.Transform(rollup.Holocene) }) + require.Panics(t, func() { c.Transform(forks.Holocene) }) } diff --git a/op-node/rollup/derive/frame_queue.go b/op-node/rollup/derive/frame_queue.go index 361f1cfda88..c2266aac3b8 100644 --- a/op-node/rollup/derive/frame_queue.go +++ b/op-node/rollup/derive/frame_queue.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -36,9 +37,9 @@ func NewFrameQueue(log log.Logger, cfg *rollup.Config, prev NextDataProvider) *F } } -func (fq *FrameQueue) Transform(f rollup.ForkName) { +func (fq *FrameQueue) Transform(f forks.Name) { switch f { - case rollup.Holocene: + case forks.Holocene: fq.log.Info("FrameQueue: resetting with Holocene activation") // With Holocene activation, the frame queue is simply reset fq.reset() diff --git a/op-node/rollup/derive/l1_block_info_test.go b/op-node/rollup/derive/l1_block_info_test.go index ebcd60139dc..463eeb0a1fe 100644 --- a/op-node/rollup/derive/l1_block_info_test.go +++ b/op-node/rollup/derive/l1_block_info_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testutils" @@ -112,7 +113,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{} - rollupCfg.ActivateAtGenesis(rollup.Regolith) + rollupCfg.ActivateAtGenesis(forks.Regolith) depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, 0) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) @@ -122,7 +123,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Ecotone) + rollupCfg.ActivateAtGenesis(forks.Ecotone) // run 1 block after ecotone transition timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) @@ -135,7 +136,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Delta) + rollupCfg.ActivateAtGenesis(forks.Delta) ecotoneTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate ecotone just after genesis rollupCfg.EcotoneTime = &ecotoneTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, ecotoneTime) @@ -148,7 +149,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Ecotone) + rollupCfg.ActivateAtGenesis(forks.Ecotone) depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) @@ -159,7 +160,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Isthmus) + rollupCfg.ActivateAtGenesis(forks.Isthmus) // run 1 block after isthmus transition timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) @@ -172,7 +173,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Holocene) + rollupCfg.ActivateAtGenesis(forks.Holocene) isthmusTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate isthmus just after genesis rollupCfg.IsthmusTime = &isthmusTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, isthmusTime) @@ -187,7 +188,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Isthmus) + rollupCfg.ActivateAtGenesis(forks.Isthmus) depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) @@ -198,7 +199,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Jovian) + rollupCfg.ActivateAtGenesis(forks.Jovian) // run 1 block after Jovian transition timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) @@ -215,7 +216,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Isthmus) + rollupCfg.ActivateAtGenesis(forks.Isthmus) jovianTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate jovian just after genesis rollupCfg.InteropTime = &jovianTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, jovianTime) @@ -230,7 +231,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Jovian) + rollupCfg.ActivateAtGenesis(forks.Jovian) depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) @@ -241,7 +242,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Interop) + rollupCfg.ActivateAtGenesis(forks.Interop) // run 1 block after interop transition timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) @@ -254,7 +255,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Jovian) + rollupCfg.ActivateAtGenesis(forks.Jovian) interopTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate interop just after genesis rollupCfg.InteropTime = &interopTime depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, interopTime) @@ -268,7 +269,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} - rollupCfg.ActivateAtGenesis(rollup.Interop) + rollupCfg.ActivateAtGenesis(forks.Interop) depTx, err := L1InfoDeposit(&rollupCfg, params.MergedTestChainConfig, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) diff --git a/op-node/rollup/derive/pipeline.go b/op-node/rollup/derive/pipeline.go index bae024da1c2..67f0511eac4 100644 --- a/op-node/rollup/derive/pipeline.go +++ b/op-node/rollup/derive/pipeline.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -49,7 +50,7 @@ type ChannelFlusher interface { } type ForkTransformer interface { - Transform(rollup.ForkName) + Transform(forks.Name) } type L2Source interface { @@ -273,7 +274,7 @@ func (dp *DerivationPipeline) initialReset(ctx context.Context, resetL2Safe eth. func (db *DerivationPipeline) transformStages(oldOrigin, newOrigin eth.L1BlockRef) { fork := db.rollupCfg.IsActivationBlock(oldOrigin.Time, newOrigin.Time) - if fork == rollup.None { + if fork == forks.None { return } diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index 7209663eca7..0d64e033118 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -10,6 +10,7 @@ import ( "time" altda "github.com/ethereum-optimism/optimism/op-alt-da" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -339,25 +340,25 @@ func (cfg *Config) Check() error { return err } - if err := checkFork(cfg.RegolithTime, cfg.CanyonTime, Regolith, Canyon); err != nil { + if err := checkFork(cfg.RegolithTime, cfg.CanyonTime, forks.Regolith, forks.Canyon); err != nil { return err } - if err := checkFork(cfg.CanyonTime, cfg.DeltaTime, Canyon, Delta); err != nil { + if err := checkFork(cfg.CanyonTime, cfg.DeltaTime, forks.Canyon, forks.Delta); err != nil { return err } - if err := checkFork(cfg.DeltaTime, cfg.EcotoneTime, Delta, Ecotone); err != nil { + if err := checkFork(cfg.DeltaTime, cfg.EcotoneTime, forks.Delta, forks.Ecotone); err != nil { return err } - if err := checkFork(cfg.EcotoneTime, cfg.FjordTime, Ecotone, Fjord); err != nil { + if err := checkFork(cfg.EcotoneTime, cfg.FjordTime, forks.Ecotone, forks.Fjord); err != nil { return err } - if err := checkFork(cfg.FjordTime, cfg.GraniteTime, Fjord, Granite); err != nil { + if err := checkFork(cfg.FjordTime, cfg.GraniteTime, forks.Fjord, forks.Granite); err != nil { return err } - if err := checkFork(cfg.GraniteTime, cfg.HoloceneTime, Granite, Holocene); err != nil { + if err := checkFork(cfg.GraniteTime, cfg.HoloceneTime, forks.Granite, forks.Holocene); err != nil { return err } - if err := checkFork(cfg.HoloceneTime, cfg.IsthmusTime, Holocene, Isthmus); err != nil { + if err := checkFork(cfg.HoloceneTime, cfg.IsthmusTime, forks.Holocene, forks.Isthmus); err != nil { return err } @@ -438,52 +439,52 @@ func (c *Config) IsForkActive(fork ForkName, timestamp uint64) bool { // IsRegolith returns true if the Regolith hardfork is active at or past the given timestamp. func (c *Config) IsRegolith(timestamp uint64) bool { - return c.IsForkActive(Regolith, timestamp) + return c.IsForkActive(forks.Regolith, timestamp) } // IsCanyon returns true if the Canyon hardfork is active at or past the given timestamp. func (c *Config) IsCanyon(timestamp uint64) bool { - return c.IsForkActive(Canyon, timestamp) + return c.IsForkActive(forks.Canyon, timestamp) } // IsDelta returns true if the Delta hardfork is active at or past the given timestamp. func (c *Config) IsDelta(timestamp uint64) bool { - return c.IsForkActive(Delta, timestamp) + return c.IsForkActive(forks.Delta, timestamp) } // IsEcotone returns true if the Ecotone hardfork is active at or past the given timestamp. func (c *Config) IsEcotone(timestamp uint64) bool { - return c.IsForkActive(Ecotone, timestamp) + return c.IsForkActive(forks.Ecotone, timestamp) } // IsFjord returns true if the Fjord hardfork is active at or past the given timestamp. func (c *Config) IsFjord(timestamp uint64) bool { - return c.IsForkActive(Fjord, timestamp) + return c.IsForkActive(forks.Fjord, timestamp) } // IsGranite returns true if the Granite hardfork is active at or past the given timestamp. func (c *Config) IsGranite(timestamp uint64) bool { - return c.IsForkActive(Granite, timestamp) + return c.IsForkActive(forks.Granite, timestamp) } // IsHolocene returns true if the Holocene hardfork is active at or past the given timestamp. func (c *Config) IsHolocene(timestamp uint64) bool { - return c.IsForkActive(Holocene, timestamp) + return c.IsForkActive(forks.Holocene, timestamp) } // IsIsthmus returns true if the Isthmus hardfork is active at or past the given timestamp. func (c *Config) IsIsthmus(timestamp uint64) bool { - return c.IsForkActive(Isthmus, timestamp) + return c.IsForkActive(forks.Isthmus, timestamp) } // IsJovian returns true if the Jovian hardfork is active at or past the given timestamp. func (c *Config) IsJovian(timestamp uint64) bool { - return c.IsForkActive(Jovian, timestamp) + return c.IsForkActive(forks.Jovian, timestamp) } // IsInterop returns true if the Interop hardfork is active at or past the given timestamp. func (c *Config) IsInterop(timestamp uint64) bool { - return c.IsForkActive(Interop, timestamp) + return c.IsForkActive(forks.Interop, timestamp) } func (c *Config) IsRegolithActivationBlock(l2BlockTime uint64) bool { @@ -561,25 +562,25 @@ func (c *Config) IsInteropActivationBlock(l2BlockTime uint64) bool { func (c *Config) ActivationTime(fork ForkName) *uint64 { // NEW FORKS MUST BE ADDED HERE switch fork { - case Interop: + case forks.Interop: return c.InteropTime - case Jovian: + case forks.Jovian: return c.JovianTime - case Isthmus: + case forks.Isthmus: return c.IsthmusTime - case Holocene: + case forks.Holocene: return c.HoloceneTime - case Granite: + case forks.Granite: return c.GraniteTime - case Fjord: + case forks.Fjord: return c.FjordTime - case Ecotone: + case forks.Ecotone: return c.EcotoneTime - case Delta: + case forks.Delta: return c.DeltaTime - case Canyon: + case forks.Canyon: return c.CanyonTime - case Regolith: + case forks.Regolith: return c.RegolithTime default: panic(fmt.Sprintf("unknown fork: %v", fork)) @@ -589,25 +590,25 @@ func (c *Config) ActivationTime(fork ForkName) *uint64 { func (c *Config) SetActivationTime(fork ForkName, timestamp *uint64) { // NEW FORKS MUST BE ADDED HERE switch fork { - case Interop: + case forks.Interop: c.InteropTime = timestamp - case Jovian: + case forks.Jovian: c.JovianTime = timestamp - case Isthmus: + case forks.Isthmus: c.IsthmusTime = timestamp - case Holocene: + case forks.Holocene: c.HoloceneTime = timestamp - case Granite: + case forks.Granite: c.GraniteTime = timestamp - case Fjord: + case forks.Fjord: c.FjordTime = timestamp - case Ecotone: + case forks.Ecotone: c.EcotoneTime = timestamp - case Delta: + case forks.Delta: c.DeltaTime = timestamp - case Canyon: + case forks.Canyon: c.CanyonTime = timestamp - case Regolith: + case forks.Regolith: c.RegolithTime = timestamp default: panic(fmt.Sprintf("unknown fork: %v", fork)) @@ -623,7 +624,7 @@ func (c *Config) IsActivationBlock(oldTime, newTime uint64) ForkName { return fork } } - return None + return forks.None } func (c *Config) IsActivationBlockForFork(l2BlockTime uint64, fork ForkName) bool { @@ -638,17 +639,17 @@ func (c *Config) ActivateAtGenesis(hardfork ForkName) { c.ActivateAt(hardfork, 0) } -var scheduleableForks = ForksFrom(Regolith) +var scheduleableForks = forks.From(forks.Regolith) // ActivateAt updates the config to activate the given fork at the given timestamp, all previous // forks at genesis, and all later forks are disabled. func (c *Config) ActivateAt(fork ForkName, timestamp uint64) { - if !IsValidFork(fork) { + if !forks.IsValid(fork) { panic(fmt.Sprintf("invalid fork: %s", fork)) } ts := new(uint64) // Special case: if only activating Bedrock, all scheduleable forks are disabled. - if fork == Bedrock { + if fork == forks.Bedrock { ts = nil } for i, f := range scheduleableForks { diff --git a/op-node/rollup/types_test.go b/op-node/rollup/types_test.go index 90069e22971..b1f8efbe528 100644 --- a/op-node/rollup/types_test.go +++ b/op-node/rollup/types_test.go @@ -12,16 +12,17 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimism/op-service/ptr" - "github.com/ethereum-optimism/optimism/op-service/testlog" - "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/ptr" + "github.com/ethereum-optimism/optimism/op-service/testlog" ) func randConfig() *Config { @@ -828,34 +829,34 @@ func TestGetPayloadVersion(t *testing.T) { func TestConfig_IsActivationBlock(t *testing.T) { // Map of fork names to their config field setters - forks := []struct { - name ForkName + tests := []struct { + name forks.Name setTime func(cfg *Config, ts uint64) }{ - {Canyon, func(cfg *Config, ts uint64) { cfg.CanyonTime = &ts }}, - {Delta, func(cfg *Config, ts uint64) { cfg.DeltaTime = &ts }}, - {Ecotone, func(cfg *Config, ts uint64) { cfg.EcotoneTime = &ts }}, - {Fjord, func(cfg *Config, ts uint64) { cfg.FjordTime = &ts }}, - {Granite, func(cfg *Config, ts uint64) { cfg.GraniteTime = &ts }}, - {Holocene, func(cfg *Config, ts uint64) { cfg.HoloceneTime = &ts }}, - {Isthmus, func(cfg *Config, ts uint64) { cfg.IsthmusTime = &ts }}, - {Interop, func(cfg *Config, ts uint64) { cfg.InteropTime = &ts }}, + {forks.Canyon, func(cfg *Config, ts uint64) { cfg.CanyonTime = &ts }}, + {forks.Delta, func(cfg *Config, ts uint64) { cfg.DeltaTime = &ts }}, + {forks.Ecotone, func(cfg *Config, ts uint64) { cfg.EcotoneTime = &ts }}, + {forks.Fjord, func(cfg *Config, ts uint64) { cfg.FjordTime = &ts }}, + {forks.Granite, func(cfg *Config, ts uint64) { cfg.GraniteTime = &ts }}, + {forks.Holocene, func(cfg *Config, ts uint64) { cfg.HoloceneTime = &ts }}, + {forks.Isthmus, func(cfg *Config, ts uint64) { cfg.IsthmusTime = &ts }}, + {forks.Interop, func(cfg *Config, ts uint64) { cfg.InteropTime = &ts }}, } - for _, fork := range forks { + for _, tc := range tests { ts := uint64(100) cfg := &Config{} - fork.setTime(cfg, ts) + tc.setTime(cfg, ts) - t.Run(string(fork.name), func(t *testing.T) { + t.Run(string(tc.name), func(t *testing.T) { // Crossing the fork boundary should return the fork name - require.Equal(t, fork.name, cfg.IsActivationBlock(ts-1, ts)) - require.Equal(t, fork.name, cfg.IsActivationBlock(ts-1, ts+10)) + require.Equal(t, tc.name, cfg.IsActivationBlock(ts-1, ts)) + require.Equal(t, tc.name, cfg.IsActivationBlock(ts-1, ts+10)) // Not crossing the fork boundary should return None - require.Equal(t, None, cfg.IsActivationBlock(ts, ts+1)) - require.Equal(t, None, cfg.IsActivationBlock(ts+1, ts+2)) + require.Equal(t, forks.None, cfg.IsActivationBlock(ts, ts+1)) + require.Equal(t, forks.None, cfg.IsActivationBlock(ts+1, ts+2)) // Before the fork - require.Equal(t, None, cfg.IsActivationBlock(ts-10, ts-1)) + require.Equal(t, forks.None, cfg.IsActivationBlock(ts-10, ts-1)) }) } } @@ -993,8 +994,8 @@ func TestConfig_ActivationBlockAndForFork(t *testing.T) { // IsActivationBlock should detect boundary crossing irrespective of block time granularity require.Equal(t, fork, cfg.IsActivationBlock(ts-1, ts)) require.Equal(t, fork, cfg.IsActivationBlock(ts-1, ts+10)) - require.Equal(t, None, cfg.IsActivationBlock(ts, ts+1)) - require.Equal(t, None, cfg.IsActivationBlock(ts+1, ts+2)) + require.Equal(t, forks.None, cfg.IsActivationBlock(ts, ts+1)) + require.Equal(t, forks.None, cfg.IsActivationBlock(ts+1, ts+2)) // IsActivationBlockForFork should be true for the first block(s) at/after activation, // i.e. for times in [ts, ts+BlockTime-1], and false otherwise. @@ -1014,7 +1015,7 @@ func TestConfig_ActivateAt(t *testing.T) { t.Run("Ecotone", func(t *testing.T) { var cfg Config ts := uint64(100) - cfg.ActivateAt(Ecotone, ts) + cfg.ActivateAt(forks.Ecotone, ts) require.Equal(t, Config{ RegolithTime: ptr.Zero64, CanyonTime: ptr.Zero64, @@ -1026,11 +1027,11 @@ func TestConfig_ActivateAt(t *testing.T) { t.Run("LatestFork", func(t *testing.T) { var cfg Config ts := uint64(100) - cfg.ActivateAt(LatestFork, ts) + cfg.ActivateAt(forks.Latest, ts) for _, f := range scheduleableForks { at := cfg.ActivationTime(f) require.NotNil(t, at) - if f == LatestFork { + if f == forks.Latest { require.EqualValues(t, ts, *at) } else { // prior forks at genesis (0) @@ -1042,7 +1043,7 @@ func TestConfig_ActivateAt(t *testing.T) { // Bedrock special case: disable all scheduleable forks t.Run("Bedrock", func(t *testing.T) { var cfg Config - cfg.ActivateAt(Bedrock, 0) + cfg.ActivateAt(forks.Bedrock, 0) for _, f := range scheduleableForks { require.Nil(t, cfg.ActivationTime(f)) } @@ -1055,7 +1056,7 @@ func TestConfig_ActivateAtGenesis(t *testing.T) { // Activate Ecotone at genesis t.Run("Ecotone", func(t *testing.T) { var cfg Config - cfg.ActivateAtGenesis(Ecotone) + cfg.ActivateAtGenesis(forks.Ecotone) require.Equal(t, Config{ RegolithTime: ptr.Zero64, CanyonTime: ptr.Zero64, @@ -1066,7 +1067,7 @@ func TestConfig_ActivateAtGenesis(t *testing.T) { t.Run("LatestFork", func(t *testing.T) { var cfg Config - cfg.ActivateAtGenesis(LatestFork) + cfg.ActivateAtGenesis(forks.Latest) for _, f := range scheduleableForks { at := cfg.ActivationTime(f) require.NotNil(t, at) @@ -1077,7 +1078,7 @@ func TestConfig_ActivateAtGenesis(t *testing.T) { // Bedrock special case: disable all scheduleable forks t.Run("Bedrock", func(t *testing.T) { var cfg Config - cfg.ActivateAtGenesis(Bedrock) + cfg.ActivateAtGenesis(forks.Bedrock) for _, f := range scheduleableForks { require.Nil(t, cfg.ActivationTime(f)) } diff --git a/op-program/Dockerfile.repro.dockerignore b/op-program/Dockerfile.repro.dockerignore index 15d6cf76382..1cf8173ca25 100644 --- a/op-program/Dockerfile.repro.dockerignore +++ b/op-program/Dockerfile.repro.dockerignore @@ -4,6 +4,7 @@ !go.* # internal dependencies !cannon/ +!op-core/ !op-alt-da/ !op-node/ !op-preimage/ diff --git a/op-program/Dockerfile.vmcompat.dockerignore b/op-program/Dockerfile.vmcompat.dockerignore index 15d6cf76382..1cf8173ca25 100644 --- a/op-program/Dockerfile.vmcompat.dockerignore +++ b/op-program/Dockerfile.vmcompat.dockerignore @@ -4,6 +4,7 @@ !go.* # internal dependencies !cannon/ +!op-core/ !op-alt-da/ !op-node/ !op-preimage/ diff --git a/op-program/client/l2/engineapi/l2_engine_api_test.go b/op-program/client/l2/engineapi/l2_engine_api_test.go index 3828e3a28fd..01fbfcc7468 100644 --- a/op-program/client/l2/engineapi/l2_engine_api_test.go +++ b/op-program/client/l2/engineapi/l2_engine_api_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" - "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/beacon/engine" @@ -179,7 +179,7 @@ func createGenesisWithIsthmusTimeOffset(forkTimeOffset uint64) *core.Genesis { }, } - deployConfig.ActivateForkAtOffset(rollup.Isthmus, forkTimeOffset) + deployConfig.ActivateForkAtOffset(forks.Isthmus, forkTimeOffset) l1Genesis, err := genesis.NewL1Genesis(deployConfig) if err != nil { diff --git a/ops/docker/op-stack-go/Dockerfile.dockerignore b/ops/docker/op-stack-go/Dockerfile.dockerignore index 16a60a2bff6..280b1603456 100644 --- a/ops/docker/op-stack-go/Dockerfile.dockerignore +++ b/ops/docker/op-stack-go/Dockerfile.dockerignore @@ -4,6 +4,7 @@ !/cannon !/devnet-sdk +!/op-core !/op-batcher !/op-chain-ops !/op-deployer From f55af963cc49ab0eb4e9fb48ccb7362efff60c4c Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Mon, 3 Nov 2025 11:02:26 -0800 Subject: [PATCH 02/20] fix: use default mips version and use local op-deployer (#18129) * fix: bump mips version from 7 to 8 * fix: don't require building binary to use justfile with correct op-deployer version * fix: remove mips version arg --- op-deployer/justfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/op-deployer/justfile b/op-deployer/justfile index 92fb5aed702..401f8623435 100644 --- a/op-deployer/justfile +++ b/op-deployer/justfile @@ -91,10 +91,9 @@ pre-deploy: build build-contracts deploy-opcm release="dev" locator="$DEFAULT_LOCATOR": _validate_rpc #!/bin/bash echo "Using artifacts locator: {{locator}}" - ./bin/op-deployer bootstrap implementations \ + go run ./cmd/op-deployer bootstrap implementations \ --l1-rpc-url $ETH_RPC_URL \ --private-key $PRIVATE_KEY \ - --mips-version 7 \ --protocol-versions-proxy $PROTOCOL_VERSIONS_PROXY \ --superchain-config-proxy $SUPERCHAIN_CONFIG_PROXY \ --l1-proxy-admin-owner $L1_PROXY_ADMIN_OWNER \ @@ -107,7 +106,7 @@ deploy-opcm release="dev" locator="$DEFAULT_LOCATOR": _validate_rpc verify-opcm locator="$DEFAULT_LOCATOR": _validate_rpc #!/bin/bash echo "Using artifacts locator: {{locator}}" - ./bin/op-deployer verify \ + go run ./cmd/op-deployer verify \ --artifacts-locator {{locator}} \ --l1-rpc-url $ETH_RPC_URL \ --etherscan-api-key $ETHERSCAN_API_KEY \ From 9750aa429c002841cc51bc2d681b4693fc256219 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 3 Nov 2025 14:46:42 -0500 Subject: [PATCH 03/20] feat: Use build-no-tests in op-deployers just build command (#18130) --- op-deployer/justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op-deployer/justfile b/op-deployer/justfile index 401f8623435..849e1e2b96d 100644 --- a/op-deployer/justfile +++ b/op-deployer/justfile @@ -6,7 +6,7 @@ test args='./...': build-contracts copy-contract-artifacts go test -v {{args}} build-contracts: - just ../packages/contracts-bedrock/forge-build + just ../packages/contracts-bedrock/build-no-tests copy-contract-artifacts: #!/bin/bash From db05fc81be8b4f062c5f9387ffdc6c69d818b986 Mon Sep 17 00:00:00 2001 From: Ariel Diaz <65925295+aliersh@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:39:26 -0500 Subject: [PATCH 04/20] fix(prompt): add guidance to skip unrelated CI failures (#18127) --- ops/ai-eng/contracts-test-maintenance/VERSION | 2 +- ops/ai-eng/contracts-test-maintenance/prompt/prompt.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ops/ai-eng/contracts-test-maintenance/VERSION b/ops/ai-eng/contracts-test-maintenance/VERSION index 26aaba0e866..6085e946503 100644 --- a/ops/ai-eng/contracts-test-maintenance/VERSION +++ b/ops/ai-eng/contracts-test-maintenance/VERSION @@ -1 +1 @@ -1.2.0 +1.2.1 diff --git a/ops/ai-eng/contracts-test-maintenance/prompt/prompt.md b/ops/ai-eng/contracts-test-maintenance/prompt/prompt.md index 1adcc5f8df4..c2dd27ace99 100644 --- a/ops/ai-eng/contracts-test-maintenance/prompt/prompt.md +++ b/ops/ai-eng/contracts-test-maintenance/prompt/prompt.md @@ -543,6 +543,11 @@ contract L1FeeVault_Version_Test { - MUST pass before creating any PR 4. Search for any vm.expectRevert() without arguments and fix them +**INTERPRETING CI STATUS:** +- Only investigate actual code failures: build errors, test failures, lint violations +- "Code Review Requirements" status = waiting for reviewer approvals, not code issues +- Test-only changes cannot affect these CI jobs - skip them: `diff-asterisc-bytecode`, `op-program-compat` + **ZERO TOLERANCE - CI FAILURES:** - vm.expectRevert() must ALWAYS have arguments: either selector or bytes message - ALL tests must pass - no exceptions From c1351bf1b088bc5236c0bcf3b56bdddac9121ca1 Mon Sep 17 00:00:00 2001 From: smartcontracts <14298799+smartcontracts@users.noreply.github.com> Date: Mon, 3 Nov 2025 16:12:47 -0500 Subject: [PATCH 05/20] feat(ci): run upgrade tests with dev flags (#18133) * feat(ci): run upgrade tests with dev flags Updates CI to run upgrade tests with dev flags enabled. Only OP will run with dev flags enabled for now, this should be sufficient and will avoid dramatically increasing CI impact. * fix: correct cannon kona prestate in validator tests --- .circleci/config.yml | 21 ++++++++++++++++++- .../OPContractsManagerStandardValidator.t.sol | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bb9fa512363..c08ea0f326a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1146,6 +1146,10 @@ jobs: fork_base_rpc: description: Fork Base RPC type: string + dev_features: + description: Comma-separated list of dev features to enable (e.g., "OPTIMISM_PORTAL_INTEROP,ANOTHER_FEATURE") + type: string + default: "" docker: - image: <> resource_class: xlarge @@ -1176,6 +1180,8 @@ jobs: - restore_cache: name: Restore forked state key: forked-state-contracts-bedrock-tests-upgrade-<>-<>-{{ checksum "packages/contracts-bedrock/pinnedBlockNumber.txt" }} + - setup-dev-features: + dev_features: <> - run: name: Run tests command: just test-upgrade @@ -2453,6 +2459,19 @@ workflows: - circleci-repo-readonly-authenticated-github-token requires: - initialize + - contracts-bedrock-tests-upgrade: + name: contracts-bedrock-tests-upgrade op-mainnet <> + fork_op_chain: op + fork_base_chain: mainnet + fork_base_rpc: https://ci-mainnet-l1-archive.optimism.io + dev_features: <> + matrix: + parameters: + dev_features: *dev_features_matrix + context: + - circleci-repo-readonly-authenticated-github-token + requires: + - initialize - contracts-bedrock-tests-upgrade: name: contracts-bedrock-tests-upgrade <>-mainnet fork_op_chain: <> @@ -2460,7 +2479,7 @@ workflows: fork_base_rpc: https://ci-mainnet-l1-archive.optimism.io matrix: parameters: - fork_op_chain: ["op", "base", "ink", "unichain"] + fork_op_chain: ["base", "ink", "unichain"] context: - circleci-repo-readonly-authenticated-github-token requires: diff --git a/packages/contracts-bedrock/test/L1/OPContractsManagerStandardValidator.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManagerStandardValidator.t.sol index 5fb4992f42f..a99a358ea19 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManagerStandardValidator.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManagerStandardValidator.t.sol @@ -95,7 +95,7 @@ abstract contract OPContractsManagerStandardValidator_TestInit is CommonTest, Di Claim cannonPrestate; /// @notice The CannonKona absolute prestate. - Claim cannonKonaPrestate = Claim.wrap(bytes32(keccak256("cannonKona"))); + Claim cannonKonaPrestate = Claim.wrap(bytes32(keccak256("cannonKonaPrestate"))); /// @notice The proposer role set on the PermissionedDisputeGame instance. address proposer; From 1b830b2f329b5cfa9587b5df90f83aab485e0a98 Mon Sep 17 00:00:00 2001 From: mbaxter Date: Mon, 3 Nov 2025 16:29:00 -0500 Subject: [PATCH 06/20] opcm: Update OPCM.migrate to support Cannon-Kona games (#18078) * Update opcm.migrate to set super-cannonKona * Validate cannonKona prestates during migrate * Update OCPM migrate tests * Cleanup: add helper to construct gameType expectations * Fix game validation test logic * Fix shadowed var warning * Rework op-deployer migrate CLI args for absolute prestate * Read cannonKona prestate in GenerateOPCMMigrateCalldata * Don't create SuperCannonKona game if prestate is zero * Update migration gameType helper * Clean up test logic, perform stricter checks on empty games * Add error messages * Clear game args when game impl removed * Add test with empty cannonKona prestate * Enforce non-empty cannon prestate * Bump contract version * Run just pre-pr * Cleanup and add another test * Fix test documentation * Add new prestate flags to the migrate CLI command * Update script comment with updated sample input * Add check for consistent permissionless weth contracts post-migrate * Bump opcm version again * Run semver-lock --- op-deployer/pkg/deployer/manage/flags.go | 15 +- op-deployer/pkg/deployer/manage/migrate.go | 5 +- .../deploy/GenerateOPCMMigrateCalldata.sol | 6 +- .../OPContractsManagerInteropMigrator.json | 5 + .../snapshots/semver-lock.json | 4 +- .../src/L1/OPContractsManager.sol | 61 ++- .../test/L1/OPContractsManager.t.sol | 352 +++++++++++------- .../test/setup/DisputeGames.sol | 5 + 8 files changed, 300 insertions(+), 153 deletions(-) diff --git a/op-deployer/pkg/deployer/manage/flags.go b/op-deployer/pkg/deployer/manage/flags.go index dc7db918f26..1f3185d780e 100644 --- a/op-deployer/pkg/deployer/manage/flags.go +++ b/op-deployer/pkg/deployer/manage/flags.go @@ -56,6 +56,18 @@ var ( EnvVars: deployer.PrefixEnvVar("DISPUTE_ABSOLUTE_PRESTATE"), Value: standard.DisputeAbsolutePrestate.Hex(), } + DisputeAbsolutePrestateCannonFlag = &cli.StringFlag{ + Name: "dispute-absolute-prestate-cannon", + Usage: "The absolute prestate hash for the CANNON dispute game. Defaults to the standard value.", + EnvVars: deployer.PrefixEnvVar("DISPUTE_ABSOLUTE_PRESTATE_CANNON"), + Value: standard.DisputeAbsolutePrestate.Hex(), + } + DisputeAbsolutePrestateCannonKonaFlag = &cli.StringFlag{ + Name: "dispute-absolute-prestate-cannon-kona", + Usage: "The absolute prestate hash for the CANNON_KONA dispute game. Defaults to the standard value.", + EnvVars: deployer.PrefixEnvVar("DISPUTE_ABSOLUTE_PRESTATE_CANNON_KONA"), + Value: standard.DisputeAbsolutePrestate.Hex(), + } DisputeMaxGameDepthFlag = &cli.Uint64Flag{ Name: "dispute-max-game-depth", Usage: "Maximum depth of the dispute game tree (value as string). Defaults to the standard value.", @@ -176,7 +188,8 @@ var Commands = cli.Commands{ // SystemConfigProxyFlag, OPChainProxyAdminFlag, - DisputeAbsolutePrestateFlag, + DisputeAbsolutePrestateCannonFlag, + DisputeAbsolutePrestateCannonKonaFlag, }, oplog.CLIFlags(deployer.EnvVarPrefix)...), Action: MigrateCLI, }, diff --git a/op-deployer/pkg/deployer/manage/migrate.go b/op-deployer/pkg/deployer/manage/migrate.go index 26da0631417..3c2c0f02734 100644 --- a/op-deployer/pkg/deployer/manage/migrate.go +++ b/op-deployer/pkg/deployer/manage/migrate.go @@ -111,8 +111,9 @@ func MigrateCLI(cliCtx *cli.Context) error { // At the moment we only support a single chain config EncodedChainConfigs: []OPChainConfig{ { - SystemConfigProxy: common.HexToAddress(cliCtx.String(SystemConfigProxyFlag.Name)), - CannonPrestate: common.HexToHash(cliCtx.String(DisputeAbsolutePrestateFlag.Name)), + SystemConfigProxy: common.HexToAddress(cliCtx.String(SystemConfigProxyFlag.Name)), + CannonPrestate: common.HexToHash(cliCtx.String(DisputeAbsolutePrestateCannonFlag.Name)), + CannonKonaPrestate: common.HexToHash(cliCtx.String(DisputeAbsolutePrestateCannonKonaFlag.Name)), }, }, } diff --git a/packages/contracts-bedrock/scripts/deploy/GenerateOPCMMigrateCalldata.sol b/packages/contracts-bedrock/scripts/deploy/GenerateOPCMMigrateCalldata.sol index 86a3a00d270..a33d0fae120 100644 --- a/packages/contracts-bedrock/scripts/deploy/GenerateOPCMMigrateCalldata.sol +++ b/packages/contracts-bedrock/scripts/deploy/GenerateOPCMMigrateCalldata.sol @@ -20,6 +20,7 @@ import { stdJson } from "forge-std/StdJson.sol"; /// Config example: /// { /// "cannonPrestate": "0x1234567890abcdef1234567890abcdef12345678", +/// "cannonKonaPrestate": "0x1122334455abcdef1234567890abcdef12345678", /// "usePermissionlessGame": true, /// "startingAnchorRoot": { /// "root": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd", @@ -45,6 +46,7 @@ import { stdJson } from "forge-std/StdJson.sol"; /// } contract GenerateOPCMMigrateCalldata is Script { bytes32 cannonPrestate; + bytes32 cannonKonaPrestate; bool usePermissionlessGame; Proposal startingAnchorRoot; address proposer; @@ -73,6 +75,7 @@ contract GenerateOPCMMigrateCalldata is Script { cannonPrestate = stdJson.readBytes32(json, "$.cannonPrestate"); require(cannonPrestate != bytes32(0), "GenerateOPCMMigrateCalldata: cannonPrestate cannot be 0"); + cannonKonaPrestate = stdJson.readBytes32(json, "$.cannonKonaPrestate"); usePermissionlessGame = stdJson.readBool(json, "$.usePermissionlessGame"); startingAnchorRoot = Proposal({ @@ -121,8 +124,7 @@ contract GenerateOPCMMigrateCalldata is Script { opChainConfigs[i] = IOPContractsManager.OpChainConfig({ systemConfigProxy: ISystemConfig(j[i].systemConfigProxy), cannonPrestate: Claim.wrap(cannonPrestate), - // TODO(#17743): cannon-kona for opcm.migrate - cannonKonaPrestate: Claim.wrap(bytes32(0)) + cannonKonaPrestate: Claim.wrap(cannonKonaPrestate) }); require( opChainConfigs[i].systemConfigProxy != ISystemConfig(address(0)), diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInteropMigrator.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInteropMigrator.json index e50b7a602ee..5644c7edb07 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInteropMigrator.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInteropMigrator.json @@ -409,6 +409,11 @@ "name": "OPContractsManager_InvalidGameType", "type": "error" }, + { + "inputs": [], + "name": "PrestateNotSet", + "type": "error" + }, { "inputs": [], "name": "ReservedBitsSet", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index aaa831f1857..5fe766f632d 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -20,8 +20,8 @@ "sourceCodeHash": "0xfca613b5d055ffc4c3cbccb0773ddb9030abedc1aa6508c9e2e7727cc0cd617b" }, "src/L1/OPContractsManager.sol:OPContractsManager": { - "initCodeHash": "0xaf9f3fe706ae2a15108451d7e665208254be8b6d398c3e738c8887a0f8cd7903", - "sourceCodeHash": "0xba3c7ef4834fda6df516249a77ef2ff6d7c512cf694f4322e696e57377086eec" + "initCodeHash": "0x6bf74671476f7a6c5d35cad90e16c7d0c1b1e7c4d33fb5f8e0966e1e3ca9cfe8", + "sourceCodeHash": "0x1e5421e93901d3a2b1c6021acf71b443bf66af4a9710ddbb331b1f8419e90dde" }, "src/L1/OPContractsManagerStandardValidator.sol:OPContractsManagerStandardValidator": { "initCodeHash": "0x0c8b15453d0f0bc5d9af07f104505e0bbb2b358f0df418289822fb73a8652b30", diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index 58930f9789f..38358594258 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -1813,7 +1813,7 @@ contract OPContractsManagerInteropMigrator is OPContractsManagerBase { // Get the proxyAdmin from the first system config. IProxyAdmin proxyAdmin = _input.opChainConfigs[0].systemConfigProxy.proxyAdmin(); - // Check that all of the configs have the same proxy admin owner and prestate. + // Check that all of the configs have the same proxy admin owner and prestates. for (uint256 i = 0; i < _input.opChainConfigs.length; i++) { // Different chains might actually have different ProxyAdmin contracts, but it's fine // as long as the owner of all of those contracts is the same. @@ -1823,6 +1823,19 @@ contract OPContractsManagerInteropMigrator is OPContractsManagerBase { if (_input.opChainConfigs[i].cannonPrestate.raw() != _input.opChainConfigs[0].cannonPrestate.raw()) { revert OPContractsManagerInteropMigrator_AbsolutePrestateMismatch(); } + if (isDevFeatureEnabled(DevFeatures.CANNON_KONA)) { + if ( + _input.opChainConfigs[i].cannonKonaPrestate.raw() + != _input.opChainConfigs[0].cannonKonaPrestate.raw() + ) { + revert OPContractsManagerInteropMigrator_AbsolutePrestateMismatch(); + } + } + } + + // Check that cannon prestate is non-empty + if (_input.opChainConfigs[0].cannonPrestate.raw() == bytes32(0)) { + revert OPContractsManager.PrestateNotSet(); } // Grab an array of portals from the configs. @@ -1935,16 +1948,16 @@ contract OPContractsManagerInteropMigrator is OPContractsManagerBase { existingLockbox.migrateLiquidity(newEthLockbox); // Before migrating the portal, clear out any implementations that might exist in the - // old DisputeGameFactory proxy. We clear out all 4 potential game types to be safe. + // old DisputeGameFactory proxy. We clear out all potential game types to be safe. IDisputeGameFactory oldDisputeGameFactory = IDisputeGameFactory(payable(address(portals[i].disputeGameFactory()))); - oldDisputeGameFactory.setImplementation(GameTypes.CANNON, IDisputeGame(address(0))); - oldDisputeGameFactory.setImplementation(GameTypes.SUPER_CANNON, IDisputeGame(address(0))); - oldDisputeGameFactory.setImplementation(GameTypes.PERMISSIONED_CANNON, IDisputeGame(address(0))); - oldDisputeGameFactory.setImplementation(GameTypes.SUPER_PERMISSIONED_CANNON, IDisputeGame(address(0))); + clearGameImplementation(oldDisputeGameFactory, GameTypes.CANNON); + clearGameImplementation(oldDisputeGameFactory, GameTypes.SUPER_CANNON); + clearGameImplementation(oldDisputeGameFactory, GameTypes.PERMISSIONED_CANNON); + clearGameImplementation(oldDisputeGameFactory, GameTypes.SUPER_PERMISSIONED_CANNON); if (isDevFeatureEnabled(DevFeatures.CANNON_KONA)) { - oldDisputeGameFactory.setImplementation(GameTypes.CANNON_KONA, IDisputeGame(address(0))); - oldDisputeGameFactory.setImplementation(GameTypes.SUPER_CANNON_KONA, IDisputeGame(address(0))); + clearGameImplementation(oldDisputeGameFactory, GameTypes.CANNON_KONA); + clearGameImplementation(oldDisputeGameFactory, GameTypes.SUPER_CANNON_KONA); } // Migrate the portal to the new ETHLockbox and AnchorStateRegistry. @@ -2035,6 +2048,34 @@ contract OPContractsManagerInteropMigrator is OPContractsManagerBase { GameTypes.SUPER_CANNON, IDisputeGame(implementations().superFaultDisputeGameImpl), gameArgs ); newDisputeGameFactory.setInitBond(GameTypes.SUPER_CANNON, _input.gameParameters.initBond); + + // If the cannon-kona game is being used, set that up too. + bytes32 cannonKonaPrestate = _input.opChainConfigs[0].cannonKonaPrestate.raw(); + if (isDevFeatureEnabled(DevFeatures.CANNON_KONA) && cannonKonaPrestate != bytes32(0)) { + gameArgs = LibGameArgs.encode( + LibGameArgs.GameArgs({ + absolutePrestate: cannonKonaPrestate, + vm: address(getImplementations().mipsImpl), + anchorStateRegistry: address(newAnchorStateRegistry), + weth: address(newPermissionlessDelayedWETHProxy), + l2ChainId: uint256(0), + proposer: address(0), + challenger: address(0) + }) + ); + newDisputeGameFactory.setImplementation( + GameTypes.SUPER_CANNON_KONA, IDisputeGame(implementations().superFaultDisputeGameImpl), gameArgs + ); + newDisputeGameFactory.setInitBond(GameTypes.SUPER_CANNON_KONA, _input.gameParameters.initBond); + } + } + } + + function clearGameImplementation(IDisputeGameFactory _dgf, GameType _gameType) internal { + if (isDevFeatureEnabled(DevFeatures.DEPLOY_V2_DISPUTE_GAMES)) { + _dgf.setImplementation(_gameType, IDisputeGame(address(0)), hex""); + } else { + _dgf.setImplementation(_gameType, IDisputeGame(address(0))); } } } @@ -2167,9 +2208,9 @@ contract OPContractsManager is ISemver { // -------- Constants and Variables -------- - /// @custom:semver 5.5.0 + /// @custom:semver 5.6.0 function version() public pure virtual returns (string memory) { - return "5.5.0"; + return "5.6.0"; } OPContractsManagerGameTypeAdder public immutable opcmGameTypeAdder; diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index 45195fba091..d09e898dffb 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -1803,8 +1803,11 @@ contract OPContractsManager_UpgradeSuperchainConfig_Test is OPContractsManager_U /// @title OPContractsManager_Migrate_Test /// @notice Tests the `migrate` function of the `OPContractsManager` contract. contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { - Claim absolutePrestate1 = Claim.wrap(bytes32(hex"ABBA")); - Claim absolutePrestate2 = Claim.wrap(bytes32(hex"DEAD")); + Claim cannonPrestate1 = Claim.wrap(bytes32(hex"ABBA")); + Claim cannonPrestate2 = Claim.wrap(bytes32(hex"DEAD")); + Claim cannonKonaPrestate1 = Claim.wrap(bytes32(hex"ABBACADABA")); + Claim cannonKonaPrestate2 = Claim.wrap(bytes32(hex"DEADBEEF")); + Claim emptyPrestate = Claim.wrap(bytes32(0)); /// @notice Function requires interop portal. function setUp() public override { @@ -1827,10 +1830,10 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { IOPContractsManager.OpChainConfig[] memory opChainConfigs = new IOPContractsManager.OpChainConfig[](2); opChainConfigs[0] = IOPContractsManager.OpChainConfig( - chainDeployOutput1.systemConfigProxy, absolutePrestate1, Claim.wrap(bytes32(0)) + chainDeployOutput1.systemConfigProxy, cannonPrestate1, cannonKonaPrestate1 ); opChainConfigs[1] = IOPContractsManager.OpChainConfig( - chainDeployOutput2.systemConfigProxy, absolutePrestate1, Claim.wrap(bytes32(0)) + chainDeployOutput2.systemConfigProxy, cannonPrestate1, cannonKonaPrestate1 ); return IOPContractsManagerInteropMigrator.MigrateInput({ @@ -1878,17 +1881,26 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { /// @param _disputeGameFactory The dispute game factory to check. function _assertOldGamesZeroed(IDisputeGameFactory _disputeGameFactory) internal view { // Assert that the old game implementations are now zeroed out. - assertEq(address(_disputeGameFactory.gameImpls(GameTypes.CANNON)), address(0)); - assertEq(address(_disputeGameFactory.gameImpls(GameTypes.SUPER_CANNON)), address(0)); - assertEq(address(_disputeGameFactory.gameImpls(GameTypes.PERMISSIONED_CANNON)), address(0)); - assertEq(address(_disputeGameFactory.gameImpls(GameTypes.SUPER_PERMISSIONED_CANNON)), address(0)); + _assertGameIsEmpty(_disputeGameFactory, GameTypes.CANNON, "CANNON"); + _assertGameIsEmpty(_disputeGameFactory, GameTypes.SUPER_CANNON, "SUPER_CANNON"); + _assertGameIsEmpty(_disputeGameFactory, GameTypes.PERMISSIONED_CANNON, "PERMISSIONED_CANNON"); + _assertGameIsEmpty(_disputeGameFactory, GameTypes.SUPER_PERMISSIONED_CANNON, "SUPER_PERMISSIONED_CANNON"); if (isDevFeatureEnabled(DevFeatures.CANNON_KONA)) { // Only explicitly zeroed out if feature is enabled. Otherwise left unchanged (which may still be 0). - assertEq(address(_disputeGameFactory.gameImpls(GameTypes.CANNON_KONA)), address(0)); - assertEq(address(_disputeGameFactory.gameImpls(GameTypes.SUPER_CANNON_KONA)), address(0)); + _assertGameIsEmpty(_disputeGameFactory, GameTypes.CANNON_KONA, "CANNON_KONA"); + _assertGameIsEmpty(_disputeGameFactory, GameTypes.SUPER_CANNON_KONA, "SUPER_CANNON_KONA"); } } + function _assertGameIsEmpty(IDisputeGameFactory _dgf, GameType _gameType, string memory _label) internal view { + assertEq( + address(_dgf.gameImpls(_gameType)), + address(0), + string.concat("Game type set when it should not be: ", _label) + ); + assertEq(_dgf.gameArgs(_gameType), hex"", string.concat("Game args should be empty: ", _label)); + } + /// @notice Runs some tests after opcm.migrate function _runPostMigrateSmokeTests(IOPContractsManagerInteropMigrator.MigrateInput memory _input) internal { IDisputeGameFactory dgf = IDisputeGameFactory(chainDeployOutput1.systemConfigProxy.disputeGameFactory()); @@ -1898,17 +1910,28 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { (, uint256 l2SequenceNumberAnchor) = anchorStateRegistry.getAnchorRoot(); uint256 l2SequenceNumber = l2SequenceNumberAnchor + 1; - GameType[] memory gameTypes = new GameType[](_input.usePermissionlessGame ? 2 : 1); - gameTypes[0] = GameTypes.SUPER_PERMISSIONED_CANNON; - if (_input.usePermissionlessGame) { - gameTypes[1] = GameTypes.SUPER_CANNON; - } + GameType[] memory gameTypes = _getPostMigrateExpectedGameTypes(_input); + + address permissionlessWeth; for (uint256 i = 0; i < gameTypes.length; i++) { LibGameArgs.GameArgs memory gameArgs = LibGameArgs.decode(dgf.gameArgs(gameTypes[i])); - assertEq(gameArgs.absolutePrestate, absolutePrestate1.raw(), "gameArgs prestate mismatch"); + if (permissionlessWeth == address(0) && !isGamePermissioned(gameTypes[i])) { + // Remember the first permissionless weth we encounter + permissionlessWeth = gameArgs.weth; + } + assertEq(gameArgs.vm, opcm.implementations().mipsImpl, "gameArgs vm mismatch"); assertEq(gameArgs.anchorStateRegistry, address(anchorStateRegistry), "gameArgs asr mismatch"); assertEq(gameArgs.l2ChainId, 0, "gameArgs non-zero l2ChainId"); + if (gameTypes[i].raw() == GameTypes.SUPER_CANNON_KONA.raw()) { + assertEq(gameArgs.absolutePrestate, cannonKonaPrestate1.raw(), "gameArgs prestate mismatch"); + } else { + assertEq(gameArgs.absolutePrestate, cannonPrestate1.raw(), "gameArgs prestate mismatch"); + } + if (!isGamePermissioned(gameTypes[i])) { + // All permissionless FDG games should share the same weth contract + assertEq(gameArgs.weth, permissionlessWeth, "gameArgs weth mismatch"); + } Claim rootClaim = Claim.wrap(bytes32(uint256(1))); uint256 bondAmount = dgf.initBonds(gameTypes[i]); @@ -1945,107 +1968,106 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { } } + function _getPostMigrateExpectedGameTypes(IOPContractsManagerInteropMigrator.MigrateInput memory _input) + internal + returns (GameType[] memory gameTypes_) + { + uint256 gameCount = 1; + bytes32 cannonKonaPrestate = _input.opChainConfigs[0].cannonKonaPrestate.raw(); + if (_input.usePermissionlessGame) { + gameCount += 1; + if (isDevFeatureEnabled(DevFeatures.CANNON_KONA) && cannonKonaPrestate != bytes32(0)) { + gameCount += 1; + } + } + + gameTypes_ = new GameType[](gameCount); + gameTypes_[0] = GameTypes.SUPER_PERMISSIONED_CANNON; + if (_input.usePermissionlessGame) { + gameTypes_[1] = GameTypes.SUPER_CANNON; + if (isDevFeatureEnabled(DevFeatures.CANNON_KONA) && cannonKonaPrestate != bytes32(0)) { + gameTypes_[2] = GameTypes.SUPER_CANNON_KONA; + } + } + } + /// @notice Tests that the migration function succeeds when requesting to use the /// permissionless game. function test_migrate_withPermissionlessGame_succeeds() public { IOPContractsManagerInteropMigrator.MigrateInput memory input = _getDefaultInput(); + (IAnchorStateRegistry asr, IDisputeGameFactory dgf) = _runMigrationAndStandardChecks(input); - // Separate context to avoid stack too deep errors. - { - // Grab the existing DisputeGameFactory for each chain. - IDisputeGameFactory oldDisputeGameFactory1 = - IDisputeGameFactory(payable(chainDeployOutput1.systemConfigProxy.disputeGameFactory())); - IDisputeGameFactory oldDisputeGameFactory2 = - IDisputeGameFactory(payable(chainDeployOutput2.systemConfigProxy.disputeGameFactory())); + // Check the respected game type + assertEq(asr.respectedGameType().raw(), GameTypes.SUPER_CANNON.raw(), "Super Cannon game type mismatch"); - // Execute the migration. - _doMigration(input); - - // Assert that the old game implementations are now zeroed out. - _assertOldGamesZeroed(oldDisputeGameFactory1); - _assertOldGamesZeroed(oldDisputeGameFactory2); - } - - // Grab the two OptimismPortal addresses. - IOptimismPortal2 optimismPortal1 = - IOptimismPortal2(payable(chainDeployOutput1.systemConfigProxy.optimismPortal())); - IOptimismPortal2 optimismPortal2 = - IOptimismPortal2(payable(chainDeployOutput2.systemConfigProxy.optimismPortal())); - - // Grab the AnchorStateRegistry from the OptimismPortal for both chains, confirm same. + // Check initial bonds assertEq( - address(optimismPortal1.anchorStateRegistry()), - address(optimismPortal2.anchorStateRegistry()), - "AnchorStateRegistry mismatch" + dgf.initBonds(GameTypes.SUPER_CANNON), input.gameParameters.initBond, "Super Cannon init bond mismatch" ); - - // Extract the AnchorStateRegistry now that we know it's the same on both chains. - IAnchorStateRegistry anchorStateRegistry = optimismPortal1.anchorStateRegistry(); - - // Grab the DisputeGameFactory from the SystemConfig for both chains, confirm same. assertEq( - chainDeployOutput1.systemConfigProxy.disputeGameFactory(), - chainDeployOutput2.systemConfigProxy.disputeGameFactory(), - "DisputeGameFactory mismatch" + dgf.initBonds(GameTypes.SUPER_PERMISSIONED_CANNON), + input.gameParameters.initBond, + "Super Permissioned Cannon init bond mismatch" ); + if (isDevFeatureEnabled(DevFeatures.CANNON_KONA)) { + assertEq( + dgf.initBonds(GameTypes.SUPER_CANNON_KONA), + input.gameParameters.initBond, + "Super CannonKona init bond mismatch" + ); + } else { + assertEq( + dgf.initBonds(GameTypes.SUPER_CANNON_KONA), uint256(0), "Super CannonKona init bond should be zero" + ); + } - // Extract the DisputeGameFactory now that we know it's the same on both chains. - IDisputeGameFactory disputeGameFactory = - IDisputeGameFactory(chainDeployOutput1.systemConfigProxy.disputeGameFactory()); + // Check game configuration + _validateSuperGameImplParams(input, dgf, GameTypes.SUPER_PERMISSIONED_CANNON, "SUPER_PERMISSIONED_CANNON"); + _validateSuperGameImplParams(input, dgf, GameTypes.SUPER_CANNON, "SUPER_CANNON"); + if (isDevFeatureEnabled(DevFeatures.CANNON_KONA)) { + _validateSuperGameImplParams(input, dgf, GameTypes.SUPER_CANNON_KONA, "SUPER_CANNON_KONA"); + } else { + _assertGameIsEmpty(dgf, GameTypes.SUPER_CANNON_KONA, "SUPER_CANNON_KONA"); + } - // Grab the ETHLockbox from the OptimismPortal for both chains, confirm same. - assertEq(address(optimismPortal1.ethLockbox()), address(optimismPortal2.ethLockbox()), "ETHLockbox mismatch"); + _runPostMigrateSmokeTests(input); + } - // Extract the ETHLockbox now that we know it's the same on both chains. - IETHLockbox ethLockbox = optimismPortal1.ethLockbox(); + /// @notice Tests that permissionless migration reverts when cannon prestates are empty. + function test_migrate_permissionlessWithEmptyCannonPrestate_reverts() public { + IOPContractsManagerInteropMigrator.MigrateInput memory input = _getDefaultInput(); + input.opChainConfigs[0].cannonPrestate = emptyPrestate; + input.opChainConfigs[1].cannonPrestate = emptyPrestate; - // Check that the ETHLockbox was migrated correctly. - assertGt(address(ethLockbox).balance, 0, "ETHLockbox balance is zero"); - assertTrue(ethLockbox.authorizedPortals(optimismPortal1), "ETHLockbox does not have portal 1 authorized"); - assertTrue(ethLockbox.authorizedPortals(optimismPortal2), "ETHLockbox does not have portal 2 authorized"); + // Execute the migration. + _doMigration(input, IOPContractsManager.PrestateNotSet.selector); + } - // Check that the respected game type is the Super Cannon game type. - assertEq( - anchorStateRegistry.respectedGameType().raw(), - GameTypes.SUPER_CANNON.raw(), - "Super Cannon game type mismatch" - ); + /// @notice Tests that the permissionless migration succeeds when cannonKona prestates are empty. + function test_migrate_permissionlessWithEmptyCannonKonaPrestate_succeeds() public { + IOPContractsManagerInteropMigrator.MigrateInput memory input = _getDefaultInput(); + input.opChainConfigs[0].cannonKonaPrestate = emptyPrestate; + input.opChainConfigs[1].cannonKonaPrestate = emptyPrestate; + (IAnchorStateRegistry asr, IDisputeGameFactory dgf) = _runMigrationAndStandardChecks(input); - // Check that the starting anchor root is the same as the input. - (Hash root, uint256 l2SequenceNumber) = anchorStateRegistry.getAnchorRoot(); - assertEq(root.raw(), input.startingAnchorRoot.root.raw(), "Starting anchor root mismatch"); - assertEq( - l2SequenceNumber, - input.startingAnchorRoot.l2SequenceNumber, - "Starting anchor root L2 sequence number mismatch" - ); + // Check the respected game type + assertEq(asr.respectedGameType().raw(), GameTypes.SUPER_CANNON.raw(), "Super Cannon game type mismatch"); + // Check initial bonds assertEq( - disputeGameFactory.initBonds(GameTypes.SUPER_CANNON), - input.gameParameters.initBond, - "Super Cannon init bond mismatch" + dgf.initBonds(GameTypes.SUPER_CANNON), input.gameParameters.initBond, "Super Cannon init bond mismatch" ); assertEq( - disputeGameFactory.initBonds(GameTypes.SUPER_PERMISSIONED_CANNON), + dgf.initBonds(GameTypes.SUPER_PERMISSIONED_CANNON), input.gameParameters.initBond, "Super Permissioned Cannon init bond mismatch" ); + assertEq(dgf.initBonds(GameTypes.SUPER_CANNON_KONA), uint256(0), "Super CannonKona init bond should be zero"); - // Check that the Super Cannon game has the correct parameters. - IDisputeGame superFdgImpl = disputeGameFactory.gameImpls(GameTypes.SUPER_CANNON); - ISuperFaultDisputeGame superFdg = ISuperFaultDisputeGame(address(superFdgImpl)); - assertEq(superFdg.maxGameDepth(), input.gameParameters.maxGameDepth); - assertEq(superFdg.splitDepth(), input.gameParameters.splitDepth); - assertEq(superFdg.clockExtension().raw(), input.gameParameters.clockExtension.raw()); - assertEq(superFdg.maxClockDuration().raw(), input.gameParameters.maxClockDuration.raw()); - - // Check that the Super Permissioned Cannon game has the correct parameters. - IDisputeGame superPdgImpl = disputeGameFactory.gameImpls(GameTypes.SUPER_PERMISSIONED_CANNON); - ISuperPermissionedDisputeGame superPdg = ISuperPermissionedDisputeGame(address(superPdgImpl)); - assertEq(superPdg.maxGameDepth(), input.gameParameters.maxGameDepth); - assertEq(superPdg.splitDepth(), input.gameParameters.splitDepth); - assertEq(superPdg.clockExtension().raw(), input.gameParameters.clockExtension.raw()); - assertEq(superPdg.maxClockDuration().raw(), input.gameParameters.maxClockDuration.raw()); + // Check game configuration + _validateSuperGameImplParams(input, dgf, GameTypes.SUPER_PERMISSIONED_CANNON, "SUPER_PERMISSIONED_CANNON"); + _validateSuperGameImplParams(input, dgf, GameTypes.SUPER_CANNON, "SUPER_CANNON"); + _assertGameIsEmpty(dgf, GameTypes.SUPER_CANNON_KONA, "SUPER_CANNON_KONA"); _runPostMigrateSmokeTests(input); } @@ -2054,10 +2076,48 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { /// permissioned game (no permissioned game is deployed). function test_migrate_withoutPermissionlessGame_succeeds() public { IOPContractsManagerInteropMigrator.MigrateInput memory input = _getDefaultInput(); + input.usePermissionlessGame = false; + (IAnchorStateRegistry asr, IDisputeGameFactory dgf) = _runMigrationAndStandardChecks(input); + + // Check the respected game type + assertEq( + asr.respectedGameType().raw(), + GameTypes.SUPER_PERMISSIONED_CANNON.raw(), + "Super Permissioned Cannon game type mismatch" + ); + + // Check intial bonds + assertEq( + dgf.initBonds(GameTypes.SUPER_PERMISSIONED_CANNON), + input.gameParameters.initBond, + "Super Permissioned Cannon init bond mismatch" + ); + assertEq(dgf.initBonds(GameTypes.SUPER_CANNON), 0, "Super Cannon init bond mismatch"); + assertEq(dgf.initBonds(GameTypes.SUPER_CANNON_KONA), 0, "Super CannonKona init bond mismatch"); + + // Check game configuration + _validateSuperGameImplParams(input, dgf, GameTypes.SUPER_PERMISSIONED_CANNON, "SUPER_PERMISSIONED_CANNON"); + _assertGameIsEmpty(dgf, GameTypes.SUPER_CANNON, "SUPER_CANNON"); + _assertGameIsEmpty(dgf, GameTypes.SUPER_CANNON_KONA, "SUPER_CANNON_KONA"); + + _runPostMigrateSmokeTests(input); + } - // Change the input to not use the permissionless game. + /// @notice Tests that permissioned migration reverts when cannon prestates are empty. + function test_migrate_permissionedWithEmptyCannonPrestate_reverts() public { + IOPContractsManagerInteropMigrator.MigrateInput memory input = _getDefaultInput(); input.usePermissionlessGame = false; + input.opChainConfigs[0].cannonPrestate = emptyPrestate; + input.opChainConfigs[1].cannonPrestate = emptyPrestate; + // Execute the migration. + _doMigration(input, IOPContractsManager.PrestateNotSet.selector); + } + + function _runMigrationAndStandardChecks(IOPContractsManagerInteropMigrator.MigrateInput memory input) + internal + returns (IAnchorStateRegistry asr_, IDisputeGameFactory dgf_) + { // Separate context to avoid stack too deep errors. { // Grab the existing DisputeGameFactory for each chain. @@ -2080,7 +2140,7 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { IOptimismPortal2 optimismPortal2 = IOptimismPortal2(payable(chainDeployOutput2.systemConfigProxy.optimismPortal())); - // Grab the AnchorStateRegistry from the SystemConfig for both chains, confirm same. + // Grab the AnchorStateRegistry from the OptimismPortal for both chains, confirm same. assertEq( address(optimismPortal1.anchorStateRegistry()), address(optimismPortal2.anchorStateRegistry()), @@ -2088,7 +2148,16 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { ); // Extract the AnchorStateRegistry now that we know it's the same on both chains. - IAnchorStateRegistry anchorStateRegistry = optimismPortal1.anchorStateRegistry(); + asr_ = optimismPortal1.anchorStateRegistry(); + + // Check that the starting anchor root is the same as the input. + (Hash root, uint256 l2SequenceNumber) = asr_.getAnchorRoot(); + assertEq(root.raw(), input.startingAnchorRoot.root.raw(), "Starting anchor root mismatch"); + assertEq( + l2SequenceNumber, + input.startingAnchorRoot.l2SequenceNumber, + "Starting anchor root L2 sequence number mismatch" + ); // Grab the DisputeGameFactory from the SystemConfig for both chains, confirm same. assertEq( @@ -2098,17 +2167,9 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { ); // Extract the DisputeGameFactory now that we know it's the same on both chains. - IDisputeGameFactory disputeGameFactory = - IDisputeGameFactory(chainDeployOutput1.systemConfigProxy.disputeGameFactory()); + dgf_ = IDisputeGameFactory(chainDeployOutput1.systemConfigProxy.disputeGameFactory()); - // Check that the respected game type is the Super Cannon game type. - assertEq( - anchorStateRegistry.respectedGameType().raw(), - GameTypes.SUPER_PERMISSIONED_CANNON.raw(), - "Super Permissioned Cannon game type mismatch" - ); - - // Grab the ETHLockbox from the SystemConfig for both chains, confirm same. + // Grab the ETHLockbox from the OptimismPortal for both chains, confirm same. assertEq(address(optimismPortal1.ethLockbox()), address(optimismPortal2.ethLockbox()), "ETHLockbox mismatch"); // Extract the ETHLockbox now that we know it's the same on both chains. @@ -2118,40 +2179,37 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { assertGt(address(ethLockbox).balance, 0, "ETHLockbox balance is zero"); assertTrue(ethLockbox.authorizedPortals(optimismPortal1), "ETHLockbox does not have portal 1 authorized"); assertTrue(ethLockbox.authorizedPortals(optimismPortal2), "ETHLockbox does not have portal 2 authorized"); + } - // Check that the starting anchor root is the same as the input. - (Hash root, uint256 l2SequenceNumber) = anchorStateRegistry.getAnchorRoot(); - assertEq(root.raw(), input.startingAnchorRoot.root.raw(), "Starting anchor root mismatch"); + function _validateSuperGameImplParams( + IOPContractsManagerInteropMigrator.MigrateInput memory _input, + IDisputeGameFactory _dgf, + GameType _gameType, + string memory _label + ) + internal + view + { + IDisputeGame dgImpl = _dgf.gameImpls(_gameType); + ISuperFaultDisputeGame superImpl = ISuperFaultDisputeGame(address(dgImpl)); assertEq( - l2SequenceNumber, - input.startingAnchorRoot.l2SequenceNumber, - "Starting anchor root L2 sequence number mismatch" + superImpl.maxGameDepth(), + _input.gameParameters.maxGameDepth, + string.concat("MaxGameDepth mismatch: ", _label) ); - - // Check that the DisputeGameFactory has implementation for the Permissioned game. assertEq( - disputeGameFactory.initBonds(GameTypes.SUPER_PERMISSIONED_CANNON), - input.gameParameters.initBond, - "Super Permissioned Cannon init bond mismatch" + superImpl.splitDepth(), _input.gameParameters.splitDepth, string.concat("SplitDepth mismatch: ", _label) ); - - // Check that the DisputeGameFactory does not have an implementation for the regular game. assertEq( - address(disputeGameFactory.gameImpls(GameTypes.SUPER_CANNON)), - address(0), - "Super Cannon game type set when it should not be" + superImpl.clockExtension().raw(), + _input.gameParameters.clockExtension.raw(), + string.concat("ClockExtension mismatch: ", _label) + ); + assertEq( + superImpl.maxClockDuration().raw(), + _input.gameParameters.maxClockDuration.raw(), + string.concat("MaxClockDuration mismatch: ", _label) ); - assertEq(disputeGameFactory.initBonds(GameTypes.SUPER_CANNON), 0, "Super Cannon init bond mismatch"); - - // Check that the Super Permissioned Cannon game has the correct parameters. - IDisputeGame superPdgImpl = disputeGameFactory.gameImpls(GameTypes.SUPER_PERMISSIONED_CANNON); - ISuperPermissionedDisputeGame superPdg = ISuperPermissionedDisputeGame(address(superPdgImpl)); - assertEq(superPdg.maxGameDepth(), input.gameParameters.maxGameDepth); - assertEq(superPdg.splitDepth(), input.gameParameters.splitDepth); - assertEq(superPdg.clockExtension().raw(), input.gameParameters.clockExtension.raw()); - assertEq(superPdg.maxClockDuration().raw(), input.gameParameters.maxClockDuration.raw()); - - _runPostMigrateSmokeTests(input); } /// @notice Tests that the migration function reverts when the ProxyAdmin owners are @@ -2179,12 +2237,12 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { /// @notice Tests that the migration function reverts when the absolute prestates are /// mismatched. - function test_migrate_mismatchedAbsolutePrestates_reverts() public { + function test_migrate_mismatchedCannonPrestates_reverts() public { IOPContractsManagerInteropMigrator.MigrateInput memory input = _getDefaultInput(); // Set the prestates to be different. - input.opChainConfigs[0].cannonPrestate = absolutePrestate1; - input.opChainConfigs[0].cannonPrestate = absolutePrestate2; + input.opChainConfigs[0].cannonPrestate = cannonPrestate1; + input.opChainConfigs[1].cannonPrestate = cannonPrestate2; // Execute the migration. _doMigration( @@ -2192,6 +2250,28 @@ contract OPContractsManager_Migrate_Test is OPContractsManager_TestInit { ); } + /// @notice Tests that the migration function reverts when the absolute prestates are + /// mismatched. + function test_migrate_mismatchedKonaPrestates_reverts() public { + IOPContractsManagerInteropMigrator.MigrateInput memory input = _getDefaultInput(); + + // Set the prestates to be different. + input.opChainConfigs[0].cannonKonaPrestate = cannonKonaPrestate1; + input.opChainConfigs[1].cannonKonaPrestate = cannonKonaPrestate2; + + // Execute the migration. + if (isDevFeatureEnabled(DevFeatures.CANNON_KONA)) { + // We should revert if there is a mismatch and cannonaKona is enabled + _doMigration( + input, + OPContractsManagerInteropMigrator.OPContractsManagerInteropMigrator_AbsolutePrestateMismatch.selector + ); + } else { + // Otherwise, migration should run without reverting + _doMigration(input); + } + } + /// @notice Tests that the migration function reverts when the SuperchainConfig addresses are /// mismatched. function test_migrate_mismatchedSuperchainConfig_reverts() public { diff --git a/packages/contracts-bedrock/test/setup/DisputeGames.sol b/packages/contracts-bedrock/test/setup/DisputeGames.sol index bd5dff7bede..4ec7493c70d 100644 --- a/packages/contracts-bedrock/test/setup/DisputeGames.sol +++ b/packages/contracts-bedrock/test/setup/DisputeGames.sol @@ -56,6 +56,11 @@ contract DisputeGames is FeatureFlags { return address(gameProxy); } + function isGamePermissioned(GameType _gameType) internal pure returns (bool) { + return _gameType.raw() == GameTypes.PERMISSIONED_CANNON.raw() + || _gameType.raw() == GameTypes.SUPER_PERMISSIONED_CANNON.raw(); + } + enum GameArg { PRESTATE, VM, From f32d61f307b7f1e5588e91aa101e4530ee47b28d Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Mon, 3 Nov 2025 15:31:46 -0800 Subject: [PATCH 07/20] fix(op-deployer): update justfile to use current CLI flags (#18143) --- op-deployer/justfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/op-deployer/justfile b/op-deployer/justfile index 849e1e2b96d..be50d106c12 100644 --- a/op-deployer/justfile +++ b/op-deployer/justfile @@ -87,8 +87,8 @@ _validate_rpc: pre-deploy: build build-contracts # Run with: -# PRIVATE_KEY=0x1234.... NETWORK=sepolia just deploy-opcm 'op-contracts/v4.0.0-rc.8' -deploy-opcm release="dev" locator="$DEFAULT_LOCATOR": _validate_rpc +# PRIVATE_KEY=0x1234.... NETWORK=sepolia just deploy-opcm +deploy-opcm locator="$DEFAULT_LOCATOR": _validate_rpc #!/bin/bash echo "Using artifacts locator: {{locator}}" go run ./cmd/op-deployer bootstrap implementations \ @@ -96,7 +96,7 @@ deploy-opcm release="dev" locator="$DEFAULT_LOCATOR": _validate_rpc --private-key $PRIVATE_KEY \ --protocol-versions-proxy $PROTOCOL_VERSIONS_PROXY \ --superchain-config-proxy $SUPERCHAIN_CONFIG_PROXY \ - --l1-proxy-admin-owner $L1_PROXY_ADMIN_OWNER \ + --upgrade-controller $L1_PROXY_ADMIN_OWNER \ --superchain-proxy-admin $SUPERCHAIN_PROXY_ADMIN \ --challenger $CHALLENGER \ --outfile deploy-${NETWORK}.json From 94706ec5072b13030600d1b45ae10b673b660c0d Mon Sep 17 00:00:00 2001 From: Josh Klopfenstein Date: Mon, 3 Nov 2025 17:17:08 -0800 Subject: [PATCH 08/20] all: update op-geth to pull in fusaka and jovian timestamps (#18131) * all: update op-geth to pull in fusaka timestamps * update for scr changes * point go.mod at op-geth rc * address comment --- go.mod | 4 ++-- go.sum | 8 ++++---- op-node/chaincfg/chains_test.go | 4 ++-- op-service/txmgr/cli_test.go | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index a55711bdd79..057eeba7802 100644 --- a/go.mod +++ b/go.mod @@ -162,7 +162,7 @@ require ( github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/golang-lru/arc/v2 v2.0.7 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e // indirect - github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect + github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect @@ -308,7 +308,7 @@ require ( lukechampine.com/blake3 v1.3.0 // indirect ) -replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101603.3-rc.3 +replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101603.4-rc.1 // replace github.com/ethereum/go-ethereum => ../op-geth diff --git a/go.sum b/go.sum index 4e96d52c1a7..daec5bd6f99 100644 --- a/go.sum +++ b/go.sum @@ -238,8 +238,8 @@ github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.4-0.20251001155152-4eb15ccedf7e h1:iy1vBIzACYUyOVyoADUwvAiq2eOPC0yVsDUdolPwQjk= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.4-0.20251001155152-4eb15ccedf7e/go.mod h1:DYj7+vYJ4cIB7zera9mv4LcAynCL5u4YVfoeUu6Wa+w= -github.com/ethereum-optimism/op-geth v1.101603.3-rc.3 h1:KGpZouRMsMcl9MWOmYKJi+XR1gTT9/2STANv1G7oaNA= -github.com/ethereum-optimism/op-geth v1.101603.3-rc.3/go.mod h1:Wiy9cngs7ll1slc/dcHHRVuGhozWOpF1y6f31xENR7k= +github.com/ethereum-optimism/op-geth v1.101603.4-rc.1 h1:5ByBDUKBY/IHibukF/C9kjzaTk4SxUoXH449VuDrMn4= +github.com/ethereum-optimism/op-geth v1.101603.4-rc.1/go.mod h1:cnGR2M8zX91+rRQxXyNTEOEpw/IwdR8P11FQX7Xaqwk= github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20251009180028-9b4658b9b7af h1:WWz0gJM/boaUImtJnROecPirAerKCLpAU4m6Tx0ArOg= github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20251009180028-9b4658b9b7af/go.mod h1:NZ816PzLU1TLv1RdAvYAb6KWOj4Zm5aInT0YpDVml2Y= github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s= @@ -432,8 +432,8 @@ github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e h1:SK4y8oR4Z github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e/go.mod h1:EMz/UIuG93P0MBeHh6CbXQAEe8ckVJLZjhD17lBzK5Q= github.com/hashicorp/raft-boltdb/v2 v2.3.1 h1:ackhdCNPKblmOhjEU9+4lHSJYFkJd6Jqyvj6eW9pwkc= github.com/hashicorp/raft-boltdb/v2 v2.3.1/go.mod h1:n4S+g43dXF1tqDT+yzcXHhXM6y7MrlUd3TTwGRcUvQE= -github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= -github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db h1:IZUYC/xb3giYwBLMnr8d0TGTzPKFGNTCGgGLoyeX330= +github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db/go.mod h1:xTEYN9KCHxuYHs+NmrmzFcnvHMzLLNiGFafCb1n3Mfg= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= diff --git a/op-node/chaincfg/chains_test.go b/op-node/chaincfg/chains_test.go index fe2c1682dda..dd0ff560cab 100644 --- a/op-node/chaincfg/chains_test.go +++ b/op-node/chaincfg/chains_test.go @@ -77,7 +77,7 @@ var mainnetCfg = rollup.Config{ GraniteTime: u64Ptr(1726070401), HoloceneTime: u64Ptr(1736445601), IsthmusTime: u64Ptr(1746806401), - JovianTime: u64Ptr(1764086401), + JovianTime: u64Ptr(1764691201), ProtocolVersionsAddress: common.HexToAddress("0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935"), ChainOpConfig: defaultOpConfig, } @@ -118,7 +118,7 @@ var sepoliaCfg = rollup.Config{ HoloceneTime: u64Ptr(1732633200), PectraBlobScheduleTime: u64Ptr(1742486400), IsthmusTime: u64Ptr(1744905600), - JovianTime: u64Ptr(1762963201), + JovianTime: u64Ptr(1763568001), ProtocolVersionsAddress: common.HexToAddress("0x79ADD5713B383DAa0a138d3C4780C7A1804a8090"), ChainOpConfig: defaultOpConfig, } diff --git a/op-service/txmgr/cli_test.go b/op-service/txmgr/cli_test.go index 892a9d498d5..759ce037d65 100644 --- a/op-service/txmgr/cli_test.go +++ b/op-service/txmgr/cli_test.go @@ -44,9 +44,9 @@ func configForArgs(args ...string) CLIConfig { } func TestFallbackToOsakaCellProofTimeIfKnown(t *testing.T) { - // No override, but we detect the L1 is Mainnet (no Osaka time yet) + // No override, but we detect the L1 is Mainnet cellProofTime := fallbackToOsakaCellProofTimeIfKnown(big.NewInt(1), math.MaxUint64) - require.Equal(t, uint64(18446744073709551615), cellProofTime) + require.Equal(t, uint64(1764798551), cellProofTime) // No override, but we detect the L1 is Sepolia cellProofTime = fallbackToOsakaCellProofTimeIfKnown(big.NewInt(11155111), math.MaxUint64) From 3d3ffcc45520e31808e2898aa128071712cbf79f Mon Sep 17 00:00:00 2001 From: Sebastian Stammler Date: Tue, 4 Nov 2025 08:34:26 +0100 Subject: [PATCH 09/20] op-service/flags: Modularize fork override flags (#18135) --- op-core/forks/forks.go | 18 +++++-- op-node/rollup/types.go | 10 ++++ op-node/service.go | 45 +++------------- op-service/flags/flags.go | 111 ++++++++++---------------------------- 4 files changed, 58 insertions(+), 126 deletions(-) diff --git a/op-core/forks/forks.go b/op-core/forks/forks.go index 0d2bd051c27..6267734cb99 100644 --- a/op-core/forks/forks.go +++ b/op-core/forks/forks.go @@ -17,11 +17,15 @@ const ( Isthmus Name = "isthmus" Jovian Name = "jovian" Interop Name = "interop" - // ADD NEW FORKS TO All BELOW! + // ADD NEW MAINLINE FORKS TO [All] BELOW! + + // Optional Forks - not part of mainline + PectraBlobSchedule Name = "pectrablobschedule" + None Name = "" ) -// All lists all known forks in chronological order. +// All lists all known mainline forks in chronological order. var All = []Name{ Bedrock, Regolith, @@ -34,10 +38,16 @@ var All = []Name{ Isthmus, Jovian, Interop, - // ADD NEW FORKS HERE! + // ADD NEW MAINLINE FORKS HERE! +} + +// AllOpt lists all optional forks in chronological order. +var AllOpt = []Name{ + PectraBlobSchedule, + // ADD NEW OPTIONAL FORKS HERE! } -// Latest returns the most recent fork in All. +// Latest returns the most recent fork in [All]. var Latest = All[len(All)-1] // From returns the list of forks starting from the provided fork, inclusive. diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index 0d64e033118..43cc795b923 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -582,6 +582,11 @@ func (c *Config) ActivationTime(fork ForkName) *uint64 { return c.CanyonTime case forks.Regolith: return c.RegolithTime + + // Optional forks + case forks.PectraBlobSchedule: + return c.PectraBlobScheduleTime + default: panic(fmt.Sprintf("unknown fork: %v", fork)) } @@ -610,6 +615,11 @@ func (c *Config) SetActivationTime(fork ForkName, timestamp *uint64) { c.CanyonTime = timestamp case forks.Regolith: c.RegolithTime = timestamp + + // Optional forks + case forks.PectraBlobSchedule: + c.PectraBlobScheduleTime = timestamp + default: panic(fmt.Sprintf("unknown fork: %v", fork)) } diff --git a/op-node/service.go b/op-node/service.go index c87f61af6f7..9335c9b7661 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -257,45 +257,12 @@ Conflicting configuration is deprecated, and will stop the op-node from starting } func applyOverrides(ctx cliiface.Context, rollupConfig *rollup.Config) { - if ctx.IsSet(opflags.CanyonOverrideFlagName) { - canyon := ctx.Uint64(opflags.CanyonOverrideFlagName) - rollupConfig.CanyonTime = &canyon - } - if ctx.IsSet(opflags.DeltaOverrideFlagName) { - delta := ctx.Uint64(opflags.DeltaOverrideFlagName) - rollupConfig.DeltaTime = &delta - } - if ctx.IsSet(opflags.EcotoneOverrideFlagName) { - ecotone := ctx.Uint64(opflags.EcotoneOverrideFlagName) - rollupConfig.EcotoneTime = &ecotone - } - if ctx.IsSet(opflags.FjordOverrideFlagName) { - fjord := ctx.Uint64(opflags.FjordOverrideFlagName) - rollupConfig.FjordTime = &fjord - } - if ctx.IsSet(opflags.GraniteOverrideFlagName) { - granite := ctx.Uint64(opflags.GraniteOverrideFlagName) - rollupConfig.GraniteTime = &granite - } - if ctx.IsSet(opflags.HoloceneOverrideFlagName) { - holocene := ctx.Uint64(opflags.HoloceneOverrideFlagName) - rollupConfig.HoloceneTime = &holocene - } - if ctx.IsSet(opflags.PectraBlobScheduleOverrideFlagName) { - pectrablobschedule := ctx.Uint64(opflags.PectraBlobScheduleOverrideFlagName) - rollupConfig.PectraBlobScheduleTime = &pectrablobschedule - } - if ctx.IsSet(opflags.IsthmusOverrideFlagName) { - isthmus := ctx.Uint64(opflags.IsthmusOverrideFlagName) - rollupConfig.IsthmusTime = &isthmus - } - if ctx.IsSet(opflags.JovianOverrideFlagName) { - jovian := ctx.Uint64(opflags.JovianOverrideFlagName) - rollupConfig.JovianTime = &jovian - } - if ctx.IsSet(opflags.InteropOverrideFlagName) { - interop := ctx.Uint64(opflags.InteropOverrideFlagName) - rollupConfig.InteropTime = &interop + for _, fork := range opflags.OverridableForks { + flagName := opflags.OverrideName(fork) + if ctx.IsSet(flagName) { + timestamp := ctx.Uint64(flagName) + rollupConfig.SetActivationTime(fork, ×tamp) + } } } diff --git a/op-service/flags/flags.go b/op-service/flags/flags.go index 4ec4e59a918..8bc54ed04c2 100644 --- a/op-service/flags/flags.go +++ b/op-service/flags/flags.go @@ -6,101 +6,46 @@ import ( "github.com/urfave/cli/v2" + "github.com/ethereum-optimism/optimism/op-core/forks" "github.com/ethereum-optimism/optimism/op-node/chaincfg" opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliiface" ) const ( - RollupConfigFlagName = "rollup.config" - NetworkFlagName = "network" - CanyonOverrideFlagName = "override.canyon" - DeltaOverrideFlagName = "override.delta" - EcotoneOverrideFlagName = "override.ecotone" - FjordOverrideFlagName = "override.fjord" - GraniteOverrideFlagName = "override.granite" - HoloceneOverrideFlagName = "override.holocene" - PectraBlobScheduleOverrideFlagName = "override.pectrablobschedule" - IsthmusOverrideFlagName = "override.isthmus" - InteropOverrideFlagName = "override.interop" - JovianOverrideFlagName = "override.jovian" + RollupConfigFlagName = "rollup.config" + NetworkFlagName = "network" ) +// OverridableForks lists all forks that can be overridden via CLI flags or env vars. +// It's all mainline forks from Canyon onwards, plus all optional forks. +var OverridableForks = append(forks.From(forks.Canyon), forks.AllOpt...) + +func OverrideName(f forks.Name) string { return "override." + string(f) } + +func OverrideEnvVar(envPrefix string, fork forks.Name) []string { + return opservice.PrefixEnvVar(envPrefix, "OVERRIDE_"+strings.ToUpper(string(fork))) +} + func CLIFlags(envPrefix string, category string) []cli.Flag { - return []cli.Flag{ - &cli.Uint64Flag{ - Name: CanyonOverrideFlagName, - Usage: "Manually specify the Canyon fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_CANYON"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: DeltaOverrideFlagName, - Usage: "Manually specify the Delta fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_DELTA"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: EcotoneOverrideFlagName, - Usage: "Manually specify the Ecotone fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_ECOTONE"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: FjordOverrideFlagName, - Usage: "Manually specify the Fjord fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_FJORD"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: GraniteOverrideFlagName, - Usage: "Manually specify the Granite fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_GRANITE"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: HoloceneOverrideFlagName, - Usage: "Manually specify the Holocene fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_HOLOCENE"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: PectraBlobScheduleOverrideFlagName, - Usage: "Manually specify the PectraBlobSchedule fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_PECTRABLOBSCHEDULE"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: IsthmusOverrideFlagName, - Usage: "Manually specify the Isthmus fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_ISTHMUS"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: JovianOverrideFlagName, - Usage: "Manually specify the Jovian fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_JOVIAN"), - Hidden: false, - Category: category, - }, - &cli.Uint64Flag{ - Name: InteropOverrideFlagName, - Usage: "Manually specify the Interop fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_INTEROP"), - Hidden: false, - Category: category, - }, + return append(CLIOverrideFlags(envPrefix, category), CLINetworkFlag(envPrefix, category), CLIRollupConfigFlag(envPrefix, category), + ) +} + +func CLIOverrideFlags(envPrefix string, category string) []cli.Flag { + var flags []cli.Flag + for _, fork := range OverridableForks { + flags = append(flags, + &cli.Uint64Flag{ + Name: OverrideName(fork), + Usage: fmt.Sprintf("Manually specify the %s fork timestamp, overriding the bundled setting", fork), + EnvVars: OverrideEnvVar(envPrefix, fork), + Category: category, + }) } + return flags } func CLINetworkFlag(envPrefix string, category string) cli.Flag { From 3e4f7c7ef1849d67e9e531f09373a89a1ce5e6fa Mon Sep 17 00:00:00 2001 From: Stefano Charissis Date: Tue, 4 Nov 2025 20:52:14 +1100 Subject: [PATCH 10/20] chore(op-acceptance-tests): op-acceptor v3.6.2 (#18120) --- mise.toml | 2 +- op-acceptance-tests/justfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mise.toml b/mise.toml index be52c50066e..58ea2bce478 100644 --- a/mise.toml +++ b/mise.toml @@ -38,7 +38,7 @@ anvil = "1.1.0" codecov-uploader = "0.8.0" goreleaser-pro = "2.11.2" kurtosis = "1.8.1" -op-acceptor = "op-acceptor/v3.6.1" +op-acceptor = "op-acceptor/v3.6.2" # Fake dependencies # Put things here if you need to track versions of tools or projects that can't diff --git a/op-acceptance-tests/justfile b/op-acceptance-tests/justfile index dda965f70f9..31525143eeb 100644 --- a/op-acceptance-tests/justfile +++ b/op-acceptance-tests/justfile @@ -1,6 +1,6 @@ REPO_ROOT := `realpath ..` # path to the root of the optimism monorepo KURTOSIS_DIR := REPO_ROOT + "/kurtosis-devnet" -ACCEPTOR_VERSION := env_var_or_default("ACCEPTOR_VERSION", "v3.6.1") +ACCEPTOR_VERSION := env_var_or_default("ACCEPTOR_VERSION", "v3.6.2") DOCKER_REGISTRY := env_var_or_default("DOCKER_REGISTRY", "us-docker.pkg.dev/oplabs-tools-artifacts/images") ACCEPTOR_IMAGE := env_var_or_default("ACCEPTOR_IMAGE", DOCKER_REGISTRY + "/op-acceptor:" + ACCEPTOR_VERSION) From c7ca9f4b61ae76b8922e591e1af80a483326d19d Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Tue, 4 Nov 2025 13:07:59 +0100 Subject: [PATCH 11/20] op-devstack: debug info when L2CL peers connection fails (#18149) --- op-devstack/sysgo/l2_cl_p2p_util.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/op-devstack/sysgo/l2_cl_p2p_util.go b/op-devstack/sysgo/l2_cl_p2p_util.go index 911434cd28e..4ea3e8df0ce 100644 --- a/op-devstack/sysgo/l2_cl_p2p_util.go +++ b/op-devstack/sysgo/l2_cl_p2p_util.go @@ -75,6 +75,7 @@ func getP2PClientsAndPeers(ctx context.Context, logger log.Logger, func WithL2CLP2PConnection(l2CL1ID, l2CL2ID stack.L2CLNodeID) stack.Option[*Orchestrator] { return stack.AfterDeploy(func(orch *Orchestrator) { require := orch.P().Require() + l := orch.P().Logger() l2CL1, ok := orch.l2CLs.Get(l2CL1ID) require.True(ok, "looking for L2 CL node 1 to connect p2p") @@ -87,15 +88,18 @@ func WithL2CLP2PConnection(l2CL1ID, l2CL2ID stack.L2CLNodeID) stack.Option[*Orch p := getP2PClientsAndPeers(ctx, logger, require, l2CL1, l2CL2) - connectPeer := func(p2pClient *sources.P2PClient, multiAddress string) { + connectPeer := func(l2CL L2CLNode, p2pClient *sources.P2PClient, multiAddress string) { err := retry.Do0(ctx, 6, retry.Exponential(), func() error { return p2pClient.ConnectPeer(ctx, multiAddress) }) - require.NoError(err, "failed to connect peer") + if err != nil { + l.Error("failed to connect L2CL peer", "l2CL", l2CL, "rpc", l2CL.UserRPC(), "multiAddress", multiAddress, "error", err) + } + require.NoError(err, "failed to connect L2CL peer") } - connectPeer(p.client1, p.peerInfo2.Addresses[0]) - connectPeer(p.client2, p.peerInfo1.Addresses[0]) + connectPeer(l2CL1, p.client1, p.peerInfo2.Addresses[0]) + connectPeer(l2CL2, p.client2, p.peerInfo1.Addresses[0]) check := func(peerDump *apis.PeerDump, peerInfo *apis.PeerInfo) { multiAddress := peerInfo.PeerID.String() From ebc2a73717822c1f5cad6e30ddaf7cf1eea93466 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 4 Nov 2025 08:36:18 -0500 Subject: [PATCH 12/20] feat(ctb): Add the nonce and txHash into the ScheduledTransactions struct (#18097) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(ctb): Add the nonce and txHash into the ScheduledTransactions struct * chore(ctb): bump the semver on SaferSafes * feat(ctb): txHash at start of struct * semver-lock * fix ITimelockGuard to match --------- Co-authored-by: Alberto Cuesta Cañada --- .../interfaces/safe/ITimelockGuard.sol | 3 +++ .../snapshots/abi/SaferSafes.json | 20 +++++++++++++++++++ .../snapshots/semver-lock.json | 4 ++-- .../contracts-bedrock/src/safe/SaferSafes.sol | 4 ++-- .../src/safe/TimelockGuard.sol | 13 ++++++++++-- .../test/safe/TimelockGuard.t.sol | 8 +++++++- 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/packages/contracts-bedrock/interfaces/safe/ITimelockGuard.sol b/packages/contracts-bedrock/interfaces/safe/ITimelockGuard.sol index 8d462136ed2..b96b3ce9747 100644 --- a/packages/contracts-bedrock/interfaces/safe/ITimelockGuard.sol +++ b/packages/contracts-bedrock/interfaces/safe/ITimelockGuard.sol @@ -12,10 +12,13 @@ interface ITimelockGuard { Cancelled, Executed } + struct ScheduledTransaction { + bytes32 txHash; uint256 executionTime; TransactionState state; ExecTransactionParams params; + uint256 nonce; } struct ExecTransactionParams { diff --git a/packages/contracts-bedrock/snapshots/abi/SaferSafes.json b/packages/contracts-bedrock/snapshots/abi/SaferSafes.json index e3656e7a7c7..5224ed6c5f1 100644 --- a/packages/contracts-bedrock/snapshots/abi/SaferSafes.json +++ b/packages/contracts-bedrock/snapshots/abi/SaferSafes.json @@ -305,6 +305,11 @@ "outputs": [ { "components": [ + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, { "internalType": "uint256", "name": "executionTime", @@ -366,6 +371,11 @@ "internalType": "struct TimelockGuard.ExecTransactionParams", "name": "params", "type": "tuple" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" } ], "internalType": "struct TimelockGuard.ScheduledTransaction[]", @@ -475,6 +485,11 @@ "outputs": [ { "components": [ + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, { "internalType": "uint256", "name": "executionTime", @@ -536,6 +551,11 @@ "internalType": "struct TimelockGuard.ExecTransactionParams", "name": "params", "type": "tuple" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" } ], "internalType": "struct TimelockGuard.ScheduledTransaction", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 5fe766f632d..7acb955c6cd 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -208,8 +208,8 @@ "sourceCodeHash": "0x7fc4789b082bc8ecd29c4c75a06058f0ff0b72f1c1028a42db6f1c35269c8865" }, "src/safe/SaferSafes.sol:SaferSafes": { - "initCodeHash": "0x2bee3bc687583bae2cb88edcf25ebe277b8d34b30bf9faac55ae6ec80080b8b9", - "sourceCodeHash": "0xed36bffcde1bf806a9bd9b599296f4818a6c123f5277d2f3e68635cb3f22973d" + "initCodeHash": "0xb4e7885e5f181e9223ecdbc4cfc8b5887fd2c22359e4c8bb4dee53f7dd193876", + "sourceCodeHash": "0x31f453780466a9d3e498a7981f66c92c3d0b76e1ee80c19e374d9692bcfbd931" }, "src/universal/OptimismMintableERC20.sol:OptimismMintableERC20": { "initCodeHash": "0x3c85eed0d017dca8eda6396aa842ddc12492587b061e8c756a8d32c4610a9658", diff --git a/packages/contracts-bedrock/src/safe/SaferSafes.sol b/packages/contracts-bedrock/src/safe/SaferSafes.sol index 09afd1abe3a..5b57b3a38fc 100644 --- a/packages/contracts-bedrock/src/safe/SaferSafes.sol +++ b/packages/contracts-bedrock/src/safe/SaferSafes.sol @@ -26,8 +26,8 @@ import { ISemver } from "interfaces/universal/ISemver.sol"; /// compatibility restrictions in the LivenessModule2 and TimelockGuard contracts. contract SaferSafes is LivenessModule2, TimelockGuard, ISemver { /// @notice Semantic version. - /// @custom:semver 1.8.0 - string public constant version = "1.8.0"; + /// @custom:semver 1.9.0 + string public constant version = "1.9.0"; /// @notice Error for when the liveness response period is insufficient. error SaferSafes_InsufficientLivenessResponsePeriod(); diff --git a/packages/contracts-bedrock/src/safe/TimelockGuard.sol b/packages/contracts-bedrock/src/safe/TimelockGuard.sol index d76f79473c7..77824e0f9d0 100644 --- a/packages/contracts-bedrock/src/safe/TimelockGuard.sol +++ b/packages/contracts-bedrock/src/safe/TimelockGuard.sol @@ -88,13 +88,17 @@ abstract contract TimelockGuard is BaseGuard { } /// @notice Scheduled transaction + /// @custom:field txHash The hash of the transaction. /// @custom:field executionTime The timestamp when execution becomes valid. /// @custom:field state The state of the transaction. /// @custom:field params The parameters of the transaction. + /// @custom:field nonce The nonce of the transaction. struct ScheduledTransaction { + bytes32 txHash; uint256 executionTime; TransactionState state; ExecTransactionParams params; + uint256 nonce; } /// @notice Parameters for the Safe's execTransaction function @@ -564,8 +568,13 @@ abstract contract TimelockGuard is BaseGuard { uint256 executionTime = block.timestamp + _currentSafeState(_safe).timelockDelay; // Schedule the transaction and add it to the pending transactions set - _currentSafeState(_safe).scheduledTransactions[txHash] = - ScheduledTransaction({ executionTime: executionTime, state: TransactionState.Pending, params: _params }); + _currentSafeState(_safe).scheduledTransactions[txHash] = ScheduledTransaction({ + txHash: txHash, + executionTime: executionTime, + state: TransactionState.Pending, + params: _params, + nonce: _nonce + }); _currentSafeState(_safe).pendingTxHashes.add(txHash); emit TransactionScheduled(_safe, txHash, executionTime); diff --git a/packages/contracts-bedrock/test/safe/TimelockGuard.t.sol b/packages/contracts-bedrock/test/safe/TimelockGuard.t.sol index f3bff3735b5..8ddb4fb1a11 100644 --- a/packages/contracts-bedrock/test/safe/TimelockGuard.t.sol +++ b/packages/contracts-bedrock/test/safe/TimelockGuard.t.sol @@ -505,9 +505,11 @@ contract TimelockGuard_ScheduledTransaction_Test is TimelockGuard_TestInit { TimelockGuard.ScheduledTransaction memory scheduledTransaction = timelockGuard.scheduledTransaction(safe, dummyTx.hash); + assertEq(scheduledTransaction.txHash, dummyTx.hash); assertEq(scheduledTransaction.executionTime, INIT_TIME + TIMELOCK_DELAY); assert(scheduledTransaction.state == TimelockGuard.TransactionState.Pending); assertEq(keccak256(abi.encode(scheduledTransaction.params)), keccak256(abi.encode(dummyTx.params))); + assertEq(scheduledTransaction.nonce, dummyTx.nonce); } } @@ -525,9 +527,13 @@ contract TimelockGuard_PendingTransactions_Test is TimelockGuard_TestInit { dummyTx.scheduleTransaction(timelockGuard); TimelockGuard.ScheduledTransaction[] memory pendingTransactions = timelockGuard.pendingTransactions(safe); + // verify the pending transaction is the one we scheduled assertEq(pendingTransactions.length, 1); - // ensure the hash of the transaction params are the same + assertEq(pendingTransactions[0].txHash, dummyTx.hash); + assertEq(pendingTransactions[0].executionTime, INIT_TIME + TIMELOCK_DELAY); + assert(pendingTransactions[0].state == TimelockGuard.TransactionState.Pending); assertEq(pendingTransactions[0].params.to, dummyTx.params.to); + assertEq(pendingTransactions[0].nonce, dummyTx.nonce); assertEq(keccak256(abi.encode(pendingTransactions[0].params)), keccak256(abi.encode(dummyTx.params))); } From 5e3fc2e3043f87fbb76705b834e6b5ff55498a3f Mon Sep 17 00:00:00 2001 From: Jake Nyquist Date: Tue, 4 Nov 2025 11:50:01 -0500 Subject: [PATCH 13/20] feat(l3s): Add support for the default finality lookback (#18071) --- op-e2e/actions/helpers/l2_verifier.go | 4 +- op-node/flags/flags.go | 14 +++ op-node/rollup/driver/config.go | 5 + op-node/rollup/driver/driver.go | 4 +- op-node/rollup/finality/altda.go | 7 +- op-node/rollup/finality/altda_test.go | 6 +- op-node/rollup/finality/finalizer.go | 42 ++++++++- op-node/rollup/finality/finalizer_test.go | 110 ++++++++++++++++++++-- op-node/service.go | 17 +++- 9 files changed, 189 insertions(+), 20 deletions(-) diff --git a/op-e2e/actions/helpers/l2_verifier.go b/op-e2e/actions/helpers/l2_verifier.go index b0b5f102650..c99e95e288b 100644 --- a/op-e2e/actions/helpers/l2_verifier.go +++ b/op-e2e/actions/helpers/l2_verifier.go @@ -155,9 +155,9 @@ func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, var finalizer driver.Finalizer if cfg.AltDAEnabled() { - finalizer = finality.NewAltDAFinalizer(ctx, log, cfg, l1, altDASrc, ec) + finalizer = finality.NewAltDAFinalizer(ctx, log, cfg, nil, l1, altDASrc, ec) } else { - finalizer = finality.NewFinalizer(ctx, log, cfg, l1, ec) + finalizer = finality.NewFinalizer(ctx, log, cfg, nil, l1, ec) } sys.Register("finalizer", finalizer, opts) diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index e7238352723..90326aeb8d8 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -252,6 +252,18 @@ var ( Value: false, Category: SequencerCategory, } + FinalityLookbackFlag = &cli.Uint64Flag{ + Name: "finality.lookback", + Usage: "Number of L1 blocks to look back for finality verification. Uses default calculation if 0 (considers alt-DA challenge/resolve windows if applicable).", + EnvVars: prefixEnvVars("FINALITY_LOOKBACK"), + Category: RollupCategory, + } + FinalityDelayFlag = &cli.Uint64Flag{ + Name: "finality.delay", + Usage: "Number of L1 blocks to traverse before trying to finalize L2 blocks again. Uses default (64) if 0.", + EnvVars: prefixEnvVars("FINALITY_DELAY"), + Category: RollupCategory, + } L1EpochPollIntervalFlag = &cli.DurationFlag{ Name: "l1.epoch-poll-interval", Usage: "Poll interval for retrieving new L1 epoch updates such as safe and finalized block changes. Disabled if 0 or negative.", @@ -450,6 +462,8 @@ var optionalFlags = []cli.Flag{ SequencerMaxSafeLagFlag, SequencerL1Confs, SequencerRecoverMode, + FinalityLookbackFlag, + FinalityDelayFlag, L1EpochPollIntervalFlag, RuntimeConfigReloadIntervalFlag, RPCAdminPersistence, diff --git a/op-node/rollup/driver/config.go b/op-node/rollup/driver/config.go index 5446e4da16a..d519a7e4547 100644 --- a/op-node/rollup/driver/config.go +++ b/op-node/rollup/driver/config.go @@ -1,5 +1,7 @@ package driver +import "github.com/ethereum-optimism/optimism/op-node/rollup/finality" + type Config struct { // VerifierConfDepth is the distance to keep from the L1 head when reading L1 data for L2 derivation. VerifierConfDepth uint64 `json:"verifier_conf_depth"` @@ -24,4 +26,7 @@ type Config struct { // RecoverMode forces the sequencer to select the next L1 Origin exactly, and create an empty block, // to be compatible with verifiers forcefully generating the same block while catching up the sequencing window timeout. RecoverMode bool `json:"recover_mode"` + + // Finalizer contains runtime configuration for finality behavior. + Finalizer *finality.Config `json:"finalizer,omitempty"` } diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index cc402cecab8..f0a7c66098f 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -65,9 +65,9 @@ func NewDriver( var finalizer Finalizer if cfg.AltDAEnabled() { - finalizer = finality.NewAltDAFinalizer(driverCtx, log, cfg, l1, altDA, ec) + finalizer = finality.NewAltDAFinalizer(driverCtx, log, cfg, driverCfg.Finalizer, l1, altDA, ec) } else { - finalizer = finality.NewFinalizer(driverCtx, log, cfg, l1, ec) + finalizer = finality.NewFinalizer(driverCtx, log, cfg, driverCfg.Finalizer, l1, ec) } sys.Register("finalizer", finalizer) diff --git a/op-node/rollup/finality/altda.go b/op-node/rollup/finality/altda.go index ae32725c70e..d722fbf89c5 100644 --- a/op-node/rollup/finality/altda.go +++ b/op-node/rollup/finality/altda.go @@ -27,11 +27,14 @@ type AltDAFinalizer struct { backend AltDABackend } -func NewAltDAFinalizer(ctx context.Context, log log.Logger, cfg *rollup.Config, +// NewAltDAFinalizer creates a new AltDAFinalizer instance. +// The finalizerCfg parameter is optional and may be nil to use default finality behavior. +// When non-nil, any non-nil fields in finalizerCfg will override the defaults. +func NewAltDAFinalizer(ctx context.Context, log log.Logger, cfg *rollup.Config, finalizerCfg *Config, l1Fetcher FinalizerL1Interface, backend AltDABackend, ec EngineController) *AltDAFinalizer { - inner := NewFinalizer(ctx, log, cfg, l1Fetcher, ec) + inner := NewFinalizer(ctx, log, cfg, finalizerCfg, l1Fetcher, ec) // In alt-da mode, the finalization signal is proxied through the AltDA manager. // Finality signal will come from the DA contract or L1 finality whichever is last. diff --git a/op-node/rollup/finality/altda_test.go b/op-node/rollup/finality/altda_test.go index a3c1a384386..5f01180a831 100644 --- a/op-node/rollup/finality/altda_test.go +++ b/op-node/rollup/finality/altda_test.go @@ -81,11 +81,11 @@ func TestAltDAFinalityData(t *testing.T) { DAResolveWindow: 90, } // should return l1 finality if altda is not enabled - require.Equal(t, uint64(defaultFinalityLookback), calcFinalityLookback(cfg)) + require.Equal(t, uint64(defaultFinalityLookback), calcFinalityLookback(cfg, nil)) cfg.AltDAConfig = altDACfg expFinalityLookback := 181 - require.Equal(t, uint64(expFinalityLookback), calcFinalityLookback(cfg)) + require.Equal(t, uint64(expFinalityLookback), calcFinalityLookback(cfg, nil)) refA1 := eth.L2BlockRef{ Hash: testutils.RandomHash(rng), @@ -108,7 +108,7 @@ func TestAltDAFinalityData(t *testing.T) { emitter := &testutils.MockEmitter{} ec := new(fakeEngineController) - fi := NewAltDAFinalizer(context.Background(), logger, cfg, l1F, altDABackend, ec) + fi := NewAltDAFinalizer(context.Background(), logger, cfg, nil, l1F, altDABackend, ec) fi.AttachEmitter(emitter) require.NotNil(t, altDABackend.forwardTo, "altda backend must have access to underlying standard finalizer") diff --git a/op-node/rollup/finality/finalizer.go b/op-node/rollup/finality/finalizer.go index 4d520696d94..ceaf3f6fb59 100644 --- a/op-node/rollup/finality/finalizer.go +++ b/op-node/rollup/finality/finalizer.go @@ -34,9 +34,26 @@ const defaultFinalityLookback = 4*32 + 1 // We do not want to do this too often, since it requires fetching a L1 block by number, so no cache data. const finalityDelay = 64 +// Config contains runtime configuration for the finalizer. +type Config struct { + // FinalityLookback specifies the number of L1 blocks to look back for finality verification. + // When nil, uses the default finality lookback calculation (which considers both + // the default lookback and alt-DA challenge/resolve windows if applicable). + FinalityLookback *uint64 + + // FinalityDelay specifies the number of L1 blocks to traverse before trying to finalize L2 blocks again. + // When nil, defaults to 64 blocks. + FinalityDelay *uint64 +} + // calcFinalityLookback calculates the default finality lookback based on DA challenge window if altDA // mode is activated or L1 finality lookback. -func calcFinalityLookback(cfg *rollup.Config) uint64 { +func calcFinalityLookback(cfg *rollup.Config, finalizerCfg *Config) uint64 { + // If a custom finality lookback is configured, use it as an override + if finalizerCfg != nil && finalizerCfg.FinalityLookback != nil { + return *finalizerCfg.FinalityLookback + } + // in alt-da mode the longest finality lookback is a commitment is challenged on the last block of // the challenge window in which case it will be both challenge + resolve window. if cfg.AltDAEnabled() { @@ -49,6 +66,15 @@ func calcFinalityLookback(cfg *rollup.Config) uint64 { return defaultFinalityLookback } +// calcFinalityDelay calculates the finality delay based on the runtime config or returns the default. +func calcFinalityDelay(finalizerCfg *Config) uint64 { + // If a custom finality delay is configured, use it as an override + if finalizerCfg != nil && finalizerCfg.FinalityDelay != nil { + return *finalizerCfg.FinalityDelay + } + return finalityDelay +} + type FinalityData struct { // The last L2 block that was fully derived and inserted into the L2 engine while processing this L1 block. L2Block eth.L2BlockRef @@ -99,11 +125,18 @@ type Finalizer struct { // Maximum amount of L2 blocks to store in finalityData. finalityLookback uint64 + // Number of L1 blocks to traverse before trying to finalize L2 blocks again. + finalityDelay uint64 + l1Fetcher FinalizerL1Interface } -func NewFinalizer(ctx context.Context, log log.Logger, cfg *rollup.Config, l1Fetcher FinalizerL1Interface, ec EngineController) *Finalizer { - lookback := calcFinalityLookback(cfg) +// NewFinalizer creates a new Finalizer instance. +// The finalizerCfg parameter is optional and may be nil to use default finality behavior. +// When non-nil, any non-nil fields in finalizerCfg will override the defaults. +func NewFinalizer(ctx context.Context, log log.Logger, cfg *rollup.Config, finalizerCfg *Config, l1Fetcher FinalizerL1Interface, ec EngineController) *Finalizer { + lookback := calcFinalityLookback(cfg, finalizerCfg) + delay := calcFinalityDelay(finalizerCfg) return &Finalizer{ ctx: ctx, cfg: cfg, @@ -113,6 +146,7 @@ func NewFinalizer(ctx context.Context, log log.Logger, cfg *rollup.Config, l1Fet triedFinalizeAt: 0, finalityData: make([]FinalityData, 0, lookback), finalityLookback: lookback, + finalityDelay: delay, l1Fetcher: l1Fetcher, } } @@ -195,7 +229,7 @@ func (fi *Finalizer) onDerivationIdle(derivedFrom eth.L1BlockRef) { return // if no L1 information is finalized yet, then skip this } // If we recently tried finalizing, then don't try again just yet, but traverse more of L1 first. - if fi.triedFinalizeAt != 0 && derivedFrom.Number <= fi.triedFinalizeAt+finalityDelay { + if fi.triedFinalizeAt != 0 && derivedFrom.Number <= fi.triedFinalizeAt+fi.finalityDelay { return } fi.log.Debug("processing L1 finality information", "l1_finalized", fi.finalizedL1, "derived_from", derivedFrom, "previous", fi.triedFinalizeAt) diff --git a/op-node/rollup/finality/finalizer_test.go b/op-node/rollup/finality/finalizer_test.go index 4ab1cf492c1..fe5ef061db8 100644 --- a/op-node/rollup/finality/finalizer_test.go +++ b/op-node/rollup/finality/finalizer_test.go @@ -194,7 +194,7 @@ func TestEngineQueue_Finalize(t *testing.T) { emitter := &testutils.MockEmitter{} ec := new(fakeEngineController) - fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, l1F, ec) + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, nil, l1F, ec) fi.AttachEmitter(emitter) // now say C1 was included in D and became the new safe head @@ -229,7 +229,7 @@ func TestEngineQueue_Finalize(t *testing.T) { emitter := &testutils.MockEmitter{} ec := new(fakeEngineController) - fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, l1F, ec) + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, nil, l1F, ec) fi.AttachEmitter(emitter) // now say C1 was included in D and became the new safe head @@ -268,7 +268,7 @@ func TestEngineQueue_Finalize(t *testing.T) { emitter := &testutils.MockEmitter{} ec := new(fakeEngineController) - fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, l1F, ec) + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, nil, l1F, ec) fi.AttachEmitter(emitter) fi.OnEvent(ctx, engine.SafeDerivedEvent{Safe: refC1, Source: refD}) @@ -352,7 +352,7 @@ func TestEngineQueue_Finalize(t *testing.T) { emitter := &testutils.MockEmitter{} ec := new(fakeEngineController) - fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, l1F, ec) + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, nil, l1F, ec) fi.AttachEmitter(emitter) // now say B1 was included in C and became the new safe head @@ -389,7 +389,7 @@ func TestEngineQueue_Finalize(t *testing.T) { emitter := &testutils.MockEmitter{} ec := new(fakeEngineController) - fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, l1F, ec) + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, nil, l1F, ec) fi.AttachEmitter(emitter) // now say B1 was included in C and became the new safe head @@ -486,7 +486,7 @@ func TestEngineQueue_Finalize(t *testing.T) { ec := new(fakeEngineController) fi := NewFinalizer(context.Background(), logger, &rollup.Config{ InteropTime: &refC1.Time, - }, l1F, ec) + }, nil, l1F, ec) fi.AttachEmitter(emitter) // now say C0 and C1 were included in D and became the new safe head @@ -504,3 +504,101 @@ func TestEngineQueue_Finalize(t *testing.T) { emitter.AssertExpectations(t) }) } + +func TestFinalizerConfig(t *testing.T) { + t.Run("uses custom finality lookback", func(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + l1F := &testutils.MockL1Source{} + ec := new(fakeEngineController) + + customLookback := uint64(200) + finalizerCfg := &Config{ + FinalityLookback: &customLookback, + } + + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, finalizerCfg, l1F, ec) + + require.Equal(t, customLookback, fi.finalityLookback, "should use custom finality lookback") + require.Equal(t, int(customLookback), cap(fi.finalityData), "finalityData capacity should match custom lookback") + }) + + t.Run("uses custom finality delay", func(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + l1F := &testutils.MockL1Source{} + ec := new(fakeEngineController) + + customDelay := uint64(32) + finalizerCfg := &Config{ + FinalityDelay: &customDelay, + } + + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, finalizerCfg, l1F, ec) + + require.Equal(t, customDelay, fi.finalityDelay, "should use custom finality delay") + }) + + t.Run("uses defaults when config is nil", func(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + l1F := &testutils.MockL1Source{} + ec := new(fakeEngineController) + + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, nil, l1F, ec) + + require.Equal(t, uint64(defaultFinalityLookback), fi.finalityLookback, "should use default finality lookback when config is nil") + require.Equal(t, uint64(finalityDelay), fi.finalityDelay, "should use default finality delay when config is nil") + }) + + t.Run("uses defaults when config fields are nil", func(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + l1F := &testutils.MockL1Source{} + ec := new(fakeEngineController) + + // Passing empty config should behave same as nil + finalizerCfg := &Config{} + + fi := NewFinalizer(context.Background(), logger, &rollup.Config{}, finalizerCfg, l1F, ec) + + require.Equal(t, uint64(defaultFinalityLookback), fi.finalityLookback, "should use default finality lookback when config fields are nil") + require.Equal(t, uint64(finalityDelay), fi.finalityDelay, "should use default finality delay when config fields are nil") + }) + + t.Run("uses alt-da lookback when configured", func(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + l1F := &testutils.MockL1Source{} + ec := new(fakeEngineController) + + cfg := &rollup.Config{ + AltDAConfig: &rollup.AltDAConfig{ + DAChallengeWindow: 90, + DAResolveWindow: 90, + }, + } + + fi := NewFinalizer(context.Background(), logger, cfg, nil, l1F, ec) + + expectedLookback := uint64(181) // 90 + 90 + 1 + require.Equal(t, expectedLookback, fi.finalityLookback, "should use alt-da calculated lookback") + }) + + t.Run("custom lookback overrides alt-da calculation", func(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + l1F := &testutils.MockL1Source{} + ec := new(fakeEngineController) + + cfg := &rollup.Config{ + AltDAConfig: &rollup.AltDAConfig{ + DAChallengeWindow: 90, + DAResolveWindow: 90, + }, + } + + customLookback := uint64(300) + finalizerCfg := &Config{ + FinalityLookback: &customLookback, + } + + fi := NewFinalizer(context.Background(), logger, cfg, finalizerCfg, l1F, ec) + + require.Equal(t, customLookback, fi.finalityLookback, "custom lookback should override alt-da calculation") + }) +} diff --git a/op-node/service.go b/op-node/service.go index 9335c9b7661..6c10e1718be 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/rollup/engine" + "github.com/ethereum-optimism/optimism/op-node/rollup/finality" "github.com/ethereum-optimism/optimism/op-node/rollup/interop" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/cliiface" @@ -202,7 +203,7 @@ func NewConfigPersistence(ctx cliiface.Context) config.ConfigPersistence { } func NewDriverConfig(ctx cliiface.Context) *driver.Config { - return &driver.Config{ + cfg := &driver.Config{ VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name), SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name), SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name), @@ -210,6 +211,20 @@ func NewDriverConfig(ctx cliiface.Context) *driver.Config { SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name), RecoverMode: ctx.Bool(flags.SequencerRecoverMode.Name), } + + // Populate finality config from flags. A finality config with null fields + // is handled the same way as a null finality config. + cfg.Finalizer = &finality.Config{} + if ctx.IsSet(flags.FinalityLookbackFlag.Name) { + lookback := ctx.Uint64(flags.FinalityLookbackFlag.Name) + cfg.Finalizer.FinalityLookback = &lookback + } + if ctx.IsSet(flags.FinalityDelayFlag.Name) { + delay := ctx.Uint64(flags.FinalityDelayFlag.Name) + cfg.Finalizer.FinalityDelay = &delay + } + + return cfg } func NewRollupConfigFromCLI(log log.Logger, ctx cliiface.Context) (*rollup.Config, error) { From 2ce9a84ca3dc5cacbadd010a953b49f63a83c8c4 Mon Sep 17 00:00:00 2001 From: Stefano Charissis Date: Wed, 5 Nov 2025 06:14:15 +1100 Subject: [PATCH 14/20] chore(op-acceptance-tests): switch to docker executor (#18084) --- .circleci/config.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c08ea0f326a..1f8f13a8d07 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1600,14 +1600,10 @@ jobs: description: Timeout for when CircleCI kills the job if there's no output type: string default: 30m - use_circleci_runner: - description: Whether to use CircleCI runners (with Docker) instead of self-hosted runners - type: boolean - default: false - machine: - image: <<# parameters.use_circleci_runner >>ubuntu-2404:current<><<^ parameters.use_circleci_runner >>true<> - docker_layer_caching: <> - resource_class: <<# parameters.use_circleci_runner >>xlarge<><<^ parameters.use_circleci_runner >>ethereum-optimism/latitude-1<> + docker: + - image: <> + circleci_ip_ranges: true + resource_class: 2xlarge steps: - checkout-from-workspace # Restore cached Go modules From d9a6c32f76849d68937e15cae381ccd7b1cb1126 Mon Sep 17 00:00:00 2001 From: Sebastian Stammler Date: Tue, 4 Nov 2025 22:05:36 +0100 Subject: [PATCH 15/20] all: Move package predeploys from op-service to op-core (#18145) * all: Move package predeploys from op-service to op-core * gofmt --------- Co-authored-by: Adrian Sutton --- op-acceptance-tests/tests/fjord/check_scripts_test.go | 2 +- op-acceptance-tests/tests/fjord/fees_test.go | 2 +- op-acceptance-tests/tests/fusaka/fusaka_test.go | 2 +- op-acceptance-tests/tests/interop/message/interop_msg_test.go | 2 +- op-acceptance-tests/tests/interop/smoke/interop_smoke_test.go | 2 +- op-acceptance-tests/tests/interop/smoke/smoke_test.go | 2 +- .../tests/interop/upgrade-singlechain/crossl2inbox_test.go | 2 +- op-acceptance-tests/tests/interop/upgrade/post_test.go | 2 +- op-acceptance-tests/tests/interop/upgrade/pre_test.go | 2 +- op-chain-ops/cmd/check-ecotone/main.go | 2 +- op-chain-ops/cmd/check-fjord/checks/checks.go | 2 +- op-chain-ops/cmd/withdrawal/init.go | 2 +- op-chain-ops/genesis/genesis.go | 2 +- op-chain-ops/genesis/layer_one.go | 2 +- op-chain-ops/genesis/layer_two.go | 2 +- {op-service => op-core}/predeploys/addresses.go | 0 {op-service => op-core}/predeploys/addresses_test.go | 0 {op-service => op-core}/predeploys/eip2935.go | 0 {op-service => op-core}/predeploys/eip4788.go | 0 {op-service => op-core}/predeploys/legacy_addresses.go | 0 {op-service => op-core}/predeploys/predeploy.go | 0 op-deployer/pkg/deployer/inspect/semvers.go | 2 +- op-deployer/pkg/deployer/integration_test/apply_test.go | 2 +- op-devstack/dsl/bridge.go | 2 +- op-devstack/dsl/ecotone_fees.go | 2 +- op-devstack/dsl/fjord_fees.go | 2 +- op-devstack/dsl/l2_el.go | 2 +- op-devstack/dsl/operator_fee.go | 2 +- op-e2e/actions/helpers/user.go | 2 +- op-e2e/actions/interop/dsl/inbox.go | 2 +- op-e2e/actions/interop/dsl/message.go | 2 +- op-e2e/actions/interop/emitter_contract_test.go | 2 +- op-e2e/actions/interop/interop_fork_test.go | 2 +- op-e2e/actions/proofs/isthmus_fork_test.go | 2 +- op-e2e/actions/proofs/jovian_dafootprint_test.go | 2 +- op-e2e/actions/proofs/jovian_minbasefee_test.go | 2 +- op-e2e/actions/proofs/l1_blob_parameter_forks_test.go | 2 +- op-e2e/actions/proofs/operator_fee_fix_transition_test.go | 2 +- op-e2e/actions/proofs/operator_fee_test.go | 2 +- op-e2e/actions/proofs/pectra_blob_schedule_test.go | 2 +- op-e2e/actions/upgrades/ecotone_fork_test.go | 2 +- op-e2e/actions/upgrades/fjord_fork_test.go | 2 +- op-e2e/e2eutils/addresses.go | 2 +- op-e2e/e2eutils/setup_test.go | 2 +- op-e2e/faultproofs/cannon_benchmark_test.go | 2 +- op-e2e/interop/supersystem.go | 2 +- op-e2e/opgeth/fastlz_test.go | 2 +- op-e2e/system/bridge/bridge_test.go | 2 +- op-e2e/system/bridge/validity_test.go | 2 +- op-e2e/system/e2esys/setup.go | 2 +- op-e2e/system/fees/fees_test.go | 2 +- op-e2e/system/fees/gaspriceoracle_test.go | 2 +- op-e2e/system/helpers/withdrawal_helper.go | 2 +- op-node/rollup/attributes/engine_consolidate_test.go | 2 +- op-node/rollup/derive/attributes.go | 2 +- op-node/rollup/derive/attributes_queue_test.go | 2 +- op-node/rollup/derive/attributes_test.go | 2 +- op-node/rollup/derive/ecotone_upgrade_transactions.go | 2 +- op-node/rollup/derive/fjord_upgrade_transactions.go | 2 +- op-node/rollup/derive/interop_upgrade_transactions.go | 2 +- op-node/rollup/derive/interop_upgrade_transactions_test.go | 2 +- op-node/rollup/derive/isthmus_upgrade_transactions.go | 2 +- op-node/rollup/derive/isthmus_upgrade_transactions_test.go | 2 +- op-node/rollup/derive/jovian_upgrade_transactions.go | 2 +- op-node/rollup/derive/l1_block_info.go | 2 +- op-node/rollup/sequencing/sequencer_test.go | 2 +- op-node/withdrawals/utils.go | 2 +- op-program/client/l2/engine.go | 2 +- op-program/client/l2/engineapi/block_processor.go | 2 +- op-program/client/l2/oracle.go | 2 +- op-service/sources/l2_client.go | 2 +- op-service/sources/types.go | 2 +- op-service/txinclude/isthmus_cost_oracle.go | 2 +- .../supervisor/backend/processors/log_processor_test.go | 2 +- .../contracts-bedrock/scripts/go-ffi/differential-testing.go | 2 +- 75 files changed, 69 insertions(+), 69 deletions(-) rename {op-service => op-core}/predeploys/addresses.go (100%) rename {op-service => op-core}/predeploys/addresses_test.go (100%) rename {op-service => op-core}/predeploys/eip2935.go (100%) rename {op-service => op-core}/predeploys/eip4788.go (100%) rename {op-service => op-core}/predeploys/legacy_addresses.go (100%) rename {op-service => op-core}/predeploys/predeploy.go (100%) diff --git a/op-acceptance-tests/tests/fjord/check_scripts_test.go b/op-acceptance-tests/tests/fjord/check_scripts_test.go index 2572332b7df..53da549bd91 100644 --- a/op-acceptance-tests/tests/fjord/check_scripts_test.go +++ b/op-acceptance-tests/tests/fjord/check_scripts_test.go @@ -8,11 +8,11 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" txib "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txintent/contractio" "github.com/ethereum-optimism/optimism/op-service/txplan" diff --git a/op-acceptance-tests/tests/fjord/fees_test.go b/op-acceptance-tests/tests/fjord/fees_test.go index 980153c7f50..384eda832be 100644 --- a/op-acceptance-tests/tests/fjord/fees_test.go +++ b/op-acceptance-tests/tests/fjord/fees_test.go @@ -8,8 +8,8 @@ import ( "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" txib "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" ) diff --git a/op-acceptance-tests/tests/fusaka/fusaka_test.go b/op-acceptance-tests/tests/fusaka/fusaka_test.go index c0d8506dcc4..c5352a8105b 100644 --- a/op-acceptance-tests/tests/fusaka/fusaka_test.go +++ b/op-acceptance-tests/tests/fusaka/fusaka_test.go @@ -10,11 +10,11 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/interop/loadtest" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txinclude" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txintent/contractio" diff --git a/op-acceptance-tests/tests/interop/message/interop_msg_test.go b/op-acceptance-tests/tests/interop/message/interop_msg_test.go index 488d2fbe0bc..c5a2bef337e 100644 --- a/op-acceptance-tests/tests/interop/message/interop_msg_test.go +++ b/op-acceptance-tests/tests/interop/message/interop_msg_test.go @@ -9,13 +9,13 @@ import ( "github.com/ethereum-optimism/optimism/devnet-sdk/contracts/constants" "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/interop" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/dsl/contract" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/plan" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum-optimism/optimism/op-service/txintent" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" diff --git a/op-acceptance-tests/tests/interop/smoke/interop_smoke_test.go b/op-acceptance-tests/tests/interop/smoke/interop_smoke_test.go index c3891ca4777..881f834f428 100644 --- a/op-acceptance-tests/tests/interop/smoke/interop_smoke_test.go +++ b/op-acceptance-tests/tests/interop/smoke/interop_smoke_test.go @@ -3,10 +3,10 @@ package smoke import ( "testing" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" txib "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txintent/contractio" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-acceptance-tests/tests/interop/smoke/smoke_test.go b/op-acceptance-tests/tests/interop/smoke/smoke_test.go index 4260c0378e4..749d66cd2b0 100644 --- a/op-acceptance-tests/tests/interop/smoke/smoke_test.go +++ b/op-acceptance-tests/tests/interop/smoke/smoke_test.go @@ -3,11 +3,11 @@ package smoke import ( "testing" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl/contract" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txintent/contractio" "github.com/ethereum-optimism/optimism/op-service/txplan" diff --git a/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go b/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go index e579de1eff1..8083675cd36 100644 --- a/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go +++ b/op-acceptance-tests/tests/interop/upgrade-singlechain/crossl2inbox_test.go @@ -5,11 +5,11 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ) diff --git a/op-acceptance-tests/tests/interop/upgrade/post_test.go b/op-acceptance-tests/tests/interop/upgrade/post_test.go index faf69facfde..dacf18248d4 100644 --- a/op-acceptance-tests/tests/interop/upgrade/post_test.go +++ b/op-acceptance-tests/tests/interop/upgrade/post_test.go @@ -10,12 +10,12 @@ import ( "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/interop" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" stypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum/go-ethereum/common" diff --git a/op-acceptance-tests/tests/interop/upgrade/pre_test.go b/op-acceptance-tests/tests/interop/upgrade/pre_test.go index 9af93d1c726..8d3e75d9380 100644 --- a/op-acceptance-tests/tests/interop/upgrade/pre_test.go +++ b/op-acceptance-tests/tests/interop/upgrade/pre_test.go @@ -13,12 +13,12 @@ import ( "github.com/ethereum-optimism/optimism/devnet-sdk/contracts/constants" "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/interop" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/presets" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txintent" stypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) diff --git a/op-chain-ops/cmd/check-ecotone/main.go b/op-chain-ops/cmd/check-ecotone/main.go index 10d5f72e7ad..a1726d72c71 100644 --- a/op-chain-ops/cmd/check-ecotone/main.go +++ b/op-chain-ops/cmd/check-ecotone/main.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-chain-ops/cmd/check-ecotone/bindings" + "github.com/ethereum-optimism/optimism/op-core/predeploys" nbindings "github.com/ethereum-optimism/optimism/op-node/bindings" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" op_service "github.com/ethereum-optimism/optimism/op-service" @@ -35,7 +36,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/eth" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/txmgr" diff --git a/op-chain-ops/cmd/check-fjord/checks/checks.go b/op-chain-ops/cmd/check-fjord/checks/checks.go index a7063bbde94..e24cfdada85 100644 --- a/op-chain-ops/cmd/check-fjord/checks/checks.go +++ b/op-chain-ops/cmd/check-fjord/checks/checks.go @@ -22,9 +22,9 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) type CheckFjordConfig struct { diff --git a/op-chain-ops/cmd/withdrawal/init.go b/op-chain-ops/cmd/withdrawal/init.go index ae84d72e0a2..341302bf26f 100644 --- a/op-chain-ops/cmd/withdrawal/init.go +++ b/op-chain-ops/cmd/withdrawal/init.go @@ -4,9 +4,9 @@ import ( "fmt" "math/big" + "github.com/ethereum-optimism/optimism/op-core/predeploys" op_service "github.com/ethereum-optimism/optimism/op-service" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/urfave/cli/v2" ) diff --git a/op-chain-ops/genesis/genesis.go b/op-chain-ops/genesis/genesis.go index 306f70df2dd..a7a437fc172 100644 --- a/op-chain-ops/genesis/genesis.go +++ b/op-chain-ops/genesis/genesis.go @@ -6,8 +6,8 @@ import ( "math/big" "time" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" diff --git a/op-chain-ops/genesis/layer_one.go b/op-chain-ops/genesis/layer_one.go index 7178cccebb9..dfcc5ee53d4 100644 --- a/op-chain-ops/genesis/layer_one.go +++ b/op-chain-ops/genesis/layer_one.go @@ -12,7 +12,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis/beacondeposit" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" ) // PrecompileCount represents the number of precompile addresses diff --git a/op-chain-ops/genesis/layer_two.go b/op-chain-ops/genesis/layer_two.go index 5a89ac0bfd3..20181596451 100644 --- a/op-chain-ops/genesis/layer_two.go +++ b/op-chain-ops/genesis/layer_two.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) type L2AllocsMode string diff --git a/op-service/predeploys/addresses.go b/op-core/predeploys/addresses.go similarity index 100% rename from op-service/predeploys/addresses.go rename to op-core/predeploys/addresses.go diff --git a/op-service/predeploys/addresses_test.go b/op-core/predeploys/addresses_test.go similarity index 100% rename from op-service/predeploys/addresses_test.go rename to op-core/predeploys/addresses_test.go diff --git a/op-service/predeploys/eip2935.go b/op-core/predeploys/eip2935.go similarity index 100% rename from op-service/predeploys/eip2935.go rename to op-core/predeploys/eip2935.go diff --git a/op-service/predeploys/eip4788.go b/op-core/predeploys/eip4788.go similarity index 100% rename from op-service/predeploys/eip4788.go rename to op-core/predeploys/eip4788.go diff --git a/op-service/predeploys/legacy_addresses.go b/op-core/predeploys/legacy_addresses.go similarity index 100% rename from op-service/predeploys/legacy_addresses.go rename to op-core/predeploys/legacy_addresses.go diff --git a/op-service/predeploys/predeploy.go b/op-core/predeploys/predeploy.go similarity index 100% rename from op-service/predeploys/predeploy.go rename to op-core/predeploys/predeploy.go diff --git a/op-deployer/pkg/deployer/inspect/semvers.go b/op-deployer/pkg/deployer/inspect/semvers.go index 232f1d4bd85..fa3cd31fa8c 100644 --- a/op-deployer/pkg/deployer/inspect/semvers.go +++ b/op-deployer/pkg/deployer/inspect/semvers.go @@ -18,12 +18,12 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline" "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/jsonutil" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "github.com/urfave/cli/v2" diff --git a/op-deployer/pkg/deployer/integration_test/apply_test.go b/op-deployer/pkg/deployer/integration_test/apply_test.go index eb900f87bb0..dcb5e10056c 100644 --- a/op-deployer/pkg/deployer/integration_test/apply_test.go +++ b/op-deployer/pkg/deployer/integration_test/apply_test.go @@ -44,7 +44,7 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-devstack/dsl/bridge.go b/op-devstack/dsl/bridge.go index 39cab10ed06..26ae4f0b84f 100644 --- a/op-devstack/dsl/bridge.go +++ b/op-devstack/dsl/bridge.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" nodebindings "github.com/ethereum-optimism/optimism/op-node/bindings" @@ -18,7 +19,6 @@ import ( "github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-service/apis" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txintent/contractio" "github.com/ethereum/go-ethereum/common" diff --git a/op-devstack/dsl/ecotone_fees.go b/op-devstack/dsl/ecotone_fees.go index d1970a94b92..ed0f85a46f1 100644 --- a/op-devstack/dsl/ecotone_fees.go +++ b/op-devstack/dsl/ecotone_fees.go @@ -3,11 +3,11 @@ package dsl import ( "math/big" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-service/apis" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) diff --git a/op-devstack/dsl/fjord_fees.go b/op-devstack/dsl/fjord_fees.go index b27566634c7..739dd11055e 100644 --- a/op-devstack/dsl/fjord_fees.go +++ b/op-devstack/dsl/fjord_fees.go @@ -5,11 +5,11 @@ import ( "fmt" "math/big" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-service/apis" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txintent/contractio" "github.com/ethereum-optimism/optimism/op-service/txplan" diff --git a/op-devstack/dsl/l2_el.go b/op-devstack/dsl/l2_el.go index c4a8be53eab..ef66f6958df 100644 --- a/op-devstack/dsl/l2_el.go +++ b/op-devstack/dsl/l2_el.go @@ -7,11 +7,11 @@ import ( "strings" "time" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/stack" "github.com/ethereum-optimism/optimism/op-devstack/sysgo" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum/go-ethereum/common" diff --git a/op-devstack/dsl/operator_fee.go b/op-devstack/dsl/operator_fee.go index 486d04d28a0..99ee6cff538 100644 --- a/op-devstack/dsl/operator_fee.go +++ b/op-devstack/dsl/operator_fee.go @@ -6,10 +6,10 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" "github.com/ethereum-optimism/optimism/op-service/txintent/contractio" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-e2e/actions/helpers/user.go b/op-e2e/actions/helpers/user.go index 9cd00d83f8f..a863bd07be3 100644 --- a/op-e2e/actions/helpers/user.go +++ b/op-e2e/actions/helpers/user.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + "github.com/ethereum-optimism/optimism/op-core/predeploys" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/config" e2ehelpers "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" @@ -31,7 +32,6 @@ import ( bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/withdrawals" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) type L1Bindings struct { diff --git a/op-e2e/actions/interop/dsl/inbox.go b/op-e2e/actions/interop/dsl/inbox.go index d89574e5d0a..bbd54a08fcc 100644 --- a/op-e2e/actions/interop/dsl/inbox.go +++ b/op-e2e/actions/interop/dsl/inbox.go @@ -8,10 +8,10 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/contracts/bindings/inbox" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" stypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) diff --git a/op-e2e/actions/interop/dsl/message.go b/op-e2e/actions/interop/dsl/message.go index 667376b9406..144e57e446f 100644 --- a/op-e2e/actions/interop/dsl/message.go +++ b/op-e2e/actions/interop/dsl/message.go @@ -1,9 +1,9 @@ package dsl import ( + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/contracts/bindings/inbox" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" ) diff --git a/op-e2e/actions/interop/emitter_contract_test.go b/op-e2e/actions/interop/emitter_contract_test.go index 5b827e93265..c1d98c74961 100644 --- a/op-e2e/actions/interop/emitter_contract_test.go +++ b/op-e2e/actions/interop/emitter_contract_test.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/interop/dsl" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/contracts/bindings/emit" @@ -22,7 +23,6 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/event" - "github.com/ethereum-optimism/optimism/op-service/predeploys" stypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) diff --git a/op-e2e/actions/interop/interop_fork_test.go b/op-e2e/actions/interop/interop_fork_test.go index ca15daa3b80..e2cf0fd513e 100644 --- a/op-e2e/actions/interop/interop_fork_test.go +++ b/op-e2e/actions/interop/interop_fork_test.go @@ -4,12 +4,12 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" actionhelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/interop/dsl" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/op-e2e/actions/proofs/isthmus_fork_test.go b/op-e2e/actions/proofs/isthmus_fork_test.go index f6e426d7f8b..7688989edb0 100644 --- a/op-e2e/actions/proofs/isthmus_fork_test.go +++ b/op-e2e/actions/proofs/isthmus_fork_test.go @@ -12,11 +12,11 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/accounts/abi/bind" diff --git a/op-e2e/actions/proofs/jovian_dafootprint_test.go b/op-e2e/actions/proofs/jovian_dafootprint_test.go index 6bd159a7f93..0171167a269 100644 --- a/op-e2e/actions/proofs/jovian_dafootprint_test.go +++ b/op-e2e/actions/proofs/jovian_dafootprint_test.go @@ -7,11 +7,11 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-e2e/actions/proofs/jovian_minbasefee_test.go b/op-e2e/actions/proofs/jovian_minbasefee_test.go index 151e410ce24..b7e5c7c5a77 100644 --- a/op-e2e/actions/proofs/jovian_minbasefee_test.go +++ b/op-e2e/actions/proofs/jovian_minbasefee_test.go @@ -6,10 +6,10 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" diff --git a/op-e2e/actions/proofs/l1_blob_parameter_forks_test.go b/op-e2e/actions/proofs/l1_blob_parameter_forks_test.go index a1b4685c2ee..db3315fd097 100644 --- a/op-e2e/actions/proofs/l1_blob_parameter_forks_test.go +++ b/op-e2e/actions/proofs/l1_blob_parameter_forks_test.go @@ -6,11 +6,11 @@ import ( batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/predeploys" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/op-e2e/actions/proofs/operator_fee_fix_transition_test.go b/op-e2e/actions/proofs/operator_fee_fix_transition_test.go index a593797ddf9..7652428c3f9 100644 --- a/op-e2e/actions/proofs/operator_fee_fix_transition_test.go +++ b/op-e2e/actions/proofs/operator_fee_fix_transition_test.go @@ -6,11 +6,11 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-e2e/actions/proofs/operator_fee_test.go b/op-e2e/actions/proofs/operator_fee_test.go index b024be821a9..6b431b2a0ec 100644 --- a/op-e2e/actions/proofs/operator_fee_test.go +++ b/op-e2e/actions/proofs/operator_fee_test.go @@ -5,12 +5,12 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/predeploys" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" diff --git a/op-e2e/actions/proofs/pectra_blob_schedule_test.go b/op-e2e/actions/proofs/pectra_blob_schedule_test.go index 71b9bba7b10..6511fcd3e72 100644 --- a/op-e2e/actions/proofs/pectra_blob_schedule_test.go +++ b/op-e2e/actions/proofs/pectra_blob_schedule_test.go @@ -4,11 +4,11 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/predeploys" actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/accounts/abi/bind" diff --git a/op-e2e/actions/upgrades/ecotone_fork_test.go b/op-e2e/actions/upgrades/ecotone_fork_test.go index 9a326d0a427..cb267dc4699 100644 --- a/op-e2e/actions/upgrades/ecotone_fork_test.go +++ b/op-e2e/actions/upgrades/ecotone_fork_test.go @@ -17,10 +17,10 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" ) diff --git a/op-e2e/actions/upgrades/fjord_fork_test.go b/op-e2e/actions/upgrades/fjord_fork_test.go index e7a4a8af8aa..2880dfb006b 100644 --- a/op-e2e/actions/upgrades/fjord_fork_test.go +++ b/op-e2e/actions/upgrades/fjord_fork_test.go @@ -6,8 +6,8 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-e2e/e2eutils/addresses.go b/op-e2e/e2eutils/addresses.go index 46e639425a2..6e5bc5d419c 100644 --- a/op-e2e/e2eutils/addresses.go +++ b/op-e2e/e2eutils/addresses.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" ) func collectAllocAddrs(alloc types.GenesisAlloc) []common.Address { diff --git a/op-e2e/e2eutils/setup_test.go b/op-e2e/e2eutils/setup_test.go index 9baf0be78c7..8eb2ed1b560 100644 --- a/op-e2e/e2eutils/setup_test.go +++ b/op-e2e/e2eutils/setup_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/config" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) func TestWriteDefaultJWT(t *testing.T) { diff --git a/op-e2e/faultproofs/cannon_benchmark_test.go b/op-e2e/faultproofs/cannon_benchmark_test.go index 2d4b52e38a3..b26aef1ae28 100644 --- a/op-e2e/faultproofs/cannon_benchmark_test.go +++ b/op-e2e/faultproofs/cannon_benchmark_test.go @@ -26,9 +26,9 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" ) diff --git a/op-e2e/interop/supersystem.go b/op-e2e/interop/supersystem.go index 1c5ac711243..7d134fb13b0 100644 --- a/op-e2e/interop/supersystem.go +++ b/op-e2e/interop/supersystem.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/blobstore" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/contracts/bindings/emit" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/contracts/bindings/inbox" @@ -42,7 +43,6 @@ import ( oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum-optimism/optimism/op-service/oppprof" - "github.com/ethereum-optimism/optimism/op-service/predeploys" oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" diff --git a/op-e2e/opgeth/fastlz_test.go b/op-e2e/opgeth/fastlz_test.go index 5b03ca38eca..55ac91cd768 100644 --- a/op-e2e/opgeth/fastlz_test.go +++ b/op-e2e/opgeth/fastlz_test.go @@ -11,10 +11,10 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/fastlz" "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" diff --git a/op-e2e/system/bridge/bridge_test.go b/op-e2e/system/bridge/bridge_test.go index 655cf612c9a..f157870c158 100644 --- a/op-e2e/system/bridge/bridge_test.go +++ b/op-e2e/system/bridge/bridge_test.go @@ -10,12 +10,12 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/receipts" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-e2e/system/bridge/validity_test.go b/op-e2e/system/bridge/validity_test.go index bb10aba541e..3e3785d9678 100644 --- a/op-e2e/system/bridge/validity_test.go +++ b/op-e2e/system/bridge/validity_test.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + "github.com/ethereum-optimism/optimism/op-core/predeploys" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/config/secrets" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" @@ -25,7 +26,6 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/bindings" bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testutils/fuzzerutils" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" diff --git a/op-e2e/system/e2esys/setup.go b/op-e2e/system/e2esys/setup.go index a79bb9b5384..3b214799e5d 100644 --- a/op-e2e/system/e2esys/setup.go +++ b/op-e2e/system/e2esys/setup.go @@ -45,6 +45,7 @@ import ( batcherCfg "github.com/ethereum-optimism/optimism/op-batcher/config" batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-core/predeploys" shared "github.com/ethereum-optimism/optimism/op-devstack/shared/challenger" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/config/secrets" @@ -74,7 +75,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/endpoint" "github.com/ethereum-optimism/optimism/op-service/eth" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/predeploys" oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" opsigner "github.com/ethereum-optimism/optimism/op-service/signer" "github.com/ethereum-optimism/optimism/op-service/sources" diff --git a/op-e2e/system/fees/fees_test.go b/op-e2e/system/fees/fees_test.go index c3a243fe48b..9c2dec22c2e 100644 --- a/op-e2e/system/fees/fees_test.go +++ b/op-e2e/system/fees/fees_test.go @@ -7,11 +7,11 @@ import ( op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/op-e2e/system/fees/gaspriceoracle_test.go b/op-e2e/system/fees/gaspriceoracle_test.go index 22ad06bb613..479f5d930bf 100644 --- a/op-e2e/system/fees/gaspriceoracle_test.go +++ b/op-e2e/system/fees/gaspriceoracle_test.go @@ -8,12 +8,12 @@ import ( op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-core/predeploys" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/stretchr/testify/require" ) diff --git a/op-e2e/system/helpers/withdrawal_helper.go b/op-e2e/system/helpers/withdrawal_helper.go index 787495e4aa5..c7edbbfea20 100644 --- a/op-e2e/system/helpers/withdrawal_helper.go +++ b/op-e2e/system/helpers/withdrawal_helper.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" @@ -22,7 +23,6 @@ import ( "github.com/ethereum-optimism/optimism/op-node/bindings" bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" "github.com/ethereum-optimism/optimism/op-node/withdrawals" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" diff --git a/op-node/rollup/attributes/engine_consolidate_test.go b/op-node/rollup/attributes/engine_consolidate_test.go index 4094758c28f..47086c518e8 100644 --- a/op-node/rollup/attributes/engine_consolidate_test.go +++ b/op-node/rollup/attributes/engine_consolidate_test.go @@ -14,9 +14,9 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" ) diff --git a/op-node/rollup/derive/attributes.go b/op-node/rollup/derive/attributes.go index 59f6d2dbb2f..55c2c3faf00 100644 --- a/op-node/rollup/derive/attributes.go +++ b/op-node/rollup/derive/attributes.go @@ -9,9 +9,9 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) type DependencySet interface { diff --git a/op-node/rollup/derive/attributes_queue_test.go b/op-node/rollup/derive/attributes_queue_test.go index 2f63983ab73..7e712022137 100644 --- a/op-node/rollup/derive/attributes_queue_test.go +++ b/op-node/rollup/derive/attributes_queue_test.go @@ -12,9 +12,9 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" ) diff --git a/op-node/rollup/derive/attributes_test.go b/op-node/rollup/derive/attributes_test.go index 744caec0313..bb76436f550 100644 --- a/op-node/rollup/derive/attributes_test.go +++ b/op-node/rollup/derive/attributes_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/depset" "github.com/ethereum/go-ethereum/common" diff --git a/op-node/rollup/derive/ecotone_upgrade_transactions.go b/op-node/rollup/derive/ecotone_upgrade_transactions.go index e2fed646dc8..9073c6affbc 100644 --- a/op-node/rollup/derive/ecotone_upgrade_transactions.go +++ b/op-node/rollup/derive/ecotone_upgrade_transactions.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/solabi" ) diff --git a/op-node/rollup/derive/fjord_upgrade_transactions.go b/op-node/rollup/derive/fjord_upgrade_transactions.go index 93f7595dd1d..5dd21b05424 100644 --- a/op-node/rollup/derive/fjord_upgrade_transactions.go +++ b/op-node/rollup/derive/fjord_upgrade_transactions.go @@ -3,7 +3,7 @@ package derive import ( "math/big" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-node/rollup/derive/interop_upgrade_transactions.go b/op-node/rollup/derive/interop_upgrade_transactions.go index e3da85b32c5..bed2a600b88 100644 --- a/op-node/rollup/derive/interop_upgrade_transactions.go +++ b/op-node/rollup/derive/interop_upgrade_transactions.go @@ -3,7 +3,7 @@ package derive import ( "math/big" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-node/rollup/derive/interop_upgrade_transactions_test.go b/op-node/rollup/derive/interop_upgrade_transactions_test.go index 6c17f61331f..84fcc65bc84 100644 --- a/op-node/rollup/derive/interop_upgrade_transactions_test.go +++ b/op-node/rollup/derive/interop_upgrade_transactions_test.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "testing" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) diff --git a/op-node/rollup/derive/isthmus_upgrade_transactions.go b/op-node/rollup/derive/isthmus_upgrade_transactions.go index 25bee50b061..c4b0efadb71 100644 --- a/op-node/rollup/derive/isthmus_upgrade_transactions.go +++ b/op-node/rollup/derive/isthmus_upgrade_transactions.go @@ -3,7 +3,7 @@ package derive import ( "math/big" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-node/rollup/derive/isthmus_upgrade_transactions_test.go b/op-node/rollup/derive/isthmus_upgrade_transactions_test.go index c005d57b161..b51df3d8ace 100644 --- a/op-node/rollup/derive/isthmus_upgrade_transactions_test.go +++ b/op-node/rollup/derive/isthmus_upgrade_transactions_test.go @@ -3,7 +3,7 @@ package derive import ( "testing" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) diff --git a/op-node/rollup/derive/jovian_upgrade_transactions.go b/op-node/rollup/derive/jovian_upgrade_transactions.go index ea773842a91..c7d544851d4 100644 --- a/op-node/rollup/derive/jovian_upgrade_transactions.go +++ b/op-node/rollup/derive/jovian_upgrade_transactions.go @@ -4,7 +4,7 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" diff --git a/op-node/rollup/derive/l1_block_info.go b/op-node/rollup/derive/l1_block_info.go index bac4689ebc6..0577125590f 100644 --- a/op-node/rollup/derive/l1_block_info.go +++ b/op-node/rollup/derive/l1_block_info.go @@ -13,9 +13,9 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/solabi" ) diff --git a/op-node/rollup/sequencing/sequencer_test.go b/op-node/rollup/sequencing/sequencer_test.go index bcdd6cdd790..bf8a88419e6 100644 --- a/op-node/rollup/sequencing/sequencer_test.go +++ b/op-node/rollup/sequencing/sequencer_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/conductor" @@ -21,7 +22,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/clock" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/event" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" ) diff --git a/op-node/withdrawals/utils.go b/op-node/withdrawals/utils.go index 7654b27e2b4..99d662502d4 100644 --- a/op-node/withdrawals/utils.go +++ b/op-node/withdrawals/utils.go @@ -15,11 +15,11 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient/gethclient" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/bindings" bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/depset" ) diff --git a/op-program/client/l2/engine.go b/op-program/client/l2/engine.go index 2d3cea18190..6dc0a5d2f6f 100644 --- a/op-program/client/l2/engine.go +++ b/op-program/client/l2/engine.go @@ -5,12 +5,12 @@ import ( "errors" "fmt" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi" l2Types "github.com/ethereum-optimism/optimism/op-program/client/l2/types" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/op-program/client/l2/engineapi/block_processor.go b/op-program/client/l2/engineapi/block_processor.go index be7178b32ed..edf264868a7 100644 --- a/op-program/client/l2/engineapi/block_processor.go +++ b/op-program/client/l2/engineapi/block_processor.go @@ -5,8 +5,8 @@ import ( "fmt" "math/big" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" diff --git a/op-program/client/l2/oracle.go b/op-program/client/l2/oracle.go index c490b60911b..af5f3249afd 100644 --- a/op-program/client/l2/oracle.go +++ b/op-program/client/l2/oracle.go @@ -8,11 +8,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum-optimism/optimism/op-core/predeploys" preimage "github.com/ethereum-optimism/optimism/op-preimage" l2Types "github.com/ethereum-optimism/optimism/op-program/client/l2/types" "github.com/ethereum-optimism/optimism/op-program/client/mpt" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) // StateOracle defines the high-level API used to retrieve L2 state data pre-images diff --git a/op-service/sources/l2_client.go b/op-service/sources/l2_client.go index f5bc5fb358a..fc826d68a99 100644 --- a/op-service/sources/l2_client.go +++ b/op-service/sources/l2_client.go @@ -9,12 +9,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/apis" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/sources/caching" ) diff --git a/op-service/sources/types.go b/op-service/sources/types.go index efbbe78ed2c..c9d6cdeb178 100644 --- a/op-service/sources/types.go +++ b/op-service/sources/types.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) // Note: these types are used, instead of the geth types, to enable: diff --git a/op-service/txinclude/isthmus_cost_oracle.go b/op-service/txinclude/isthmus_cost_oracle.go index 4083b87328c..a999d5c40e0 100644 --- a/op-service/txinclude/isthmus_cost_oracle.go +++ b/op-service/txinclude/isthmus_cost_oracle.go @@ -7,8 +7,8 @@ import ( "sync/atomic" "time" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/signer" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" diff --git a/op-supervisor/supervisor/backend/processors/log_processor_test.go b/op-supervisor/supervisor/backend/processors/log_processor_test.go index 7d7580a15dd..05b6dbcb945 100644 --- a/op-supervisor/supervisor/backend/processors/log_processor_test.go +++ b/op-supervisor/supervisor/backend/processors/log_processor_test.go @@ -10,8 +10,8 @@ import ( "github.com/ethereum/go-ethereum/common" ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) diff --git a/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go b/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go index 7c328d23f26..2bdb3e3ef16 100644 --- a/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go +++ b/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go @@ -20,8 +20,8 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm/arch" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + "github.com/ethereum-optimism/optimism/op-core/predeploys" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/predeploys" ) // ABI types From 9008d082eaef66ee1bc8fe5a57b42653c5f3de00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Cuesta=20Ca=C3=B1ada?= <38806121+alcueca@users.noreply.github.com> Date: Tue, 4 Nov 2025 22:16:53 +0000 Subject: [PATCH 16/20] Safer Safes audit fixes (no bytecode changes) (#18147) * Typo * Fix natspec notice * `_blockingThreshold` natspec * Bump the safe nonce when cancelling * Accepted trade-off * We allow cancelling transactions from disabled guards. * Fixed `changeOwnershipToFallback` natspec. * Updated version and semver-lock * Typo --- .../snapshots/semver-lock.json | 4 ++-- .../src/safe/LivenessModule2.sol | 16 +++++++++------ .../contracts-bedrock/src/safe/SaferSafes.sol | 4 ++-- .../src/safe/TimelockGuard.sol | 20 ++++++++++++++++--- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 7acb955c6cd..f7dbfcffbe4 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -208,8 +208,8 @@ "sourceCodeHash": "0x7fc4789b082bc8ecd29c4c75a06058f0ff0b72f1c1028a42db6f1c35269c8865" }, "src/safe/SaferSafes.sol:SaferSafes": { - "initCodeHash": "0xb4e7885e5f181e9223ecdbc4cfc8b5887fd2c22359e4c8bb4dee53f7dd193876", - "sourceCodeHash": "0x31f453780466a9d3e498a7981f66c92c3d0b76e1ee80c19e374d9692bcfbd931" + "initCodeHash": "0xea63f8c74f2ce10cc53e460b5f7f5006a06ab5612adc7253885a1ca3df124adb", + "sourceCodeHash": "0x169dc281821d3951fb399deefb0b84021b8172cf32ca03526686421bb6478cb4" }, "src/universal/OptimismMintableERC20.sol:OptimismMintableERC20": { "initCodeHash": "0x3c85eed0d017dca8eda6396aa842ddc12492587b061e8c756a8d32c4610a9658", diff --git a/packages/contracts-bedrock/src/safe/LivenessModule2.sol b/packages/contracts-bedrock/src/safe/LivenessModule2.sol index 290d3f8017f..0651bd3b9b6 100644 --- a/packages/contracts-bedrock/src/safe/LivenessModule2.sol +++ b/packages/contracts-bedrock/src/safe/LivenessModule2.sol @@ -279,12 +279,16 @@ abstract contract LivenessModule2 { _cancelChallenge(callingSafe); } - /// @notice With successful challenge, removes all current owners from enabled safe, - /// appoints fallback as sole owner, and sets its quorum to 1. - /// @dev Note: After ownership transfer, the fallback owner becomes the sole owner - /// and is also still configured as the fallback owner. This means the - /// fallback owner effectively becomes its own fallback owner, maintaining - /// the ability to challenge itself if needed. + /// @notice With successful challenge, removes all current owners from enabled safe, appoints + /// fallback as sole owner, and sets its quorum to 1. + /// @dev After ownership transfer, the fallback owner becomes the sole owner and is also still + /// configured as the fallback owner. If the fallback owner would become unable to sign, + /// it would not be able challenge the safe again. For this reason, it is important that + /// the fallback owner has a way to preserve its own liveness. + /// + /// It is of critical importance that this function never reverts. If it were to do so, + /// the Safe would be permanently bricked. For this reason, the external calls from this + /// function are allowed to fail silently instead of reverting. /// @param _safe The Safe address to transfer ownership of. function changeOwnershipToFallback(Safe _safe) external { // Ensure Safe is configured with this module to prevent unauthorized execution. diff --git a/packages/contracts-bedrock/src/safe/SaferSafes.sol b/packages/contracts-bedrock/src/safe/SaferSafes.sol index 5b57b3a38fc..533e360bd51 100644 --- a/packages/contracts-bedrock/src/safe/SaferSafes.sol +++ b/packages/contracts-bedrock/src/safe/SaferSafes.sol @@ -26,8 +26,8 @@ import { ISemver } from "interfaces/universal/ISemver.sol"; /// compatibility restrictions in the LivenessModule2 and TimelockGuard contracts. contract SaferSafes is LivenessModule2, TimelockGuard, ISemver { /// @notice Semantic version. - /// @custom:semver 1.9.0 - string public constant version = "1.9.0"; + /// @custom:semver 1.9.1 + string public constant version = "1.9.1"; /// @notice Error for when the liveness response period is insufficient. error SaferSafes_InsufficientLivenessResponsePeriod(); diff --git a/packages/contracts-bedrock/src/safe/TimelockGuard.sol b/packages/contracts-bedrock/src/safe/TimelockGuard.sol index 77824e0f9d0..57ef493ddf8 100644 --- a/packages/contracts-bedrock/src/safe/TimelockGuard.sol +++ b/packages/contracts-bedrock/src/safe/TimelockGuard.sol @@ -212,13 +212,15 @@ abstract contract TimelockGuard is BaseGuard { /// @notice Returns the blocking threshold, which is defined as the minimum number of owners /// that must coordinate to block a transaction from being executed by refusing to /// sign. + /// @dev Because `_safe.getOwners()` loops through the owners list, it could run out of gas if + /// there are a lot of owners. /// @param _safe The Safe address to query /// @return The current blocking threshold function _blockingThreshold(Safe _safe) internal view returns (uint256) { return _safe.getOwners().length - _safe.getThreshold() + 1; } - /// @notice Internal helper to get the guard address from a Safe + /// @notice Internal helper to check if TimelockGuard is enabled for a Safe /// @param _safe The Safe address /// @return The current guard address function _isGuardEnabled(Safe _safe) internal view returns (bool) { @@ -233,7 +235,7 @@ abstract contract TimelockGuard is BaseGuard { return _safeStates[_safe][_safeConfigNonces[_safe]]; } - /// @notice Internal helper function which can be overriden in a child contract to check if the + /// @notice Internal helper function which can be overridden in a child contract to check if the /// guard's configuration is valid in the context of other extensions that are enabled /// on the Safe. function _checkCombinedConfig(Safe _safe) internal view virtual; @@ -346,7 +348,8 @@ abstract contract TimelockGuard is BaseGuard { // Limit execution of transactions to owners of the Safe only. // This ensures that an attacker cannot simply collect valid signatures, but must also - // control a private key. + // control a private key. It is accepted as a trade-off that paymasters, relayers or UX + // wrappers cannot execute transactions with the TimelockGuard enabled. if (!callingSafe.isOwner(_msgSender)) { revert TimelockGuard_NotOwner(); } @@ -475,6 +478,9 @@ abstract contract TimelockGuard is BaseGuard { /// 1. Safe disables the guard via GuardManager.setGuard(address(0)). /// 2. Safe calls this clearTimelockGuard() function to remove stored configuration. /// 3. If Safe later re-enables the guard, it must call configureTimelockGuard() again. + /// Warning: Clearing the configuration allows all transactions previously scheduled to be + /// scheduled again, including cancelled transactions. It is strongly recommended to + /// manually increment the Safe's nonce when a scheduled transaction is cancelled. function clearTimelockGuard() external { Safe callingSafe = Safe(payable(msg.sender)); @@ -496,6 +502,11 @@ abstract contract TimelockGuard is BaseGuard { /// existing signature generation tools. Owners can use any method to sign the a /// transaction, including signing with a private key, calling the Safe's approveHash /// function, or EIP1271 contract signatures. + /// The Safe doesn't increase its nonce when a transaction is cancelled in the Timelock. + /// This means that it is possible to add the very same transaction a second time to the + /// safe queue, but it won't be possible to schedule it again in the Timelock. It is + /// recommended that the safe nonce is manually incremented when a scheduled transaction + /// is cancelled. /// @param _safe The Safe address to schedule the transaction for. /// @param _nonce The nonce of the Safe for the transaction being scheduled. /// @param _params The parameters of the transaction being scheduled. @@ -594,6 +605,9 @@ abstract contract TimelockGuard is BaseGuard { /// of checkNSignatures is that owners can use any method to sign the cancellation /// transaction inputs, including signing with a private key, calling the Safe's /// approveHash function, or EIP1271 contract signatures. + /// + /// It is allowed to cancel transactions from a disabled TimelockGuard, as a way of + /// clearing the queue that wouldn't be as blunt as calling `clearTimelockConfiguration`. /// @param _safe The Safe address to cancel the transaction for. /// @param _txHash The hash of the transaction being cancelled. /// @param _nonce The nonce of the Safe for the transaction being cancelled. From d19d7d9a8acad2fb745d80e43bbb5d419220c9fc Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 5 Nov 2025 09:19:10 +1000 Subject: [PATCH 17/20] op-acceptance: Add acceptance test for playing out dispute games (#18085) * op-acceptance: Add acceptance test for playing out dispute games. * op-acceptance: Wait for step to be called by honest challenger. * dsl: Make asChallengerClaim private * dsl: Support posting the root claim of the bottom game. * Don't need to use permissioned proposals. * Cache honest trace accessors. * Review feedback --- .../tests/interop/proofs/proposer_test.go | 2 +- .../tests/isthmus/preinterop/proposer_test.go | 2 +- .../tests/proofs/cannon/init_test.go | 18 ++ .../tests/proofs/cannon/step_test.go | 28 +++ op-devstack/dsl/proofs/claim.go | 49 ++++- .../dsl/proofs/dispute_game_factory.go | 182 ++++++++++++++--- op-devstack/dsl/proofs/fault_dispute_game.go | 72 +++++-- op-devstack/dsl/proofs/game_helper.go | 183 ++++++++++++++++-- .../dsl/proofs/super_fault_dispute_game.go | 12 +- op-devstack/presets/interop.go | 2 +- op-devstack/presets/minimal.go | 34 ++-- op-devstack/shim/l2_challenger.go | 16 +- op-devstack/stack/l2_challenger.go | 2 + op-devstack/sysgo/l2_challenger.go | 3 + op-service/eth/block_info.go | 7 +- op-service/testutils/l1info.go | 4 + .../txintent/bindings/FaultDisputeGame.go | 17 +- 17 files changed, 544 insertions(+), 89 deletions(-) create mode 100644 op-acceptance-tests/tests/proofs/cannon/init_test.go create mode 100644 op-acceptance-tests/tests/proofs/cannon/step_test.go diff --git a/op-acceptance-tests/tests/interop/proofs/proposer_test.go b/op-acceptance-tests/tests/interop/proofs/proposer_test.go index da20c56ad97..444720542a1 100644 --- a/op-acceptance-tests/tests/interop/proofs/proposer_test.go +++ b/op-acceptance-tests/tests/interop/proofs/proposer_test.go @@ -17,6 +17,6 @@ func TestProposer(gt *testing.T) { rootClaim := newGame.RootClaim().Value() l2SequenceNumber := newGame.L2SequenceNumber() - superRoot := sys.Supervisor.FetchSuperRootAtTimestamp(l2SequenceNumber.Uint64()) + superRoot := sys.Supervisor.FetchSuperRootAtTimestamp(l2SequenceNumber) t.Require().Equal(superRoot.SuperRoot[:], rootClaim[:]) } diff --git a/op-acceptance-tests/tests/isthmus/preinterop/proposer_test.go b/op-acceptance-tests/tests/isthmus/preinterop/proposer_test.go index e5e8a884565..3e0aea06e2d 100644 --- a/op-acceptance-tests/tests/isthmus/preinterop/proposer_test.go +++ b/op-acceptance-tests/tests/isthmus/preinterop/proposer_test.go @@ -18,6 +18,6 @@ func TestProposer(gt *testing.T) { rootClaim := newGame.RootClaim().Value() l2SequenceNumber := newGame.L2SequenceNumber() - superRoot := sys.Supervisor.FetchSuperRootAtTimestamp(l2SequenceNumber.Uint64()) + superRoot := sys.Supervisor.FetchSuperRootAtTimestamp(l2SequenceNumber) t.Require().Equal(superRoot.SuperRoot[:], rootClaim[:]) } diff --git a/op-acceptance-tests/tests/proofs/cannon/init_test.go b/op-acceptance-tests/tests/proofs/cannon/init_test.go new file mode 100644 index 00000000000..d86e75daff9 --- /dev/null +++ b/op-acceptance-tests/tests/proofs/cannon/init_test.go @@ -0,0 +1,18 @@ +package cannon + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-devstack/compat" + "github.com/ethereum-optimism/optimism/op-devstack/presets" +) + +func TestMain(m *testing.M) { + presets.DoMain(m, + presets.WithProofs(), + presets.WithJovianAtGenesis(), + presets.WithSafeDBEnabled(), + // Requires access to a challenger config which only sysgo provides + // These tests would also be exceptionally slow on real L1s + presets.WithCompatibleTypes(compat.SysGo)) +} diff --git a/op-acceptance-tests/tests/proofs/cannon/step_test.go b/op-acceptance-tests/tests/proofs/cannon/step_test.go new file mode 100644 index 00000000000..2c97e14f428 --- /dev/null +++ b/op-acceptance-tests/tests/proofs/cannon/step_test.go @@ -0,0 +1,28 @@ +package cannon + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-devstack/devtest" + "github.com/ethereum-optimism/optimism/op-devstack/dsl/proofs" + "github.com/ethereum-optimism/optimism/op-devstack/presets" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +func TestExecuteStep(gt *testing.T) { + t := devtest.ParallelT(gt) + sys := presets.NewMinimal(t) + + l1User := sys.FunderL1.NewFundedEOA(eth.ThousandEther) + blockNum := uint64(3) + sys.L2CL.Reached(types.LocalSafe, blockNum, 30) + + game := sys.DisputeGameFactory().StartCannonGame(l1User, proofs.WithL2SequenceNumber(blockNum)) + claim := game.DisputeL2SequenceNumber(l1User, game.RootClaim(), blockNum) + game.LogGameData() + claim = claim.WaitForCounterClaim() // Wait for the honest challenger to counter + claim = game.DisputeToStep(l1User, claim, 1000) // Skip down to max depth + game.LogGameData() + claim.WaitForCountered() +} diff --git a/op-devstack/dsl/proofs/claim.go b/op-devstack/dsl/proofs/claim.go index 51051224e89..3842d750682 100644 --- a/op-devstack/dsl/proofs/claim.go +++ b/op-devstack/dsl/proofs/claim.go @@ -1,10 +1,14 @@ package proofs import ( + "context" "fmt" + "math/big" "slices" "time" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -43,12 +47,35 @@ func (c *Claim) Value() common.Hash { return c.claim.Value } +func (c *Claim) Bond() *big.Int { + return c.claim.Bond +} + +func (c *Claim) Position() types.Position { + return c.claim.Position +} + func (c *Claim) Claimant() common.Address { return c.claim.Claimant } -func (c *Claim) Depth() uint64 { - return uint64(c.claim.Depth()) +func (c *Claim) Depth() types.Depth { + return c.claim.Depth() +} + +func (c *Claim) asChallengerClaim() types.Claim { + return types.Claim{ + ClaimData: types.ClaimData{ + Value: c.claim.Value, + Bond: c.claim.Bond, + Position: c.claim.Position, + }, + CounteredBy: c.claim.CounteredBy, + Claimant: c.claim.Claimant, + Clock: c.claim.Clock, + ContractIndex: int(c.Index), + ParentContractIndex: int(c.claim.ParentContractIndex), + } } // WaitForCounterClaim waits for the claim to be countered by another claim being posted. @@ -60,6 +87,19 @@ func (c *Claim) WaitForCounterClaim(ignoreClaims ...*Claim) *Claim { return newClaim(c.t, c.require, counterIdx, counterClaim, c.game) } +// WaitForCountered waits until the claim is countered either by a child claim or by a step call. +func (c *Claim) WaitForCountered() { + timedCtx, cancel := context.WithTimeout(c.t.Ctx(), defaultTimeout) + defer cancel() + err := wait.For(timedCtx, time.Second, func() (bool, error) { + claim := c.game.claimAtIndex(c.Index) + return claim.CounteredBy != common.Address{}, nil + }) + if err != nil { // Avoid waiting time capturing game data when there's no error + c.require.NoErrorf(err, "Claim %v was not countered\n%v", c.Index, c.game.GameData()) + } +} + func (c *Claim) VerifyNoCounterClaim() { for i, claim := range c.game.allClaims() { c.require.NotEqualValuesf(c.Index, claim.ParentContractIndex, "Found unexpected counter-claim at index %v: %v", i, claim) @@ -71,6 +111,11 @@ func (c *Claim) Attack(eoa *dsl.EOA, newClaim common.Hash) *Claim { return c.WaitForCounterClaim() } +func (c *Claim) Defend(eoa *dsl.EOA, newClaim common.Hash) *Claim { + c.game.Defend(eoa, c.Index, newClaim) + return c.WaitForCounterClaim() +} + func containsClaim(claimIdx uint64, haystack []*Claim) bool { return slices.ContainsFunc(haystack, func(candidate *Claim) bool { return candidate.Index == claimIdx diff --git a/op-devstack/dsl/proofs/dispute_game_factory.go b/op-devstack/dsl/proofs/dispute_game_factory.go index 3dc0166df04..b9ed373f670 100644 --- a/op-devstack/dsl/proofs/dispute_game_factory.go +++ b/op-devstack/dsl/proofs/dispute_game_factory.go @@ -1,11 +1,17 @@ package proofs import ( + "context" "encoding/binary" "math/big" "time" + challengerConfig "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-service/eth" + safetyTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -21,37 +27,58 @@ import ( ) type DisputeGameFactory struct { - t devtest.T - require *require.Assertions - log log.Logger - l1Network *dsl.L1Network - ethClient apis.EthClient - dgf *bindings.DisputeGameFactory - addr common.Address - supervisor *dsl.Supervisor - gameHelper *GameHelper -} - -func NewDisputeGameFactory(t devtest.T, l1Network *dsl.L1Network, ethClient apis.EthClient, dgfAddr common.Address, supervisor *dsl.Supervisor) *DisputeGameFactory { + t devtest.T + require *require.Assertions + log log.Logger + l1Network *dsl.L1Network + ethClient apis.EthClient + dgf *bindings.DisputeGameFactory + addr common.Address + l2CL *dsl.L2CLNode + l2EL *dsl.L2ELNode + supervisor *dsl.Supervisor + gameHelper *GameHelper + challengerCfg *challengerConfig.Config + + honestTraces map[common.Address]challengerTypes.TraceAccessor +} + +func NewDisputeGameFactory( + t devtest.T, + l1Network *dsl.L1Network, + ethClient apis.EthClient, + dgfAddr common.Address, + l2CL *dsl.L2CLNode, + l2EL *dsl.L2ELNode, + supervisor *dsl.Supervisor, + challengerCfg *challengerConfig.Config, +) *DisputeGameFactory { dgf := bindings.NewDisputeGameFactory(bindings.WithClient(ethClient), bindings.WithTo(dgfAddr), bindings.WithTest(t)) return &DisputeGameFactory{ - t: t, - require: require.New(t), - log: t.Logger(), - l1Network: l1Network, - dgf: dgf, - addr: dgfAddr, - supervisor: supervisor, - ethClient: ethClient, + t: t, + require: require.New(t), + log: t.Logger(), + l1Network: l1Network, + dgf: dgf, + addr: dgfAddr, + l2CL: l2CL, + l2EL: l2EL, + supervisor: supervisor, + ethClient: ethClient, + challengerCfg: challengerCfg, + + honestTraces: make(map[common.Address]challengerTypes.TraceAccessor), } } type GameCfg struct { - allowFuture bool - allowUnsafe bool - rootClaimSet bool - rootClaim common.Hash + allowFuture bool + allowUnsafe bool + l2SequenceNumber uint64 + l2SequenceNumberSet bool + rootClaimSet bool + rootClaim common.Hash } type GameOpt interface { Apply(cfg *GameCfg) @@ -81,6 +108,13 @@ func WithRootClaim(claim common.Hash) GameOpt { }) } +func WithL2SequenceNumber(seqNum uint64) GameOpt { + return gameOptFn(func(c *GameCfg) { + c.l2SequenceNumber = seqNum + c.l2SequenceNumberSet = true + }) +} + func NewGameCfg(opts ...GameOpt) *GameCfg { cfg := &GameCfg{} for _, opt := range opts { @@ -97,7 +131,7 @@ func (f *DisputeGameFactory) getGameHelper(eoa *dsl.EOA) *GameHelper { if f.gameHelper != nil { return f.gameHelper } - gs := DeployGameHelper(f.t, eoa) + gs := DeployGameHelper(f.t, eoa, f.honestTraceForGame) f.gameHelper = gs return gs } @@ -109,13 +143,13 @@ func (f *DisputeGameFactory) GameCount() int64 { func (f *DisputeGameFactory) GameAtIndex(idx int64) *FaultDisputeGame { gameInfo := contract.Read(f.dgf.GameAtIndex(big.NewInt(idx))) game := bindings.NewFaultDisputeGame(bindings.WithClient(f.ethClient), bindings.WithTo(gameInfo.Proxy), bindings.WithTest(f.t)) - return NewFaultDisputeGame(f.t, f.require, gameInfo.Proxy, f.getGameHelper, game) + return NewFaultDisputeGame(f.t, f.require, gameInfo.Proxy, f.getGameHelper, f.honestTraceForGame, game) } func (f *DisputeGameFactory) GameImpl(gameType challengerTypes.GameType) *FaultDisputeGame { implAddr := contract.Read(f.dgf.GameImpls(uint32(gameType))) game := bindings.NewFaultDisputeGame(bindings.WithClient(f.ethClient), bindings.WithTo(implAddr), bindings.WithTest(f.t)) - return NewFaultDisputeGame(f.t, f.require, implAddr, f.getGameHelper, game) + return NewFaultDisputeGame(f.t, f.require, implAddr, f.getGameHelper, f.honestTraceForGame, game) } func (f *DisputeGameFactory) GameArgs(gameType challengerTypes.GameType) []byte { @@ -136,13 +170,16 @@ func (f *DisputeGameFactory) WaitForGame() *FaultDisputeGame { func (f *DisputeGameFactory) StartSuperCannonGame(eoa *dsl.EOA, opts ...GameOpt) *SuperFaultDisputeGame { f.require.NotNil(f.supervisor, "supervisor is required to start super games") - proposalTimestamp := f.supervisor.FetchSyncStatus().SafeTimestamp - return f.startSuperCannonGameOfType(eoa, proposalTimestamp, challengerTypes.SuperCannonGameType, opts...) + return f.startSuperCannonGameOfType(eoa, challengerTypes.SuperCannonGameType, opts...) } -func (f *DisputeGameFactory) startSuperCannonGameOfType(eoa *dsl.EOA, timestamp uint64, gameType challengerTypes.GameType, opts ...GameOpt) *SuperFaultDisputeGame { +func (f *DisputeGameFactory) startSuperCannonGameOfType(eoa *dsl.EOA, gameType challengerTypes.GameType, opts ...GameOpt) *SuperFaultDisputeGame { cfg := NewGameCfg(opts...) + timestamp := cfg.l2SequenceNumber + if !cfg.l2SequenceNumberSet { + timestamp = f.supervisor.FetchSyncStatus().SafeTimestamp + } extraData := f.createSuperGameExtraData(timestamp, cfg) rootClaim := cfg.rootClaim if !cfg.rootClaimSet { @@ -165,6 +202,77 @@ func (f *DisputeGameFactory) createSuperGameExtraData(timestamp uint64, cfg *Gam return extraData } +func (f *DisputeGameFactory) StartCannonGame(eoa *dsl.EOA, opts ...GameOpt) *FaultDisputeGame { + return f.startOutputRootGameOfType(eoa, challengerTypes.CannonGameType, f.honestTraceForGame, opts...) +} + +func (f *DisputeGameFactory) honestTraceForGame(game *FaultDisputeGame) challengerTypes.TraceAccessor { + if existing, ok := f.honestTraces[game.Address]; ok { + return existing + } + f.require.Equal(challengerTypes.CannonGameType, game.GameType(), "Honest trace only supported for cannon game types") + f.require.NotNil(f.challengerCfg, "Challenger config is required to create honest trace") + logger := f.t.Logger().New("role", "honestTrace") + prestateBlock := game.StartingL2SequenceNumber() + rollupClient := f.l2CL.Escape().RollupAPI() + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) + l1HeadHash := game.L1Head() + l1Head, err := f.ethClient.BlockRefByHash(f.t.Ctx(), l1HeadHash) + f.require.NoError(err, "Failed to fetch L1 Head") + + l2ElClient := f.l2EL.Escape().L2EthClient() + accessor, err := outputs.NewOutputCannonTraceAccessor( + logger, + metrics.NoopMetrics, + f.challengerCfg.Cannon, + vm.NewOpProgramServerExecutor(logger), + ðClientHeaderProvider{client: l2ElClient}, + prestateProvider, + f.challengerCfg.CannonAbsolutePreState, + rollupClient, + f.t.TempDir(), + l1Head.ID(), + game.SplitDepth(), + prestateBlock, + game.L2SequenceNumber(), + ) + f.require.NoError(err, "Failed to create cannon trace accessor") + f.honestTraces[game.Address] = accessor + return accessor +} + +func (f *DisputeGameFactory) startOutputRootGameOfType( + eoa *dsl.EOA, + gameType challengerTypes.GameType, + honestTraceProvider func(game *FaultDisputeGame) challengerTypes.TraceAccessor, + opts ...GameOpt) *FaultDisputeGame { + cfg := NewGameCfg(opts...) + blockNum := cfg.l2SequenceNumber + if !cfg.l2SequenceNumberSet { + blockNum = f.l2CL.SafeL2BlockRef().Number + } + extraData := f.createOutputGameExtraData(blockNum, cfg) + rootClaim := cfg.rootClaim + if !cfg.rootClaimSet { + // Default to correct root claim + response, err := f.l2CL.Escape().RollupAPI().OutputAtBlock(f.t.Ctx(), blockNum) + f.require.NoErrorf(err, "Failed to get output root at block %v", blockNum) + rootClaim = common.Hash(response.OutputRoot) + } + game, addr := f.createNewGame(eoa, gameType, rootClaim, extraData) + return NewFaultDisputeGame(f.t, f.require, addr, f.getGameHelper, honestTraceProvider, game) +} + +func (f *DisputeGameFactory) createOutputGameExtraData(blockNum uint64, cfg *GameCfg) []byte { + f.require.NotNil(f.l2CL, "L2 CL is required create output games") + if !cfg.allowFuture { + f.l2CL.Reached(safetyTypes.LocalSafe, blockNum, 30) + } + extraData := make([]byte, 32) + binary.BigEndian.PutUint64(extraData[24:], blockNum) + return extraData +} + func (f *DisputeGameFactory) createNewGame(eoa *dsl.EOA, gameType challengerTypes.GameType, claim common.Hash, extraData []byte) (*bindings.FaultDisputeGame, common.Address) { f.log.Info("Creating dispute game", "gameType", gameType, "claim", claim.Hex(), "extradata", common.Bytes2Hex(extraData)) @@ -209,3 +317,17 @@ func (a *GameHelperEOA) PerformMoves(game *FaultDisputeGame, moves ...GameHelper func (a *GameHelperEOA) Address() common.Address { return a.EOA.Address() } + +// ethClientHeaderProvider is an adapter for the L1Client interface used in op-node and devstack to +// the HeaderProvider interface used in challenger +type ethClientHeaderProvider struct { + client apis.EthClient +} + +func (p *ethClientHeaderProvider) HeaderByNumber(ctx context.Context, blockNum *big.Int) (*types.Header, error) { + info, err := p.client.InfoByNumber(ctx, blockNum.Uint64()) + if err != nil { + return nil, err + } + return info.Header(), nil +} diff --git a/op-devstack/dsl/proofs/fault_dispute_game.go b/op-devstack/dsl/proofs/fault_dispute_game.go index aa6bc8a15ae..fcf1d589d97 100644 --- a/op-devstack/dsl/proofs/fault_dispute_game.go +++ b/op-devstack/dsl/proofs/fault_dispute_game.go @@ -24,37 +24,57 @@ import ( type gameHelperProvider func(deployer *dsl.EOA) *GameHelper type FaultDisputeGame struct { - t devtest.T - require *require.Assertions - game *bindings.FaultDisputeGame - Address common.Address - helperProvider gameHelperProvider -} - -func NewFaultDisputeGame(t devtest.T, require *require.Assertions, addr common.Address, helperProvider gameHelperProvider, game *bindings.FaultDisputeGame) *FaultDisputeGame { - return &FaultDisputeGame{ + t devtest.T + require *require.Assertions + game *bindings.FaultDisputeGame + Address common.Address + helperProvider gameHelperProvider + honestTraceProvider func() challengerTypes.TraceAccessor +} + +func NewFaultDisputeGame( + t devtest.T, + require *require.Assertions, + addr common.Address, + helperProvider gameHelperProvider, + honestTrace func(game *FaultDisputeGame) challengerTypes.TraceAccessor, + game *bindings.FaultDisputeGame, +) *FaultDisputeGame { + fdg := &FaultDisputeGame{ t: t, require: require, game: game, Address: addr, helperProvider: helperProvider, } + fdg.honestTraceProvider = func() challengerTypes.TraceAccessor { + return honestTrace(fdg) + } + return fdg +} + +func (g *FaultDisputeGame) GameType() challengerTypes.GameType { + return challengerTypes.GameType(contract.Read(g.game.GameType())) } func (g *FaultDisputeGame) MaxDepth() challengerTypes.Depth { return challengerTypes.Depth(contract.Read(g.game.MaxGameDepth()).Uint64()) } -func (g *FaultDisputeGame) SplitDepth() uint64 { - return contract.Read(g.game.SplitDepth()).Uint64() +func (g *FaultDisputeGame) SplitDepth() challengerTypes.Depth { + return challengerTypes.Depth(contract.Read(g.game.SplitDepth()).Uint64()) } func (g *FaultDisputeGame) RootClaim() *Claim { return g.ClaimAtIndex(0) } -func (g *FaultDisputeGame) L2SequenceNumber() *big.Int { - return contract.Read(g.game.L2SequenceNumber()) +func (g *FaultDisputeGame) L2SequenceNumber() uint64 { + return contract.Read(g.game.L2SequenceNumber()).Uint64() +} + +func (g *FaultDisputeGame) StartingL2SequenceNumber() uint64 { + return contract.Read(g.game.StartingBlockNumber()) } func (g *FaultDisputeGame) ClaimAtIndex(claimIndex uint64) *Claim { @@ -62,6 +82,10 @@ func (g *FaultDisputeGame) ClaimAtIndex(claimIndex uint64) *Claim { return g.newClaim(claimIndex, claim) } +func (g *FaultDisputeGame) L1Head() common.Hash { + return contract.Read(g.game.L1Head()) +} + func (g *FaultDisputeGame) Attack(eoa *dsl.EOA, claimIdx uint64, newClaim common.Hash) { claim := g.claimAtIndex(claimIdx) g.t.Logf("Attacking claim %v (depth: %d) with counter-claim %v", claimIdx, claim.Position.Depth(), newClaim) @@ -74,10 +98,31 @@ func (g *FaultDisputeGame) Attack(eoa *dsl.EOA, claimIdx uint64, newClaim common g.t.Require().Equal(receipt.Status, types.ReceiptStatusSuccessful) } +func (g *FaultDisputeGame) Defend(eoa *dsl.EOA, claimIdx uint64, newClaim common.Hash) { + claim := g.claimAtIndex(claimIdx) + g.t.Logf("Defending claim %v (depth: %d) with counter-claim %v", claimIdx, claim.Position.Depth(), newClaim) + g.require.False(claim.IsRootPosition(), "Cannot defend the root claim") + + requiredBond := g.requiredBond(claim.Position.Defend()) + + defendCall := g.game.Defend(claim.Value, new(big.Int).SetUint64(claimIdx), newClaim) + + receipt := contract.Write(eoa, defendCall, txplan.WithValue(requiredBond), txplan.WithGasRatio(2)) + g.t.Require().Equal(receipt.Status, types.ReceiptStatusSuccessful) +} + func (g *FaultDisputeGame) PerformMoves(eoa *dsl.EOA, moves ...GameHelperMove) []*Claim { return g.helperProvider(eoa).PerformMoves(eoa, g, moves) } +func (g *FaultDisputeGame) DisputeL2SequenceNumber(eoa *dsl.EOA, startClaim *Claim, l2SequenceNumber uint64) *Claim { + return g.helperProvider(eoa).DisputeL2SequenceNumber(eoa, g, startClaim, l2SequenceNumber) +} + +func (g *FaultDisputeGame) DisputeToStep(eoa *dsl.EOA, startClaim *Claim, traceIndex uint64) *Claim { + return g.helperProvider(eoa).DisputeToStep(eoa, g, startClaim, traceIndex) +} + func (g *FaultDisputeGame) requiredBond(pos challengerTypes.Position) eth.ETH { return eth.WeiBig(contract.Read(g.game.GetRequiredBond((*bindings.Uint128)(pos.ToGIndex())))) } @@ -131,7 +176,6 @@ func (g *FaultDisputeGame) waitForClaim(timeout time.Duration, errorMsg string, } return false, nil }) - g.require.NoError(err, errorMsg) if err != nil { // Avoid waiting time capturing game data when there's no error g.require.NoErrorf(err, "%v\n%v", errorMsg, g.GameData()) } diff --git a/op-devstack/dsl/proofs/game_helper.go b/op-devstack/dsl/proofs/game_helper.go index a5075303958..76e60dc2408 100644 --- a/op-devstack/dsl/proofs/game_helper.go +++ b/op-devstack/dsl/proofs/game_helper.go @@ -3,6 +3,7 @@ package proofs import ( "bytes" "encoding/json" + "fmt" "math/big" "os" "path/filepath" @@ -32,13 +33,14 @@ type contractArtifactData struct { } type GameHelper struct { - t devtest.T - require *require.Assertions - contractAddr common.Address - abi abi.ABI + t devtest.T + require *require.Assertions + contractAddr common.Address + abi abi.ABI + honestTraceProvider func(game *FaultDisputeGame) challengerTypes.TraceAccessor } -func DeployGameHelper(t devtest.T, deployer *dsl.EOA) *GameHelper { +func DeployGameHelper(t devtest.T, deployer *dsl.EOA, honestTraceProvider func(game *FaultDisputeGame) challengerTypes.TraceAccessor) *GameHelper { req := require.New(t) artifactData := getGameHelperArtifactData(t) @@ -66,10 +68,11 @@ func DeployGameHelper(t devtest.T, deployer *dsl.EOA) *GameHelper { t.Logf("GameHelper contract deployed at: %s", contractAddr.Hex()) return &GameHelper{ - t: t, - require: require.New(t), - contractAddr: contractAddr, - abi: artifactData.ABI, + t: t, + require: require.New(t), + contractAddr: contractAddr, + abi: artifactData.ABI, + honestTraceProvider: honestTraceProvider, } } @@ -124,10 +127,11 @@ func (gs *GameHelper) AuthEOA(eoa *dsl.EOA) *GameHelper { gs.require.NoError(err) gs.require.Equal(types.ReceiptStatusSuccessful, receipt.Status) return &GameHelper{ - t: gs.t, - require: require.New(gs.t), - contractAddr: eoa.Address(), - abi: gs.abi, + t: gs.t, + require: require.New(gs.t), + contractAddr: eoa.Address(), + abi: gs.abi, + honestTraceProvider: gs.honestTraceProvider, } } @@ -161,7 +165,134 @@ func (gs *GameHelper) CreateGameWithClaims( return receipt.ContractAddress } +func (gs *GameHelper) DisputeL2SequenceNumber(eoa *dsl.EOA, game *FaultDisputeGame, startClaim *Claim, l2SequenceNumber uint64) *Claim { + splitDepth := game.SplitDepth() + startingSeqNumber := game.StartingL2SequenceNumber() + gs.require.Greater(l2SequenceNumber, startingSeqNumber, "Cannot dispute things at or prior to the starting block") + seqNumAtPosition := func(pos challengerTypes.Position) uint64 { + return pos.TraceIndex(splitDepth).Uint64() + startingSeqNumber + 1 + } + shouldMoveLeftFrom := func(pos challengerTypes.Position) bool { + // Move left when equal to the sequence number so that we disagree with it + return seqNumAtPosition(pos) >= l2SequenceNumber + } + finalClaim, gameState := gs.disputeTo(eoa, game, startClaim, splitDepth, shouldMoveLeftFrom) + + // Check that we landed in the right place + // We can only land on every second sequence number, starting from startingSeqNumber+1 + // And we want to land on the sequence number that's either equal to or one before l2SequenceNumber + // If it's equal to we would attack, if it's the one before we would defend to ensure the bottom + // half of the game is executing l2SequenceNumber. + finalPosition := seqNumAtPosition(finalClaim.Position()) + if l2SequenceNumber%2 == startingSeqNumber%2 { + gs.require.Equal(l2SequenceNumber-1, finalPosition) + // When defending the required status code depends on whether we provided the next trace or not. + disputedClaim, found := gameState.AncestorWithTraceIndex(finalClaim.asChallengerClaim(), finalClaim.Position().MoveRight().TraceIndex(game.MaxDepth())) + gs.require.True(found, "Did not find ancestor at target trace index") + statusCode := byte(0x00) + if disputedClaim.Position.Depth()%2 == splitDepth%2 { + statusCode = byte(0x01) + } + gs.t.Logf("Defend at split depth with status code %v", statusCode) + finalClaim = finalClaim.Defend(eoa, common.Hash{statusCode, 0xba, 0xd0}) + } else { + gs.t.Log("Attack at split depth") + gs.require.Equal(l2SequenceNumber, finalPosition) + // When attacking, the final block must be invalid so always use 0x01 as status code + finalClaim = finalClaim.Attack(eoa, common.Hash{0x01, 0xba, 0xd0}) + } + return finalClaim +} + +func (gs *GameHelper) DisputeToStep(eoa *dsl.EOA, game *FaultDisputeGame, startClaim *Claim, traceIndex uint64) *Claim { + splitDepth := game.SplitDepth() + maxDepth := game.MaxDepth() + if startClaim.Depth() < splitDepth { + gs.require.Greater(startClaim.Depth(), splitDepth, "Start claim must be past the game split depth") + } + traceIndexAtPosition := func(pos challengerTypes.Position) uint64 { + relativeFinalPosition, err := pos.RelativeToAncestorAtDepth(splitDepth + 1) + gs.require.NoError(err, "Failed to calculate relative position") + return relativeFinalPosition.TraceIndex(maxDepth - splitDepth - 1).Uint64() + } + shouldMoveLeftFrom := func(pos challengerTypes.Position) bool { + // Move left when equal to the trace index so that we disagree with it + return traceIndexAtPosition(pos) >= traceIndex + } + finalClaim, _ := gs.disputeTo(eoa, game, startClaim, maxDepth, shouldMoveLeftFrom) + // Check that we landed in the right place + // We can only land on every second sequence number, starting from startingSeqNumber+1 + // And we want to land on the sequence number that's either equal to or one before l2SequenceNumber + // If it's equal to we would attack, if it's the one before we would defend to ensure the bottom + // half of the game is executing l2SequenceNumber. + finalTraceIndex := traceIndexAtPosition(finalClaim.Position()) + if traceIndex%2 == 1 { + gs.require.Equal(traceIndex-1, finalTraceIndex) + } else { + gs.require.Equal(traceIndex, finalTraceIndex) + } + return finalClaim +} + +func (gs *GameHelper) disputeTo(eoa *dsl.EOA, game *FaultDisputeGame, startClaim *Claim, targetDepth challengerTypes.Depth, shouldMoveLeftFrom func(pos challengerTypes.Position) bool) (*Claim, challengerTypes.Game) { + honestTrace := gs.honestTraceProvider(game) + maxDepth := game.MaxDepth() + parentIdx := int64(startClaim.Index) + moves := make([]GameHelperMove, 0, targetDepth) + currentPos := startClaim.Position() + claims := allChallengerClaims(game) + gameState := challengerTypes.NewGameState(claims, maxDepth) + honestRootClaim, err := honestTrace.Get(gs.t.Ctx(), gameState, claims[0], challengerTypes.RootPosition) + gs.require.NoError(err, "Failed to get honest root claim") + agreeWithRoot := claims[0].Value == honestRootClaim + for currentPos.Depth() < targetDepth { + shouldAttack := shouldMoveLeftFrom(currentPos) + nextPos := currentPos.Defend() + if shouldAttack { + nextPos = currentPos.Attack() + } + claimValue := common.Hash{0xba, 0xd0} + gs.t.Logf("Disputing claim %v at depth %v with claim at depth %v", parentIdx, currentPos.Depth(), nextPos.Depth()) + if !shouldMoveLeftFrom(nextPos) || !gameState.AgreeWithClaimLevel(claims[len(claims)-1], agreeWithRoot) { + // Either we needed the honest actor to move right (defend) after this move or we are the honest actor + // so make sure we use an honest claim value. + value, err := honestTrace.Get(gs.t.Ctx(), gameState, startClaim.asChallengerClaim(), nextPos) + gs.require.NoError(err, "Failed to get trace value at position %v", nextPos) + claimValue = value + } + nextMove := Move(parentIdx, claimValue, shouldAttack) + + moves = append(moves, nextMove) + claims = append(claims, challengerTypes.Claim{ + ClaimData: challengerTypes.ClaimData{ + Value: nextMove.Claim, + Bond: big.NewInt(0), + Position: nextPos, + }, + Claimant: eoa.Address(), + Clock: challengerTypes.Clock{}, + ContractIndex: int(parentIdx + 1), + ParentContractIndex: int(parentIdx), + }) + gameState = challengerTypes.NewGameState(claims, maxDepth) + currentPos = nextPos + parentIdx++ + } + addedClaims := gs.PerformMoves(eoa, game, moves) + return addedClaims[len(addedClaims)-1], gameState +} + +func allChallengerClaims(game *FaultDisputeGame) []challengerTypes.Claim { + claims := game.allClaims() + challengerClaims := make([]challengerTypes.Claim, len(claims)) + for i, claim := range claims { + challengerClaims[i] = game.newClaim(uint64(i), claim).asChallengerClaim() + } + return challengerClaims +} + func (gs *GameHelper) PerformMoves(eoa *dsl.EOA, game *FaultDisputeGame, moves []GameHelperMove) []*Claim { + gs.t.Log("Performing moves: \n" + describeMoves(moves)) data, err := gs.abi.Pack("performMoves", game.Address, moves) gs.require.NoError(err) @@ -196,19 +327,39 @@ func (gs *GameHelper) PerformMoves(eoa *dsl.EOA, game *FaultDisputeGame, moves [ return claims } +func describeMoves(moves []GameHelperMove) string { + description := "" + for _, move := range moves { + moveType := "Defend" + if move.Attack { + moveType = "Attack" + } + description += fmt.Sprintf("%s claim %s, value %s\n", moveType, move.ParentIdx, move.Claim) + } + return description +} + func (gs *GameHelper) totalMoveBonds(game *FaultDisputeGame, moves []GameHelperMove) eth.ETH { claimPositions := map[uint64]challengerTypes.Position{ - 0: challengerTypes.RootPosition, + 0: challengerTypes.RootPosition, // The claim at index 0 is always in the root position } + preExistingClaimCount := game.claimCount() totalBond := eth.Ether(0) for i, move := range moves { parentPos := claimPositions[move.ParentIdx.Uint64()] - gs.require.NotEmpty(parentPos, "Move references non-existent parent - may be out of order") + if parentPos == (challengerTypes.Position{}) { + gs.require.LessOrEqual(move.ParentIdx.Uint64(), preExistingClaimCount, "No parent position found - moves may be out of order") + // Handle cases were there are existing claims and we're adding moves that reference them + gs.t.Logf("Loading parent position for existing claim at index %v", move.ParentIdx) + parentClaim := game.ClaimAtIndex(move.ParentIdx.Uint64()) + parentPos = parentClaim.Position() + claimPositions[move.ParentIdx.Uint64()] = parentPos + } childPos := parentPos.Defend() if move.Attack { childPos = parentPos.Attack() } - claimPositions[uint64(i)+1] = childPos + claimPositions[uint64(i)+preExistingClaimCount] = childPos bond := game.requiredBond(childPos) totalBond = totalBond.Add(bond) } diff --git a/op-devstack/dsl/proofs/super_fault_dispute_game.go b/op-devstack/dsl/proofs/super_fault_dispute_game.go index 7e096bd5c06..a680aabcfa5 100644 --- a/op-devstack/dsl/proofs/super_fault_dispute_game.go +++ b/op-devstack/dsl/proofs/super_fault_dispute_game.go @@ -1,6 +1,8 @@ package proofs import ( + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-devstack/dsl/contract" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -13,8 +15,16 @@ type SuperFaultDisputeGame struct { } func NewSuperFaultDisputeGame(t devtest.T, require *require.Assertions, addr common.Address, helperProvider gameHelperProvider, game *bindings.FaultDisputeGame) *SuperFaultDisputeGame { - fdg := NewFaultDisputeGame(t, require, addr, helperProvider, game) + honestTraceProvider := func(_ *FaultDisputeGame) types.TraceAccessor { + require.Fail("Honest trace not supported for super games") + return nil + } + fdg := NewFaultDisputeGame(t, require, addr, helperProvider, honestTraceProvider, game) return &SuperFaultDisputeGame{ FaultDisputeGame: fdg, } } + +func (g *SuperFaultDisputeGame) StartingL2SequenceNumber() uint64 { + return contract.Read(g.game.StartingSequenceNumber()) +} diff --git a/op-devstack/presets/interop.go b/op-devstack/presets/interop.go index c4589ec36d2..88200a2413d 100644 --- a/op-devstack/presets/interop.go +++ b/op-devstack/presets/interop.go @@ -114,7 +114,7 @@ func (s *SimpleInterop) L2Networks() []*dsl.L2Network { } func (s *SimpleInterop) DisputeGameFactory() *proofs.DisputeGameFactory { - return proofs.NewDisputeGameFactory(s.T, s.L1Network, s.L1EL.EthClient(), s.L2ChainA.DisputeGameFactoryProxyAddr(), s.Supervisor) + return proofs.NewDisputeGameFactory(s.T, s.L1Network, s.L1EL.EthClient(), s.L2ChainA.DisputeGameFactoryProxyAddr(), nil, nil, s.Supervisor, nil) } func (s *SingleChainInterop) StandardBridge(l2Chain *dsl.L2Network) *dsl.StandardBridge { diff --git a/op-devstack/presets/minimal.go b/op-devstack/presets/minimal.go index d97d3b1c7ab..8aa7b50cfad 100644 --- a/op-devstack/presets/minimal.go +++ b/op-devstack/presets/minimal.go @@ -1,6 +1,7 @@ package presets import ( + challengerConfig "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-devstack/devtest" @@ -31,6 +32,9 @@ type Minimal struct { FaucetL2 *dsl.Faucet FunderL1 *dsl.Funder FunderL2 *dsl.Funder + + // May be nil if not using sysgo + challengerConfig *challengerConfig.Config } func (m *Minimal) L2Networks() []*dsl.L2Network { @@ -44,7 +48,7 @@ func (m *Minimal) StandardBridge() *dsl.StandardBridge { } func (m *Minimal) DisputeGameFactory() *proofs.DisputeGameFactory { - return proofs.NewDisputeGameFactory(m.T, m.L1Network, m.L1EL.EthClient(), m.L2Chain.DisputeGameFactoryProxyAddr(), nil) + return proofs.NewDisputeGameFactory(m.T, m.L1Network, m.L1EL.EthClient(), m.L2Chain.DisputeGameFactoryProxyAddr(), m.L2CL, m.L2EL, nil, m.challengerConfig) } func WithMinimal() stack.CommonOption { @@ -64,18 +68,24 @@ func minimalFromSystem(t devtest.T, system stack.ExtensibleSystem, orch stack.Or l2 := system.L2Network(match.Assume(t, match.L2ChainA)) sequencerCL := l2.L2CLNode(match.Assume(t, match.WithSequencerActive(t.Ctx()))) sequencerEL := l2.L2ELNode(match.Assume(t, match.EngineFor(sequencerCL))) + var challengerCfg *challengerConfig.Config + if len(l2.L2Challengers()) > 0 { + challengerCfg = l2.L2Challengers()[0].Config() + } + out := &Minimal{ - Log: t.Logger(), - T: t, - ControlPlane: orch.ControlPlane(), - L1Network: dsl.NewL1Network(system.L1Network(match.FirstL1Network)), - L1EL: dsl.NewL1ELNode(l1Net.L1ELNode(match.Assume(t, match.FirstL1EL))), - L2Chain: dsl.NewL2Network(l2, orch.ControlPlane()), - L2Batcher: dsl.NewL2Batcher(l2.L2Batcher(match.Assume(t, match.FirstL2Batcher))), - L2EL: dsl.NewL2ELNode(sequencerEL, orch.ControlPlane()), - L2CL: dsl.NewL2CLNode(sequencerCL, orch.ControlPlane()), - Wallet: dsl.NewRandomHDWallet(t, 30), // Random for test isolation - FaucetL2: dsl.NewFaucet(l2.Faucet(match.Assume(t, match.FirstFaucet))), + Log: t.Logger(), + T: t, + ControlPlane: orch.ControlPlane(), + L1Network: dsl.NewL1Network(system.L1Network(match.FirstL1Network)), + L1EL: dsl.NewL1ELNode(l1Net.L1ELNode(match.Assume(t, match.FirstL1EL))), + L2Chain: dsl.NewL2Network(l2, orch.ControlPlane()), + L2Batcher: dsl.NewL2Batcher(l2.L2Batcher(match.Assume(t, match.FirstL2Batcher))), + L2EL: dsl.NewL2ELNode(sequencerEL, orch.ControlPlane()), + L2CL: dsl.NewL2CLNode(sequencerCL, orch.ControlPlane()), + Wallet: dsl.NewRandomHDWallet(t, 30), // Random for test isolation + FaucetL2: dsl.NewFaucet(l2.Faucet(match.Assume(t, match.FirstFaucet))), + challengerConfig: challengerCfg, } out.FaucetL1 = dsl.NewFaucet(out.L1Network.Escape().Faucet(match.Assume(t, match.FirstFaucet))) out.FunderL1 = dsl.NewFunder(out.Wallet, out.FaucetL1, out.L1EL) diff --git a/op-devstack/shim/l2_challenger.go b/op-devstack/shim/l2_challenger.go index 6eadba5e80a..a5fe76f431a 100644 --- a/op-devstack/shim/l2_challenger.go +++ b/op-devstack/shim/l2_challenger.go @@ -1,15 +1,24 @@ package shim -import "github.com/ethereum-optimism/optimism/op-devstack/stack" +import ( + "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-devstack/stack" +) type L2ChallengerConfig struct { CommonConfig - ID stack.L2ChallengerID + ID stack.L2ChallengerID + Config *config.Config } type rpcL2Challenger struct { commonImpl - id stack.L2ChallengerID + id stack.L2ChallengerID + config *config.Config +} + +func (r *rpcL2Challenger) Config() *config.Config { + return r.config } var _ stack.L2Challenger = (*rpcL2Challenger)(nil) @@ -19,6 +28,7 @@ func NewL2Challenger(cfg L2ChallengerConfig) stack.L2Challenger { return &rpcL2Challenger{ commonImpl: newCommon(cfg.CommonConfig), id: cfg.ID, + config: cfg.Config, } } diff --git a/op-devstack/stack/l2_challenger.go b/op-devstack/stack/l2_challenger.go index 81b394add03..c1caded6848 100644 --- a/op-devstack/stack/l2_challenger.go +++ b/op-devstack/stack/l2_challenger.go @@ -3,6 +3,7 @@ package stack import ( "log/slog" + "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -69,4 +70,5 @@ func (id L2ChallengerID) Match(elems []L2Challenger) []L2Challenger { type L2Challenger interface { Common ID() L2ChallengerID + Config() *config.Config } diff --git a/op-devstack/sysgo/l2_challenger.go b/op-devstack/sysgo/l2_challenger.go index 4a56e1fc194..ae5735644bd 100644 --- a/op-devstack/sysgo/l2_challenger.go +++ b/op-devstack/sysgo/l2_challenger.go @@ -21,12 +21,14 @@ type L2Challenger struct { id stack.L2ChallengerID service cliapp.Lifecycle l2NetIDs []stack.L2NetworkID + config *config.Config } func (p *L2Challenger) hydrate(system stack.ExtensibleSystem) { bFrontend := shim.NewL2Challenger(shim.L2ChallengerConfig{ CommonConfig: shim.NewCommonConfig(system.T()), ID: p.id, + Config: p.config, }) for _, netID := range p.l2NetIDs { @@ -176,6 +178,7 @@ func WithL2ChallengerPostDeploy(orch *Orchestrator, challengerID stack.L2Challen id: challengerID, service: svc, l2NetIDs: l2NetIDs, + config: cfg, } orch.challengers.Set(challengerID, c) } diff --git a/op-service/eth/block_info.go b/op-service/eth/block_info.go index 3d09d8ba535..8d28b38c253 100644 --- a/op-service/eth/block_info.go +++ b/op-service/eth/block_info.go @@ -34,6 +34,7 @@ type BlockInfo interface { // HeaderRLP returns the RLP of the block header as per consensus rules // Returns an error if the header RLP could not be written HeaderRLP() ([]byte, error) + Header() *types.Header } func InfoToL1BlockRef(info BlockInfo) L1BlockRef { @@ -162,7 +163,11 @@ func (h *headerBlockInfo) HeaderRLP() ([]byte, error) { return rlp.EncodeToBytes(h.header) // usage is rare and mostly 1-time-use, no need to cache } -func (h headerBlockInfo) WithdrawalsRoot() *common.Hash { +func (h *headerBlockInfo) Header() *types.Header { + return h.header +} + +func (h *headerBlockInfo) WithdrawalsRoot() *common.Hash { return h.header.WithdrawalsHash } diff --git a/op-service/testutils/l1info.go b/op-service/testutils/l1info.go index d15c9790c61..294b637b08d 100644 --- a/op-service/testutils/l1info.go +++ b/op-service/testutils/l1info.go @@ -36,6 +36,10 @@ type MockBlockInfo struct { InfoWithdrawalsRoot *common.Hash } +func (l *MockBlockInfo) Header() *types.Header { + panic("not implemented") +} + func (l *MockBlockInfo) Hash() common.Hash { return l.InfoHash } diff --git a/op-service/txintent/bindings/FaultDisputeGame.go b/op-service/txintent/bindings/FaultDisputeGame.go index 9a4a01aab55..695e05f6b66 100644 --- a/op-service/txintent/bindings/FaultDisputeGame.go +++ b/op-service/txintent/bindings/FaultDisputeGame.go @@ -45,15 +45,18 @@ type FaultDisputeGame struct { L1Head func() TypedCall[common.Hash] `sol:"l1Head"` L2SequenceNumber func() TypedCall[*big.Int] `sol:"l2SequenceNumber"` Status func() TypedCall[uint8] `sol:"status"` + GameType func() TypedCall[uint32] `sol:"gameType"` // IFaultDisputeGame.sol read methods - ClaimDataLen func() TypedCall[*big.Int] `sol:"claimDataLen"` - ClaimData func(*big.Int) TypedCall[ClaimData] `sol:"claimData"` - GetRequiredBond func(position *Uint128) TypedCall[*big.Int] `sol:"getRequiredBond"` - MaxGameDepth func() TypedCall[*big.Int] `sol:"maxGameDepth"` - SplitDepth func() TypedCall[*big.Int] `sol:"splitDepth"` - SubGame func(parentClaimIndex *big.Int, subGameIndex *big.Int) TypedCall[*big.Int] `sol:"subgame"` - MaxClockDuration func() TypedCall[uint64] `sol:"maxClockDuration"` + ClaimDataLen func() TypedCall[*big.Int] `sol:"claimDataLen"` + ClaimData func(*big.Int) TypedCall[ClaimData] `sol:"claimData"` + GetRequiredBond func(position *Uint128) TypedCall[*big.Int] `sol:"getRequiredBond"` + MaxGameDepth func() TypedCall[*big.Int] `sol:"maxGameDepth"` + SplitDepth func() TypedCall[*big.Int] `sol:"splitDepth"` + SubGame func(parentClaimIndex *big.Int, subGameIndex *big.Int) TypedCall[*big.Int] `sol:"subgame"` + MaxClockDuration func() TypedCall[uint64] `sol:"maxClockDuration"` + StartingBlockNumber func() TypedCall[uint64] `sol:"startingBlockNumber"` + StartingSequenceNumber func() TypedCall[uint64] `sol:"startingSequenceNumber"` // IFaultDisputeGame.sol write methods Move func(targetClaim common.Hash, targetClaimIndex *big.Int, newClaim common.Hash, isAttack bool) TypedCall[any] `sol:"move"` From 78daacda28646a39315f7bdf70e5fe9c0cc7b5f1 Mon Sep 17 00:00:00 2001 From: Stefano Charissis Date: Wed, 5 Nov 2025 13:32:28 +1100 Subject: [PATCH 18/20] fix(op-acceptance-tests): ci; slack token (#18156) --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1f8f13a8d07..9f9fbba750f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3204,6 +3204,7 @@ workflows: no_output_timeout: 90m context: - circleci-repo-readonly-authenticated-github-token + - slack - discord requires: - contracts-bedrock-build From 40554025301e5adde90191adba6ad432e185fa50 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 5 Nov 2025 17:36:56 +0100 Subject: [PATCH 19/20] op-batcher: refactor (#18174) * op-batcher: embed ChannelBuilder and remove redundant code * op-batcher: remove dead code --- op-batcher/batcher/channel.go | 107 +++--------------- op-batcher/batcher/channel_builder.go | 13 --- op-batcher/batcher/channel_manager.go | 12 +- op-batcher/batcher/channel_manager_test.go | 6 +- op-batcher/batcher/channel_test.go | 14 +-- .../batcher/throttler/linear_strategy_test.go | 12 -- .../batcher/throttler/pid_strategy_test.go | 5 - .../throttler/quadratic_strategy_test.go | 12 +- .../batcher/throttler/step_strategy_test.go | 7 -- 9 files changed, 32 insertions(+), 156 deletions(-) diff --git a/op-batcher/batcher/channel.go b/op-batcher/batcher/channel.go index 8270977a68c..b9299d11bf4 100644 --- a/op-batcher/batcher/channel.go +++ b/op-batcher/batcher/channel.go @@ -13,30 +13,26 @@ import ( // channel is a lightweight wrapper around a ChannelBuilder which keeps track of pending // and confirmed transactions for a single channel. type channel struct { + *ChannelBuilder // pending channel builder + log log.Logger metr metrics.Metricer cfg ChannelConfig - // pending channel builder - channelBuilder *ChannelBuilder - // Set of unconfirmed txID -> tx data. For tx resubmission - pendingTransactions map[string]txData - // Set of confirmed txID -> inclusion block. For determining if the channel is timed out - confirmedTransactions map[string]eth.BlockID - - // Inclusion block number of first confirmed TX - minInclusionBlock uint64 - // Inclusion block number of last confirmed TX - maxInclusionBlock uint64 + pendingTransactions map[string]txData // Set of unconfirmed txID -> tx data. For tx resubmission + confirmedTransactions map[string]eth.BlockID // Set of confirmed txID -> inclusion block. For determining if the channel is timed out + + minInclusionBlock uint64 // Inclusion block number of first confirmed TX + maxInclusionBlock uint64 // Inclusion block number of last confirmed TX } func newChannel(log log.Logger, metr metrics.Metricer, cfg ChannelConfig, rollupCfg *rollup.Config, latestL1OriginBlockNum uint64, channelOut derive.ChannelOut) *channel { cb := NewChannelBuilderWithChannelOut(cfg, rollupCfg, latestL1OriginBlockNum, channelOut) return &channel{ + ChannelBuilder: cb, log: log, metr: metr, cfg: cfg, - channelBuilder: cb, pendingTransactions: make(map[string]txData), confirmedTransactions: make(map[string]eth.BlockID), minInclusionBlock: math.MaxUint64, @@ -51,7 +47,7 @@ func (c *channel) TxFailed(id string) { // Rewind to the first frame of the failed tx // -- the frames are ordered, and we want to send them // all again. - c.channelBuilder.RewindFrameCursor(data.Frames()[0]) + c.RewindFrameCursor(data.Frames()[0]) delete(c.pendingTransactions, id) } else { c.log.Warn("unknown transaction marked as failed", "id", id) @@ -73,7 +69,7 @@ func (c *channel) TxConfirmed(id string, inclusionBlock eth.BlockID) bool { } delete(c.pendingTransactions, id) c.confirmedTransactions[id] = inclusionBlock - c.channelBuilder.FramePublished(inclusionBlock.Number) + c.FramePublished(inclusionBlock.Number) // Update min/max inclusion blocks for timeout check c.minInclusionBlock = min(c.minInclusionBlock, inclusionBlock.Number) @@ -95,11 +91,6 @@ func (c *channel) TxConfirmed(id string, inclusionBlock eth.BlockID) bool { return false } -// Timeout returns the channel timeout L1 block number. If there is no timeout set, it returns 0. -func (c *channel) Timeout() uint64 { - return c.channelBuilder.Timeout() -} - // isTimedOut returns true if submitted channel has timed out. // A channel has timed out if the difference in L1 Inclusion blocks between // the first & last included block is greater than or equal to the channel timeout. @@ -115,14 +106,10 @@ func (c *channel) isFullySubmitted() bool { return c.IsFull() && len(c.pendingTransactions)+c.PendingFrames() == 0 } -func (c *channel) NoneSubmitted() bool { +func (c *channel) noneSubmitted() bool { return len(c.confirmedTransactions) == 0 && len(c.pendingTransactions) == 0 } -func (c *channel) ID() derive.ChannelID { - return c.channelBuilder.ID() -} - // NextTxData dequeues the next frames from the channel and returns them encoded in a tx data packet. // If cfg.UseBlobs is false, it returns txData with a single frame. // If cfg.UseBlobs is true, it will read frames from its channel builder @@ -132,8 +119,8 @@ func (c *channel) ID() derive.ChannelID { func (c *channel) NextTxData() txData { nf := c.cfg.MaxFramesPerTx() txdata := txData{frames: make([]frameData, 0, nf), asBlob: c.cfg.UseBlobs} - for i := 0; i < nf && c.channelBuilder.HasPendingFrame(); i++ { - frame := c.channelBuilder.NextFrame() + for i := 0; i < nf && c.HasPendingFrame(); i++ { + frame := c.NextFrame() txdata.frames = append(txdata.frames, frame) } @@ -147,74 +134,10 @@ func (c *channel) NextTxData() txData { func (c *channel) HasTxData() bool { if c.IsFull() || // If the channel is full, we should start to submit it !c.cfg.UseBlobs { // If using calldata, we only send one frame per tx - return c.channelBuilder.HasPendingFrame() + return c.HasPendingFrame() } // Collect enough frames if channel is not full yet - return c.channelBuilder.PendingFrames() >= int(c.cfg.MaxFramesPerTx()) -} - -func (c *channel) IsFull() bool { - return c.channelBuilder.IsFull() -} - -func (c *channel) FullErr() error { - return c.channelBuilder.FullErr() -} - -func (c *channel) CheckTimeout(l1BlockNum uint64) { - c.channelBuilder.CheckTimeout(l1BlockNum) -} - -func (c *channel) AddBlock(block SizedBlock) (*derive.L1BlockInfo, error) { - return c.channelBuilder.AddBlock(block) -} - -func (c *channel) InputBytes() int { - return c.channelBuilder.InputBytes() -} - -func (c *channel) ReadyBytes() int { - return c.channelBuilder.ReadyBytes() -} - -func (c *channel) OutputBytes() int { - return c.channelBuilder.OutputBytes() -} - -func (c *channel) TotalFrames() int { - return c.channelBuilder.TotalFrames() -} - -func (c *channel) PendingFrames() int { - return c.channelBuilder.PendingFrames() -} - -func (c *channel) OutputFrames() error { - return c.channelBuilder.OutputFrames() -} - -// LatestL1Origin returns the latest L1 block origin from all the L2 blocks that have been added to the channel -func (c *channel) LatestL1Origin() eth.BlockID { - return c.channelBuilder.LatestL1Origin() -} - -// OldestL1Origin returns the oldest L1 block origin from all the L2 blocks that have been added to the channel -func (c *channel) OldestL1Origin() eth.BlockID { - return c.channelBuilder.OldestL1Origin() -} - -// LatestL2 returns the latest L2 block from all the L2 blocks that have been added to the channel -func (c *channel) LatestL2() eth.BlockID { - return c.channelBuilder.LatestL2() -} - -// OldestL2 returns the oldest L2 block from all the L2 blocks that have been added to the channel -func (c *channel) OldestL2() eth.BlockID { - return c.channelBuilder.OldestL2() -} - -func (c *channel) Close() { - c.channelBuilder.Close() + return c.PendingFrames() >= int(c.cfg.MaxFramesPerTx()) } func (c *channel) MaxInclusionBlock() uint64 { diff --git a/op-batcher/batcher/channel_builder.go b/op-batcher/batcher/channel_builder.go index c9f29283cd9..eab2f203726 100644 --- a/op-batcher/batcher/channel_builder.go +++ b/op-batcher/batcher/channel_builder.go @@ -133,12 +133,6 @@ func (c *ChannelBuilder) OutputBytes() int { return c.outputBytes } -// Blocks returns a backup list of all blocks that were added to the channel. It -// can be used in case the channel needs to be rebuilt. -func (c *ChannelBuilder) Blocks() []SizedBlock { - return c.blocks -} - // LatestL1Origin returns the latest L1 block origin from all the L2 blocks that have been added to the channel func (c *ChannelBuilder) LatestL1Origin() eth.BlockID { return c.latestL1Origin @@ -213,13 +207,6 @@ func (c *ChannelBuilder) AddBlock(block SizedBlock) (*derive.L1BlockInfo, error) return l1info, nil } -// Timeout management - -// Timeout returns the block number of the channel timeout. If no timeout is set it returns 0 -func (c *ChannelBuilder) Timeout() uint64 { - return c.timeout -} - // FramePublished should be called whenever a frame of this channel got // published with the L1-block number of the block that the frame got included // in. diff --git a/op-batcher/batcher/channel_manager.go b/op-batcher/batcher/channel_manager.go index b933de454f2..4e1ca799cc3 100644 --- a/op-batcher/batcher/channel_manager.go +++ b/op-batcher/batcher/channel_manager.go @@ -152,12 +152,12 @@ func (s *channelManager) rewindToBlock(block eth.BlockID) { // and removes the channel from the channelQueue, along with // any channels which are newer than the provided channel. func (s *channelManager) handleChannelInvalidated(c *channel) { - if len(c.channelBuilder.blocks) > 0 { + if len(c.ChannelBuilder.blocks) > 0 { // This is usually true, but there is an edge case // where a channel timed out before any blocks got added. // In that case we end up with an empty frame (header only), // and there are no blocks to requeue. - blockID := eth.ToBlockID(c.channelBuilder.blocks[0]) + blockID := eth.ToBlockID(c.ChannelBuilder.blocks[0]) s.rewindToBlock(blockID) } else { s.log.Debug("channelManager.handleChannelInvalidated: channel had no blocks") @@ -176,7 +176,7 @@ func (s *channelManager) handleChannelInvalidated(c *channel) { for i := invalidatedChannelIdx; i < len(s.channelQueue); i++ { s.log.Warn("Dropped channel", "id", s.channelQueue[i].ID(), - "none_submitted", s.channelQueue[i].NoneSubmitted(), + "none_submitted", s.channelQueue[i].noneSubmitted(), "fully_submitted", s.channelQueue[i].isFullySubmitted(), "timed_out", s.channelQueue[i].isTimedOut(), "full_reason", s.channelQueue[i].FullErr(), @@ -232,7 +232,7 @@ func (s *channelManager) TxData(l1Head eth.BlockID, isPectra, isThrottling, forc } // If the channel has already started being submitted, // return now and ensure no requeuing happens - if !channel.NoneSubmitted() { + if !channel.noneSubmitted() { return s.nextTxData(channel) } @@ -472,7 +472,7 @@ func (s *channelManager) outputFrames() error { "compr_ratio", comprRatio, ) - s.currentChannel.channelBuilder.co.DiscardCompressor() // Free up memory by discarding the compressor + s.currentChannel.ChannelBuilder.co.DiscardCompressor() // Free up memory by discarding the compressor return nil } @@ -586,7 +586,7 @@ func (s *channelManager) unsafeBytesInOpenChannels() int64 { var bytesInOpenChannels int64 for _, channel := range s.channelQueue { if channel.TotalFrames() == 0 { - for _, block := range channel.channelBuilder.blocks { + for _, block := range channel.ChannelBuilder.blocks { bytesInOpenChannels += int64(block.EstimatedDABytes()) } } diff --git a/op-batcher/batcher/channel_manager_test.go b/op-batcher/batcher/channel_manager_test.go index c8bce13262e..2aafe1f315d 100644 --- a/op-batcher/batcher/channel_manager_test.go +++ b/op-batcher/batcher/channel_manager_test.go @@ -153,7 +153,7 @@ func ChannelManager_Clear(t *testing.T, batchType uint) { // Process the blocks // We should have a pending channel with 1 frame require.NoError(m.processBlocks()) - require.NoError(m.currentChannel.channelBuilder.co.Flush()) + require.NoError(m.currentChannel.ChannelBuilder.co.Flush()) require.NoError(m.outputFrames()) _, err := m.nextTxData(m.currentChannel) require.NoError(err) @@ -270,7 +270,7 @@ func TestChannelManager_ChannelCreation(t *testing.T) { require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) require.NotNil(t, m.currentChannel) - require.Equal(t, test.expectedChannelTimeout, m.currentChannel.Timeout()) + require.Equal(t, test.expectedChannelTimeout, m.currentChannel.timeout) }) } } @@ -693,7 +693,7 @@ func TestChannelManager_ChannelOutFactory(t *testing.T) { }) require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) - require.IsType(t, &ChannelOutWrapper{}, m.currentChannel.channelBuilder.co) + require.IsType(t, &ChannelOutWrapper{}, m.currentChannel.ChannelBuilder.co) } // TestChannelManager_TxData seeds the channel manager with blocks and triggers the diff --git a/op-batcher/batcher/channel_test.go b/op-batcher/batcher/channel_test.go index 0e1365eceec..e1674fe8814 100644 --- a/op-batcher/batcher/channel_test.go +++ b/op-batcher/batcher/channel_test.go @@ -113,7 +113,7 @@ func TestChannelManager_NextTxData(t *testing.T) { frameNumber: uint16(0), }, } - channel.channelBuilder.frames = append(channel.channelBuilder.frames, frame) + channel.ChannelBuilder.frames = append(channel.ChannelBuilder.frames, frame) require.Equal(t, 1, channel.PendingFrames()) // Now the nextTxData function should return the frame @@ -142,7 +142,7 @@ func TestChannel_NextTxData_singleFrameTx(t *testing.T) { mockframes := makeMockFrameDatas(chID, n+1) // put multiple frames into channel, but less than target - ch.channelBuilder.frames = mockframes[:n-1] + ch.ChannelBuilder.frames = mockframes[:n-1] requireTxData := func(i int) { require.True(ch.HasTxData(), "expected tx data %d", i) @@ -160,7 +160,7 @@ func TestChannel_NextTxData_singleFrameTx(t *testing.T) { require.False(ch.HasTxData()) // put in last two - ch.channelBuilder.frames = append(ch.channelBuilder.frames, mockframes[n-1:n+1]...) + ch.ChannelBuilder.frames = append(ch.ChannelBuilder.frames, mockframes[n-1:n+1]...) for i := n - 1; i < n+1; i++ { requireTxData(i) } @@ -183,11 +183,11 @@ func TestChannel_NextTxData_multiFrameTx(t *testing.T) { mockframes := makeMockFrameDatas(chID, n+1) // put multiple frames into channel, but less than target - ch.channelBuilder.frames = append(ch.channelBuilder.frames, mockframes[:n-1]...) + ch.ChannelBuilder.frames = append(ch.ChannelBuilder.frames, mockframes[:n-1]...) require.False(ch.HasTxData()) // put in last two - ch.channelBuilder.frames = append(ch.channelBuilder.frames, mockframes[n-1:n+1]...) + ch.ChannelBuilder.frames = append(ch.ChannelBuilder.frames, mockframes[n-1:n+1]...) require.True(ch.HasTxData()) txdata := ch.NextTxData() require.Len(txdata.frames, n) @@ -240,7 +240,7 @@ func TestChannelTxConfirmed(t *testing.T) { frameNumber: uint16(0), }, } - m.currentChannel.channelBuilder.frames = append(m.currentChannel.channelBuilder.frames, frame) + m.currentChannel.ChannelBuilder.frames = append(m.currentChannel.ChannelBuilder.frames, frame) require.Equal(t, 1, m.currentChannel.PendingFrames()) returnedTxData, err := m.nextTxData(m.currentChannel) @@ -292,7 +292,7 @@ func TestChannelTxFailed(t *testing.T) { frameNumber: uint16(0), }, } - m.currentChannel.channelBuilder.frames = append(m.currentChannel.channelBuilder.frames, frame) + m.currentChannel.ChannelBuilder.frames = append(m.currentChannel.ChannelBuilder.frames, frame) require.Equal(t, 1, m.currentChannel.PendingFrames()) returnedTxData, err := m.nextTxData(m.currentChannel) expectedTxData := singleFrameTxData(frame) diff --git a/op-batcher/batcher/throttler/linear_strategy_test.go b/op-batcher/batcher/throttler/linear_strategy_test.go index bcef50f375b..8080d70ee43 100644 --- a/op-batcher/batcher/throttler/linear_strategy_test.go +++ b/op-batcher/batcher/throttler/linear_strategy_test.go @@ -46,61 +46,51 @@ func TestLinearStrategy_Update(t *testing.T) { tests := []struct { name string pendingBytes uint64 - targetBytes uint64 expectedIntensity float64 }{ { name: "zero load", pendingBytes: 0, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "below threshold", pendingBytes: TestLinearThreshold / 2, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "exactly at threshold", pendingBytes: TestLinearThreshold, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "25% above threshold", pendingBytes: TestLinearThreshold + TestLinearThreshold/4, - targetBytes: 0, expectedIntensity: 0.25, }, { name: "50% above threshold", pendingBytes: TestLinearThreshold + TestLinearThreshold/2, - targetBytes: 0, expectedIntensity: 0.50, }, { name: "75% above threshold", pendingBytes: TestLinearThreshold + 3*TestLinearThreshold/4, - targetBytes: 0, expectedIntensity: 0.75, }, { name: "100% above threshold (max)", pendingBytes: TestLinearMaxThreshold, - targetBytes: 0, expectedIntensity: TestIntensityMax, }, { name: "beyond max threshold", pendingBytes: TestLinearMaxThreshold * 2, - targetBytes: 0, expectedIntensity: TestIntensityMax, }, { name: "with target bytes ignored", pendingBytes: TestLinearThreshold + TestLinearThreshold/2, - targetBytes: TestLinearThreshold * 10, // Target bytes should be ignored expectedIntensity: 0.50, }, } @@ -173,12 +163,10 @@ func TestLinearStrategy_Reset(t *testing.T) { func TestLinearStrategy_EdgeCases(t *testing.T) { t.Run("max threshold less than threshold", func(t *testing.T) { - require.Panics(t, func() { // Test when multiplier results in maxThreshold <= threshold NewLinearStrategy(TestLinearThreshold, 0, newTestLogger(t)) }) - }) t.Run("very large multiplier", func(t *testing.T) { diff --git a/op-batcher/batcher/throttler/pid_strategy_test.go b/op-batcher/batcher/throttler/pid_strategy_test.go index 835e9ece029..1bd4050da3c 100644 --- a/op-batcher/batcher/throttler/pid_strategy_test.go +++ b/op-batcher/batcher/throttler/pid_strategy_test.go @@ -299,31 +299,26 @@ func TestPIDStrategy_ErrorCalculation(t *testing.T) { testCases := []struct { name string pendingBytes uint64 - targetBytes uint64 expectError bool }{ { name: "no error at threshold", pendingBytes: TestPIDThreshold, - targetBytes: TestPIDThreshold, expectError: false, }, { name: "error above threshold", pendingBytes: TestPIDThreshold * 2, - targetBytes: TestPIDThreshold, expectError: true, }, { name: "no error below threshold", pendingBytes: TestPIDThreshold / 2, - targetBytes: TestPIDThreshold, expectError: false, }, { name: "error with different target", pendingBytes: TestPIDThreshold * 2, - targetBytes: TestPIDThreshold / 2, expectError: true, }, } diff --git a/op-batcher/batcher/throttler/quadratic_strategy_test.go b/op-batcher/batcher/throttler/quadratic_strategy_test.go index a88c0f0755b..a6b44e1789f 100644 --- a/op-batcher/batcher/throttler/quadratic_strategy_test.go +++ b/op-batcher/batcher/throttler/quadratic_strategy_test.go @@ -46,62 +46,52 @@ func TestQuadraticStrategy_Update(t *testing.T) { tests := []struct { name string pendingBytes uint64 - targetBytes uint64 expectedIntensity float64 }{ { name: "zero load", pendingBytes: 0, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "below threshold", pendingBytes: TestQuadraticThreshold / 2, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "exactly at threshold", pendingBytes: TestQuadraticThreshold, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "25% above threshold", pendingBytes: TestQuadraticThreshold + TestQuadraticThreshold/4, - targetBytes: 0, expectedIntensity: 0.0625, // (0.25)^2 }, { name: "50% above threshold", pendingBytes: TestQuadraticThreshold + TestQuadraticThreshold/2, - targetBytes: 0, expectedIntensity: 0.25, // (0.5)^2 }, { name: "75% above threshold", pendingBytes: TestQuadraticThreshold + 3*TestQuadraticThreshold/4, - targetBytes: 0, expectedIntensity: 0.5625, // (0.75)^2 }, { name: "100% above threshold (max)", pendingBytes: TestQuadraticMaxThreshold, - targetBytes: 0, expectedIntensity: TestIntensityMax, }, { name: "beyond max threshold", pendingBytes: TestQuadraticMaxThreshold * 2, - targetBytes: 0, expectedIntensity: TestIntensityMax, }, { name: "with target bytes ignored", pendingBytes: TestQuadraticThreshold + TestQuadraticThreshold/2, - targetBytes: TestQuadraticThreshold * 10, // Target bytes should be ignored - expectedIntensity: 0.25, // (0.5)^2 + expectedIntensity: 0.25, // (0.5)^2 }, } diff --git a/op-batcher/batcher/throttler/step_strategy_test.go b/op-batcher/batcher/throttler/step_strategy_test.go index a4e668ee094..7c7f2d7d731 100644 --- a/op-batcher/batcher/throttler/step_strategy_test.go +++ b/op-batcher/batcher/throttler/step_strategy_test.go @@ -38,43 +38,36 @@ func TestStepStrategy_Update(t *testing.T) { tests := []struct { name string pendingBytes uint64 - targetBytes uint64 expectedIntensity float64 }{ { name: "zero load", pendingBytes: 0, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "below threshold", pendingBytes: TestStepThreshold / 2, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "exactly at threshold", pendingBytes: TestStepThreshold, - targetBytes: 0, expectedIntensity: TestIntensityMin, }, { name: "just above threshold", pendingBytes: TestStepThreshold + 1, - targetBytes: 0, expectedIntensity: TestIntensityMax, }, { name: "far above threshold", pendingBytes: TestStepThreshold * 10, - targetBytes: 0, expectedIntensity: TestIntensityMax, }, { name: "with target bytes ignored", pendingBytes: TestStepThreshold + 1000, - targetBytes: TestStepThreshold * 2, // Target bytes should be ignored in step strategy expectedIntensity: TestIntensityMax, }, } From c1b38d39498052a2e4ad4616faefa2519451b76f Mon Sep 17 00:00:00 2001 From: Inphi Date: Wed, 5 Nov 2025 11:43:17 -0500 Subject: [PATCH 20/20] op-acceptance-tests: Replace fast games with regular FDGs in withdrawal test (#18152) --- .../tests/base/withdrawal/init_test.go | 10 +------ .../tests/base/withdrawal/withdrawal_test.go | 9 +++++- op-devstack/presets/minimal.go | 12 +++++++- op-devstack/presets/proof.go | 30 ------------------- 4 files changed, 20 insertions(+), 41 deletions(-) diff --git a/op-acceptance-tests/tests/base/withdrawal/init_test.go b/op-acceptance-tests/tests/base/withdrawal/init_test.go index 7154f5445ba..ac5aa8113ef 100644 --- a/op-acceptance-tests/tests/base/withdrawal/init_test.go +++ b/op-acceptance-tests/tests/base/withdrawal/init_test.go @@ -3,7 +3,6 @@ package withdrawal import ( "testing" - faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-devstack/compat" "github.com/ethereum-optimism/optimism/op-devstack/presets" ) @@ -13,14 +12,7 @@ func TestMain(m *testing.M) { // TODO(infra#401): Re-enable the test when the sysext missing toolset is implemented presets.WithCompatibleTypes(compat.SysGo), presets.WithMinimal(), - presets.WithProposerGameType(faultTypes.FastGameType), - // Fast game for test - presets.WithFastGame(), - // Deployer must be L1PAO to make op-deployer happy - presets.WithDeployerMatchL1PAO(), - // Guardian must be L1PAO to make AnchorStateRegistry's setRespectedGameType method work - presets.WithGuardianMatchL1PAO(), - // Fast finalization for fast withdrawal + presets.WithTimeTravel(), presets.WithFinalizationPeriodSeconds(1), // Satisfy OptimismPortal2 PROOF_MATURITY_DELAY_SECONDS check, avoid OptimismPortal_ProofNotOldEnough() revert presets.WithProofMaturityDelaySeconds(2), diff --git a/op-acceptance-tests/tests/base/withdrawal/withdrawal_test.go b/op-acceptance-tests/tests/base/withdrawal/withdrawal_test.go index d2b40beb723..a9e1e7814b3 100644 --- a/op-acceptance-tests/tests/base/withdrawal/withdrawal_test.go +++ b/op-acceptance-tests/tests/base/withdrawal/withdrawal_test.go @@ -15,7 +15,7 @@ func TestWithdrawal(gt *testing.T) { require := sys.T.Require() bridge := sys.StandardBridge() - require.EqualValues(faultTypes.FastGameType, bridge.RespectedGameType(), "Respected game type must be FastGame") + require.EqualValues(faultTypes.PermissionedGameType, bridge.RespectedGameType(), "Respected game type must be PermissionedGameType") initialL1Balance := eth.OneThirdEther @@ -45,6 +45,13 @@ func TestWithdrawal(gt *testing.T) { expectedL1UserBalance = expectedL1UserBalance.Sub(withdrawal.ProveGasCost()) l1User.VerifyBalanceExact(expectedL1UserBalance) + // Advance time until game is resolvable + sys.AdvanceTime(bridge.GameResolutionDelay()) + withdrawal.WaitForDisputeGameResolved() + + // Advance time to when game finalization and proof finalization delay has expired + sys.AdvanceTime(max(bridge.WithdrawalDelay()-bridge.GameResolutionDelay(), bridge.DisputeGameFinalityDelay())) + t.Logger().Info("Attempting to finalize", "proofMaturity", bridge.WithdrawalDelay(), "gameResolutionDelay", bridge.GameResolutionDelay(), "gameFinalityDelay", bridge.DisputeGameFinalityDelay()) withdrawal.Finalize(l1User) expectedL1UserBalance = expectedL1UserBalance.Sub(withdrawal.FinalizeGasCost()).Add(withdrawalAmount) diff --git a/op-devstack/presets/minimal.go b/op-devstack/presets/minimal.go index 8aa7b50cfad..ac44c35e84d 100644 --- a/op-devstack/presets/minimal.go +++ b/op-devstack/presets/minimal.go @@ -1,9 +1,11 @@ package presets import ( - challengerConfig "github.com/ethereum-optimism/optimism/op-challenger/config" + "time" + "github.com/ethereum/go-ethereum/log" + challengerConfig "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" "github.com/ethereum-optimism/optimism/op-devstack/dsl/proofs" @@ -17,6 +19,7 @@ type Minimal struct { Log log.Logger T devtest.T ControlPlane stack.ControlPlane + system stack.ExtensibleSystem L1Network *dsl.L1Network L1EL *dsl.L1ELNode @@ -51,6 +54,12 @@ func (m *Minimal) DisputeGameFactory() *proofs.DisputeGameFactory { return proofs.NewDisputeGameFactory(m.T, m.L1Network, m.L1EL.EthClient(), m.L2Chain.DisputeGameFactoryProxyAddr(), m.L2CL, m.L2EL, nil, m.challengerConfig) } +func (m *Minimal) AdvanceTime(amount time.Duration) { + ttSys, ok := m.system.(stack.TimeTravelSystem) + m.T.Require().True(ok, "attempting to advance time on incompatible system") + ttSys.AdvanceTime(amount) +} + func WithMinimal() stack.CommonOption { return stack.MakeCommon(sysgo.DefaultMinimalSystem(&sysgo.DefaultMinimalSystemIDs{})) } @@ -77,6 +86,7 @@ func minimalFromSystem(t devtest.T, system stack.ExtensibleSystem, orch stack.Or Log: t.Logger(), T: t, ControlPlane: orch.ControlPlane(), + system: system, L1Network: dsl.NewL1Network(system.L1Network(match.FirstL1Network)), L1EL: dsl.NewL1ELNode(l1Net.L1ELNode(match.Assume(t, match.FirstL1EL))), L2Chain: dsl.NewL2Network(l2, orch.ControlPlane()), diff --git a/op-devstack/presets/proof.go b/op-devstack/presets/proof.go index 23202fd1805..fabda7b8a1c 100644 --- a/op-devstack/presets/proof.go +++ b/op-devstack/presets/proof.go @@ -2,11 +2,9 @@ package presets import ( faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" "github.com/ethereum-optimism/optimism/op-devstack/stack" "github.com/ethereum-optimism/optimism/op-devstack/sysgo" ps "github.com/ethereum-optimism/optimism/op-proposer/proposer" - "github.com/ethereum/go-ethereum/common" ) func WithProposerGameType(gameType faultTypes.GameType) stack.CommonOption { @@ -17,34 +15,6 @@ func WithProposerGameType(gameType faultTypes.GameType) stack.CommonOption { }))) } -// TODO(infra#401): Implement support in the sysext toolset -func WithFastGame() stack.CommonOption { - return stack.MakeCommon( - sysgo.WithDeployerOptions( - sysgo.WithAdditionalDisputeGames( - []state.AdditionalDisputeGame{ - { - ChainProofParams: state.ChainProofParams{ - DisputeGameType: uint32(faultTypes.FastGameType), - // Use Alphabet VM prestate which is a pre-determined fixed hash - DisputeAbsolutePrestate: common.HexToHash("0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98"), - DisputeMaxGameDepth: 14 + 3 + 1, - DisputeSplitDepth: 14, - DisputeClockExtension: 0, - DisputeMaxClockDuration: 0, - }, - VMType: state.VMTypeAlphabet, - UseCustomOracle: true, - OracleMinProposalSize: 10000, - OracleChallengePeriodSeconds: 0, - MakeRespected: true, - }, - }, - ), - ), - ) -} - // TODO(infra#401): Implement support in the sysext toolset func WithDeployerMatchL1PAO() stack.CommonOption { return stack.MakeCommon(