This EIP removes the block access list (BAL) introduced in EIP-7928 from the execution payload and propagates it as an independent sidecar on a dedicated gossip topic. Builders commit to the BAL by including keccak256(rlp(BAL)), the same value written to the execution block header, in the ExecutionPayloadBid.
Since a BAL is roughly the size of the payload, this halves the block on the critical propagation path and separates state diffs from the transactions. Delivering the BAL ahead of the payload gives execution clients a guaranteed window to prefetch state and begin post-state root computation before execution starts, and lets EIP-7805 inclusion list builders advance their state view past the current block.
Motivation
EIP-7928 adds the BAL to the ExecutionPayload, which under EIP-7732 travels in a SignedExecutionPayloadEnvelope that the builder reveals during the slot. The BAL therefore arrives with the transactions, on the same topic and under the same deadline.
Propagating it as an independent sidecar has four benefits:
Separation of concerns: The BAL is a state diff, the payload is the set of transactions that produced it. Nodes that only advance state, such as clients syncing without re-execution, need the diff and not the transactions.
Block size on the critical path: A full BAL is roughly the size of the rest of the compressed block, ~72.4 KiB against ~71.7 KiB in the size analysis at a 60M gas limit. Removing it from the envelope halves object sizes, allowing lower networking caps as DoS protection.
Earlier BAL delivery: Inside the envelope, the BAL cannot be used before the payload arrives. With an earlier observation deadline, it precedes the payload by at least one second, enforced by the Payload Timeliness Committee (PTC), so execution clients enter execution with the declared state prefetched and the post-state root under way.
Better inclusion lists: The EIP-7805 inclusion list committee of slot N freezes its lists before slot N’s payload is revealed, and may list transactions that the block already includes or invalidates. An early BAL provides the post-values of every account block N touches, so inclusion list builders can advance their state view without executing the payload.
Specification
Execution Layer
BAL construction, validation and the block_access_list_hash header field remain as specified in EIP-7928. Only delivery changes: the BAL reaches the execution layer through a dedicated engine method instead of inside the payload.
Epochs for which sidecars must be served, matching the BAL retention window of EIP-7928
BLOCK_ACCESS_LIST_LEAD_TIME
uint64(1)
Seconds a sidecar must precede the payload attestation deadline to count as available
Types
Name
SSZ equivalent
Description
BlockAccessList
ByteList[MAX_BLOCK_ACCESS_LIST_SIZE]
RLP-encoded block access list, opaque to the consensus layer
Containers
ExecutionPayload
The block_access_list field added by EIP-7928 is removed:
classExecutionPayload(Container):# ... fields unchanged from EIP-7732 ...
blob_gas_used:uint64excess_blob_gas:uint64# [Removed in EIP-8146]
# block_access_list: BlockAccessList
ExecutionPayloadBid
classExecutionPayloadBid(Container):parent_block_hash:Hash32parent_block_root:Rootblock_hash:Hash32prev_randao:Bytes32fee_recipient:ExecutionAddressgas_limit:uint64builder_index:BuilderIndexslot:Slotvalue:Gweiexecution_payment:Gweiblob_kzg_commitments:List[KZGCommitment,MAX_BLOB_COMMITMENTS_PER_BLOCK]# [New in EIP-8146]
block_access_list_hash:Bytes32
block_access_list_hash is keccak256(rlp(BlockAccessList)), the value the execution block header carries under EIP-7928.
PayloadAttestationData
classPayloadAttestationData(Container):beacon_block_root:Rootslot:Slotpayload_present:booleanblob_data_available:boolean# [New in EIP-8146]
block_access_list_present:boolean
@dataclassclassStore(object):# ... existing fields ...
# [New in EIP-8146]
block_access_lists:Dict[Root,BlockAccessList]=field(default_factory=dict)block_access_list_availability_vote:Dict[Root,List[Optional[boolean]]]=field(default_factory=dict)
on_block
Alongside the existing ptc_vote initialization:
# [New in EIP-8146]
store.block_access_list_availability_vote[block_root]=[None]*PTC_SIZE
on_payload_attestation_message
Alongside the existing payload_present recording:
# [New in EIP-8146]
store.block_access_list_availability_vote[data.beacon_block_root][ptc_index]=(data.block_access_list_present)
notify_ptc_messages propagates block_access_list_present when extracting PayloadAttestationMessage objects from the aggregates in a beacon block.
on_block_access_list_sidecar
Called for each sidecar that passes gossip validation:
defon_block_access_list_sidecar(store:Store,sidecar:BlockAccessListSidecar)->None:assertsidecar.beacon_block_rootinstore.blocksblock=store.blocks[sidecar.beacon_block_root]assertsidecar.slot==block.slot# The consensus layer treats the BAL as opaque bytes; no RLP decoding
bid=block.body.signed_execution_payload_bid.messageassertkeccak256(sidecar.block_access_list)==bid.block_access_list_hashstore.block_access_lists[sidecar.beacon_block_root]=sidecar.block_access_list# Deliver to the execution layer without waiting for the payload
EXECUTION_ENGINE.notify_block_access_list(sidecar.block_access_list,bid.block_hash)
on_execution_payload_envelope
The payload MUST NOT be passed to the execution layer before the BAL of the same block:
defon_execution_payload_envelope(store:Store,signed_envelope:SignedExecutionPayloadEnvelope)->None:envelope=signed_envelope.messageassertenvelope.beacon_block_rootinstore.block_statesassertis_data_available(envelope.beacon_block_root)# [New in EIP-8146] The BAL must be available locally
assertenvelope.beacon_block_rootinstore.block_access_listsstate=store.block_states[envelope.beacon_block_root]verify_execution_payload_envelope(state,signed_envelope,EXECUTION_ENGINE)store.payloads[envelope.beacon_block_root]=envelope
verify_execution_payload_envelope is unchanged. An envelope that arrives before its sidecar MUST NOT be dropped: the client caches it and runs this handler again once on_block_access_list_sidecar has stored the matching BAL.
Networking
Gossip: block_access_list_sidecar
A new global topic carrying BlockAccessListSidecar objects. The following validations MUST pass before forwarding a sidecar:
[IGNORE]sidecar.slot <= current_slot, allowing for MAXIMUM_GOSSIP_CLOCK_DISPARITY.
Returns the sidecars in slot range [start_slot, start_slot + count), ordered by slot, at most MAX_REQUEST_PAYLOADS entries.
Clients MUST serve sidecars over both methods for the most recent MIN_EPOCHS_FOR_BLOCK_ACCESS_LIST_SIDECARS_REQUESTS epochs and MAY prune older ones.
Validator Duties
Builders
Obtain the payload and the BAL from engine_getPayloadV6.
Set block_access_list_hash = keccak256(blockAccessList) in the ExecutionPayloadBid.
Once the beacon block carrying the bid is published, broadcast the BlockAccessListSidecar on the block_access_list_sidecar topic.
Broadcast the SignedExecutionPayloadEnvelope, which no longer carries the BAL.
Builders SHOULD broadcast the sidecar as early as possible and MUST NOT delay step 3 until the payload envelope is revealed in step 4.
PTC Members
A PTC member sets block_access_list_present = True only if a sidecar for the block passed gossip validation locally at least BLOCK_ACCESS_LIST_LEAD_TIME seconds before the payload attestation deadline. payload_present and blob_data_available are set as specified in EIP-7732, independently of block_access_list_present.
Engine API
The BAL is delivered to the execution layer by a dedicated method, separately from the payload. For a given blockHash, the consensus layer MUST call engine_notifyBlockAccessListV1 before engine_newPayloadV5.
engine_getPayloadV6
Returns blockAccessList, the RLP-encoded BAL, as a top-level field of the response instead of a field of the payload structure.
engine_notifyBlockAccessListV1
Delivers the BAL to the execution layer independently of the payload.
Parameters:
blockAccessList: RLP-encoded BAL bytes.
blockHash: 32 bytes, ties the BAL to a payload.
On receipt, the execution layer:
Stores the BAL under blockHash.
Begins prefetching the accounts and storage slots the BAL declares.
MAY begin computing the post-state root from the BAL’s post-values.
The call is not a validity check; the BAL is validated against the header when the payload is executed. The method acknowledges receipt.
Consensus clients MUST call this method as soon as a sidecar is verified in on_block_access_list_sidecar, without waiting for the payload envelope.
engine_newPayloadV5
The blockAccessList field that EIP-7928 adds to the engine API payload structure is removed; the method is otherwise unchanged. The execution layer pairs the payload with the BAL previously delivered for the same blockHash and validates it as specified in EIP-7928.
Rationale
Header Commitment Reuse
EIP-7928 already commits to the BAL in the execution block header as keccak256(rlp(BAL)). Carrying the same 32 bytes in the bid gives the consensus layer everything it needs to authenticate a sidecar, without a second hashing scheme and without RLP decoding outside the execution layer. A builder cannot equivocate: bid.block_hash transitively commits to the header, so if bid.block_access_list_hash disagrees with the revealed payload, either payload.block_hash != bid.block_hash and the envelope is rejected, or the execution layer recomputes a BAL that does not match its own header and the payload is rejected per EIP-7928.
Removing the BAL from the ExecutionPayload container also removes the need for the hash tree root substitution that EIP-7928 describes for pruned BALs, since sidecar retention no longer affects the payload’s Merkle commitment.
No Sidecar Signature
The builder already signs the bid, and verification is keccak256(sidecar.block_access_list) == bid.block_access_list_hash. A BLS signature on the sidecar would add verification cost without adding binding. This mirrors how blob data is verified against the commitments carried in the bid.
Separate PTC Field
block_access_list_present follows the pattern of blob_data_available. payload_present signals envelope timeliness, blob_data_available signals blob availability, and block_access_list_present signals BAL availability, so a missing object can be attributed to its cause. The vote is a signal; this EIP attaches no penalty to it. Availability is enforced locally, since on_execution_payload_envelope gates on the BAL being present regardless of the PTC outcome.
Publication Timing
In ePBS, builders delay publishing the execution payload envelope until close to the attestation deadline. Releasing it early exposes the transactions to same-slot unbundling, where a malicious proposer inserts adversarial bundles to exploit the builder.
The BAL is not exposed to this risk. It carries access lists and post-state values, not signed transactions. A proposer that receives the BAL early learns which contracts were touched and which balances moved, but to steal the MEV it would risk being slashed.
BLOCK_ACCESS_LIST_LEAD_TIME covers builders that publish late. A BAL that arrives with the payload, or after it, loses the availability vote, which leaves one second as the guaranteed window for prefetching and post-state root computation. Without it, the lead time would depend entirely on builder behaviour.
Dedicated Engine API Method
Delivering the BAL and the payload in separate calls is what creates the lead time:
t0 sidecar received --engine_notifyBlockAccessListV1--> EL prefetches state, MAY start post-state root
t1 envelope received --engine_newPayloadV5-------------> EL executes against warm state
t2 <--------- {status: VALID}--------
t1 - t0 is the head start this EIP creates; with the BAL inside the envelope it is zero. Ordering is the consensus layer’s responsibility: an envelope that arrives first is cached until the sidecar arrives, so the execution layer never receives a payload without its BAL and needs no fallback path.
Sidecar Retention
EIP-7928 requires the execution layer to retain BALs for the weak subjectivity period, so that a node offline for less than that period can sync by re-execution. MIN_EPOCHS_FOR_BLOCK_ACCESS_LIST_SIDECARS_REQUESTS uses the same window, so a node syncing within the weak subjectivity period can obtain BALs from either layer. Beyond it, BALs can be regenerated by executing the block.
Backwards Compatibility
This proposal changes the ExecutionPayload, ExecutionPayloadBid and PayloadAttestationData containers from EIP-7732 and the engine API methods from EIP-7928. These changes are not backwards compatible and require a hard fork. BALs of pre-fork blocks remain inside their execution payloads and stay retrievable as specified in EIP-7928; the sidecar topic and req/resp methods apply from the fork onwards.
Security Considerations
Withholding
A builder can withhold the BAL sidecar. PTC members then vote block_access_list_present = False, making the failure visible network-wide, and no node can validate the payload since on_execution_payload_envelope gates on local BAL availability. A payload that cannot be validated is not built on, so withholding costs the builder its own block. The payment properties from EIP-7732 are unchanged.
Early BAL Exposure
An early sidecar reveals state changes before the transactions that caused them. No independently signed object is exposed, so nothing can be unbundled. What leaks is coarse in-slot activity, and it leaks to parties that observe the same changes in the payload moments later.
Network Overhead
Bytes per slot are unchanged, as the BAL that travelled inside the envelope now travels on its own topic. The load is redistributed across topics and spread over a wider window instead of concentrating between payload reveal and the attestation deadline.
Verification Cost
Sidecar verification requires one keccak256 over at most MAX_BLOCK_ACCESS_LIST_SIZE bytes, which is negligible compared to payload validation. Consensus clients gain a keccak dependency, satisfied by well-tested off-the-shelf libraries.
Unmatched BALs
The execution layer may hold BALs for payloads that never arrive. Implementations SHOULD bound this cache, for example by slot distance or at finalization. Inflow is bounded by the gossip rules to one sidecar per valid beacon block root.