feat(p2p): add inbound BlocksByRange req/resp support#348
Conversation
Greptile SummaryThis PR adds inbound
Confidence Score: 4/5Safe to merge with the traversal performance concern addressed; no correctness bugs in block selection or validation. The block-selection logic is correct and the validation catches the required bad inputs. The one concern is that crates/net/p2p/src/req_resp/handlers.rs — specifically the
|
| Filename | Overview |
|---|---|
| crates/net/p2p/src/req_resp/handlers.rs | Adds inbound BlocksByRange handling and canonical_blocks_by_range; the traversal walks from head to start_slot unconditionally, creating an O(head_slot) DoS surface for requests targeting old slot ranges. |
| crates/net/p2p/src/req_resp/messages.rs | Adds BlocksByRangeRequest struct, BLOCKS_BY_RANGE_PROTOCOL_V1 constant, MAX_REQUEST_BLOCKS, and renames ResponsePayload::BlocksByRoot to ResponsePayload::Blocks; changes look correct and well-typed. |
| crates/net/p2p/src/req_resp/codec.rs | Adds BlocksByRange decode path and unifies block response decoding under decode_blocks_response; logic is correct and symmetric with the existing BlocksByRoot path. |
| crates/net/p2p/src/req_resp/mod.rs | Re-exports new types and constants; straightforward bookkeeping, no issues. |
| crates/net/p2p/src/lib.rs | Registers BLOCKS_BY_RANGE_PROTOCOL_V1 with ProtocolSupport::Full; consistent with how BlocksByRoot is registered. |
Sequence Diagram
sequenceDiagram
participant Peer
participant Codec
participant Handler
participant Store
Peer->>Codec: BlocksByRange SSZ request
Codec->>Handler: "Request::BlocksByRange { start_slot, count, step }"
Handler->>Handler: "validate (step==0, count==0, count>1024)"
alt invalid request
Handler-->>Peer: Response::Error(INVALID_REQUEST)
else valid request
Handler->>Store: store.head()
loop walk backward from head to start_slot
Store-->>Handler: block header (slot, parent_root)
end
Handler->>Store: store.get_signed_block(root) per matched slot
Store-->>Handler: "Vec<SignedBlock>"
Handler-->>Codec: Response::Success(ResponsePayload::Blocks)
Codec-->>Peer: SSZ-encoded block chunks
end
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
crates/net/p2p/src/req_resp/handlers.rs:210-236
**Unbounded chain traversal is a DoS vector**
`canonical_blocks_by_range` always starts from `store.head()` and walks backward block-by-block until it passes `start_slot`, regardless of how far `end_slot` is from the head. A peer sending a valid request (passes all validation) for `start_slot=1, count=1024, step=1` on a node whose head is at slot 1,000,000 forces ~1,000,000 `store.get_block_header` calls per request. The 1024-block cap on `count` bounds the range width but places no limit on `head_slot – end_slot`, so repeated requests for old slot ranges can saturate the node with O(head_slot) work.
Adding an early exit once all matching slots have been collected would cap the traversal at the first filled slot in the range, and a separate guard rejecting requests where `end_slot` is unreasonably far below the head would prevent the worst-case walk entirely.
Reviews (2): Last reviewed commit: "Merge branch 'main' into feat/blocks-by-..." | Re-trigger Greptile
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
MegaRedHand
left a comment
There was a problem hiding this comment.
Left some comments and questions
Co-authored-by: Tomás Grüner <[email protected]>
|
@MegaRedHand You can review again |
|
CI's failing due to a linter error |
let me see if I can fix from my end. @MegaRedHand You review issue again. |
🗒️ Description / Motivation
This PR adds inbound
BlocksByRangerequest-response support to the P2P req/resp protocol implementation.The change follows the recently merged spec update:
This is needed so peers can request canonical blocks by slot range, similar to the existing
BlocksByRootprotocol.The implementation:
This improves interoperability with other clients implementing the updated spec.
What Changed
Req/Resp Protocol
BlocksByRangeRequestBlocksByRangeresponse payload variant/leanconsensus/req/blocks_by_range/1/ssz_snappyCodec
Behaviour Registration
BlocksByRangein the libp2p request-response behaviourInbound Request Handling
BlocksByRangeValidation
Added validation for:
step == 0count > 1024Invalid requests return protocol error responses.
Tests
Correctness / Behavior Guarantees
Preserved Invariants
Behavior Notes
1024blocksBlocksByRoothandling patterns for consistencyTests Added / Run
Added
blocks_by_range_returns_canonical_blocks_in_requested_orderVerified With
cargo fmt --check cargo check -p ethlambda-p2p cargo test -p ethlambda-p2p blocks_by_range_returns_canonical_blocks_in_requested_order git diff --checkRelated Issues / PRs
BlocksByRangerequest support #346