Skip to content

cl/persistence, cl/antiquary: back off when historical replay cannot find a parent block root - #25244

Closed
domiwei wants to merge 1 commit into
mainfrom
kewei/antiquary-parent-root-backoff
Closed

domiwei wants to merge 1 commit into
mainfrom
kewei/antiquary-parent-root-backoff

Conversation

@domiwei

@domiwei domiwei commented Oct 22, 2026

Copy link
Copy Markdown
Member

Fixes #25239. Stacked on #25211.

Problem

ReadParticipations resolves the parent of every Gloas block that has attestations through kv.BlockRootToSlot. When that entry is missing and the parent is not the genesis block, it returned a plain error. initializeStateAntiquaryIfNeeded treated it as fatal, so the state antiquary could not start from that resume point.

Change

  • ReadParticipations returns the new ErrMissingParentBlock sentinel when the parent root is neither in the block index nor the genesis block root. A genesis root row that is present but not 32 bytes long stays a hard error (invalid genesis block root length), the same as other corrupt root rows.
  • initializeStateAntiquaryIfNeeded backs off on ErrMissingParentBlock, the same as on ErrMissingGloasData and ErrMissingHistoryVectorData. The check moved into shouldBackoffHistoricalStateRead.

Backing off only moves the resume point to a state before the gap. The antiquary does not write kv.BlockRootToSlot, so this does not rebuild the block index.

Tests

  • TestReadParticipationsReturnsMissingParentBlockError: missing index entry with a non-genesis parent returns the sentinel.
  • TestReadParticipationsReturnsMalformedGenesisRootError: a 31-byte genesis root returns the length error, not the sentinel.
  • TestReadHistoricalStateReturnsMissingParentBlockError: the sentinel survives the %w wrap in ReadHistoricalState.
  • TestShouldBackoffHistoricalStateRead: classification, including a wrapped sentinel.

There is no end-to-end test through initializeStateAntiquaryIfNeeded: the Gloas fixtures are a few slots long and cannot reach the first backoff step of 10 * SlotsPerDump slots.

Not in this PR

The backoff loop in initializeStateAntiquaryIfNeeded does not check ctx between attempts. This is the same for every backoff sentinel and predates this change.

@domiwei domiwei added Glamsterdam https://eips.ethereum.org/EIPS/eip-7773 Caplin Caplin: Consensus Layer, Beacon API labels Oct 22, 2026
@domiwei domiwei self-assigned this Oct 22, 2026
@domiwei
domiwei requested review from lystopad and yperbasis October 22, 2026 14:15
Base automatically changed from kewei/historical-gloas-payload-match to main October 22, 2026 15:43
@domiwei
domiwei force-pushed the kewei/antiquary-parent-root-backoff branch from e412beb to 9e1fa26 Compare October 22, 2026 17:37
@domiwei
domiwei force-pushed the kewei/antiquary-parent-root-backoff branch from 9e1fa26 to 403bf62 Compare October 22, 2026 20:23
@yperbasis
yperbasis requested a balanced review from Copilot October 23, 2026 08:28

Copilot AI left a comment

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.

🟢 Approval recommended

The narrow change uses the existing backoff mechanism, preserves corruption handling, and includes focused regression coverage.

No open issues 🎉

What changed in this PR

This PR addresses #25239 by routing missing parent-block index entries into the antiquary’s existing historical-state backoff path. It builds on #25211 without attempting to rebuild the block index.

Changes:

  • Adds ErrMissingParentBlock while preserving hard errors for malformed genesis-root rows.
  • Makes the antiquary recognize the sentinel as a reason to back off.
  • Adds regression coverage for sentinel propagation, corruption handling, and backoff classification.
File Description
cl/​persistence/​state/​historical_states_reader/​historical_states_reader.go Defines and returns the missing-parent sentinel; distinguishes malformed genesis roots.
cl/​persistence/​state/​historical_states_reader/​historical_states_reader_test.go Tests missing-parent errors, wrapping, and malformed genesis-root handling.
cl/​antiquary/​state_antiquary.go Adds the sentinel to the existing backoff classifier.
cl/​antiquary/​state_antiquary_test.go Extends backoff classification coverage to missing-parent errors.

Review effort: Balanced

@domiwei

domiwei commented Oct 24, 2026

Copy link
Copy Markdown
Member Author

Closing. A missing BlockRootToSlot entry for a parent block only happens with corrupt or inconsistent data. WriteHeaderSlot writes the entry on every block write path and in the snapshot indexer, nothing deletes from the table, and the snapshot index is rebuilt before the state antiquary starts. Backing off would also not repair the index, so reads of those states through the API would still fail. A loud error is the better outcome here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Caplin Caplin: Consensus Layer, Beacon API Glamsterdam https://eips.ethereum.org/EIPS/eip-7773

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cl/antiquary: back off instead of failing init when historical replay cannot find a parent block root

2 participants