Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions packages/testing/src/execution_testing/specs/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,11 +549,16 @@ def make_genesis(
state_root = pre_alloc.state_root()
genesis = FixtureHeader.genesis(self.fork, env, state_root)

genesis_bal = None
if self.fork.header_bal_hash_required(block_number=0, timestamp=0):
genesis_bal = BlockAccessList()

return (
pre_alloc,
FixtureBlockBase(
header=genesis,
withdrawals=None if env.withdrawals is None else [],
block_access_list=genesis_bal,
).with_rlp(txs=[]),
)

Expand Down
8 changes: 4 additions & 4 deletions src/ethereum/forks/amsterdam/block_access_lists/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ def _build_from_builder(
[`BlockAccessList`]: ref:ethereum.forks.amsterdam.block_access_lists.rlp_types.BlockAccessList # noqa: E501

"""
account_changes_list = []
block_access_list: BlockAccessList = []

for address, changes in builder.accounts.items():
storage_changes = []
Expand Down Expand Up @@ -444,11 +444,11 @@ def _build_from_builder(
code_changes=code_changes,
)

account_changes_list.append(account_change)
block_access_list.append(account_change)

account_changes_list.sort(key=lambda x: x.address)
block_access_list.sort(key=lambda x: x.address)

return BlockAccessList(account_changes=tuple(account_changes_list))
return block_access_list


def build_block_access_list(
Expand Down
13 changes: 2 additions & 11 deletions src/ethereum/forks/amsterdam/block_access_lists/rlp_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"""

from dataclasses import dataclass
from typing import Tuple
from typing import List, Tuple

from ethereum_types.bytes import Bytes, Bytes20, Bytes32
from ethereum_types.frozen import slotted_freezable
Expand Down Expand Up @@ -118,13 +118,4 @@ class AccountChanges:
code_changes: Tuple[CodeChange, ...]


@slotted_freezable
@dataclass
class BlockAccessList:
"""
Block-Level Access List for EIP-7928.
Contains all addresses accessed during block execution.
RLP encoded as a list of AccountChanges.
"""

account_changes: Tuple[AccountChanges, ...]
BlockAccessList = List[AccountChanges]
10 changes: 4 additions & 6 deletions src/ethereum/forks/amsterdam/block_access_lists/rlp_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def rlp_encode_block_access_list(block_access_list: BlockAccessList) -> Bytes:
"""
# Encode as a list of AccountChanges directly (not wrapped)
account_changes_list = []
for account in block_access_list.account_changes:
for account in block_access_list:
# Each account is encoded as:
# [address, storage_changes, storage_reads,
# balance_changes, nonce_changes, code_changes]
Expand Down Expand Up @@ -146,7 +146,7 @@ def validate_block_access_list_against_execution(
# 1. Validate structural constraints

# Check that storage changes and reads don't overlap for the same slot
for account in block_access_list.account_changes:
for account in block_access_list:
changed_slots = {sc.slot for sc in account.storage_changes}
read_slots = set(account.storage_reads)

Expand All @@ -155,17 +155,15 @@ def validate_block_access_list_against_execution(
return False

# 2. Validate ordering (addresses should be sorted lexicographically)
addresses = [
account.address for account in block_access_list.account_changes
]
addresses = [account.address for account in block_access_list]
if addresses != sorted(addresses):
return False

# 3. Validate all data is within bounds
max_block_access_index = (
MAX_TXS + 1
) # 0 for pre-exec, 1..MAX_TXS for txs, MAX_TXS+1 for post-exec
for account in block_access_list.account_changes:
for account in block_access_list:
# Validate storage slots are sorted within each account
storage_slots = [sc.slot for sc in account.storage_changes]
if storage_slots != sorted(storage_slots):
Expand Down
4 changes: 1 addition & 3 deletions src/ethereum/forks/amsterdam/vm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,7 @@ class BlockOutput:
)
blob_gas_used: U64 = U64(0)
requests: List[Bytes] = field(default_factory=list)
block_access_list: BlockAccessList = field(
default_factory=lambda: BlockAccessList(account_changes=())
)
block_access_list: BlockAccessList = field(default_factory=list)


@dataclass
Expand Down
4 changes: 4 additions & 0 deletions src/ethereum_spec_tools/evm_tools/loaders/fixture_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,8 @@ def json_to_header(self, raw: Any) -> Any:
requests_hash = hex_to_bytes32(raw.get("requestsHash"))
parameters.append(requests_hash)

if "blockAccessListHash" in raw:
bal_hash = hex_to_bytes32(raw.get("blockAccessListHash"))
parameters.append(bal_hash)

return self.fork.Header(*parameters)
18 changes: 6 additions & 12 deletions src/ethereum_spec_tools/evm_tools/t8n/t8n_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,18 +333,17 @@ def update(self, t8n: "T8N", block_env: Any, block_output: Any) -> None:
)
)

def _block_access_list_to_json(self, bal: Any) -> Any:
@staticmethod
def _block_access_list_to_json(account_changes: Any) -> Any:
"""
Convert BlockAccessList to JSON format matching the Pydantic models.
"""
account_changes = []

for account in bal.account_changes:
json_account_changes = []
for account in account_changes:
account_data: Dict[str, Any] = {
"address": "0x" + account.address.hex()
}

# Add storage changes if present
if account.storage_changes:
storage_changes = []
for slot_change in account.storage_changes:
Expand All @@ -364,14 +363,12 @@ def _block_access_list_to_json(self, bal: Any) -> Any:
storage_changes.append(slot_data)
account_data["storageChanges"] = storage_changes

# Add storage reads if present
if account.storage_reads:
account_data["storageReads"] = [
int.from_bytes(slot, "big")
for slot in account.storage_reads
]

# Add balance changes if present
if account.balance_changes:
account_data["balanceChanges"] = [
{
Expand All @@ -381,7 +378,6 @@ def _block_access_list_to_json(self, bal: Any) -> Any:
for change in account.balance_changes
]

# Add nonce changes if present
if account.nonce_changes:
account_data["nonceChanges"] = [
{
Expand All @@ -391,7 +387,6 @@ def _block_access_list_to_json(self, bal: Any) -> Any:
for change in account.nonce_changes
]

# Add code changes if present
if account.code_changes:
account_data["codeChanges"] = [
{
Expand All @@ -401,10 +396,9 @@ def _block_access_list_to_json(self, bal: Any) -> Any:
for change in account.code_changes
]

account_changes.append(account_data)
json_account_changes.append(account_data)

# return as list directly
return account_changes
return json_account_changes

def json_encode_receipts(self) -> Any:
"""
Expand Down
21 changes: 20 additions & 1 deletion tests/json_infra/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ class _FixtureSource(TypedDict):
"fixture_path": "tests/json_infra/fixtures/ethereum_tests",
},
"latest_fork_tests": {
"url": "https://github.com/ethereum/execution-spec-tests/releases/download/v5.0.0/fixtures_develop.tar.gz",
"url": "https://github.com/ethereum/execution-spec-tests/releases/download/v5.3.0/fixtures_develop.tar.gz",
"fixture_path": "tests/json_infra/fixtures/latest_fork_tests",
},
"amsterdam_tests": {
"url": "https://github.com/ethereum/execution-spec-tests/releases/download/bal%40v1.8.0/fixtures_bal.tar.gz",
"fixture_path": "tests/json_infra/fixtures/amsterdam_tests",
},
}


