diff --git a/.github/actions/setup-uv/action.yaml b/.github/actions/setup-uv/action.yaml
index 6c78479b96..8d5aa10b78 100644
--- a/.github/actions/setup-uv/action.yaml
+++ b/.github/actions/setup-uv/action.yaml
@@ -6,6 +6,6 @@ runs:
- name: Install UV
shell: bash
run: |
- UV_VERSION="0.4.2"
+ UV_VERSION="0.4.17"
echo "Installing UV version $UV_VERSION..."
curl -LsSf https://astral.sh/uv/${UV_VERSION}/install.sh | sh
diff --git a/.github/workflows/tox_verify.yaml b/.github/workflows/tox_verify.yaml
index dd5bdac4a3..b534eae85f 100644
--- a/.github/workflows/tox_verify.yaml
+++ b/.github/workflows/tox_verify.yaml
@@ -8,21 +8,22 @@ jobs:
strategy:
matrix:
include:
- - os: ubuntu-24.04
- python: "3.10"
- evm-type: "stable"
- tox-cmd: "uvx --with=tox-uv tox" # run-parallel --parallel-no-spinner" # TODO: disable parallelisation for uv testing
- - os: ubuntu-24.04
+ # Temporarily disable
+ # - os: ubuntu-latest
+ # python: "3.10"
+ # evm-type: "stable"
+ # tox-cmd: "uvx --with=tox-uv tox" # run-parallel --parallel-no-spinner" # TODO: disable parallelisation for uv testing
+ - os: ubuntu-latest
python: "3.12"
evm-type: "stable"
tox-cmd: "uvx --with=tox-uv tox" # run-parallel --parallel-no-spinner"
# Disabled due to unavailable evm implementation for devnet-1
- # - os: ubuntu-24.04
+ # - os: ubuntu-latest
# python: '3.11'
# evm-type: 'develop'
# tox-cmd: 'tox -e tests-develop'
# Disabled to not be gated by evmone implementation
- # - os: ubuntu-24.04
+ # - os: ubuntu-latest
# python: '3.11'
# evm-type: 'eip7692'
# tox-cmd: 'tox -e tests-eip7692'
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 63b078645e..60728028ce 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -42,6 +42,7 @@ Test fixtures for use by clients are available for each release on the [Github r
- 🐞 Fix `Conditional` code generator in EOF mode ([#821](https://github.com/ethereum/execution-spec-tests/pull/821))
- 🔀 `ethereum_test_rpc` library has been created with what was previously `ethereum_test_tools.rpc` ([#822](https://github.com/ethereum/execution-spec-tests/pull/822))
- ✨ Add `Wei` type to `ethereum_test_base_types` which allows parsing wei amounts from strings like "1 ether", "1000 wei", "10**2 gwei", etc ([#825](https://github.com/ethereum/execution-spec-tests/pull/825))
+- 🔀 Replace `ethereum.base_types` with `ethereum-types` ([#850](https://github.com/ethereum/execution-spec-tests/pull/850))
### 🔧 EVM Tools
diff --git a/pyproject.toml b/pyproject.toml
index 129d8100fb..7a9f9b4507 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,6 +39,7 @@ dependencies = [
"rich>=13.7.0,<14",
"solc-select>=1.0.4,<2",
"filelock>=3.15.1,<4",
+ "ethereum-types>=0.2.1,<0.3",
]
[project.urls]
diff --git a/src/cli/gen_index.py b/src/cli/gen_index.py
index 19e49ae6a2..8178e4d1c3 100644
--- a/src/cli/gen_index.py
+++ b/src/cli/gen_index.py
@@ -20,7 +20,7 @@
)
from ethereum_test_base_types import HexNumber
-from ethereum_test_fixtures import FixtureFormats
+from ethereum_test_fixtures import FIXTURE_FORMATS, BlockchainFixture, FixtureFormat
from ethereum_test_fixtures.consume import IndexFile, TestCaseIndexFile
from ethereum_test_fixtures.file import Fixtures
@@ -48,21 +48,16 @@ def count_json_files_exclude_index(start_path: Path) -> int:
return json_file_count
-def infer_fixture_format_from_path(file: Path) -> FixtureFormats:
+def infer_fixture_format_from_path(file: Path) -> FixtureFormat | None:
"""
Attempt to infer the fixture format from the file path.
"""
- if "blockchain_tests_engine" in file.parts:
- return FixtureFormats.BLOCKCHAIN_TEST_ENGINE
- if "blockchain_tests" in file.parts:
- return FixtureFormats.BLOCKCHAIN_TEST
+ for fixture_type in FIXTURE_FORMATS.values():
+ if fixture_type.output_base_dir_name() in file.parts:
+ return fixture_type
if "BlockchainTests" in file.parts: # ethereum/tests
- return FixtureFormats.BLOCKCHAIN_TEST
- if "state_tests" in file.parts:
- return FixtureFormats.STATE_TEST
- if "eof_tests" in file.parts:
- return FixtureFormats.EOF_TEST
- return FixtureFormats.UNSET_TEST_FORMAT
+ return BlockchainFixture
+ return None
@click.command(
@@ -200,7 +195,7 @@ def generate_fixtures_index(
json_path=relative_file_path,
fixture_hash=fixture.info.get("hash", None),
fork=fixture.get_fork(),
- format=fixture.format,
+ format=fixture.__class__,
)
)
diff --git a/src/ethereum_test_base_types/base_types.py b/src/ethereum_test_base_types/base_types.py
index 01f80df796..fb77e9e96b 100644
--- a/src/ethereum_test_base_types/base_types.py
+++ b/src/ethereum_test_base_types/base_types.py
@@ -197,12 +197,12 @@ def or_none(cls, input: "Bytes | BytesConvertible | None") -> "Bytes | None":
return input
return cls(input)
- def keccak256(self) -> "Bytes":
+ def keccak256(self) -> "Hash":
"""
Return the keccak256 hash of the opcode byte representation.
"""
k = keccak.new(digest_bits=256)
- return Bytes(k.update(bytes(self)).digest())
+ return Hash(k.update(bytes(self)).digest())
S = TypeVar("S", bound="FixedSizeHexNumber")
diff --git a/src/ethereum_test_fixtures/__init__.py b/src/ethereum_test_fixtures/__init__.py
index b6c5c9f317..455eac8a0b 100644
--- a/src/ethereum_test_fixtures/__init__.py
+++ b/src/ethereum_test_fixtures/__init__.py
@@ -2,33 +2,35 @@
Ethereum test fixture format definitions.
"""
-from typing import List, Type
+from typing import Dict
-from .base import BaseFixture
+from .base import BaseFixture, FixtureFormat
from .blockchain import EngineFixture as BlockchainEngineFixture
from .blockchain import Fixture as BlockchainFixture
from .blockchain import FixtureCommon as BlockchainFixtureCommon
from .collector import FixtureCollector, TestInfo
from .eof import Fixture as EOFFixture
-from .formats import FixtureFormats
from .state import Fixture as StateFixture
from .verify import FixtureVerifier
-FIXTURE_TYPES: List[Type[BaseFixture]] = [
- BlockchainFixture,
- BlockchainEngineFixture,
- EOFFixture,
- StateFixture,
-]
+FIXTURE_FORMATS: Dict[str, FixtureFormat] = {
+ f.fixture_format_name: f # type: ignore
+ for f in [
+ BlockchainFixture,
+ BlockchainEngineFixture,
+ EOFFixture,
+ StateFixture,
+ ]
+}
__all__ = [
- "FIXTURE_TYPES",
+ "FIXTURE_FORMATS",
"BaseFixture",
"BlockchainFixture",
"BlockchainFixtureCommon",
"BlockchainEngineFixture",
"EOFFixture",
"FixtureCollector",
- "FixtureFormats",
+ "FixtureFormat",
"FixtureVerifier",
"StateFixture",
"TestInfo",
diff --git a/src/ethereum_test_fixtures/base.py b/src/ethereum_test_fixtures/base.py
index 32298230b8..05e83ff62e 100644
--- a/src/ethereum_test_fixtures/base.py
+++ b/src/ethereum_test_fixtures/base.py
@@ -5,20 +5,30 @@
import hashlib
import json
from functools import cached_property
-from typing import Any, ClassVar, Dict
+from typing import Any, ClassVar, Dict, Type
from pydantic import Field
from ethereum_test_base_types import CamelModel, ReferenceSpec
-
-from .formats import FixtureFormats
+from ethereum_test_forks import Fork
class BaseFixture(CamelModel):
"""Represents a base Ethereum test fixture of any type."""
info: Dict[str, str] = Field(default_factory=dict, alias="_info")
- format: ClassVar[FixtureFormats] = FixtureFormats.UNSET_TEST_FORMAT
+
+ # Fixture format properties
+ fixture_format_name: ClassVar[str] = "unset"
+ output_file_extension: ClassVar[str] = ".json"
+ description: ClassVar[str] = "Unknown fixture format; it has not been set."
+
+ @classmethod
+ def output_base_dir_name(cls) -> str:
+ """
+ Returns the name of the subdirectory where this type of fixture should be dumped to.
+ """
+ return cls.fixture_format_name.replace("test", "tests")
@cached_property
def json_dict(self) -> Dict[str, Any]:
@@ -69,3 +79,16 @@ def get_fork(self) -> str | None:
Returns the fork of the fixture as a string.
"""
raise NotImplementedError
+
+ @classmethod
+ def supports_fork(cls, fork: Fork) -> bool:
+ """
+ Returns whether the fixture can be generated for the given fork.
+
+ By default, all fixtures support all forks.
+ """
+ return True
+
+
+# Type alias for a base fixture class
+FixtureFormat = Type[BaseFixture]
diff --git a/src/ethereum_test_fixtures/blockchain.py b/src/ethereum_test_fixtures/blockchain.py
index 3a0d6a2ba9..9b770ce986 100644
--- a/src/ethereum_test_fixtures/blockchain.py
+++ b/src/ethereum_test_fixtures/blockchain.py
@@ -6,8 +6,7 @@
from typing import Annotated, Any, ClassVar, List, Literal, Tuple, Union, get_args, get_type_hints
from ethereum import rlp as eth_rlp
-from ethereum.base_types import Uint
-from ethereum.crypto.hash import keccak256
+from ethereum_types.numeric import Uint
from pydantic import AliasChoices, Field, PlainSerializer, computed_field
from ethereum_test_base_types import (
@@ -24,7 +23,7 @@
ZeroPaddedHexNumber,
)
from ethereum_test_exceptions import EngineAPIError, ExceptionInstanceOrList
-from ethereum_test_forks import Fork
+from ethereum_test_forks import Fork, Paris
from ethereum_test_types.types import (
AuthorizationTupleGeneric,
ConsolidationRequest,
@@ -42,7 +41,6 @@
)
from .base import BaseFixture
-from .formats import FixtureFormats
class HeaderForkRequirement(str):
@@ -182,7 +180,7 @@ def block_hash(self) -> Hash:
"""
Compute the RLP of the header
"""
- return Hash(keccak256(self.rlp))
+ return self.rlp.keccak256()
class FixtureExecutionPayload(CamelModel):
@@ -500,19 +498,32 @@ class Fixture(FixtureCommon):
Cross-client specific blockchain test model use in JSON fixtures.
"""
+ fixture_format_name: ClassVar[str] = "blockchain_test"
+ description: ClassVar[str] = "Tests that generate a blockchain test fixture."
+
genesis_rlp: Bytes = Field(..., alias="genesisRLP")
blocks: List[FixtureBlock | InvalidFixtureBlock]
seal_engine: Literal["NoProof"] = Field("NoProof")
- format: ClassVar[FixtureFormats] = FixtureFormats.BLOCKCHAIN_TEST
-
class EngineFixture(FixtureCommon):
"""
Engine specific test fixture information.
"""
+ fixture_format_name: ClassVar[str] = "blockchain_test_engine"
+ description: ClassVar[
+ str
+ ] = "Tests that generate a blockchain test fixture in Engine API format."
+
payloads: List[FixtureEngineNewPayload] = Field(..., alias="engineNewPayloads")
sync_payload: FixtureEngineNewPayload | None = None
- format: ClassVar[FixtureFormats] = FixtureFormats.BLOCKCHAIN_TEST_ENGINE
+ @classmethod
+ def supports_fork(cls, fork: Fork) -> bool:
+ """
+ Returns whether the fixture can be generated for the given fork.
+
+ The Engine API is available only on Paris and afterwards.
+ """
+ return fork >= Paris
diff --git a/src/ethereum_test_fixtures/collector.py b/src/ethereum_test_fixtures/collector.py
index 112a1033a6..24542223fb 100644
--- a/src/ethereum_test_fixtures/collector.py
+++ b/src/ethereum_test_fixtures/collector.py
@@ -15,7 +15,6 @@
from .base import BaseFixture
from .file import Fixtures
-from .formats import FixtureFormats
from .verify import FixtureVerifier
@@ -139,8 +138,8 @@ def add_fixture(self, info: TestInfo, fixture: BaseFixture) -> Path:
fixture_path = (
self.output_dir
- / fixture.format.output_base_dir_name
- / fixture_basename.with_suffix(fixture.format.output_file_extension)
+ / fixture.output_base_dir_name()
+ / fixture_basename.with_suffix(fixture.output_file_extension)
)
if fixture_path not in self.all_fixtures.keys(): # relevant when we group by test function
self.all_fixtures[fixture_path] = Fixtures(root={})
@@ -163,7 +162,7 @@ def dump_fixtures(self) -> None:
os.makedirs(self.output_dir, exist_ok=True)
for fixture_path, fixtures in self.all_fixtures.items():
os.makedirs(fixture_path.parent, exist_ok=True)
- if len({fixture.format for fixture in fixtures.values()}) != 1:
+ if len({fixture.__class__ for fixture in fixtures.values()}) != 1:
raise TypeError("All fixtures in a single file must have the same format.")
fixtures.collect_into_file(fixture_path)
@@ -173,11 +172,11 @@ def verify_fixture_files(self, evm_fixture_verification: FixtureVerifier) -> Non
"""
for fixture_path, name_fixture_dict in self.all_fixtures.items():
for fixture_name, fixture in name_fixture_dict.items():
- if FixtureFormats.is_verifiable(fixture.format):
+ if evm_fixture_verification.is_verifiable(fixture.__class__):
info = self.json_path_to_test_item[fixture_path]
verify_fixtures_dump_dir = self._get_verify_fixtures_dump_dir(info)
evm_fixture_verification.verify_fixture(
- fixture.format,
+ fixture.__class__,
fixture_path,
fixture_name=None,
debug_output_path=verify_fixtures_dump_dir,
diff --git a/src/ethereum_test_fixtures/consume.py b/src/ethereum_test_fixtures/consume.py
index f155388e1d..ab46ee9e1f 100644
--- a/src/ethereum_test_fixtures/consume.py
+++ b/src/ethereum_test_fixtures/consume.py
@@ -5,15 +5,16 @@
import datetime
import json
from pathlib import Path
-from typing import List, TextIO
+from typing import Annotated, List, TextIO
-from pydantic import BaseModel, RootModel
+from pydantic import BaseModel, PlainSerializer, PlainValidator, RootModel
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 .file import Fixtures
-from .formats import FixtureFormats
from .state import Fixture as StateFixture
@@ -25,7 +26,11 @@ class TestCaseBase(BaseModel):
id: str
fixture_hash: HexNumber | None
fork: str | None
- format: FixtureFormats
+ format: Annotated[
+ FixtureFormat,
+ PlainSerializer(lambda f: f.fixture_format_name),
+ PlainValidator(lambda f: FIXTURE_FORMATS[f] if f in FIXTURE_FORMATS else f),
+ ]
__test__ = False # stop pytest from collecting this class as a test
@@ -129,14 +134,14 @@ def from_stream(cls, fd: TextIO) -> "TestCases":
fixtures = Fixtures.from_json_data(json.load(fd))
test_cases = []
for fixture_name, fixture in fixtures.items():
- if fixture.format == FixtureFormats.BLOCKCHAIN_TEST_ENGINE:
+ if fixture == BlockchainEngineFixture:
print("Skipping engine fixture", fixture_name)
test_cases.append(
TestCaseStream(
id=fixture_name,
fixture_hash=fixture.hash,
fork=fixture.get_fork(),
- format=fixture.format,
+ format=fixture.__class__,
fixture=fixture,
)
)
diff --git a/src/ethereum_test_fixtures/eof.py b/src/ethereum_test_fixtures/eof.py
index 987cea8ea0..ae43e0a1fa 100644
--- a/src/ethereum_test_fixtures/eof.py
+++ b/src/ethereum_test_fixtures/eof.py
@@ -12,7 +12,6 @@
from ethereum_test_types.eof.v1 import ContainerKind
from .base import BaseFixture
-from .formats import FixtureFormats
class Result(CamelModel):
@@ -50,9 +49,10 @@ class Fixture(BaseFixture):
Fixture for a single EOFTest.
"""
- vectors: Mapping[Number, Vector]
+ fixture_format_name: ClassVar[str] = "eof_test"
+ description: ClassVar[str] = "Tests that generate an EOF test fixture."
- format: ClassVar[FixtureFormats] = FixtureFormats.EOF_TEST
+ vectors: Mapping[Number, Vector]
def get_fork(self) -> str | None:
"""
diff --git a/src/ethereum_test_fixtures/file.py b/src/ethereum_test_fixtures/file.py
index ffed125bb5..3d6e573a7a 100644
--- a/src/ethereum_test_fixtures/file.py
+++ b/src/ethereum_test_fixtures/file.py
@@ -3,20 +3,16 @@
"""
import json
from pathlib import Path
-from typing import Any, Dict, Literal, Optional
+from typing import Any, Dict, Optional
from pydantic import RootModel
+from .base import FixtureFormat
from .blockchain import EngineFixture as BlockchainEngineFixture
from .blockchain import Fixture as BlockchainFixture
from .eof import Fixture as EOFFixture
-from .formats import FixtureFormats
from .state import Fixture as StateFixture
-FixtureFormatsValues = Literal[
- "blockchain_test_engine", "blockchain_test", "state_test", "eof_test", "unset_test_format"
-]
-
FixtureModel = BlockchainFixture | BlockchainEngineFixture | StateFixture | EOFFixture
@@ -75,7 +71,7 @@ def collect_into_file(self, file_path: Path):
def from_file(
cls,
file_path: Path,
- fixture_format: Optional[FixtureFormats | FixtureFormatsValues] = None,
+ fixture_format: Optional[FixtureFormat] = None,
) -> "BaseFixturesRootModel":
"""
Dynamically create a fixture model from the specified json file and,
@@ -89,7 +85,7 @@ def from_file(
def from_json_data(
cls,
json_data: Dict[str, Any],
- fixture_format: Optional[FixtureFormats | FixtureFormatsValues] = None,
+ fixture_format: Optional[FixtureFormat] = None,
) -> "BaseFixturesRootModel":
"""
Dynamically create a fixture model from the specified json data and,
@@ -101,17 +97,13 @@ def from_json_data(
fixture_format will provide a speed-up.
"""
model_mapping = {
- FixtureFormats.BLOCKCHAIN_TEST: BlockchainFixtures,
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE: BlockchainEngineFixtures,
- FixtureFormats.STATE_TEST: StateFixtures,
- FixtureFormats.EOF_TEST: EOFFixtures,
- FixtureFormats.BLOCKCHAIN_TEST.value: BlockchainFixtures,
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE.value: BlockchainEngineFixtures,
- FixtureFormats.STATE_TEST.value: StateFixtures,
- FixtureFormats.EOF_TEST.value: EOFFixtures,
+ BlockchainFixture: BlockchainFixtures,
+ BlockchainEngineFixture: BlockchainEngineFixtures,
+ StateFixture: StateFixtures,
+ EOFFixture: EOFFixtures,
}
- if fixture_format not in [None, "unset_test_format", FixtureFormats.UNSET_TEST_FORMAT]:
+ if fixture_format is not None:
if fixture_format not in model_mapping:
raise TypeError(f"Unsupported fixture format: {fixture_format}")
model_class = model_mapping[fixture_format]
diff --git a/src/ethereum_test_fixtures/formats.py b/src/ethereum_test_fixtures/formats.py
deleted file mode 100644
index 3acea77a1f..0000000000
--- a/src/ethereum_test_fixtures/formats.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""
-Fixture formats enum.
-"""
-from enum import Enum
-from pathlib import Path
-
-
-class FixtureFormats(Enum):
- """
- Helper class to define fixture formats.
- """
-
- UNSET_TEST_FORMAT = "unset_test_format"
- STATE_TEST = "state_test"
- BLOCKCHAIN_TEST = "blockchain_test"
- BLOCKCHAIN_TEST_ENGINE = "blockchain_test_engine"
- EOF_TEST = "eof_test"
-
- @classmethod
- def is_state_test(cls, format): # noqa: D102
- return format == cls.STATE_TEST
-
- @classmethod
- def is_blockchain_test(cls, format): # noqa: D102
- return format in (cls.BLOCKCHAIN_TEST, cls.BLOCKCHAIN_TEST_ENGINE)
-
- @classmethod
- def is_hive_format(cls, format): # noqa: D102
- return format == cls.BLOCKCHAIN_TEST_ENGINE
-
- @classmethod
- def is_standard_format(cls, format): # noqa: D102
- return format in (cls.STATE_TEST, cls.BLOCKCHAIN_TEST)
-
- @classmethod
- def is_verifiable(cls, format): # noqa: D102
- return format in (cls.STATE_TEST, cls.BLOCKCHAIN_TEST)
-
- @classmethod
- def get_format_description(cls, format):
- """
- Returns a description of the fixture format.
-
- Used to add a description to the generated pytest marks.
- """
- if format == cls.UNSET_TEST_FORMAT:
- return "Unknown fixture format; it has not been set."
- elif format == cls.STATE_TEST:
- return "Tests that generate a state test fixture."
- elif format == cls.BLOCKCHAIN_TEST:
- return "Tests that generate a blockchain test fixture."
- elif format == cls.BLOCKCHAIN_TEST_ENGINE:
- return "Tests that generate a blockchain test fixture in Engine API format."
- elif format == cls.EOF_TEST:
- return "Tests that generate an EOF test fixture."
- raise Exception(f"Unknown fixture format: {format}.")
-
- @property
- def output_base_dir_name(self) -> Path:
- """
- Returns the name of the subdirectory where this type of fixture should be dumped to.
- """
- return Path(self.value.replace("test", "tests"))
-
- @property
- def output_file_extension(self) -> str:
- """
- Returns the file extension for this type of fixture.
-
- By default, fixtures are dumped as JSON files.
- """
- return ".json"
diff --git a/src/ethereum_test_fixtures/state.py b/src/ethereum_test_fixtures/state.py
index d3c35b1496..7b2cbc57e2 100644
--- a/src/ethereum_test_fixtures/state.py
+++ b/src/ethereum_test_fixtures/state.py
@@ -18,7 +18,6 @@
)
from .base import BaseFixture
-from .formats import FixtureFormats
class FixtureEnvironment(EnvironmentGeneric[ZeroPaddedHexNumber]):
@@ -108,13 +107,14 @@ class Fixture(BaseFixture):
Fixture for a single StateTest.
"""
+ fixture_format_name: ClassVar[str] = "state_test"
+ description: ClassVar[str] = "Tests that generate a state test fixture."
+
env: FixtureEnvironment
pre: Alloc
transaction: FixtureTransaction
post: Mapping[str, List[FixtureForkPost]]
- format: ClassVar[FixtureFormats] = FixtureFormats.STATE_TEST
-
def get_fork(self) -> str | None:
"""
Returns the fork of the fixture as a string.
diff --git a/src/ethereum_test_fixtures/tests/test_blockchain.py b/src/ethereum_test_fixtures/tests/test_blockchain.py
index d9f98ecc7e..ab01f5f946 100644
--- a/src/ethereum_test_fixtures/tests/test_blockchain.py
+++ b/src/ethereum_test_fixtures/tests/test_blockchain.py
@@ -620,8 +620,7 @@
"excessBlobGas": hex(18),
"blockHash": "0xd90115b7fde329f64335763a446af150ab67e639281dccdb07a007d18bb80211",
"transactions": [
- "0x"
- + Transaction(
+ Transaction(
to=0x1234,
data=b"\x01\x00",
access_list=[
@@ -735,8 +734,7 @@
"0x8eca4747db6a4b272018f2850e4208b863989ce9971bb1907467ae2204950695"
),
"transactions": [
- "0x"
- + Transaction(
+ Transaction(
to=0x1234,
data=b"\x01\x00",
access_list=[
@@ -914,8 +912,7 @@
"0x78a4bf2520248e0b403d343c32b6746a43da1ebcf3cc8de14b959bc9f461fe76"
),
"transactions": [
- "0x"
- + Transaction(
+ Transaction(
to=0x1234,
data=b"\x01\x00",
access_list=[
@@ -1082,8 +1079,7 @@ def test_json_deserialization(
"blockHash": "0xd90115b7fde329f64335763a446af1"
"50ab67e639281dccdb07a007d18bb80211",
"transactions": [
- "0x"
- + Transaction(
+ Transaction(
to=0x1234,
data=b"\x01\x00",
access_list=[
@@ -1193,8 +1189,7 @@ def test_json_deserialization(
"blockHash": "0xd90115b7fde329f64335763a446af1"
"50ab67e639281dccdb07a007d18bb80211",
"transactions": [
- "0x"
- + Transaction(
+ Transaction(
to=0x1234,
data=b"\x01\x00",
access_list=[
diff --git a/src/ethereum_test_fixtures/verify.py b/src/ethereum_test_fixtures/verify.py
index c3a6faced5..234834d9ba 100644
--- a/src/ethereum_test_fixtures/verify.py
+++ b/src/ethereum_test_fixtures/verify.py
@@ -5,7 +5,7 @@
from abc import ABC, abstractmethod
from pathlib import Path
-from .formats import FixtureFormats
+from .base import FixtureFormat
class FixtureVerifier(ABC):
@@ -13,10 +13,19 @@ class FixtureVerifier(ABC):
Abstract class for verifying Ethereum test fixtures.
"""
+ def is_verifiable(
+ self,
+ fixture_format: FixtureFormat,
+ ) -> bool:
+ """
+ Returns whether the fixture format is verifiable by this verifier.
+ """
+ return False
+
@abstractmethod
def verify_fixture(
self,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
fixture_path: Path,
fixture_name: str | None = None,
debug_output_path: Path | None = None,
diff --git a/src/ethereum_test_specs/base.py b/src/ethereum_test_specs/base.py
index 9e50eb7b31..a79bf6e8ab 100644
--- a/src/ethereum_test_specs/base.py
+++ b/src/ethereum_test_specs/base.py
@@ -13,7 +13,7 @@
from pydantic import BaseModel, Field
from ethereum_test_base_types import to_hex
-from ethereum_test_fixtures import BaseFixture, FixtureFormats
+from ethereum_test_fixtures import BaseFixture, FixtureFormat
from ethereum_test_forks import Fork
from ethereum_test_types import Environment, Transaction, Withdrawal
from evm_transition_tool import Result, TransitionTool
@@ -73,7 +73,7 @@ class BaseTest(BaseModel):
t8n_dump_dir: Path | None = Field(None, exclude=True)
_t8n_call_counter: Iterator[int] = count(0)
- supported_fixture_formats: ClassVar[List[FixtureFormats]] = []
+ supported_fixture_formats: ClassVar[List[FixtureFormat]] = []
@abstractmethod
def generate(
@@ -82,7 +82,7 @@ def generate(
request: pytest.FixtureRequest,
t8n: TransitionTool,
fork: Fork,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
eips: Optional[List[int]] = None,
) -> BaseFixture:
"""
diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py
index 3d0c232387..d91fb18180 100644
--- a/src/ethereum_test_specs/blockchain.py
+++ b/src/ethereum_test_specs/blockchain.py
@@ -21,7 +21,12 @@
Number,
)
from ethereum_test_exceptions import BlockException, EngineAPIError, TransactionException
-from ethereum_test_fixtures import BaseFixture, FixtureFormats
+from ethereum_test_fixtures import (
+ BaseFixture,
+ BlockchainEngineFixture,
+ BlockchainFixture,
+ FixtureFormat,
+)
from ethereum_test_fixtures.blockchain import (
EngineFixture,
Fixture,
@@ -319,9 +324,9 @@ class BlockchainTest(BaseTest):
verify_sync: bool = False
chain_id: int = 1
- supported_fixture_formats: ClassVar[List[FixtureFormats]] = [
- FixtureFormats.BLOCKCHAIN_TEST,
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE,
+ supported_fixture_formats: ClassVar[List[FixtureFormat]] = [
+ BlockchainFixture,
+ BlockchainEngineFixture,
]
def make_genesis(
@@ -718,16 +723,16 @@ def generate(
request: pytest.FixtureRequest,
t8n: TransitionTool,
fork: Fork,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
eips: Optional[List[int]] = None,
) -> BaseFixture:
"""
Generate the BlockchainTest fixture.
"""
t8n.reset_traces()
- if fixture_format == FixtureFormats.BLOCKCHAIN_TEST_ENGINE:
+ if fixture_format == BlockchainEngineFixture:
return self.make_hive_fixture(t8n, fork, eips)
- elif fixture_format == FixtureFormats.BLOCKCHAIN_TEST:
+ elif fixture_format == BlockchainFixture:
return self.make_fixture(t8n, fork, eips)
raise Exception(f"Unknown fixture format: {fixture_format}")
diff --git a/src/ethereum_test_specs/eof.py b/src/ethereum_test_specs/eof.py
index 83a4f0417a..e251eff6f6 100644
--- a/src/ethereum_test_specs/eof.py
+++ b/src/ethereum_test_specs/eof.py
@@ -15,8 +15,15 @@
from ethereum_test_base_types import Account, Bytes
from ethereum_test_exceptions import EvmoneExceptionMapper
from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList, to_pipe_str
-from ethereum_test_fixtures import BaseFixture, FixtureFormats
-from ethereum_test_fixtures.eof import Fixture, Result, Vector
+from ethereum_test_fixtures import (
+ BaseFixture,
+ BlockchainEngineFixture,
+ BlockchainFixture,
+ EOFFixture,
+ FixtureFormat,
+ StateFixture,
+)
+from ethereum_test_fixtures.eof import Result, Vector
from ethereum_test_forks import Fork
from ethereum_test_types import Alloc, Environment, Transaction
from ethereum_test_types.eof.v1 import Container, ContainerKind
@@ -143,8 +150,8 @@ class EOFTest(BaseTest):
expect_exception: EOFExceptionInstanceOrList | None = None
container_kind: ContainerKind | None = None
- supported_fixture_formats: ClassVar[List[FixtureFormats]] = [
- FixtureFormats.EOF_TEST,
+ supported_fixture_formats: ClassVar[List[FixtureFormat]] = [
+ EOFFixture,
]
@model_validator(mode="before")
@@ -192,7 +199,7 @@ def make_eof_test_fixture(
request: pytest.FixtureRequest,
fork: Fork,
eips: Optional[List[int]],
- ) -> Fixture:
+ ) -> EOFFixture:
"""
Generate the EOF test fixture.
"""
@@ -213,7 +220,7 @@ def make_eof_test_fixture(
},
)
]
- fixture = Fixture(vectors=dict(enumerate(vectors)))
+ fixture = EOFFixture(vectors=dict(enumerate(vectors)))
try:
eof_parse = EOFParse()
except FileNotFoundError as e:
@@ -272,13 +279,13 @@ def generate(
t8n: TransitionTool,
fork: Fork,
eips: Optional[List[int]] = None,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
**_,
) -> BaseFixture:
"""
Generate the BlockchainTest fixture.
"""
- if fixture_format == FixtureFormats.EOF_TEST:
+ if fixture_format == EOFFixture:
return self.make_eof_test_fixture(request=request, fork=fork, eips=eips)
raise Exception(f"Unknown fixture format: {fixture_format}")
@@ -301,11 +308,11 @@ class EOFStateTest(EOFTest):
container_post: Account = Field(default_factory=Account)
pre: Alloc | None = None
- supported_fixture_formats: ClassVar[List[FixtureFormats]] = [
- FixtureFormats.EOF_TEST,
- FixtureFormats.STATE_TEST,
- FixtureFormats.BLOCKCHAIN_TEST,
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE,
+ supported_fixture_formats: ClassVar[List[FixtureFormat]] = [
+ EOFFixture,
+ StateFixture,
+ BlockchainFixture,
+ BlockchainEngineFixture,
]
@model_validator(mode="before")
@@ -372,22 +379,22 @@ def generate(
t8n: TransitionTool,
fork: Fork,
eips: Optional[List[int]] = None,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
**_,
) -> BaseFixture:
"""
Generate the BlockchainTest fixture.
"""
- if fixture_format == FixtureFormats.EOF_TEST:
+ if fixture_format == EOFFixture:
if self.data in existing_tests:
# Gracefully skip duplicate tests because one EOFStateTest can generate multiple
# state fixtures with the same data.
pytest.skip(f"Duplicate EOF container on EOFStateTest: {request.node.nodeid}")
return self.make_eof_test_fixture(request=request, fork=fork, eips=eips)
elif fixture_format in (
- FixtureFormats.STATE_TEST,
- FixtureFormats.BLOCKCHAIN_TEST,
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE,
+ StateFixture,
+ BlockchainFixture,
+ BlockchainEngineFixture,
):
return self.generate_state_test().generate(
request=request, t8n=t8n, fork=fork, fixture_format=fixture_format, eips=eips
diff --git a/src/ethereum_test_specs/state.py b/src/ethereum_test_specs/state.py
index dcdaac5a6b..2252393253 100644
--- a/src/ethereum_test_specs/state.py
+++ b/src/ethereum_test_specs/state.py
@@ -7,7 +7,13 @@
import pytest
from ethereum_test_exceptions import EngineAPIError
-from ethereum_test_fixtures import BaseFixture, FixtureFormats
+from ethereum_test_fixtures import (
+ BaseFixture,
+ BlockchainEngineFixture,
+ BlockchainFixture,
+ FixtureFormat,
+ StateFixture,
+)
from ethereum_test_fixtures.state import (
Fixture,
FixtureEnvironment,
@@ -39,10 +45,10 @@ class StateTest(BaseTest):
blockchain_test_rlp_modifier: Optional[Header] = None
chain_id: int = 1
- supported_fixture_formats: ClassVar[List[FixtureFormats]] = [
- FixtureFormats.BLOCKCHAIN_TEST,
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE,
- FixtureFormats.STATE_TEST,
+ supported_fixture_formats: ClassVar[List[FixtureFormat]] = [
+ BlockchainFixture,
+ BlockchainEngineFixture,
+ StateFixture,
]
def _generate_blockchain_genesis_environment(self) -> Environment:
@@ -166,7 +172,7 @@ def generate(
request: pytest.FixtureRequest,
t8n: TransitionTool,
fork: Fork,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
eips: Optional[List[int]] = None,
) -> BaseFixture:
"""
@@ -176,7 +182,7 @@ def generate(
return self.generate_blockchain_test().generate(
request=request, t8n=t8n, fork=fork, fixture_format=fixture_format, eips=eips
)
- elif fixture_format == FixtureFormats.STATE_TEST:
+ elif fixture_format == StateFixture:
return self.make_state_test_fixture(t8n, fork, eips)
raise Exception(f"Unknown fixture format: {fixture_format}")
@@ -187,7 +193,7 @@ class StateTestOnly(StateTest):
StateTest filler that only generates a state test fixture.
"""
- supported_fixture_formats: ClassVar[List[FixtureFormats]] = [FixtureFormats.STATE_TEST]
+ supported_fixture_formats: ClassVar[List[FixtureFormat]] = [StateFixture]
StateTestSpec = Callable[[str], Generator[StateTest, None, None]]
diff --git a/src/ethereum_test_specs/tests/test_expect.py b/src/ethereum_test_specs/tests/test_expect.py
index 43df2775e7..36ee92f132 100644
--- a/src/ethereum_test_specs/tests/test_expect.py
+++ b/src/ethereum_test_specs/tests/test_expect.py
@@ -7,7 +7,7 @@
import pytest
from ethereum_test_base_types import Account, Address
-from ethereum_test_fixtures import FixtureFormats
+from ethereum_test_fixtures import StateFixture
from ethereum_test_forks import Fork, get_deployed_forks
from ethereum_test_types import Alloc, Environment, Storage, Transaction
from evm_transition_tool import ExecutionSpecsTransitionTool
@@ -116,9 +116,7 @@ def test_post_storage_value_mismatch(
Test post state `Account.storage` exceptions during state test fixture generation.
"""
with pytest.raises(Storage.KeyValueMismatch) as e_info:
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
assert e_info.value == expected_exception
@@ -145,14 +143,10 @@ def test_post_nonce_value_mismatch(pre: Alloc, post: Alloc, state_test, t8n, for
pre_nonce = pre_account.nonce
post_nonce = post_account.nonce
if "nonce" not in post_account.model_fields_set: # no exception
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
return
with pytest.raises(Account.NonceMismatch) as e_info:
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
assert e_info.value == Account.NonceMismatch(
address=ADDRESS_UNDER_TEST, want=post_nonce, got=pre_nonce
)
@@ -181,14 +175,10 @@ def test_post_code_value_mismatch(pre: Alloc, post: Alloc, state_test, t8n, fork
pre_code = pre_account.code
post_code = post_account.code
if "code" not in post_account.model_fields_set: # no exception
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
return
with pytest.raises(Account.CodeMismatch) as e_info:
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
assert e_info.value == Account.CodeMismatch(
address=ADDRESS_UNDER_TEST, want=post_code, got=pre_code
)
@@ -217,14 +207,10 @@ def test_post_balance_value_mismatch(pre: Alloc, post: Alloc, state_test, t8n, f
pre_balance = pre_account.balance
post_balance = post_account.balance
if "balance" not in post_account.model_fields_set: # no exception
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
return
with pytest.raises(Account.BalanceMismatch) as e_info:
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
assert e_info.value == Account.BalanceMismatch(
address=ADDRESS_UNDER_TEST, want=post_balance, got=pre_balance
)
@@ -264,11 +250,7 @@ def test_post_account_mismatch(state_test, t8n, fork, exception_type: Type[Excep
fixture generation.
"""
if exception_type is None:
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
return
with pytest.raises(exception_type) as _:
- state_test.generate(
- request=None, t8n=t8n, fork=fork, fixture_format=FixtureFormats.STATE_TEST
- )
+ state_test.generate(request=None, t8n=t8n, fork=fork, fixture_format=StateFixture)
diff --git a/src/ethereum_test_specs/tests/test_fixtures.py b/src/ethereum_test_specs/tests/test_fixtures.py
index d31f83816d..de2b1d9cde 100644
--- a/src/ethereum_test_specs/tests/test_fixtures.py
+++ b/src/ethereum_test_specs/tests/test_fixtures.py
@@ -12,7 +12,12 @@
import cli.check_fixtures
from ethereum_test_base_types import Account, Address, Hash
from ethereum_test_exceptions import TransactionException
-from ethereum_test_fixtures import BlockchainFixture, FixtureFormats
+from ethereum_test_fixtures import (
+ BlockchainEngineFixture,
+ BlockchainFixture,
+ 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
@@ -96,7 +101,7 @@ def test_make_genesis(fork: Fork, hash: bytes): # noqa: D103
request=None, # type: ignore
t8n=t8n,
fork=fork,
- fixture_format=FixtureFormats.BLOCKCHAIN_TEST,
+ fixture_format=BlockchainFixture,
)
assert isinstance(fixture, BlockchainFixture)
assert fixture.genesis is not None
@@ -109,17 +114,17 @@ def test_make_genesis(fork: Fork, hash: bytes): # noqa: D103
@pytest.mark.parametrize(
"fork,fixture_format",
[
- (Istanbul, FixtureFormats.BLOCKCHAIN_TEST),
- (London, FixtureFormats.BLOCKCHAIN_TEST),
- (Paris, FixtureFormats.BLOCKCHAIN_TEST_ENGINE),
- (Shanghai, FixtureFormats.BLOCKCHAIN_TEST_ENGINE),
- (Paris, FixtureFormats.STATE_TEST),
- (Shanghai, FixtureFormats.STATE_TEST),
+ (Istanbul, BlockchainFixture),
+ (London, BlockchainFixture),
+ (Paris, BlockchainEngineFixture),
+ (Shanghai, BlockchainEngineFixture),
+ (Paris, StateFixture),
+ (Shanghai, StateFixture),
],
)
def test_fill_state_test(
fork: Fork,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
):
"""
Test `ethereum_test.filler.fill_fixtures` with `StateTest`.
@@ -166,12 +171,12 @@ def test_fill_state_test(
fork=fork,
fixture_format=fixture_format,
)
- assert generated_fixture.format == fixture_format
+ assert generated_fixture.__class__ == fixture_format
fixture = {
f"000/my_chain_id_test/{fork}": generated_fixture.json_dict_with_info(hash_only=True),
}
- expected_json_file = f"chainid_{fork.name().lower()}_{fixture_format.value}.json"
+ expected_json_file = f"chainid_{fork.name().lower()}_{fixture_format.fixture_format_name}.json"
with open(
os.path.join(
"src",
@@ -471,9 +476,7 @@ def genesis_environment(self): # noqa: D102
@pytest.fixture
def fixture_format(self, check_hive: bool): # noqa: D102
- return (
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE if check_hive else FixtureFormats.BLOCKCHAIN_TEST
- )
+ return BlockchainEngineFixture if check_hive else BlockchainFixture
@pytest.fixture
def blockchain_test_fixture( # noqa: D102
@@ -484,7 +487,7 @@ def blockchain_test_fixture( # noqa: D102
post: Mapping[Any, Any],
blocks: List[Block],
genesis_environment: Environment,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
):
t8n = ExecutionSpecsTransitionTool()
return BlockchainTest(
@@ -506,11 +509,11 @@ def test_fill_blockchain_valid_txs( # noqa: D102
self,
fork: Fork,
check_hive: bool,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
expected_json_file: str,
blockchain_test_fixture: BlockchainFixture,
):
- assert blockchain_test_fixture.format == fixture_format
+ assert blockchain_test_fixture.__class__ == fixture_format
assert isinstance(blockchain_test_fixture, FixtureCommon)
fixture_name = f"000/my_blockchain_test/{fork.name()}"
@@ -870,8 +873,8 @@ def test_fill_blockchain_invalid_txs(fork: Fork, check_hive: bool, expected_json
)
t8n = ExecutionSpecsTransitionTool()
- fixture_format = (
- FixtureFormats.BLOCKCHAIN_TEST_ENGINE if check_hive else FixtureFormats.BLOCKCHAIN_TEST
+ fixture_format: FixtureFormat = (
+ BlockchainEngineFixture if check_hive else BlockchainFixture # type: ignore
)
generated_fixture = BlockchainTest(
pre=pre,
@@ -884,7 +887,7 @@ def test_fill_blockchain_invalid_txs(fork: Fork, check_hive: bool, expected_json
fork=fork,
fixture_format=fixture_format,
)
- assert generated_fixture.format == fixture_format
+ assert generated_fixture.__class__ == fixture_format
assert isinstance(generated_fixture, FixtureCommon)
fixture_name = f"000/my_blockchain_test/{fork.name()}"
diff --git a/src/ethereum_test_tools/__init__.py b/src/ethereum_test_tools/__init__.py
index 33720ece20..54bff9d1fc 100644
--- a/src/ethereum_test_tools/__init__.py
+++ b/src/ethereum_test_tools/__init__.py
@@ -56,6 +56,7 @@
copy_opcode_cost,
cost_memory_bytes,
eip_2028_transaction_data_cost,
+ keccak256,
)
from ethereum_test_vm import (
Bytecode,
@@ -151,5 +152,6 @@
"eip_2028_transaction_data_cost",
"eip_2028_transaction_data_cost",
"extend_with_defaults",
+ "keccak256",
"vm",
)
diff --git a/src/ethereum_test_tools/tests/test_code.py b/src/ethereum_test_tools/tests/test_code.py
index 71eb614f0c..18fd71bec2 100644
--- a/src/ethereum_test_tools/tests/test_code.py
+++ b/src/ethereum_test_tools/tests/test_code.py
@@ -9,7 +9,7 @@
from semver import Version
from ethereum_test_base_types import Account, Address, Bytes, Hash, TestAddress, TestPrivateKey
-from ethereum_test_fixtures import FixtureFormats
+from ethereum_test_fixtures import BlockchainFixture
from ethereum_test_forks import (
Cancun,
Fork,
@@ -640,7 +640,7 @@ def test_switch(tx_data: bytes, switch_bytecode: bytes, expected_storage: Mappin
request=None, # type: ignore
t8n=ExecutionSpecsTransitionTool(),
fork=Cancun,
- fixture_format=FixtureFormats.BLOCKCHAIN_TEST,
+ fixture_format=BlockchainFixture,
eips=None,
)
diff --git a/src/ethereum_test_types/__init__.py b/src/ethereum_test_types/__init__.py
index b8b0cf5aba..028313de33 100644
--- a/src/ethereum_test_types/__init__.py
+++ b/src/ethereum_test_types/__init__.py
@@ -29,6 +29,7 @@
Transaction,
Withdrawal,
WithdrawalRequest,
+ keccak256,
)
__all__ = (
@@ -64,5 +65,6 @@
"copy_opcode_cost",
"cost_memory_bytes",
"eip_2028_transaction_data_cost",
+ "keccak256",
"to_json",
)
diff --git a/src/ethereum_test_types/helpers.py b/src/ethereum_test_types/helpers.py
index fda50ed820..66cf0fe09d 100644
--- a/src/ethereum_test_types/helpers.py
+++ b/src/ethereum_test_types/helpers.py
@@ -5,7 +5,6 @@
from dataclasses import MISSING, dataclass, fields
from typing import List, SupportsBytes
-from ethereum.crypto.hash import keccak256
from ethereum.rlp import encode
from ethereum_test_base_types.base_types import Address, Bytes, Hash
@@ -48,7 +47,7 @@ def compute_create_address(
if nonce is None:
nonce = 0
nonce_bytes = bytes() if nonce == 0 else nonce.to_bytes(length=1, byteorder="big")
- hash = keccak256(encode([address, nonce_bytes]))
+ hash = Bytes(encode([address, nonce_bytes])).keccak256()
return Address(hash[-20:])
if opcode == Op.CREATE2:
return compute_create2_address(address, salt, initcode)
@@ -62,7 +61,7 @@ def compute_create2_address(
Compute address of the resulting contract created using the `CREATE2`
opcode.
"""
- hash = keccak256(b"\xff" + Address(address) + Hash(salt) + keccak256(Bytes(initcode)))
+ hash = Bytes(b"\xff" + Address(address) + Hash(salt) + Bytes(initcode).keccak256()).keccak256()
return Address(hash[-20:])
@@ -100,7 +99,9 @@ def compute_eofcreate_address(
"""
Compute address of the resulting contract created using the `EOFCREATE` opcode.
"""
- hash = keccak256(b"\xff" + Address(address) + Hash(salt) + keccak256(Bytes(init_container)))
+ hash = Bytes(
+ b"\xff" + Address(address) + Hash(salt) + Bytes(init_container).keccak256()
+ ).keccak256()
return Address(hash[-20:])
diff --git a/src/ethereum_test_types/tests/test_transactions.py b/src/ethereum_test_types/tests/test_transactions.py
index d830e1fde5..bbe61b476c 100644
--- a/src/ethereum_test_types/tests/test_transactions.py
+++ b/src/ethereum_test_types/tests/test_transactions.py
@@ -260,4 +260,4 @@ def test_transaction_signing(
assert signature == expected_signature
assert tx.sender is not None
assert tx.sender.hex() == expected_sender
- assert ("0x" + tx.rlp.hex()) == expected_serialized
+ assert (tx.rlp.hex()) == expected_serialized
diff --git a/src/ethereum_test_types/types.py b/src/ethereum_test_types/types.py
index 66bbff841f..543b361201 100644
--- a/src/ethereum_test_types/types.py
+++ b/src/ethereum_test_types/types.py
@@ -8,11 +8,10 @@
from coincurve.keys import PrivateKey, PublicKey
from ethereum import rlp as eth_rlp
-from ethereum.base_types import U256, Uint
-from ethereum.crypto.hash import keccak256
from ethereum.frontier.fork_types import Account as FrontierAccount
from ethereum.frontier.fork_types import Address as FrontierAddress
from ethereum.frontier.state import State, set_account, set_storage, state_root
+from ethereum_types.numeric import U256, Uint
from pydantic import (
BaseModel,
ConfigDict,
@@ -50,6 +49,13 @@
from ethereum_test_vm import EVMCodeType
+def keccak256(data: bytes) -> Hash:
+ """
+ Calculates the keccak256 hash of the given data.
+ """
+ return Bytes(data).keccak256()
+
+
# Sentinel classes
class Removable:
"""
@@ -494,16 +500,19 @@ def to_list(self) -> List[Any]:
]
@cached_property
- def signing_bytes(self) -> bytes:
+ def signing_bytes(self) -> Bytes:
"""
Returns the data to be signed.
"""
- return int.to_bytes(self.magic, length=1, byteorder="big") + eth_rlp.encode(
- [
- Uint(self.chain_id),
- self.address,
- Uint(self.nonce),
- ]
+ return Bytes(
+ int.to_bytes(self.magic, length=1, byteorder="big")
+ + eth_rlp.encode(
+ [
+ Uint(self.chain_id),
+ self.address,
+ Uint(self.nonce),
+ ]
+ )
)
def signature(self, private_key: Hash) -> Tuple[int, int, int]:
@@ -552,7 +561,7 @@ def model_post_init(self, __context: Any) -> None:
+ bytes([self.v])
)
public_key = PublicKey.from_signature_and_message(
- signature_bytes, keccak256(self.signing_bytes), hasher=None
+ signature_bytes, self.signing_bytes.keccak256(), hasher=None
)
self.signer = EOA(
address=Address(keccak256(public_key.format(compressed=False)[1:])[32 - 20 :])
@@ -668,7 +677,7 @@ class Transaction(TransactionGeneric[HexNumber], TransactionTransitionToolConver
error: List[TransactionException] | TransactionException | None = Field(None, exclude=True)
protected: bool = Field(True, exclude=True)
- rlp_override: bytes | None = Field(None, exclude=True)
+ rlp_override: Bytes | None = Field(None, exclude=True)
wrapped_blob_transaction: bool = Field(False, exclude=True)
blobs: Sequence[Bytes] | None = Field(None, exclude=True)
@@ -788,7 +797,7 @@ def with_signature_and_sender(self, *, keep_secret_key: bool = False) -> "Transa
return self
public_key = PublicKey.from_signature_and_message(
- self.signature_bytes, keccak256(self.signing_bytes), hasher=None
+ self.signature_bytes, self.signing_bytes.keccak256(), hasher=None
)
updated_values["sender"] = Address(
keccak256(public_key.format(compressed=False)[1:])[32 - 20 :]
@@ -799,7 +808,7 @@ def with_signature_and_sender(self, *, keep_secret_key: bool = False) -> "Transa
raise ValueError("secret_key must be set to sign a transaction")
# Get the signing bytes
- signing_hash = keccak256(self.signing_bytes)
+ signing_hash = self.signing_bytes.keccak256()
# Sign the bytes
signature_bytes = PrivateKey(secret=self.secret_key).sign_recoverable(
@@ -984,7 +993,7 @@ def payload_body(self) -> List[Any]:
return signing_envelope + [Uint(self.v), Uint(self.r), Uint(self.s)]
@cached_property
- def rlp(self) -> bytes:
+ def rlp(self) -> Bytes:
"""
Returns bytes of the serialized representation of the transaction,
which is almost always RLP encoding.
@@ -992,30 +1001,30 @@ def rlp(self) -> bytes:
if self.rlp_override is not None:
return self.rlp_override
if self.ty > 0:
- return bytes([self.ty]) + eth_rlp.encode(self.payload_body)
+ return Bytes(bytes([self.ty]) + eth_rlp.encode(self.payload_body))
else:
- return eth_rlp.encode(self.payload_body)
+ return Bytes(eth_rlp.encode(self.payload_body))
@cached_property
def hash(self) -> Hash:
"""
Returns hash of the transaction.
"""
- return Hash(keccak256(self.rlp))
+ return self.rlp.keccak256()
@cached_property
- def signing_bytes(self) -> bytes:
+ def signing_bytes(self) -> Bytes:
"""
Returns the serialized bytes of the transaction used for signing.
"""
- return (
+ return Bytes(
bytes([self.ty]) + eth_rlp.encode(self.signing_envelope)
if self.ty > 0
else eth_rlp.encode(self.signing_envelope)
)
@cached_property
- def signature_bytes(self) -> bytes:
+ def signature_bytes(self) -> Bytes:
"""
Returns the serialized bytes of the transaction signature.
"""
@@ -1027,7 +1036,7 @@ def signature_bytes(self) -> bytes:
v -= 35 + (self.chain_id * 2)
else:
v -= 27
- return (
+ return Bytes(
self.r.to_bytes(32, byteorder="big")
+ self.s.to_bytes(32, byteorder="big")
+ bytes([v])
@@ -1074,7 +1083,7 @@ def created_contract(self) -> Address:
)
if self.sender is None:
raise ValueError("sender address is None")
- hash = keccak256(eth_rlp.encode([self.sender, nonce_bytes]))
+ hash = Bytes(eth_rlp.encode([self.sender, nonce_bytes])).keccak256()
return Address(hash[-20:])
diff --git a/src/ethereum_test_vm/bytecode.py b/src/ethereum_test_vm/bytecode.py
index a9907df601..80055da92a 100644
--- a/src/ethereum_test_vm/bytecode.py
+++ b/src/ethereum_test_vm/bytecode.py
@@ -3,7 +3,7 @@
"""
from typing import SupportsBytes
-from ethereum.crypto.hash import keccak256
+from ethereum_test_base_types import Bytes, Hash
class Bytecode:
@@ -216,8 +216,8 @@ def hex(self) -> str:
"""
return bytes(self).hex()
- def keccak256(self) -> bytes:
+ def keccak256(self) -> Hash:
"""
Return the keccak256 hash of the opcode byte representation.
"""
- return keccak256(self._bytes_)
+ return Bytes(self._bytes_).keccak256()
diff --git a/src/evm_transition_tool/geth.py b/src/evm_transition_tool/geth.py
index 02c4d86438..700d3a43d5 100644
--- a/src/evm_transition_tool/geth.py
+++ b/src/evm_transition_tool/geth.py
@@ -10,9 +10,10 @@
from re import compile
from typing import Optional
+from ethereum_test_fixtures import BlockchainFixture, StateFixture
from ethereum_test_forks import Fork
-from .transition_tool import FixtureFormats, TransitionTool, dump_files_to_directory
+from .transition_tool import FixtureFormat, TransitionTool, dump_files_to_directory
class GethTransitionTool(TransitionTool):
@@ -67,9 +68,18 @@ def get_blocktest_help(self) -> str:
raise Exception(f"Unexpected exception calling evm tool: {e}.")
return result.stdout
+ def is_verifiable(
+ self,
+ fixture_format: FixtureFormat,
+ ) -> bool:
+ """
+ Returns whether the fixture format is verifiable by this Geth's evm tool.
+ """
+ return fixture_format in {StateFixture, BlockchainFixture}
+
def verify_fixture(
self,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
fixture_path: Path,
fixture_name: Optional[str] = None,
debug_output_path: Optional[Path] = None,
@@ -82,16 +92,16 @@ def verify_fixture(
if debug_output_path:
command += ["--debug", "--json", "--verbosity", "100"]
- if FixtureFormats.is_state_test(fixture_format):
+ if fixture_format == StateFixture:
assert self.statetest_subcommand, "statetest subcommand not set"
command.append(self.statetest_subcommand)
- elif FixtureFormats.is_blockchain_test(fixture_format):
+ elif fixture_format == BlockchainFixture:
assert self.blocktest_subcommand, "blocktest subcommand not set"
command.append(self.blocktest_subcommand)
else:
raise Exception(f"Invalid test fixture format: {fixture_format}")
- if fixture_name and fixture_format == FixtureFormats.BLOCKCHAIN_TEST:
+ if fixture_name and fixture_format == BlockchainFixture:
assert isinstance(fixture_name, str), "fixture_name must be a string"
command.append("--run")
command.append(fixture_name)
@@ -130,7 +140,7 @@ def verify_fixture(
f"EVM test failed.\n{' '.join(command)}\n\n Error:\n{result.stderr.decode()}"
)
- if FixtureFormats.is_state_test(fixture_format):
+ if fixture_format == StateFixture:
result_json = json.loads(result.stdout.decode())
if not isinstance(result_json, list):
raise Exception(f"Unexpected result from evm statetest: {result_json}")
diff --git a/src/evm_transition_tool/transition_tool.py b/src/evm_transition_tool/transition_tool.py
index 863c9d15dc..b86b67fe2f 100644
--- a/src/evm_transition_tool/transition_tool.py
+++ b/src/evm_transition_tool/transition_tool.py
@@ -17,7 +17,7 @@
from requests_unixsocket import Session # type: ignore
-from ethereum_test_fixtures import FixtureFormats, FixtureVerifier
+from ethereum_test_fixtures import FixtureFormat, FixtureVerifier
from ethereum_test_forks import Fork
from ethereum_test_types import Alloc, Environment, Transaction
@@ -616,7 +616,7 @@ def evaluate(
def verify_fixture(
self,
- fixture_format: FixtureFormats,
+ fixture_format: FixtureFormat,
fixture_path: Path,
fixture_name: Optional[str] = None,
debug_output_path: Optional[Path] = None,
diff --git a/src/pytest_plugins/consume/consume.py b/src/pytest_plugins/consume/consume.py
index 02999206f3..1a301ac4e8 100644
--- a/src/pytest_plugins/consume/consume.py
+++ b/src/pytest_plugins/consume/consume.py
@@ -191,7 +191,7 @@ def pytest_generate_tests(metafunc):
(
pytest.param(test_case, id=test_case.id)
for test_case in metafunc.config.test_cases
- if test_case.format in metafunc.function.fixture_formats
+ if test_case.format in metafunc.function.fixture_format
and (not fork or test_case.fork == fork)
),
)
diff --git a/src/pytest_plugins/consume/decorator.py b/src/pytest_plugins/consume/decorator.py
index 43b9641813..21f3c456e8 100644
--- a/src/pytest_plugins/consume/decorator.py
+++ b/src/pytest_plugins/consume/decorator.py
@@ -2,16 +2,16 @@
Consume test function decorator used to mark properties of a test function.
"""
-from ethereum_test_fixtures import FixtureFormats
+from ethereum_test_fixtures import FixtureFormat
-def fixture_format(*formats: FixtureFormats):
+def fixture_format(*formats: FixtureFormat):
"""
Mark a test function as a test that consumes a specific fixture format.
"""
def decorator(func):
- func.fixture_formats = formats
+ func.fixture_format = formats
return func
return decorator
diff --git a/src/pytest_plugins/consume/direct/test_via_direct.py b/src/pytest_plugins/consume/direct/test_via_direct.py
index 4e1f92ef59..0bdfe13731 100644
--- a/src/pytest_plugins/consume/direct/test_via_direct.py
+++ b/src/pytest_plugins/consume/direct/test_via_direct.py
@@ -9,7 +9,7 @@
import pytest
-from ethereum_test_fixtures import FixtureFormats
+from ethereum_test_fixtures import BlockchainFixture, StateFixture
from ethereum_test_fixtures.consume import TestCaseIndexFile, TestCaseStream
from evm_transition_tool import TransitionTool
@@ -18,7 +18,7 @@
statetest_results: dict[Path, List[dict[str, Any]]] = {}
-@fixture_format(FixtureFormats.BLOCKCHAIN_TEST)
+@fixture_format(BlockchainFixture)
def test_blocktest( # noqa: D103
test_case: TestCaseIndexFile | TestCaseStream,
evm: TransitionTool,
@@ -60,7 +60,7 @@ def run_statetest(
@pytest.mark.usefixtures("run_statetest")
-@fixture_format(FixtureFormats.STATE_TEST)
+@fixture_format(StateFixture)
def test_statetest( # noqa: D103
test_case: TestCaseIndexFile | TestCaseStream,
fixture_path: Path,
diff --git a/src/pytest_plugins/consume/hive_simulators/engine/test_via_engine.py b/src/pytest_plugins/consume/hive_simulators/engine/test_via_engine.py
index df3ae5b9be..6871e7dafb 100644
--- a/src/pytest_plugins/consume/hive_simulators/engine/test_via_engine.py
+++ b/src/pytest_plugins/consume/hive_simulators/engine/test_via_engine.py
@@ -5,7 +5,7 @@
Each `engine_newPayloadVX` is verified against the appropriate VALID/INVALID responses.
"""
-from ethereum_test_fixtures import BlockchainEngineFixture, FixtureFormats
+from ethereum_test_fixtures import BlockchainEngineFixture
from ethereum_test_rpc import EngineRPC, EthRPC
from ethereum_test_rpc.types import ForkchoiceState, PayloadStatusEnum
from pytest_plugins.consume.hive_simulators.exceptions import GenesisBlockMismatchException
@@ -14,7 +14,7 @@
from ..timing import TimingData
-@fixture_format(FixtureFormats.BLOCKCHAIN_TEST_ENGINE)
+@fixture_format(BlockchainEngineFixture)
def test_via_engine(
timing_data: TimingData,
eth_rpc: EthRPC,
diff --git a/src/pytest_plugins/consume/hive_simulators/rlp/test_via_rlp.py b/src/pytest_plugins/consume/hive_simulators/rlp/test_via_rlp.py
index 6df6dd781e..e3dfdbe9d5 100644
--- a/src/pytest_plugins/consume/hive_simulators/rlp/test_via_rlp.py
+++ b/src/pytest_plugins/consume/hive_simulators/rlp/test_via_rlp.py
@@ -5,7 +5,7 @@
Clients consume the genesis and RLP-encoded blocks from input files upon start-up.
"""
-from ethereum_test_fixtures import BlockchainFixture, FixtureFormats
+from ethereum_test_fixtures import BlockchainFixture
from ethereum_test_rpc import EthRPC
from pytest_plugins.consume.hive_simulators.exceptions import GenesisBlockMismatchException
@@ -13,7 +13,7 @@
from ..timing import TimingData
-@fixture_format(FixtureFormats.BLOCKCHAIN_TEST)
+@fixture_format(BlockchainFixture)
def test_via_rlp(
timing_data: TimingData,
eth_rpc: EthRPC,
diff --git a/src/pytest_plugins/filler/filler.py b/src/pytest_plugins/filler/filler.py
index 180ff55a20..010dac4e85 100644
--- a/src/pytest_plugins/filler/filler.py
+++ b/src/pytest_plugins/filler/filler.py
@@ -11,7 +11,7 @@
import tarfile
import warnings
from pathlib import Path
-from typing import Generator, List, Type
+from typing import Any, Dict, Generator, List, Type
import pytest
from filelock import FileLock
@@ -19,10 +19,9 @@
from cli.gen_index import generate_fixtures_index
from ethereum_test_base_types import Alloc, ReferenceSpec
-from ethereum_test_fixtures import FixtureCollector, FixtureFormats, TestInfo
+from ethereum_test_fixtures import FIXTURE_FORMATS, BaseFixture, FixtureCollector, TestInfo
from ethereum_test_forks import (
Fork,
- Paris,
get_closest_fork_with_solc_support,
get_forks_with_solc_support,
)
@@ -207,13 +206,10 @@ def pytest_configure(config):
called before the pytest-html plugin's pytest_configure to ensure that
it uses the modified `htmlpath` option.
"""
- for fixture_format in FixtureFormats:
+ for fixture_format in FIXTURE_FORMATS.values():
config.addinivalue_line(
"markers",
- (
- f"{fixture_format.name.lower()}: "
- f"{FixtureFormats.get_format_description(fixture_format)}"
- ),
+ (f"{fixture_format.fixture_format_name.lower()}: {fixture_format.description}"),
)
config.addinivalue_line(
"markers",
@@ -798,7 +794,7 @@ def base_test_parametrizer_func(
When parametrize, indirect must be used along with the fixture format as value.
"""
fixture_format = request.param
- assert isinstance(fixture_format, FixtureFormats)
+ assert issubclass(fixture_format, BaseFixture)
class BaseTestWrapper(cls): # type: ignore
def __init__(self, *args, **kwargs):
@@ -830,7 +826,7 @@ def __init__(self, *args, **kwargs):
request.node.config.fixture_path_relative = str(
fixture_path.relative_to(output_dir)
)
- request.node.config.fixture_format = fixture_format.value
+ request.node.config.fixture_format = fixture_format.fixture_format_name
return BaseTestWrapper
@@ -855,8 +851,8 @@ def pytest_generate_tests(metafunc: pytest.Metafunc):
[
pytest.param(
fixture_format,
- id=fixture_format.name.lower(),
- marks=[getattr(pytest.mark, fixture_format.name.lower())],
+ id=fixture_format.fixture_format_name.lower(),
+ marks=[getattr(pytest.mark, fixture_format.fixture_format_name.lower())],
)
for fixture_format in test_type.supported_fixture_formats
],
@@ -865,9 +861,9 @@ def pytest_generate_tests(metafunc: pytest.Metafunc):
)
-def pytest_collection_modifyitems(config, items):
+def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]):
"""
- Remove pre-Paris tests parametrized to generate engine type fixtures; these
+ Remove pre-Paris tests parametrized to generate hive type fixtures; these
can't be used in the Hive Pyspec Simulator.
This can't be handled in this plugins pytest_generate_tests() as the fork
@@ -876,23 +872,16 @@ def pytest_collection_modifyitems(config, items):
for item in items[:]: # use a copy of the list, as we'll be modifying it
if isinstance(item, EIPSpecTestItem):
continue
- if "fork" not in item.callspec.params or item.callspec.params["fork"] is None:
+ params: Dict[str, Any] = item.callspec.params # type: ignore
+ if "fork" not in params or params["fork"] is None:
items.remove(item)
continue
- if item.callspec.params["fork"] < Paris:
- # Even though the `state_test` test spec does not produce an engine STATE_TEST, it does
- # produce a BLOCKCHAIN_TEST_ENGINE, so we need to remove it here.
- # TODO: Ideally, the logic could be contained in the `FixtureFormat` class, we create
- # a `fork_supported` method that returns True if the fork is supported.
- if ("state_test" in item.callspec.params) and item.callspec.params[
- "state_test"
- ].name.endswith("ENGINE"):
+ fork: Fork = params["fork"]
+ for spec_name in [spec_type.pytest_parameter_name() for spec_type in SPEC_TYPES]:
+ if spec_name in params and not params[spec_name].supports_fork(fork):
items.remove(item)
- if ("blockchain_test" in item.callspec.params) and item.callspec.params[
- "blockchain_test"
- ].name.endswith("ENGINE"):
- items.remove(item)
- if "yul" in item.fixturenames:
+ break
+ if "yul" in item.fixturenames: # type: ignore
item.add_marker(pytest.mark.yul_test)
diff --git a/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py b/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
index 3d9d0c95bf..f70e1938fe 100644
--- a/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
+++ b/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py
@@ -388,16 +388,20 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) ->
values = [param_set[key] for key in keys]
# TODO: This formatting of bytes objects should be moved elsewhere
values = [
- " ".join(
- f"{chunk}
" for chunk in textwrap.wrap(value.hex(), 32)
+ (
+ " ".join(
+ f"{chunk}
"
+ for chunk in textwrap.wrap(value.hex(), 32)
+ )
+ if isinstance(value, bytes)
+ else str(value)
)
- if isinstance(value, bytes)
- else str(value)
for value in values
]
fork = item.callspec.params.get("fork").name() # type: ignore
test_type = get_test_function_test_type(item)
- fixture_type = item.callspec.params.get(test_type).name # type: ignore
+ test_type_value = item.callspec.params.get(test_type)
+ fixture_type = test_type_value.fixture_format_name # type: ignore
test_cases.append(
TestCase(
full_id=item.nodeid,
diff --git a/src/pytest_plugins/forks/tests/test_forks.py b/src/pytest_plugins/forks/tests/test_forks.py
index 29911a47f6..46b0e4ebed 100644
--- a/src/pytest_plugins/forks/tests/test_forks.py
+++ b/src/pytest_plugins/forks/tests/test_forks.py
@@ -4,13 +4,7 @@
import pytest
-from ethereum_test_forks import (
- ArrowGlacier,
- Paris,
- forks_from_until,
- get_deployed_forks,
- get_forks,
-)
+from ethereum_test_forks import ArrowGlacier, forks_from_until, get_deployed_forks, get_forks
from ethereum_test_tools import StateTest
@@ -47,11 +41,17 @@ def test_all_forks({StateTest.pytest_parameter_name()}):
stdout = "\n".join(result.stdout.lines)
for fork in forks_under_test:
for fixture_format in StateTest.supported_fixture_formats:
- if fixture_format.name.endswith("ENGINE") and fork < Paris:
+ if not fixture_format.supports_fork(fork):
expected_passed -= 1
- assert f":test_all_forks[fork_{fork}-{fixture_format.name.lower()}]" not in stdout
+ assert (
+ f":test_all_forks[fork_{fork}-{fixture_format.fixture_format_name.lower()}]"
+ not in stdout
+ )
continue
- assert f":test_all_forks[fork_{fork}-{fixture_format.name.lower()}]" in stdout
+ assert (
+ f":test_all_forks[fork_{fork}-{fixture_format.fixture_format_name.lower()}]"
+ in stdout
+ )
result.assert_outcomes(
passed=expected_passed,
@@ -85,11 +85,17 @@ def test_all_forks({StateTest.pytest_parameter_name()}):
stdout = "\n".join(result.stdout.lines)
for fork in forks_under_test:
for fixture_format in StateTest.supported_fixture_formats:
- if fixture_format.name.endswith("ENGINE") and fork < Paris:
+ if not fixture_format.supports_fork(fork):
expected_passed -= 1
- assert f":test_all_forks[fork_{fork}-{fixture_format.name.lower()}]" not in stdout
+ assert (
+ f":test_all_forks[fork_{fork}-{fixture_format.fixture_format_name.lower()}]"
+ not in stdout
+ )
continue
- assert f":test_all_forks[fork_{fork}-{fixture_format.name.lower()}]" in stdout
+ assert (
+ f":test_all_forks[fork_{fork}-{fixture_format.fixture_format_name.lower()}]"
+ in stdout
+ )
result.assert_outcomes(
passed=expected_passed,
failed=0,
@@ -123,11 +129,17 @@ def test_all_forks({StateTest.pytest_parameter_name()}):
expected_passed -= len(StateTest.supported_fixture_formats)
for fork in forks_under_test:
for fixture_format in StateTest.supported_fixture_formats:
- if fixture_format.name.endswith("ENGINE") and fork < Paris:
+ if not fixture_format.supports_fork(fork):
expected_passed -= 1
- assert f":test_all_forks[fork_{fork}-{fixture_format.name.lower()}]" not in stdout
+ assert (
+ f":test_all_forks[fork_{fork}-{fixture_format.fixture_format_name.lower()}]"
+ not in stdout
+ )
continue
- assert f":test_all_forks[fork_{fork}-{fixture_format.name.lower()}]" in stdout
+ assert (
+ f":test_all_forks[fork_{fork}-{fixture_format.fixture_format_name.lower()}]"
+ in stdout
+ )
result.assert_outcomes(
passed=expected_passed,
failed=0,
@@ -158,7 +170,10 @@ def test_all_forks({StateTest.pytest_parameter_name()}):
stdout = "\n".join(result.stdout.lines)
for fork in forks_under_test:
for fixture_format in StateTest.supported_fixture_formats:
- assert f":test_all_forks[fork_{fork}-{fixture_format.name.lower()}]" in stdout
+ assert (
+ f":test_all_forks[fork_{fork}-{fixture_format.fixture_format_name.lower()}]"
+ in stdout
+ )
result.assert_outcomes(
passed=expected_passed,
failed=0,
diff --git a/tests/cancun/eip4788_beacon_root/conftest.py b/tests/cancun/eip4788_beacon_root/conftest.py
index 1c8d91581c..c286bff0d1 100644
--- a/tests/cancun/eip4788_beacon_root/conftest.py
+++ b/tests/cancun/eip4788_beacon_root/conftest.py
@@ -6,7 +6,6 @@
from typing import Dict, Iterator, List
import pytest
-from ethereum.crypto.hash import keccak256
from ethereum_test_tools import (
AccessList,
@@ -19,6 +18,7 @@
Storage,
Transaction,
add_kzg_version,
+ keccak256,
)
from ethereum_test_tools.vm.opcode import Opcodes as Op
diff --git a/tests/cancun/eip5656_mcopy/test_mcopy.py b/tests/cancun/eip5656_mcopy/test_mcopy.py
index 1e8ca50c19..74b980301d 100644
--- a/tests/cancun/eip5656_mcopy/test_mcopy.py
+++ b/tests/cancun/eip5656_mcopy/test_mcopy.py
@@ -3,14 +3,14 @@
Test copy operations of [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656)
""" # noqa: E501
+
from typing import Mapping
import pytest
-from ethereum.crypto.hash import keccak256
from ethereum_test_tools import Account, Address, Alloc, Bytecode, Environment, Hash
from ethereum_test_tools import Opcodes as Op
-from ethereum_test_tools import StateTestFiller, Storage, Transaction, ceiling_division
+from ethereum_test_tools import StateTestFiller, Storage, Transaction, ceiling_division, keccak256
from .common import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION, mcopy
diff --git a/tests/constantinople/eip1014_create2/test_create_returndata.py b/tests/constantinople/eip1014_create2/test_create_returndata.py
index 753b103a43..c4eb9672d5 100644
--- a/tests/constantinople/eip1014_create2/test_create_returndata.py
+++ b/tests/constantinople/eip1014_create2/test_create_returndata.py
@@ -5,10 +5,10 @@
"""
import pytest
-from ethereum.crypto.hash import keccak256
-from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
-from ethereum_test_tools.vm.opcode import Opcodes as Op
+from ethereum_test_tools import Account, Alloc, Environment
+from ethereum_test_tools import Opcodes as Op
+from ethereum_test_tools import StateTestFiller, Transaction, keccak256
from .spec import ref_spec_1014
@@ -102,20 +102,22 @@ def test_create2_return_data(
slot_returndatacopy_before_create_2: 0,
#
# the actual bytes returned by returndatacopy opcode after create
- slot_returndatacopy_after_create: return_data_in_create
- if return_type_in_create == Op.REVERT
- else 0,
+ slot_returndatacopy_after_create: (
+ return_data_in_create if return_type_in_create == Op.REVERT else 0
+ ),
slot_returndatasize_before_create: call_return_size,
#
# return datasize value after create
- slot_returndatasize_after_create: 0x20
- if return_type_in_create == Op.REVERT
- else 0,
+ slot_returndatasize_after_create: (
+ 0x20 if return_type_in_create == Op.REVERT else 0
+ ),
#
slot_return_data_hash_before_create: keccak256(expected_call_return_data),
- slot_return_data_hash_after_create: keccak256(empty_data)
- if return_type_in_create == Op.RETURN
- else keccak256(int.to_bytes(return_data_in_create, 32, byteorder="big")),
+ slot_return_data_hash_after_create: (
+ keccak256(empty_data)
+ if return_type_in_create == Op.RETURN
+ else keccak256(int.to_bytes(return_data_in_create, 32, byteorder="big"))
+ ),
#
# check that create 2 didn't mess up with initial memory space declared for return
slot_begin_memory_after_create: expected_returndatacopy,
diff --git a/tests/prague/eip2537_bls_12_381_precompiles/conftest.py b/tests/prague/eip2537_bls_12_381_precompiles/conftest.py
index 78b7244191..9dba8490ce 100644
--- a/tests/prague/eip2537_bls_12_381_precompiles/conftest.py
+++ b/tests/prague/eip2537_bls_12_381_precompiles/conftest.py
@@ -1,13 +1,14 @@
"""
Shared pytest definitions local to EIP-2537 tests.
"""
+
from typing import SupportsBytes
import pytest
-from ethereum.crypto.hash import keccak256
-from ethereum_test_tools import EOA, Address, Alloc, Bytecode, Storage, Transaction
-from ethereum_test_tools.vm import Opcodes as Op
+from ethereum_test_tools import EOA, Address, Alloc, Bytecode
+from ethereum_test_tools import Opcodes as Op
+from ethereum_test_tools import Storage, Transaction, keccak256
from .spec import GAS_CALCULATION_FUNCTION_MAP
diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py
index 344edc3736..eb5dc99dda 100644
--- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py
+++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py
@@ -1,12 +1,13 @@
"""
test execution semantics changes
"""
+
import pytest
-from ethereum.crypto.hash import keccak256
-from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Storage, Transaction
+from ethereum_test_tools import Account, Alloc, Environment
+from ethereum_test_tools import Opcodes as Op
+from ethereum_test_tools import StateTestFiller, Storage, Transaction, keccak256
from ethereum_test_tools.eof.v1 import Container, Section
-from ethereum_test_tools.vm.opcode import Opcodes as Op
from .. import EOF_FORK_NAME
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 91531ddc9a..1f84924ebd 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
@@ -9,7 +9,6 @@
from typing import List
import pytest
-from ethereum.crypto.hash import keccak256
from ethereum_test_tools import (
AccessList,
@@ -38,6 +37,7 @@
add_kzg_version,
call_return_code,
compute_create_address,
+ keccak256,
)
from ethereum_test_tools.eof.v1 import Container, Section
@@ -1404,12 +1404,12 @@ def test_ext_code_on_chain_delegating_set_code(
set_code_2 = Spec.delegation_designation(auth_signer_1)
callee_storage[slot_ext_code_size_result_1] = len(set_code_2)
- callee_storage[slot_ext_code_hash_result_1] = keccak256(set_code_2)
+ callee_storage[slot_ext_code_hash_result_1] = set_code_2.keccak256()
callee_storage[slot_ext_code_copy_result_1] = bytes(set_code_2).ljust(32, b"\x00")[:32]
callee_storage[slot_ext_balance_result_1] = auth_signer_1_balance
callee_storage[slot_ext_code_size_result_2] = len(set_code_1)
- callee_storage[slot_ext_code_hash_result_2] = keccak256(set_code_1)
+ callee_storage[slot_ext_code_hash_result_2] = set_code_1.keccak256()
callee_storage[slot_ext_code_copy_result_2] = bytes(set_code_1).ljust(32, b"\x00")[:32]
callee_storage[slot_ext_balance_result_2] = auth_signer_2_balance
diff --git a/tox.ini b/tox.ini
index d8de391c66..7f6dbb6688 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,6 +9,7 @@ develop = Prague
eip7692 = CancunEIP7692
[testenv]
+runner = uv-venv-lock-runner
package = wheel
wheel_build_env = .pkg
diff --git a/uv.lock b/uv.lock
index 1aa15d67cc..7e4f655292 100644
--- a/uv.lock
+++ b/uv.lock
@@ -498,9 +498,10 @@ wheels = [
[[package]]
name = "ethereum"
version = "0.1.0"
-source = { git = "https://github.com/ethereum/execution-specs#51fac24740e662844446439ceeb96a460aae0ba0" }
+source = { git = "https://github.com/ethereum/execution-specs#9b95554a88d2a8485f8180254d0f6a493a593fda" }
dependencies = [
{ name = "coincurve" },
+ { name = "ethereum-types" },
{ name = "py-ecc" },
{ name = "pycryptodome" },
{ name = "typing-extensions" },
@@ -517,6 +518,7 @@ dependencies = [
{ name = "colorlog" },
{ name = "ethereum" },
{ name = "ethereum-spec-evm-resolver" },
+ { name = "ethereum-types" },
{ name = "filelock" },
{ name = "gitpython" },
{ name = "hive-py" },
@@ -578,6 +580,7 @@ requires-dist = [
{ name = "colorlog", specifier = ">=6.7.0,<7" },
{ name = "ethereum", git = "https://github.com/ethereum/execution-specs" },
{ name = "ethereum-spec-evm-resolver", git = "https://github.com/petertdavies/ethereum-spec-evm-resolver" },
+ { name = "ethereum-types", specifier = ">=0.2.1,<0.3" },
{ name = "filelock", specifier = ">=3.15.1,<4" },
{ name = "flake8", marker = "extra == 'lint'", specifier = ">=6.1.0,<7" },
{ name = "flake8-docstrings", marker = "extra == 'lint'", specifier = ">=1.6,<2" },
@@ -635,6 +638,18 @@ dependencies = [
{ name = "urllib3" },
]
+[[package]]
+name = "ethereum-types"
+version = "0.2.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/07/a8/053c5fcc8581fe599a87b86431a50b7df5b84a88242a6ba33ab1138a2a34/ethereum_types-0.2.1.tar.gz", hash = "sha256:2b53c5f08aff52004d7a49cdb09e70163482b55a41e274a95a8d27d194c5d146", size = 14935 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/aa/76/3bbd13a9637287388f23c0c4094c81adf2d1467e314f8974ea0c61d2fc94/ethereum_types-0.2.1-py3-none-any.whl", hash = "sha256:6f6c51b239c231c6e33c10451b8fffb2fc168c6a7f0975cac3893d7e38e9c3e9", size = 10288 },
+]
+
[[package]]
name = "exceptiongroup"
version = "1.2.2"