This EIP modifies the 'eth' p2p protocol to support Block-level Access Lists (BALs). It adds two new messages, GetBlockAccessLists (0x12) and BlockAccessLists (0x13), enabling peers to request and serve BALs for synchronization and parallel execution.
EIP-7928 introduces block-level access lists that record all state locations accessed during block execution. These lists enable parallel disk reads, parallel transaction execution, and executionless state updates.
For syncing clients to leverage these capabilities, BALs must be obtainable from peers. The Engine API provides BALs from the consensus layer during normal operation, but historical BALs and peer-based sync require wire protocol support.
The block header is extended with a new field after requests-hash:
block-header = [
...
requests-hash: B_32,
block-access-list-hash: B_32,
]
The block-access-list-hash field contains keccak256(rlp.encode(block-access-list)) as defined in EIP-7928. This field MUST be present in headers after the Amsterdam fork and absent for earlier blocks.
BALs are RLP-encoded as a list of account changes, sorted lexicographically by address:
block-access-list = [account-changes₁, account-changes₂, ...]
account-changes = [
address: B_20,
storage-changes,
storage-reads,
balance-changes,
nonce-changes,
code-changes,
]
storage-changes = [slot-changes₁, slot-changes₂, ...]
slot-changes = [slot: B_32, [storage-change₁, storage-change₂, ...]]
storage-change = [block-access-index: P, value: B_32]
storage-reads = [slot₁: B_32, slot₂: B_32, ...]
balance-changes = [balance-change₁, balance-change₂, ...]
balance-change = [block-access-index: P, balance: P]
nonce-changes = [nonce-change₁, nonce-change₂, ...]
nonce-change = [block-access-index: P, nonce: P]
code-changes = [code-change₁, code-change₂, ...]
code-change = [block-access-index: P, code: B]
storage-changes MUST be sorted lexicographically by slot. Changes within each slot MUST be sorted by block-access-index ascending. storage-reads MUST be sorted lexicographically by slot.
Where block-access-index indicates when the change occurred:
0 for pre-execution system contract calls1...n for transactions (in block order)n+1 for post-execution system contract calls and withdrawalsSee EIP-7928 for complete BAL generation rules and inclusion semantics.
[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]
Request BALs for the given block hashes. The number of BALs that can be requested in a single message is subject to implementation-defined limits.
BALs are only available for blocks after EIP-7928 activation and within the retention period defined therein. Requests for unavailable BALs return empty entries.
[request-id: P, [block-access-list₁, block-access-list₂, ...]]
Response to GetBlockAccessLists. Each element corresponds to a block hash from the request, in order. Empty BALs (RLP-encoded empty list 0xc0) are returned for blocks where the BAL is unavailable.
The recommended soft limit for BlockAccessLists responses is 10 MiB.
When a BAL is received, clients MUST validate it by computing keccak256(rlp.encode(bal)) and comparing against the block-access-list-hash in the corresponding block header.
BALs are transmitted via dedicated messages rather than extending block bodies because:
Message IDs 0x12 and 0x13 follow sequentially from the existing eth/69 messages (BlockRangeUpdate is 0x11).
The 10 MiB soft limit aligns with existing protocol conventions and accommodates multiple BALs per response while remaining within typical message size constraints.
This EIP changes the eth protocol and requires rolling out a new version, eth/71. Supporting multiple protocol versions is standard practice. Rolling out eth/71 does not break older clients, as they can continue using eth/69 or eth/70.
This EIP requires the Amsterdam hard fork for the header field extension. The new messages are only meaningful for post-Amsterdam blocks.
BAL validation requires computing a keccak256 hash of the RLP-encoded list. For typical BALs (~70 KiB), this is negligible. For worst-case BALs at high gas limits, validation remains bounded by the block gas limit.
A GetBlockAccessLists request can trigger responses larger than the request. Implementations SHOULD apply rate limiting and respect the soft response size limit to prevent amplification attacks.
Clients MUST handle empty responses gracefully. A peer returning empty entries for available blocks may be misbehaving but could also have pruned the data legitimately.
Copyright and related rights waived via CC0.