Skip to content

Commit 3d71cee

Browse files
authored
fix(syncer): fix time comparison and improve estimation accuraccy (#319)
* Finding a new tail in the regular case (not subjective init) only relied on old tail. In the worst case, where the old tail is 1, the estimation results are inaccurate. The fix is to dynamically decide what to estimate with (head or tail) basing on the time diff between old and expected tails * When confirming the estimation by looking at the actual header, the comparison was wrong
1 parent 2062eec commit 3d71cee

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

sync/syncer_tail.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -188,42 +188,62 @@ func (s *Syncer[H]) estimateTailHeight(head H) uint64 {
188188
// findTailHeight find the tail height based on the current head and tail.
189189
// It respects the pruning window, ensuring Syncer maintains the tail within the window.
190190
func (s *Syncer[H]) findTailHeight(ctx context.Context, oldTail, head H) (uint64, error) {
191-
expectedTailTime := head.Time().UTC().Add(-s.Params.PruningWindow)
191+
window := s.Params.PruningWindow
192+
expectedTailTime := head.Time().UTC().Add(-window)
192193
currentTailTime := oldTail.Time().UTC()
194+
tailTimeDiff := expectedTailTime.Sub(currentTailTime)
193195

194-
timeDiff := expectedTailTime.Sub(currentTailTime)
195-
if timeDiff <= 0 {
196+
var estimatedTailHeight uint64
197+
switch {
198+
case tailTimeDiff <= 0:
196199
// current tail is relevant as is
197200
return oldTail.Height(), nil
201+
case tailTimeDiff >= window:
202+
// current and expected tails are far from each other
203+
// estimate with head for higher accuracy
204+
headersToStore := uint64(window / s.Params.blockTime) //nolint:gosec
205+
estimatedTailHeight = head.Height() - headersToStore
206+
case tailTimeDiff < window:
207+
// tails are close
208+
// estimate with tail for higher accuracy
209+
headersToStore := uint64(tailTimeDiff / s.Params.blockTime) //nolint:gosec
210+
estimatedTailHeight = oldTail.Height() + headersToStore
198211
}
212+
199213
log.Debugw(
200214
"current tail is beyond pruning window",
201-
"tail_height", oldTail.Height(),
202-
"time_diff", timeDiff.String(),
215+
"time_diff", tailTimeDiff.String(),
203216
"window", s.Params.PruningWindow.String(),
217+
"curr_tail", oldTail.Height(),
218+
"new_estimated_tail", estimatedTailHeight,
204219
)
205220

206-
heightDiff := uint64(timeDiff / s.Params.blockTime) //nolint:gosec
207-
newTailHeight := oldTail.Height() + heightDiff
221+
newTailHeight := estimatedTailHeight
208222
for {
209223
// store keeps all the headers up to the current head
210224
// to iterate over the headers and find the most accurate tail
211225
newTail, err := s.store.GetByHeight(ctx, newTailHeight)
212226
if err != nil {
213227
return 0, fmt.Errorf(
214228
"getting estimated new tail(%d) from store: %w",
215-
newTailHeight,
229+
estimatedTailHeight,
216230
err,
217231
)
218232
}
219-
if newTail.Time().UTC().Compare(expectedTailTime) <= 0 {
220-
// new tail time is before or equal to expectedTailTime
233+
234+
if expectedTailTime.Compare(newTail.Time().UTC()) <= 0 {
221235
break
222236
}
223237

224238
newTailHeight++
225239
}
226240

227-
log.Debugw("found new tail height", "height", newTailHeight)
241+
log.Debugw(
242+
"new tail height",
243+
"new_confirmed_tail",
244+
newTailHeight,
245+
"estimation_error",
246+
newTailHeight-estimatedTailHeight,
247+
)
228248
return newTailHeight, nil
229249
}

0 commit comments

Comments
 (0)