network: blocks_by_range catch-up cadence — @min(gap, MAX_REQUEST_BLOCKS) cycle-gates large gaps
- Dominant language
- Zig
- Stars
- 97
- Forks
- 39
- PR merge metrics
- No merged PRs in 30d
Description
# network: blocks_by_range catch-up cadence — `@min(gap, MAX_REQUEST_BLOCKS)` cycle-gates large gaps
Reported by @ch4r10t33r in review of #824.
## Problem
In `pkgs/node/src/node.zig:1002`, the sync trigger does:
```zig
const requested_count: u64 = @min(gap, params.MAX_REQUEST_BLOCKS);
```
If a peer is e.g. 10 000 slots ahead, we request the first 1 024 (= `MAX_REQUEST_BLOCKS`), then **wait for the next status response** to advance further. With status interval at `STATUS_INTERVAL_SLOTS = 8` slots = 32 seconds (`pkgs/node/src/constants.zig:39`), a 10 k-slot catch-up needs ~10 cycles = **~5 minutes minimum just from cycle gating**.
For a fresh node joining a long-running devnet, this is a meaningful chunk of the catch-up budget burned on idle wait time rather than DB+network work.
## Options
### (a) Chain follow-up requests after first batch lands
When `processBlockByRangeChunk` finishes a batch and the peer's `head_slot` is still significantly ahead of our `last applied slot`, immediately fire the next `blocks_by_range` request without waiting for the next status cycle. Bounded by some max-in-flight cap.
### (b) Document cadence
Just write down "catch-up rate is bounded by status interval × MAX_REQUEST_BLOCKS / slot_duration" in operator docs and the protocol description. Cheaper but doesn't actually improve catch-up.
### (c) Both — chain follow-ups + document the bounded cadence
Recommendation: (c). The bounded-cadence note is for operators; the chained-request fix is for sync correctness when a node falls badly behind.
## Acceptance criteria
- [ ] After a `blocks_by_range` batch is fully applied, if peer's head is still ahead by `>` some threshold (e.g., `BLOCKS_BY_RANGE_SYNC_THRESHOLD`), issue the next batch immediately rather than waiting for the next status response.
- [ ] Some bound on max-in-flight chained requests (e.g., 1 — strictly serial — to start, with room to relax later).
- [ ] Metrics: chained-request counter so we can observe the catch-up trajectory in Prometheus.
- [ ] Documentation in `docs/` (or wherever the protocol is described) covering the cadence.
## Out of scope
- The pending-state race fix for `sendBlocksByRangeRequest` (separate follow-up).
- DoS / rate-limit on the server side (separate follow-up).
cc @ch4r10t33r
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at the sync trigger in pkgs/node/src/node.zig:1002 and read the status interval constant in pkgs/node/src/constants.zig:39, then trace processBlockByRangeChunk and the existing blocks_by_range flow. Determine how a bounded serial follow-up request can use the peer head and applied slot without addressing the explicitly out-of-scope pending-state race. Done includes the chained-request metric and cadence documentation in docs/ or the protocol documentation location.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- prometheus, zig
- Domain
- distributed-systems, documentation, networking, observability
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100