Expand Down Expand Up @@ -58,6 +62,7 @@ def _build_eest_test_paths(base_path: str) -> tuple:
# Base paths
ETHEREUM_TESTS_BASE = _get_fixture_path("ethereum_tests")
EEST_TESTS_BASE = _get_fixture_path("latest_fork_tests")
AMSTERDAM_TESTS_BASE = _get_fixture_path("amsterdam_tests")

# Ethereum test paths
(
Expand All @@ -74,6 +79,9 @@ def _build_eest_test_paths(base_path: str) -> tuple:

# EEST test paths
EEST_BC_TESTS, EEST_STATE_TESTS = _build_eest_test_paths(EEST_TESTS_BASE)
AMSTERDAM_BC_TESTS, AMSTERDAM_STATE_TESTS = _build_eest_test_paths(
AMSTERDAM_TESTS_BASE
)

ForkConfig = TypedDict(
"ForkConfig",
Expand Down Expand Up @@ -110,6 +118,11 @@ def _create_fork_config(
[STATE_ETHEREUM_TESTS, EEST_STATE_TESTS],
)

AMSTERDAM_DIRS = (
[AMSTERDAM_BC_TESTS],
[AMSTERDAM_STATE_TESTS],
)

FORKS: Dict[str, ForkConfig] = {
**{
json_fork: _create_fork_config(eels_fork, *PRE_CONSTANTINOPLE_DIRS)
Expand Down Expand Up @@ -140,4 +153,10 @@ def _create_fork_config(
("Osaka", "osaka"),
]
},
**{
json_fork: _create_fork_config(eels_fork, *AMSTERDAM_DIRS)
for json_fork, eels_fork in [
("Amsterdam", "amsterdam"),
]
},
}
4 changes: 2 additions & 2 deletions tests/json_infra/helpers/load_blockchain_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def run_blockchain_st_test(test_case: Dict, load: Load) -> None:
if hasattr(genesis_header, "withdrawals_root"):
parameters.append(())

if hasattr(genesis_header, "requests_root"):
parameters.append(())
if hasattr(genesis_header, "block_access_list_hash"):
parameters.append([])

genesis_block = load.fork.Block(*parameters)

Expand Down
Loading