net: window catch-up getdata to the serve cap - #272
Merged
Conversation
rearden-grok
Bot
force-pushed
the
net/catchup-getdata-window
branch
from
August 26, 2026 15:24
1b19ad3 to
1b6b9f0
Compare
Connecting headers of 20 asked GetData for the whole path. The peer serves at most MAX_SERVE_BLOCKS (16), so extra hashes stuck in requested and sync_blocks timed out (minchainwork 50, createmultisig 149, bip68 CSV). Co-authored-by: Cursor <cursoragent@cursor.com>
Asking the whole header path left hashes in requested while the peer reconstructed at most 16. First ask and drain continuation share fetchable_header_path_bodies so leftover heights are re-asked after the window connects. Co-authored-by: Cursor <cursoragent@cursor.com>
Node-to-node getdata is MSG_CMPCT_BLOCK. Accepting CmpctBlock left the hash in requested, so drain's serve window stayed full and the rest of the header path was never asked. Co-authored-by: Cursor <cursoragent@cursor.com>
MSG_CMPCT_BLOCK replies never left requested, so drain truncated the next window to zero. Also cap compact ancestor getdata at MAX_SERVE_BLOCKS like the headers path. Co-authored-by: Cursor <cursoragent@cursor.com>
rearden-grok
Bot
force-pushed
the
net/catchup-getdata-window
branch
from
August 26, 2026 16:11
1b6b9f0 to
2196b85
Compare
Writer fetch_sub on every CmpctBlock wrapped 0 to usize::MAX when tip announce used queue_out, so later reconstruct was skipped (sync_blocks 60s). Count announce on the same counter, saturating-sub on write, and fill coinbase-only compact without a mempool. Co-authored-by: Cursor <cursoragent@cursor.com>
Counting tip announce on serve_inflight filled the reconstruct cap during a generate burst, so later getdata was skipped (bip68 activateCSV sync_blocks). Announce uses queue_out; writer still saturating-subs so an unpaired CmpctBlock cannot wrap the counter. Co-authored-by: Cursor <cursoragent@cursor.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.
Summary
Overnight core-functional (
sync_blocks60s) stalled when a catch-up node asked the whole header path while the serving peer reconstructs at most 16 bodies (MAX_SERVE_BLOCKS). Extra hashes stayed inrequested/note_asked_blockand were never re-asked.Node-to-node getdata is
MSG_CMPCT_BLOCK. AcceptingCmpctBlockalso left the hash inrequested, so drain's window stayed full even after the 16 bodies connected.Writer
fetch_subon everyBlock/CmpctBlockwrappedserve_inflight0 →usize::MAXwhen compact tip announce usedqueue_out(no matchingfetch_add). Later reconstruct then saw the cap and skipped serve. Saturating-sub fixes the wrap. Counting announce on the same cap then starved getdata during a generate burst (feature_bip68_sequenceactivateCSV 432 blocks). Coinbase-only compact used to bail when the hub had no mempool.catchup_headers_getdata_stays_in_serve_window— 20 connecting headers must GetData 16, then the remaining 4 after those bodies connect (failed: got 20).drain_pendingcontinuation sharefetchable_header_path_bodies, truncated toMAX_SERVE_BLOCKS. Weaker / below-minwork paths stay header-only.catchup_compact_getdata_clears_requested_for_next_window— same 20-header catch-up answered withCmpctBlock(failed:requestedstill 16).blocktxn/ already-have drop the hash fromrequested. Compact ancestor getdata is also capped at 16. Serve-inflight cap test is unchanged.compact_tip_announce_must_not_wrap_serve_inflight— unpaired writer decrement after announce must leave inflight at 0.queue_out.compact_tip_announce_must_not_consume_serve_slots— 16 queued announces must leave inflight at 0 so a laterMSG_CMPCT_BLOCKgetdata still serves.fetch_add. Coinbase-only compact fills from prefilled txs without a mempool.Overnight run: https://github.com/reardencode/rbitcoin/actions/runs/32941780319
Green core-functional: https://github.com/reardencode/rbitcoin/actions/runs/32995598334
Test plan
cargo test -p rbitcoin-net --lib catchup_headers_getdatacargo test -p rbitcoin-net --lib catchup_compact_getdatacargo test -p rbitcoin-net --lib compact_tip_announcecargo test -p rbitcoin-net --lib coinbase_compact_fills_without_mempoolcargo test -p rbitcoin-net --lib(worktree)core-functional