Describe the bug
A remote peer can request data-column sidecars over a very wide slot range via the PeerDAS /eth2/beacon_chain/req/data_column_sidecars_by_range/1/ssz_snappy protocol.
Unlike the handlers for blocks-by-range and blobs-by-range, the validateDataColumnsByRange function in beacon-chain/sync/rpc_data_column_sidecars_by_range.go does not cap the size of the batch loaded from the database.
It currently sets rangeParams.size to the entire requested window (up to the peer’s rate-limit burst, defaulting to 16384 slots):
rangeParameters := &rangeParams{start: startSlot, end: endSlot, size: uint64(size)}
// `size` is essentially `endSlot - startSlot + 1` without batch clamping
return rangeParameters, nil
Because the shared blockRangeBatcher uses rangeParams.size as the per-batch slot width, this results in a single, massive synchronous DB read (db.Blocks(start, end)) over the full width of the window before the stream write quota stops it.
For comparison, in the same repository, validateBlobsByRange correctly clamps this:
limit := min(blobBatchLimit(current), maxRequest)
if rp.size > limit {
rp.size = limit
}
return rp, nil
Other clients (e.g., Lodestar, Lighthouse) also clamp the requested count or reject requests that are too large. While the rate-limiter prevents infinite bounds (capping at burst ~16384), pulling up to 16384 slots in a single DB batch causes measurable transient CPU and disk I/O spikes on the node.
Has this worked before in a previous version?
N/A. This is related to the upcoming Fulu / PeerDAS data columns implementation.
🔬 Minimal Reproduction
Run a Prysm beacon node on a Fulu devnet (or with Fulu enabled via Kurtosis).
Establish a libp2p connection to the node.
Send a data_column_sidecars_by_range request with a large count parameter that is within the rate-limiter's burst limit but much larger than typical batch sizes.
Example parameters: start_slot = head_slot - 20000 (within DA window), count = 4096 or 16384, columns = 0..127.
Observe the node's disk read and CPU usage during the request, as well as the Prometheus metric rpc_data_columns_by_range_response_latency.
The wall-clock time for a single inbound request with count=4096 is significantly higher than a baseline count=128 because the node is fetching all 4096 slots in a single DB batch rather than chunking them into batches of 64/128.
Error
No application crash or explicit error is printed, but this creates a performance bottleneck. The node will experience severe I/O blocking during the massive DB fetch.
Platform(s)
No response
What version of Prysm are you running? (Which release)
No response
Anything else relevant (validator index / public key)?
No response
Describe the bug
A remote peer can request data-column sidecars over a very wide slot range via the PeerDAS /eth2/beacon_chain/req/data_column_sidecars_by_range/1/ssz_snappy protocol.
Unlike the handlers for blocks-by-range and blobs-by-range, the validateDataColumnsByRange function in beacon-chain/sync/rpc_data_column_sidecars_by_range.go does not cap the size of the batch loaded from the database.
It currently sets rangeParams.size to the entire requested window (up to the peer’s rate-limit burst, defaulting to 16384 slots):
Because the shared blockRangeBatcher uses rangeParams.size as the per-batch slot width, this results in a single, massive synchronous DB read (db.Blocks(start, end)) over the full width of the window before the stream write quota stops it.
For comparison, in the same repository, validateBlobsByRange correctly clamps this:
Other clients (e.g., Lodestar, Lighthouse) also clamp the requested count or reject requests that are too large. While the rate-limiter prevents infinite bounds (capping at burst ~16384), pulling up to 16384 slots in a single DB batch causes measurable transient CPU and disk I/O spikes on the node.
Has this worked before in a previous version?
🔬 Minimal Reproduction
Run a Prysm beacon node on a Fulu devnet (or with Fulu enabled via Kurtosis).
Establish a libp2p connection to the node.
Send a data_column_sidecars_by_range request with a large count parameter that is within the rate-limiter's burst limit but much larger than typical batch sizes.
Example parameters: start_slot = head_slot - 20000 (within DA window), count = 4096 or 16384, columns = 0..127.
Observe the node's disk read and CPU usage during the request, as well as the Prometheus metric rpc_data_columns_by_range_response_latency.
The wall-clock time for a single inbound request with count=4096 is significantly higher than a baseline count=128 because the node is fetching all 4096 slots in a single DB batch rather than chunking them into batches of 64/128.
Error
No application crash or explicit error is printed, but this creates a performance bottleneck. The node will experience severe I/O blocking during the massive DB fetch.
Platform(s)
No response
What version of Prysm are you running? (Which release)
No response
Anything else relevant (validator index / public key)?
No response