Abstract
Replace repeated 20-byte addresses and 32-byte storage keys in EIP-7928 Block Access Lists (BALs) with compact references into one of the last eight canonical ancestor BALs. Expected reduction in BAL size is approximately 30–50%, depending on cross-block reuse.
Motivation
A large share of BAL bytes are addresses and storage keys that already appeared in a recent block. Referencing the prior position is shorter than re-emitting the literal.
Specification
The key words "MUST", "MUST NOT", "SHOULD", and "MAY" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Types
AddressKey = Address | AccountRef
StorageKeyRef = StorageKey | SlotRef
AccountRef = [ancestor_offset: uint8, account_index: uint32]
SlotRef = [ancestor_offset: uint8, account_index: uint32, slot_index: uint32]ancestor_offset ∈ [0..7], where 0 is the parent block, 1 the grandparent, and so on up to 7 (the 8th ancestor).
AccountRef MUST be an RLP list of length 2. SlotRef MUST be an RLP list of length 3.
References and literals are disambiguated by RLP type: an Address is a 20-byte string and an AccountRef is a list; a StorageKey is an RLP-encoded 32-byte value and a SlotRef is a list.
Modified Structures
The EIP-7928 structures are amended to accept references:
SlotChanges = [StorageKeyRef, List[StorageChange]]
AccountChanges = [AddressKey, List[SlotChanges], List[StorageKeyRef],
List[BalanceChange], List[NonceChange], List[CodeChange]]
BlockAccessList = List[AccountChanges]All other EIP-7928 fields and semantics are unchanged.
Reference Targets
A reference target is the expanded view of a canonical ancestor BAL: the literal-only BlockAccessList that has already passed EIP-7928 validation, with all of this EIP's references resolved. References MUST NOT target encoded ancestor BALs. References MUST NOT target the current block.
For an expanded ancestor BAL:
account_indexis the position in the BAL, which EIP-7928 already requires to be sorted lexicographically by address.slot_indexis the position in the account's canonical slot dictionary: the lexicographically sorted union of the storage keys appearing in the account'sstorage_changesandstorage_reads, with duplicates removed.
This EIP does not redefine ancestor BAL ordering beyond defining the per-account slot dictionary used for slot_index lookup.
Clients MUST retain or reconstruct expanded views and their per-account slot dictionaries for the last eight post-activation canonical blocks.
Canonical Encoding
The targeted ancestor of a reference is the block at height block_number(B) - ancestor_offset - 1.
For any literal Address or StorageKey in the current BAL B, a valid reference is any AccountRef or SlotRef with ancestor_offset ∈ [0..7] that resolves to the same value against an expanded ancestor view available among the last eight canonical post-activation ancestor BALs. If multiple references resolve to the same literal value, all are valid candidates.
The canonical order over valid references is:
- For
AccountRef: smallest(ancestor_offset, account_index). - For
SlotRef: smallest(ancestor_offset, account_index, slot_index).
A literal MUST NOT be used if a valid reference exists. The encoding MUST use the smallest valid reference under the canonical order.
Validation
For a block with BlockAccessList B:
- Reject any reference with
ancestor_offset ∉ [0..7]. - Reject any reference whose targeted ancestor (
block_number(B) - ancestor_offset - 1) is< 0or<activation height. - Reject any
AccountRefwhoseaccount_indexis out of bounds in the targeted ancestor. - Reject any
SlotRefwhoseaccount_indexorslot_indexis out of bounds in the targeted ancestor. - Resolve each
AccountRefandSlotRefagainst the cached expanded view of the corresponding ancestor and replace it inBwith its resolved literal to obtain the expandedB'. - Apply EIP-7928 validation to
B'. - Reject
Bif any literalAddressorStorageKeyin it has a valid reference in the last eight expanded ancestor views. - Reject
Bif any reference is not the smallest valid reference under the canonical order defined above.
Activation
References to blocks prior to activation are invalid. References are only valid if the targeted ancestor lies within the last eight canonical post-activation blocks.
Size Constraint
The bal_items count from EIP-7928 is computed on the expanded BAL.
Rationale
Encoding Savings
Address 20 bytes → AccountRef ≈ 5 bytes (1 + 4)
StorageKey 32 bytes → SlotRef ≈ 9 bytes (1 + 4 + 4)Window of Eight
Eight blocks bounds the ancestor state held for validation while capturing most cross-block reuse, and fits ancestor_offset in 3 bits.
Canonical Encoding Rule
Forcing the smallest valid reference makes the encoded BAL a function of the block and its ancestors only, preventing producers from bloating the encoding by choosing literals or larger offsets.
Backwards Compatibility
Hard fork. Pre-activation BALs are unreachable from references and remain valid in their original literal form.
Test Cases
TBD
Security Considerations
Validation requires retaining eight expanded ancestor BAL views and their per-account slot dictionaries. Reference resolution is then a bounded array lookup, with no recursion, bounding DoS risk. The EIP-7928 bal_items budget continues to bound the expanded size.
A reorg invalidates blocks whose references no longer resolve under the new canonical chain, consistent with normal handling of block-bound data.
Copyright
Copyright and related rights waived via CC0.
