diff --git a/packages/testing/src/execution_testing/client_clis/cli_types.py b/packages/testing/src/execution_testing/client_clis/cli_types.py index 333e1103582..0e76e5f0b44 100644 --- a/packages/testing/src/execution_testing/client_clis/cli_types.py +++ b/packages/testing/src/execution_testing/client_clis/cli_types.py @@ -288,6 +288,9 @@ class Result(CamelModel): requests: List[Bytes] | None = None block_access_list: BlockAccessList | None = None block_access_list_hash: Hash | None = None + slot_number: HexNumber | None = Field( + None, alias="currentSlotNumber" + ) block_exception: Annotated[ BlockExceptionWithMessage | UndefinedException | None, ExceptionMapperValidator, diff --git a/packages/testing/src/execution_testing/fixtures/blockchain.py b/packages/testing/src/execution_testing/fixtures/blockchain.py index 6b15039515a..4447c9bf19a 100644 --- a/packages/testing/src/execution_testing/fixtures/blockchain.py +++ b/packages/testing/src/execution_testing/fixtures/blockchain.py @@ -214,6 +214,9 @@ class FixtureHeader(CamelModel): block_access_list_hash: ( Annotated[Hash, HeaderForkRequirement("bal_hash")] | None ) = Field(None, alias="blockAccessListHash") + slot_number: ZeroPaddedHexNumber | None = Field( + None, alias="slotNumber" + ) fork: Fork | None = Field(None, exclude=True) @@ -382,6 +385,13 @@ def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> Self: if fork.header_bal_hash_required(block_number=0, timestamp=0) else None ), + "slot_number": ( + ZeroPaddedHexNumber(0) + if fork.header_slot_number_required( + block_number=0, timestamp=0 + ) + else None + ), "fork": fork, } return cls(**environment_values, **extras) @@ -422,6 +432,7 @@ class FixtureExecutionPayload(CamelModel): block_access_list: Bytes | None = Field( None, description="RLP-serialized EIP-7928 Block Access List" ) + slot_number: HexNumber | None = Field(None) @classmethod def from_fixture_header( diff --git a/packages/testing/src/execution_testing/forks/base_fork.py b/packages/testing/src/execution_testing/forks/base_fork.py index 89fa18afc26..6bbfff2124b 100644 --- a/packages/testing/src/execution_testing/forks/base_fork.py +++ b/packages/testing/src/execution_testing/forks/base_fork.py @@ -361,6 +361,14 @@ def header_bal_hash_required( """Return true if the header must contain block access list hash.""" pass + @classmethod + @abstractmethod + def header_slot_number_required( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> bool: + """Return true if the header must contain slot_number (EIP-7843).""" + pass + # Gas related abstract methods @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/forks.py b/packages/testing/src/execution_testing/forks/forks/forks.py index c2d219953f5..fee3045f5a8 100644 --- a/packages/testing/src/execution_testing/forks/forks/forks.py +++ b/packages/testing/src/execution_testing/forks/forks/forks.py @@ -976,6 +976,14 @@ def header_bal_hash_required( del block_number, timestamp return False + @classmethod + def header_slot_number_required( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> bool: + """Pre-Amsterdam forks have no slot number in header.""" + del block_number, timestamp + return False + @classmethod def engine_new_payload_version( cls, *, block_number: int = 0, timestamp: int = 0 @@ -3360,6 +3368,14 @@ def header_bal_hash_required( del block_number, timestamp return True + @classmethod + def header_slot_number_required( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> bool: + """Amsterdam requires slot_number in header (EIP-7843).""" + del block_number, timestamp + return True + @classmethod def is_deployed(cls) -> bool: """Return True if this fork is deployed.""" diff --git a/src/ethereum/forks/amsterdam/blocks.py b/src/ethereum/forks/amsterdam/blocks.py index ef44549d280..94e04b1bbe6 100644 --- a/src/ethereum/forks/amsterdam/blocks.py +++ b/src/ethereum/forks/amsterdam/blocks.py @@ -254,6 +254,14 @@ class Header: [cbalh]: ref:ethereum.forks.amsterdam.block_access_lists.rlp_utils.compute_block_access_list_hash """ # noqa: E501 + slot_number: U64 + """ + The beacon chain slot number corresponding to this execution block. + Introduced in [EIP-7843]. + + [EIP-7843]: https://eips.ethereum.org/EIPS/eip-7843 + """ + @slotted_freezable @dataclass diff --git a/src/ethereum/genesis.py b/src/ethereum/genesis.py index 444302ffebf..51525396c18 100644 --- a/src/ethereum/genesis.py +++ b/src/ethereum/genesis.py @@ -209,7 +209,7 @@ def add_genesis_block( chain.state, address, hardfork.Account( - Uint(int(account.get("nonce", "0"))), + hex_to_uint(account.get("nonce", "0x0")), hex_or_base_10_str_to_u256(account.get("balance", 0)), hex_to_bytes(account.get("code", "0x")), ), @@ -257,11 +257,19 @@ def add_genesis_block( fields["parent_beacon_block_root"] = Hash32(b"\0" * 32) if has_field(hardfork.Header, "requests_hash"): - fields["requests_hash"] = Hash32(b"\0" * 32) + # SHA-256 of empty string per EIP-7685 + fields["requests_hash"] = Hash32( + bytes.fromhex( + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + ) + ) if has_field(hardfork.Header, "block_access_list_hash"): fields["block_access_list_hash"] = keccak256(rlp.encode([])) + if has_field(hardfork.Header, "slot_number"): + fields["slot_number"] = U64(0) + genesis_header = hardfork.Header(**fields) block_fields = { diff --git a/src/ethereum_spec_tools/evm_tools/t8n/env.py b/src/ethereum_spec_tools/evm_tools/t8n/env.py index be719ba7af5..e025a0c14ae 100644 --- a/src/ethereum_spec_tools/evm_tools/t8n/env.py +++ b/src/ethereum_spec_tools/evm_tools/t8n/env.py @@ -11,6 +11,7 @@ from ethereum_types.numeric import U64, U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils import has_field from ethereum.utils.byte import left_pad_zero_bytes from ethereum.utils.hexadecimal import hex_to_bytes @@ -148,6 +149,9 @@ def read_excess_blob_gas(self, data: Any, t8n: "T8N") -> None: if t8n.fork.has_block_access_list_hash: arguments["block_access_list_hash"] = Hash32(b"\0" * 32) + if has_field(t8n.fork.Header, "slot_number"): + arguments["slot_number"] = U64(0) + parent_header = t8n.fork.Header(**arguments) self.excess_blob_gas = t8n.fork.calculate_excess_blob_gas(