diff --git a/packages/testing/src/execution_testing/base_types/pydantic.py b/packages/testing/src/execution_testing/base_types/pydantic.py index 75f07fa263..dee04ced28 100644 --- a/packages/testing/src/execution_testing/base_types/pydantic.py +++ b/packages/testing/src/execution_testing/base_types/pydantic.py @@ -32,7 +32,14 @@ def copy(self: Self, **kwargs: Any) -> Self: """ Create a copy of the model with the updated fields that are validated. """ - return self.__class__(**(self.model_dump(exclude_unset=True) | kwargs)) + # Only include actual model fields, not computed fields + model_field_names = set(self.__class__.model_fields.keys()) + dumped = { + k: v + for k, v in self.model_dump(exclude_unset=True).items() + if k in model_field_names + } + return self.__class__(**(dumped | kwargs)) class CamelModel(CopyValidateModel): @@ -47,4 +54,5 @@ class CamelModel(CopyValidateModel): alias_generator=to_camel, populate_by_name=True, validate_default=True, + extra="forbid", ) diff --git a/packages/testing/src/execution_testing/cli/eofwrap.py b/packages/testing/src/execution_testing/cli/eofwrap.py index cf8ea29744..2f37444134 100644 --- a/packages/testing/src/execution_testing/cli/eofwrap.py +++ b/packages/testing/src/execution_testing/cli/eofwrap.py @@ -355,8 +355,8 @@ def _wrap_fixture( fixture_tx_dump.pop("ty") fixture_tx_dump.pop("data") tx = Transaction( - type=fixture_tx.ty, - input=fixture_tx.data, + ty=fixture_tx.ty, + data=fixture_tx.data, **fixture_tx_dump, ) block.txs.append(tx) diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/execute_types.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/execute_types.py index c5391ef6d0..e82a61d31f 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/execute_types.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/execute_types.py @@ -333,6 +333,8 @@ def preprocess_fork_times_blocks(cls, data: Any) -> Any: if synonym: stripped_key = synonym else: + # Remove deprecated fork keys that have no synonym + data.pop(key) continue fork_activation_times[stripped_key] = data.pop(key) if fork_activation_times: @@ -360,7 +362,8 @@ class Genesis(CamelModel): def hash(self) -> Hash: """Calculate the genesis hash.""" dumped_genesis = self.model_dump( - mode="json", exclude={"config", "alloc"} + mode="json", + exclude={"config", "alloc", "nonce", "mixhash", "parent_hash"}, ) genesis_fork = self.config.fork() env = Environment(**dumped_genesis).set_fork_requirements(genesis_fork) diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/tests/test_genesis.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/tests/test_genesis.py index 8454399e5c..5e42440953 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/tests/test_genesis.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/eth_config/tests/test_genesis.py @@ -76,28 +76,44 @@ def genesis_contents(genesis_file_name: str) -> str: ), blob_schedule={ Cancun: ForkConfigBlobSchedule( - target=3, max=6, baseFeeUpdateFraction=3338477 + target_blobs_per_block=3, + max_blobs_per_block=6, + base_fee_update_fraction=3338477, ), Prague: ForkConfigBlobSchedule( - target=6, max=9, baseFeeUpdateFraction=5007716 + target_blobs_per_block=6, + max_blobs_per_block=9, + base_fee_update_fraction=5007716, ), Osaka: ForkConfigBlobSchedule( - target=6, max=9, baseFeeUpdateFraction=5007716 + target_blobs_per_block=6, + max_blobs_per_block=9, + base_fee_update_fraction=5007716, ), BPO1: ForkConfigBlobSchedule( - target=9, max=12, baseFeeUpdateFraction=5007716 + target_blobs_per_block=9, + max_blobs_per_block=12, + base_fee_update_fraction=5007716, ), BPO2: ForkConfigBlobSchedule( - target=12, max=15, baseFeeUpdateFraction=5007716 + target_blobs_per_block=12, + max_blobs_per_block=15, + base_fee_update_fraction=5007716, ), BPO3: ForkConfigBlobSchedule( - target=15, max=18, baseFeeUpdateFraction=5007716 + target_blobs_per_block=15, + max_blobs_per_block=18, + base_fee_update_fraction=5007716, ), BPO4: ForkConfigBlobSchedule( - target=6, max=9, baseFeeUpdateFraction=5007716 + target_blobs_per_block=6, + max_blobs_per_block=9, + base_fee_update_fraction=5007716, ), BPO5: ForkConfigBlobSchedule( - target=15, max=20, baseFeeUpdateFraction=5007716 + target_blobs_per_block=15, + max_blobs_per_block=20, + base_fee_update_fraction=5007716, ), }, ), diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/tests/test_filling_session.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/tests/test_filling_session.py index 9a5bda6345..f74dff6da6 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/tests/test_filling_session.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/tests/test_filling_session.py @@ -86,8 +86,8 @@ def test_init_use_pre_alloc(self) -> None: pre=Alloc().model_dump(mode="json"), environment=Environment() .set_fork_requirements(Prague) - .model_dump(mode="json"), - network=Prague.name(), + .model_dump(mode="json", exclude={"parent_hash"}), + fork=Prague.name(), ) test_group = test_group_builder.build() mock_groups = PreAllocGroups(root={"test_hash": test_group}) @@ -171,8 +171,8 @@ def test_get_pre_alloc_group(self) -> None: pre=Alloc().model_dump(mode="json"), environment=Environment() .set_fork_requirements(Prague) - .model_dump(mode="json"), - network=Prague.name(), + .model_dump(mode="json", exclude={"parent_hash"}), + fork=Prague.name(), ) test_group = test_group_builder.build() mock_groups = PreAllocGroups(root={"test_hash": test_group}) @@ -239,8 +239,8 @@ def test_update_pre_alloc_group(self) -> None: pre=Alloc().model_dump(mode="json"), environment=Environment() .set_fork_requirements(Prague) - .model_dump(mode="json"), - network=Prague.name(), + .model_dump(mode="json", exclude={"parent_hash"}), + fork=Prague.name(), ) session.update_pre_alloc_group_builder("test_hash", test_group_builder) @@ -265,8 +265,8 @@ def test_update_pre_alloc_group_wrong_phase(self) -> None: pre=Alloc().model_dump(mode="json"), environment=Environment() .set_fork_requirements(Prague) - .model_dump(mode="json"), - network=Prague.name(), + .model_dump(mode="json", exclude={"parent_hash"}), + fork=Prague.name(), ) with pytest.raises( ValueError, @@ -291,8 +291,8 @@ def test_save_pre_alloc_groups(self) -> None: pre=Alloc().model_dump(mode="json"), environment=Environment() .set_fork_requirements(Prague) - .model_dump(mode="json"), - network=Prague.name(), + .model_dump(mode="json", exclude={"parent_hash"}), + fork=Prague.name(), ) session.update_pre_alloc_group_builder("test_hash", test_group_builder) diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/pytest_hive/hive_info.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/pytest_hive/hive_info.py index aac72ee27c..2afea60421 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/pytest_hive/hive_info.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/pytest_hive/hive_info.py @@ -49,6 +49,10 @@ class ClientFile(RootModel, YAMLModel): class HiveInfo(CamelModel): """Hive instance information.""" + # Allow extra fields: HiveInfo parses external hive API responses which + # may include fields not defined in this model. + model_config = CamelModel.model_config | {"extra": "ignore"} + command: List[str] client_file: ClientFile = Field( default_factory=lambda: ClientFile(root=[]) 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 f8950ecab0..e56896262d 100644 --- a/packages/testing/src/execution_testing/client_clis/cli_types.py +++ b/packages/testing/src/execution_testing/client_clis/cli_types.py @@ -77,6 +77,7 @@ class TraceLine(CamelModel): refund: int op_name: str error: str | None = None + return_data: str | None = None def are_equivalent(self, other: Self) -> bool: """Return True if the only difference is the gas counter.""" diff --git a/packages/testing/src/execution_testing/client_clis/tests/test_execution_specs.py b/packages/testing/src/execution_testing/client_clis/tests/test_execution_specs.py index 80c44a9920..df0d35b6a6 100644 --- a/packages/testing/src/execution_testing/client_clis/tests/test_execution_specs.py +++ b/packages/testing/src/execution_testing/client_clis/tests/test_execution_specs.py @@ -198,9 +198,6 @@ def test_evm_t8n( for key in missing_receipt_fields: for i, _ in enumerate(expected.get("result")["receipts"]): del expected.get("result")["receipts"][i][key] - for i, receipt in enumerate(expected.get("result")["receipts"]): - if int(receipt["logsBloom"], 16) == 0: - del expected.get("result")["receipts"][i]["logsBloom"] t8n_result = to_json(t8n_output.result) for i, _ in enumerate(expected.get("result")["rejected"]): diff --git a/packages/testing/src/execution_testing/fixtures/blockchain.py b/packages/testing/src/execution_testing/fixtures/blockchain.py index d5476034ab..77c58d984e 100644 --- a/packages/testing/src/execution_testing/fixtures/blockchain.py +++ b/packages/testing/src/execution_testing/fixtures/blockchain.py @@ -143,6 +143,10 @@ class FixtureHeader(CamelModel): We combine the `Environment` and `Result` contents to create this model. """ + # Allow extra fields: FixtureHeader is constructed from merged Result and + # Environment data via model_dump(), which includes fields not in this model. + model_config = CamelModel.model_config | {"extra": "ignore"} + parent_hash: Hash = Hash(0) ommers_hash: Hash = Field(Hash(EmptyOmmersRoot), alias="uncleHash") fee_recipient: Address = Field( @@ -293,6 +297,10 @@ class FixtureExecutionPayload(CamelModel): Representation of an Ethereum execution payload within a test Fixture. """ + # Allow extra fields: FixtureExecutionPayload is constructed from + # FixtureHeader via model_dump(), which includes fields not in this model. + model_config = CamelModel.model_config | {"extra": "ignore"} + parent_hash: Hash fee_recipient: Address state_root: Hash @@ -333,7 +341,7 @@ def from_fixture_header( transactions, a list of withdrawals, and an optional block access list. """ return cls( - **header.model_dump(exclude={"rlp"}, exclude_none=True), + **header.model_dump(exclude_none=True), transactions=[tx.rlp() for tx in transactions], withdrawals=withdrawals, block_access_list=block_access_list, @@ -460,6 +468,10 @@ class FixtureTransaction( ): """Representation of an Ethereum transaction within a test Fixture.""" + # Allow extra fields: FixtureTransaction is constructed from + # Transaction via model_dump(), which includes fields not in this model. + model_config = CamelModel.model_config | {"extra": "ignore"} + authorization_list: List[FixtureAuthorizationTuple] | None = None initcodes: List[Bytes] | None = None @@ -505,6 +517,18 @@ class FixtureBlockBase(CamelModel): bytes. """ + @model_validator(mode="before") + @classmethod + def strip_block_number_computed_field(cls, data: Any) -> Any: + """ + Strip the block_number computed field which gets included in model_dump() + but is not a valid input field. + """ + if isinstance(data, dict): + data.pop("blocknumber", None) + data.pop("block_number", None) + return data + header: FixtureHeader = Field(..., alias="blockHeader") txs: List[FixtureTransaction] = Field( default_factory=list, alias="transactions" @@ -517,6 +541,7 @@ class FixtureBlockBase(CamelModel): block_access_list: BlockAccessList | None = Field( None, description="EIP-7928 Block Access List" ) + fork: Fork | None = Field(None, exclude=True) @computed_field(alias="blocknumber") # type: ignore[prop-decorator] @cached_property @@ -677,6 +702,10 @@ class BlockchainEngineXFixture(BlockchainEngineFixtureCommon): test execution without client restarts. """ + # Allow extra fields: BlockchainEngineXFixture is constructed from shared + # fixture_data that includes fields for other fixture formats (e.g. genesis). + model_config = CamelModel.model_config | {"extra": "ignore"} + format_name: ClassVar[str] = "blockchain_test_engine_x" description: ClassVar[str] = ( "Tests that generate a Blockchain Test Engine X fixture." diff --git a/packages/testing/src/execution_testing/fixtures/common.py b/packages/testing/src/execution_testing/fixtures/common.py index 5f5f1a2818..17aa874852 100644 --- a/packages/testing/src/execution_testing/fixtures/common.py +++ b/packages/testing/src/execution_testing/fixtures/common.py @@ -1,8 +1,8 @@ """Common types used to define multiple fixture types.""" -from typing import Dict +from typing import Any, Dict -from pydantic import AliasChoices, Field +from pydantic import AliasChoices, Field, model_validator from execution_testing.base_types import ( BlobSchedule, @@ -51,6 +51,10 @@ class FixtureAuthorizationTuple( ): """Authorization tuple for fixture transactions.""" + # Allow extra fields: FixtureAuthorizationTuple is constructed from + # AuthorizationTuple via model_dump(), which includes fields not in this model. + model_config = CamelModel.model_config | {"extra": "ignore"} + v: ZeroPaddedHexNumber = Field( validation_alias=AliasChoices("v", "yParity") ) @@ -59,12 +63,26 @@ class FixtureAuthorizationTuple( signer: Address | None = None + @model_validator(mode="before") + @classmethod + def strip_y_parity_duplicate(cls, data: Any) -> Any: + """ + Strip yParity if v is present since yParity is added as a duplicate + during serialization for compatibility. + """ + if isinstance(data, dict) and "v" in data and "yParity" in data: + data.pop("yParity") + return data + @classmethod def from_authorization_tuple( cls, auth_tuple: AuthorizationTupleGeneric ) -> "FixtureAuthorizationTuple": """Return FixtureAuthorizationTuple from an AuthorizationTuple.""" - return cls(**auth_tuple.model_dump()) + # Exclude fields that don't exist in FixtureAuthorizationTuple + auth_dump = auth_tuple.model_dump() + auth_dump.pop("secret_key", None) + return cls(**auth_dump) def sign(self) -> None: """Sign the current object for further serialization.""" diff --git a/packages/testing/src/execution_testing/fixtures/pre_alloc_groups.py b/packages/testing/src/execution_testing/fixtures/pre_alloc_groups.py index 904d2d08e8..989a10a0bd 100644 --- a/packages/testing/src/execution_testing/fixtures/pre_alloc_groups.py +++ b/packages/testing/src/execution_testing/fixtures/pre_alloc_groups.py @@ -257,8 +257,6 @@ class PreAllocGroup(PreAllocGroupBuilder): pre-allocation group optimization. """ - # Allow both field names and aliases - model_config = {"populate_by_name": True} pre: GroupPreAlloc genesis: FixtureHeader pre_account_count: int diff --git a/packages/testing/src/execution_testing/fixtures/state.py b/packages/testing/src/execution_testing/fixtures/state.py index 8864f2b145..a69eb35899 100644 --- a/packages/testing/src/execution_testing/fixtures/state.py +++ b/packages/testing/src/execution_testing/fixtures/state.py @@ -28,12 +28,20 @@ class FixtureEnvironment(EnvironmentGeneric[ZeroPaddedHexNumber]): """Type used to describe the environment of a state test.""" + # Allow extra fields: FixtureEnvironment is constructed from Environment + # via model_dump(), which includes many fields not in EnvironmentGeneric. + model_config = CamelModel.model_config | {"extra": "ignore"} + prev_randao: Hash | None = Field(None, alias="currentRandom") # type: ignore class FixtureTransaction(TransactionFixtureConverter): """Type used to describe a transaction in a state test.""" + # Allow extra fields: FixtureTransaction is constructed from Transaction + # via model_dump(), which includes many fields not in this model. + model_config = CamelModel.model_config | {"extra": "ignore"} + nonce: ZeroPaddedHexNumber gas_price: ZeroPaddedHexNumber | None = None max_priority_fee_per_gas: ZeroPaddedHexNumber | None = None diff --git a/packages/testing/src/execution_testing/fixtures/tests/test_base.py b/packages/testing/src/execution_testing/fixtures/tests/test_base.py index 5b8d422d58..9aaa251329 100644 --- a/packages/testing/src/execution_testing/fixtures/tests/test_base.py +++ b/packages/testing/src/execution_testing/fixtures/tests/test_base.py @@ -11,7 +11,7 @@ def test_json_dict() -> None: """Test that the json_dict property does not include the info field.""" fixture = TransactionFixture( - txbytes="0x1234", + transaction="0x1234", result={"Paris": FixtureResult(intrinsic_gas=0)}, ) assert "_info" not in fixture.json_dict, ( diff --git a/packages/testing/src/execution_testing/fixtures/tests/test_blockchain.py b/packages/testing/src/execution_testing/fixtures/tests/test_blockchain.py index 381109811f..966b8359bb 100644 --- a/packages/testing/src/execution_testing/fixtures/tests/test_blockchain.py +++ b/packages/testing/src/execution_testing/fixtures/tests/test_blockchain.py @@ -396,7 +396,7 @@ blob_gas_used=17, excess_blob_gas=18, ), - transactions=[ + txs=[ FixtureTransaction.from_transaction( Transaction().with_signature_and_sender() ) @@ -470,7 +470,7 @@ blob_gas_used=17, excess_blob_gas=18, ), - transactions=[ + txs=[ FixtureTransaction.from_transaction( Transaction(to=None).with_signature_and_sender() ) diff --git a/packages/testing/src/execution_testing/rpc/rpc_types.py b/packages/testing/src/execution_testing/rpc/rpc_types.py index 19ce78ef1d..e4aec4827b 100644 --- a/packages/testing/src/execution_testing/rpc/rpc_types.py +++ b/packages/testing/src/execution_testing/rpc/rpc_types.py @@ -149,6 +149,8 @@ class PayloadAttributes(CamelModel): suggested_fee_recipient: Address withdrawals: List[Withdrawal] | None = None parent_beacon_block_root: Hash | None = None + target_blobs_per_block: HexNumber | None = None + max_blobs_per_block: HexNumber | None = None class BlobsBundle(CamelModel): diff --git a/packages/testing/src/execution_testing/specs/blockchain.py b/packages/testing/src/execution_testing/specs/blockchain.py index 8504bc7931..0bfa1eb419 100644 --- a/packages/testing/src/execution_testing/specs/blockchain.py +++ b/packages/testing/src/execution_testing/specs/blockchain.py @@ -181,7 +181,10 @@ class Header(CamelModel): ``` """ - model_config = ConfigDict(arbitrary_types_allowed=True) + model_config = ConfigDict( + **CamelModel.model_config, + arbitrary_types_allowed=True, + ) @model_serializer(mode="wrap", when_used="json") def _serialize_model(self, serializer: Any, info: Any) -> Dict[str, Any]: diff --git a/packages/testing/src/execution_testing/test_types/block_access_list/account_absent_values.py b/packages/testing/src/execution_testing/test_types/block_access_list/account_absent_values.py index 5c9c9537f3..735a56e036 100644 --- a/packages/testing/src/execution_testing/test_types/block_access_list/account_absent_values.py +++ b/packages/testing/src/execution_testing/test_types/block_access_list/account_absent_values.py @@ -74,8 +74,6 @@ class BalAccountAbsentValues(CamelModel): """ - model_config = CamelModel.model_config | {"extra": "forbid"} - nonce_changes: List[BalNonceChange] = Field( default_factory=list, description="List of nonce changes that should NOT exist in the BAL. " diff --git a/packages/testing/src/execution_testing/test_types/block_access_list/account_changes.py b/packages/testing/src/execution_testing/test_types/block_access_list/account_changes.py index 7f6820061f..330731fd10 100644 --- a/packages/testing/src/execution_testing/test_types/block_access_list/account_changes.py +++ b/packages/testing/src/execution_testing/test_types/block_access_list/account_changes.py @@ -22,8 +22,6 @@ class BalNonceChange(CamelModel, RLPSerializable): """Represents a nonce change in the block access list.""" - model_config = CamelModel.model_config | {"extra": "forbid"} - tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -38,8 +36,6 @@ class BalNonceChange(CamelModel, RLPSerializable): class BalBalanceChange(CamelModel, RLPSerializable): """Represents a balance change in the block access list.""" - model_config = CamelModel.model_config | {"extra": "forbid"} - tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -54,8 +50,6 @@ class BalBalanceChange(CamelModel, RLPSerializable): class BalCodeChange(CamelModel, RLPSerializable): """Represents a code change in the block access list.""" - model_config = CamelModel.model_config | {"extra": "forbid"} - tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -68,8 +62,6 @@ class BalCodeChange(CamelModel, RLPSerializable): class BalStorageChange(CamelModel, RLPSerializable): """Represents a change to a specific storage slot.""" - model_config = CamelModel.model_config | {"extra": "forbid"} - tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -84,8 +76,6 @@ class BalStorageChange(CamelModel, RLPSerializable): class BalStorageSlot(CamelModel, RLPSerializable): """Represents all changes to a specific storage slot.""" - model_config = CamelModel.model_config | {"extra": "forbid"} - slot: StorageKey = Field(..., description="Storage slot key") slot_changes: List[BalStorageChange] = Field( default_factory=list, description="List of changes to this slot" @@ -97,8 +87,6 @@ class BalStorageSlot(CamelModel, RLPSerializable): class BalAccountChange(CamelModel, RLPSerializable): """Represents all changes to a specific account in a block.""" - model_config = CamelModel.model_config | {"extra": "forbid"} - address: Address = Field(..., description="Account address") nonce_changes: List[BalNonceChange] = Field( default_factory=list, description="List of nonce changes" diff --git a/packages/testing/src/execution_testing/test_types/block_access_list/expectations.py b/packages/testing/src/execution_testing/test_types/block_access_list/expectations.py index fad7017c4c..080aafc661 100644 --- a/packages/testing/src/execution_testing/test_types/block_access_list/expectations.py +++ b/packages/testing/src/execution_testing/test_types/block_access_list/expectations.py @@ -32,8 +32,6 @@ class BalAccountExpectation(CamelModel): used for expectations. """ - model_config = CamelModel.model_config | {"extra": "forbid"} - nonce_changes: List[BalNonceChange] = Field( default_factory=list, description="List of expected nonce changes" ) @@ -119,8 +117,6 @@ class BlockAccessListExpectation(CamelModel): """ - model_config = CamelModel.model_config | {"extra": "forbid"} - account_expectations: Dict[Address, BalAccountExpectation | None] = Field( default_factory=dict, description="Expected account changes or exclusions to verify", diff --git a/packages/testing/src/execution_testing/test_types/block_types.py b/packages/testing/src/execution_testing/test_types/block_types.py index 807d37a18b..2c73a558b9 100644 --- a/packages/testing/src/execution_testing/test_types/block_types.py +++ b/packages/testing/src/execution_testing/test_types/block_types.py @@ -7,7 +7,7 @@ import ethereum_rlp as eth_rlp from ethereum_types.numeric import Uint -from pydantic import Field, computed_field +from pydantic import Field, computed_field, model_validator from trie import HexaryTrie from execution_testing.base_types import ( @@ -117,6 +117,15 @@ class Environment(EnvironmentGeneric[ZeroPaddedHexNumber]): executed. """ + @model_validator(mode="before") + @classmethod + def strip_computed_fields(cls, data: Any) -> Any: + """Strip computed fields that are not valid input fields.""" + if isinstance(data, dict): + data.pop("parent_hash", None) + data.pop("parentHash", None) + return data + blob_gas_used: ZeroPaddedHexNumber | None = Field( None, alias="currentBlobGasUsed" ) diff --git a/packages/testing/src/execution_testing/test_types/receipt_types.py b/packages/testing/src/execution_testing/test_types/receipt_types.py index cdaf73859f..c2e40e1f41 100644 --- a/packages/testing/src/execution_testing/test_types/receipt_types.py +++ b/packages/testing/src/execution_testing/test_types/receipt_types.py @@ -1,8 +1,8 @@ """Transaction receipt and log types for Ethereum tests.""" -from typing import List +from typing import Any, List -from pydantic import Field +from pydantic import AliasChoices, Field, model_validator from execution_testing.base_types import ( Address, @@ -39,12 +39,26 @@ class ReceiptDelegation(CamelModel): class TransactionReceipt(CamelModel): """Transaction receipt.""" + @model_validator(mode="before") + @classmethod + def strip_extra_fields(cls, data: Any) -> Any: + """Strip extra fields from t8n tool output that are not part of the model.""" + if isinstance(data, dict): + # t8n tool returns 'succeeded' which is redundant with 'status' + data.pop("succeeded", None) + # t8n tool may return 'post_state' which is not part of this model + data.pop("post_state", None) + data.pop("postState", None) + return data + transaction_hash: Hash | None = None gas_used: HexNumber | None = None root: Bytes | None = None status: HexNumber | None = None cumulative_gas_used: HexNumber | None = None - logs_bloom: Bloom | None = None + logs_bloom: Bloom | None = Field( + None, validation_alias=AliasChoices("logs_bloom", "logsBloom", "bloom") + ) logs: List[TransactionLog] | None = None contract_address: Address | None = None effective_gas_price: HexNumber | None = None diff --git a/packages/testing/src/execution_testing/test_types/transaction_types.py b/packages/testing/src/execution_testing/test_types/transaction_types.py index ffa49e46e4..0d689f4488 100644 --- a/packages/testing/src/execution_testing/test_types/transaction_types.py +++ b/packages/testing/src/execution_testing/test_types/transaction_types.py @@ -300,7 +300,19 @@ class Transaction( ): """Generic object that can represent all Ethereum transaction types.""" - gas_limit: HexNumber = Field(HexNumber(21_000), serialization_alias="gas") + @model_validator(mode="before") + @classmethod + def strip_hash_from_t8n_output(cls, data: Any) -> Any: + """Strip the hash field which may be included in t8n tool output.""" + if isinstance(data, dict): + data.pop("hash", None) + return data + + gas_limit: HexNumber = Field( + HexNumber(21_000), + serialization_alias="gas", + validation_alias=AliasChoices("gas_limit", "gasLimit", "gas"), + ) to: Address | None = Field(Address(0xAA)) data: Bytes = Field(Bytes(b""), alias="input") diff --git a/tests/cancun/eip4844_blobs/test_blob_txs_full.py b/tests/cancun/eip4844_blobs/test_blob_txs_full.py index 82f7a5efbb..7adc5ac568 100644 --- a/tests/cancun/eip4844_blobs/test_blob_txs_full.py +++ b/tests/cancun/eip4844_blobs/test_blob_txs_full.py @@ -179,7 +179,6 @@ def txs( # noqa: D103 access_list=[], blob_versioned_hashes=tx_versioned_hashes, error=tx_error, - wrapped_blob_transaction=tx_wrapped_blobs, ) if tx_wrapped_blobs: network_wrapped_tx = NetworkWrappedTransaction( diff --git a/tests/frontier/scenarios/test_scenarios.py b/tests/frontier/scenarios/test_scenarios.py index 80d28d479f..4888c13704 100644 --- a/tests/frontier/scenarios/test_scenarios.py +++ b/tests/frontier/scenarios/test_scenarios.py @@ -278,7 +278,7 @@ def make_result( ) post[runner_contract] = Account(storage=post_storage) - blocks.append(Block(txs=[tx], post=post)) + blocks.append(Block(txs=[tx], expected_post_state=post)) if tests > 0: blockchain_test( diff --git a/tests/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py b/tests/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py index a08623f03a..af7e3191ba 100644 --- a/tests/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py +++ b/tests/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py @@ -78,16 +78,16 @@ def create_test_header(gas_used: int) -> FixtureHeader: number="0x1", gas_limit=hex(BLOCK_GAS_LIMIT), timestamp=hex(HEADER_TIMESTAMP), - coinbase="0x" + "00" * 20, + fee_recipient="0x" + "00" * 20, parent_hash="0x" + "00" * 32, - uncle_hash="0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + ommers_hash="0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", state_root="0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", transactions_trie="0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - receiptTrie="0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - bloom="0x" + "00" * 256, + receipts_root="0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + logs_bloom="0x" + "00" * 256, gas_used=hex(gas_used), extra_data=EXTRA_DATA_AT_LIMIT.hex(), - mix_hash="0x" + "00" * 32, + prev_randao="0x" + "00" * 32, nonce="0x0000000000000042", base_fee_per_gas="0x0", withdrawals_root="0x" + "00" * 32, @@ -132,9 +132,7 @@ def get_block_rlp_size( ) for w in withdrawals ] - test_block = FixtureBlockBase( - blockHeader=header, withdrawals=block_withdrawals - ) + test_block = FixtureBlockBase(header=header, withdrawals=block_withdrawals) return len(test_block.with_rlp(txs=transactions).rlp) diff --git a/tests/paris/eip7610_create_collision/test_initcollision.py b/tests/paris/eip7610_create_collision/test_initcollision.py index 181b4575b1..2f5c42789f 100644 --- a/tests/paris/eip7610_create_collision/test_initcollision.py +++ b/tests/paris/eip7610_create_collision/test_initcollision.py @@ -73,7 +73,7 @@ def test_init_collision_create_tx( """ tx = Transaction( sender=pre.fund_eoa(), - type=tx_type, + ty=tx_type, to=None, data=initcode, gas_limit=200_000, diff --git a/tests/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py b/tests/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py index 97e0df8bd9..79b78d5158 100644 --- a/tests/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py +++ b/tests/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py @@ -4,7 +4,7 @@ from os.path import realpath from pathlib import Path -from typing import Any, Dict, Generator +from typing import Dict, Generator import pytest from execution_testing import ( @@ -17,7 +17,7 @@ Transaction, generate_system_contract_deploy_test, ) -from execution_testing.forks import Prague +from execution_testing.forks import Fork, Prague from .spec import Spec, ref_spec_2935 @@ -37,10 +37,10 @@ ) def test_system_contract_deployment( *, + fork: Fork, pre: Alloc, post: Alloc, test_type: DeploymentTestType, - **kwargs: Any, ) -> Generator[Block, None, None]: """Verify deployment of the block hashes system contract.""" # Deploy a contract that calls the history contract and verifies the block diff --git a/tests/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py b/tests/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py index 2b09c0f9aa..f7160a6ea6 100644 --- a/tests/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py +++ b/tests/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py @@ -12,7 +12,6 @@ Alloc, Block, Fork, - Header, Requests, Transaction, generate_system_contract_deploy_test, @@ -66,7 +65,5 @@ def test_system_contract_deployment( yield Block( txs=[test_transaction], - header=Header( - requests_hash=Requests(withdrawal_request), - ), + requests_hash=Requests(withdrawal_request), ) diff --git a/tests/prague/eip7251_consolidations/test_contract_deployment.py b/tests/prague/eip7251_consolidations/test_contract_deployment.py index 0d9dfbeeb0..b1e14f8ef9 100644 --- a/tests/prague/eip7251_consolidations/test_contract_deployment.py +++ b/tests/prague/eip7251_consolidations/test_contract_deployment.py @@ -12,7 +12,6 @@ Alloc, Block, Fork, - Header, Requests, Transaction, generate_system_contract_deploy_test, @@ -68,7 +67,5 @@ def test_system_contract_deployment( yield Block( txs=[test_transaction], - header=Header( - requests_hash=Requests(consolidation_request), - ), + requests_hash=Requests(consolidation_request), ) diff --git a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py index 2334234800..07a5826983 100644 --- a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -3095,7 +3095,7 @@ def test_eoa_tx_after_set_code( follow_up_eoa_txs.extend( [ Transaction( - type=tx_type, + ty=tx_type, sender=auth_signer, gas_limit=500_000, to=auth_signer, @@ -3103,7 +3103,7 @@ def test_eoa_tx_after_set_code( protected=True, ), Transaction( - type=tx_type, + ty=tx_type, sender=auth_signer, gas_limit=500_000, to=auth_signer, @@ -3115,7 +3115,7 @@ def test_eoa_tx_after_set_code( case 1: follow_up_eoa_txs.append( Transaction( - type=tx_type, + ty=tx_type, sender=auth_signer, gas_limit=500_000, to=auth_signer, @@ -3131,7 +3131,7 @@ def test_eoa_tx_after_set_code( case 2: follow_up_eoa_txs.append( Transaction( - type=tx_type, + ty=tx_type, sender=auth_signer, gas_limit=500_000, to=auth_signer, @@ -3143,7 +3143,7 @@ def test_eoa_tx_after_set_code( case 3: follow_up_eoa_txs.append( Transaction( - type=tx_type, + ty=tx_type, sender=auth_signer, gas_limit=500_000, to=auth_signer,