diff --git a/op-acceptance-tests/tests/depreqres/depreqres_test.go b/op-acceptance-tests/tests/depreqres/depreqres_test.go new file mode 100644 index 00000000000..79fa05817e0 --- /dev/null +++ b/op-acceptance-tests/tests/depreqres/depreqres_test.go @@ -0,0 +1,56 @@ +package depreqres + +import ( + "testing" + "time" + + "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-supervisor/supervisor/types" +) + +func TestUnsafeChainStalling_DisabledReqRespSync(gt *testing.T) { + t := devtest.SerialT(gt) + sys := presets.NewSingleChainMultiNode(t) + require := t.Require() + l := t.Logger() + + l.Info("Confirm that the CL nodes are progressing the unsafe chain") + target := uint64(10) + dsl.CheckAll(t, + sys.L2CL.AdvancedFn(types.LocalUnsafe, target, 30), + sys.L2CLB.AdvancedFn(types.LocalUnsafe, target, 30), + ) + + l.Info("Stop the L2 batcher") + sys.L2Batcher.Stop() + + l.Info("Disconnect L2CL from L2CLB, and vice versa") + sys.L2CLB.DisconnectPeer(sys.L2CL) + sys.L2CL.DisconnectPeer(sys.L2CLB) + + ssA_before := sys.L2CL.SyncStatus() + ssB_before := sys.L2CLB.SyncStatus() + + l.Info("L2CL status before delay", "unsafeL2", ssA_before.UnsafeL2.ID(), "safeL2", ssA_before.SafeL2.ID()) + l.Info("L2CLB status before delay", "unsafeL2", ssB_before.UnsafeL2.ID(), "safeL2", ssB_before.SafeL2.ID()) + + time.Sleep(20 * time.Second) + + ssA_after := sys.L2CL.SyncStatus() + ssB_after := sys.L2CLB.SyncStatus() + + l.Info("L2CL status after delay", "unsafeL2", ssA_after.UnsafeL2.ID(), "safeL2", ssA_after.SafeL2.ID()) + l.Info("L2CLB status after delay", "unsafeL2", ssB_after.UnsafeL2.ID(), "safeL2", ssB_after.SafeL2.ID()) + + require.Greater(ssA_after.UnsafeL2.Number, ssA_before.UnsafeL2.Number, "unsafe chain for L2CL should have advanced") + require.Equal(ssB_after.UnsafeL2.Number, ssB_before.UnsafeL2.Number, "unsafe chain for L2CLB should have stalled") + + l.Info("Re-connect L2CL to L2CLB") + sys.L2CLB.ConnectPeer(sys.L2CL) + sys.L2CL.ConnectPeer(sys.L2CLB) + + l.Info("Confirm that the unsafe chain for L2CLB is stalled") + sys.L2CLB.NotAdvanced(types.LocalUnsafe, 10) +} diff --git a/op-acceptance-tests/tests/depreqres/init_test.go b/op-acceptance-tests/tests/depreqres/init_test.go new file mode 100644 index 00000000000..ff0f2710d95 --- /dev/null +++ b/op-acceptance-tests/tests/depreqres/init_test.go @@ -0,0 +1,16 @@ +package depreqres + +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.WithSingleChainMultiNode(), + presets.WithExecutionLayerSyncOnVerifiers(), + presets.WithCompatibleTypes(compat.SysGo), + presets.WithReqRespSyncDisabled(), + ) +} diff --git a/op-devstack/presets/cl_config.go b/op-devstack/presets/cl_config.go index d56cbe4d48f..95a3d900ae6 100644 --- a/op-devstack/presets/cl_config.go +++ b/op-devstack/presets/cl_config.go @@ -31,3 +31,11 @@ func WithSafeDBEnabled() stack.CommonOption { cfg.SafeDBPath = p.TempDir() }))) } + +func WithReqRespSyncDisabled() stack.CommonOption { + return stack.MakeCommon( + sysgo.WithGlobalL2CLOption(sysgo.L2CLOptionFn( + func(_ devtest.P, id stack.L2CLNodeID, cfg *sysgo.L2CLConfig) { + cfg.EnableReqRespSync = false + }))) +} diff --git a/op-devstack/sysgo/l2_cl.go b/op-devstack/sysgo/l2_cl.go index a7f3a4366dc..32f16a679c9 100644 --- a/op-devstack/sysgo/l2_cl.go +++ b/op-devstack/sysgo/l2_cl.go @@ -27,6 +27,9 @@ type L2CLConfig struct { IsSequencer bool IndexingMode bool + + // EnableReqRespSync is the flag to enable/disable req-resp sync. + EnableReqRespSync bool } func L2CLSequencer() L2CLOption { @@ -48,6 +51,7 @@ func DefaultL2CLConfig() *L2CLConfig { SafeDBPath: "", IsSequencer: false, IndexingMode: false, + EnableReqRespSync: true, } } diff --git a/op-devstack/sysgo/l2_cl_opnode.go b/op-devstack/sysgo/l2_cl_opnode.go index 46bfdb916ec..99fcc60b066 100644 --- a/op-devstack/sysgo/l2_cl_opnode.go +++ b/op-devstack/sysgo/l2_cl_opnode.go @@ -241,6 +241,9 @@ func WithOpNode(l2CLID stack.L2CLNodeID, l1CLID stack.L1CLNodeID, l1ELID stack.L } } + // Set the req-resp sync flag as per config + p2pConfig.EnableReqRespSync = cfg.EnableReqRespSync + // Get the L2 engine address from the EL node (which can be a regular EL node or a SyncTesterEL) l2EngineAddr := l2EL.EngineRPC()