Skip to content

Serve verified uncommitted blocks to seq-only lookups in CachedStorage - #497

Draft
samliok wants to merge 3 commits into
mainfrom
fix/cachedstorage-seq-only-lookup
Draft

Serve verified uncommitted blocks to seq-only lookups in CachedStorage#497
samliok wants to merge 3 commits into
mainfrom
fix/cachedstorage-seq-only-lookup

Conversation

@samliok

@samliok samliok commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Problem

CachedStorage keeps verified-but-not-yet-finalized blocks in a cache keyed by digest. The msm sealing-block checks (buildBlockOrTransitionEpoch, areWeReadyToTransitionEpoch) look blocks up by sequence only and pass a zero digest, so they can never hit the cache. The lookup falls through to committed storage, and while the sealing block is notarized but not yet indexed, block building fails with failed to retrieve sealing block for previous epoch. The failed build is not retried, so the leader misses its round and the round empty-notarizes.

The window is the normal pipelining case right after a sealing block: the next leader builds on the notarized sealing block before it finalizes. Surfaced as a deterministic-ish hang in a new multi-node instance test where round 2's build races round 1's commit (test lands separately with the instance test harness).

Fix

When a lookup misses the cache and the digest is zero, scan the cache by sequence before falling back to storage. A hit returns the block with a nil finalization, matching the documented cache invariant (cached means not yet finalized), so callers correctly compute isSealingBlockFinalized = false instead of erroring. Digest-based lookups are unchanged: a real digest that is not cached still resolves through committed storage.

Related: #495 and #496 fix the error masking that hid this failure (the msm error was dropped and misreported as a context cancellation).

🤖 Generated with Claude Code

Comment thread adapters.go Outdated
Comment thread adapters.go
func (cs *CachedStorage) Retrieve(seq uint64, digest common.Digest) (common.VerifiedBlock, *common.Finalization, error) {
cs.lock.RLock()
item, exists := cs.cache[digest]
if !exists && digest == (common.Digest{}) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's add a test that tests the added lines.

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.

2 participants