Repository navigation
ibd: connect archived blocks that spend a same-batch create - #1067
reardencode merged 3 commits into
Conversation
198003f to
9c5222f
Compare
9c5222f to
7c4bdb4
Compare
There was a problem hiding this comment.
Summary
An all-archived retry (plan=None, IBD skeleton present) used to stamp a same-batch create with a txid and no body_range. Load then failed closed with lookup stage miss (load parent without body_range denserels) and halted under blocks Core connects. The new branch loc-fills create.loc body, spent, and n_out for every tx fk in this stamp's metas. spend_edges_from_stamp still picks the in-batch fk. That is the right parent for a same-block spend and for A→B→C inside one load chunk. It does not run on plan=Some, and it does not loc-fill skeleton parents. There is no durable pin: the read dies with the batch, and Class A stays idempotent.
A kill -9 in one write era leaves a single load batch above the tip, and that batch fits one chunk, so this fill covers that crash. It does not cover a spend whose parent was only note_creates'd by an earlier load chunk of a larger archived wave.
Issue counts by severity
- bugs: 0
- suggestions: 2
- nits: 1
Issues outside the diff
These findings reference lines that are not present in the diff and could not be posted as inline comments:
- [nit] crates/rbitcoin-query/src/stamp.rs:9 -- The module contract still says IBD (
skeleton = Some) never loc-by-fk, and that spent is pin loc, skeleton TipOnly loc, or unset.stamp_external_parentsstill obeys that.stamp_parent_pin_archivedno longer does, for this batch's own creates.docs/invariants.mdstates the exception; this comment does not. A later edit that restores the module rule would re-break the retry.- Suggestion: Say that an all-archived retry may loc-fill its own creates, and that external IBD parents still must not.
|
@rearden-grok On the outside-diff nit ( |
|
@rearden-grok please re-review the latest commit (544a16f). |
32a11ca to
7f10c98
Compare
A batch with an invalid block is retried from its archived bodies. With the IBD skeleton, the stamp gave no range to a parent created in that batch. Load failed with "lookup stage miss" twice and IBD halted below the valid blocks. Fill ranges for the batch's own creates on that retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review nit: the test should fail if a batching change stops putting both blocks in one wave. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review: a wave longer than one load batch notes chunk 1's archived creates in flight with no outs. A spend of one in chunk 2 was not in that chunk's metas, so it still had no range. Fill every parent with no body on the archived retry: this batch's own creates and an earlier chunk's. Skeleton parents keep their body and in-flight pins are still skipped. Test: 145 archived blocks, the last spends a create from the first and loads in the second chunk. The stamp.rs module note and the invariants row name the exception. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7f10c98 to
544a16f
Compare
There was a problem hiding this comment.
Summary
The widened fill is the right scope. It runs only on an all-archived retry (plan=None with a skeleton). A parent that never got an ident still fails closed. Skeleton ranges are left alone, in-flight pins are still skipped, and what remains is this chunk's own creates plus an earlier chunk's no-out rows. archived_wave_pins_a_parent_from_the_previous_chunk fails if the extract is narrowed back to this stamp's metas. The stamp.rs note and the invariants row are the exception to "IBD never loc-by-fk", which is the counterintuitive contract.
Prior notes on the 144-block split and the cascade assert are addressed. The rebase onto current master kept that exception on the Lookup parent stamp row next to the BIP34 wording from #1072.
Issue counts by severity
- bugs: 0
- suggestions: 0
- nits: 0
No further rebase. This head is ahead of master and mergeable. Merge this before #1068 so that PR's diff is only the tip-hole fetch; #1068 is already stacked on this tip.
Summary
During IBD, a block can spend a tx created earlier in the same batch. When that batch is retried from its archived bodies (plan=None) with the IBD skeleton, the stamp only filled parent ranges when there was no skeleton. The same-batch parent had no range. Load failed with
lookup stage miss (load parent without body_range denserels)twice, and IBD halted below valid blocks.The retry happens in two cases:
Bitcoin Core connects the valid blocks in both cases.
stamp_parent_pin_archived (plan=None) stamp external parents # the skeleton carries their ranges stamp this batch's own creates # identity only if no skeleton fill missing ranges + else + fill missing ranges for this batch's own createsOnly an all-archived retry takes this branch. A normal IBD batch has a plan. The
docs/invariants.mdrow notes the one loc read this adds.Evidence
Invalid block in a batch. Same 140-block regtest chain sent to Core 31.1 and rbitcoin over IBD. Block 116 has a parent and its child. Block 118 is invalid.
engine fault repeated @116Before, this failed in 5 of 6 runs (it depends on how blocks split into batches). After, 5 of 5 matched Core.
Crash restart.
kill -9three times during a 1,500-block regtest IBD whose blocks spend same-block outputs, then restart:hole=,0.0/s)lookup stage miss)lookup stage miss)hole=,0.0/s)hole=,0.0/s)"halted" is this PR. "stuck" is #1068.
New test
archived_retry_pins_a_same_block_parent(WireRig, one wave: valid block with a same-block spend, then a block whose coinbase overpays):Cascade, thenEngineFaulttwice on the valid block, then halt.Merge Danger
Door: two-way
Blast Radius: small. Only the all-archived retry path changes. It is reachable on a live network after a crash during IBD, since blocks often spend outputs from the same batch.
🤖 Generated with Claude Code