From 015eb07726b17ad303146cdab73072cd77ec8364 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Wed, 15 Jan 2025 00:56:27 +0000 Subject: [PATCH 1/7] fix(fixtures,forks,specs,types): Remove target blobs from header --- src/ethereum_test_fixtures/blockchain.py | 9 --------- src/ethereum_test_forks/base_fork.py | 8 -------- src/ethereum_test_forks/forks/forks.py | 9 --------- src/ethereum_test_specs/blockchain.py | 8 -------- src/ethereum_test_types/types.py | 12 ------------ src/pytest_plugins/execute/rpc/hive.py | 7 ------- 6 files changed, 53 deletions(-) diff --git a/src/ethereum_test_fixtures/blockchain.py b/src/ethereum_test_fixtures/blockchain.py index f459320ed08..edcc8580865 100644 --- a/src/ethereum_test_fixtures/blockchain.py +++ b/src/ethereum_test_fixtures/blockchain.py @@ -118,9 +118,6 @@ class FixtureHeader(CamelModel): None ) requests_hash: Annotated[Hash, HeaderForkRequirement("requests")] | None = Field(None) - target_blobs_per_block: ( - Annotated[ZeroPaddedHexNumber, HeaderForkRequirement("target_blobs_per_block")] | None - ) = Field(None) fork: Fork | None = Field(None, exclude=True) @@ -306,12 +303,6 @@ def from_fixture_header( raise ValueError(f"Requests are required for ${fork}.") params.append(requests) - if fork.engine_new_payload_target_blobs_per_block(header.number, header.timestamp): - target_blobs_per_block = header.target_blobs_per_block - if target_blobs_per_block is None: - raise ValueError(f"Target blobs per block is required for ${fork}.") - params.append(target_blobs_per_block) - payload_params: EngineNewPayloadParameters = cast( EngineNewPayloadParameters, tuple(params), diff --git a/src/ethereum_test_forks/base_fork.py b/src/ethereum_test_forks/base_fork.py index 282571559bd..0f0eafcfa1c 100644 --- a/src/ethereum_test_forks/base_fork.py +++ b/src/ethereum_test_forks/base_fork.py @@ -218,14 +218,6 @@ def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> """Return true if the header must contain beacon chain requests.""" pass - @classmethod - @abstractmethod - def header_target_blobs_per_block_required( - cls, block_number: int = 0, timestamp: int = 0 - ) -> bool: - """Return true if the header must contain target blobs per block.""" - pass - # Gas related abstract methods @classmethod diff --git a/src/ethereum_test_forks/forks/forks.py b/src/ethereum_test_forks/forks/forks.py index b613743b96e..5cd7eb7f5b6 100644 --- a/src/ethereum_test_forks/forks/forks.py +++ b/src/ethereum_test_forks/forks/forks.py @@ -273,15 +273,6 @@ def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) """At genesis, header must not contain parent beacon block root.""" return False - @classmethod - def header_target_blobs_per_block_required( - cls, - block_number: int = 0, - timestamp: int = 0, - ) -> bool: - """At genesis, header must not contain target blobs per block.""" - return False - @classmethod def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, payloads do not have blob hashes.""" diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py index bae78a09eea..f25f5860a5a 100644 --- a/src/ethereum_test_specs/blockchain.py +++ b/src/ethereum_test_specs/blockchain.py @@ -109,7 +109,6 @@ class Header(CamelModel): excess_blob_gas: Removable | HexNumber | None = None parent_beacon_block_root: Removable | Hash | None = None requests_hash: Removable | Hash | None = None - target_blobs_per_block: Removable | HexNumber | None = None REMOVE_FIELD: ClassVar[Removable] = Removable() """ @@ -256,8 +255,6 @@ def set_environment(self, env: Environment) -> Environment: new_env_values["blob_gas_used"] = self.blob_gas_used if not isinstance(self.parent_beacon_block_root, Removable): new_env_values["parent_beacon_block_root"] = self.parent_beacon_block_root - if not isinstance(self.target_blobs_per_block, Removable): - new_env_values["target_blobs_per_block"] = self.target_blobs_per_block """ These values are required, but they depend on the previous environment, so they can be calculated here. @@ -342,11 +339,6 @@ def make_genesis( ), parent_beacon_block_root=env.parent_beacon_block_root, requests_hash=Requests() if fork.header_requests_required(0, 0) else None, - target_blobs_per_block=( - fork.target_blobs_per_block(0, 0) - if fork.header_target_blobs_per_block_required(0, 0) - else None - ), fork=fork, ) diff --git a/src/ethereum_test_types/types.py b/src/ethereum_test_types/types.py index e2879f2c7ff..1fe493b1d3f 100644 --- a/src/ethereum_test_types/types.py +++ b/src/ethereum_test_types/types.py @@ -343,10 +343,6 @@ class EnvironmentGeneric(CamelModel, Generic[NumberBoundTypeVar]): difficulty: NumberBoundTypeVar | None = Field(None, alias="currentDifficulty") base_fee_per_gas: NumberBoundTypeVar | None = Field(None, alias="currentBaseFee") excess_blob_gas: NumberBoundTypeVar | None = Field(None, alias="currentExcessBlobGas") - target_blobs_per_block: NumberBoundTypeVar | None = Field( - None, - alias="currentTargetBlobsPerBlock", - ) parent_difficulty: NumberBoundTypeVar | None = Field(None) parent_timestamp: NumberBoundTypeVar | None = Field(None) @@ -430,14 +426,6 @@ def set_fork_requirements(self, fork: Fork) -> "Environment": ): updated_values["parent_beacon_block_root"] = 0 - if ( - fork.header_target_blobs_per_block_required(number, timestamp) - and self.target_blobs_per_block is None - ): - updated_values["target_blobs_per_block"] = fork.target_blobs_per_block( - number, timestamp - ) - return self.copy(**updated_values) diff --git a/src/pytest_plugins/execute/rpc/hive.py b/src/pytest_plugins/execute/rpc/hive.py index fd4cf48be18..3b27fb10cad 100644 --- a/src/pytest_plugins/execute/rpc/hive.py +++ b/src/pytest_plugins/execute/rpc/hive.py @@ -245,13 +245,6 @@ def base_pre_genesis( requests_hash=Requests() if base_fork.header_requests_required(block_number=block_number, timestamp=timestamp) else None, - target_blobs_per_block=( - base_fork.target_blobs_per_block(block_number=block_number, timestamp=timestamp) - if base_fork.header_target_blobs_per_block_required( - block_number=block_number, timestamp=timestamp - ) - else None - ), ) return (pre_alloc, genesis) From 66ef551f9b3583d3a24d1c1db407707cd1c3aedf Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Wed, 15 Jan 2025 01:02:26 +0000 Subject: [PATCH 2/7] refactor(fixtures,specs): Rename Fixture classes --- src/ethereum_test_fixtures/__init__.py | 6 ++---- src/ethereum_test_fixtures/blockchain.py | 6 +++--- src/ethereum_test_fixtures/consume.py | 5 ++--- src/ethereum_test_fixtures/file.py | 5 ++--- src/ethereum_test_fixtures/state.py | 2 +- src/ethereum_test_specs/blockchain.py | 10 ++++------ src/ethereum_test_specs/state.py | 5 ++--- src/ethereum_test_specs/tests/test_fixtures.py | 6 +++--- 8 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/ethereum_test_fixtures/__init__.py b/src/ethereum_test_fixtures/__init__.py index dd6ebddf62d..0b892f8eab9 100644 --- a/src/ethereum_test_fixtures/__init__.py +++ b/src/ethereum_test_fixtures/__init__.py @@ -3,12 +3,10 @@ from typing import Dict from .base import BaseFixture, FixtureFormat -from .blockchain import EngineFixture as BlockchainEngineFixture -from .blockchain import Fixture as BlockchainFixture -from .blockchain import FixtureCommon as BlockchainFixtureCommon +from .blockchain import BlockchainEngineFixture, BlockchainFixture, BlockchainFixtureCommon from .collector import FixtureCollector, TestInfo from .eof import Fixture as EOFFixture -from .state import Fixture as StateFixture +from .state import StateFixture from .transaction import Fixture as TransactionFixture from .verify import FixtureVerifier diff --git a/src/ethereum_test_fixtures/blockchain.py b/src/ethereum_test_fixtures/blockchain.py index edcc8580865..5755acdd8e5 100644 --- a/src/ethereum_test_fixtures/blockchain.py +++ b/src/ethereum_test_fixtures/blockchain.py @@ -404,7 +404,7 @@ class InvalidFixtureBlock(CamelModel): rlp_decoded: FixtureBlockBase | None = Field(None, alias="rlp_decoded") -class FixtureCommon(BaseFixture): +class BlockchainFixtureCommon(BaseFixture): """Base blockchain test fixture model.""" fork: str = Field(..., alias="network") @@ -418,7 +418,7 @@ def get_fork(self) -> str | None: return self.fork -class Fixture(FixtureCommon): +class BlockchainFixture(BlockchainFixtureCommon): """Cross-client specific blockchain test model use in JSON fixtures.""" fixture_format_name: ClassVar[str] = "blockchain_test" @@ -429,7 +429,7 @@ class Fixture(FixtureCommon): seal_engine: Literal["NoProof"] = Field("NoProof") -class EngineFixture(FixtureCommon): +class BlockchainEngineFixture(BlockchainFixtureCommon): """Engine specific test fixture information.""" fixture_format_name: ClassVar[str] = "blockchain_test_engine" diff --git a/src/ethereum_test_fixtures/consume.py b/src/ethereum_test_fixtures/consume.py index 0cc066fdef3..ebed0e0360b 100644 --- a/src/ethereum_test_fixtures/consume.py +++ b/src/ethereum_test_fixtures/consume.py @@ -10,10 +10,9 @@ from ethereum_test_base_types import HexNumber from ethereum_test_fixtures import FIXTURE_FORMATS, FixtureFormat -from .blockchain import EngineFixture as BlockchainEngineFixture -from .blockchain import Fixture as BlockchainFixture +from .blockchain import BlockchainEngineFixture, BlockchainFixture from .file import Fixtures -from .state import Fixture as StateFixture +from .state import StateFixture class TestCaseBase(BaseModel): diff --git a/src/ethereum_test_fixtures/file.py b/src/ethereum_test_fixtures/file.py index 6e4f4d96d6f..65fa96d2574 100644 --- a/src/ethereum_test_fixtures/file.py +++ b/src/ethereum_test_fixtures/file.py @@ -9,10 +9,9 @@ from ethereum_test_base_types import EthereumTestRootModel from .base import FixtureFormat -from .blockchain import EngineFixture as BlockchainEngineFixture -from .blockchain import Fixture as BlockchainFixture +from .blockchain import BlockchainEngineFixture, BlockchainFixture from .eof import Fixture as EOFFixture -from .state import Fixture as StateFixture +from .state import StateFixture from .transaction import Fixture as TransactionFixture FixtureModel = ( diff --git a/src/ethereum_test_fixtures/state.py b/src/ethereum_test_fixtures/state.py index fc8d7e2f35f..871a4f75abe 100644 --- a/src/ethereum_test_fixtures/state.py +++ b/src/ethereum_test_fixtures/state.py @@ -86,7 +86,7 @@ class FixtureForkPost(CamelModel): expect_exception: TransactionExceptionInstanceOrList | None = None -class Fixture(BaseFixture): +class StateFixture(BaseFixture): """Fixture for a single StateTest.""" fixture_format_name: ClassVar[str] = "state_test" diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py index f25f5860a5a..cd68f018161 100644 --- a/src/ethereum_test_specs/blockchain.py +++ b/src/ethereum_test_specs/blockchain.py @@ -28,8 +28,6 @@ FixtureFormat, ) from ethereum_test_fixtures.blockchain import ( - EngineFixture, - Fixture, FixtureBlock, FixtureBlockBase, FixtureEngineNewPayload, @@ -504,7 +502,7 @@ def make_fixture( fork: Fork, eips: Optional[List[int]] = None, slow: bool = False, - ) -> Fixture: + ) -> BlockchainFixture: """Create a fixture from the blockchain test definition.""" fixture_blocks: List[FixtureBlock | InvalidFixtureBlock] = [] @@ -575,7 +573,7 @@ def make_fixture( ) self.verify_post_state(t8n, t8n_state=alloc) - return Fixture( + return BlockchainFixture( fork=self.network_info(fork, eips), genesis=genesis.header, genesis_rlp=genesis.rlp, @@ -591,7 +589,7 @@ def make_hive_fixture( fork: Fork, eips: Optional[List[int]] = None, slow: bool = False, - ) -> EngineFixture: + ) -> BlockchainEngineFixture: """Create a hive fixture from the blocktest definition.""" fixture_payloads: List[FixtureEngineNewPayload] = [] @@ -668,7 +666,7 @@ def make_hive_fixture( error_code=None, ) - return EngineFixture( + return BlockchainEngineFixture( fork=self.network_info(fork, eips), genesis=genesis.header, payloads=fixture_payloads, diff --git a/src/ethereum_test_specs/state.py b/src/ethereum_test_specs/state.py index 44e691898e3..59a0e3babb1 100644 --- a/src/ethereum_test_specs/state.py +++ b/src/ethereum_test_specs/state.py @@ -17,7 +17,6 @@ StateFixture, ) from ethereum_test_fixtures.state import ( - Fixture, FixtureEnvironment, FixtureForkPost, FixtureTransaction, @@ -113,7 +112,7 @@ def make_state_test_fixture( fork: Fork, eips: Optional[List[int]] = None, slow: bool = False, - ) -> Fixture: + ) -> StateFixture: """Create a fixture from the state test definition.""" # We can't generate a state test fixture that names a transition fork, # so we get the fork at the block number and timestamp of the state test @@ -159,7 +158,7 @@ def make_state_test_fixture( pprint(transition_tool_output.alloc) raise e - return Fixture( + return StateFixture( env=FixtureEnvironment(**env.model_dump(exclude_none=True)), pre=pre_alloc, post={ diff --git a/src/ethereum_test_specs/tests/test_fixtures.py b/src/ethereum_test_specs/tests/test_fixtures.py index e14374b52ea..acb5b587b3a 100644 --- a/src/ethereum_test_specs/tests/test_fixtures.py +++ b/src/ethereum_test_specs/tests/test_fixtures.py @@ -14,10 +14,10 @@ from ethereum_test_fixtures import ( BlockchainEngineFixture, BlockchainFixture, + BlockchainFixtureCommon, FixtureFormat, StateFixture, ) -from ethereum_test_fixtures.blockchain import FixtureCommon from ethereum_test_forks import Berlin, Fork, Istanbul, London, Paris, Shanghai from ethereum_test_types import Alloc, Environment, Transaction from ethereum_test_vm import Opcodes as Op @@ -499,7 +499,7 @@ def test_fill_blockchain_valid_txs( # noqa: D102 blockchain_test_fixture: BlockchainFixture, ): assert blockchain_test_fixture.__class__ == fixture_format - assert isinstance(blockchain_test_fixture, FixtureCommon) + assert isinstance(blockchain_test_fixture, BlockchainFixtureCommon) fixture_name = f"000/my_blockchain_test/{fork.name()}" @@ -870,7 +870,7 @@ def test_fill_blockchain_invalid_txs(fork: Fork, check_hive: bool, expected_json fixture_format=fixture_format, ) assert generated_fixture.__class__ == fixture_format - assert isinstance(generated_fixture, FixtureCommon) + assert isinstance(generated_fixture, BlockchainFixtureCommon) fixture_name = f"000/my_blockchain_test/{fork.name()}" From 11bf6efc8492fa5e8f568d1373f5b613b253499e Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Wed, 15 Jan 2025 01:02:57 +0000 Subject: [PATCH 3/7] feat(forks): Add `parent` method --- src/ethereum_test_forks/base_fork.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ethereum_test_forks/base_fork.py b/src/ethereum_test_forks/base_fork.py index 0f0eafcfa1c..9014e187e77 100644 --- a/src/ethereum_test_forks/base_fork.py +++ b/src/ethereum_test_forks/base_fork.py @@ -539,6 +539,15 @@ def ignore(cls) -> bool: """Return whether the fork should be ignored during test generation.""" return cls._ignore + @classmethod + def parent(cls) -> Type["BaseFork"] | None: + """Return the parent fork.""" + base_class = cls.__bases__[0] + assert issubclass(base_class, BaseFork) + if base_class == BaseFork: + return None + return base_class + # Fork Type Fork = Type[BaseFork] From 8e0f19cfa7633564162b25abb2cac06e1b55a642 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Tue, 21 Jan 2025 17:25:44 +0000 Subject: [PATCH 4/7] refactor(clis/t8n): Request objects --- src/ethereum_clis/transition_tool.py | 41 +++++++++++++++++----------- src/ethereum_clis/types.py | 15 ++++++++++ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/ethereum_clis/transition_tool.py b/src/ethereum_clis/transition_tool.py index 96965c8f324..d68fb8439cc 100644 --- a/src/ethereum_clis/transition_tool.py +++ b/src/ethereum_clis/transition_tool.py @@ -24,7 +24,13 @@ from .ethereum_cli import EthereumCLI from .file_utils import dump_files_to_directory, write_json_file -from .types import TransactionReceipt, TransitionToolInput, TransitionToolOutput +from .types import ( + TransactionReceipt, + TransitionToolContext, + TransitionToolInput, + TransitionToolOutput, + TransitionToolRequest, +) model_dump_config: Mapping = {"by_alias": True, "exclude_none": True} @@ -142,6 +148,17 @@ def to_input(self) -> TransitionToolInput: env=self.env, ) + def get_request_data(self) -> TransitionToolRequest: + """Convert the data to a TransitionToolRequest object.""" + return TransitionToolRequest( + state=TransitionToolContext( + fork=self.fork_name, + chain_id=self.chain_id, + reward=self.reward, + ), + input=self.to_input(), + ) + def _evaluate_filesystem( self, *, @@ -298,37 +315,29 @@ def _evaluate_server( timeout: int, ) -> TransitionToolOutput: """Execute the transition tool sending inputs and outputs via a server.""" - input_contents = t8n_data.to_input() - input_json = input_contents.model_dump(mode="json", **model_dump_config) - post_data = { - "state": { - "fork": t8n_data.fork_name, - "chainid": t8n_data.chain_id, - "reward": t8n_data.reward, - }, - "input": input_json, - } + request_data = t8n_data.get_request_data() + request_data_json = request_data.model_dump(mode="json", **model_dump_config) if debug_output_path: request_info = ( f"Server URL: {self.server_url}\n\n" - f"Request Data:\n{json.dumps(post_data, indent=2)}\n" + f"Request Data:\n{json.dumps(request_data_json, indent=2)}\n" ) dump_files_to_directory( debug_output_path, { - "input/alloc.json": input_contents.alloc, - "input/env.json": input_contents.env, + "input/alloc.json": request_data.input.alloc, + "input/env.json": request_data.input.env, "input/txs.json": [ tx.model_dump(mode="json", **model_dump_config) - for tx in input_contents.txs + for tx in request_data.input.txs ], "request_info.txt": request_info, }, ) response = self._server_post( - data=post_data, url_args=self._generate_post_args(t8n_data), timeout=timeout + data=request_data_json, url_args=self._generate_post_args(t8n_data), timeout=timeout ) output: TransitionToolOutput = TransitionToolOutput.model_validate(response.json()) diff --git a/src/ethereum_clis/types.py b/src/ethereum_clis/types.py index 75325fd4d9a..bbe29e43ade 100644 --- a/src/ethereum_clis/types.py +++ b/src/ethereum_clis/types.py @@ -52,3 +52,18 @@ class TransitionToolOutput(CamelModel): alloc: Alloc result: Result body: Bytes | None = None + + +class TransitionToolContext(CamelModel): + """Transition tool context.""" + + fork: str + chain_id: int = Field(..., alias="chainid") + reward: int + + +class TransitionToolRequest(CamelModel): + """Transition tool server request data.""" + + state: TransitionToolContext + input: TransitionToolInput From 2d830ca80f5620d9247bfe7abf78f33c074efc9d Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Tue, 21 Jan 2025 18:25:10 +0000 Subject: [PATCH 5/7] feat(fixtures/specs): Add fixture config objects --- docs/consuming_tests/blockchain_test.md | 14 ++ .../consuming_tests/blockchain_test_engine.md | 18 +++ docs/consuming_tests/state_test.md | 8 ++ src/ethereum_test_fixtures/blockchain.py | 7 + src/ethereum_test_fixtures/state.py | 7 + src/ethereum_test_specs/blockchain.py | 13 +- src/ethereum_test_specs/state.py | 2 + .../blockchain_london_invalid_filled.json | 7 +- .../blockchain_london_valid_filled.json | 7 +- ...kchain_shanghai_invalid_filled_engine.json | 6 +- ...ockchain_shanghai_valid_filled_engine.json | 6 +- .../chainid_cancun_blockchain_test.json | 135 ++++++++++++++++++ ...chainid_cancun_blockchain_test_engine.json | 117 +++++++++++++++ .../fixtures/chainid_cancun_state_test.json | 85 +++++++++++ .../chainid_istanbul_blockchain_test.json | 7 +- .../chainid_london_blockchain_test.json | 7 +- .../chainid_paris_blockchain_test_engine.json | 6 +- .../fixtures/chainid_paris_state_test.json | 5 +- ...ainid_shanghai_blockchain_test_engine.json | 6 +- .../fixtures/chainid_shanghai_state_test.json | 5 +- 20 files changed, 446 insertions(+), 22 deletions(-) create mode 100644 src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json create mode 100644 src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json create mode 100644 src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json diff --git a/docs/consuming_tests/blockchain_test.md b/docs/consuming_tests/blockchain_test.md index 46a3d18b068..0162366ff9a 100644 --- a/docs/consuming_tests/blockchain_test.md +++ b/docs/consuming_tests/blockchain_test.md @@ -54,8 +54,12 @@ For each [`Fixture`](#fixture) test object in the JSON fixture file, perform the #### - `network`: [`Fork`](./common_types.md#fork) +##### TO BE DEPRECATED + Fork configuration for the test. +This field is going to be replaced by the value contained in `config.network`. + #### - `pre`: [`Alloc`](./common_types.md#alloc-mappingaddressaccount) Starting account allocation for the test. State root calculated from this allocation must match the one in the genesis block. @@ -84,6 +88,16 @@ Account allocation for verification after all the blocks have been processed. Deprecated: Seal engine used to mine the blocks. +#### - `config`: [`FixtureConfig`](#fixtureconfig) + +Chain configuration object to be applied to the client running the blockchain test. + +### `FixtureConfig` + +#### - `network`: [`Fork`](./common_types.md#fork) + +Fork configuration for the test. It is guaranteed that this field contains the same value as the root field `network`. + ### `FixtureHeader` #### - `parentHash`: [`Hash`](./common_types.md#hash) diff --git a/docs/consuming_tests/blockchain_test_engine.md b/docs/consuming_tests/blockchain_test_engine.md index d09a2c40f27..aa08879e429 100644 --- a/docs/consuming_tests/blockchain_test_engine.md +++ b/docs/consuming_tests/blockchain_test_engine.md @@ -45,8 +45,12 @@ For each [`HiveFixture`](#hivefixture) test object in the JSON fixture file, per #### - `network`: [`Fork`](./common_types.md#fork) +##### TO BE DEPRECATED + Fork configuration for the test. +This field is going to be replaced by the value contained in `config.network`. + #### - `genesisBlockHeader`: [`FixtureHeader`](./blockchain_test.md#fixtureheader) Genesis block header. @@ -63,10 +67,24 @@ Version of the `engine_forkchoiceUpdatedVX` directive to use to set the head of Starting account allocation for the test. State root calculated from this allocation must match the one in the genesis block. +#### - `lastblockhash`: [`Hash`](./common_types.md#hash) + +Hash of the last valid block, or the genesis block hash if the list of blocks is empty, or contains a single invalid block. + #### - `post`: [`Alloc`](./common_types.md#alloc-mappingaddressaccount) Account allocation for verification after all the blocks have been processed. +#### - `config`: [`FixtureConfig`](#fixtureconfig) + +Chain configuration object to be applied to the client running the blockchain engine test. + +### `FixtureConfig` + +#### - `network`: [`Fork`](./common_types.md#fork) + +Fork configuration for the test. It is guaranteed that this field contains the same value as the root field `network`. + ### `FixtureEngineNewPayload` #### - `executionPayload`: [`FixtureExecutionPayload`](#fixtureexecutionpayload) diff --git a/docs/consuming_tests/state_test.md b/docs/consuming_tests/state_test.md index fb98be76e7f..ae77289e6f5 100644 --- a/docs/consuming_tests/state_test.md +++ b/docs/consuming_tests/state_test.md @@ -60,6 +60,14 @@ Transaction to be executed. Mapping of lists of post for verification per fork, where each element represents a single possible outcome of the transaction execution after being applied to the `pre`. +#### - `config`: [`FixtureConfig`](#fixtureconfig) + +Chain configuration object. + +### `FixtureConfig` + +At the moment, this object is an empty dictionary and contains no fields. + ### `FixtureEnvironment` #### - `currentCoinbase`: [`Address`](./common_types.md#address) diff --git a/src/ethereum_test_fixtures/blockchain.py b/src/ethereum_test_fixtures/blockchain.py index 5755acdd8e5..a781e71c7a6 100644 --- a/src/ethereum_test_fixtures/blockchain.py +++ b/src/ethereum_test_fixtures/blockchain.py @@ -396,6 +396,12 @@ def without_rlp(self) -> FixtureBlockBase: ) +class FixtureConfig(CamelModel): + """Chain configuration for a fixture.""" + + fork: str = Field(..., alias="network") + + class InvalidFixtureBlock(CamelModel): """Representation of an invalid Ethereum block within a test Fixture.""" @@ -412,6 +418,7 @@ class BlockchainFixtureCommon(BaseFixture): pre: Alloc post_state: Alloc | None = Field(None) last_block_hash: Hash = Field(..., alias="lastblockhash") # FIXME: lastBlockHash + config: FixtureConfig def get_fork(self) -> str | None: """Return fork of the fixture as a string.""" diff --git a/src/ethereum_test_fixtures/state.py b/src/ethereum_test_fixtures/state.py index 871a4f75abe..9e2bb8da6f5 100644 --- a/src/ethereum_test_fixtures/state.py +++ b/src/ethereum_test_fixtures/state.py @@ -86,6 +86,12 @@ class FixtureForkPost(CamelModel): expect_exception: TransactionExceptionInstanceOrList | None = None +class FixtureConfig(CamelModel): + """Chain configuration for a fixture.""" + + pass + + class StateFixture(BaseFixture): """Fixture for a single StateTest.""" @@ -96,6 +102,7 @@ class StateFixture(BaseFixture): pre: Alloc transaction: FixtureTransaction post: Mapping[str, List[FixtureForkPost]] + config: FixtureConfig def get_fork(self) -> str | None: """Return fork of the fixture as a string.""" diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py index cd68f018161..dd749dff4c6 100644 --- a/src/ethereum_test_specs/blockchain.py +++ b/src/ethereum_test_specs/blockchain.py @@ -30,6 +30,7 @@ from ethereum_test_fixtures.blockchain import ( FixtureBlock, FixtureBlockBase, + FixtureConfig, FixtureEngineNewPayload, FixtureHeader, FixtureTransaction, @@ -573,14 +574,18 @@ def make_fixture( ) self.verify_post_state(t8n, t8n_state=alloc) + network_info = self.network_info(fork, eips) return BlockchainFixture( - fork=self.network_info(fork, eips), + fork=network_info, genesis=genesis.header, genesis_rlp=genesis.rlp, blocks=fixture_blocks, last_block_hash=head, pre=pre, post_state=alloc, + config=FixtureConfig( + fork=network_info, + ), ) def make_hive_fixture( @@ -666,8 +671,9 @@ def make_hive_fixture( error_code=None, ) + network_info = self.network_info(fork, eips) return BlockchainEngineFixture( - fork=self.network_info(fork, eips), + fork=network_info, genesis=genesis.header, payloads=fixture_payloads, fcu_version=fcu_version, @@ -675,6 +681,9 @@ def make_hive_fixture( post_state=alloc, sync_payload=sync_payload, last_block_hash=head_hash, + config=FixtureConfig( + fork=network_info, + ), ) def generate( diff --git a/src/ethereum_test_specs/state.py b/src/ethereum_test_specs/state.py index 59a0e3babb1..90c42bd616e 100644 --- a/src/ethereum_test_specs/state.py +++ b/src/ethereum_test_specs/state.py @@ -17,6 +17,7 @@ StateFixture, ) from ethereum_test_fixtures.state import ( + FixtureConfig, FixtureEnvironment, FixtureForkPost, FixtureTransaction, @@ -173,6 +174,7 @@ def make_state_test_fixture( ] }, transaction=FixtureTransaction.from_transaction(tx), + config=FixtureConfig(), ) def generate( diff --git a/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json b/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json index 2e1148de8e7..73c712e6a7d 100644 --- a/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json @@ -1,7 +1,7 @@ { "000/my_blockchain_test/London": { "_info": { - "hash": "0x4de3f84e3cb1e678141d81ce96ce75edb53f1824a708e26098b610c3c1030e66", + "hash": "0x76838b666ca44a330fcf031ae20392647c3251ad54f29e995890bd608948b915", "fixture_format": "blockchain_test" }, "network": "London", @@ -539,6 +539,9 @@ "storage": {} } }, - "sealEngine": "NoProof" + "sealEngine": "NoProof", + "config": { + "network": "London" + } } } diff --git a/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json b/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json index e7114716435..08690ab4e09 100644 --- a/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json @@ -1,7 +1,7 @@ { "000/my_blockchain_test/London": { "_info": { - "hash": "0x91032fb245f4488b204198312cbf16429c121435705ac3f9c6eb3943ec0bc36d", + "hash": "0x7694748a5d5e0ea1e5e914210fb8db7c8077f070dd29ffcb13774d526aee35de", "fixture_format": "blockchain_test" }, "network": "London", @@ -417,6 +417,9 @@ "storage": {} } }, - "sealEngine": "NoProof" + "sealEngine": "NoProof", + "config": { + "network": "London" + } } } diff --git a/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json index c113c079e95..72adf5b8819 100644 --- a/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json @@ -1,7 +1,7 @@ { "000/my_blockchain_test/Shanghai": { "_info": { - "hash": "0x107426e7483fe00d8db263f7522d523a6efbed5c93fd98006e65593ce496a1c4", + "hash": "0x75f8ac4dbd5bfee6046a0edd5bec5448e23d1f249c10025a47bfb46ff7dab303", "fixture_format": "blockchain_test_engine" }, "lastblockhash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", @@ -188,7 +188,6 @@ "forkchoiceUpdatedVersion": "2" } ], - "lastblockhash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", "pre": { "0x000000000000000000000000000000000000c0de": { "nonce": "0x01", @@ -313,6 +312,9 @@ "code": "0x", "storage": {} } + }, + "config": { + "network": "Shanghai" } } } \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json index 77a95f81ac5..199e7d691a8 100644 --- a/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json @@ -1,7 +1,7 @@ { "000/my_blockchain_test/Shanghai": { "_info": { - "hash": "0x9a25679729dab0fa4d90f56a7458ca2c4b7428853e9ef1e1aea6dae203926368", + "hash": "0xe0738285cd63c07ce0dbc7801ad9d91962d25edcca544bc8475d88a86cab4a15", "fixture_format": "blockchain_test_engine" }, "lastblockhash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", @@ -26,7 +26,6 @@ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "hash": "0xee9490b3af4ef92610c3d55270c3d2cab510331f4b0fa0b3c2a805eee1c454b0" }, - "lastblockhash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", "engineNewPayloads": [ { "params": [ @@ -259,6 +258,9 @@ "code": "0x", "storage": {} } + }, + "config": { + "network": "Shanghai" } } } \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json new file mode 100644 index 00000000000..13595a3946d --- /dev/null +++ b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json @@ -0,0 +1,135 @@ +{ + "000/my_chain_id_test/Cancun": { + "_info": { + "hash": "0x37875fcfb57e7ed60d05785caa956330c87de4101a83e479255af280fbf99ece", + "fixture_format": "blockchain_test" + }, + "network": "Cancun", + "genesisRLP": "0xf9023df90237a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0789d559bf5d313e15da4139b57627160d23146cf6cdf9995e0394d165b1527efa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808502540be400808000a0000000000000000000000000000000000000000000000000000000000000000088000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000c0c0c0", + "genesisBlockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x789d559bf5d313e15da4139b57627160d23146cf6cdf9995e0394d165b1527ef", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x00", + "number": "0x00", + "gasLimit": "0x02540be400", + "gasUsed": "0x00", + "timestamp": "0x00", + "extraData": "0x00", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x07", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "blobGasUsed": "0x00", + "excessBlobGas": "0x00", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash": "0x28c341ffc393152bd02e8689d8172dd66939ac3be2b91c5841721d1755d13c2b" + }, + "blocks": [ + { + "rlp": "0xf902a5f9023ba028c341ffc393152bd02e8689d8172dd66939ac3be2b91c5841721d1755d13c2ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0db94ed1be4d52fb6360c88b363cb71af08df2493e57a66ec4751f90097f2fcbba08151d548273f6683169524b66ca9fe338b9ce42bc3540046c828fd939ae23bcba0c598f69a5674cae9337261b669970e24abc0b46e6d284372a239ec8ccbf20b0ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080018502540be40082a8618203e800a0000000000000000000000000000000000000000000000000000000000000000088000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000f863f861800a8405f5e10094100000000000000000000000000000000000000080801ba07e09e26678ed4fac08a249ebe8ed680bf9051a5e14ad223e4b2b9d26e0208f37a05f6e3f188e3e6eab7d7d3b6568f5eac7d687b08d307d3154ccd8c87b4630509bc0c0", + "blockHeader": { + "parentHash": "0x28c341ffc393152bd02e8689d8172dd66939ac3be2b91c5841721d1755d13c2b", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "stateRoot": "0xdb94ed1be4d52fb6360c88b363cb71af08df2493e57a66ec4751f90097f2fcbb", + "transactionsTrie": "0x8151d548273f6683169524b66ca9fe338b9ce42bc3540046c828fd939ae23bcb", + "receiptTrie": "0xc598f69a5674cae9337261b669970e24abc0b46e6d284372a239ec8ccbf20b0a", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x00", + "number": "0x01", + "gasLimit": "0x02540be400", + "gasUsed": "0xa861", + "timestamp": "0x03e8", + "extraData": "0x00", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x07", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "blobGasUsed": "0x00", + "excessBlobGas": "0x00", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash": "0x3cce15f0f21f4ea23499856be01a090f0ea1be6bea4a11777b4d0cc70d105a4b" + }, + "blocknumber": "1", + "transactions": [ + { + "type": "0x00", + "chainId": "0x00", + "nonce": "0x00", + "gasPrice": "0x0a", + "gasLimit": "0x05f5e100", + "to": "0x1000000000000000000000000000000000000000", + "value": "0x00", + "data": "0x", + "v": "0x1b", + "r": "0x7e09e26678ed4fac08a249ebe8ed680bf9051a5e14ad223e4b2b9d26e0208f37", + "s": "0x5f6e3f188e3e6eab7d7d3b6568f5eac7d687b08d307d3154ccd8c87b4630509b", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "uncleHeaders": [], + "withdrawals": [] + } + ], + "lastblockhash": "0x3cce15f0f21f4ea23499856be01a090f0ea1be6bea4a11777b4d0cc70d105a4b", + "pre": { + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "nonce": "0x01", + "storage": {} + }, + "0x1000000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x00", + "code": "0x4660015500", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0x3635c9adc5dea00000", + "code": "0x", + "storage": {} + } + }, + "postState": { + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "nonce": "0x01", + "storage": { + "0x03e8": "0x03e8" + } + }, + "0x1000000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x00", + "code": "0x4660015500", + "storage": { + "0x01": "0x01" + } + }, + "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { + "nonce": "0x00", + "balance": "0x01f923", + "code": "0x", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x01", + "balance": "0x3635c9adc5de996c36", + "code": "0x", + "storage": {} + } + }, + "sealEngine": "NoProof", + "config": { + "network": "Cancun" + } + } +} \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json new file mode 100644 index 00000000000..a7ab004ff58 --- /dev/null +++ b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json @@ -0,0 +1,117 @@ +{ + "000/my_chain_id_test/Cancun": { + "_info": { + "hash": "0x032fd65c778b70737fffb69071aa24be48f576303ea6d5dcfbaf7b1301ad106c", + "fixture_format": "blockchain_test_engine" + }, + "network": "Cancun", + "genesisBlockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x789d559bf5d313e15da4139b57627160d23146cf6cdf9995e0394d165b1527ef", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x00", + "number": "0x00", + "gasLimit": "0x02540be400", + "gasUsed": "0x00", + "timestamp": "0x00", + "extraData": "0x00", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x07", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "blobGasUsed": "0x00", + "excessBlobGas": "0x00", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash": "0x28c341ffc393152bd02e8689d8172dd66939ac3be2b91c5841721d1755d13c2b" + }, + "engineNewPayloads": [ + { + "params": [ + { + "parentHash": "0x28c341ffc393152bd02e8689d8172dd66939ac3be2b91c5841721d1755d13c2b", + "feeRecipient": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "stateRoot": "0xdb94ed1be4d52fb6360c88b363cb71af08df2493e57a66ec4751f90097f2fcbb", + "receiptsRoot": "0xc598f69a5674cae9337261b669970e24abc0b46e6d284372a239ec8ccbf20b0a", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x2540be400", + "gasUsed": "0xa861", + "timestamp": "0x3e8", + "extraData": "0x00", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x7", + "blobGasUsed": "0x0", + "excessBlobGas": "0x0", + "blockHash": "0x3cce15f0f21f4ea23499856be01a090f0ea1be6bea4a11777b4d0cc70d105a4b", + "transactions": [ + "0xf861800a8405f5e10094100000000000000000000000000000000000000080801ba07e09e26678ed4fac08a249ebe8ed680bf9051a5e14ad223e4b2b9d26e0208f37a05f6e3f188e3e6eab7d7d3b6568f5eac7d687b08d307d3154ccd8c87b4630509b" + ], + "withdrawals": [] + }, + [], + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "newPayloadVersion": "3", + "forkchoiceUpdatedVersion": "3" + } + ], + "lastblockhash": "0x3cce15f0f21f4ea23499856be01a090f0ea1be6bea4a11777b4d0cc70d105a4b", + "pre": { + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "nonce": "0x01", + "storage": {} + }, + "0x1000000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x00", + "code": "0x4660015500", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0x3635c9adc5dea00000", + "code": "0x", + "storage": {} + } + }, + "postState": { + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "nonce": "0x01", + "storage": { + "0x03e8": "0x03e8" + } + }, + "0x1000000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x00", + "code": "0x4660015500", + "storage": { + "0x01": "0x01" + } + }, + "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { + "nonce": "0x00", + "balance": "0x01f923", + "code": "0x", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x01", + "balance": "0x3635c9adc5de996c36", + "code": "0x", + "storage": {} + } + }, + "config": { + "network": "Cancun" + } + } +} \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json new file mode 100644 index 00000000000..97f7efdfb78 --- /dev/null +++ b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json @@ -0,0 +1,85 @@ +{ + "000/my_chain_id_test/Cancun": { + "_info": { + "hash": "0x3315ff9dd48a4cbcf7c09e2df2098c8f56800e64516088f6f8eacb468382c460", + "fixture_format": "state_test" + }, + "env": { + "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentGasLimit": "0x02540be400", + "currentNumber": "0x01", + "currentTimestamp": "0x03e8", + "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000000000", + "currentDifficulty": "0x00", + "currentBaseFee": "0x07", + "currentExcessBlobGas": "0x00" + }, + "config": {}, + "pre": { + "0x1000000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x00", + "code": "0x4660015500", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0x3635c9adc5dea00000", + "code": "0x", + "storage": {} + } + }, + "transaction": { + "nonce": "0x00", + "gasPrice": "0x0a", + "gasLimit": [ + "0x05f5e100" + ], + "to": "0x1000000000000000000000000000000000000000", + "value": [ + "0x00" + ], + "data": [ + "0x" + ], + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + }, + "post": { + "Cancun": [ + { + "hash": "0x19919608275963e6e20a1191996f5b19db8208dd8df54097cfd2b9cb14f682b6", + "logs": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "txbytes": "0xf861800a8405f5e10094100000000000000000000000000000000000000080801ba07e09e26678ed4fac08a249ebe8ed680bf9051a5e14ad223e4b2b9d26e0208f37a05f6e3f188e3e6eab7d7d3b6568f5eac7d687b08d307d3154ccd8c87b4630509b", + "indexes": { + "data": 0, + "gas": 0, + "value": 0 + }, + "state": { + "0x1000000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x00", + "code": "0x4660015500", + "storage": { + "0x01": "0x01" + } + }, + "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { + "balance": "0x01f923", + "nonce": "0x00", + "code": "0x", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x01", + "balance": "0x3635c9adc5de996c36", + "code": "0x", + "storage": {} + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test.json index 3ab1e609be6..f99a79d5578 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Istanbul": { "_info": { - "hash": "0x3ca9936ff21270dd7ac781b5fafd98e4264bc9fcff4ab3cc8dff0677ccf7fc25", + "hash": "0x523fefcabce674d5b2ef4d99a151dabac431d61aff3e44f42d6d3b8a910a464b", "fixture_format": "blockchain_test" }, "network": "Istanbul", @@ -102,6 +102,9 @@ "storage": {} } }, - "sealEngine": "NoProof" + "sealEngine": "NoProof", + "config": { + "network": "Istanbul" + } } } diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test.json index a9c4ccf2930..6bbf2d39cef 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/London": { "_info": { - "hash": "0x9c09a561959f81ff5e5b081b9081bd626739fa029e9d411ea89797673366eb80", + "hash": "0xb0d368cde0d719d6d0652854133631267760c0c41a88d12144c1d8845f677088", "fixture_format": "blockchain_test" }, "network": "London", @@ -104,6 +104,9 @@ "storage": {} } }, - "sealEngine": "NoProof" + "sealEngine": "NoProof", + "config": { + "network": "London" + } } } diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine.json b/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine.json index 82c45e2b79c..70d057f49fd 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Paris": { "_info": { - "hash": "0x1c6d2ca8e03c5074e8afadbad869c90b61d2f9752c5ef2d7908900aa000a3878", + "hash": "0x72d0f1b29136f637f4e7cc22e990911fed6f9cdbd5f1987f1351cfc4efb4673b", "fixture_format": "blockchain_test_engine" }, "network": "Paris", @@ -51,7 +51,6 @@ "forkchoiceUpdatedVersion": "1" } ], - "lastblockhash": "0xe92eedff2a0489bd861f528e248994b6791b0f5b845d90b34c68bc8cbc51c369", "pre": { "0x1000000000000000000000000000000000000000": { "nonce": "0x00", @@ -87,6 +86,9 @@ "code": "0x", "storage": {} } + }, + "config": { + "network": "Paris" } } } \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test.json index 332116948b7..40dfca410fc 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Paris": { "_info": { - "hash": "0x14d892cf15f595cc7160e0e66020fa553252c33fc185c3b825bb018d4aac62b6", + "hash": "0x1384e915045d477e8d6d0b26fa32f27cc0d30ec2b05f3b166d48d4134017e071", "fixture_format": "state_test" }, "env": { @@ -78,6 +78,7 @@ } } ] - } + }, + "config": {} } } \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine.json b/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine.json index 24785254ee6..6e7e4b1229b 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Shanghai": { "_info": { - "hash": "0xfeded8f82a93725388c2436c76ea328cf2008dab43000de76306b3ed95de63b7", + "hash": "0x0853409d8524239ae79581d1fcf8d2da12dc98cd7c1cfd7d730d33ec75e0c56e", "fixture_format": "blockchain_test_engine" }, "lastblockhash": "0x9c10141361e180632f7973f4f3a0aed2baa5ebb776bae84caafdcc07a24933e8", @@ -53,7 +53,6 @@ "forkchoiceUpdatedVersion": "2" } ], - "lastblockhash": "0x9c10141361e180632f7973f4f3a0aed2baa5ebb776bae84caafdcc07a24933e8", "pre": { "0x1000000000000000000000000000000000000000": { "nonce": "0x00", @@ -89,6 +88,9 @@ "code": "0x", "storage": {} } + }, + "config": { + "network": "Shanghai" } } } \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test.json index 404a9afabde..1a542e42f24 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Shanghai": { "_info": { - "hash": "0x288556997e3809e7b3a3f97415a661600fdf3652e9fedf617264d70ce255893f", + "hash": "0x2f1baaa3821157d4bc534b6a0f6908a9900839261b7e6347d3dc5206b8a333b3", "fixture_format": "state_test" }, "env": { @@ -78,6 +78,7 @@ } } ] - } + }, + "config": {} } } \ No newline at end of file From cacab7f63740148b39a003211db6c31cc8c50e96 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Wed, 15 Jan 2025 01:03:20 +0000 Subject: [PATCH 6/7] feat(types,forks,fixtures,specs): EIP-7691: Add blob schedule Co-authored-by: danceratopz --- docs/CHANGELOG.md | 2 + docs/consuming_tests/blockchain_test.md | 4 ++ .../consuming_tests/blockchain_test_engine.md | 4 ++ docs/consuming_tests/common_types.md | 20 ++++++ docs/consuming_tests/state_test.md | 6 +- src/ethereum_test_base_types/__init__.py | 14 +++- .../composite_types.py | 26 +++++++ src/ethereum_test_fixtures/blockchain.py | 2 + src/ethereum_test_fixtures/common.py | 37 ++++++++++ src/ethereum_test_fixtures/state.py | 12 +++- src/ethereum_test_forks/__init__.py | 2 + src/ethereum_test_forks/base_fork.py | 9 ++- src/ethereum_test_forks/forks/forks.py | 30 ++++++++- src/ethereum_test_forks/tests/test_forks.py | 67 +++++++++++++++++-- src/ethereum_test_specs/blockchain.py | 3 + src/ethereum_test_specs/state.py | 5 +- .../chainid_cancun_blockchain_test.json | 11 ++- ...chainid_cancun_blockchain_test_engine.json | 11 ++- .../fixtures/chainid_cancun_state_test.json | 12 +++- .../tests/test_fixtures.py | 24 ++++--- 20 files changed, 274 insertions(+), 27 deletions(-) create mode 100644 src/ethereum_test_fixtures/common.py diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 6465f14da79..6442b9dad94 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -80,6 +80,7 @@ Release tarball changes: - ✨ Allow verification of the transaction receipt on executed test transactions ([#1068](https://github.com/ethereum/execution-spec-tests/pull/1068)). - ✨ Modify `valid_at_transition_to` marker to add keyword arguments `subsequent_transitions` and `until` to fill a test using multiple transition forks ([#1081](https://github.com/ethereum/execution-spec-tests/pull/1081)). - 🐞 fix(consume): use `"HIVE_CHECK_LIVE_PORT"` to signal hive to wait for port 8551 (Engine API port) instead of the 8545 port when running `consume engine` ([#1095](https://github.com/ethereum/execution-spec-tests/pull/1095)). +- ✨ `state_test`, `blockchain_test` and `blockchain_test_engine` fixtures now contain the `blobSchedule` from [EIP-7840](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7840.md), only for tests filled for Cancun and Prague forks ([#1040](https://github.com/ethereum/execution-spec-tests/pull/1040)). ### 🔧 EVM Tools @@ -107,6 +108,7 @@ Release tarball changes: - The EOF fixture format contained in `eof_tests` may now contain multiple exceptions in the `"exception"` field in the form of a pipe (`|`) separated string ([#759](https://github.com/ethereum/execution-spec-tests/pull/759)). - Remove redundant tests within stable and develop fixture releases, moving them to a separate legacy release ([#788](https://github.com/ethereum/execution-spec-tests/pull/788)). - Ruff now replaces Flake8, Isort and Black resulting in significant changes to the entire code base including its usage ([#922](https://github.com/ethereum/execution-spec-tests/pull/922)). +- `state_test`, `blockchain_test` and `blockchain_test_engine` fixtures now contain a `config` field, which contains an object that contains a `blobSchedule` field. On the `blockchain_test` and `blockchain_test_engine` fixtures, the object also contains a duplicate of the `network` root field. The root's `network` field will be eventually deprecated ([#1040](https://github.com/ethereum/execution-spec-tests/pull/1040)). ## [v3.0.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v3.0.0) - 2024-07-22 diff --git a/docs/consuming_tests/blockchain_test.md b/docs/consuming_tests/blockchain_test.md index 0162366ff9a..6ac0c544e22 100644 --- a/docs/consuming_tests/blockchain_test.md +++ b/docs/consuming_tests/blockchain_test.md @@ -98,6 +98,10 @@ Chain configuration object to be applied to the client running the blockchain te Fork configuration for the test. It is guaranteed that this field contains the same value as the root field `network`. +#### - `blobSchedule`: [`BlobSchedule`](./common_types.md#blobschedule-mappingforkforkblobschedule) + +Optional; present from Cancun on. Maps forks to their blob schedule configurations as defined by [EIP-7840](https://eips.ethereum.org/EIPS/eip-7840). + ### `FixtureHeader` #### - `parentHash`: [`Hash`](./common_types.md#hash) diff --git a/docs/consuming_tests/blockchain_test_engine.md b/docs/consuming_tests/blockchain_test_engine.md index aa08879e429..f03e37eb4a7 100644 --- a/docs/consuming_tests/blockchain_test_engine.md +++ b/docs/consuming_tests/blockchain_test_engine.md @@ -85,6 +85,10 @@ Chain configuration object to be applied to the client running the blockchain en Fork configuration for the test. It is guaranteed that this field contains the same value as the root field `network`. +#### - `blobSchedule`: [`BlobSchedule`](./common_types.md#blobschedule-mappingforkforkblobschedule) + +Optional; present from Cancun on. Maps forks to their blob schedule configurations as defined by [EIP-7840](https://eips.ethereum.org/EIPS/eip-7840). + ### `FixtureEngineNewPayload` #### - `executionPayload`: [`FixtureExecutionPayload`](#fixtureexecutionpayload) diff --git a/docs/consuming_tests/common_types.md b/docs/consuming_tests/common_types.md index 176175551ee..2cf3b1a0d43 100644 --- a/docs/consuming_tests/common_types.md +++ b/docs/consuming_tests/common_types.md @@ -82,6 +82,26 @@ Storage of the account. State allocation represented as a JSON object, where the keys are the addresses of the accounts, and the values are the accounts. +### `BlobSchedule`: [`Mapping`](#mapping)`[`[`Fork`](#fork)`,`[`ForkBlobSchedule`](#forkblobschedule)`]` + +Maps forks to blob schedule configurations as defined by [EIP-7840](https://eips.ethereum.org/EIPS/eip-7840). + +### `ForkBlobSchedule` + +A fork blob schedule as defined by [EIP-7840](https://eips.ethereum.org/EIPS/eip-7840) as a JSON dictionary with the following entries: + +#### - `target`: [`ZeroPaddedHexNumber`](#zeropaddedhexnumber) + +The target blob count for a block. + +#### - `max`: [`ZeroPaddedHexNumber`](#zeropaddedhexnumber) + +The maximum possible blob count for a block. + +#### - `base_fee_update_fraction`: [`ZeroPaddedHexNumber`](#zeropaddedhexnumber) + +The blob base fee update fraction (adjusts the responsiveness of blob gas pricing per fork). + ## Fork Fork type is represented as a JSON string that can be set to one of the following values: diff --git a/docs/consuming_tests/state_test.md b/docs/consuming_tests/state_test.md index ae77289e6f5..c642d7ef9db 100644 --- a/docs/consuming_tests/state_test.md +++ b/docs/consuming_tests/state_test.md @@ -66,7 +66,11 @@ Chain configuration object. ### `FixtureConfig` -At the moment, this object is an empty dictionary and contains no fields. +At the moment this object can contain only the `blobSchedule` that is necessary to apply the correct cap to the maximum amount of blobs that a transaction can have. Otherwise, in forks prior to Cancun for example, it will be an empty JSON object. + +#### - `blobSchedule`: [`BlobSchedule`](./common_types.md#blobschedule-mappingforkforkblobschedule) + +Optional; present from Cancun on. Maps forks to their blob schedule configurations as defined by [EIP-7840](https://eips.ethereum.org/EIPS/eip-7840). ### `FixtureEnvironment` diff --git a/src/ethereum_test_base_types/__init__.py b/src/ethereum_test_base_types/__init__.py index c274593207c..1d926437430 100644 --- a/src/ethereum_test_base_types/__init__.py +++ b/src/ethereum_test_base_types/__init__.py @@ -16,7 +16,15 @@ Wei, ZeroPaddedHexNumber, ) -from .composite_types import AccessList, Account, Alloc, Storage, StorageRootType +from .composite_types import ( + AccessList, + Account, + Alloc, + BlobSchedule, + ForkBlobSchedule, + Storage, + StorageRootType, +) from .constants import ( AddrAA, AddrBB, @@ -39,6 +47,7 @@ "AddrBB", "Address", "Alloc", + "BlobSchedule", "Bloom", "BLSPublicKey", "BLSSignature", @@ -46,9 +55,10 @@ "CamelModel", "EmptyOmmersRoot", "EmptyTrieRoot", - "FixedSizeBytes", "EthereumTestBaseModel", "EthereumTestRootModel", + "FixedSizeBytes", + "ForkBlobSchedule", "Hash", "HashInt", "HeaderNonce", diff --git a/src/ethereum_test_base_types/composite_types.py b/src/ethereum_test_base_types/composite_types.py index 15789ce6d2c..b445f786fd1 100644 --- a/src/ethereum_test_base_types/composite_types.py +++ b/src/ethereum_test_base_types/composite_types.py @@ -462,3 +462,29 @@ class AccessList(CamelModel): def to_list(self) -> List[Address | List[Hash]]: """Return access list as a list of serializable elements.""" return [self.address, self.storage_keys] + + +class ForkBlobSchedule(CamelModel): + """Representation of the blob schedule of a given fork.""" + + target_blobs_per_block: HexNumber = Field(..., alias="target") + max_blobs_per_block: HexNumber = Field(..., alias="max") + base_fee_update_fraction: HexNumber = Field(...) + + +class BlobSchedule(EthereumTestRootModel[Dict[str, ForkBlobSchedule]]): + """Blob schedule configuration dictionary.""" + + root: Dict[str, ForkBlobSchedule] = Field(default_factory=dict, validate_default=True) + + def append(self, *, fork: str, schedule: Any): + """Append a new fork schedule.""" + if not isinstance(schedule, ForkBlobSchedule): + schedule = ForkBlobSchedule(**schedule) + self.root[fork] = schedule + + def last(self) -> ForkBlobSchedule | None: + """Return the last schedule.""" + if len(self.root) == 0: + return None + return list(self.root.values())[-1] diff --git a/src/ethereum_test_fixtures/blockchain.py b/src/ethereum_test_fixtures/blockchain.py index a781e71c7a6..07214a23e0a 100644 --- a/src/ethereum_test_fixtures/blockchain.py +++ b/src/ethereum_test_fixtures/blockchain.py @@ -43,6 +43,7 @@ ) from .base import BaseFixture +from .common import FixtureBlobSchedule class HeaderForkRequirement(str): @@ -400,6 +401,7 @@ class FixtureConfig(CamelModel): """Chain configuration for a fixture.""" fork: str = Field(..., alias="network") + blob_schedule: FixtureBlobSchedule | None = None class InvalidFixtureBlock(CamelModel): diff --git a/src/ethereum_test_fixtures/common.py b/src/ethereum_test_fixtures/common.py new file mode 100644 index 00000000000..a7ed9099e3c --- /dev/null +++ b/src/ethereum_test_fixtures/common.py @@ -0,0 +1,37 @@ +"""Common types used to define multiple fixture types.""" + +from typing import Dict + +from pydantic import Field + +from ethereum_test_base_types import ( + BlobSchedule, + CamelModel, + EthereumTestRootModel, + ZeroPaddedHexNumber, +) + + +class FixtureForkBlobSchedule(CamelModel): + """Representation of the blob schedule of a given fork.""" + + target_blobs_per_block: ZeroPaddedHexNumber = Field(..., alias="target") + max_blobs_per_block: ZeroPaddedHexNumber = Field(..., alias="max") + base_fee_update_fraction: ZeroPaddedHexNumber = Field(...) + + +class FixtureBlobSchedule(EthereumTestRootModel[Dict[str, FixtureForkBlobSchedule]]): + """Blob schedule configuration dictionary.""" + + root: Dict[str, FixtureForkBlobSchedule] = Field(default_factory=dict, validate_default=True) + + @classmethod + def from_blob_schedule( + cls, blob_schedule: BlobSchedule | None + ) -> "FixtureBlobSchedule | None": + """Return a FixtureBlobSchedule from a BlobSchedule.""" + if blob_schedule is None: + return None + return cls( + root=blob_schedule.model_dump(), + ) diff --git a/src/ethereum_test_fixtures/state.py b/src/ethereum_test_fixtures/state.py index 9e2bb8da6f5..37d22c17762 100644 --- a/src/ethereum_test_fixtures/state.py +++ b/src/ethereum_test_fixtures/state.py @@ -4,7 +4,14 @@ from pydantic import BaseModel, Field -from ethereum_test_base_types import AccessList, Address, Alloc, Bytes, Hash, ZeroPaddedHexNumber +from ethereum_test_base_types import ( + AccessList, + Address, + Alloc, + Bytes, + Hash, + ZeroPaddedHexNumber, +) from ethereum_test_exceptions import TransactionExceptionInstanceOrList from ethereum_test_types.types import ( AuthorizationTupleGeneric, @@ -15,6 +22,7 @@ ) from .base import BaseFixture +from .common import FixtureBlobSchedule class FixtureEnvironment(EnvironmentGeneric[ZeroPaddedHexNumber]): @@ -89,7 +97,7 @@ class FixtureForkPost(CamelModel): class FixtureConfig(CamelModel): """Chain configuration for a fixture.""" - pass + blob_schedule: FixtureBlobSchedule | None = None class StateFixture(BaseFixture): diff --git a/src/ethereum_test_forks/__init__.py b/src/ethereum_test_forks/__init__.py index 20c90c901ef..94de79acf20 100644 --- a/src/ethereum_test_forks/__init__.py +++ b/src/ethereum_test_forks/__init__.py @@ -21,6 +21,7 @@ ) from .forks.transition import ( BerlinToLondonAt5, + CancunToPragueAtTime15k, ParisToShanghaiAtTime15k, ShanghaiToCancunAtTime15k, ) @@ -64,6 +65,7 @@ "Shanghai", "ShanghaiToCancunAtTime15k", "Cancun", + "CancunToPragueAtTime15k", "Prague", "Osaka", "get_transition_forks", diff --git a/src/ethereum_test_forks/base_fork.py b/src/ethereum_test_forks/base_fork.py index 9014e187e77..ca039abbc6a 100644 --- a/src/ethereum_test_forks/base_fork.py +++ b/src/ethereum_test_forks/base_fork.py @@ -5,7 +5,7 @@ from semver import Version -from ethereum_test_base_types import AccessList, Address +from ethereum_test_base_types import AccessList, Address, BlobSchedule from ethereum_test_base_types.conversions import BytesConvertible from ethereum_test_vm import EVMCodeType, Opcodes @@ -313,6 +313,13 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: """Return the max blobs per block at a given fork.""" pass + @classmethod + @prefer_transition_to_method + @abstractmethod + def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: + """Return the blob schedule up until the given fork.""" + pass + @classmethod @abstractmethod def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: diff --git a/src/ethereum_test_forks/forks/forks.py b/src/ethereum_test_forks/forks/forks.py index 5cd7eb7f5b6..5e6f208acfd 100644 --- a/src/ethereum_test_forks/forks/forks.py +++ b/src/ethereum_test_forks/forks/forks.py @@ -8,7 +8,7 @@ from semver import Version -from ethereum_test_base_types import AccessList, Address, Bytes +from ethereum_test_base_types import AccessList, Address, BlobSchedule, Bytes, ForkBlobSchedule from ethereum_test_base_types.conversions import BytesConvertible from ethereum_test_vm import EVMCodeType, Opcodes @@ -256,6 +256,11 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: """Return the max number of blobs per block at a given fork.""" raise NotImplementedError(f"Max blobs per block is not supported in {cls.name()}") + @classmethod + def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: + """At genesis, no blob schedule is used.""" + return None + @classmethod def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain beacon chain requests.""" @@ -951,6 +956,29 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: """Blobs are enabled starting from Cancun, with a static max of 6 blobs.""" return 6 + @classmethod + def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: + """ + At Cancun, the fork object runs this routine to get the updated blob + schedule. + """ + parent_fork = cls.parent() + assert parent_fork is not None, "Parent fork must be defined" + blob_schedule = parent_fork.blob_schedule(block_number, timestamp) + if blob_schedule is None: + last_blob_schedule = None + blob_schedule = BlobSchedule() + else: + last_blob_schedule = blob_schedule.last() + current_blob_schedule = ForkBlobSchedule( + target_blobs_per_block=cls.target_blobs_per_block(block_number, timestamp), + max_blobs_per_block=cls.max_blobs_per_block(block_number, timestamp), + base_fee_update_fraction=cls.blob_base_fee_update_fraction(block_number, timestamp), + ) + if last_blob_schedule is None or last_blob_schedule != current_blob_schedule: + blob_schedule.append(fork=cls.__name__, schedule=current_blob_schedule) + return blob_schedule + @classmethod def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: """At Cancun, blob type transactions are introduced.""" diff --git a/src/ethereum_test_forks/tests/test_forks.py b/src/ethereum_test_forks/tests/test_forks.py index d4328c8fdf5..dc06f692f5d 100644 --- a/src/ethereum_test_forks/tests/test_forks.py +++ b/src/ethereum_test_forks/tests/test_forks.py @@ -1,10 +1,12 @@ """Test fork utilities.""" -from typing import Mapping, cast +from typing import Dict, cast import pytest from semver import Version +from ethereum_test_base_types import BlobSchedule + from ..base_fork import Fork from ..forks.forks import ( Berlin, @@ -221,7 +223,7 @@ class PrePreAllocFork(Shanghai): """Dummy fork used for testing.""" @classmethod - def pre_allocation(cls) -> Mapping: + def pre_allocation(cls) -> Dict: """Return some starting point for allocation.""" return {"test": "test"} @@ -230,12 +232,12 @@ class PreAllocFork(PrePreAllocFork): """Dummy fork used for testing.""" @classmethod - def pre_allocation(cls) -> Mapping: + def pre_allocation(cls) -> Dict: """Add allocation to the pre-existing one from previous fork.""" return {"test2": "test2"} | super(PreAllocFork, cls).pre_allocation() -@transition_fork(to_fork=PreAllocFork, at_timestamp=15_000) +@transition_fork(to_fork=PreAllocFork, at_timestamp=15_000) # type: ignore class PreAllocTransitionFork(PrePreAllocFork): """PrePreAllocFork to PreAllocFork transition at Timestamp 15k.""" @@ -316,3 +318,60 @@ def test_tx_intrinsic_gas_functions(fork: Fork, calldata: bytes, create_tx: bool ) == intrinsic_gas ) + + +@pytest.mark.parametrize( + "fork,expected_schedule", + [ + pytest.param(Frontier, None, id="Frontier"), + pytest.param( + Cancun, + { + "Cancun": { + "target_blobs_per_block": 3, + "max_blobs_per_block": 6, + "baseFeeUpdateFraction": 3338477, + }, + }, + id="Cancun", + ), + pytest.param( + Prague, + { + "Cancun": { + "target_blobs_per_block": 3, + "max_blobs_per_block": 6, + "baseFeeUpdateFraction": 3338477, + }, + "Prague": { + "target_blobs_per_block": 6, + "max_blobs_per_block": 9, + "baseFeeUpdateFraction": 5007716, + }, + }, + id="Prague", + ), + pytest.param( + CancunToPragueAtTime15k, + { + "Cancun": { + "target_blobs_per_block": 3, + "max_blobs_per_block": 6, + "baseFeeUpdateFraction": 3338477, + }, + "Prague": { + "target_blobs_per_block": 6, + "max_blobs_per_block": 9, + "baseFeeUpdateFraction": 5007716, + }, + }, + id="CancunToPragueAtTime15k", + ), + ], +) +def test_blob_schedules(fork: Fork, expected_schedule: Dict | None): + """Test blob schedules for different forks.""" + if expected_schedule is None: + assert fork.blob_schedule() is None + else: + assert fork.blob_schedule() == BlobSchedule(**expected_schedule) diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py index dd749dff4c6..75039f11131 100644 --- a/src/ethereum_test_specs/blockchain.py +++ b/src/ethereum_test_specs/blockchain.py @@ -37,6 +37,7 @@ FixtureWithdrawal, InvalidFixtureBlock, ) +from ethereum_test_fixtures.common import FixtureBlobSchedule from ethereum_test_forks import Fork from ethereum_test_types import Alloc, Environment, Removable, Requests, Transaction, Withdrawal @@ -585,6 +586,7 @@ def make_fixture( post_state=alloc, config=FixtureConfig( fork=network_info, + blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()), ), ) @@ -683,6 +685,7 @@ def make_hive_fixture( last_block_hash=head_hash, config=FixtureConfig( fork=network_info, + blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()), ), ) diff --git a/src/ethereum_test_specs/state.py b/src/ethereum_test_specs/state.py index 90c42bd616e..56f0d01a695 100644 --- a/src/ethereum_test_specs/state.py +++ b/src/ethereum_test_specs/state.py @@ -16,6 +16,7 @@ FixtureFormat, StateFixture, ) +from ethereum_test_fixtures.common import FixtureBlobSchedule from ethereum_test_fixtures.state import ( FixtureConfig, FixtureEnvironment, @@ -174,7 +175,9 @@ def make_state_test_fixture( ] }, transaction=FixtureTransaction.from_transaction(tx), - config=FixtureConfig(), + config=FixtureConfig( + blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()), + ), ) def generate( diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json index 13595a3946d..0f3f2aa4c7f 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Cancun": { "_info": { - "hash": "0x37875fcfb57e7ed60d05785caa956330c87de4101a83e479255af280fbf99ece", + "hash": "0xdc67839b9bbea740321a4ce4cd9124e14387e74627761cf65ff425bc44d56c1e", "fixture_format": "blockchain_test" }, "network": "Cancun", @@ -129,7 +129,14 @@ }, "sealEngine": "NoProof", "config": { - "network": "Cancun" + "network": "Cancun", + "blobSchedule": { + "Cancun": { + "max": "0x06", + "target": "0x03", + "baseFeeUpdateFraction": "0x32f0ed" + } + } } } } \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json index a7ab004ff58..0d49d31f3a9 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Cancun": { "_info": { - "hash": "0x032fd65c778b70737fffb69071aa24be48f576303ea6d5dcfbaf7b1301ad106c", + "hash": "0x66186573da8dc65698bed9544ccbe25c13a1ff1039320609531e134473e7210c", "fixture_format": "blockchain_test_engine" }, "network": "Cancun", @@ -111,7 +111,14 @@ } }, "config": { - "network": "Cancun" + "network": "Cancun", + "blobSchedule": { + "Cancun": { + "max": "0x06", + "target": "0x03", + "baseFeeUpdateFraction": "0x32f0ed" + } + } } } } \ No newline at end of file diff --git a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json index 97f7efdfb78..141a67379a8 100644 --- a/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json +++ b/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test.json @@ -1,7 +1,7 @@ { "000/my_chain_id_test/Cancun": { "_info": { - "hash": "0x3315ff9dd48a4cbcf7c09e2df2098c8f56800e64516088f6f8eacb468382c460", + "hash": "0x85756178b1a4315d675dd7a25ca319b61dd1f86a665baf8d51ba7faf7f3cb444", "fixture_format": "state_test" }, "env": { @@ -14,7 +14,15 @@ "currentBaseFee": "0x07", "currentExcessBlobGas": "0x00" }, - "config": {}, + "config": { + "blobSchedule": { + "Cancun": { + "max": "0x06", + "target": "0x03", + "baseFeeUpdateFraction": "0x32f0ed" + } + } + }, "pre": { "0x1000000000000000000000000000000000000000": { "nonce": "0x00", diff --git a/src/ethereum_test_specs/tests/test_fixtures.py b/src/ethereum_test_specs/tests/test_fixtures.py index acb5b587b3a..3d252d3f2a6 100644 --- a/src/ethereum_test_specs/tests/test_fixtures.py +++ b/src/ethereum_test_specs/tests/test_fixtures.py @@ -18,7 +18,7 @@ FixtureFormat, StateFixture, ) -from ethereum_test_forks import Berlin, Fork, Istanbul, London, Paris, Shanghai +from ethereum_test_forks import Berlin, Cancun, Fork, Istanbul, London, Paris, Shanghai from ethereum_test_types import Alloc, Environment, Transaction from ethereum_test_vm import Opcodes as Op @@ -28,12 +28,15 @@ @pytest.fixture() -def fixture_hash(request: pytest.FixtureRequest): - """Set the hash based on the fork and solc version.""" - if request.node.funcargs["fork"] == Berlin: +def fixture_hash(fork: Fork) -> bytes: + """Set the fixture hash based on the fork.""" + if fork == Berlin: return bytes.fromhex("e57ad774ca") - elif request.node.funcargs["fork"] == London: + elif fork == London: return bytes.fromhex("3714102a4c") + elif fork == Cancun: + return bytes.fromhex("2885c707e3") + raise ValueError(f"Unexpected fork: {fork}") def test_check_helper_fixtures(): @@ -57,12 +60,12 @@ def test_check_helper_fixtures(): @pytest.mark.run_in_serial @pytest.mark.parametrize( - "fork,fixture_hash", + "fork", [ - (Berlin, "set using indirect & hash fixture"), - (London, "set using indirect & hash fixture"), + Berlin, + London, + Cancun, ], - indirect=["fixture_hash"], ) def test_make_genesis(fork: Fork, fixture_hash: bytes): # noqa: D103 env = Environment() @@ -104,10 +107,13 @@ def test_make_genesis(fork: Fork, fixture_hash: bytes): # noqa: D103 [ (Istanbul, BlockchainFixture), (London, BlockchainFixture), + (Cancun, BlockchainFixture), (Paris, BlockchainEngineFixture), (Shanghai, BlockchainEngineFixture), + (Cancun, BlockchainEngineFixture), (Paris, StateFixture), (Shanghai, StateFixture), + (Cancun, StateFixture), ], ) def test_fill_state_test( From f42e22425a19641148c3033a46326d7b76319c52 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Wed, 15 Jan 2025 01:06:47 +0000 Subject: [PATCH 7/7] feat(cli,specs): EIP-7691: Pass blob schedule to t8n --- src/ethereum_clis/clis/besu.py | 6 ++++-- src/ethereum_clis/tests/test_execution_specs.py | 3 +++ src/ethereum_clis/transition_tool.py | 17 +++++++++++------ src/ethereum_clis/types.py | 3 ++- src/ethereum_test_specs/blockchain.py | 1 + src/ethereum_test_specs/state.py | 1 + 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/ethereum_clis/clis/besu.py b/src/ethereum_clis/clis/besu.py index cc01d64548d..fe326e5e234 100644 --- a/src/ethereum_clis/clis/besu.py +++ b/src/ethereum_clis/clis/besu.py @@ -11,6 +11,7 @@ import requests +from ethereum_test_base_types import BlobSchedule from ethereum_test_exceptions import ( EOFException, ExceptionMapper, @@ -101,8 +102,9 @@ def evaluate( txs: List[Transaction], env: Environment, fork: Fork, - chain_id: int = 1, - reward: int = 0, + chain_id: int, + reward: int, + blob_schedule: BlobSchedule | None = None, eips: Optional[List[int]] = None, debug_output_path: str = "", state_test: bool = False, diff --git a/src/ethereum_clis/tests/test_execution_specs.py b/src/ethereum_clis/tests/test_execution_specs.py index b94ff892a8a..bc8c8a0bfa5 100644 --- a/src/ethereum_clis/tests/test_execution_specs.py +++ b/src/ethereum_clis/tests/test_execution_specs.py @@ -176,6 +176,9 @@ def test_evm_t8n( txs=txs, env=env, fork=Berlin, + chain_id=1, + reward=0, + blob_schedule=Berlin.blob_schedule(), ) assert to_json(t8n_output.alloc) == expected.get("alloc") if isinstance(t8n, ExecutionSpecsTransitionTool): diff --git a/src/ethereum_clis/transition_tool.py b/src/ethereum_clis/transition_tool.py index d68fb8439cc..6614b1928e2 100644 --- a/src/ethereum_clis/transition_tool.py +++ b/src/ethereum_clis/transition_tool.py @@ -8,7 +8,7 @@ import textwrap import time from abc import abstractmethod -from dataclasses import dataclass, field +from dataclasses import dataclass from pathlib import Path from typing import Any, Dict, List, Mapping, Optional, Type from urllib.parse import urlencode @@ -17,6 +17,7 @@ from requests.exceptions import ConnectionError as RequestsConnectionError from requests_unixsocket import Session # type: ignore +from ethereum_test_base_types import BlobSchedule from ethereum_test_exceptions import ExceptionMapper from ethereum_test_fixtures import FixtureFormat, FixtureVerifier from ethereum_test_forks import Fork @@ -136,9 +137,10 @@ class TransitionToolData: txs: List[Transaction] env: Environment fork_name: str - chain_id: int = field(default=1) - reward: int = field(default=0) - state_test: bool = field(default=False) + chain_id: int + reward: int + blob_schedule: BlobSchedule | None + state_test: bool def to_input(self) -> TransitionToolInput: """Convert the data to a TransactionToolInput object.""" @@ -155,6 +157,7 @@ def get_request_data(self) -> TransitionToolRequest: fork=self.fork_name, chain_id=self.chain_id, reward=self.reward, + blob_schedule=self.blob_schedule, ), input=self.to_input(), ) @@ -474,8 +477,9 @@ def evaluate( txs: List[Transaction], env: Environment, fork: Fork, - chain_id: int = 1, - reward: int = 0, + chain_id: int, + reward: int, + blob_schedule: BlobSchedule | None, eips: Optional[List[int]] = None, debug_output_path: str = "", state_test: bool = False, @@ -502,6 +506,7 @@ def evaluate( fork_name=fork_name, chain_id=chain_id, reward=reward, + blob_schedule=blob_schedule, state_test=state_test, ) diff --git a/src/ethereum_clis/types.py b/src/ethereum_clis/types.py index bbe29e43ade..74badc4dbee 100644 --- a/src/ethereum_clis/types.py +++ b/src/ethereum_clis/types.py @@ -4,7 +4,7 @@ from pydantic import Field -from ethereum_test_base_types import Bloom, Bytes, CamelModel, Hash, HexNumber +from ethereum_test_base_types import BlobSchedule, Bloom, Bytes, CamelModel, Hash, HexNumber from ethereum_test_types import Alloc, Environment, Transaction, TransactionReceipt @@ -60,6 +60,7 @@ class TransitionToolContext(CamelModel): fork: str chain_id: int = Field(..., alias="chainid") reward: int + blob_schedule: BlobSchedule | None class TransitionToolRequest(CamelModel): diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py index 75039f11131..267ce6b25b4 100644 --- a/src/ethereum_test_specs/blockchain.py +++ b/src/ethereum_test_specs/blockchain.py @@ -391,6 +391,7 @@ def generate_block_data( fork=fork, chain_id=self.chain_id, reward=fork.get_reward(env.number, env.timestamp), + blob_schedule=fork.blob_schedule(), eips=eips, debug_output_path=self.get_next_transition_tool_output_path(), slow_request=slow, diff --git a/src/ethereum_test_specs/state.py b/src/ethereum_test_specs/state.py index 56f0d01a695..3b10548a427 100644 --- a/src/ethereum_test_specs/state.py +++ b/src/ethereum_test_specs/state.py @@ -136,6 +136,7 @@ def make_state_test_fixture( fork=fork, chain_id=self.chain_id, reward=0, # Reward on state tests is always zero + blob_schedule=fork.blob_schedule(), eips=eips, debug_output_path=self.get_next_transition_tool_output_path(), state_test=True,