fix: blockdb retention default, rare-name slot filter timeout, address page crash#806
Merged
Conversation
qu0b
approved these changes
Jul 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: blockdb retention default, rare-name slot filter timeout, address page crash
Fixes three issues found on the long-running sepolia production instance.
1. Blockdb retention never ran without an explicit
cleanupIntervalThe pebble/tiered blockdb cleanup worker only started when
blockDb.pebble.cleanupIntervalwas set. With the field unset (as in the production config),
CacheCleanup.Start()loggedcleanup disabled (interval is 0)and the configured per-type retention caps were neverapplied — the local cache grew unbounded (38GB observed against 3×5GB configured caps).
Fix:
NewCacheCleanupnow defaults the interval to 12h when unset. A negativeinterval disables the cleanup loop explicitly. Applies to both tiered (cache eviction) and
pebble-authoritative (deletion) mode.
Verified in production: the first cleanup run evicted ~46GB of logical data and pebble's
deletion-triggered compactions reclaimed disk space within minutes (38GB → 17GB).
2. Proposer-name filter on the slots list times out for rare names
GetFilteredSlotsevaluates the history-aware proposer-name predicate per row (correlatedEXISTSprobes +ilikeon the joinedvalidator_names), which is not indexable. WithORDER BY slot DESC LIMIT n, Postgres walks the slot index backwards testing the predicaterow by row. For a name whose validators proposed fewer slots than the page size (e.g.
"ethrex" on sepolia: 10 new validators, 33 proposed slots ever), the limit never fills and
the scan visits the entire table — measured 77s over 10.75M rows, timing out the page.
The planner cannot pick the proposer-index plan by itself: per-value statistics
overestimate rarely-proposing validators by orders of magnitude (~39k estimated vs 33
actual rows), so the slot-ordered scan always looks cheaper.
Fix: for non-inverted name filters, pre-resolve the matching validator identity set
(current-name indexes + matching history ranges with their snapshot windows, capped at
5000/1000 entries) before building the query:
LIMIT-bounded count probe) → restrict thescan to the candidates via an optimization-fenced subquery (
OFFSET 0), forcing theproposer-index plan,
page limit quickly there.
The candidate restriction is a strict superset of the precise predicate, which still
applies unchanged on top. Measured on the production dataset: 77s → 108ms for the
"ethrex" filter. Covered by the existing
TestGetFilteredSlotsHistoryNamescases (whichnow exercise the candidate-driven shape, including the empty-match early return).
3.
/addresscrashes for addresses unknown to the execution indexerThe address tab loaders (which populate the filter and pager models) only run for accounts
present in the DB (
account.ID > 0). For unknown addresses the placeholder account skipsthem, and the tab templates dereference the nil models unconditionally:
Fix:
buildAddressPageDatabackfills empty filter and pager models after the tabloaders, so unknown addresses render an empty page instead of a 500.