feat(l1): implement EIP-7975 eth/70 partial receipt fetching#6327
Conversation
🤖 Kimi Code ReviewReview SummaryThis PR adds support for eth/70 protocol version, implementing EIP-7975 (partial receipt requests). The implementation is well-structured and follows the existing patterns in the codebase. Here are the key findings: Issues Found1. Critical: Missing
|
🤖 Kimi Code ReviewReview SummaryThis PR adds support for eth/70 (EIP-7975) with partial receipt requests. The implementation is clean and follows the established patterns in the codebase. Below are specific findings: ✅ Correctness & EIP Compliance
|
🤖 Codex Code Review
Overall, eth/70 message wiring and version-gated decoding look solid; I didn’t see EVM/gas/consensus-rule regressions in this PR’s scope (networking/protocol handling). Automated review by OpenAI Codex · custom prompt |
Lines of code reportTotal lines added: Detailed view |
🤖 Claude Code ReviewHere is the review for PR #6327: Code Review: feat(l1) — EIP-7975 eth/70 partial receipt fetchingOverall the implementation is well-structured and the test coverage is solid. There is one meaningful correctness issue with the Correctness —
|
625ab2b to
c9e2715
Compare
🤖 Claude Code ReviewNow I have enough information to produce a thorough review. Code Review: PR #6327 — EIP-7975 eth/70 Partial Receipt FetchingSummaryOverall, this is a well-structured incremental implementation. The message framing, dispatch logic, and server-side pagination logic are correct. The test coverage is commendable. Below are findings ordered by severity. Correctness Issues
EIP-7975 defines
Both a missing block and a block with zero transactions return
The condition at line 92: if total_size + receipt_size > SOFT_RESPONSE_LIMIT
&& (!block_receipt_list.is_empty() || !all_receipts.is_empty())For the very first receipt of the very first block (both lists empty), this allows the oversized receipt to be included unconditionally — correct per the spec's "at least one receipt" guarantee. However, for the very first receipt of a subsequent block when Protocol Correctness
The Minor IssuesTypo in struct field names — This typo ("lastest" instead of "latest") is copied from
let (eth_version, decoder): (u32, _) = decoder.decode_field("protocolVersion")?;
// ...
eth_version: eth_version as u8,The field is decoded as Duplicate Identical helper defined in two modules. Consider extracting to a test utility module shared across receipt tests. Redundant constants with identical values const SNAP_CAPABILITY_OFFSET_ETH_69: u8 = 0x22;
const SNAP_CAPABILITY_OFFSET_ETH_70: u8 = 0x22; // same value
const BASED_CAPABILITY_OFFSET_ETH_69: u8 = 0x31;
const BASED_CAPABILITY_OFFSET_ETH_70: u8 = 0x31; // same valueThese are intentionally equal because eth/70 reuses the same message codes (0x0F / 0x10) as eth/68-69, so the capability offset doesn't change. A comment explaining why they share the value would help future maintainers and prevent someone from incorrectly assuming this is a copy-paste error.
Consistent visibility is fine; just noting the pattern is already established. Missing Client-Side Implementation (Informational)The PR correctly implements server-side handling of Positive Highlights
Automated review by Claude (Anthropic) · custom prompt |
🤖 Codex Code Review
Everything else in the diff looks structurally solid: eth/70 capability negotiation, status message support, and partial receipts encoding/decoding are implemented cleanly. I couldn’t run Automated review by OpenAI Codex · custom prompt |
Greptile SummaryThis PR implements EIP-7975 ( Critical issue: Other findings: The RLP encode/decode for all three new message types is correct and well-tested (21 round-trip tests). Message code dispatch, capability negotiation, and storage layer are all implemented correctly. Confidence Score: 1/5
Sequence DiagramsequenceDiagram
participant Peer as Remote Peer (eth/70)
participant Server as ethrex Server
participant Store as Storage
Peer->>Server: GetReceipts70(id, firstBlockReceiptIndex, [hash1, hash2, ...])
activate Server
loop for each block hash
Server->>Store: get_receipts_for_block_from_index(hash, start_index)
Store-->>Server: Vec Receipt
Note over Server: Accumulate receipts up to 10 MiB limit. Set lastBlockIncomplete if mid-block cutoff.
end
Server-->>Peer: Receipts70(id, lastBlockIncomplete, receipts)
deactivate Server
alt lastBlockIncomplete == true
Note over Peer: Re-request same block from offset len(partial_receipts)
Peer->>Server: GetReceipts70(id, followUpIndex, [lastBlockHash])
else lastBlockIncomplete == false
Note over Peer: All included blocks complete. Request next blocks if needed.
end
Last reviewed commit: c9e2715 |
58bbb02 to
891367e
Compare
Introduce eth/70 protocol support with modified GetReceipts and Receipts messages that allow requesting and serving partial block receipt lists. This prevents synchronization failures when complete receipt lists exceed the 10 MiB devp2p message size limit at higher block gas limits.
- Fix last_block_incomplete flag: only set when the current block actually has a partial receipt list. Previously the flag was incorrectly set when the limit was hit at a block boundary, causing peers to re-request an already-complete block. - Fix lastest -> latest typo in status message field names across eth68, eth69, and eth70 (including RLP decode field names).
891367e to
9f4cb5a
Compare
Prevents a malicious peer from triggering unbounded DB reads by sending an excessive number of block hashes.
…enum variants Adds version-explicit naming to match the existing Receipts68/Receipts69/Receipts70 convention, making the message enum consistent across all receipt-related types.
Implements [EIP-7975](https://eips.ethereum.org/EIPS/eip-7975) — a new `eth/70` protocol version that extends the `GetReceipts` and `Receipts` messages with partial receipt list support. As Ethereum scales with higher block gas limits, complete block receipt lists can exceed the 10 MiB devp2p message size limit, causing synchronization failures. eth/70 solves this by adding: - **`GetReceipts` (eth/70)**: `[request-id, firstBlockReceiptIndex, [blockhash₁, ...]]` — allows the client to request receipts starting from a specific index in the first block (for pagination of large receipt lists). - **`Receipts` (eth/70)**: `[request-id, lastBlockIncomplete, [[receipt₁, ...], ...]]` — includes a flag indicating whether the last block's receipt list is incomplete, signaling the client to make a follow-up request. **New files:** - `crates/networking/p2p/rlpx/eth/eth70/` — `GetReceipts70`, `Receipts70`, and `StatusMessage70` message types with RLP encode/decode **Modified files:** - `message.rs` — `V70` variant in `EthCapVersion`, new `Message` enum variants, updated dispatch (decode/encode/code/request_id/Display) - `p2p.rs` — `Capability::eth(70)` added to `SUPPORTED_ETH_CAPABILITIES` - `server.rs` — V70 capability negotiation, Status70 handling, `GetReceipts70` handler with 10 MiB soft response limit and partial receipt pagination - `store.rs` — `get_receipts_for_block_from_index()` for partial receipt retrieval - Accumulates receipts per block using `RLPEncode::length()` for zero-allocation size estimation - Stops when the 10 MiB soft limit would be exceeded and sets `lastBlockIncomplete = true` - Guarantees at least one receipt is always included, even if it alone exceeds the limit - Avoids pushing empty trailing receipt lists that could mislead peers - [x] 21 new unit tests for `GetReceipts70` and `Receipts70` roundtrip encoding - [x] Wire format compatibility tests (eth/70 differs from eth/69, cross-decode rejected) - [x] All 93 p2p crate tests pass - [x] `cargo fmt`, `make lint` clean - [ ] Hive eth/70 protocol tests (when available upstream)
## Summary Implements [EIP-7975](https://eips.ethereum.org/EIPS/eip-7975) — a new `eth/70` protocol version that extends the `GetReceipts` and `Receipts` messages with partial receipt list support. As Ethereum scales with higher block gas limits, complete block receipt lists can exceed the 10 MiB devp2p message size limit, causing synchronization failures. eth/70 solves this by adding: - **`GetReceipts` (eth/70)**: `[request-id, firstBlockReceiptIndex, [blockhash₁, ...]]` — allows the client to request receipts starting from a specific index in the first block (for pagination of large receipt lists). - **`Receipts` (eth/70)**: `[request-id, lastBlockIncomplete, [[receipt₁, ...], ...]]` — includes a flag indicating whether the last block's receipt list is incomplete, signaling the client to make a follow-up request. ### Changes **New files:** - `crates/networking/p2p/rlpx/eth/eth70/` — `GetReceipts70`, `Receipts70`, and `StatusMessage70` message types with RLP encode/decode **Modified files:** - `message.rs` — `V70` variant in `EthCapVersion`, new `Message` enum variants, updated dispatch (decode/encode/code/request_id/Display) - `p2p.rs` — `Capability::eth(70)` added to `SUPPORTED_ETH_CAPABILITIES` - `server.rs` — V70 capability negotiation, Status70 handling, `GetReceipts70` handler with 10 MiB soft response limit and partial receipt pagination - `store.rs` — `get_receipts_for_block_from_index()` for partial receipt retrieval ### Server-side partial receipt logic - Accumulates receipts per block using `RLPEncode::length()` for zero-allocation size estimation - Stops when the 10 MiB soft limit would be exceeded and sets `lastBlockIncomplete = true` - Guarantees at least one receipt is always included, even if it alone exceeds the limit - Avoids pushing empty trailing receipt lists that could mislead peers ## Test plan - [x] 21 new unit tests for `GetReceipts70` and `Receipts70` roundtrip encoding - [x] Wire format compatibility tests (eth/70 differs from eth/69, cross-decode rejected) - [x] All 93 p2p crate tests pass - [x] `cargo fmt`, `make lint` clean - [ ] Hive eth/70 protocol tests (when available upstream)
…lass#6327) ## Summary Implements [EIP-7975](https://eips.ethereum.org/EIPS/eip-7975) — a new `eth/70` protocol version that extends the `GetReceipts` and `Receipts` messages with partial receipt list support. As Ethereum scales with higher block gas limits, complete block receipt lists can exceed the 10 MiB devp2p message size limit, causing synchronization failures. eth/70 solves this by adding: - **`GetReceipts` (eth/70)**: `[request-id, firstBlockReceiptIndex, [blockhash₁, ...]]` — allows the client to request receipts starting from a specific index in the first block (for pagination of large receipt lists). - **`Receipts` (eth/70)**: `[request-id, lastBlockIncomplete, [[receipt₁, ...], ...]]` — includes a flag indicating whether the last block's receipt list is incomplete, signaling the client to make a follow-up request. ### Changes **New files:** - `crates/networking/p2p/rlpx/eth/eth70/` — `GetReceipts70`, `Receipts70`, and `StatusMessage70` message types with RLP encode/decode **Modified files:** - `message.rs` — `V70` variant in `EthCapVersion`, new `Message` enum variants, updated dispatch (decode/encode/code/request_id/Display) - `p2p.rs` — `Capability::eth(70)` added to `SUPPORTED_ETH_CAPABILITIES` - `server.rs` — V70 capability negotiation, Status70 handling, `GetReceipts70` handler with 10 MiB soft response limit and partial receipt pagination - `store.rs` — `get_receipts_for_block_from_index()` for partial receipt retrieval ### Server-side partial receipt logic - Accumulates receipts per block using `RLPEncode::length()` for zero-allocation size estimation - Stops when the 10 MiB soft limit would be exceeded and sets `lastBlockIncomplete = true` - Guarantees at least one receipt is always included, even if it alone exceeds the limit - Avoids pushing empty trailing receipt lists that could mislead peers ## Test plan - [x] 21 new unit tests for `GetReceipts70` and `Receipts70` roundtrip encoding - [x] Wire format compatibility tests (eth/70 differs from eth/69, cross-decode rejected) - [x] All 93 p2p crate tests pass - [x] `cargo fmt`, `make lint` clean - [ ] Hive eth/70 protocol tests (when available upstream)
Summary
Implements EIP-7975 — a new
eth/70protocol version that extends theGetReceiptsandReceiptsmessages with partial receipt list support.As Ethereum scales with higher block gas limits, complete block receipt lists can exceed the 10 MiB devp2p message size limit, causing synchronization failures. eth/70 solves this by adding:
GetReceipts(eth/70):[request-id, firstBlockReceiptIndex, [blockhash₁, ...]]— allows the client to request receipts starting from a specific index in the first block (for pagination of large receipt lists).Receipts(eth/70):[request-id, lastBlockIncomplete, [[receipt₁, ...], ...]]— includes a flag indicating whether the last block's receipt list is incomplete, signaling the client to make a follow-up request.Changes
New files:
crates/networking/p2p/rlpx/eth/eth70/—GetReceipts70,Receipts70, andStatusMessage70message types with RLP encode/decodeModified files:
message.rs—V70variant inEthCapVersion, newMessageenum variants, updated dispatch (decode/encode/code/request_id/Display)p2p.rs—Capability::eth(70)added toSUPPORTED_ETH_CAPABILITIESserver.rs— V70 capability negotiation, Status70 handling,GetReceipts70handler with 10 MiB soft response limit and partial receipt paginationstore.rs—get_receipts_for_block_from_index()for partial receipt retrievalServer-side partial receipt logic
RLPEncode::length()for zero-allocation size estimationlastBlockIncomplete = trueTest plan
GetReceipts70andReceipts70roundtrip encodingcargo fmt,make lintclean