Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cli/operator/eventsync.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,12 @@ func syncContractEvents(
// Sync ongoing registry events in the background. Crash if it stops: the node can't operate
// without staying current with Ethereum events, and until reorg handling exists, restarting
// from persisted state is safer than continuing on possibly-incorrect state.
ongoingFromBlock := fromBlock.Uint64()
go func() {
err := eventSyncer.SyncOngoing(ctx, fromBlock.Uint64())
err := eventSyncer.SyncOngoing(ctx, ongoingFromBlock)
if err != nil && !errors.Is(err, context.Canceled) {
logger.Fatal("failed syncing ongoing registry events",
zap.Uint64("last_processed_block", lastProcessedBlock),
zap.Uint64("from_block", ongoingFromBlock),
zap.Error(err),
)
}
Expand Down
2 changes: 1 addition & 1 deletion doppelganger/doppelganger.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func (h *handler) Start(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.Next():
case <-ticker.Advance():
currentSlot := ticker.Slot()
currentEpoch := h.beaconConfig.EstimatedEpochAtSlot(currentSlot)

Expand Down
5 changes: 3 additions & 2 deletions hprobe/prober.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ func (p *HealthProber) ProbeAll(ctx context.Context) error {
defer wg.Done()

err := p.probeComponent(ctx, n)
if err != nil {
// Relay the error and quit early.
if err != nil && !errors.Is(err, context.Canceled) {

@momosh-ssv momosh-ssv Jun 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth considering a regression test for the masking path this guard fixes?
All current cases in prober_test.go use retryDelay: 0, so the retry-wait select is never where a sibling cancel() lands — the exact scenario this addresses isn't exercised.

A two-component test (one failing fast, one with a non-zero retryDelay) would lock the fix in.

// Relay the error and quit early. Skip context.Canceled: it means
// a sibling failure triggered our cancel(), not a real probe fault.
errsCh <- fmt.Errorf("probe component %s: %w", name, err)
cancel()
}
Expand Down
2 changes: 1 addition & 1 deletion ibft/storage/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (i *ParticipantStorage) PruneContinuously(ctx context.Context, slotTickerPr
select {
case <-ctx.Done():
return
case <-ticker.Next():
case <-ticker.Advance():
threshold := ticker.Slot() - retain - 1
count, err := i.removeSlotAt(threshold)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion ibft/storage/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func TestSlotCleanupJob(t *testing.T) {
close(mockTimeChan)
})

ticker.EXPECT().Next().Return(mockTimeChan).AnyTimes()
ticker.EXPECT().Advance().Return(mockTimeChan).AnyTimes()
ticker.EXPECT().Slot().DoAndReturn(func() phase0.Slot {
return <-mockSlotChan
}).AnyTimes()
Expand Down
4 changes: 2 additions & 2 deletions operator/duties/attester.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,15 @@ func (h *AttesterHandler) HandleDuties(ctx context.Context) {
h.logger.Info("starting duty handler")
defer h.logger.Info("duty handler exited")

next := h.ticker.Next()
next := h.ticker.Advance()
for {
select {
case <-ctx.Done():
return

case <-next:
currentSlot := h.ticker.Slot()
next = h.ticker.Next() // advances h.ticker
next = h.ticker.Advance() // advances h.ticker
currentEpoch := h.beaconConfig.EstimatedEpochAtSlot(currentSlot)
nextEpoch := currentEpoch + 1

Expand Down
4 changes: 2 additions & 2 deletions operator/duties/committee.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ func (h *CommitteeHandler) HandleDuties(ctx context.Context) {
h.logger.Info("starting duty handler")
defer h.logger.Info("duty handler exited")

next := h.ticker.Next()
next := h.ticker.Advance()
for {
select {
case <-ctx.Done():
return

case <-next:
currentSlot := h.ticker.Slot()
next = h.ticker.Next()
next = h.ticker.Advance()
currentEpoch := h.beaconConfig.EstimatedEpochAtSlot(currentSlot)
currentPeriod := h.beaconConfig.EstimatedSyncCommitteePeriodAtEpoch(currentEpoch)

Expand Down
4 changes: 2 additions & 2 deletions operator/duties/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ func (h *ProposerHandler) HandleDuties(ctx context.Context) {
h.logger.Info("starting duty handler")
defer h.logger.Info("duty handler exited")

next := h.ticker.Next()
next := h.ticker.Advance()
for {
select {
case <-ctx.Done():
return

case <-next:
currentSlot := h.ticker.Slot()
next = h.ticker.Next() // advances h.ticker
next = h.ticker.Advance() // advances h.ticker
currentEpoch := h.beaconConfig.EstimatedEpochAtSlot(currentSlot)
nextEpoch := currentEpoch + 1

Expand Down
2 changes: 1 addition & 1 deletion operator/duties/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ func (s *Scheduler) SlotTicker(ctx context.Context) {
select {
case <-ctx.Done():
return
case <-s.ticker.Next():
case <-s.ticker.Advance():
slot := s.ticker.Slot()

delay := s.beaconConfig.IntervalDuration()
Expand Down
6 changes: 3 additions & 3 deletions operator/duties/scheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (m *MockSlotTicker) start(ctx context.Context) {
}()
}

func (m *MockSlotTicker) Next() <-chan time.Time {
func (m *MockSlotTicker) Advance() <-chan time.Time {
return m.timeChan
}

Expand Down Expand Up @@ -482,7 +482,7 @@ func TestScheduler_Run(t *testing.T) {
s.dutyHandlers = []dutyHandler{mockDutyHandler1, mockDutyHandler2}

mockBeaconNode.EXPECT().SubscribeToHeadEvents(ctx, "duty_scheduler", gomock.Any()).Return(nil)
mockTicker.EXPECT().Next().Return(nil).AnyTimes()
mockTicker.EXPECT().Advance().Return(nil).AnyTimes()

// setup mock duty handler expectations
for _, mockDutyHandler := range s.dutyHandlers {
Expand Down Expand Up @@ -535,7 +535,7 @@ func TestScheduler_Regression_IndicesChangeStuck(t *testing.T) {
// add multiple mock duty handlers
s.dutyHandlers = []dutyHandler{NewValidatorRegistrationHandler(nil)}
mockBeaconNode.EXPECT().SubscribeToHeadEvents(ctx, "duty_scheduler", gomock.Any()).Return(nil)
mockTicker.EXPECT().Next().Return(nil).AnyTimes()
mockTicker.EXPECT().Advance().Return(nil).AnyTimes()
err := s.Start(ctx)
require.NoError(t, err)
t.Cleanup(func() {
Expand Down
4 changes: 2 additions & 2 deletions operator/duties/sync_committee.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@ func (h *SyncCommitteeHandler) HandleDuties(ctx context.Context) {
h.logger.Info("starting duty handler")
defer h.logger.Info("duty handler exited")

next := h.ticker.Next()
next := h.ticker.Advance()
for {
select {
case <-ctx.Done():
return

case <-next:
currentSlot := h.ticker.Slot()
next = h.ticker.Next()
next = h.ticker.Advance()
currentEpoch := h.beaconConfig.EstimatedEpochAtSlot(currentSlot)
currentPeriod := h.beaconConfig.EstimatedSyncCommitteePeriodAtEpoch(currentEpoch)

Expand Down
4 changes: 2 additions & 2 deletions operator/duties/validator_registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,15 @@ func (h *ValidatorRegistrationHandler) HandleDuties(ctx context.Context) {
h.logger.Info("starting duty handler")
defer h.logger.Info("duty handler exited")

next := h.ticker.Next()
next := h.ticker.Advance()
for {
select {
case <-ctx.Done():
return

case <-next:
currentSlot := h.ticker.Slot()
next = h.ticker.Next()
next = h.ticker.Advance()
currentEpoch := h.beaconConfig.EstimatedEpochAtSlot(currentSlot)

slotNumber := uint64(currentSlot)%h.beaconConfig.SlotsPerEpoch + 1
Expand Down
4 changes: 2 additions & 2 deletions operator/duties/voluntary_exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@ func (h *VoluntaryExitHandler) HandleDuties(ctx context.Context) {
h.logger.Info("starting duty handler")
defer h.logger.Info("duty handler exited")

next := h.ticker.Next()
next := h.ticker.Advance()
for {
select {
case <-ctx.Done():
return

case <-next:
currentSlot := h.ticker.Slot()
next = h.ticker.Next()
next = h.ticker.Advance()
currentEpoch := h.beaconConfig.EstimatedEpochAtSlot(currentSlot)

slotNumber := uint64(currentSlot)%h.beaconConfig.SlotsPerEpoch + 1
Expand Down
4 changes: 2 additions & 2 deletions operator/dutytracer/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (c *Collector) Start(ctx context.Context, tickerProvider slotticker.Provide
select {
case <-ctx.Done():
return
case <-ticker.Next():
case <-ticker.Advance():
currentSlot := ticker.Slot()
c.evict(currentSlot)
}
Expand Down Expand Up @@ -1304,7 +1304,7 @@ func (c *Collector) startScheduleFiller(ctx context.Context, tickerProvider slot
select {
case <-ctx.Done():
return
case <-t.Next():
case <-t.Advance():
slot := t.Slot()
// Enqueue current slot quickly; if queue is full, drop to avoid backpressure.
select {
Expand Down
2 changes: 1 addition & 1 deletion operator/fee_recipient/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (rc *recipientController) submitPreparationsOnSchedule(ctx context.Context)
select {
case <-ctx.Done():
return
case <-ticker.Next():
case <-ticker.Advance():
slot := ticker.Slot()
// Check if this is the middle slot of the epoch
if firstTimeSubmitted && uint64(slot)%rc.beaconConfig.SlotsPerEpoch != (rc.beaconConfig.SlotsPerEpoch/2) {
Expand Down
4 changes: 2 additions & 2 deletions operator/fee_recipient/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func TestSubmitProposal(t *testing.T) {
ticker := mocks.NewMockSlotTicker(ctrl)
mockTimeChan := make(chan time.Time)
mockSlotChan := make(chan phase0.Slot)
ticker.EXPECT().Next().Return(mockTimeChan).AnyTimes()
ticker.EXPECT().Advance().Return(mockTimeChan).AnyTimes()
ticker.EXPECT().Slot().DoAndReturn(func() phase0.Slot { return <-mockSlotChan }).AnyTimes()

frCtrl.beaconClient = client
Expand Down Expand Up @@ -174,7 +174,7 @@ func TestSubmitProposal(t *testing.T) {

ticker := mocks.NewMockSlotTicker(ctrl)
mockTimeChan := make(chan time.Time, 1)
ticker.EXPECT().Next().Return(mockTimeChan).AnyTimes()
ticker.EXPECT().Advance().Return(mockTimeChan).AnyTimes()
ticker.EXPECT().Slot().Return(phase0.Slot(100)).AnyTimes()

frCtrl.beaconClient = client
Expand Down
12 changes: 6 additions & 6 deletions operator/slotticker/mocks/slotticker.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions operator/slotticker/slotticker.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ type Provider func() SlotTicker
// Note, the caller is RESPONSIBLE for calling Next method periodically in order for

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth updating this — the doc still says calling Next method periodically, but the method is now Advance. Since the whole point of the rename was making the name honest, the comment should follow.

// SlotTicker to advance forward (to keep ticking) to newer slots.
type SlotTicker interface {
// Next returns a channel that will relay 1 tick signaling that "freshest" slot has started.
// Advance returns a channel that will relay 1 tick signaling that "freshest" slot has started.
// It advances slot number SlotTicker keeps track of (potentially jumping several slots ahead)
// and returns a channel that will signal once the time corresponding to that "freshest" slot
// comes.
Next() <-chan time.Time
Advance() <-chan time.Time
// Slot returns the slot number that corresponds to Next.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: corresponds to Next should now read Advance.

Slot() phase0.Slot
}
Expand Down Expand Up @@ -75,9 +75,9 @@ func newWithCustomTimer(logger *zap.Logger, cfg Config, timerProvider TimerProvi
}
}

// Next implements SlotTicker.Next.
// Advance implements SlotTicker.Advance.
// Note, this method is not thread-safe.
func (s *slotTicker) Next() <-chan time.Time {
func (s *slotTicker) Advance() <-chan time.Time {
timeSinceGenesis := time.Since(s.genesisTime)
if timeSinceGenesis < 0 {
// we are waiting for slotTicker to tick at s.genesisTime (signaling 0th slot start)
Expand Down
Loading