From 71737d7538ad86e65d0bd968c4ac943b6b900774 Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Fri, 7 Mar 2025 06:16:15 +0800 Subject: [PATCH] op-node: continue sequencing when `L1TemporaryErrorEvent` happens (#14062) * continue sequencing when L1TemporaryErrorEvent happens * add TestSequencerL1TemporaryErrorEvent * address comment * fix test --- op-node/rollup/sequencing/sequencer.go | 2 + op-node/rollup/sequencing/sequencer_test.go | 54 +++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/op-node/rollup/sequencing/sequencer.go b/op-node/rollup/sequencing/sequencer.go index 9e6a7e96c3726..d66bcbad02248 100644 --- a/op-node/rollup/sequencing/sequencer.go +++ b/op-node/rollup/sequencing/sequencer.go @@ -491,6 +491,8 @@ func (d *Sequencer) startBuildingBlock() { // Figure out which L1 origin block we're going to be building on top of. l1Origin, err := d.l1OriginSelector.FindL1Origin(ctx, l2Head) if err != nil { + d.nextAction = d.timeNow().Add(time.Second) + d.nextActionOK = d.active.Load() d.log.Error("Error finding next L1 Origin", "err", err) d.emitter.Emit(rollup.L1TemporaryErrorEvent{Err: err}) return diff --git a/op-node/rollup/sequencing/sequencer_test.go b/op-node/rollup/sequencing/sequencer_test.go index 9c4e77ee72532..094ed0b09c013 100644 --- a/op-node/rollup/sequencing/sequencer_test.go +++ b/op-node/rollup/sequencing/sequencer_test.go @@ -3,6 +3,7 @@ package sequencing import ( "context" "encoding/binary" + "fmt" "math/rand" // nosemgrep "testing" "time" @@ -613,6 +614,59 @@ func TestSequencerBuild(t *testing.T) { require.Equal(t, testClock.Now(), nextTime, "start asap on the next block") } +func TestSequencerL1TemporaryErrorEvent(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + seq, deps := createSequencer(logger) + testClock := clock.NewSimpleClock() + seq.timeNow = testClock.Now + testClock.SetTime(30000) + emitter := &testutils.MockEmitter{} + seq.AttachEmitter(emitter) + + // Init will request a forkchoice update + emitter.ExpectOnce(engine.ForkchoiceRequestEvent{}) + require.NoError(t, seq.Init(context.Background(), true)) + emitter.AssertExpectations(t) + require.True(t, seq.Active(), "started in active mode") + + // It will request a forkchoice update, it needs the head before being able to build on top of it + emitter.ExpectOnce(engine.ForkchoiceRequestEvent{}) + seq.OnEvent(SequencerActionEvent{}) + emitter.AssertExpectations(t) + + // Now send the forkchoice data, for the sequencer to learn what to build on top of. + head := eth.L2BlockRef{ + Hash: common.Hash{0x22}, + Number: 100, + L1Origin: eth.BlockID{ + Hash: common.Hash{0x11, 0xa}, + Number: 1000, + }, + Time: uint64(testClock.Now().Unix()), + } + seq.OnEvent(engine.ForkchoiceUpdateEvent{UnsafeL2Head: head}) + emitter.AssertExpectations(t) + + // force FindL1Origin to return an error + deps.l1OriginSelector.l1OriginFn = func(l2Head eth.L2BlockRef) (eth.L1BlockRef, error) { + return eth.L1BlockRef{}, fmt.Errorf("l1OriginFn error") + } + + emitter.ExpectOnceRun(func(ev event.Event) { + _, ok := ev.(rollup.L1TemporaryErrorEvent) + require.True(t, ok) + }) + + sealTargetTime1, ok1 := seq.NextAction() + seq.OnEvent(SequencerActionEvent{}) + emitter.AssertExpectations(t) + + // FindL1Origin error will updating d.nextAction + sealTargetTime2, ok2 := seq.NextAction() + + require.True(t, ok1 == ok2 && sealTargetTime2.After(sealTargetTime1)) +} + type sequencerTestDeps struct { cfg *rollup.Config attribBuilder *FakeAttributesBuilder