diff --git a/docs/writing_tests/fork_methods.md b/docs/writing_tests/fork_methods.md index 7184ee4ef5e..0c7b5eb9727 100644 --- a/docs/writing_tests/fork_methods.md +++ b/docs/writing_tests/fork_methods.md @@ -153,7 +153,6 @@ fork.name() # Returns the name of the fork fork.transition_tool_name(block_number=0, timestamp=0) # Returns name for transition tools fork.solc_name() # Returns name for the solc compiler fork.solc_min_version() # Returns minimum solc version supporting this fork -fork.blockchain_test_network_name() # Returns network name for blockchain tests fork.is_deployed() # Returns whether the fork is deployed to mainnet ``` diff --git a/src/ethereum_clis/clis/besu.py b/src/ethereum_clis/clis/besu.py index 1631440c60d..88c53dd9f2b 100644 --- a/src/ethereum_clis/clis/besu.py +++ b/src/ethereum_clis/clis/besu.py @@ -106,7 +106,6 @@ def evaluate( chain_id: int, reward: int, blob_schedule: BlobSchedule | None = None, - eips: Optional[List[int]] = None, debug_output_path: str = "", state_test: bool = False, slow_request: bool = False, @@ -119,8 +118,6 @@ def evaluate( block_number=env.number, timestamp=env.timestamp, ) - if eips is not None: - fork_name = "+".join([fork_name] + [str(eip) for eip in eips]) input_json = TransitionToolInput( alloc=alloc, diff --git a/src/ethereum_clis/transition_tool.py b/src/ethereum_clis/transition_tool.py index fe14833b6b3..f9178021b2d 100644 --- a/src/ethereum_clis/transition_tool.py +++ b/src/ethereum_clis/transition_tool.py @@ -500,7 +500,6 @@ def evaluate( chain_id: int, reward: int, blob_schedule: BlobSchedule | None, - eips: Optional[List[int]] = None, debug_output_path: str = "", state_test: bool = False, slow_request: bool = False, @@ -515,8 +514,6 @@ def evaluate( block_number=env.number, timestamp=env.timestamp, ) - if eips is not None: - fork_name = "+".join([fork_name] + [str(eip) for eip in eips]) if env.number == 0: reward = -1 t8n_data = self.TransitionToolData( diff --git a/src/ethereum_test_fixtures/base.py b/src/ethereum_test_fixtures/base.py index 7e842f4dc9d..d7fe3e1e46f 100644 --- a/src/ethereum_test_fixtures/base.py +++ b/src/ethereum_test_fixtures/base.py @@ -132,7 +132,7 @@ def fill_info( if _info_metadata: self.info.update(_info_metadata) - def get_fork(self) -> str | None: + def get_fork(self) -> Fork | None: """Return fork of the fixture as a string.""" raise NotImplementedError diff --git a/src/ethereum_test_fixtures/blockchain.py b/src/ethereum_test_fixtures/blockchain.py index 2a1df8e9552..20e120e6f3c 100644 --- a/src/ethereum_test_fixtures/blockchain.py +++ b/src/ethereum_test_fixtures/blockchain.py @@ -386,7 +386,7 @@ def without_rlp(self) -> FixtureBlockBase: class FixtureConfig(CamelModel): """Chain configuration for a fixture.""" - fork: str = Field(..., alias="network") + fork: Fork = Field(..., alias="network") chain_id: ZeroPaddedHexNumber = Field(ZeroPaddedHexNumber(1), alias="chainid") blob_schedule: FixtureBlobSchedule | None = None @@ -402,7 +402,7 @@ class InvalidFixtureBlock(CamelModel): class BlockchainFixtureCommon(BaseFixture): """Base blockchain test fixture model.""" - fork: str = Field(..., alias="network") + fork: Fork = Field(..., alias="network") genesis: FixtureHeader = Field(..., alias="genesisBlockHeader") pre: Alloc post_state: Alloc | None = Field(None) @@ -435,7 +435,7 @@ def config_defaults_for_backwards_compatibility(cls, data: Any) -> Any: data["config"]["chainid"] = "0x01" return data - def get_fork(self) -> str | None: + def get_fork(self) -> Fork | None: """Return fork of the fixture as a string.""" return self.fork diff --git a/src/ethereum_test_fixtures/consume.py b/src/ethereum_test_fixtures/consume.py index 947aa963fca..8dd22c48a8b 100644 --- a/src/ethereum_test_fixtures/consume.py +++ b/src/ethereum_test_fixtures/consume.py @@ -8,6 +8,7 @@ from pydantic import BaseModel, RootModel from ethereum_test_base_types import HexNumber +from ethereum_test_forks import Fork from .base import BaseFixture, FixtureFormat from .file import Fixtures @@ -44,7 +45,7 @@ class TestCaseBase(BaseModel): id: str fixture_hash: HexNumber | None - fork: str | None + fork: Fork | None format: FixtureFormat __test__ = False # stop pytest from collecting this class as a test @@ -80,7 +81,7 @@ class IndexFile(BaseModel): root_hash: HexNumber | None created_at: datetime.datetime test_count: int - forks: Optional[List[str]] = [] + forks: Optional[List[Fork]] = [] fixture_formats: Optional[List[str]] = [] test_cases: List[TestCaseIndexFile] diff --git a/src/ethereum_test_fixtures/eof.py b/src/ethereum_test_fixtures/eof.py index 0321552835c..ef18da5c507 100644 --- a/src/ethereum_test_fixtures/eof.py +++ b/src/ethereum_test_fixtures/eof.py @@ -6,6 +6,7 @@ from ethereum_test_base_types import Bytes, CamelModel, Number from ethereum_test_exceptions.exceptions import EOFExceptionInstanceOrList +from ethereum_test_forks import Fork from ethereum_test_types.eof.v1 import ContainerKind from .base import BaseFixture @@ -34,7 +35,7 @@ class Vector(CamelModel): code: Bytes container_kind: ContainerKind = ContainerKind.RUNTIME - results: Mapping[str, Result] + results: Mapping[Fork, Result] class EOFFixture(BaseFixture): @@ -45,6 +46,6 @@ class EOFFixture(BaseFixture): vectors: Mapping[Number, Vector] - def get_fork(self) -> str | None: + def get_fork(self) -> Fork | None: """Return fork of the fixture as a string.""" return None diff --git a/src/ethereum_test_fixtures/state.py b/src/ethereum_test_fixtures/state.py index c87c92fca7b..8d389db57f3 100644 --- a/src/ethereum_test_fixtures/state.py +++ b/src/ethereum_test_fixtures/state.py @@ -14,6 +14,7 @@ ZeroPaddedHexNumber, ) from ethereum_test_exceptions import TransactionExceptionInstanceOrList +from ethereum_test_forks import Fork from ethereum_test_types.block_types import EnvironmentGeneric from ethereum_test_types.transaction_types import ( Transaction, @@ -97,10 +98,10 @@ class StateFixture(BaseFixture): env: FixtureEnvironment pre: Alloc transaction: FixtureTransaction - post: Mapping[str, List[FixtureForkPost]] + post: Mapping[Fork, List[FixtureForkPost]] config: FixtureConfig - def get_fork(self) -> str | None: + def get_fork(self) -> Fork | None: """Return fork of the fixture as a string.""" forks = list(self.post.keys()) assert len(forks) == 1, "Expected state test fixture with single fork" diff --git a/src/ethereum_test_fixtures/tests/test_base.py b/src/ethereum_test_fixtures/tests/test_base.py index 1775eb51623..ed3edb6e017 100644 --- a/src/ethereum_test_fixtures/tests/test_base.py +++ b/src/ethereum_test_fixtures/tests/test_base.py @@ -12,7 +12,7 @@ def test_json_dict(): """Test that the json_dict property does not include the info field.""" fixture = TransactionFixture( txbytes="0x1234", - result={"fork": FixtureResult(intrinsic_gas=0)}, + result={"Paris": FixtureResult(intrinsic_gas=0)}, ) assert "_info" not in fixture.json_dict, "json_dict should exclude the 'info' field" @@ -38,7 +38,7 @@ def test_json_dict(): pytest.param( TransactionFixture( transaction="0x1234", - result={"fork": FixtureResult(intrinsic_gas=0)}, + result={"Paris": FixtureResult(intrinsic_gas=0)}, ), id="TransactionFixture", ), diff --git a/src/ethereum_test_fixtures/tests/test_eof.py b/src/ethereum_test_fixtures/tests/test_eof.py index 23c492acb9a..175563e90ab 100644 --- a/src/ethereum_test_fixtures/tests/test_eof.py +++ b/src/ethereum_test_fixtures/tests/test_eof.py @@ -21,7 +21,7 @@ code=Bytes(b"\x00"), container_kind=ContainerKind.INITCODE, results={ - "result1": Result( + "Paris": Result( exception=None, valid=True, ), @@ -35,7 +35,7 @@ "code": "0x00", "containerKind": "INITCODE", "results": { - "result1": { + "Paris": { "result": True, }, }, @@ -52,7 +52,7 @@ code=Bytes(b"\x00"), container_kind=ContainerKind.RUNTIME, results={ - "result1": Result( + "Paris": Result( exception=EOFException.INVALID_MAGIC, valid=False, ), @@ -66,7 +66,7 @@ "code": "0x00", "containerKind": "RUNTIME", "results": { - "result1": { + "Paris": { "exception": "EOFException.INVALID_MAGIC", "result": False, }, diff --git a/src/ethereum_test_fixtures/transaction.py b/src/ethereum_test_fixtures/transaction.py index 7943847bd33..03e1e4f3d83 100644 --- a/src/ethereum_test_fixtures/transaction.py +++ b/src/ethereum_test_fixtures/transaction.py @@ -6,6 +6,7 @@ from ethereum_test_base_types import Address, Bytes, CamelModel, Hash, ZeroPaddedHexNumber from ethereum_test_exceptions import TransactionExceptionInstanceOrList +from ethereum_test_forks import Fork from .base import BaseFixture @@ -25,10 +26,10 @@ class TransactionFixture(BaseFixture): format_name: ClassVar[str] = "transaction_test" description: ClassVar[str] = "Tests that generate a transaction test fixture." - result: Mapping[str, FixtureResult] + result: Mapping[Fork, FixtureResult] transaction: Bytes = Field(..., alias="txbytes") - def get_fork(self) -> str | None: + def get_fork(self) -> Fork | None: """Return the fork of the fixture as a string.""" forks = list(self.result.keys()) assert len(forks) == 1, "Expected transaction test fixture with single fork" diff --git a/src/ethereum_test_forks/__init__.py b/src/ethereum_test_forks/__init__.py index 495e0edff1f..650b689b6bf 100644 --- a/src/ethereum_test_forks/__init__.py +++ b/src/ethereum_test_forks/__init__.py @@ -1,6 +1,6 @@ """Ethereum test fork definitions.""" -from .base_fork import Fork, ForkAttribute +from .base_fork import ForkAttribute from .forks.forks import ( ArrowGlacier, Berlin, @@ -24,12 +24,15 @@ BerlinToLondonAt5, CancunToPragueAtTime15k, ParisToShanghaiAtTime15k, + PragueToOsakaAtTime15k, ShanghaiToCancunAtTime15k, ) from .gas_costs import GasCosts from .helpers import ( + Fork, ForkRangeDescriptor, InvalidForkError, + TransitionFork, forks_from, forks_from_until, get_closest_fork_with_solc_support, @@ -53,6 +56,7 @@ __all__ = [ "Fork", + "TransitionFork", "ForkAttribute", "ArrowGlacier", "Berlin", @@ -76,6 +80,7 @@ "Cancun", "CancunToPragueAtTime15k", "Prague", + "PragueToOsakaAtTime15k", "Osaka", "get_transition_forks", "forks_from", diff --git a/src/ethereum_test_forks/base_fork.py b/src/ethereum_test_forks/base_fork.py index 7883b5921a2..578523bfed2 100644 --- a/src/ethereum_test_forks/base_fork.py +++ b/src/ethereum_test_forks/base_fork.py @@ -151,7 +151,6 @@ class BaseFork(ABC, metaclass=BaseForkMeta): """ _transition_tool_name: ClassVar[Optional[str]] = None - _blockchain_test_network_name: ClassVar[Optional[str]] = None _solc_name: ClassVar[Optional[str]] = None _ignore: ClassVar[bool] = False @@ -159,13 +158,11 @@ def __init_subclass__( cls, *, transition_tool_name: Optional[str] = None, - blockchain_test_network_name: Optional[str] = None, solc_name: Optional[str] = None, ignore: bool = False, ) -> None: """Initialize new fork with values that don't carry over to subclass forks.""" cls._transition_tool_name = transition_tool_name - cls._blockchain_test_network_name = blockchain_test_network_name cls._solc_name = solc_name cls._ignore = ignore @@ -533,13 +530,6 @@ def solc_min_version(cls) -> Version: """Return minimum version of solc that supports this fork.""" pass - @classmethod - def blockchain_test_network_name(cls) -> str: - """Return network configuration name to be used in BlockchainTests for this fork.""" - if cls._blockchain_test_network_name is not None: - return cls._blockchain_test_network_name - return cls.name() - @classmethod def is_deployed(cls) -> bool: """ @@ -563,7 +553,3 @@ def parent(cls) -> Type["BaseFork"] | None: if base_class == BaseFork: return None return base_class - - -# Fork Type -Fork = Type[BaseFork] diff --git a/src/ethereum_test_forks/forks/forks.py b/src/ethereum_test_forks/forks/forks.py index 514bdd8eaea..856d78d013d 100644 --- a/src/ethereum_test_forks/forks/forks.py +++ b/src/ethereum_test_forks/forks/forks.py @@ -818,7 +818,6 @@ class GrayGlacier(ArrowGlacier, solc_name="london", ignore=True): class Paris( London, transition_tool_name="Merge", - blockchain_test_network_name="Paris", ): """Paris (Merge) fork.""" diff --git a/src/ethereum_test_forks/forks/transition.py b/src/ethereum_test_forks/forks/transition.py index 2195dd36155..97063a97f58 100644 --- a/src/ethereum_test_forks/forks/transition.py +++ b/src/ethereum_test_forks/forks/transition.py @@ -1,7 +1,7 @@ """List of all transition fork definitions.""" from ..transition_base_fork import transition_fork -from .forks import Berlin, Cancun, London, Paris, Prague, Shanghai +from .forks import Berlin, Cancun, London, Osaka, Paris, Prague, Shanghai # Transition Forks @@ -13,7 +13,7 @@ class BerlinToLondonAt5(Berlin): @transition_fork(to_fork=Shanghai, at_timestamp=15_000) -class ParisToShanghaiAtTime15k(Paris, blockchain_test_network_name="ParisToShanghaiAtTime15k"): +class ParisToShanghaiAtTime15k(Paris): """Paris to Shanghai transition at Timestamp 15k.""" pass @@ -31,3 +31,10 @@ class CancunToPragueAtTime15k(Cancun): """Cancun to Prague transition at Timestamp 15k.""" pass + + +@transition_fork(to_fork=Osaka, at_timestamp=15_000) +class PragueToOsakaAtTime15k(Prague): + """Prague to Osaka transition at Timestamp 15k.""" + + pass diff --git a/src/ethereum_test_forks/helpers.py b/src/ethereum_test_forks/helpers.py index c51b1e01641..e3434efdec7 100644 --- a/src/ethereum_test_forks/helpers.py +++ b/src/ethereum_test_forks/helpers.py @@ -1,12 +1,19 @@ """Helper methods to resolve forks during test filling.""" import re -from typing import Any, List, Optional, Set - -from pydantic import BaseModel, ConfigDict, ValidatorFunctionWrapHandler, model_validator +from typing import Annotated, Any, Callable, List, Optional, Set, Type + +from pydantic import ( + BaseModel, + ConfigDict, + PlainSerializer, + PlainValidator, + ValidatorFunctionWrapHandler, + model_validator, +) from semver import Version -from .base_fork import BaseFork, Fork +from .base_fork import BaseFork from .forks import forks, transition from .transition_base_fork import TransitionBaseClass @@ -19,7 +26,7 @@ def __init__(self, message): super().__init__(message) -all_forks: List[Fork] = [] +all_forks: List[Type[BaseFork]] = [] for fork_name in forks.__dict__: fork = forks.__dict__[fork_name] if not isinstance(fork, type): @@ -27,8 +34,17 @@ def __init__(self, message): if issubclass(fork, BaseFork) and fork is not BaseFork: all_forks.append(fork) +transition_forks: List[Type[BaseFork]] = [] + +for fork_name in transition.__dict__: + fork = transition.__dict__[fork_name] + if not isinstance(fork, type): + continue + if issubclass(fork, TransitionBaseClass) and issubclass(fork, BaseFork): + transition_forks.append(fork) + -def get_forks() -> List[Fork]: +def get_forks() -> List[Type[BaseFork]]: """ Return list of all the fork classes implemented by `ethereum_test_forks` ordered chronologically by deployment. @@ -36,7 +52,7 @@ def get_forks() -> List[Fork]: return all_forks -def get_deployed_forks() -> List[Fork]: +def get_deployed_forks() -> List[Type[BaseFork]]: """ Return list of all the fork classes implemented by `ethereum_test_forks` that have been deployed to mainnet, chronologically ordered by deployment. @@ -44,7 +60,7 @@ def get_deployed_forks() -> List[Fork]: return [fork for fork in get_forks() if fork.is_deployed()] -def get_development_forks() -> List[Fork]: +def get_development_forks() -> List[Type[BaseFork]]: """ Return list of all the fork classes implemented by `ethereum_test_forks` that have been not yet deployed to mainnet and are currently under @@ -53,7 +69,7 @@ def get_development_forks() -> List[Fork]: return [fork for fork in get_forks() if not fork.is_deployed()] -def get_parent_fork(fork: Fork) -> Fork: +def get_parent_fork(fork: Type[BaseFork]) -> Type[BaseFork]: """Return parent fork of the specified fork.""" parent_fork = fork.__base__ if not parent_fork: @@ -61,17 +77,19 @@ def get_parent_fork(fork: Fork) -> Fork: return parent_fork -def get_forks_with_solc_support(solc_version: Version) -> List[Fork]: +def get_forks_with_solc_support(solc_version: Version) -> List[Type[BaseFork]]: """Return list of all fork classes that are supported by solc.""" return [fork for fork in get_forks() if solc_version >= fork.solc_min_version()] -def get_forks_without_solc_support(solc_version: Version) -> List[Fork]: +def get_forks_without_solc_support(solc_version: Version) -> List[Type[BaseFork]]: """Return list of all fork classes that aren't supported by solc.""" return [fork for fork in get_forks() if solc_version < fork.solc_min_version()] -def get_closest_fork_with_solc_support(fork: Fork, solc_version: Version) -> Optional[Fork]: +def get_closest_fork_with_solc_support( + fork: Type[BaseFork], solc_version: Version +) -> Optional[Type[BaseFork]]: """ Return closest fork, potentially the provided fork itself, that has solc support. @@ -85,28 +103,19 @@ def get_closest_fork_with_solc_support(fork: Fork, solc_version: Version) -> Opt ) -def get_transition_forks() -> Set[Fork]: +def get_transition_forks() -> Set[Type[BaseFork]]: """Return all the transition forks.""" - transition_forks: Set[Fork] = set() + return set(transition_forks) - for fork_name in transition.__dict__: - fork = transition.__dict__[fork_name] - if not isinstance(fork, type): - continue - if issubclass(fork, TransitionBaseClass) and issubclass(fork, BaseFork): - transition_forks.add(fork) - return transition_forks - - -def get_transition_fork_predecessor(transition_fork: Fork) -> Fork: +def get_transition_fork_predecessor(transition_fork: Type[BaseFork]) -> Type[BaseFork]: """Return the fork from which the transition fork transitions.""" if not issubclass(transition_fork, TransitionBaseClass): raise InvalidForkError(f"{transition_fork} is not a transition fork.") return transition_fork.transitions_from() -def get_transition_fork_successor(transition_fork: Fork) -> Fork: +def get_transition_fork_successor(transition_fork: Type[BaseFork]) -> Type[BaseFork]: """Return the fork to which the transition fork transitions.""" if not issubclass(transition_fork, TransitionBaseClass): raise InvalidForkError(f"{transition_fork} is not a transition fork.") @@ -114,8 +123,8 @@ def get_transition_fork_successor(transition_fork: Fork) -> Fork: def get_from_until_fork_set( - forks: Set[Fork], forks_from: Set[Fork], forks_until: Set[Fork] -) -> Set[Fork]: + forks: Set[Type[BaseFork]], forks_from: Set[Type[BaseFork]], forks_until: Set[Type[BaseFork]] +) -> Set[Type[BaseFork]]: """Get fork range from forks_from to forks_until.""" resulting_set = set() for fork_from in forks_from: @@ -126,9 +135,9 @@ def get_from_until_fork_set( return resulting_set -def get_forks_with_no_parents(forks: Set[Fork]) -> Set[Fork]: +def get_forks_with_no_parents(forks: Set[Type[BaseFork]]) -> Set[Type[BaseFork]]: """Get forks with no parents in the inheritance hierarchy.""" - resulting_forks: Set[Fork] = set() + resulting_forks: Set[Type[BaseFork]] = set() for fork in forks: parents = False for next_fork in forks - {fork}: @@ -140,9 +149,9 @@ def get_forks_with_no_parents(forks: Set[Fork]) -> Set[Fork]: return resulting_forks -def get_forks_with_no_descendants(forks: Set[Fork]) -> Set[Fork]: +def get_forks_with_no_descendants(forks: Set[Type[BaseFork]]) -> Set[Type[BaseFork]]: """Get forks with no descendants in the inheritance hierarchy.""" - resulting_forks: Set[Fork] = set() + resulting_forks: Set[Type[BaseFork]] = set() for fork in forks: descendants = False for next_fork in forks - {fork}: @@ -154,9 +163,11 @@ def get_forks_with_no_descendants(forks: Set[Fork]) -> Set[Fork]: return resulting_forks -def get_last_descendants(forks: Set[Fork], forks_from: Set[Fork]) -> Set[Fork]: +def get_last_descendants( + forks: Set[Type[BaseFork]], forks_from: Set[Type[BaseFork]] +) -> Set[Type[BaseFork]]: """Get last descendant of a class in the inheritance hierarchy.""" - resulting_forks: Set[Fork] = set() + resulting_forks: Set[Type[BaseFork]] = set() forks = get_forks_with_no_descendants(forks) for fork_from in forks_from: for fork in forks: @@ -165,7 +176,9 @@ def get_last_descendants(forks: Set[Fork], forks_from: Set[Fork]) -> Set[Fork]: return resulting_forks -def transition_fork_from_to(fork_from: Fork, fork_to: Fork) -> Fork | None: +def transition_fork_from_to( + fork_from: Type[BaseFork], fork_to: Type[BaseFork] +) -> Type[BaseFork] | None: """ Return transition fork that transitions to and from the specified forks. @@ -182,9 +195,9 @@ def transition_fork_from_to(fork_from: Fork, fork_to: Fork) -> Fork | None: return None -def transition_fork_to(fork_to: Fork) -> Set[Fork]: +def transition_fork_to(fork_to: Type[BaseFork]) -> Set[Type[BaseFork]]: """Return transition fork that transitions to the specified fork.""" - transition_forks: Set[Fork] = set() + transition_forks: Set[Type[BaseFork]] = set() for transition_fork in get_transition_forks(): if not issubclass(transition_fork, TransitionBaseClass): continue @@ -194,14 +207,16 @@ def transition_fork_to(fork_to: Fork) -> Set[Fork]: return transition_forks -def forks_from_until(fork_from: Fork, fork_until: Fork) -> List[Fork]: +def forks_from_until( + fork_from: Type[BaseFork], fork_until: Type[BaseFork] +) -> List[Type[BaseFork]]: """ Return specified fork and all forks after it until and including the second specified fork. """ prev_fork = fork_until - forks: List[Fork] = [] + forks: List[Type[BaseFork]] = [] while prev_fork != BaseFork and prev_fork != fork_from: forks.insert(0, prev_fork) @@ -216,7 +231,7 @@ def forks_from_until(fork_from: Fork, fork_until: Fork) -> List[Fork]: return forks -def forks_from(fork: Fork, deployed_only: bool = True) -> List[Fork]: +def forks_from(fork: Type[BaseFork], deployed_only: bool = True) -> List[Type[BaseFork]]: """Return specified fork and all forks after it.""" if deployed_only: latest_fork = get_deployed_forks()[-1] @@ -225,7 +240,9 @@ def forks_from(fork: Fork, deployed_only: bool = True) -> List[Fork]: return forks_from_until(fork, latest_fork) -def get_relative_fork_markers(fork_identifier: Fork | str, strict_mode: bool = True) -> list[str]: +def get_relative_fork_markers( + fork_identifier: Type[BaseFork] | str, strict_mode: bool = True +) -> list[str]: """ Return a list of marker names for a given fork. @@ -256,7 +273,7 @@ def get_relative_fork_markers(fork_identifier: Fork | str, strict_mode: bool = T return [fork_class.name()] -def get_fork_by_name(fork_name: str) -> Fork | None: +def get_fork_by_name(fork_name: str) -> Type[BaseFork] | None: """Get a fork by name.""" for fork in get_forks(): if fork.name() == fork_name: @@ -267,11 +284,11 @@ def get_fork_by_name(fork_name: str) -> Fork | None: class ForkRangeDescriptor(BaseModel): """Fork descriptor parsed from string normally contained in ethereum/tests fillers.""" - greater_equal: Fork | None = None - less_than: Fork | None = None + greater_equal: Type[BaseFork] | None = None + less_than: Type[BaseFork] | None = None model_config = ConfigDict(frozen=True) - def fork_in_range(self, fork: Fork) -> bool: + def fork_in_range(self, fork: Type[BaseFork]) -> bool: """Return whether the given fork is within range.""" if self.greater_equal is not None and fork < self.greater_equal: return False @@ -295,7 +312,7 @@ def validate_fork_range_descriptor(cls, v: Any, handler: ValidatorFunctionWrapHa descriptor_string = re.sub(r"\s+", "", v.strip()) v = {} if m := re.search(r">=(\w+)", descriptor_string): - fork: Fork | None = get_fork_by_name(m.group(1)) + fork: Type[BaseFork] | None = get_fork_by_name(m.group(1)) if fork is None: raise Exception(f"Unable to parse fork name: {m.group(1)}") v["greater_equal"] = fork @@ -312,3 +329,36 @@ def validate_fork_range_descriptor(cls, v: Any, handler: ValidatorFunctionWrapHa + f'Remaining string: "{descriptor_string}"' ) return handler(v) + + +def fork_validator_generator( + cls_name: str, forks: List[Type[BaseFork]] +) -> Callable[[Any], Type[BaseFork]]: + """Generate a fork validator function.""" + forks_dict = {fork.name(): fork for fork in forks} + + def fork_validator(obj: Any) -> Type[BaseFork]: + """Get a fork by name or raise an error.""" + if obj is None: + raise InvalidForkError("Fork cannot be None") + if isinstance(obj, type) and issubclass(obj, BaseFork): + return obj + if isinstance(obj, str): + if obj in forks_dict: + return forks_dict[obj] + raise InvalidForkError(f"Invalid {cls_name}: {obj} (type: {type(obj)})") + + return fork_validator + + +# Annotated Pydantic-Friendly Fork Types +Fork = Annotated[ + Type[BaseFork], + PlainSerializer(str), + PlainValidator(fork_validator_generator("Fork", all_forks + transition_forks)), +] +TransitionFork = Annotated[ + Type[BaseFork], + PlainSerializer(str), + PlainValidator(fork_validator_generator("TransitionFork", transition_forks)), +] diff --git a/src/ethereum_test_forks/tests/test_forks.py b/src/ethereum_test_forks/tests/test_forks.py index 12319afb127..1d525bb9f7e 100644 --- a/src/ethereum_test_forks/tests/test_forks.py +++ b/src/ethereum_test_forks/tests/test_forks.py @@ -3,11 +3,11 @@ from typing import Dict, cast import pytest +from pydantic import BaseModel from semver import Version from ethereum_test_base_types import BlobSchedule -from ..base_fork import Fork from ..forks.forks import ( Berlin, Cancun, @@ -26,6 +26,7 @@ ShanghaiToCancunAtTime15k, ) from ..helpers import ( + Fork, forks_from, forks_from_until, get_closest_fork_with_solc_support, @@ -108,9 +109,9 @@ def test_forks(): # the default assert Paris.transition_tool_name() == "Merge" assert Shanghai.transition_tool_name() == "Shanghai" - assert Paris.blockchain_test_network_name() == "Paris" - assert Shanghai.blockchain_test_network_name() == "Shanghai" - assert ParisToShanghaiAtTime15k.blockchain_test_network_name() == "ParisToShanghaiAtTime15k" + assert f"{Paris}" == "Paris" + assert f"{Shanghai}" == "Shanghai" + assert f"{ParisToShanghaiAtTime15k}" == "ParisToShanghaiAtTime15k" # Test some fork properties assert Berlin.header_base_fee_required(0, 0) is False @@ -127,6 +128,34 @@ def test_forks(): assert cast(Fork, ParisToShanghaiAtTime15k).header_withdrawals_required() is True +class ForkInPydanticModel(BaseModel): + """Fork in pydantic model.""" + + fork_1: Fork + fork_2: Fork + fork_3: Fork | None + + +def test_fork_in_pydantic_model(): + """Test fork in pydantic model.""" + model = ForkInPydanticModel(fork_1=Paris, fork_2=ParisToShanghaiAtTime15k, fork_3=None) + assert model.model_dump() == { + "fork_1": "Paris", + "fork_2": "ParisToShanghaiAtTime15k", + "fork_3": None, + } + assert ( + model.model_dump_json() + == '{"fork_1":"Paris","fork_2":"ParisToShanghaiAtTime15k","fork_3":null}' + ) + model = ForkInPydanticModel.model_validate_json( + '{"fork_1": "Paris", "fork_2": "ParisToShanghaiAtTime15k", "fork_3": null}' + ) + assert model.fork_1 == Paris + assert model.fork_2 == ParisToShanghaiAtTime15k + assert model.fork_3 is None + + def test_fork_comparison(): """Test fork comparison operators.""" # Test fork comparison diff --git a/src/ethereum_test_forks/transition_base_fork.py b/src/ethereum_test_forks/transition_base_fork.py index 1453a3d84b9..8ccfab6a68c 100644 --- a/src/ethereum_test_forks/transition_base_fork.py +++ b/src/ethereum_test_forks/transition_base_fork.py @@ -3,7 +3,7 @@ from inspect import signature from typing import Callable, List, Type -from .base_fork import BaseFork, Fork +from .base_fork import BaseFork ALWAYS_TRANSITIONED_BLOCK_NUMBER = 10_000 ALWAYS_TRANSITIONED_BLOCK_TIMESTAMP = 10_000_000 @@ -13,12 +13,12 @@ class TransitionBaseClass: """Base class for transition forks.""" @classmethod - def transitions_to(cls) -> Fork: + def transitions_to(cls) -> Type[BaseFork]: """Return fork where the transition ends.""" raise Exception("Not implemented") @classmethod - def transitions_from(cls) -> Fork: + def transitions_from(cls) -> Type[BaseFork]: """Return fork where the transition starts.""" raise Exception("Not implemented") @@ -28,7 +28,7 @@ def base_fork_abstract_methods() -> List[str]: return list(BaseFork.__abstractmethods__) -def transition_fork(to_fork: Fork, at_block: int = 0, at_timestamp: int = 0): +def transition_fork(to_fork: Type[BaseFork], at_block: int = 0, at_timestamp: int = 0): """Mark a class as a transition fork.""" def decorator(cls) -> Type[TransitionBaseClass]: @@ -41,16 +41,15 @@ class NewTransitionClass( TransitionBaseClass, BaseFork, transition_tool_name=cls._transition_tool_name, - blockchain_test_network_name=cls._blockchain_test_network_name, solc_name=cls._solc_name, ignore=cls._ignore, ): @classmethod - def transitions_to(cls) -> Fork: + def transitions_to(cls) -> Type[BaseFork]: return to_fork @classmethod - def transitions_from(cls) -> Fork: + def transitions_from(cls) -> Type[BaseFork]: return from_fork NewTransitionClass.name = lambda: transition_name # type: ignore diff --git a/src/ethereum_test_specs/base.py b/src/ethereum_test_specs/base.py index 479fed15615..17c7c78f976 100644 --- a/src/ethereum_test_specs/base.py +++ b/src/ethereum_test_specs/base.py @@ -4,7 +4,7 @@ from functools import reduce from os import path from pathlib import Path -from typing import Callable, ClassVar, Dict, Generator, List, Optional, Sequence, Type, TypeVar +from typing import Callable, ClassVar, Dict, Generator, List, Sequence, Type, TypeVar import pytest from pydantic import BaseModel, Field, PrivateAttr @@ -115,7 +115,6 @@ def generate( t8n: TransitionTool, fork: Fork, fixture_format: FixtureFormat, - eips: Optional[List[int]] = None, ) -> BaseFixture: """Generate the list of test fixtures.""" pass @@ -125,7 +124,6 @@ def execute( *, fork: Fork, execute_format: ExecuteFormat, - eips: Optional[List[int]] = None, ) -> BaseExecute: """Generate the list of test fixtures.""" raise Exception(f"Unsupported execute format: {execute_format}") diff --git a/src/ethereum_test_specs/blobs.py b/src/ethereum_test_specs/blobs.py index eb9cd0962c7..7fbce96c5d8 100644 --- a/src/ethereum_test_specs/blobs.py +++ b/src/ethereum_test_specs/blobs.py @@ -1,6 +1,6 @@ """Test specification for blob tests.""" -from typing import Callable, ClassVar, Generator, List, Optional, Sequence, Type +from typing import Callable, ClassVar, Generator, List, Sequence, Type from ethereum_clis import TransitionTool from ethereum_test_base_types import Alloc @@ -35,7 +35,6 @@ def generate( t8n: TransitionTool, fork: Fork, fixture_format: FixtureFormat, - eips: Optional[List[int]] = None, ) -> BaseFixture: """Generate the list of test fixtures.""" raise Exception(f"Unknown fixture format: {fixture_format}") @@ -45,7 +44,6 @@ def execute( *, fork: Fork, execute_format: ExecuteFormat, - eips: Optional[List[int]] = None, ) -> BaseExecute: """Generate the list of test fixtures.""" if execute_format == BlobTransaction: diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py index fc1a406208a..fb2eb06dc11 100644 --- a/src/ethereum_test_specs/blockchain.py +++ b/src/ethereum_test_specs/blockchain.py @@ -401,7 +401,6 @@ def generate_block_data( block: Block, previous_env: Environment, previous_alloc: Alloc, - eips: Optional[List[int]] = None, ) -> Tuple[FixtureHeader, List[Transaction], List[Bytes] | None, Alloc, Environment]: """Generate common block data for both make_fixture and make_hive_fixture.""" if block.rlp and block.exception is not None: @@ -443,7 +442,6 @@ def generate_block_data( chain_id=self.chain_id, reward=fork.get_reward(env.number, env.timestamp), blob_schedule=fork.blob_schedule(), - eips=eips, debug_output_path=self.get_next_transition_tool_output_path(), slow_request=self.is_tx_gas_heavy_test(), ) @@ -550,15 +548,6 @@ def generate_block_data( env, ) - @staticmethod - def network_info(fork: Fork, eips: Optional[List[int]] = None): - """Return fixture network information for the fork & EIP/s.""" - return ( - "+".join([fork.blockchain_test_network_name()] + [str(eip) for eip in eips]) - if eips - else fork.blockchain_test_network_name() - ) - def verify_post_state(self, t8n, t8n_state: Alloc, expected_state: Alloc | None = None): """Verify post alloc after all block/s or payload/s are generated.""" try: @@ -574,7 +563,6 @@ def make_fixture( self, t8n: TransitionTool, fork: Fork, - eips: Optional[List[int]] = None, ) -> BlockchainFixture: """Create a fixture from the blockchain test definition.""" fixture_blocks: List[FixtureBlock | InvalidFixtureBlock] = [] @@ -596,7 +584,6 @@ def make_fixture( block=block, previous_env=env, previous_alloc=alloc, - eips=eips, ) fixture_block = FixtureBlockBase( header=header, @@ -647,9 +634,8 @@ def make_fixture( ) self.check_exception_test(exception=invalid_blocks > 0) self.verify_post_state(t8n, t8n_state=alloc) - network_info = BlockchainTest.network_info(fork, eips) return BlockchainFixture( - fork=network_info, + fork=fork, genesis=genesis.header, genesis_rlp=genesis.rlp, blocks=fixture_blocks, @@ -658,7 +644,7 @@ def make_fixture( post_state=alloc if not self.exclude_full_post_state_in_output else None, post_state_hash=alloc.state_root() if self.exclude_full_post_state_in_output else None, config=FixtureConfig( - fork=network_info, + fork=fork, blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()), chain_id=self.chain_id, ), @@ -668,7 +654,6 @@ def make_hive_fixture( self, t8n: TransitionTool, fork: Fork, - eips: Optional[List[int]] = None, ) -> BlockchainEngineFixture: """Create a hive fixture from the blocktest definition.""" fixture_payloads: List[FixtureEngineNewPayload] = [] @@ -685,7 +670,6 @@ def make_hive_fixture( block=block, previous_env=env, previous_alloc=alloc, - eips=eips, ) if block.rlp is None: fixture_payloads.append( @@ -735,7 +719,6 @@ def make_hive_fixture( block=Block(), previous_env=env, previous_alloc=alloc, - eips=eips, ) sync_payload = FixtureEngineNewPayload.from_fixture_header( fork=fork, @@ -747,9 +730,8 @@ def make_hive_fixture( error_code=None, ) - network_info = BlockchainTest.network_info(fork, eips) return BlockchainEngineFixture( - fork=network_info, + fork=fork, genesis=genesis.header, payloads=fixture_payloads, fcu_version=fcu_version, @@ -759,7 +741,7 @@ def make_hive_fixture( sync_payload=sync_payload, last_block_hash=head_hash, config=FixtureConfig( - fork=network_info, + fork=fork, chain_id=self.chain_id, blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()), ), @@ -770,14 +752,13 @@ def generate( t8n: TransitionTool, fork: Fork, fixture_format: FixtureFormat, - eips: Optional[List[int]] = None, ) -> BaseFixture: """Generate the BlockchainTest fixture.""" t8n.reset_traces() if fixture_format == BlockchainEngineFixture: - return self.make_hive_fixture(t8n, fork, eips) + return self.make_hive_fixture(t8n, fork) elif fixture_format == BlockchainFixture: - return self.make_fixture(t8n, fork, eips) + return self.make_fixture(t8n, fork) raise Exception(f"Unknown fixture format: {fixture_format}") @@ -786,7 +767,6 @@ def execute( *, fork: Fork, execute_format: ExecuteFormat, - eips: Optional[List[int]] = None, ) -> BaseExecute: """Generate the list of test fixtures.""" if execute_format == TransactionPost: diff --git a/src/ethereum_test_specs/eof.py b/src/ethereum_test_specs/eof.py index 4319ebf926e..35f58984897 100644 --- a/src/ethereum_test_specs/eof.py +++ b/src/ethereum_test_specs/eof.py @@ -326,7 +326,6 @@ def make_eof_test_fixture( self, *, fork: Fork, - eips: Optional[List[int]], ) -> EOFFixture: """Generate the EOF test fixture.""" container_bytes = Bytes(self.container) @@ -341,7 +340,7 @@ def make_eof_test_fixture( code=container_bytes, container_kind=self.container_kind, results={ - fork.blockchain_test_network_name(): Result( + fork: Result( exception=self.expect_exception, valid=self.expect_exception is None, ), @@ -358,7 +357,7 @@ def make_eof_test_fixture( return fixture for _, vector in fixture.vectors.items(): - expected_result = vector.results.get(fork.blockchain_test_network_name()) + expected_result = vector.results.get(fork) if expected_result is None: raise Exception(f"EOF Fixture missing vector result for fork: {fork}") args = [] @@ -476,16 +475,15 @@ def generate( *, t8n: TransitionTool, fork: Fork, - eips: Optional[List[int]] = None, fixture_format: FixtureFormat, **_, ) -> BaseFixture: """Generate the BlockchainTest fixture.""" if fixture_format == EOFFixture: - return self.make_eof_test_fixture(fork=fork, eips=eips) + return self.make_eof_test_fixture(fork=fork) elif fixture_format in StateTest.supported_fixture_formats: return self.generate_state_test(fork).generate( - t8n=t8n, fork=fork, fixture_format=fixture_format, eips=eips + t8n=t8n, fork=fork, fixture_format=fixture_format ) raise Exception(f"Unknown fixture format: {fixture_format}") @@ -494,13 +492,10 @@ def execute( *, fork: Fork, execute_format: ExecuteFormat, - eips: Optional[List[int]] = None, ) -> BaseExecute: """Generate the list of test fixtures.""" if execute_format == TransactionPost: - return self.generate_state_test(fork).execute( - fork=fork, execute_format=execute_format, eips=eips - ) + return self.generate_state_test(fork).execute(fork=fork, execute_format=execute_format) raise Exception(f"Unsupported execute format: {execute_format}") @@ -633,7 +628,6 @@ def generate( *, t8n: TransitionTool, fork: Fork, - eips: Optional[List[int]] = None, fixture_format: FixtureFormat, **_, ) -> BaseFixture: @@ -643,10 +637,10 @@ def generate( # Gracefully skip duplicate tests because one EOFStateTest can generate multiple # state fixtures with the same data. pytest.skip(f"Duplicate EOF container on EOFStateTest: {self.node_id()}") - return self.make_eof_test_fixture(fork=fork, eips=eips) + return self.make_eof_test_fixture(fork=fork) elif fixture_format in StateTest.supported_fixture_formats: return self.generate_state_test(fork).generate( - t8n=t8n, fork=fork, fixture_format=fixture_format, eips=eips + t8n=t8n, fork=fork, fixture_format=fixture_format ) raise Exception(f"Unknown fixture format: {fixture_format}") diff --git a/src/ethereum_test_specs/state.py b/src/ethereum_test_specs/state.py index 265f136ee81..83bd526fa1c 100644 --- a/src/ethereum_test_specs/state.py +++ b/src/ethereum_test_specs/state.py @@ -161,7 +161,6 @@ def make_state_test_fixture( self, t8n: TransitionTool, fork: Fork, - eips: Optional[List[int]] = None, ) -> StateFixture: """Create a fixture from the state test definition.""" # We can't generate a state test fixture that names a transition fork, @@ -190,7 +189,6 @@ def make_state_test_fixture( chain_id=self.chain_id, reward=0, # Reward on state tests is always zero blob_schedule=fork.blob_schedule(), - eips=eips, debug_output_path=self.get_next_transition_tool_output_path(), state_test=True, slow_request=self.is_tx_gas_heavy_test(), @@ -218,7 +216,7 @@ def make_state_test_fixture( env=FixtureEnvironment(**env.model_dump(exclude_none=True)), pre=pre_alloc, post={ - fork.blockchain_test_network_name(): [ + fork: [ FixtureForkPost( state_root=transition_tool_output.result.state_root, logs_hash=transition_tool_output.result.logs_hash, @@ -240,16 +238,15 @@ def generate( t8n: TransitionTool, fork: Fork, fixture_format: FixtureFormat, - eips: Optional[List[int]] = None, ) -> BaseFixture: """Generate the BlockchainTest fixture.""" self.check_exception_test(exception=self.tx.error is not None) if fixture_format in BlockchainTest.supported_fixture_formats: return self.generate_blockchain_test(fork=fork).generate( - t8n=t8n, fork=fork, fixture_format=fixture_format, eips=eips + t8n=t8n, fork=fork, fixture_format=fixture_format ) elif fixture_format == StateFixture: - return self.make_state_test_fixture(t8n, fork, eips) + return self.make_state_test_fixture(t8n, fork) raise Exception(f"Unknown fixture format: {fixture_format}") @@ -258,7 +255,6 @@ def execute( *, fork: Fork, execute_format: ExecuteFormat, - eips: Optional[List[int]] = None, ) -> BaseExecute: """Generate the list of test fixtures.""" if execute_format == TransactionPost: diff --git a/src/ethereum_test_specs/transaction.py b/src/ethereum_test_specs/transaction.py index b4f96d8b8fa..0dbf927201c 100644 --- a/src/ethereum_test_specs/transaction.py +++ b/src/ethereum_test_specs/transaction.py @@ -1,6 +1,6 @@ """Ethereum transaction test spec definition and filler.""" -from typing import Callable, ClassVar, Generator, List, Optional, Sequence, Type +from typing import Callable, ClassVar, Generator, Sequence, Type from ethereum_clis import TransitionTool from ethereum_test_execution import ( @@ -42,7 +42,6 @@ class TransactionTest(BaseTest): def make_transaction_test_fixture( self, fork: Fork, - eips: Optional[List[int]] = None, ) -> TransactionFixture: """Create a fixture from the transaction test definition.""" if self.tx.error is not None: @@ -69,7 +68,7 @@ def make_transaction_test_fixture( return TransactionFixture( result={ - fork.blockchain_test_network_name(): result, + fork: result, }, transaction=self.tx.with_signature_and_sender().rlp(), ) @@ -79,12 +78,11 @@ def generate( t8n: TransitionTool, fork: Fork, fixture_format: FixtureFormat, - eips: Optional[List[int]] = None, ) -> BaseFixture: """Generate the TransactionTest fixture.""" self.check_exception_test(exception=self.tx.error is not None) if fixture_format == TransactionFixture: - return self.make_transaction_test_fixture(fork, eips) + return self.make_transaction_test_fixture(fork) raise Exception(f"Unknown fixture format: {fixture_format}") @@ -93,7 +91,6 @@ def execute( *, fork: Fork, execute_format: ExecuteFormat, - eips: Optional[List[int]] = None, ) -> BaseExecute: """Execute the transaction test by sending it to the live network.""" if execute_format == TransactionPost: diff --git a/src/ethereum_test_tools/tests/test_code.py b/src/ethereum_test_tools/tests/test_code.py index 70ec9c3899a..88cef12e4fe 100644 --- a/src/ethereum_test_tools/tests/test_code.py +++ b/src/ethereum_test_tools/tests/test_code.py @@ -633,7 +633,6 @@ def test_switch( t8n=default_t8n, fork=Cancun, fixture_format=BlockchainFixture, - eips=None, ) diff --git a/src/pytest_plugins/consume/hive_simulators/conftest.py b/src/pytest_plugins/consume/hive_simulators/conftest.py index 97c7e1cb41f..4d0c92fc6ca 100644 --- a/src/pytest_plugins/consume/hive_simulators/conftest.py +++ b/src/pytest_plugins/consume/hive_simulators/conftest.py @@ -328,7 +328,7 @@ def fork_strict_exception_matching( """Return True if the fork should use strict exception matching.""" # NOTE: `in` makes it easier for transition forks ("Prague" in "CancunToPragueAtTime15k") return not any( - fork.lower() in fixture.fork.lower() for fork in disable_strict_exception_matching + s.lower() in str(fixture.fork).lower() for s in disable_strict_exception_matching ) diff --git a/src/pytest_plugins/consume/hive_simulators/ruleset.py b/src/pytest_plugins/consume/hive_simulators/ruleset.py index 0d60a44e136..e44700412e7 100644 --- a/src/pytest_plugins/consume/hive_simulators/ruleset.py +++ b/src/pytest_plugins/consume/hive_simulators/ruleset.py @@ -7,7 +7,27 @@ from typing import Dict, List -from ethereum_test_forks import Cancun, Fork, Osaka, Prague +from ethereum_test_forks import ( + Berlin, + BerlinToLondonAt5, + Byzantium, + Cancun, + CancunToPragueAtTime15k, + Constantinople, + ConstantinopleFix, + Fork, + Frontier, + Homestead, + Istanbul, + London, + Osaka, + Paris, + ParisToShanghaiAtTime15k, + Prague, + PragueToOsakaAtTime15k, + Shanghai, + ShanghaiToCancunAtTime15k, +) def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: @@ -36,8 +56,8 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: return entries -ruleset = { - "Frontier": { +ruleset: Dict[Fork, Dict[str, int]] = { + Frontier: { "HIVE_FORK_HOMESTEAD": 2000, "HIVE_FORK_DAO_BLOCK": 2000, "HIVE_FORK_TANGERINE": 2000, @@ -49,7 +69,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 2000, "HIVE_FORK_LONDON": 2000, }, - "Homestead": { + Homestead: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_DAO_BLOCK": 2000, "HIVE_FORK_TANGERINE": 2000, @@ -61,29 +81,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 2000, "HIVE_FORK_LONDON": 2000, }, - "EIP150": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 2000, - "HIVE_FORK_BYZANTIUM": 2000, - "HIVE_FORK_CONSTANTINOPLE": 2000, - "HIVE_FORK_PETERSBURG": 2000, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "EIP158": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 2000, - "HIVE_FORK_CONSTANTINOPLE": 2000, - "HIVE_FORK_PETERSBURG": 2000, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "Byzantium": { + Byzantium: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -94,7 +92,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 2000, "HIVE_FORK_LONDON": 2000, }, - "Constantinople": { + Constantinople: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -105,7 +103,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 2000, "HIVE_FORK_LONDON": 2000, }, - "ConstantinopleFix": { + ConstantinopleFix: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -116,7 +114,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 2000, "HIVE_FORK_LONDON": 2000, }, - "Istanbul": { + Istanbul: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -127,7 +125,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 2000, "HIVE_FORK_LONDON": 2000, }, - "Berlin": { + Berlin: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -138,97 +136,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 0, "HIVE_FORK_LONDON": 2000, }, - "FrontierToHomesteadAt5": { - "HIVE_FORK_HOMESTEAD": 5, - "HIVE_FORK_DAO_BLOCK": 2000, - "HIVE_FORK_TANGERINE": 2000, - "HIVE_FORK_SPURIOUS": 2000, - "HIVE_FORK_BYZANTIUM": 2000, - "HIVE_FORK_CONSTANTINOPLE": 2000, - "HIVE_FORK_PETERSBURG": 2000, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "HomesteadToEIP150At5": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 5, - "HIVE_FORK_SPURIOUS": 2000, - "HIVE_FORK_BYZANTIUM": 2000, - "HIVE_FORK_CONSTANTINOPLE": 2000, - "HIVE_FORK_PETERSBURG": 2000, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "HomesteadToDaoAt5": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_DAO_BLOCK": 5, - "HIVE_FORK_TANGERINE": 2000, - "HIVE_FORK_SPURIOUS": 2000, - "HIVE_FORK_BYZANTIUM": 2000, - "HIVE_FORK_CONSTANTINOPLE": 2000, - "HIVE_FORK_PETERSBURG": 2000, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "EIP158ToByzantiumAt5": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 5, - "HIVE_FORK_CONSTANTINOPLE": 2000, - "HIVE_FORK_PETERSBURG": 2000, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "ByzantiumToConstantinopleAt5": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 0, - "HIVE_FORK_CONSTANTINOPLE": 5, - "HIVE_FORK_PETERSBURG": 2000, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "ByzantiumToConstantinopleFixAt5": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 0, - "HIVE_FORK_CONSTANTINOPLE": 5, - "HIVE_FORK_PETERSBURG": 5, - "HIVE_FORK_ISTANBUL": 2000, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "ConstantinopleFixToIstanbulAt5": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 0, - "HIVE_FORK_CONSTANTINOPLE": 0, - "HIVE_FORK_PETERSBURG": 0, - "HIVE_FORK_ISTANBUL": 5, - "HIVE_FORK_BERLIN": 2000, - "HIVE_FORK_LONDON": 2000, - }, - "IstanbulToBerlinAt5": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 0, - "HIVE_FORK_CONSTANTINOPLE": 0, - "HIVE_FORK_PETERSBURG": 0, - "HIVE_FORK_ISTANBUL": 0, - "HIVE_FORK_BERLIN": 5, - "HIVE_FORK_LONDON": 2000, - }, - "BerlinToLondonAt5": { + BerlinToLondonAt5: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -239,30 +147,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_BERLIN": 0, "HIVE_FORK_LONDON": 5, }, - "London": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 0, - "HIVE_FORK_CONSTANTINOPLE": 0, - "HIVE_FORK_PETERSBURG": 0, - "HIVE_FORK_ISTANBUL": 0, - "HIVE_FORK_BERLIN": 0, - "HIVE_FORK_LONDON": 0, - }, - "ArrowGlacierToMergeAtDiffC0000": { - "HIVE_FORK_HOMESTEAD": 0, - "HIVE_FORK_TANGERINE": 0, - "HIVE_FORK_SPURIOUS": 0, - "HIVE_FORK_BYZANTIUM": 0, - "HIVE_FORK_CONSTANTINOPLE": 0, - "HIVE_FORK_PETERSBURG": 0, - "HIVE_FORK_ISTANBUL": 0, - "HIVE_FORK_BERLIN": 0, - "HIVE_FORK_LONDON": 0, - "HIVE_TERMINAL_TOTAL_DIFFICULTY": 786432, - }, - "Merge": { + London: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -272,10 +157,8 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_ISTANBUL": 0, "HIVE_FORK_BERLIN": 0, "HIVE_FORK_LONDON": 0, - "HIVE_FORK_MERGE": 0, - "HIVE_TERMINAL_TOTAL_DIFFICULTY": 0, }, - "Paris": { + Paris: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -288,7 +171,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_FORK_MERGE": 0, "HIVE_TERMINAL_TOTAL_DIFFICULTY": 0, }, - "Shanghai": { + Shanghai: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -302,7 +185,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_TERMINAL_TOTAL_DIFFICULTY": 0, "HIVE_SHANGHAI_TIMESTAMP": 0, }, - "ParisToShanghaiAtTime15k": { + ParisToShanghaiAtTime15k: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -316,7 +199,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_TERMINAL_TOTAL_DIFFICULTY": 0, "HIVE_SHANGHAI_TIMESTAMP": 15000, }, - "Cancun": { + Cancun: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -332,7 +215,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_CANCUN_TIMESTAMP": 0, **get_blob_schedule_entries(Cancun), }, - "ShanghaiToCancunAtTime15k": { + ShanghaiToCancunAtTime15k: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -348,7 +231,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_CANCUN_TIMESTAMP": 15000, **get_blob_schedule_entries(Cancun), }, - "Prague": { + Prague: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -365,7 +248,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_PRAGUE_TIMESTAMP": 0, **get_blob_schedule_entries(Prague), }, - "CancunToPragueAtTime15k": { + CancunToPragueAtTime15k: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -382,7 +265,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_PRAGUE_TIMESTAMP": 15000, **get_blob_schedule_entries(Prague), }, - "Osaka": { + Osaka: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, @@ -400,7 +283,7 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: "HIVE_OSAKA_TIMESTAMP": 0, **get_blob_schedule_entries(Osaka), }, - "PragueToOsakaAtTime15k": { + PragueToOsakaAtTime15k: { "HIVE_FORK_HOMESTEAD": 0, "HIVE_FORK_TANGERINE": 0, "HIVE_FORK_SPURIOUS": 0, diff --git a/src/pytest_plugins/execute/execute.py b/src/pytest_plugins/execute/execute.py index 7970560e436..8b20e642444 100644 --- a/src/pytest_plugins/execute/execute.py +++ b/src/pytest_plugins/execute/execute.py @@ -261,7 +261,6 @@ def base_test_parametrizer_func( request: Any, fork: Fork, pre: Alloc, - eips: List[int], eth_rpc: EthRPC, engine_rpc: EngineRPC | None, collector: Collector, @@ -311,7 +310,7 @@ def __init__(self, *args, **kwargs): [str(eoa) for eoa in pre._funded_eoa] ) - execute = self.execute(fork=fork, execute_format=execute_format, eips=eips) + execute = self.execute(fork=fork, execute_format=execute_format) execute.execute(fork=fork, eth_rpc=eth_rpc, engine_rpc=engine_rpc) collector.collect(request.node.nodeid, execute) diff --git a/src/pytest_plugins/execute/rpc/hive.py b/src/pytest_plugins/execute/rpc/hive.py index 8efac210b2e..bfb2ed28b43 100644 --- a/src/pytest_plugins/execute/rpc/hive.py +++ b/src/pytest_plugins/execute/rpc/hive.py @@ -299,12 +299,12 @@ def environment(base_fork: Fork) -> dict: Define the environment that hive will start the client with using the fork rules specific for the simulator. """ - assert base_fork.name() in ruleset, f"fork '{base_fork.name()}' missing in hive ruleset" + assert base_fork in ruleset, f"fork '{base_fork}' missing in hive ruleset" return { "HIVE_CHAIN_ID": "1", "HIVE_FORK_DAO_VOTE": "1", "HIVE_NODETYPE": "full", - **{k: f"{v:d}" for k, v in ruleset[base_fork.name()].items()}, + **{k: f"{v:d}" for k, v in ruleset[base_fork].items()}, } diff --git a/src/pytest_plugins/filler/filler.py b/src/pytest_plugins/filler/filler.py index e1a4a1256f2..6a47e60198d 100644 --- a/src/pytest_plugins/filler/filler.py +++ b/src/pytest_plugins/filler/filler.py @@ -718,7 +718,6 @@ def base_test_parametrizer_func( t8n: TransitionTool, fork: Fork, reference_spec: ReferenceSpec, - eips: List[int], pre: Alloc, output_dir: Path, dump_dir_parameter_level: Path | None, @@ -756,7 +755,6 @@ def __init__(self, *args, **kwargs): t8n=t8n, fork=fork, fixture_format=fixture_format, - eips=eips, ) fixture.fill_info( t8n.version(), diff --git a/src/pytest_plugins/shared/execute_fill.py b/src/pytest_plugins/shared/execute_fill.py index ae9706624c1..4d139d582f2 100644 --- a/src/pytest_plugins/shared/execute_fill.py +++ b/src/pytest_plugins/shared/execute_fill.py @@ -91,19 +91,6 @@ def pytest_configure(config: pytest.Config): ) -@pytest.fixture(autouse=True) -def eips(): - """ - Fixture for specifying that, by default, no EIPs should be activated for - tests. - - This fixture (function) may be redefined in test filler modules in order - to overwrite this default and return a list of integers specifying which - EIPs should be activated for the tests in scope. - """ - return [] - - @pytest.fixture def yul(fork: Fork, request: pytest.FixtureRequest): """ diff --git a/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py b/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py index 21afb82f38c..aa7a17b7532 100644 --- a/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py +++ b/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py @@ -4,7 +4,7 @@ from ethereum_test_base_types import Bytes from ethereum_test_base_types.base_types import Address, Hash -from ethereum_test_forks.base_fork import Fork +from ethereum_test_forks import Fork from ethereum_test_tools import ( Account, Alloc,