Repository navigation
hub: link a live block from one-block files up to that block only - #88
Merged
sduchesneau merged 1 commit intoOct 29, 2026
Merged
Conversation
linkLiveUsingOneBlocks walked the one-block store from the LIB to its end and decoded every unknown file into the forkable. Files above the live block can't help link it: when a reader restarts below blocks already in the store (for example blocks stranded above a gap the merger can't pass), the hub decoded all of them, payloads included. On a chain with blocks of up to ~190 MB, with a few thousand one-block files stranded above a gap, this took the process from a completed bootstrap to OOM within about 90 seconds of its first live block. The walk now stops at the live block's number. The live block's LIB and every block between it and the live block are still read, so the reconnection check (blockFromFile.Number == blk.LibNum) is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
When a live block can't be linked,
ForkableHub.linkLiveUsingOneBlockswalks the one-block store from the LIB to the end of the store, and decodes every unknown file into the forkable. One-block files above the live block can't help link it. This change makes the walk stop at the live block's number, through a newWalkOneBlocksStoreRange.How it was found
Setup: reader-node, merger, firehose and substreams tier1/tier2 run in one firecore process on a single node, with local
file://stores. The hub is fed straight from that reader's gRPC: there is no separate relayer.The chain has large blocks, up to about 190 MB decoded each.
linkLiveUsingOneBlocksfrom its own LIB to the end of the store.Result: the hub decoded the whole pile, and the process was OOM-killed (128G) within about 90 seconds of every start.
The gap itself shouldn't happen. A follow-up PR will improve how reader cursors work, so a block that was printed but never stored is no longer skipped on restart. This PR is about the hub's behaviour once such a gap exists.
Behaviour change
The lookup still reads the live block's LIB and everything up to the live block, so two things are unchanged:
blockFromFile.Number == blk.LibNum);unknownOneBlockFiles).Files above the live block are left alone, and the hub links them later as they arrive live.
Reproduction
firecore from
develop, built twice, with this branch's base and with this branch. The same single-node setup,reader-node merger firehose, with a synthetic chain:Without the bound, the decoded files also move the forkable's LIB to the top of the stranded range. Live blocks below the LIB are dropped (#70), so the hub serves nothing until the reader catches up, while holding all of it in memory.
On the affected node
firecore v1.21.1 with only this change (its bstream, 775b59f, is this branch's base). The bootstrap still failed as before. The lookup for the first live block took 4 ms, and the hub was ready 31 ms later. There were no OOMs afterwards, and the heap settled at 2–5 GB once the bootstrap's blocks were released.
Not tested
A distributed setup, with readers, relayers, merger and firehose on separate nodes. The change only bounds the walk's upper end, so no difference is expected there. But a relayer-fed hub reaches this path in its own ways (reconnects, #79), and those weren't exercised.
Tests
TestForkableHub_LinkLiveUsingOneBlocks_StopsAtLiveBlock: a hub without LIB, one-block files below and above a gap, and a live block below the gap. It fails ondevelop, which decodes the files above, and passes here.TestForkableHub_WalkOneBlocksStoreRange.go test ./...passes.