diff --git a/op-acceptance-tests/tests/interop/loadtest/invalid_msg_test.go b/op-acceptance-tests/tests/interop/loadtest/invalid_msg_test.go index ce017f3444397..21d47cb30292d 100644 --- a/op-acceptance-tests/tests/interop/loadtest/invalid_msg_test.go +++ b/op-acceptance-tests/tests/interop/loadtest/invalid_msg_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" + "github.com/ethereum-optimism/optimism/op-devstack/sysgo" "github.com/ethereum-optimism/optimism/op-service/bigs" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/txinclude" @@ -83,8 +84,9 @@ func (ie *InvalidExecMsgSpammer) Spam(t devtest.T) error { // executing messages are also spammed. The number of invalid messages spammed per slot is // configurable via NAT_INVALID_MPS (default: 1_000). func TestRelayWithInvalidMessagesSteady(gt *testing.T) { - gt.Skip("Skipping Interop Acceptance Test") t, l2A, l2B := setupLoadTest(gt) + // TODO(#19411): remove skip once op-reth safe head mismatch is fixed + sysgo.SkipUnlessOpGeth(t, "panics due to safe head mismatch in EngineController") // Emit a valid initiating message. initTx, err := l2A.Include(t, planCall(t, &txintent.InitTrigger{ diff --git a/op-acceptance-tests/tests/interop/message/interop_happy_tx_test.go b/op-acceptance-tests/tests/interop/message/interop_happy_tx_test.go index 9162ce4330c88..f3e361f69961c 100644 --- a/op-acceptance-tests/tests/interop/message/interop_happy_tx_test.go +++ b/op-acceptance-tests/tests/interop/message/interop_happy_tx_test.go @@ -19,7 +19,7 @@ import ( func TestInteropHappyTx(gt *testing.T) { gt.Skip("Skipping Interop Acceptance Test") t := devtest.ParallelT(gt) - sys := presets.NewSimpleInterop(t) + sys := presets.NewTwoL2SupernodeInterop(t, 0) // two EOAs for triggering the init and exec interop txs alice := sys.FunderA.NewFundedEOA(eth.OneHundredthEther) @@ -28,24 +28,24 @@ func TestInteropHappyTx(gt *testing.T) { eventLoggerAddress := alice.DeployEventLogger() // wait for chain B to catch up to chain A if necessary - sys.L2ChainB.CatchUpTo(sys.L2ChainA) + sys.L2B.CatchUpTo(sys.L2A) // send initiating message on chain A rng := rand.New(rand.NewSource(time.Now().UnixNano())) initMsg := alice.SendInitMessage(interop.RandomInitTrigger(rng, eventLoggerAddress, rng.Intn(3), rng.Intn(10))) // at least one block between the init tx on chain A and the exec tx on chain B - sys.L2ChainB.WaitForBlock() + sys.L2B.WaitForBlock() // send executing message on chain B execMsg := bob.SendExecMessage(initMsg) // confirm that the cross-safe safety passed init and exec receipts and that blocks were not reorged dsl.CheckAll(t, - sys.L2CLA.ReachedRefFn(stypes.CrossSafe, initMsg.BlockID(), + sys.L2ACL.ReachedRefFn(stypes.CrossSafe, initMsg.BlockID(), // TODO(#16598): Make this relative to the block time 500), - sys.L2CLB.ReachedRefFn(stypes.CrossSafe, execMsg.BlockID(), + sys.L2BCL.ReachedRefFn(stypes.CrossSafe, execMsg.BlockID(), // TODO(#16598): Make this relative to the block time 500), ) diff --git a/op-acceptance-tests/tests/interop/message/interop_mon_test.go b/op-acceptance-tests/tests/interop/message/interop_mon_test.go index 05d0860756751..76a2197ef08de 100644 --- a/op-acceptance-tests/tests/interop/message/interop_mon_test.go +++ b/op-acceptance-tests/tests/interop/message/interop_mon_test.go @@ -19,7 +19,7 @@ import ( func TestInteropMon(gt *testing.T) { gt.Skip("Skipping Interop Acceptance Test") t := devtest.ParallelT(gt) - sys := presets.NewSimpleInterop(t) + sys := presets.NewTwoL2SupernodeInterop(t, 0) clients := map[eth.ChainID]*sources.EthClient{ sys.L2ELA.Escape().ChainID(): sys.L2ELA.Escape().EthClient().(*sources.EthClient), diff --git a/op-acceptance-tests/tests/interop/proofs/serial/interop_fault_proofs_test.go b/op-acceptance-tests/tests/interop/proofs/serial/interop_fault_proofs_test.go index 7d9cdf66019d9..f8c4884a2d9a9 100644 --- a/op-acceptance-tests/tests/interop/proofs/serial/interop_fault_proofs_test.go +++ b/op-acceptance-tests/tests/interop/proofs/serial/interop_fault_proofs_test.go @@ -56,8 +56,9 @@ func TestInteropFaultProofs_VariedBlockTimes_FasterChainB(gt *testing.T) { func TestInteropFaultProofs_InvalidBlock(gt *testing.T) { t := devtest.SerialT(gt) - // TODO(#19411): Unskip once supernode removes invalid transactions - t.Skip("Supernode does not yet remove invalid transactions from blocks") - sys := presets.NewSimpleInteropSupernodeProofs(t) + // TODO(#19411): Re-enable once the invalid-block supernode proof expectations match the + // native Kona FPP and challenger provider behavior again. + t.Skip("Temporarily skipped while investigating invalid-block supernode proof mismatches") + sys := presets.NewSimpleInteropSupernodeProofs(t, presets.WithChallengerCannonKonaEnabled()) sfp.RunInvalidBlockTest(t, sys) } diff --git a/op-acceptance-tests/tests/interop/reorgs/init_exec_msg_test.go b/op-acceptance-tests/tests/interop/reorgs/init_exec_msg_test.go index 1fc1d5c18d730..f932e6470231a 100644 --- a/op-acceptance-tests/tests/interop/reorgs/init_exec_msg_test.go +++ b/op-acceptance-tests/tests/interop/reorgs/init_exec_msg_test.go @@ -10,6 +10,7 @@ import ( "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/sysgo" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-service/bigs" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -23,8 +24,9 @@ import ( ) func TestReorgInitExecMsg(gt *testing.T) { - gt.Skip("Skipping Interop Acceptance Test") t := devtest.ParallelT(gt) + // TODO(#19411): remove skip once op-reth safe head mismatch is fixed + sysgo.SkipUnlessOpGeth(t, "panics due to safe head mismatch in EngineController") ctx := t.Ctx() sys := presets.NewSimpleInterop(t) diff --git a/op-acceptance-tests/tests/interop/reorgs/invalid_exec_msgs_test.go b/op-acceptance-tests/tests/interop/reorgs/invalid_exec_msgs_test.go index 29c9003544120..59842869a6280 100644 --- a/op-acceptance-tests/tests/interop/reorgs/invalid_exec_msgs_test.go +++ b/op-acceptance-tests/tests/interop/reorgs/invalid_exec_msgs_test.go @@ -11,7 +11,7 @@ import ( "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-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-devstack/sysgo" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/txintent" "github.com/ethereum-optimism/optimism/op-service/txintent/bindings" @@ -23,10 +23,12 @@ import ( "github.com/stretchr/testify/require" ) -// TestReorgInvalidExecMsgs tests that the supervisor reorgs the chain when an invalid exec msg is included +// TestReorgInvalidExecMsgs tests that the supernode reorgs the chain when an invalid exec msg is included // Each subtest runs a test with a different invalid message, by modifying the message in the txModifierFn func TestReorgInvalidExecMsgs(gt *testing.T) { - gt.Skip("Skipping Interop Acceptance Test") + t := devtest.ParallelT(gt) + // TODO(#19411): remove skip once op-reth safe head mismatch is fixed + sysgo.SkipUnlessOpGeth(t, "panics due to safe head mismatch in EngineController") gt.Run("invalid log index", func(gt *testing.T) { testReorgInvalidExecMsg(gt, func(msg *suptypes.Message) { msg.Identifier.LogIndex = 1024 @@ -50,10 +52,10 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess t := devtest.ParallelT(gt) ctx := t.Ctx() - sys := presets.NewSimpleInterop(t) + sys := presets.NewTwoL2SupernodeInterop(t, 0) l := sys.Log - ia := sys.TestSequencer.Escape().ControlAPI(sys.L2ChainA.ChainID()) + ia := sys.TestSequencer.Escape().ControlAPI(sys.L2A.ChainID()) // three EOAs for triggering the init and exec interop txs, as well as a simple transfer tx alice := sys.FunderA.NewFundedEOA(eth.OneHundredthEther) @@ -61,7 +63,7 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess cathrine := sys.FunderA.NewFundedEOA(eth.OneHundredthEther) sys.L1Network.WaitForBlock() - sys.L2ChainA.WaitForBlock() + sys.L2A.WaitForBlock() // stop batcher on chain A sys.L2BatcherA.Stop() @@ -94,7 +96,7 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess } // wait for chain B to catch up to chain A if necessary - sys.L2ChainB.CatchUpTo(sys.L2ChainA) + sys.L2B.CatchUpTo(sys.L2A) var initTx *txintent.IntentTx[*txintent.InitTrigger, *txintent.InteropOutput] var initReceipt *types.Receipt @@ -106,14 +108,14 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess initReceipt, err = initTx.PlannedTx.Included.Eval(ctx) require.NoError(t, err) - l.Info("initiating message included in chain B", "chain", sys.L2ChainB.ChainID(), "block_number", initReceipt.BlockNumber, "block_hash", initReceipt.BlockHash, "now", time.Now().Unix()) + l.Info("initiating message included in chain B", "chain", sys.L2B.ChainID(), "block_number", initReceipt.BlockNumber, "block_hash", initReceipt.BlockHash, "now", time.Now().Unix()) } // at least one block between the init tx on chain B and the exec tx on chain A - sys.L2ChainA.WaitForBlock() + sys.L2A.WaitForBlock() // stop sequencer on chain A so that we later force include an invalid exec msg - latestUnsafe_A := sys.L2CLA.StopSequencer() + latestUnsafe_A := sys.L2ACL.StopSequencer() var execTx *txintent.IntentTx[*txintent.ExecTrigger, *txintent.InteropOutput] var execSignedTx *types.Transaction @@ -151,7 +153,7 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess // sequence a new block with an invalid executing msg on chain A { - l.Info("Building chain A with op-test-sequencer, and include invalid exec msg", "chain", sys.L2ChainA.ChainID(), "unsafeHead", latestUnsafe_A) + l.Info("Building chain A with op-test-sequencer, and include invalid exec msg", "chain", sys.L2A.ChainID(), "unsafeHead", latestUnsafe_A) err := ia.New(ctx, seqtypes.BuildOpts{ Parent: latestUnsafe_A, @@ -175,12 +177,12 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess { currentUnsafeRef := sys.L2ELA.BlockRefByLabel(eth.Unsafe) - l.Info("Unsafe head after invalid exec msg has been included in chain A", "chain", sys.L2ChainA.ChainID(), "unsafeHead", currentUnsafeRef, "parent", currentUnsafeRef.ParentID()) + l.Info("Unsafe head after invalid exec msg has been included in chain A", "chain", sys.L2A.ChainID(), "unsafeHead", currentUnsafeRef, "parent", currentUnsafeRef.ParentID()) divergenceBlockNumber_A = currentUnsafeRef.Number originalHash_A = currentUnsafeRef.Hash originalParentHash_A = currentUnsafeRef.ParentHash - l.Info("Continue building chain A with another block with op-test-sequencer", "chain", sys.L2ChainA.ChainID(), "unsafeHead", currentUnsafeRef, "parent", currentUnsafeRef.ParentID()) + l.Info("Continue building chain A with another block with op-test-sequencer", "chain", sys.L2A.ChainID(), "unsafeHead", currentUnsafeRef, "parent", currentUnsafeRef.ParentID()) err := ia.New(ctx, seqtypes.BuildOpts{ Parent: currentUnsafeRef.Hash, L1Origin: nil, @@ -207,8 +209,8 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess time.Sleep(2 * time.Second) } - // continue sequencing with op-node - sys.L2CLA.StartSequencer() + // continue sequencing with the supernode + sys.L2ACL.StartSequencer() // start batcher on chain A sys.L2BatcherA.Start() @@ -220,25 +222,11 @@ func testReorgInvalidExecMsg(gt *testing.T, txModifierFn func(msg *suptypes.Mess ParentHash: originalParentHash_A, }, 30) - err := wait.For(ctx, 5*time.Second, func() (bool, error) { - safeL2Head_supervisor_A := sys.Supervisor.SafeBlockID(sys.L2ChainA.ChainID()).Hash - safeL2Head_sequencer_A := sys.L2CLA.SafeL2BlockRef() - - if safeL2Head_sequencer_A.Number < divergenceBlockNumber_A { - l.Info("Safe ref number is still behind divergence block A number", "divergence", divergenceBlockNumber_A, "safe", safeL2Head_sequencer_A.Number) - return false, nil - } + // Wait for the supernode to validate the replacement block's timestamp. + divergenceTimestamp_A := sys.L2A.TimestampForBlockNum(divergenceBlockNumber_A) + sys.Supernode.AwaitValidatedTimestamp(divergenceTimestamp_A) - if safeL2Head_sequencer_A.Hash.Cmp(safeL2Head_supervisor_A) != 0 { - l.Info("Safe ref still not the same on supervisor and sequencer A", "supervisor", safeL2Head_supervisor_A, "sequencer", safeL2Head_sequencer_A.Hash) - return false, nil - } - - l.Info("Safe ref the same across supervisor and sequencers", - "supervisor_A", safeL2Head_supervisor_A, - "sequencer_A", safeL2Head_sequencer_A.Hash) - - return true, nil - }) - require.NoError(t, err, "Expected to get same safe ref on both supervisor and sequencer eventually") + l.Info("supernode validated replacement block", + "divergence", divergenceBlockNumber_A, + "timestamp", divergenceTimestamp_A) } diff --git a/op-acceptance-tests/tests/interop/sync/simple_interop/interop_sync_test.go b/op-acceptance-tests/tests/interop/sync/simple_interop/interop_sync_test.go index 8c5ddd0321bea..88e64bd325f9f 100644 --- a/op-acceptance-tests/tests/interop/sync/simple_interop/interop_sync_test.go +++ b/op-acceptance-tests/tests/interop/sync/simple_interop/interop_sync_test.go @@ -16,7 +16,7 @@ import ( func TestL2CLResync(gt *testing.T) { gt.Skip("Skipping Interop Acceptance Test") t := devtest.ParallelT(gt) - sys := presets.NewSimpleInterop(t) + sys := presets.NewTwoL2SupernodeInterop(t, 0) logger := sys.Log.With("Test", "TestL2CLResync") logger.Info("Check unsafe chains are advancing") @@ -26,8 +26,8 @@ func TestL2CLResync(gt *testing.T) { ) logger.Info("Stop L2CL nodes") - sys.L2CLA.Stop() - sys.L2CLB.Stop() + sys.L2ACL.Stop() + sys.L2BCL.Stop() logger.Info("Make sure L2ELs does not advance") dsl.CheckAll(t, @@ -36,8 +36,8 @@ func TestL2CLResync(gt *testing.T) { ) logger.Info("Restart L2CL nodes") - sys.L2CLA.Start() - sys.L2CLB.Start() + sys.L2ACL.Start() + sys.L2BCL.Start() // L2CL may advance a few blocks without supervisor connection, but eventually it will stop without the connection // we must check that unsafe head is advancing due to reconnection diff --git a/op-acceptance-tests/tests/supernode/interop/reorg/invalid_message_reorg_test.go b/op-acceptance-tests/tests/supernode/interop/reorg/invalid_message_reorg_test.go index f5322fa3c0d8c..9528a73940729 100644 --- a/op-acceptance-tests/tests/supernode/interop/reorg/invalid_message_reorg_test.go +++ b/op-acceptance-tests/tests/supernode/interop/reorg/invalid_message_reorg_test.go @@ -26,8 +26,8 @@ import ( // - The replacement block's timestamp eventually becomes verified func TestSupernodeInteropInvalidMessageReplacement(gt *testing.T) { t := devtest.SerialT(gt) - // TODO(ethereum-optimism/optimism#19411): remove skip once op-reth safe head mismatch is fixed - sysgo.SkipOnOpReth(t, "panics due to safe head mismatch in EngineController") + // TODO(#19411): remove skip once op-reth safe head mismatch is fixed + sysgo.SkipUnlessOpGeth(t, "panics due to safe head mismatch in EngineController") sys := presets.NewTwoL2SupernodeInterop(t, 0) ctx := t.Ctx() diff --git a/op-acceptance-tests/tests/supernode/interop/same_timestamp_invalid/same_timestamp_test.go b/op-acceptance-tests/tests/supernode/interop/same_timestamp_invalid/same_timestamp_test.go index f198e9c0c38a9..96a28258c5de8 100644 --- a/op-acceptance-tests/tests/supernode/interop/same_timestamp_invalid/same_timestamp_test.go +++ b/op-acceptance-tests/tests/supernode/interop/same_timestamp_invalid/same_timestamp_test.go @@ -28,8 +28,8 @@ func TestSupernodeSameTimestampExecMessage(gt *testing.T) { // TestSupernodeSameTimestampInvalidTransitive: Bad log index causes transitive invalidation func TestSupernodeSameTimestampInvalidTransitive(gt *testing.T) { t := devtest.SerialT(gt) - // TODO(ethereum-optimism/optimism#19411): remove skip once op-reth safe head mismatch is fixed - sysgo.SkipOnOpReth(t, "panics due to safe head mismatch in EngineController") + // TODO(#19411): remove skip once op-reth safe head mismatch is fixed + sysgo.SkipUnlessOpGeth(t, "panics due to safe head mismatch in EngineController") sys := presets.NewTwoL2SupernodeInterop(t, 0).ForSameTimestampTesting(t) rng := rand.New(rand.NewSource(77777)) @@ -46,8 +46,8 @@ func TestSupernodeSameTimestampInvalidTransitive(gt *testing.T) { // TestSupernodeSameTimestampCycle: Mutual exec messages create cycle - both replaced func TestSupernodeSameTimestampCycle(gt *testing.T) { t := devtest.SerialT(gt) - // TODO(ethereum-optimism/optimism#19411): remove skip once op-reth safe head mismatch is fixed - sysgo.SkipOnOpReth(t, "panics due to safe head mismatch in EngineController") + // TODO(#19411): remove skip once op-reth safe head mismatch is fixed + sysgo.SkipUnlessOpGeth(t, "panics due to safe head mismatch in EngineController") sys := presets.NewTwoL2SupernodeInterop(t, 0).ForSameTimestampTesting(t) rng := rand.New(rand.NewSource(55555)) diff --git a/op-devstack/dsl/l2_el.go b/op-devstack/dsl/l2_el.go index 41452a72ce7ff..a5e11b570d967 100644 --- a/op-devstack/dsl/l2_el.go +++ b/op-devstack/dsl/l2_el.go @@ -464,7 +464,7 @@ func (el *L2ELNode) AssertTxNotInBlock(blockNumber uint64, txHash common.Hash) { el.log.Info("confirmed transaction not in block", "blockNumber", blockNumber, "txHash", txHash) } -// AssertTxNotInBlock asserts that a transaction with the given hash does not exist in the block at the given number. +// AssertTxInBlock asserts that a transaction with the given hash does not exist in the block at the given number. func (el *L2ELNode) AssertTxInBlock(blockNumber uint64, txHash common.Hash) { ctx, cancel := context.WithTimeout(el.ctx, DefaultTimeout) defer cancel() diff --git a/op-devstack/sysgo/mixed_runtime.go b/op-devstack/sysgo/mixed_runtime.go index 3e096dab76459..05234c90626f7 100644 --- a/op-devstack/sysgo/mixed_runtime.go +++ b/op-devstack/sysgo/mixed_runtime.go @@ -49,10 +49,10 @@ const ( MixedL2ELOpReth MixedL2ELKind = "op-reth" ) -// SkipOnOpReth skips the test when the L2 execution layer is op-reth +// SkipUnlessOpGeth skips the test when the L2 execution layer is op-reth // (i.e. DEVSTACK_L2EL_KIND is not "op-geth"). -func SkipOnOpReth(t devtest.T, reason string) { - if MixedL2ELKind(os.Getenv(DevstackL2ELKindEnvVar)) == MixedL2ELOpReth { +func SkipUnlessOpGeth(t devtest.T, reason string) { + if MixedL2ELKind(os.Getenv(DevstackL2ELKindEnvVar)) != MixedL2ELOpGeth { t.Skipf("skipping on op-reth: %s", reason) } }