Add opt-in bulk block streaming (-bulkblocksync)
A single getblockstrm request makes a peer stream a contiguous range of old blocks back-to-back as ordinary BLOCK messages, amortizing the per-block round-trip over the whole range instead of the MAX_BLOCKS_IN_TRANSIT_PER_PEER window. This targets the bandwidth-delay-product ceiling that dominates IBD from few/high-latency peers below the checkpoint. Design (off by default; negotiated via a NODE_BULKBLOCKS service bit; the default getdata IBD path is untouched when disabled): - protocol: NODE_BULKBLOCKS service bit + getblockstrm/blockstream messages. - requester: in SendMessages, after FindNextBlocksToDownload, when the first needed block is >= BULK_TIP_MARGIN (5000) below the network tip and the peer advertises the bit and we are in IBD, request a contiguous range (<=128 blocks) instead of per-block getdata; mark the range in-flight. - server: stream the range (caps 128 blocks / 8 MiB; reads outside cs_main; per-peer flood throttle), then a trailing blockstream header with the actual count sent. Self-suppresses while the server itself is in IBD. - received blocks ride the existing BLOCK -> ProcessNewBlock path (fully validated; checkpoints below 2.84M still apply); the trailing header reconciles partial deliveries and the range is freed on a 90s timeout, so a partial/withheld/refused batch falls back to the normal path (no leak, no permanent gap, no disconnect). In-flight tracking is by literal hash, so a reorg cannot orphan range entries. Hardened against the issues found in two adversarial review passes (drain vs timeout, partial reconciliation, ownership-guarded frees, one-shot header, reorg-proof helpers, cs_main hold). Validated end-to-end between two local v1.0.3 nodes (128/128 and partial serves; height advanced; no errors). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
16
src/main.h
16
src/main.h
@@ -102,6 +102,22 @@ static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
|
||||
* ceiling at negligible bandwidth cost. */
|
||||
static const int DEFAULT_MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
|
||||
extern int MAX_BLOCKS_IN_TRANSIT_PER_PEER;
|
||||
/** Opt-in bulk block streaming (DragonX, -bulkblocksync). A single GETBLOCKSTREAM request makes a
|
||||
* peer stream a contiguous range of old blocks as back-to-back BLOCK messages, amortizing the
|
||||
* per-block round-trip over the whole range instead of the MAX_BLOCKS_IN_TRANSIT_PER_PEER window.
|
||||
* OFF by default; negotiated via NODE_BULKBLOCKS; only used during IBD for blocks more than
|
||||
* BULK_TIP_MARGIN below the active tip; never alters the default getdata path. */
|
||||
static const bool DEFAULT_BULKBLOCKSYNC = false;
|
||||
extern bool fBulkBlockSync;
|
||||
/** Only bulk-stream blocks at least this far below the active tip (near-tip uses the normal path). */
|
||||
static const int BULK_TIP_MARGIN = 5000;
|
||||
/** Hard DoS cap: max blocks a single GETBLOCKSTREAM may request/serve. */
|
||||
static const uint16_t BULK_MAX_BLOCKS_PER_REQUEST = 128;
|
||||
/** Hard DoS cap: max total bytes streamed in response to one GETBLOCKSTREAM. */
|
||||
static const size_t BULK_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
||||
/** Requester fallback: if a promised bulk range doesn't fully arrive within this many microseconds,
|
||||
* free the in-flight range so the normal per-block path re-fetches it. */
|
||||
static const int64_t BULK_RESPONSE_TIMEOUT_US = 90 * 1000000LL;
|
||||
/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */
|
||||
static const unsigned int BLOCK_STALLING_TIMEOUT = 2;
|
||||
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
|
||||
|
||||
Reference in New Issue
Block a user