Skip to content

fix(web): flag serving checkpoint by block root, not epoch#243

Open
barnabasbusa wants to merge 1 commit intomasterfrom
bbusa/fix-checkpoint-flag-root-match
Open

fix(web): flag serving checkpoint by block root, not epoch#243
barnabasbusa wants to merge 1 commit intomasterfrom
bbusa/fix-checkpoint-flag-root-match

Conversation

@barnabasbusa
Copy link
Copy Markdown
Contributor

Summary

The historical-checkpoints table flags the row currently being served. Previously it matched by epoch (status.data.finality.finalized.epoch === slot.epoch), which has two problems:

  1. Head/serving drift. The slots list is built from d.head (majority-decided finality) while status.data.finality comes from d.servingBundle (last fully-downloaded bundle). When bundle downloads lag — e.g. short-lived devnets, kurtosis enclaves, or any transient fetch failure — d.head advances while d.servingBundle stays behind. Result: the slots list contains rows for epochs that aren't yet serving, so the flag appears on a non-top row or disappears until the bundle catches up.
  2. Epoch is ambiguous. Two different block roots could share the same epoch across restarts/reorgs. Block root is the semantically correct identifier for "the bundle we're serving."

Switch to slot.block_root === status.finality.finalized.root, with a fallback to the old epoch comparison for rows whose block_root hasn't been populated yet.

Repro

Spin up a kurtosis devnet with SLOTS_PER_EPOCH=8. While bundle downloads occasionally retry, the Checkpoints table's flag icon goes missing despite the upstream tab showing healthy finality.

Test plan

  • npx tsc --noEmit clean
  • npm run lint clean
  • Manual: rebuild image, verify flag renders on the row matching status.data.finality.finalized.root, even when d.head is ahead of d.servingBundle

Related: #241 (underflow fix for ListFinalizedSlots that exposes this UI bug on short-lived chains).

The historical-checkpoints table flags the row currently being served by
the checkpointz instance. It did this by comparing each row's epoch
against `status.data.finality.finalized.epoch`.

Two issues:

1. The slots list is built from `d.head` (majority-decided finality), but
   the status's `finality.finalized` is `d.servingBundle` (the last
   fully-downloaded bundle). When bundle downloads lag — e.g. after an
   upstream blip or on short-lived devnets — `d.head` advances while
   `d.servingBundle` stays behind, so the slots list contains rows for
   epochs that don't yet have a serving bundle. The flag then either
   appears on a non-top row with no explanation or disappears entirely
   until the bundle catches up.
2. Epoch-only comparison is ambiguous in principle (two different roots
   can share the same finalized epoch across restarts / reorgs, however
   rare post-finality). Matching by block root is the semantically
   correct signal: "which row's bundle is the one we're serving".

Prefer matching by `slot.block_root === status.finality.finalized.root`
and fall back to the old epoch-based comparison for rows whose
block_root hasn't been populated yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant