From 628045c44e8e9c803a3adc936f217a7d389c927b Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 25 Sep 2025 11:39:52 +0200 Subject: [PATCH 1/3] op-acceptance-tests: move all ext hfs tests to a single pkg --- .../sync_tester_hfs_ext_test.go | 65 +++++++++++++++++++ .../sync_tester_hfs_ext_canyon_test.go | 17 ----- .../sync_tester_hfs_ext_delta_test.go | 17 ----- .../sync_tester_hfs_ext_ecotone_test.go | 17 ----- .../sync_tester_hfs_ext_fjord_test.go | 17 ----- .../sync_tester_hfs_ext_granite_test.go | 17 ----- .../sync_tester_hfs_ext_holocene_test.go | 17 ----- .../sync_tester_hfs_ext_isthmus_test.go | 17 ----- 8 files changed, 65 insertions(+), 119 deletions(-) create mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext/sync_tester_hfs_ext_test.go delete mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_canyon/sync_tester_hfs_ext_canyon_test.go delete mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_delta/sync_tester_hfs_ext_delta_test.go delete mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_ecotone/sync_tester_hfs_ext_ecotone_test.go delete mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_fjord/sync_tester_hfs_ext_fjord_test.go delete mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_granite/sync_tester_hfs_ext_granite_test.go delete mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_holocene/sync_tester_hfs_ext_holocene_test.go delete mode 100644 op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_isthmus/sync_tester_hfs_ext_isthmus_test.go 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 new file mode 100644 index 0000000000000..cd26b577e9547 --- /dev/null +++ b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext/sync_tester_hfs_ext_test.go @@ -0,0 +1,65 @@ +package sync_tester_hfs_ext + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" +) + +func TestSyncTesterHFS_Canyon_CLSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Canyon, sync.CLSync) +} + +func TestSyncTesterHFS_Canyon_ELSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Canyon, sync.ELSync) +} + +func TestSyncTesterHFS_Delta_CLSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Delta, sync.CLSync) +} + +func TestSyncTesterHFS_Delta_ELSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Delta, sync.ELSync) +} + +func TestSyncTesterHFS_Ecotone_CLSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Ecotone, sync.CLSync) +} + +func TestSyncTesterHFS_Ecotone_ELSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Ecotone, sync.ELSync) +} + +func TestSyncTesterHFS_Fjord_CLSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Fjord, sync.CLSync) +} + +func TestSyncTesterHFS_Fjord_ELSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Fjord, sync.ELSync) +} + +func TestSyncTesterHFS_Granite_CLSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Granite, sync.CLSync) +} + +func TestSyncTesterHFS_Granite_ELSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Granite, sync.ELSync) +} + +func TestSyncTesterHFS_Holocene_CLSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Holocene, sync.CLSync) +} + +func TestSyncTesterHFS_Holocene_ELSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Holocene, sync.ELSync) +} + +func TestSyncTesterHFS_Isthmus_CLSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Isthmus, sync.CLSync) +} + +func TestSyncTesterHFS_Isthmus_ELSync(gt *testing.T) { + hardforks_ext.SyncTesterHFSExt(gt, rollup.Isthmus, sync.ELSync) +} diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_canyon/sync_tester_hfs_ext_canyon_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_canyon/sync_tester_hfs_ext_canyon_test.go deleted file mode 100644 index 1c0f30a1ec6b7..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_canyon/sync_tester_hfs_ext_canyon_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sync_tester_hfs_ext_canyon - -import ( - "testing" - - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -) - -func TestSyncTesterHFS_Canyon_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Canyon, sync.CLSync) -} - -func TestSyncTesterHFS_Canyon_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Canyon, sync.ELSync) -} diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_delta/sync_tester_hfs_ext_delta_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_delta/sync_tester_hfs_ext_delta_test.go deleted file mode 100644 index ca5448d85bae0..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_delta/sync_tester_hfs_ext_delta_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sync_tester_hfs_ext_delta - -import ( - "testing" - - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -) - -func TestSyncTesterHFS_Delta_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Delta, sync.CLSync) -} - -func TestSyncTesterHFS_Delta_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Delta, sync.ELSync) -} diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_ecotone/sync_tester_hfs_ext_ecotone_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_ecotone/sync_tester_hfs_ext_ecotone_test.go deleted file mode 100644 index 2eba940053a1e..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_ecotone/sync_tester_hfs_ext_ecotone_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sync_tester_hfs_ext_ecotone - -import ( - "testing" - - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -) - -func TestSyncTesterHFS_Ecotone_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Ecotone, sync.CLSync) -} - -func TestSyncTesterHFS_Ecotone_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Ecotone, sync.ELSync) -} diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_fjord/sync_tester_hfs_ext_fjord_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_fjord/sync_tester_hfs_ext_fjord_test.go deleted file mode 100644 index a9ed1963a4883..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_fjord/sync_tester_hfs_ext_fjord_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sync_tester_hfs_ext_fjord - -import ( - "testing" - - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -) - -func TestSyncTesterHFS_Fjord_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Fjord, sync.CLSync) -} - -func TestSyncTesterHFS_Fjord_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Fjord, sync.ELSync) -} diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_granite/sync_tester_hfs_ext_granite_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_granite/sync_tester_hfs_ext_granite_test.go deleted file mode 100644 index 971ceece0cfb2..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_granite/sync_tester_hfs_ext_granite_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sync_tester_hfs_ext_granite - -import ( - "testing" - - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -) - -func TestSyncTesterHFS_Granite_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Granite, sync.CLSync) -} - -func TestSyncTesterHFS_Granite_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Granite, sync.ELSync) -} diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_holocene/sync_tester_hfs_ext_holocene_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_holocene/sync_tester_hfs_ext_holocene_test.go deleted file mode 100644 index 33fc86e425dfb..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_holocene/sync_tester_hfs_ext_holocene_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sync_tester_hfs_ext_holocene - -import ( - "testing" - - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -) - -func TestSyncTesterHFS_Holocene_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Holocene, sync.CLSync) -} - -func TestSyncTesterHFS_Holocene_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Holocene, sync.ELSync) -} diff --git a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_isthmus/sync_tester_hfs_ext_isthmus_test.go b/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_isthmus/sync_tester_hfs_ext_isthmus_test.go deleted file mode 100644 index 09e2c7f7eed89..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/sync_tester_hfs_ext_isthmus/sync_tester_hfs_ext_isthmus_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sync_tester_hfs_ext_isthmus - -import ( - "testing" - - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -) - -func TestSyncTesterHFS_Isthmus_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Isthmus, sync.CLSync) -} - -func TestSyncTesterHFS_Isthmus_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Isthmus, sync.ELSync) -} From 2c3204509ac43b5243b5c615e89cd1262391c448 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 25 Sep 2025 12:57:49 +0200 Subject: [PATCH 2/3] op-acceptance-tests/hfs-ext: change Serial to Parallel --- .../tests/sync_tester/hardforks_ext/hardforks_ext.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go b/op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go index 9046d9ff324d0..0113b43225ae3 100644 --- a/op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go +++ b/op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go @@ -166,7 +166,7 @@ func setupOrchestrator(gt *testing.T, t devtest.T, blk, targetBlock uint64, l2CL } func SyncTesterHFSExt(gt *testing.T, upgradeName rollup.ForkName, l2CLSyncMode sync.Mode) { - t := devtest.SerialT(gt) + t := devtest.ParallelT(gt) l := t.Logger() // Initial block number to sync from before the upgrade From 463b16cf942a6efafec9d42973ee807a2f2d9b90 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 25 Sep 2025 14:10:56 +0200 Subject: [PATCH 3/3] op-acceptance_tests: consolidate hardforks_ext and sync_tester_hfs_ext --- .../hardforks_ext/hardforks_ext.go | 236 ---------------- .../sync_tester_hfs_ext_test.go | 257 +++++++++++++++++- 2 files changed, 242 insertions(+), 251 deletions(-) delete mode 100644 op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go diff --git a/op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go b/op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go deleted file mode 100644 index 0113b43225ae3..0000000000000 --- a/op-acceptance-tests/tests/sync_tester/hardforks_ext/hardforks_ext.go +++ /dev/null @@ -1,236 +0,0 @@ -package hardforks_ext - -import ( - "context" - "fmt" - "os" - "runtime" - "strconv" - "testing" - - "github.com/ethereum/go-ethereum/log" - - "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/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/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" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" -) - -// Configuration defaults for op-sepolia -const ( - DefaultL2NetworkName = "op-sepolia" - DefaultL1ChainID = 11155111 - DefaultL2ELEndpoint = "https://ci-sepolia-l2.optimism.io" - DefaultL1CLBeaconEndpoint = "https://ci-sepolia-beacon.optimism.io" - DefaultL1ELEndpoint = "https://ci-sepolia-l1.optimism.io" - - // Tailscale networking endpoints - DefaultL2ELEndpointTailscale = "https://proxyd-l2-sepolia.primary.client.dev.oplabs.cloud" - DefaultL1CLBeaconEndpointTailscale = "https://beacon-api-proxy-sepolia.primary.client.dev.oplabs.cloud" - DefaultL1ELEndpointTailscale = "https://proxyd-l1-sepolia.primary.client.dev.oplabs.cloud" -) - -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, - } - - // Load configuration from environment variables with defaults - L2NetworkName = getEnvOrDefault("L2_NETWORK_NAME", DefaultL2NetworkName) - L1ChainID = eth.ChainIDFromUInt64(getEnvUint64OrDefault("L1_CHAIN_ID", DefaultL1ChainID)) - - // Default endpoints - L2ELEndpoint = getEnvOrDefault("L2_EL_ENDPOINT", DefaultL2ELEndpoint) - L1CLBeaconEndpoint = getEnvOrDefault("L1_CL_BEACON_ENDPOINT", DefaultL1CLBeaconEndpoint) - L1ELEndpoint = getEnvOrDefault("L1_EL_ENDPOINT", DefaultL1ELEndpoint) -) - -// getEnvOrDefault returns the environment variable value or the default if not set -func getEnvOrDefault(envVar, defaultValue string) string { - if value := os.Getenv(envVar); value != "" { - return value - } - return defaultValue -} - -// getEnvUint64OrDefault returns the environment variable value as uint64 or the default if not set -func getEnvUint64OrDefault(envVar string, defaultValue uint64) uint64 { - if value := os.Getenv(envVar); value != "" { - if parsed, err := strconv.ParseUint(value, 10, 64); err == nil { - return parsed - } - } - return defaultValue -} - -// setupOrchestrator initializes and configures the orchestrator for the test -func setupOrchestrator(gt *testing.T, t devtest.T, blk, targetBlock uint64, l2CLSyncMode sync.Mode) *sysgo.Orchestrator { - l := t.Logger() - - // Override configuration with Tailscale endpoints if Tailscale networking is enabled - l2ELEndpoint := L2ELEndpoint - l1CLBeaconEndpoint := L1CLBeaconEndpoint - l1ELEndpoint := L1ELEndpoint - - if os.Getenv("TAILSCALE_NETWORKING") == "true" { - l2ELEndpoint = getEnvOrDefault("L2_EL_ENDPOINT_TAILSCALE", DefaultL2ELEndpointTailscale) - l1CLBeaconEndpoint = getEnvOrDefault("L1_CL_BEACON_ENDPOINT_TAILSCALE", DefaultL1CLBeaconEndpointTailscale) - l1ELEndpoint = getEnvOrDefault("L1_EL_ENDPOINT_TAILSCALE", DefaultL1ELEndpointTailscale) - } - - // Setup orchestrator directly without TestMain - logger := testlog.Logger(gt, log.LevelInfo) - onFail := func(now bool) { - if now { - gt.FailNow() - } else { - gt.Fail() - } - } - onSkipNow := func() { - gt.SkipNow() - } - p := devtest.NewP(context.Background(), logger, onFail, onSkipNow) - gt.Cleanup(p.Close) - - // Runtime configuration values - l.Info("Runtime configuration values for TestSyncTesterExtEL") - l.Info("L2_NETWORK_NAME", "value", L2NetworkName) - l.Info("L1_CHAIN_ID", "value", L1ChainID) - l.Info("L2_EL_ENDPOINT", "value", l2ELEndpoint) - l.Info("L1_CL_BEACON_ENDPOINT", "value", l1CLBeaconEndpoint) - l.Info("L1_EL_ENDPOINT", "value", l1ELEndpoint) - l.Info("TAILSCALE_NETWORKING", "value", os.Getenv("TAILSCALE_NETWORKING")) - l.Info("L2_CL_SYNCMODE", "value", l2CLSyncMode) - - config := stack.ExtNetworkConfig{ - L2NetworkName: L2NetworkName, - L1ChainID: L1ChainID, - L2ELEndpoint: L2ELEndpoint, - L1CLBeaconEndpoint: L1CLBeaconEndpoint, - L1ELEndpoint: L1ELEndpoint, - } - - // Create orchestrator with the same configuration that was in TestMain - opt := presets.WithExternalELWithSuperchainRegistry(config) - if l2CLSyncMode == sync.ELSync { - chainCfg := chaincfg.ChainByName(config.L2NetworkName) - if chainCfg == nil { - panic(fmt.Sprintf("network %s not found in superchain registry", config.L2NetworkName)) - } - opt = stack.Combine(opt, - presets.WithExecutionLayerSyncOnVerifiers(), - presets.WithELSyncTarget(targetBlock), - presets.WithSyncTesterELInitialState(eth.FCUState{ - Latest: blk, - Safe: 0, - // Need to set finalized to genesis to unskip EL Sync - Finalized: chainCfg.Genesis.L2.Number, - }), - ) - // TODO(#17564): op-node has a suspected race during EL Sync. - // To temporarily mitigate and stabilize tests, restrict runtime - // parallelism to 1 (no true concurrency). This masks the race; - // remove once the underlying issue is fixed. - runtime.GOMAXPROCS(1) - } else { - opt = stack.Combine(opt, - presets.WithSyncTesterELInitialState(eth.FCUState{ - Latest: blk, - Safe: blk, - Finalized: blk, - }), - ) - } - - var orch stack.Orchestrator = sysgo.NewOrchestrator(p, stack.SystemHook(opt)) - stack.ApplyOptionLifecycle(opt, orch) - - return orch.(*sysgo.Orchestrator) -} - -func SyncTesterHFSExt(gt *testing.T, upgradeName rollup.ForkName, l2CLSyncMode sync.Mode) { - t := devtest.ParallelT(gt) - l := t.Logger() - - // Initial block number to sync from before the upgrade - blk := networkUpgradeBlocks[upgradeName] - 5 - - blocksToSync := uint64(10) - targetBlock := blk + blocksToSync - // Initialize orchestrator - - orch := setupOrchestrator(gt, t, blk, targetBlock, l2CLSyncMode) - system := shim.NewSystem(t) - orch.Hydrate(system) - - l2 := system.L2Network(match.L2ChainA) - verifierCL := l2.L2CLNode(match.FirstL2CL) - syncTester := l2.SyncTester(match.FirstSyncTester) - - sys := &struct { - L2CL *dsl.L2CLNode - L2ELReadOnly *dsl.L2ELNode - L2EL *dsl.L2ELNode - SyncTester *dsl.SyncTester - L2 *dsl.L2Network - }{ - L2CL: dsl.NewL2CLNode(verifierCL, orch.ControlPlane()), - L2ELReadOnly: dsl.NewL2ELNode(l2.L2ELNode(match.FirstL2EL), orch.ControlPlane()), - L2EL: dsl.NewL2ELNode(l2.L2ELNode(match.SecondL2EL), orch.ControlPlane()), - SyncTester: dsl.NewSyncTester(syncTester), - L2: dsl.NewL2Network(l2, orch.ControlPlane()), - } - require := t.Require() - - ft := sys.L2.Escape().RollupConfig().ActivationTimeFor(upgradeName) - var l2CLSyncStatus *eth.SyncStatus - attempts := 1000 - if l2CLSyncMode == sync.ELSync { - // After EL Sync is finished, the FCU state will advance to target immediately so less attempts - attempts = 5 - // Signal L2CL for finishing EL Sync - sys.L2CL.SignalTarget(sys.L2ELReadOnly, targetBlock) - } else { - l2CLSyncStatus := sys.L2CL.WaitForNonZeroUnsafeTime(t.Ctx()) - require.Less(l2CLSyncStatus.UnsafeL2.Time, *ft, "L2CL unsafe time should be less than fork timestamp before upgrade") - } - - sys.L2CL.Reached(types.LocalUnsafe, targetBlock, attempts) - l.Info("L2CL unsafe reached", "targetBlock", targetBlock, "upgrade_name", upgradeName) - sys.L2CL.Reached(types.LocalSafe, targetBlock, attempts) - l.Info("L2CL safe reached", "targetBlock", targetBlock, "upgrade_name", upgradeName) - - l2CLSyncStatus = sys.L2CL.SyncStatus() - require.NotNil(l2CLSyncStatus, "L2CL should have sync status") - require.Greater(l2CLSyncStatus.UnsafeL2.Time, *ft, "L2CL unsafe time should be greater than fork timestamp after upgrade") - - unsafeL2Ref := l2CLSyncStatus.UnsafeL2 - ref := sys.L2EL.BlockRefByNumber(unsafeL2Ref.Number) - require.Equal(unsafeL2Ref.Hash, ref.Hash, "L2EL should be on the same block as L2CL") - - stSessions := sys.SyncTester.ListSessions() - require.Equal(len(stSessions), 1, "expect exactly one session") - - stSession := sys.SyncTester.GetSession(stSessions[0]) - require.GreaterOrEqualf(stSession.CurrentState.Latest, stSession.InitialState.Latest+blocksToSync, "SyncTester session CurrentState.Latest only advanced %d", stSession.CurrentState.Latest-stSession.InitialState.Latest) - require.GreaterOrEqualf(stSession.CurrentState.Safe, stSession.InitialState.Safe+blocksToSync, "SyncTester session CurrentState.Safe only advanced %d", stSession.CurrentState.Safe-stSession.InitialState.Safe) - - l.Info("SyncTester HFS Ext test completed successfully", "l2cl_chain_id", sys.L2CL.ID().ChainID(), "l2cl_sync_status", l2CLSyncStatus, "upgrade_name", upgradeName) -} 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 cd26b577e9547..bc190690ca99d 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 @@ -1,65 +1,292 @@ package sync_tester_hfs_ext import ( + "context" + "fmt" + "os" + "runtime" + "strconv" "testing" - "github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sync_tester/hardforks_ext" + "github.com/ethereum/go-ethereum/log" + + "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/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/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" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +// Configuration defaults for op-sepolia +const ( + DefaultL2NetworkName = "op-sepolia" + DefaultL1ChainID = 11155111 + DefaultL2ELEndpoint = "https://ci-sepolia-l2.optimism.io" + DefaultL1CLBeaconEndpoint = "https://ci-sepolia-beacon.optimism.io" + DefaultL1ELEndpoint = "https://ci-sepolia-l1.optimism.io" + + // Tailscale networking endpoints + DefaultL2ELEndpointTailscale = "https://proxyd-l2-sepolia.primary.client.dev.oplabs.cloud" + DefaultL1CLBeaconEndpointTailscale = "https://beacon-api-proxy-sepolia.primary.client.dev.oplabs.cloud" + DefaultL1ELEndpointTailscale = "https://proxyd-l1-sepolia.primary.client.dev.oplabs.cloud" +) + +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, + } + + // Load configuration from environment variables with defaults + L2NetworkName = getEnvOrDefault("L2_NETWORK_NAME", DefaultL2NetworkName) + L1ChainID = eth.ChainIDFromUInt64(getEnvUint64OrDefault("L1_CHAIN_ID", DefaultL1ChainID)) + + // Default endpoints + L2ELEndpoint = getEnvOrDefault("L2_EL_ENDPOINT", DefaultL2ELEndpoint) + L1CLBeaconEndpoint = getEnvOrDefault("L1_CL_BEACON_ENDPOINT", DefaultL1CLBeaconEndpoint) + L1ELEndpoint = getEnvOrDefault("L1_EL_ENDPOINT", DefaultL1ELEndpoint) ) func TestSyncTesterHFS_Canyon_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Canyon, sync.CLSync) + hfsExt(gt, rollup.Canyon, sync.CLSync) } func TestSyncTesterHFS_Canyon_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Canyon, sync.ELSync) + hfsExt(gt, rollup.Canyon, sync.ELSync) } func TestSyncTesterHFS_Delta_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Delta, sync.CLSync) + hfsExt(gt, rollup.Delta, sync.CLSync) } func TestSyncTesterHFS_Delta_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Delta, sync.ELSync) + hfsExt(gt, rollup.Delta, sync.ELSync) } func TestSyncTesterHFS_Ecotone_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Ecotone, sync.CLSync) + hfsExt(gt, rollup.Ecotone, sync.CLSync) } func TestSyncTesterHFS_Ecotone_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Ecotone, sync.ELSync) + hfsExt(gt, rollup.Ecotone, sync.ELSync) } func TestSyncTesterHFS_Fjord_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Fjord, sync.CLSync) + hfsExt(gt, rollup.Fjord, sync.CLSync) } func TestSyncTesterHFS_Fjord_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Fjord, sync.ELSync) + hfsExt(gt, rollup.Fjord, sync.ELSync) } func TestSyncTesterHFS_Granite_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Granite, sync.CLSync) + hfsExt(gt, rollup.Granite, sync.CLSync) } func TestSyncTesterHFS_Granite_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Granite, sync.ELSync) + hfsExt(gt, rollup.Granite, sync.ELSync) } func TestSyncTesterHFS_Holocene_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Holocene, sync.CLSync) + hfsExt(gt, rollup.Holocene, sync.CLSync) } func TestSyncTesterHFS_Holocene_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Holocene, sync.ELSync) + hfsExt(gt, rollup.Holocene, sync.ELSync) } func TestSyncTesterHFS_Isthmus_CLSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Isthmus, sync.CLSync) + hfsExt(gt, rollup.Isthmus, sync.CLSync) } func TestSyncTesterHFS_Isthmus_ELSync(gt *testing.T) { - hardforks_ext.SyncTesterHFSExt(gt, rollup.Isthmus, sync.ELSync) + hfsExt(gt, rollup.Isthmus, sync.ELSync) +} + +// getEnvOrDefault returns the environment variable value or the default if not set +func getEnvOrDefault(envVar, defaultValue string) string { + if value := os.Getenv(envVar); value != "" { + return value + } + return defaultValue +} + +// getEnvUint64OrDefault returns the environment variable value as uint64 or the default if not set +func getEnvUint64OrDefault(envVar string, defaultValue uint64) uint64 { + if value := os.Getenv(envVar); value != "" { + if parsed, err := strconv.ParseUint(value, 10, 64); err == nil { + return parsed + } + } + return defaultValue +} + +// setupOrchestrator initializes and configures the orchestrator for the test +func setupOrchestrator(gt *testing.T, t devtest.T, blk, targetBlock uint64, l2CLSyncMode sync.Mode) *sysgo.Orchestrator { + l := t.Logger() + + // Override configuration with Tailscale endpoints if Tailscale networking is enabled + l2ELEndpoint := L2ELEndpoint + l1CLBeaconEndpoint := L1CLBeaconEndpoint + l1ELEndpoint := L1ELEndpoint + + if os.Getenv("TAILSCALE_NETWORKING") == "true" { + l2ELEndpoint = getEnvOrDefault("L2_EL_ENDPOINT_TAILSCALE", DefaultL2ELEndpointTailscale) + l1CLBeaconEndpoint = getEnvOrDefault("L1_CL_BEACON_ENDPOINT_TAILSCALE", DefaultL1CLBeaconEndpointTailscale) + l1ELEndpoint = getEnvOrDefault("L1_EL_ENDPOINT_TAILSCALE", DefaultL1ELEndpointTailscale) + } + + // Setup orchestrator directly without TestMain + logger := testlog.Logger(gt, log.LevelInfo) + onFail := func(now bool) { + if now { + gt.FailNow() + } else { + gt.Fail() + } + } + onSkipNow := func() { + gt.SkipNow() + } + p := devtest.NewP(context.Background(), logger, onFail, onSkipNow) + gt.Cleanup(p.Close) + + // Runtime configuration values + l.Info("Runtime configuration values for TestSyncTesterExtEL") + l.Info("L2_NETWORK_NAME", "value", L2NetworkName) + l.Info("L1_CHAIN_ID", "value", L1ChainID) + l.Info("L2_EL_ENDPOINT", "value", l2ELEndpoint) + l.Info("L1_CL_BEACON_ENDPOINT", "value", l1CLBeaconEndpoint) + l.Info("L1_EL_ENDPOINT", "value", l1ELEndpoint) + l.Info("TAILSCALE_NETWORKING", "value", os.Getenv("TAILSCALE_NETWORKING")) + l.Info("L2_CL_SYNCMODE", "value", l2CLSyncMode) + + config := stack.ExtNetworkConfig{ + L2NetworkName: L2NetworkName, + L1ChainID: L1ChainID, + L2ELEndpoint: L2ELEndpoint, + L1CLBeaconEndpoint: L1CLBeaconEndpoint, + L1ELEndpoint: L1ELEndpoint, + } + + // Create orchestrator with the same configuration that was in TestMain + opt := presets.WithExternalELWithSuperchainRegistry(config) + if l2CLSyncMode == sync.ELSync { + chainCfg := chaincfg.ChainByName(config.L2NetworkName) + if chainCfg == nil { + panic(fmt.Sprintf("network %s not found in superchain registry", config.L2NetworkName)) + } + opt = stack.Combine(opt, + presets.WithExecutionLayerSyncOnVerifiers(), + presets.WithELSyncTarget(targetBlock), + presets.WithSyncTesterELInitialState(eth.FCUState{ + Latest: blk, + Safe: 0, + // Need to set finalized to genesis to unskip EL Sync + Finalized: chainCfg.Genesis.L2.Number, + }), + ) + // TODO(#17564): op-node has a suspected race during EL Sync. + // To temporarily mitigate and stabilize tests, restrict runtime + // parallelism to 1 (no true concurrency). This masks the race; + // remove once the underlying issue is fixed. + runtime.GOMAXPROCS(1) + } else { + opt = stack.Combine(opt, + presets.WithSyncTesterELInitialState(eth.FCUState{ + Latest: blk, + Safe: blk, + Finalized: blk, + }), + ) + } + + var orch stack.Orchestrator = sysgo.NewOrchestrator(p, stack.SystemHook(opt)) + stack.ApplyOptionLifecycle(opt, orch) + + return orch.(*sysgo.Orchestrator) +} + +func hfsExt(gt *testing.T, upgradeName rollup.ForkName, l2CLSyncMode sync.Mode) { + t := devtest.ParallelT(gt) + l := t.Logger() + + // Initial block number to sync from before the upgrade + blk := networkUpgradeBlocks[upgradeName] - 5 + + blocksToSync := uint64(10) + targetBlock := blk + blocksToSync + // Initialize orchestrator + + orch := setupOrchestrator(gt, t, blk, targetBlock, l2CLSyncMode) + system := shim.NewSystem(t) + orch.Hydrate(system) + + l2 := system.L2Network(match.L2ChainA) + verifierCL := l2.L2CLNode(match.FirstL2CL) + syncTester := l2.SyncTester(match.FirstSyncTester) + + sys := &struct { + L2CL *dsl.L2CLNode + L2ELReadOnly *dsl.L2ELNode + L2EL *dsl.L2ELNode + SyncTester *dsl.SyncTester + L2 *dsl.L2Network + }{ + L2CL: dsl.NewL2CLNode(verifierCL, orch.ControlPlane()), + L2ELReadOnly: dsl.NewL2ELNode(l2.L2ELNode(match.FirstL2EL), orch.ControlPlane()), + L2EL: dsl.NewL2ELNode(l2.L2ELNode(match.SecondL2EL), orch.ControlPlane()), + SyncTester: dsl.NewSyncTester(syncTester), + L2: dsl.NewL2Network(l2, orch.ControlPlane()), + } + require := t.Require() + + ft := sys.L2.Escape().RollupConfig().ActivationTimeFor(upgradeName) + var l2CLSyncStatus *eth.SyncStatus + attempts := 1000 + if l2CLSyncMode == sync.ELSync { + // After EL Sync is finished, the FCU state will advance to target immediately so less attempts + attempts = 5 + // Signal L2CL for finishing EL Sync + sys.L2CL.SignalTarget(sys.L2ELReadOnly, targetBlock) + } else { + l2CLSyncStatus := sys.L2CL.WaitForNonZeroUnsafeTime(t.Ctx()) + require.Less(l2CLSyncStatus.UnsafeL2.Time, *ft, "L2CL unsafe time should be less than fork timestamp before upgrade") + } + + sys.L2CL.Reached(types.LocalUnsafe, targetBlock, attempts) + l.Info("L2CL unsafe reached", "targetBlock", targetBlock, "upgrade_name", upgradeName) + sys.L2CL.Reached(types.LocalSafe, targetBlock, attempts) + l.Info("L2CL safe reached", "targetBlock", targetBlock, "upgrade_name", upgradeName) + + l2CLSyncStatus = sys.L2CL.SyncStatus() + require.NotNil(l2CLSyncStatus, "L2CL should have sync status") + require.Greater(l2CLSyncStatus.UnsafeL2.Time, *ft, "L2CL unsafe time should be greater than fork timestamp after upgrade") + + unsafeL2Ref := l2CLSyncStatus.UnsafeL2 + ref := sys.L2EL.BlockRefByNumber(unsafeL2Ref.Number) + require.Equal(unsafeL2Ref.Hash, ref.Hash, "L2EL should be on the same block as L2CL") + + stSessions := sys.SyncTester.ListSessions() + require.Equal(len(stSessions), 1, "expect exactly one session") + + stSession := sys.SyncTester.GetSession(stSessions[0]) + require.GreaterOrEqualf(stSession.CurrentState.Latest, stSession.InitialState.Latest+blocksToSync, "SyncTester session CurrentState.Latest only advanced %d", stSession.CurrentState.Latest-stSession.InitialState.Latest) + require.GreaterOrEqualf(stSession.CurrentState.Safe, stSession.InitialState.Safe+blocksToSync, "SyncTester session CurrentState.Safe only advanced %d", stSession.CurrentState.Safe-stSession.InitialState.Safe) + + l.Info("SyncTester HFS Ext test completed successfully", "l2cl_chain_id", sys.L2CL.ID().ChainID(), "l2cl_sync_status", l2CLSyncStatus, "upgrade_name", upgradeName) }