Skip to content

Commit 6552a82

Browse files
committed
Handle edge case in catch up
1 parent c31af08 commit 6552a82

3 files changed

Lines changed: 24 additions & 7 deletions

File tree

apps/testapp/cmd/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func createSequencer(
124124
return nil, fmt.Errorf("based sequencer mode requires aggregator mode to be enabled")
125125
}
126126

127-
basedSeq, err := based.NewBasedSequencer(daClient, nodeConfig, datastore, genesis, logger, executor)
127+
basedSeq, err := based.NewBasedSequencer(ctx, daClient, nodeConfig, datastore, genesis, logger, executor)
128128
if err != nil {
129129
return nil, fmt.Errorf("failed to create based sequencer: %w", err)
130130
}

block/internal/da/subscriber.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ type Subscriber struct {
6565
// headReached tracks whether the subscriber has caught up to DA head.
6666
headReached atomic.Bool
6767

68+
// seenSubscriptionEvent tracks whether followLoop has observed at least one
69+
// subscription event in this run. Without this, startup catchup can stop
70+
// too early when highestSeen is still just the initial start height.
71+
seenSubscriptionEvent atomic.Bool
72+
6873
// catchupSignal wakes catchupLoop when a new height is seen above localDAHeight.
6974
catchupSignal chan struct{}
7075

@@ -192,6 +197,7 @@ func (s *Subscriber) runSubscription(ctx context.Context) error {
192197
if !ok {
193198
return errors.New("subscription channel closed")
194199
}
200+
s.seenSubscriptionEvent.Store(true)
195201
s.updateHighest(ev.Height)
196202

197203
local := s.localDAHeight.Load()
@@ -317,6 +323,13 @@ func (s *Subscriber) runCatchup(ctx context.Context) {
317323
}
318324

319325
local := s.localDAHeight.Load()
326+
highest := s.highestSeenDAHeight.Load()
327+
328+
if s.seenSubscriptionEvent.Load() && local > highest {
329+
s.headReached.Store(true)
330+
return
331+
}
332+
320333
// CAS claims this height — prevents followLoop from inline-processing.
321334
if !s.localDAHeight.CompareAndSwap(local, local+1) {
322335
// followLoop already advanced past this height via inline processing.
@@ -326,7 +339,7 @@ func (s *Subscriber) runCatchup(ctx context.Context) {
326339
if err := s.handler.HandleCatchup(ctx, local); err != nil {
327340
// Roll back so we can retry after backoff.
328341
s.localDAHeight.Store(local)
329-
if errors.Is(err, datypes.ErrHeightFromFuture) {
342+
if errors.Is(err, datypes.ErrHeightFromFuture) && local >= highest {
330343
s.headReached.Store(true)
331344
return
332345
}

block/internal/da/subscriber_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ func TestSubscriber_RunCatchup(t *testing.T) {
4646
DABlockTime: time.Millisecond,
4747
})
4848

49-
// It should try 100, 101, then we return ErrHeightFromFuture at 102
49+
// It should process observed heights [100..101] then stop when local passes highestSeen.
50+
sub.updateHighest(101)
51+
sub.seenSubscriptionEvent.Store(true)
5052
mockHandler.On("HandleCatchup", mock.Anything, uint64(100)).Return(nil).Once()
5153
mockHandler.On("HandleCatchup", mock.Anything, uint64(101)).Return(nil).Once()
52-
mockHandler.On("HandleCatchup", mock.Anything, uint64(102)).Return(datypes.ErrHeightFromFuture).Once()
5354

5455
sub.runCatchup(ctx)
5556

@@ -76,6 +77,9 @@ func TestSubscriber_RunCatchup(t *testing.T) {
7677

7778
var callCount int
7879

80+
sub.updateHighest(100)
81+
sub.seenSubscriptionEvent.Store(true)
82+
7983
mockHandler.On("HandleCatchup", mock.Anything, uint64(100)).
8084
Run(func(args mock.Arguments) {
8185
callCount++
@@ -85,14 +89,14 @@ func TestSubscriber_RunCatchup(t *testing.T) {
8589
mockHandler.On("HandleCatchup", mock.Anything, uint64(100)).
8690
Run(func(args mock.Arguments) {
8791
callCount++
88-
cancel()
8992
}).
90-
Return(datypes.ErrHeightFromFuture).Once()
93+
Return(nil).Once()
9194

9295
sub.runCatchup(ctx)
9396

9497
mockHandler.AssertExpectations(t)
9598
assert.Equal(t, 2, callCount)
96-
assert.Equal(t, uint64(100), sub.LocalDAHeight(), "should roll back to 100 on future error")
99+
assert.Equal(t, uint64(101), sub.LocalDAHeight())
100+
assert.True(t, sub.HasReachedHead())
97101
})
98102
}

0 commit comments

Comments
 (0)