p2p/protocols/eth: EIP-8159 eth/71 wire protocol (PR 1/3)#20793
Merged
Conversation
No code changes yet. This plan catalogues: - Which EIP-8159 pieces are already in-tree via EIP-7928 prep (BlockAccessListHash header field, BAL rawdb sidecar, BAL.Hash method matching the spec hash, Amsterdam fork gate, empty-BAL hash constant). - The net-new networking work needed: ETH71 version constant, two new wire message codes (0x12/0x13), packet types, protobuf enum entries, ToProto/FromProto table entries, sentry dispatch, libsentry negotiation, and a consumer-side BAL fetcher. - A 6-phase implementation split across 4 stackable PRs so each is small and independently revertible. - Risk list, test plan per phase, and explicit out-of-scope items. The plan is intentionally light on code — it names file:line anchors so the subsequent implementation PRs drop directly into the cited sites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 1+2 of the EIP-8159 (Block Access List Exchange) implementation,
targeting bal-devnet-4. No behavioural change yet — just the wire-protocol
substrate so subsequent phases can add the handler, sentry dispatch, and
consumer-side fetcher on top.
Changes:
- node/interfaces/p2psentry/sentry.proto:
- Protocol enum: ETH71 = 7
- MessageId enum: GET_BLOCK_ACCESS_LISTS_71 = 42, BLOCK_ACCESS_LISTS_71 = 43
Regenerated node/gointerfaces/sentryproto/sentry.pb.go via `make grpc`.
- node/direct/sentry_client.go:
- ETH71 = 71 constant
- ProtocolToUintMap and UintToProtocolMap entries
- p2p/protocols/eth/protocol.go:
- ProtocolToString[ETH71] = "eth71"
- ProtocolLengths[ETH71] = 20 (two new message codes above eth/70's 18)
- Message code constants: GetBlockAccessListsMsg = 0x12, BlockAccessListsMsg = 0x13
- ToProto[ETH71] / FromProto[ETH71] tables, cloned from ETH70 plus the
two new mappings
- Packet types: GetBlockAccessListsPacket ([]common.Hash), its eth/66
request-id-wrapped GetBlockAccessListsPacket66, the corresponding
BlockAccessListsPacket ([]rlp.RawValue — payloads passed through as-is
since rawdb stores BALs in canonical RLP form), and BlockAccessListsPacket66.
Name/Kind methods for the Packet interface.
- p2p/protocols/eth/protocol_test.go:
- TestEth66EmptyMessages extended to cover the new packets at nil and empty-slice
- TestBlockAccessListsPacket66RoundTrip — new table-driven round-trip covering
nil, empty, single-hash/single-BAL, and multi-entry mixed responses including
the 0xc0 "not available / genuinely empty" case the EIP treats specially
- TestEth71ProtocolRegistration — asserts ProtocolToString / ProtocolLengths /
ToProto / FromProto entries are present and correctly mapped
- docs/plans/eip-8159-eth71-bal-exchange.md: plan refinements captured from
review feedback:
- validation runs in the p2p layer (not a higher-layer callback), matching
the bodies/receipts validation pattern
- explicit empty-RLP ambiguity documentation (0xc0 = "not available" OR
"genuinely empty BAL" — disambiguated only via the expected header hash)
- bad-peer management split into two penalty tracks: garbage/wrong-hash
(immediate disconnect) and silent-withholding (per-peer score, ban after
N confirmed withholdings in a rolling window)
No consumer-side fetcher yet — the wire-protocol substrate is in place but
nothing requests or validates BALs over the wire. Phase 3 adds the server-side
answer handler; Phase 4 adds sentry dispatch; Phase 5 adds the client-side
fetcher with the peer-scoring described in the plan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 24, 2026
yperbasis
approved these changes
Apr 24, 2026
yperbasis
left a comment
Member
There was a problem hiding this comment.
So this implements eth/71 for the bal-devnet-3 spec (prior to ethereum/EIPs#11553).
Sahil-4555
pushed a commit
to Sahil-4555/erigon
that referenced
this pull request
Apr 27, 2026
…#20793) ## Summary First of three stacked PRs implementing [EIP-8159](https://eips.ethereum.org/EIPS/eip-8159) — the eth/71 Block Access List exchange protocol. This PR lays the wire-protocol substrate: constants, message-code numbering, packet types, protobuf enum, and a round-trip encode/decode test. No peer-level logic yet. Follows the implementation plan at [docs/plans/eip-8159-eth71-bal-exchange.md](docs/plans/eip-8159-eth71-bal-exchange.md) (added in the first commit). ### What lands - `eth/71` added to `ProtocolToString` and `ProtocolLengths` with length 20. - Message codes `GetBlockAccessListsMsg = 0x12`, `BlockAccessListsMsg = 0x13`. - Request-id-wrapped packet types `GetBlockAccessListsPacket66` and `BlockAccessListsPacket66` (`[]common.Hash` in, `[]rlp.RawValue` out — the on-disk BAL bytes are already RLP). - `ToProto` / `FromProto` entries for `ETH71` covering all existing eth/70 codes plus the two new ones. - `sentry.proto` gains `GET_BLOCK_ACCESS_LISTS_71 = 42` and `BLOCK_ACCESS_LISTS_71 = 43`, with regenerated gRPC bindings. - `TestBlockAccessListsPacket66RoundTrip` — RLP round-trip for nil / empty / populated / oversized hash lists. ### What's NOT here No handler (PR 2), no sentry dispatch (PR 2), no fetcher (PR 3). Sending a `GetBlockAccessLists` message against this branch alone produces a protocol-level NACK. ## Stack 1. **This PR** — wire protocol constants + packet types. 2. #TBD (handler + sentry) — depends on this one. 3. #TBD (fetcher + downloader + devnet skill) — depends on 2. ## Test plan - [x] `go test -short ./p2p/protocols/eth/...` - [x] `make lint` (0 issues) - [x] `make erigon integration` - [ ] Downstream stacks (PR 2, PR 3) build and test cleanly on top. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sahil-4555
pushed a commit
to Sahil-4555/erigon
that referenced
this pull request
Apr 27, 2026
…#20793) ## Summary First of three stacked PRs implementing [EIP-8159](https://eips.ethereum.org/EIPS/eip-8159) — the eth/71 Block Access List exchange protocol. This PR lays the wire-protocol substrate: constants, message-code numbering, packet types, protobuf enum, and a round-trip encode/decode test. No peer-level logic yet. Follows the implementation plan at [docs/plans/eip-8159-eth71-bal-exchange.md](docs/plans/eip-8159-eth71-bal-exchange.md) (added in the first commit). ### What lands - `eth/71` added to `ProtocolToString` and `ProtocolLengths` with length 20. - Message codes `GetBlockAccessListsMsg = 0x12`, `BlockAccessListsMsg = 0x13`. - Request-id-wrapped packet types `GetBlockAccessListsPacket66` and `BlockAccessListsPacket66` (`[]common.Hash` in, `[]rlp.RawValue` out — the on-disk BAL bytes are already RLP). - `ToProto` / `FromProto` entries for `ETH71` covering all existing eth/70 codes plus the two new ones. - `sentry.proto` gains `GET_BLOCK_ACCESS_LISTS_71 = 42` and `BLOCK_ACCESS_LISTS_71 = 43`, with regenerated gRPC bindings. - `TestBlockAccessListsPacket66RoundTrip` — RLP round-trip for nil / empty / populated / oversized hash lists. ### What's NOT here No handler (PR 2), no sentry dispatch (PR 2), no fetcher (PR 3). Sending a `GetBlockAccessLists` message against this branch alone produces a protocol-level NACK. ## Stack 1. **This PR** — wire protocol constants + packet types. 2. #TBD (handler + sentry) — depends on this one. 3. #TBD (fetcher + downloader + devnet skill) — depends on 2. ## Test plan - [x] `go test -short ./p2p/protocols/eth/...` - [x] `make lint` (0 issues) - [x] `make erigon integration` - [ ] Downstream stacks (PR 2, PR 3) build and test cleanly on top. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AskAlexSharov
pushed a commit
to Sahil-4555/erigon
that referenced
this pull request
Apr 28, 2026
…tch (PR 2/3) (erigontech#20794) ## Summary Second of three stacked PRs implementing [EIP-8159](https://eips.ethereum.org/EIPS/eip-8159). Adds the server-side answer handler and wires eth/71 message dispatch into the sentry. **Depends on erigontech#20793** — review/merge that one first. ### What lands - `AnswerGetBlockAccessListsQuery` in [p2p/protocols/eth/handlers.go](p2p/protocols/eth/handlers.go): - Iterates request hashes, resolves block number via `HeaderReader.HeaderNumber`. - Calls `rawdb.ReadBlockAccessListBytes` and appends RLP to response. - Returns empty RLP list (`0xc0`) for any hash not in local rawdb — EIP-8159's "not available" signal. - Enforces a soft-size limit (default 2 MiB per EIP recommendation) by truncating the response rather than padding. - Sentry dispatch in `sentry_grpc_server.go` for the two new message codes. - `libsentry/protocol.go` — `ETH71` added to `ethProtocolsByVersion`, `ProtoIds` whitelist extended; `MinProtocol(GET_BLOCK_ACCESS_LISTS_71)` returns `ETH71` so only eth/71 peers are queried. - Tests in [p2p/protocols/eth/handlers_test.go](p2p/protocols/eth/handlers_test.go): - `TestAnswerGetBlockAccessListsQuery_OrderedResponseWithMissing` — asserts positional ordering, plus unknown-block and known-block-no-BAL both return `0xc0` in the correct slot. - `TestAnswerGetBlockAccessListsQuery_SoftSizeLimit` — seeds 5 oversized BALs, asserts truncation (no partial payloads in the response). ### What's NOT here No consumer-side fetcher yet — peers that speak eth/71 can answer our queries, but we don't send any. That's PR 3. ## Stack 1. erigontech#20793 — wire protocol constants + packet types. 2. **This PR** — handler + sentry dispatch. 3. #TBD (fetcher + downloader + devnet skill) — depends on this one. ## Test plan - [x] `go test -short ./p2p/protocols/eth/... ./p2p/sentry/...` - [x] `make lint` (0 issues) - [x] `make erigon integration` - [ ] PR 3 builds and tests cleanly on top. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lupin012
pushed a commit
that referenced
this pull request
May 2, 2026
## Summary First of three stacked PRs implementing [EIP-8159](https://eips.ethereum.org/EIPS/eip-8159) — the eth/71 Block Access List exchange protocol. This PR lays the wire-protocol substrate: constants, message-code numbering, packet types, protobuf enum, and a round-trip encode/decode test. No peer-level logic yet. Follows the implementation plan at [docs/plans/eip-8159-eth71-bal-exchange.md](docs/plans/eip-8159-eth71-bal-exchange.md) (added in the first commit). ### What lands - `eth/71` added to `ProtocolToString` and `ProtocolLengths` with length 20. - Message codes `GetBlockAccessListsMsg = 0x12`, `BlockAccessListsMsg = 0x13`. - Request-id-wrapped packet types `GetBlockAccessListsPacket66` and `BlockAccessListsPacket66` (`[]common.Hash` in, `[]rlp.RawValue` out — the on-disk BAL bytes are already RLP). - `ToProto` / `FromProto` entries for `ETH71` covering all existing eth/70 codes plus the two new ones. - `sentry.proto` gains `GET_BLOCK_ACCESS_LISTS_71 = 42` and `BLOCK_ACCESS_LISTS_71 = 43`, with regenerated gRPC bindings. - `TestBlockAccessListsPacket66RoundTrip` — RLP round-trip for nil / empty / populated / oversized hash lists. ### What's NOT here No handler (PR 2), no sentry dispatch (PR 2), no fetcher (PR 3). Sending a `GetBlockAccessLists` message against this branch alone produces a protocol-level NACK. ## Stack 1. **This PR** — wire protocol constants + packet types. 2. #TBD (handler + sentry) — depends on this one. 3. #TBD (fetcher + downloader + devnet skill) — depends on 2. ## Test plan - [x] `go test -short ./p2p/protocols/eth/...` - [x] `make lint` (0 issues) - [x] `make erigon integration` - [ ] Downstream stacks (PR 2, PR 3) build and test cleanly on top. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lupin012
pushed a commit
that referenced
this pull request
May 2, 2026
…tch (PR 2/3) (#20794) ## Summary Second of three stacked PRs implementing [EIP-8159](https://eips.ethereum.org/EIPS/eip-8159). Adds the server-side answer handler and wires eth/71 message dispatch into the sentry. **Depends on #20793** — review/merge that one first. ### What lands - `AnswerGetBlockAccessListsQuery` in [p2p/protocols/eth/handlers.go](p2p/protocols/eth/handlers.go): - Iterates request hashes, resolves block number via `HeaderReader.HeaderNumber`. - Calls `rawdb.ReadBlockAccessListBytes` and appends RLP to response. - Returns empty RLP list (`0xc0`) for any hash not in local rawdb — EIP-8159's "not available" signal. - Enforces a soft-size limit (default 2 MiB per EIP recommendation) by truncating the response rather than padding. - Sentry dispatch in `sentry_grpc_server.go` for the two new message codes. - `libsentry/protocol.go` — `ETH71` added to `ethProtocolsByVersion`, `ProtoIds` whitelist extended; `MinProtocol(GET_BLOCK_ACCESS_LISTS_71)` returns `ETH71` so only eth/71 peers are queried. - Tests in [p2p/protocols/eth/handlers_test.go](p2p/protocols/eth/handlers_test.go): - `TestAnswerGetBlockAccessListsQuery_OrderedResponseWithMissing` — asserts positional ordering, plus unknown-block and known-block-no-BAL both return `0xc0` in the correct slot. - `TestAnswerGetBlockAccessListsQuery_SoftSizeLimit` — seeds 5 oversized BALs, asserts truncation (no partial payloads in the response). ### What's NOT here No consumer-side fetcher yet — peers that speak eth/71 can answer our queries, but we don't send any. That's PR 3. ## Stack 1. #20793 — wire protocol constants + packet types. 2. **This PR** — handler + sentry dispatch. 3. #TBD (fetcher + downloader + devnet skill) — depends on this one. ## Test plan - [x] `go test -short ./p2p/protocols/eth/... ./p2p/sentry/...` - [x] `make lint` (0 issues) - [x] `make erigon integration` - [ ] PR 3 builds and tests cleanly on top. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pull Bot
pushed a commit
to Dustin4444/erigon
that referenced
this pull request
May 5, 2026
…ader (PR 3/3) (erigontech#20795) ## Summary Third of three stacked PRs implementing [EIP-8159](https://eips.ethereum.org/EIPS/eip-8159). Adds the consumer-side `BALFetcher` primitive, a background `BALDownloader` that wires the fetcher into the node start path, and enables eth/71 in the default protocol-version list. Also ships a companion devnet-launch skill so bal-devnet-3 reproducers are reusable. **Depends on erigontech#20794** — review/merge that one first. ### What lands - `BALFetcher` in `p2p/sentry/sentry_multi_client/bal_fetcher.go`: - Hash-mismatch → `Sentry.PenalizePeer(Kick)`. Garbage or wrong-hash payloads never cross the p2p boundary. - Disambiguates empty-RLP (`0xc0`): accepted only when `expected_hash == empty.BlockAccessListHash`, treated as "peer has nothing" otherwise. - Writes validated BALs via `rawdb.WriteBlockAccessListBytes`. - `BALDownloader` in `p2p/sentry/sentry_multi_client/bal_downloader.go`: periodic scan for blocks whose header has a `BlockAccessListHash` and no local BAL entry; dispatches batches via the fetcher. - `node/eth/backend.go` spawns the downloader at startup. Always-on, negotiation-driven — silent no-op if no peer advertises eth/71. - `node/nodecfg` adds `ETH71` to the default P2P protocol version list so erigon advertises eth/71 in its handshake. - `.claude/skills/launch-bal-devnet-3/SKILL.md` — companion skill for launching erigon + Lighthouse on the bal-devnet-3 ethpandaops devnet (parallels the existing `launch-bal-devnet-2`). ### Deferred follow-ups - **Silent-withholding peer scoring** (the Phase 5b.2 plan item) is explicitly not in this PR. See the comment at [bal_fetcher.go:89](https://github.com/erigontech/erigon/blob/feat/eip-8159/fetcher-downloader/p2p/sentry/sentry_multi_client/bal_fetcher.go#L89) — a per-peer score for repeated `0xc0` replies to non-empty expected hashes will build on top of this primitive. Will land as a follow-up once the substrate is reviewed. ### Testing limitations End-to-end verification on bal-devnet-3 is currently blocked by an **unrelated** execution bug at block 503 (EIP-8037 state-gas accounting, tracked in erigontech#20791). Reproduces deterministically on `main` with a fresh datadir and is not caused by anything in these PRs. When bal-devnet-4 goes live (currently no genesis/bootnodes yet), we'll re-run the end-to-end check there. Local test coverage: - [x] `go test -short ./p2p/...` (includes `TestBlockAccessListsPacket66RoundTrip`, `TestAnswerGetBlockAccessListsQuery_OrderedResponseWithMissing`, `TestAnswerGetBlockAccessListsQuery_SoftSizeLimit`, plus `bal_fetcher_test.go`) - [x] `make lint` (0 issues, 2× determinism pass) - [x] `make erigon integration` ## Stack 1. erigontech#20793 — wire protocol constants + packet types. 2. erigontech#20794 — handler + sentry dispatch. 3. **This PR** — fetcher + background downloader + default protocol version + devnet-3 skill. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
mh0lt
added a commit
that referenced
this pull request
May 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First of three stacked PRs implementing EIP-8159 — the eth/71 Block Access List exchange protocol. This PR lays the wire-protocol substrate: constants, message-code numbering, packet types, protobuf enum, and a round-trip encode/decode test. No peer-level logic yet.
Follows the implementation plan at docs/plans/eip-8159-eth71-bal-exchange.md (added in the first commit).
What lands
eth/71added toProtocolToStringandProtocolLengthswith length 20.GetBlockAccessListsMsg = 0x12,BlockAccessListsMsg = 0x13.GetBlockAccessListsPacket66andBlockAccessListsPacket66([]common.Hashin,[]rlp.RawValueout — the on-disk BAL bytes are already RLP).ToProto/FromProtoentries forETH71covering all existing eth/70 codes plus the two new ones.sentry.protogainsGET_BLOCK_ACCESS_LISTS_71 = 42andBLOCK_ACCESS_LISTS_71 = 43, with regenerated gRPC bindings.TestBlockAccessListsPacket66RoundTrip— RLP round-trip for nil / empty / populated / oversized hash lists.What's NOT here
No handler (PR 2), no sentry dispatch (PR 2), no fetcher (PR 3). Sending a
GetBlockAccessListsmessage against this branch alone produces a protocol-level NACK.Stack
Test plan
go test -short ./p2p/protocols/eth/...make lint(0 issues)make erigon integration