Skip to content

Implement EIP-7928: "Block-Level Access Lists" - #1752

Open
chfast wants to merge 2 commits into
masterfrom
amsterdam/bal
Open

chfast wants to merge 2 commits into
masterfrom
amsterdam/bal

Conversation

@chfast

@chfast chfast commented Oct 7, 2026

Copy link
Copy Markdown
Member

From Amsterdam, build the block access list alongside block execution
and validate it against the header:

  • bal.{hpp,cpp}: the BAL builder — per-address account changes (balance,
    nonce, code) and per-slot storage writes recorded per transaction
    index, storage reads deduplicated across the block, entries ordered
    lexicographically; the keccak256 hash of the RLP-encoded list and the
    item-count-vs-block-gas-limit bound. The withdrawals and the block-end
    system calls share the last index, so their balance changes net out.
  • State-access observation: a StateView decorator records every account
    and storage read. Warming (EIP-2929) is not a read, so it loads
    neither the account nor the slot (State::get_for_access() and the
    loaded flags); they are loaded by the access that follows the gas
    check. SLOAD warming journals only the access-status change
    (JournalStorageAccess), EXTCODECOPY of 0 bytes still reads the code,
    and the delegate address is read once its access cost is committed.
  • Block accounting: the withdrawals are applied before the block-end
    system calls, absent pre-execution system contracts are recorded, and
    the blockchain-test runner checks the BAL hash and the item bound
    against the header.

The second commit runs the Amsterdam blockchain tests of tests@v21.0.0
in CI, which need EIP-7928 to pass.

chfast added 2 commits October 7, 2026 15:21
From Amsterdam, build the block access list alongside block execution and
validate it against the header:

- bal.{hpp,cpp}: the BAL builder — per-address account changes (balance,
  nonce, code) and per-slot storage writes recorded per transaction index,
  storage reads deduplicated across the block, entries ordered
  lexicographically; the keccak256 hash of the RLP-encoded list and the
  item-count-vs-block-gas-limit bound. The withdrawals and the block-end
  system calls share the last index, so their balance changes net out.
- State-access observation: a StateView decorator records every account and
  storage read. Warming (EIP-2929) is not a read, so it loads neither the
  account nor the slot (State::get_for_access() and the loaded flags); they
  are loaded by the access that follows the gas check. SLOAD warming
  journals only the access-status change (JournalStorageAccess), EXTCODECOPY
  of 0 bytes still reads the code, and the delegate address is read once its
  access cost is committed.
- Block accounting: the withdrawals are applied before the block-end system
  calls, absent pre-execution system contracts are recorded, and the
  blockchain-test runner checks the BAL hash and the item bound against the
  header.
Stop ignoring the tests@v21.0.0 Amsterdam blockchain tests, which need
EIP-7928 to pass.
@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.38202% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.12%. Comparing base (39425f3) to head (9f93001).

Files with missing lines Patch % Lines
test/utils/blockchaintest_runner.cpp 78.26% 2 Missing and 3 partials ⚠️
test/state/bal.cpp 94.66% 2 Missing and 2 partials ⚠️
test/state/bal.hpp 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1752      +/-   ##
==========================================
+ Coverage   98.06%   98.12%   +0.05%     
==========================================
  Files         183      185       +2     
  Lines       16940    17076     +136     
  Branches     3873     3908      +35     
==========================================
+ Hits        16613    16755     +142     
+ Misses        245      239       -6     
  Partials       82       82              
