Commit 525e1721 authored by Joshua Gutow's avatar Joshua Gutow

op-node: Reproduce invalid advance in unit tests

This reproduces a bug found by mdehoog. This bug causes the system
to halt under certain circustances. Specifically, when generating
batches at the end of the sequence window the batch queue would attempt
to generate empy batches from the next L2 timestamp to the timestamp of
the next L1 origin. If the timestamp of the next L1 origin was less than
the timestamp of the next L2 block time, no batches would be generated
and the internal L1 blocks would be advanced. This would cause L1 origins
to be skipped. This got caught by a consistency check we have in the batch
queue, but loops in an unrecoverable error until this bug is fixed.
parent 0d46735a
...@@ -183,6 +183,96 @@ func TestBatchQueueEager(t *testing.T) { ...@@ -183,6 +183,96 @@ func TestBatchQueueEager(t *testing.T) {
} }
} }
// Tests CLI-3378
func TestBatchQueueInvalidInternalAdvance(t *testing.T) {
log := testlog.Logger(t, log.LvlTrace)
l1 := L1Chain([]uint64{10, 15, 20, 25, 30})
safeHead := eth.L2BlockRef{
Hash: mockHash(10, 2),
Number: 0,
ParentHash: common.Hash{},
Time: 10,
L1Origin: l1[0].ID(),
SequenceNumber: 0,
}
cfg := &rollup.Config{
Genesis: rollup.Genesis{
L2Time: 10,
},
BlockTime: 2,
MaxSequencerDrift: 600,
SeqWindowSize: 2,
}
batches := []*BatchData{b(12, l1[0]), b(14, l1[0]), b(16, l1[0]), b(18, l1[0]), b(20, l1[0]), b(22, l1[0]), nil}
errors := []error{nil, nil, nil, nil, nil, nil, io.EOF}
input := &fakeBatchQueueInput{
batches: batches,
errors: errors,
origin: l1[0],
}
bq := NewBatchQueue(log, cfg, input)
_ = bq.Reset(context.Background(), l1[0], eth.SystemConfig{})
// Load continuous batches for epoch 0
for i := 0; i < len(batches); i++ {
b, e := bq.NextBatch(context.Background(), safeHead)
require.ErrorIs(t, e, errors[i])
require.Equal(t, batches[i], b)
if b != nil {
safeHead.Number += 1
safeHead.Time += 2
safeHead.Hash = mockHash(b.Timestamp, 2)
safeHead.L1Origin = b.Epoch()
}
}
// Advance to origin 1. No forced batches yet.
input.origin = l1[1]
b, e := bq.NextBatch(context.Background(), safeHead)
require.ErrorIs(t, e, io.EOF)
require.Nil(t, b)
// Advance to origin 2. No forced batches yet because we are still on epoch 0
// & have batches for epoch 0.
input.origin = l1[2]
b, e = bq.NextBatch(context.Background(), safeHead)
require.ErrorIs(t, e, io.EOF)
require.Nil(t, b)
// Advance to origin 3. Should generate one empty batch.
input.origin = l1[3]
// b, e = bq.NextBatch(context.Background(), safeHead)
// require.Nil(t, e)
// require.NotNil(t, b)
// require.Equal(t, safeHead.Time+2, b.Timestamp)
// safeHead.Number += 1
// safeHead.Time += 2
// safeHead.Hash = mockHash(b.Timestamp, 2)
// safeHead.L1Origin = b.Epoch()
b, e = bq.NextBatch(context.Background(), safeHead)
require.ErrorIs(t, e, io.EOF)
require.Nil(t, b)
// Advance to origin 4. Should generate one empty batch.
input.origin = l1[4]
// b, e = bq.NextBatch(context.Background(), safeHead)
// require.Nil(t, e)
// require.NotNil(t, b)
// require.Equal(t, safeHead.Time+2, b.Timestamp)
// safeHead.Number += 1
// safeHead.Time += 2
// safeHead.Hash = mockHash(b.Timestamp, 2)
// safeHead.L1Origin = b.Epoch()
b, e = bq.NextBatch(context.Background(), safeHead)
require.ErrorIs(t, e, io.EOF)
require.Nil(t, b)
}
func TestBatchQueueMissing(t *testing.T) { func TestBatchQueueMissing(t *testing.T) {
log := testlog.Logger(t, log.LvlCrit) log := testlog.Logger(t, log.LvlCrit)
l1 := L1Chain([]uint64{10, 15, 20, 25}) l1 := L1Chain([]uint64{10, 15, 20, 25})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment