EIP-7928: block-level access lists - #2875
Open
anvacaru wants to merge 8 commits into
Open
Conversation
…primitives, schedule flag Introduce the EIP-7928 Block-Level Access List infrastructure with no behavior change: nothing is journaled or validated yet. - schedule.md: add the Ghaseip7928 flag (DEFAULT false, AMSTERDAM true) and the Gbalitemcost constant (DEFAULT 0, AMSTERDAM 2000). - evm.md: add the block-lifetime <blockAccessLists> cell group (index, touched set, reads, per-phase capture maps, accumulated change maps), the balE/balCE journal entries, #balTouch/#balRead/#balCapture* hooks, the per-phase #balIncorporate workers with total post-lookups, the #balAppend* / #balSortInts helpers, and a skip-only #validateBlockAccessList shell. Reset the cells in #startBlock. - state-utils.md: reset the cells in clearBLOCK next to <balHash>. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wire the EIP-7928 capture/read/touch hooks into every state-mutation and account-access site, plus the per-phase incorporate points and block-access index lifecycle. Validation is still off (the #validateBlockAccessList shell remains a no-op), so all fixtures are unchanged. - evm.md: capture balance in #transferFunds and the Amsterdam #finalizeTx refund/credit and #finalizeWithdrawals; capture nonce in #incrementNonce, #mkCreate, loadTx; capture code in #finishCodeDeposit and the EIP-8246 #deleteAccounts reset; capture storage plus implicit read in SSTORE and the beacon-root / block-hash-history writes; read in SLOAD; touch in BALANCE / EXTCODE* / CALL-family / delegated-designation / CREATE / CREATE2 / SELFDESTRUCT beneficiary / #systemCall. Append #balIncorporate to #startBlock (idx 0) and #finalizeTx(true) (per-tx idx); bump <balIndex> to N+1 in #finalizeBlock. - driver.md: capture sender balance/nonce and touch sender+recipient in both loadTx rules; capture blob-fee balance debit; bump <balIndex> per tx in startTx; touch the 7702 authority and capture its code/nonce on the Amsterdam #setDelegation / #addAuthority success paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…zeBlock Turn on EIP-7928 validation. #validateBlockAccessList (injected into #finalizeBlock between #processGeneralPurposeRequests and #finalizeBlockBlobs) flushes the N+1 phase via #balIncorporate, reconstructs the canonical BAL as a JSON value from the accumulated cells, keccak256-hashes its RLP encoding, and enforces both the bal_items gas-limit budget and the header blockAccessListHash. - Address universe = balTouched ∪ keys(reads) ∪ keys(change maps), sorted by #balSortInts; per account the JSON is [addr, [slotChanges], [reads], [balanceChanges], [nonceChanges], [codeChanges]] with reads filtered to slots without a surviving storage change. - #balCheckItems enforces bal_items <= gasLimit / Gbalitemcost; #checkBalHash mirrors #checkRequestsRoot, setting EVMC_INVALID_BLOCK on mismatch. - Validation is gated on Ghaseip7928, a nonzero <balHash>, and a non-INVALID_BLOCK status, so pre-Amsterdam and transition-fork blocks are unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…BlobGas Both loadTx paths run #balCaptureBalance on the sender before #deductBlobGas, and #balCaptureBalance is first-write-wins, so the capture here was always discarded. Blob transactions are the only ones reaching the rule; full test_bchain still 11650/0/14. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit 8a1fc12b1ae5a4342d094984c6639f93934bc756)
#validateBlockAccessList only ran when the last transaction's status was SUCCESS/REVERT/none, so a block whose final transaction halted exceptionally never checked blockAccessListHash and accepted any BAL. Exclude only EVMC_INVALID_BLOCK, matching EELS, which validates the header unconditionally on otherwise-valid blocks. Depends on the matching #processGeneralPurposeRequests guard change (system-contract-hardening): without it a block ending in an exceptional transaction skips the post-execution system calls, so the computed BAL would be missing their index n+1 entries and the hash check would falsely reject. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Implements EIP-7928: the block-level access list is journaled during execution, built and RLP-encoded at #finalizeBlock, and validated against the header's blockAccessListHash (keccak256 of the RLP encoding).
Changes:
<blockAccessLists>cells and journal primitives (#balTouch,#balRead,#balCapture*), plus theGhaseip7928flag andGbalitemcost(2000) schedule constants.BALANCE/EXTCODE*,CALL*,CREATE*,SELFDESTRUCT,SLOAD/SSTORE, transaction setup, EIP-7702 authorities, withdrawals, and the pre/post-block system calls.#balIncorporatediffs them against the post-state at transaction end. Changes made in reverted frames drop out on their own, and no-op writes (SSTOREof the same value, EIP-7702 re-delegation to the same target) produce no entry.#balIncorporateruns at each boundary owning aBlockAccessIndex: 0 after the pre-block system calls, 1..n per transaction, n+1 after withdrawals and the post-block system calls.SLOADand no-opSSTOREslots go tostorage_reads, and any slot with a recorded change is filtered out of the reads when the list is built.#validateBlockAccessListbuilds the canonical list (addresses and slots sorted, entries in index order), RLP-encodes it, and compares itskeccakagainst the headerblockAccessListHash; it also rejects blocks whose item count exceedsgasLimit / ITEM_COST. The BAL carried in the block body is not consumed.SYSTEM_ADDRESS, and precompiles warmed at transaction start, as only actual accesses are recorded.