Skip to content

p2p/protocols/eth: EIP-8159 eth/71 wire protocol (PR 1/3)#20793

Merged
mh0lt merged 2 commits into
mainfrom
feat/eip-8159/wire-protocol
Apr 26, 2026
Merged

p2p/protocols/eth: EIP-8159 eth/71 wire protocol (PR 1/3)#20793
mh0lt merged 2 commits into
mainfrom
feat/eip-8159/wire-protocol

Conversation

@mh0lt

@mh0lt mh0lt commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

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/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

  • go test -short ./p2p/protocols/eth/...
  • make lint (0 issues)
  • make erigon integration
  • Downstream stacks (PR 2, PR 3) build and test cleanly on top.

mh0lt and others added 2 commits April 24, 2026 12:32
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>

@yperbasis yperbasis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this implements eth/71 for the bal-devnet-3 spec (prior to ethereum/EIPs#11553).

@mh0lt mh0lt added this pull request to the merge queue Apr 26, 2026
Merged via the queue into main with commit 0f080eb Apr 26, 2026
38 checks passed
@mh0lt mh0lt deleted the feat/eip-8159/wire-protocol branch April 26, 2026 11:51
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
…) (#20880)

Cherry-pick of #20793 onto bal-devnet-3. Stacked on top of #20879
(devp2p fixes). Bottom of the eth/71 cherry-pick stack.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Glamsterdam https://eips.ethereum.org/EIPS/eip-7773 Networking

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants