Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow dynamic evm fork definitions via pytest plugin #753

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ addopts =
-p pytest_plugins.filler.pre_alloc
-p pytest_plugins.filler.filler
-p pytest_plugins.forks.forks
-p pytest_plugins.chain_selector.chain_selector
-p pytest_plugins.spec_version_checker.spec_version_checker
-p pytest_plugins.help.help
-m "not eip_version_check"
Expand Down
6 changes: 6 additions & 0 deletions src/ethereum_test_forks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
Prague,
Shanghai,
)

from .forks.transition import (
BerlinToLondonAt5,
ParisToShanghaiAtTime15k,
ShanghaiToCancunAtTime15k,
)

from .fork_registry import update_fork_registry, get_fork_registry

from .helpers import (
InvalidForkError,
forks_from,
Expand Down Expand Up @@ -67,10 +71,12 @@
"forks_from_until",
"get_deployed_forks",
"get_development_forks",
"get_fork_registry",
"get_forks",
"get_forks_with_solc_support",
"get_forks_without_solc_support",
"get_closest_fork_with_solc_support",
"transition_fork_from_to",
"transition_fork_to",
"update_fork_registry",
]
33 changes: 33 additions & 0 deletions src/ethereum_test_forks/fork_registry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
Define a global registry for forks that can be used in the Ethereum test
framework.

This approach allows different chains to register their fork class
definitions.
"""

from typing import Dict, Type
from .base_fork import BaseFork
from .helpers import get_forks

fork_registry: Dict[str, Dict[str, Type[BaseFork]]] = {}

fork_registry["ethereum-mainnet"] = {fork.name(): fork for fork in get_forks()}


def update_fork_registry(chain_name: str, forks: Dict[str, Type[BaseFork]]):
"""
Updates the global fork registry with forks from a specific chain.
If the chain already exists, it merges the new forks with the existing ones.
"""
if chain_name in fork_registry:
fork_registry[chain_name].update(forks)
else:
fork_registry[chain_name] = forks


def get_fork_registry() -> Dict[str, Dict[str, Type[BaseFork]]]:
"""
Returns the current fork registry.
"""
return fork_registry
41 changes: 41 additions & 0 deletions src/pytest_plugins/chain_selector/chain_selector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""

"""

import pytest
from ethereum_test_forks.fork_registry import get_fork_registry
from ethereum_test_forks.helpers import get_forks


def pytest_addoption(parser):
parser.addoption(
"--chain",
action="store",
default="ethereum-mainnet",
help="Select the EVM chain for testing. Default: ethereum-mainnet.",
)


@pytest.fixture(scope="session")
def chain(request):
return request.config.getoption("--chain")


@pytest.fixture(scope="session")
def forks(chain):
fork_registry = get_fork_registry()
if chain not in fork_registry:
raise ValueError(f"No forks found for chain: {chain}")
return fork_registry[chain].values()


# @pytest.hookimpl(tryfirst=True)
# def pytest_generate_tests(metafunc):
# if "fork" in metafunc.fixturenames:
# chain = metafunc.config.getoption("chain")
# fork_registry = get_fork_registry()
# if chain in fork_registry:
# forks = fork_registry[chain]
# metafunc.parametrize(
# "fork", forks.values(), ids=[fork.__name__ for fork in forks.values()]
# )
7 changes: 5 additions & 2 deletions src/pytest_plugins/forks/forks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
ForkAttribute,
get_deployed_forks,
get_forks,
get_fork_registry,
get_transition_forks,
transition_fork_to,
)
Expand Down Expand Up @@ -274,7 +275,9 @@ def pytest_configure(config: pytest.Config):
for d in fork_covariant_descriptors:
config.addinivalue_line("markers", f"{d.marker_name}: {d.description}")

forks = set([fork for fork in get_forks() if not fork.ignore()])
chain = config.getoption("chain")
assert chain in get_fork_registry(), f"No forks found for chain: {chain}"
forks = set([fork for fork in get_fork_registry()[chain].values() if not fork.ignore()])
config.forks = forks # type: ignore
config.fork_names = set([fork.name() for fork in sorted(list(forks))]) # type: ignore
config.forks_by_name = {fork.name(): fork for fork in forks} # type: ignore
Expand Down Expand Up @@ -305,7 +308,7 @@ def get_fork_option(config, option_name: str, parameter_name: str) -> Set[Fork]:

resulting_forks = set()

for fork in get_forks():
for fork in get_fork_registry()[chain].values():
if fork.name() in forks_str:
resulting_forks.add(fork)

Expand Down
30 changes: 30 additions & 0 deletions src/pytest_plugins/optimism.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
Chain definition for the Optimism network.
"""
from typing import List

import pytest

from ethereum_test_forks import Cancun, get_fork_registry, update_fork_registry


class OptimismCancun(Cancun):
"""
Defines the Optimism Cancun fork, which adds the secp256r1 precompile.
"""

@classmethod
def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
"""
Optimism added the secp256r1 precompile to its Cancun fork.
"""
return [0x100] + super(OptimismCancun, cls).precompiles(block_number, timestamp)


@pytest.hookimpl(tryfirst=True)
def pytest_configure(config):
ethereum_mainnet_forks = get_fork_registry()["ethereum-mainnet"]
assert "Cancun" in ethereum_mainnet_forks, "Cancun fork not found in ethereum-mainnet forks."
optimism_mainnet_forks = ethereum_mainnet_forks.copy()
optimism_mainnet_forks["Cancun"] = OptimismCancun
update_fork_registry("optimism", optimism_mainnet_forks)
Loading