Skip to content

Commit 44cb00e

Browse files
authored
op e2e: interop action test: cycle in self at single block (#15501)
* Add cycle in block testcase * happy lint
1 parent 6e563de commit 44cb00e

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

op-e2e/actions/interop/interop_txplan_test.go

+77
Original file line numberDiff line numberDiff line change
@@ -902,3 +902,80 @@ func TestCycleInTx(gt *testing.T) {
902902
unsafeHeadNumAfterReorg := targetNum - 1
903903
reorgOutUnsafeAndConsolidateToSafe(t, actors, actors.ChainB, actors.ChainA, 0, 0, 1, targetNum, unsafeHeadNumAfterReorg)
904904
}
905+
906+
// TestCycleInBlock tests below scenario:
907+
// Transaction executes message, then initiates it: cycle in block
908+
// To elaborate, single block contains txs in below order:
909+
// {exec message X tx, dummy tx, ..., dummy tx, init message X tx}
910+
func TestCycleInBlock(gt *testing.T) {
911+
t := helpers.NewDefaultTesting(gt)
912+
rng := rand.New(rand.NewSource(1234))
913+
is := dsl.SetupInterop(t)
914+
actors := is.CreateActors()
915+
actors.PrepareChainState(t)
916+
alice := setupUser(t, is, actors.ChainA, 0)
917+
918+
actors.ChainA.Sequencer.ActL2StartBlock(t)
919+
deployOptsA, _ := DefaultTxOpts(t, setupUser(t, is, actors.ChainA, 1), actors.ChainA)
920+
eventLoggerAddressA := DeployEventLogger(t, deployOptsA)
921+
922+
assertHeads(t, actors.ChainA, 1, 0, 0, 0)
923+
924+
// assume every tx including target exec message and init message land in block number 2
925+
// all other txs are dummy tx to make block include multiple tx
926+
targetTime := actors.ChainA.RollupCfg.Genesis.L2Time + actors.ChainA.RollupCfg.BlockTime*2
927+
targetNum := uint64(2)
928+
929+
// attempt to include multiple txs in a single L2 block
930+
actors.ChainA.Sequencer.ActL2StartBlock(t)
931+
932+
nonce := uint64(0)
933+
934+
// speculatively build exec message by knowing necessary info to build Message
935+
init := interop.RandomInitTrigger(rng, eventLoggerAddressA, 3, 10)
936+
logIndexX := uint(0)
937+
exec, err := interop.ExecTriggerFromInitTrigger(init, logIndexX, targetNum, targetTime, actors.ChainA.ChainID)
938+
require.NoError(t, err)
939+
940+
intents := []*txintent.IntentTx[txintent.Call, *txintent.InteropOutput]{}
941+
submitIntent := func(trigger txintent.Call, nonce uint64) {
942+
opts, _ := DefaultTxOptsWithoutBlockSeal(t, alice, actors.ChainA, nonce)
943+
intent := txintent.NewIntent[txintent.Call, *txintent.InteropOutput](opts)
944+
intent.Content.Set(trigger)
945+
_, err := intent.PlannedTx.Submitted.Eval(t.Ctx())
946+
require.NoError(t, err)
947+
intents = append(intents, intent)
948+
}
949+
txCount := 2 + rng.Intn(15)
950+
// include exec message X tx first in block
951+
{
952+
submitIntent(exec, nonce)
953+
nonce += 1
954+
}
955+
// include dummy txs in block
956+
for range txCount - 2 {
957+
randomInitTrigger := interop.RandomInitTrigger(rng, eventLoggerAddressA, 3, 10)
958+
submitIntent(randomInitTrigger, nonce)
959+
nonce += 1
960+
}
961+
// include init message X last in block
962+
{
963+
submitIntent(init, nonce)
964+
// no need to increment nonce since this is the last tx
965+
}
966+
actors.ChainA.Sequencer.ActL2EndBlock(t)
967+
968+
// Make sure tx in block sealed at expected time
969+
for _, intent := range intents {
970+
included, err := intent.PlannedTx.IncludedBlock.Eval(t.Ctx())
971+
require.NoError(t, err)
972+
require.Equal(t, included.Time, targetTime)
973+
require.Equal(t, included.Number, targetNum)
974+
}
975+
976+
// Make batcher happy by advancing at least a single block
977+
actors.ChainB.Sequencer.ActL2EmptyBlock(t)
978+
979+
unsafeHeadNumAfterReorg := targetNum - 1
980+
reorgOutUnsafeAndConsolidateToSafe(t, actors, actors.ChainB, actors.ChainA, 0, 0, 1, targetNum, unsafeHeadNumAfterReorg)
981+
}

0 commit comments

Comments
 (0)