Flag Coverage Δ
eest-develop-gmp 25.69% <19.66%> (-0.18%) ⬇️
eest-legacy 16.97% <35.39%> (-0.08%) ⬇️
eest-libsecp256k1 27.86% <19.66%> (-0.19%) ⬇️
eest-stable 84.19% <94.38%> (+0.31%) ⬆️
evmone-unittests 94.02% <75.28%> (-0.23%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
core 96.33% <96.12%> (+0.08%) ⬆️
tooling 94.65% <89.79%> (+0.35%) ⬆️
tests 99.81% <ø> (ø)
Files with missing lines Coverage Δ
lib/evmone/instructions.hpp 100.00% <100.00%> (+0.46%) ⬆️
lib/evmone/instructions_calls.cpp 99.41% <100.00%> (+<0.01%) ⬆️
test/state/account.hpp 100.00% <ø> (ø)
test/state/errors.hpp 91.76% <100.00%> (+0.40%) ⬆️
test/state/host.cpp 100.00% <100.00%> (ø)
test/state/state.cpp 99.56% <100.00%> (+0.44%) ⬆️
test/state/state.hpp 100.00% <100.00%> (ø)
test/state/system_contracts.cpp 100.00% <100.00%> (+3.57%) ⬆️
test/utils/block_transition.cpp 100.00% <100.00%> (ø)
test/utils/blockchaintest_loader.cpp 97.14% <100.00%> (+0.02%) ⬆️
... and 3 more

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

It changes consensus-critical state observation, journaling, execution ordering, and header validation across the block transition pipeline.

Review effort: Balanced
Findings: None

What changed in this PR

Implements EIP-7928 block-level access-list construction, hashing, validation, and Amsterdam test coverage.

Changes:

  • Tracks account/storage reads and per-index state changes.
  • Validates BAL hashes and gas-limit bounds.
  • Enables Amsterdam execution-spec tests.
File Description
test/​state/​bal.hpp Defines BAL structures, builder, and observing state view.
test/​state/​bal.cpp Builds, sorts, encodes, hashes, and bounds BALs.
test/​state/​account.hpp Tracks whether accounts and slots are loaded.
test/​state/​state.hpp Adds warm-only access and journaling support.
test/​state/​state.cpp Separates warming from reads and updates rollback behavior.
test/​state/​host.cpp Uses warm-only account and storage access paths.
test/​state/​system_contracts.cpp Records system-contract account reads.
test/​state/​errors.hpp Adds BAL and block-hash validation errors.
test/​state/​CMakeLists.txt Builds the BAL implementation.
test/​utils/​block_transition.hpp Exposes the generated BAL in transition results.
test/​utils/​block_transition.cpp Builds the BAL throughout block execution.
test/​utils/​blockchaintest.hpp Models the BAL header commitment.
test/​utils/​blockchaintest_loader.cpp Loads blockAccessListHash.
test/​utils/​blockchaintest_runner.cpp Validates BAL presence, hash, and size.
lib/​evmone/​instructions.hpp Observes zero-length EXTCODECOPY reads.
lib/​evmone/​instructions_calls.cpp Observes delegate reads after access charging.
test/​integration/​evmone-cli/​test/​blockchaintest/​eip7778_block_gas.json Adds the Amsterdam BAL hash fixture.
circle.yml Enables Amsterdam execution-spec blockchain tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codspeed

codspeed Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will degrade performance by 1.67%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 8 improved benchmarks
❌ 91 regressed benchmarks
✅ 800 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ test_selfbalance[fork_Osaka-blockchain_test-contract_balance_1-benchmark-gas-value_1M] 39.9 ms 43.3 ms -7.74%
❌ test_selfbalance[fork_Osaka-blockchain_test-contract_balance_0-benchmark-gas-value_1M] 39.9 ms 43.2 ms -7.7%
❌ test_tload[fork_Osaka-blockchain_test-fixed_value_True-fixed_key_True-benchmark-gas-value_1M] 7.5 ms 7.8 ms -3.42%
❌ test_tload[fork_Osaka-blockchain_test-fixed_value_True-fixed_key_False-benchmark-gas-value_1M] 7.5 ms 7.7 ms -3.33%
❌ test_storage_access_warm[fork_Osaka-blockchain_test-SLOAD-benchmark-gas-value_1M] 8 ms 8.2 ms -3.21%
❌ test_storage_access_warm_benchmark[fork_Osaka-blockchain_test-SLOAD-benchmark-gas-value_1M] 9.9 ms 10.2 ms -3.08%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_False-initial_balance_False-empty_code_True-opcode_STATICCALL-benchmark-gas-value_1M] 13.6 ms 13.9 ms -2.49%
❌ test_dup[fork_Osaka-blockchain_test-opcode_DUP14-benchmark-gas-value_1M] 12.3 ms 12.6 ms -2.47%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_True-initial_balance_True-empty_code_True-opcode_STATICCALL-benchmark-gas-value_1M] 13.6 ms 14 ms -2.45%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_True-initial_balance_False-empty_code_True-opcode_STATICCALL-benchmark-gas-value_1M] 13.6 ms 14 ms -2.45%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_False-initial_balance_True-empty_code_True-opcode_STATICCALL-benchmark-gas-value_1M] 13.7 ms 14 ms -2.44%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_False-initial_balance_False-empty_code_True-opcode_CALL-benchmark-gas-value_1M] 14.1 ms 14.4 ms -2.34%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_True-initial_balance_False-empty_code_True-opcode_CALL-benchmark-gas-value_1M] 14.2 ms 14.5 ms -2.31%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_False-initial_balance_True-empty_code_True-opcode_CALL-benchmark-gas-value_1M] 14.2 ms 14.5 ms -2.3%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_True-initial_balance_True-empty_code_True-opcode_CALL-benchmark-gas-value_1M] 14.2 ms 14.5 ms -2.3%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_True-initial_balance_False-empty_code_True-opcode_DELEGATECALL-benchmark-gas-value_1M] 12.9 ms 13.2 ms -2.21%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_True-initial_balance_True-empty_code_True-opcode_DELEGATECALL-benchmark-gas-value_1M] 12.9 ms 13.2 ms -2.19%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_False-initial_balance_True-empty_code_True-opcode_DELEGATECALL-benchmark-gas-value_1M] 12.9 ms 13.2 ms -2.18%
❌ test_ext_account_query_warm[fork_Osaka-blockchain_test-initial_storage_False-initial_balance_False-empty_code_True-opcode_DELEGATECALL-benchmark-gas-value_1M] 12.9 ms 13.1 ms -2.15%
❌ test_extcodecopy_warm[fork_Osaka-blockchain_test-copy_size_32-benchmark-gas-value_1M] 8.7 ms 8.9 ms -2.12%
... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing amsterdam/bal (9f93001) with master (39425f3)

Open in CodSpeed

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants