From c2d4a9e60c1c58636487419f89e151c7d3e24ec5 Mon Sep 17 00:00:00 2001 From: Gabriel de Quadros Ligneul Date: Thu, 24 Oct 2024 15:54:05 -0300 Subject: [PATCH] Add two more delay-buffer tests * Test batch poster without delay buffer works * Test delay buffer don't force batch without delayed messages --- system_tests/batch_poster_test.go | 129 ++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 34 deletions(-) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 6b602d38a8..2ba3da328e 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -6,6 +6,7 @@ package arbtest import ( "context" "crypto/rand" + "errors" "fmt" "math/big" "strings" @@ -365,52 +366,112 @@ func TestAllowPostingFirstBatchWhenSequencerMessageCountMismatchDisabled(t *test testAllowPostingFirstBatchWhenSequencerMessageCountMismatch(t, false) } -func TestBatchPosterDelayBuffer(t *testing.T) { - const messagesPerBatch = 10 - const threshold = 100 +func GetBatchCount(t *testing.T, builder *NodeBuilder) uint64 { + t.Helper() + sequenceInbox, err := bridgegen.NewSequencerInbox(builder.L1Info.GetAddress("SequencerInbox"), builder.L1.Client) + Require(t, err) + batchCount, err := sequenceInbox.BatchCount(&bind.CallOpts{Context: builder.ctx}) + Require(t, err) + return batchCount.Uint64() +} + +func CheckBatchCount(t *testing.T, builder *NodeBuilder, want uint64) { + if got := GetBatchCount(t, builder); got != want { + t.Fatalf("invalid batch count, want %v, got %v", want, got) + } +} + +func testBatchPosterDelayBuffer(t *testing.T, delayBufferEnabled bool) { + const messagesPerBatch = 3 + const numBatches = 3 + var threshold uint64 + if delayBufferEnabled { + threshold = 100 + } ctx, cancel := context.WithCancel(context.Background()) defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, true).WithDelayBuffer(threshold) + builder.L2Info.GenerateAccount("User2") builder.nodeConfig.BatchPoster.MaxDelay = time.Hour // set high max-delay so we can test the delay buffer cleanup := builder.Build(t) defer cleanup() - builder.L2Info.GenerateAccount("User2") + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) + defer cleanupB() + + initialBatchCount := GetBatchCount(t, builder) + for batch := uint64(0); batch < numBatches; batch++ { + txs := make(types.Transactions, messagesPerBatch) + for i := range txs { + txs[i] = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) + } + SendSignedTxesInBatchViaL1(t, ctx, builder.L1Info, builder.L1.Client, builder.L2.Client, txs) + + // Check batch wasn't sent + _, err := WaitForTx(ctx, testClientB.Client, txs[0].Hash(), 100*time.Millisecond) + if err == nil || !errors.Is(err, context.DeadlineExceeded) { + Fatal(t, "expected context-deadline exceeded error, but got:", err) + } + CheckBatchCount(t, builder, initialBatchCount+batch) + + // Advance L1 to force a batch given the delay buffer threshold + AdvanceL1(t, ctx, builder.L1.Client, builder.L1Info, int(threshold)) // #nosec G115 + if !delayBufferEnabled { + // If the delay buffer is disabled, set max delay to zero to force it + CheckBatchCount(t, builder, initialBatchCount+batch) + builder.nodeConfig.BatchPoster.MaxDelay = 0 + } + for _, tx := range txs { + _, err := testClientB.EnsureTxSucceeded(tx) + Require(t, err, "tx not found on second node") + } + CheckBatchCount(t, builder, initialBatchCount+batch+1) + if !delayBufferEnabled { + builder.nodeConfig.BatchPoster.MaxDelay = time.Hour + } + } +} +func TestBatchPosterDelayBufferEnabled(t *testing.T) { + testBatchPosterDelayBuffer(t, true) +} + +func TestBatchPosterDelayBufferDisabled(t *testing.T) { + testBatchPosterDelayBuffer(t, false) +} + +func TestBatchPosterDelayBufferDontForceNonDelayedMessages(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + const threshold = 100 + builder := NewNodeBuilder(ctx).DefaultConfig(t, true).WithDelayBuffer(threshold) + builder.L2Info.GenerateAccount("User2") + builder.nodeConfig.BatchPoster.MaxDelay = time.Hour // set high max-delay so we can test the delay buffer + cleanup := builder.Build(t) + defer cleanup() testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) defer cleanupB() - sequenceInbox, err := bridgegen.NewSequencerInbox(builder.L1Info.GetAddress("SequencerInbox"), builder.L1.Client) - Require(t, err) - getBatchCount := func() uint64 { - batchCount, err := sequenceInbox.BatchCount(&bind.CallOpts{Context: ctx}) - Require(t, err) - return batchCount.Uint64() + // Send non-delayed message and advance L1 + initialBatchCount := GetBatchCount(t, builder) + const numTxs = 3 + txs := make(types.Transactions, numTxs) + for i := range txs { + txs[i] = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) } + builder.L2.SendWaitTestTransactions(t, txs) + AdvanceL1(t, ctx, builder.L1.Client, builder.L1Info, threshold) - t.Run("SendsDelayedMessages", func(t *testing.T) { - previousBatchCount := getBatchCount() - const numBatches = 3 - for batch := uint64(0); batch < numBatches; batch++ { - txs := make(types.Transactions, messagesPerBatch) - for i := range txs { - txs[i] = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) - } - SendSignedTxesInBatchViaL1(t, ctx, builder.L1Info, builder.L1.Client, builder.L2.Client, txs) - time.Sleep(time.Second) - if currBatchCount := getBatchCount(); currBatchCount != previousBatchCount+batch { - t.Fatalf("expected batch count %v; got %v", previousBatchCount+batch, currBatchCount) - } - // Advance L1 to force the delay buffer - AdvanceL1(t, ctx, builder.L1.Client, builder.L1Info, threshold) - if currBatchCount := getBatchCount(); currBatchCount != previousBatchCount+batch+1 { - t.Fatalf("expected batch count %v; got %v", previousBatchCount+batch+1, currBatchCount) - } - for _, tx := range txs { - _, err := testClientB.EnsureTxSucceeded(tx) - Require(t, err, "tx not found on second node") - } - } - }) + // Even advancing the L1, the batch won't be posted because it doesn't contain a delayed message + CheckBatchCount(t, builder, initialBatchCount) + + // Set delay to zero to force non-delayed messages + builder.nodeConfig.BatchPoster.MaxDelay = 0 + for _, tx := range txs { + _, err := testClientB.EnsureTxSucceeded(tx) + Require(t, err, "tx not found on second node") + } + CheckBatchCount(t, builder, initialBatchCount+1) }