Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e597ce3
feat(spec-specs): create Amsterdam from Osaka
fselmo Dec 8, 2025
2a2d0d5
fix(spec-tools): Fix lint by adding TODO docstring for Amsterdam init
fselmo Dec 9, 2025
3113f47
feat(specs): Implement EIP-7928: Block-Level Access Lists
fselmo Nov 11, 2025
dfce10d
fix(specs): Fix zero value withdrawals BAL tracking (#29)
fselmo Oct 30, 2025
468e75e
fix(specs): static upfront check for create + selfdestruct (#22)
nerolation Oct 30, 2025
c6df0b6
feat(tests): Implement more EIP-7928 tests
raxhvl Oct 29, 2025
6da8a02
fix(specs): Ensure tracking before first access (#1722)
nerolation Oct 31, 2025
743b06d
chore(tests): fill all tests for bal releases
fselmo Nov 3, 2025
3b17eb1
fix(spec-specs): duplicate storage writes in state tracker (#1743)
fselmo Nov 4, 2025
c7f83a3
fix(test-specs): validate t8n BAL independent of expectation existenc…
fselmo Nov 13, 2025
5f0e971
feat(specs): EIP-7928 refactoring
nerolation Nov 5, 2025
6c9ec93
fix(spec-specs): require and use blockenv for state tracking
fselmo Nov 5, 2025
0fc2f69
refactor(spec-specs): track BAL changes via frames
fselmo Nov 6, 2025
6aae4bb
fix(spec-specs): Mark original addr warm before delegation
fselmo Nov 11, 2025
338e733
fix(spec-specs): Make sure we account for no changes
fselmo Nov 11, 2025
e405848
fix(spec-specs): Better tracking for code changes; ensure with BAL test
fselmo Nov 12, 2025
bc46e65
fix(spec-specs): Use child frame for create message
fselmo Nov 12, 2025
40e7acc
fix(spec-specs): Normalize transaction before merging to block frame
fselmo Nov 12, 2025
c9851e1
fix(spec-specs): Early static check for SSTORE before any reads
fselmo Nov 12, 2025
1d9bf1f
fix(spec-specs): Track storage writes more appropriately wrt index
fselmo Nov 13, 2025
42def64
fix(spec-specs): Use functions, not methods; fix create revert
fselmo Nov 13, 2025
362e01a
fix(spec-specs): Default code to b"" in tracker, skip empty setting
fselmo Nov 14, 2025
05c122e
fix(spec-specs): Fix BAL cross-transaction tracking and nonce dedup
fselmo Nov 14, 2025
8ceade2
fix(spec-specs): Move destroy_account before BAL normalization
fselmo Nov 14, 2025
5a4a373
fix(spec-specs): Check delegation access gas before reading
fselmo Nov 14, 2025
dc01c2f
fix(spec-specs): Track code per auth; filter pre at tx frame
fselmo Nov 15, 2025
7f42477
fix(spec-specs): Use proper frames for system transactions
fselmo Nov 16, 2025
6ece1e5
fix(spec-specs): Track address at init collision
fselmo Nov 21, 2025
6c1d971
chore(spec-specs): Add Amsterdam docstring; update prepare msg
fselmo Nov 21, 2025
775cb9a
chore: Add pre-amsterdam BAL tests to doc for tracking
fselmo Nov 21, 2025
635edd8
fix(spec-specs): Calculate all gas we can before accessing state
fselmo Nov 24, 2025
39ed8c3
fix(test-tools): Remove named forks from blobSchedule; turn off BPOs
fselmo Nov 25, 2025
2b6e4d6
fix: add bal exception for erigon (#1809)
felix314159 Nov 26, 2025
3d65d6f
feat(test): Better describe the BAL for selfdestruct revert
fselmo Nov 26, 2025
c45d6b8
test(eip7928): add EXTCODECOPY OOG memory expansion BAL test
qu0b Nov 30, 2025
1364138
refactor(test-tests): parametrize existing test oog case instead
fselmo Dec 1, 2025
0a60532
test(eip7928): add cross-block precompile state leak test
qu0b Dec 1, 2025
7f73c1a
refactor(test-tests): Add BAL expectation to state leak test; fix lint
fselmo Dec 1, 2025
796c505
eip7928: add SELFDESTRUCT OOG BAL test
qu0b Dec 4, 2025
70d6f71
refactor(tests): move selfdestruct bal tests to oog file; add gas bou…
fselmo Dec 4, 2025
7fc5d4d
update test_cases.md
fselmo Dec 5, 2025
14f8d34
feat(tests): Port oog create refund test; add BAL >= Amsterdam
fselmo Dec 1, 2025
402d813
refactor(spec-specs): Refactor state changes and frame hierarchy (#1841)
fselmo Dec 8, 2025
b6c9410
fix(spec,tests): Change BAL to List[AccountChange] (#1844)
gurukamath Dec 8, 2025
051adb0
fix mkdocs
fselmo Dec 8, 2025
8882960
Qu0b/add bal test cases (#1812)
qu0b Dec 8, 2025
a0c8747
feat(test-tests): BAL test for nested storage write reset same tx (#1…
fselmo Dec 8, 2025
6044b67
fix(spec-specs): Fix issues after rebasing with forks/osaka
fselmo Dec 9, 2025
dd3a353
fix(spec-specs): post-exec net-zero filtering post specs refactor
fselmo Dec 9, 2025
3a85f3d
refactor(spec-specs): Move net-zero filtering inside commit tx frame
fselmo Dec 9, 2025
9c97c73
add nigthly fixture & run ubuntu latest
qu0b Dec 12, 2025
6eb403b
limit feature fixture creation
qu0b Dec 12, 2025
a1374b0
add clean to build fixtures
qu0b Dec 12, 2025
b4ca2c3
move clean flag
qu0b Dec 12, 2025
feb7b72
isolate in test grp
qu0b Dec 12, 2025
f6e61d7
isolate in test grp
qu0b Dec 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .github/actions/build-fixtures/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ inputs:
python_version:
description: "Version of Python to install"
required: true
extra_fill_params:
description: "Additional parameters to pass to fill command (e.g., '-k eip7928' to filter by EIP)"
required: false
default: ""
continue_on_test_failure:
description: "Continue generating fixtures even if some tests fail (useful for nightly builds)"
required: false
default: "false"
runs:
using: "composite"
steps:
Expand All @@ -34,10 +42,12 @@ runs:
- name: Generate fixtures using fill
shell: bash
run: |
# Only include extra_fill_params if non-empty
EXTRA_PARAMS="${{ inputs.extra_fill_params }}"
if [ "${{ steps.evm-builder.outputs.impl }}" = "eels" ]; then
uv run fill -n ${{ steps.evm-builder.outputs.x-dist }} ${{ steps.properties.outputs.fill-params }} --output=fixtures_${{ inputs.release_name }}.tar.gz --build-name ${{ inputs.release_name }}
uv run fill -n ${{ steps.evm-builder.outputs.x-dist }} --clean ${{ steps.properties.outputs.fill-params }} ${EXTRA_PARAMS:+$EXTRA_PARAMS} --output=fixtures_${{ inputs.release_name }}.tar.gz --build-name ${{ inputs.release_name }}
else
uv run fill -n ${{ steps.evm-builder.outputs.x-dist }} --evm-bin=${{ steps.evm-builder.outputs.evm-bin }} ${{ steps.properties.outputs.fill-params }} --output=fixtures_${{ inputs.release_name }}.tar.gz --build-name ${{ inputs.release_name }}
uv run fill -n ${{ steps.evm-builder.outputs.x-dist }} --clean --evm-bin=${{ steps.evm-builder.outputs.evm-bin }} ${{ steps.properties.outputs.fill-params }} ${EXTRA_PARAMS:+$EXTRA_PARAMS} --output=fixtures_${{ inputs.release_name }}.tar.gz --build-name ${{ inputs.release_name }}
fi
- name: Generate Benchmark Genesis Files
if: contains(inputs.release_name, 'benchmark')
Expand Down
3 changes: 2 additions & 1 deletion .github/configs/feature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ benchmark_fast:

bal:
evm-type: develop
fill-params: --fork=Amsterdam ./tests/amsterdam/eip7928_block_level_access_lists
# TODO: Turn on block rlp limit tests after making filling them more flexible.
fill-params: --fork=Amsterdam -k "not eip7934"
feature_only: true
141 changes: 141 additions & 0 deletions .github/workflows/nightly_fixture_feature.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
name: Build Nightly Fixtures for Feature Branches

on:
push:
branches:
- "eips/amsterdam/**"
- "qu0b/add-nightly-bal-workflow"
workflow_dispatch:
inputs:
feature:
description: "Feature name from feature.yaml (e.g., bal, develop)"
required: true
default: "bal"
branch:
description: "Branch name for the release tag (leave empty to use current branch)"
required: false
eip_filter:
description: "EIP filter for tests (e.g., 'eip7928' to only fill EIP-7928 tests)"
required: false

jobs:
build:
runs-on: [ubuntu-latest]
# runs-on: [self-hosted-ghr, size-gigachungus-x64]
timeout-minutes: 1440
outputs:
feature: ${{ steps.feature.outputs.name }}
branch_slug: ${{ steps.feature.outputs.branch_slug }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
submodules: true

- name: Determine feature name, EIP filter, and branch slug
id: feature
shell: bash
run: |
BRANCH="${{ github.ref_name }}"

# Determine feature name and EIP filter based on branch
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.feature }}" ]; then
FEATURE="${{ inputs.feature }}"
# Use manual EIP filter if provided
if [ -n "${{ inputs.eip_filter }}" ]; then
EIP_FILTER="-k ${{ inputs.eip_filter }}"
else
EIP_FILTER=""
fi
elif [[ "$BRANCH" == eips/amsterdam/* ]]; then
FEATURE="bal"
# Extract EIP number from branch name (e.g., eips/amsterdam/eip-7928 -> eip7928)
EIP=$(echo "$BRANCH" | grep -oP 'eip-?\d+' | tr -d '-' || true)
if [ -n "$EIP" ]; then
EIP_FILTER="-k ${EIP}"
echo "Detected EIP filter: ${EIP_FILTER}"
else
EIP_FILTER=""
echo "No EIP detected in branch name, building all tests"
fi
else
echo "Error: Could not determine feature name"
exit 1
fi
echo "name=${FEATURE}" >> "$GITHUB_OUTPUT"
echo "eip_filter=${EIP_FILTER}" >> "$GITHUB_OUTPUT"

# Determine branch for release tag
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.branch }}" ]; then
BRANCH="${{ inputs.branch }}"
fi
# Convert branch name to slug (replace / with -)
BRANCH_SLUG="${BRANCH//\//-}"
echo "branch_slug=${BRANCH_SLUG}" >> "$GITHUB_OUTPUT"

- name: Fetch lllc
uses: ./.github/actions/fetch-binary
with:
version: v1.0.0
repo_owner: felix314159
repo_name: lllc-custom
remote_name: lllc
binary_name: lllc
expected_sha256: 865a0d5379acb3b5471337b5dcf686a2dd71587c6b65b9da6c963de627e0b300

- name: Fetch Solidity
uses: ./.github/actions/fetch-binary
with:
version: v0.8.24
repo_owner: ethereum
repo_name: solidity
remote_name: solc-static-linux
binary_name: solc
expected_sha256: fb03a29a517452b9f12bcf459ef37d0a543765bb3bbc911e70a87d6a37c30d5f

- uses: ./.github/actions/build-fixtures
with:
release_name: ${{ steps.feature.outputs.name }}
uv_version: ${{ vars.UV_VERSION }}
python_version: ${{ vars.DEFAULT_PYTHON_VERSION }}
extra_fill_params: ${{ steps.feature.outputs.eip_filter }}

release:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
submodules: false

- name: Download fixtures artifact
run: |
gh run download ${{ github.run_id }} --dir ./artifacts
env:
GH_TOKEN: ${{ github.token }}

- name: Upload to nightly release
run: |
FEATURE="${{ needs.build.outputs.feature }}"
BRANCH_SLUG="${{ needs.build.outputs.branch_slug }}"
RELEASE_TAG="${FEATURE}@nightly-${BRANCH_SLUG}"
COMMIT_SHA="${{ github.sha }}"
SHORT_SHA="${COMMIT_SHA:0:7}"

# Delete existing release if it exists
gh release delete "${RELEASE_TAG}" --repo ethereum/execution-spec-tests --yes || true

# Create new release
gh release create "${RELEASE_TAG}" \
--repo ethereum/execution-spec-tests \
--prerelease \
--title "Nightly: ${FEATURE} from ${BRANCH_SLUG}" \
--notes "Auto-generated fixtures from branch \`${{ github.ref_name }}\` at commit ${SHORT_SHA}.

**Generated:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Commit:** ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}
**Workflow run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

> ⚠️ This is an automatically updated nightly release. It will be replaced on every push to the branch." \
./artifacts/**/*
env:
GH_TOKEN: ${{ secrets.EEST_RELEASE_TOKEN }}
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Test fixtures for use by clients are available for each release on the [Github r
### 📋 Misc

- 🐞 WELDed the EEST tox environments relevant to producing documentation into EELS, and added a tool to cleanly add codespell whitelist entries. ([#1695](https://github.com/ethereum/execution-specs/pull/1659)).
- 🐞 Fix duplicate storage write issues for block access lists EIP-7928 implementation ([#1743](https://github.com/ethereum/execution-specs/pull/1743)).

### 🧪 Test Cases

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]:
"HIVE_CANCUN_TIMESTAMP": 0,
"HIVE_PRAGUE_TIMESTAMP": 0,
"HIVE_OSAKA_TIMESTAMP": 0,
**get_blob_schedule_entries(Osaka),
},
PragueToOsakaAtTime15k: {
"HIVE_FORK_HOMESTEAD": 0,
Expand All @@ -314,7 +313,6 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]:
"HIVE_CANCUN_TIMESTAMP": 0,
"HIVE_PRAGUE_TIMESTAMP": 0,
"HIVE_OSAKA_TIMESTAMP": 15000,
**get_blob_schedule_entries(Osaka),
},
BPO1: {
"HIVE_FORK_HOMESTEAD": 0,
Expand Down Expand Up @@ -496,11 +494,10 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]:
"HIVE_CANCUN_TIMESTAMP": 0,
"HIVE_PRAGUE_TIMESTAMP": 0,
"HIVE_OSAKA_TIMESTAMP": 0,
"HIVE_BPO1_TIMESTAMP": 0,
"HIVE_BPO2_TIMESTAMP": 0,
"HIVE_BPO3_TIMESTAMP": 0,
"HIVE_BPO4_TIMESTAMP": 0,
# TODO: While we are still reworking BPO interaction with T8N,
# turn off BPO timestamps for now.
# "HIVE_BPO1_TIMESTAMP": 0,
# "HIVE_BPO2_TIMESTAMP": 0,
"HIVE_AMSTERDAM_TIMESTAMP": 0,
**get_blob_schedule_entries(Amsterdam),
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class ErigonExceptionMapper(ExceptionMapper):
BlockException.INVALID_LOG_BLOOM: "invalid bloom",
}
mapping_regex = {
BlockException.INVALID_BLOCK_ACCESS_LIST: r"invalid block access list|block access list mismatch",
TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: (
r"invalid block, txnIdx=\d+,.*gas limit too high"
),
Expand Down
16 changes: 16 additions & 0 deletions packages/testing/src/execution_testing/fixtures/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ class FixtureHeader(CamelModel):
requests_hash: (
Annotated[Hash, HeaderForkRequirement("requests")] | None
) = Field(None)
block_access_list_hash: (
Annotated[Hash, HeaderForkRequirement("bal_hash")] | None
) = Field(None, alias="blockAccessListHash")

fork: Fork | None = Field(None, exclude=True)

Expand Down Expand Up @@ -283,6 +286,11 @@ def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> Self:
"requests_hash": Requests()
if fork.header_requests_required(block_number=0, timestamp=0)
else None,
"block_access_list_hash": (
BlockAccessList().rlp_hash
if fork.header_bal_hash_required(block_number=0, timestamp=0)
else None
),
"fork": fork,
}
return cls(**environment_values, **extras)
Expand Down Expand Up @@ -408,6 +416,14 @@ def from_fixture_header(
"Invalid header for engine_newPayload"
)

if fork.engine_execution_payload_block_access_list(
block_number=header.number, timestamp=header.timestamp
):
if block_access_list is None:
raise ValueError(
f"`block_access_list` is required in engine `ExecutionPayload` for >={fork}."
)

execution_payload = FixtureExecutionPayload.from_fixture_header(
header=header,
transactions=transactions,
Expand Down
19 changes: 19 additions & 0 deletions packages/testing/src/execution_testing/forks/base_fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ def header_requests_required(
"""Return true if the header must contain beacon chain requests."""
pass

@classmethod
@abstractmethod
def header_bal_hash_required(
cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
"""Return true if the header must contain block access list hash."""
pass

# Gas related abstract methods

@classmethod
Expand Down Expand Up @@ -710,6 +718,17 @@ def engine_new_payload_target_blobs_per_block(
"""
pass

@classmethod
@abstractmethod
def engine_execution_payload_block_access_list(
cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
"""
Return `True` if the engine api version requires execution payload to
include a `block_access_list`.
"""
pass

@classmethod
@abstractmethod
def engine_payload_attribute_target_blobs_per_block(
Expand Down
37 changes: 37 additions & 0 deletions packages/testing/src/execution_testing/forks/forks/forks.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,14 @@ def header_requests_required(
del block_number, timestamp
return False

@classmethod
def header_bal_hash_required(
cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
"""At genesis, header must not contain block access list hash."""
del block_number, timestamp
return False

@classmethod
def engine_new_payload_version(
cls, *, block_number: int = 0, timestamp: int = 0
Expand Down Expand Up @@ -483,6 +491,14 @@ def engine_new_payload_requests(
del block_number, timestamp
return False

@classmethod
def engine_execution_payload_block_access_list(
cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
"""At genesis, payloads do not have block access list."""
del block_number, timestamp
return False

@classmethod
def engine_new_payload_target_blobs_per_block(
cls,
Expand Down Expand Up @@ -2462,6 +2478,16 @@ class BPO5(BPO4, bpo_fork=True):
class Amsterdam(Osaka):
"""Amsterdam fork."""

@classmethod
def header_bal_hash_required(
cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
"""
From Amsterdam, header must contain block access list hash (EIP-7928).
"""
del block_number, timestamp
return True

@classmethod
def is_deployed(cls) -> bool:
"""Return True if this fork is deployed."""
Expand All @@ -2475,6 +2501,17 @@ def engine_new_payload_version(
del block_number, timestamp
return 5

@classmethod
def engine_execution_payload_block_access_list(
cls, *, block_number: int = 0, timestamp: int = 0
) -> bool:
"""
From Amsterdam, engine execution payload includes `block_access_list`
as a parameter.
"""
del block_number, timestamp
return True


class EOFv1(Prague, solc_name="cancun"):
"""EOF fork."""
Expand Down
Loading
Loading