yellowstone-reconcile
Reconcile complete Solana blocks across independent Yellowstone connections.
The problem
Solana's Alpenglow integration guidance points consumers at per-connection block reconstruction, then stops short of the next layer:
Run one buffer per connection.
solana.com/upgrades/alpenglowbank_idmeans nothing outside the stream it arrived on. [...] Reconciling across connections is still yours to write.
The same page warns that merging on (slot, bank_id) across streams
fails silently and hands back blocks fused from unrelated banks. Alpenglow activated on
mainnet on 21 October 2026, and the Foundation marks it a breaking change that requires indexing
changes. This library is that missing layer.
What it does
- Takes one upstream
BlockStreamper connection and never mixes their events. - Reconciles sealed blocks on blockhash, parent and counts, not on
bank_id. - Requires a configurable number of distinct providers before emitting.
- Quarantines disagreement and reports conflicts explicitly, never selecting silently.
- Keeps provider identity stable across reconnects, so a reconnect is not a second vote.
- Never fuses payload fragments from different providers.
Measured behaviour
Each figure below is produced by an example or test in the repository and is reproducible. Slot rate measured on mainnet-beta on 25 October 2026.
| Property | Measured |
|---|---|
| Silent provider tolerated before the pending bound rejects | 27.1 s (128 blocks at 212 ms/slot) |
| Retention window before a slot is refused as stale | 868 s (4,096 slots) |
| Payload held at the bound, replaying measured mainnet block sizes | 570.8 MiB |
| Same, were every block the largest sampled | 1,011 MiB |
| Restart from a checkpoint re-emitting a committed slot | never |
| Sink writes across a crash and full replay of 20 slots | 20 rows, 20 writes |
Mainnet block sizes were sampled the same day: median 4.26 MiB, largest 7.90 MiB, smallest 2,389 bytes. A round 2 MiB assumption understates the memory ceiling by roughly half.
Using it
[dependencies]
yellowstone-reconcile = { git = "https://github.com/ss1738/yellowstone-reconcile" }
Assign a stable ProviderId per independent provider, call connect
for each connection, pass each stream's output with its returned Session to
ingest, and halt downstream processing for a slot on Conflict. Advance
retention explicitly and handle the pending slots the prune report returns.
Commit to your sink first, keyed idempotently on slot, and only then persist the checkpoint. A crash between those two steps re-delivers exactly one slot, which is why the sink write has to be idempotent.
Status
Working prototype with a passing verification suite and continuous integration. Tested against synthetic fixtures and a synthetic reconstruction probe, not against two live providers.
No production adopter, no pilot and no upstream endorsement. The upstream dependency is currently pinned to the head of an open, unmerged pull request rather than to its default branch, which is recorded in the repository's dependency review.
Apache-2.0. Not audited.