diff --git a/src/ethereum_clis/clis/besu.py b/src/ethereum_clis/clis/besu.py index dc6c59f9854..6bde1e844f5 100644 --- a/src/ethereum_clis/clis/besu.py +++ b/src/ethereum_clis/clis/besu.py @@ -7,11 +7,10 @@ import tempfile import textwrap from pathlib import Path -from typing import ClassVar, Dict, List, Optional +from typing import ClassVar, Dict, Optional import requests # type: ignore -from ethereum_test_base_types import BlobSchedule from ethereum_test_exceptions import ( BlockException, ExceptionBase, @@ -19,10 +18,9 @@ TransactionException, ) from ethereum_test_forks import Fork -from ethereum_test_types import Alloc, Environment, Transaction from ..transition_tool import TransitionTool, dump_files_to_directory, model_dump_config -from ..types import TransitionToolInput, TransitionToolOutput +from ..types import TransitionToolOutput class BesuTransitionTool(TransitionTool): @@ -98,36 +96,20 @@ def shutdown(self): def evaluate( self, *, - alloc: Alloc, - txs: List[Transaction], - env: Environment, - fork: Fork, - chain_id: int, - reward: int, - blob_schedule: BlobSchedule | None = None, + transition_tool_data: TransitionTool.TransitionToolData, debug_output_path: str = "", - state_test: bool = False, slow_request: bool = False, ) -> TransitionToolOutput: """Execute `evm t8n` with the specified arguments.""" if not self.process: self.start_server() - fork_name = fork.transition_tool_name( - block_number=env.number, - timestamp=env.timestamp, - ) - - input_json = TransitionToolInput( - alloc=alloc, - txs=txs, - env=env, - ).model_dump(mode="json", **model_dump_config) + input_json = transition_tool_data.to_input().model_dump(mode="json", **model_dump_config) state_json = { - "fork": fork_name, - "chainid": chain_id, - "reward": reward, + "fork": transition_tool_data.fork_name, + "chainid": transition_tool_data.chain_id, + "reward": transition_tool_data.reward, } post_data = {"state": state_json, "input": input_json} diff --git a/src/ethereum_clis/tests/test_execution_specs.py b/src/ethereum_clis/tests/test_execution_specs.py index ed115b88419..410c58a831c 100644 --- a/src/ethereum_clis/tests/test_execution_specs.py +++ b/src/ethereum_clis/tests/test_execution_specs.py @@ -164,13 +164,15 @@ def test_evm_t8n( expected = json.load(exp) t8n_output = default_t8n.evaluate( - alloc=alloc, - txs=txs, - env=env, - fork=Berlin, - chain_id=1, - reward=0, - blob_schedule=Berlin.blob_schedule(), + transition_tool_data=TransitionTool.TransitionToolData( + alloc=alloc, + txs=txs, + env=env, + fork=Berlin, + chain_id=1, + reward=0, + blob_schedule=Berlin.blob_schedule(), + ), ) assert to_json(t8n_output.alloc) == expected.get("alloc") if isinstance(default_t8n, ExecutionSpecsTransitionTool): diff --git a/src/ethereum_clis/transition_tool.py b/src/ethereum_clis/transition_tool.py index 27b0471baaf..f732c12c136 100644 --- a/src/ethereum_clis/transition_tool.py +++ b/src/ethereum_clis/transition_tool.py @@ -136,11 +136,24 @@ class TransitionToolData: alloc: Alloc txs: List[Transaction] env: Environment - fork_name: str + fork: Fork chain_id: int reward: int blob_schedule: BlobSchedule | None - state_test: bool + state_test: bool = False + + @property + def fork_name(self) -> str: + """Return the fork name.""" + return self.fork.transition_tool_name( + block_number=self.env.number, + timestamp=self.env.timestamp, + ) + + def __post_init__(self): + """Modify the reward if the environment number is 0.""" + if self.env.number == 0: + self.reward = -1 def to_input(self) -> TransitionToolInput: """Convert the data to a TransactionToolInput object.""" @@ -493,15 +506,8 @@ def dump_debug_stream( def evaluate( self, *, - alloc: Alloc, - txs: List[Transaction], - env: Environment, - fork: Fork, - chain_id: int, - reward: int, - blob_schedule: BlobSchedule | None, + transition_tool_data: TransitionToolData, debug_output_path: str = "", - state_test: bool = False, slow_request: bool = False, ) -> TransitionToolOutput: """ @@ -510,36 +516,21 @@ def evaluate( If a client's `t8n` tool varies from the default behavior, this method can be overridden. """ - fork_name = fork.transition_tool_name( - block_number=env.number, - timestamp=env.timestamp, - ) - if env.number == 0: - reward = -1 - t8n_data = self.TransitionToolData( - alloc=alloc, - txs=txs, - env=env, - fork_name=fork_name, - chain_id=chain_id, - reward=reward, - blob_schedule=blob_schedule, - state_test=state_test, - ) - if self.t8n_use_server: if not self.process: self.start_server() return self._evaluate_server( - t8n_data=t8n_data, + t8n_data=transition_tool_data, debug_output_path=debug_output_path, timeout=SLOW_REQUEST_TIMEOUT if slow_request else NORMAL_SERVER_TIMEOUT, ) if self.t8n_use_stream: - return self._evaluate_stream(t8n_data=t8n_data, debug_output_path=debug_output_path) + return self._evaluate_stream( + t8n_data=transition_tool_data, debug_output_path=debug_output_path + ) return self._evaluate_filesystem( - t8n_data=t8n_data, + t8n_data=transition_tool_data, debug_output_path=debug_output_path, ) diff --git a/src/ethereum_test_specs/blockchain.py b/src/ethereum_test_specs/blockchain.py index 4ec141632c8..b43211d072c 100644 --- a/src/ethereum_test_specs/blockchain.py +++ b/src/ethereum_test_specs/blockchain.py @@ -498,13 +498,15 @@ def generate_block_data( ) transition_tool_output = t8n.evaluate( - alloc=previous_alloc, - txs=txs, - env=env, - fork=fork, - chain_id=self.chain_id, - reward=fork.get_reward(env.number, env.timestamp), - blob_schedule=fork.blob_schedule(), + transition_tool_data=TransitionTool.TransitionToolData( + alloc=previous_alloc, + txs=txs, + env=env, + fork=fork, + chain_id=self.chain_id, + reward=fork.get_reward(env.number, env.timestamp), + blob_schedule=fork.blob_schedule(), + ), debug_output_path=self.get_next_transition_tool_output_path(), slow_request=self.is_tx_gas_heavy_test(), ) diff --git a/src/ethereum_test_specs/state.py b/src/ethereum_test_specs/state.py index 3bb63f762d3..04fdf13bcab 100644 --- a/src/ethereum_test_specs/state.py +++ b/src/ethereum_test_specs/state.py @@ -182,15 +182,17 @@ def make_state_test_fixture( raise Exception(f"Empty accounts in pre state: {empty_accounts}") transition_tool_output = t8n.evaluate( - alloc=pre_alloc, - txs=[tx], - env=env, - fork=fork, - chain_id=self.chain_id, - reward=0, # Reward on state tests is always zero - blob_schedule=fork.blob_schedule(), + transition_tool_data=TransitionTool.TransitionToolData( + alloc=pre_alloc, + txs=[tx], + env=env, + fork=fork, + chain_id=self.chain_id, + reward=0, # Reward on state tests is always zero + blob_schedule=fork.blob_schedule(), + state_test=True, + ), debug_output_path=self.get_next_transition_tool_output_path(), - state_test=True, slow_request=self.is_tx_gas_heavy_test(), ) diff --git a/src/pytest_plugins/filler/filler.py b/src/pytest_plugins/filler/filler.py index d84b0c4b2a7..5d387aad9d2 100644 --- a/src/pytest_plugins/filler/filler.py +++ b/src/pytest_plugins/filler/filler.py @@ -122,7 +122,7 @@ def pytest_addoption(parser: pytest.Parser): action="store", dest="evm_bin", type=Path, - default="ethereum-spec-evm-resolver", + default=None, help=( "Path to an evm executable (or name of an executable in the PATH) that provides `t8n`." " Default: `ethereum-spec-evm-resolver`." @@ -345,18 +345,23 @@ def pytest_configure(config): # Instantiate the transition tool here to check that the binary path/trace option is valid. # This ensures we only raise an error once, if appropriate, instead of for every test. - t8n = TransitionTool.from_binary_path( - binary_path=config.getoption("evm_bin"), trace=config.getoption("evm_collect_traces") - ) - if ( - isinstance(config.getoption("numprocesses"), int) - and config.getoption("numprocesses") > 0 - and "Besu" in str(t8n.detect_binary_pattern) - ): - pytest.exit( - "The Besu t8n tool does not work well with the xdist plugin; use -n=0.", - returncode=pytest.ExitCode.USAGE_ERROR, + evm_bin = config.getoption("evm_bin") + if evm_bin is None: + assert TransitionTool.default_tool is not None, "No default transition tool found" + t8n = TransitionTool.default_tool(trace=config.getoption("evm_collect_traces")) + else: + t8n = TransitionTool.from_binary_path( + binary_path=evm_bin, trace=config.getoption("evm_collect_traces") ) + if ( + isinstance(config.getoption("numprocesses"), int) + and config.getoption("numprocesses") > 0 + and "Besu" in str(t8n.detect_binary_pattern) + ): + pytest.exit( + "The Besu t8n tool does not work well with the xdist plugin; use -n=0.", + returncode=pytest.ExitCode.USAGE_ERROR, + ) if "Tools" not in config.stash[metadata_key]: config.stash[metadata_key]["Tools"] = { @@ -538,7 +543,7 @@ def pytest_html_report_title(report): @pytest.fixture(autouse=True, scope="session") -def evm_bin(request: pytest.FixtureRequest) -> Path: +def evm_bin(request: pytest.FixtureRequest) -> Path | None: """Return configured evm tool binary path used to run t8n.""" return request.config.getoption("evm_bin") @@ -553,11 +558,17 @@ def verify_fixtures_bin(request: pytest.FixtureRequest) -> Path | None: @pytest.fixture(autouse=True, scope="session") -def t8n(request: pytest.FixtureRequest, evm_bin: Path) -> Generator[TransitionTool, None, None]: +def t8n( + request: pytest.FixtureRequest, evm_bin: Path | None +) -> Generator[TransitionTool, None, None]: """Return configured transition tool.""" - t8n = TransitionTool.from_binary_path( - binary_path=evm_bin, trace=request.config.getoption("evm_collect_traces") - ) + if evm_bin is None: + assert TransitionTool.default_tool is not None, "No default transition tool found" + t8n = TransitionTool.default_tool(trace=request.config.getoption("evm_collect_traces")) + else: + t8n = TransitionTool.from_binary_path( + binary_path=evm_bin, trace=request.config.getoption("evm_collect_traces") + ) if not t8n.exception_mapper.reliable: warnings.warn( f"The t8n tool that is currently being used to fill tests ({t8n.__class__.__name__}) " @@ -590,7 +601,7 @@ def do_fixture_verification( def evm_fixture_verification( request: pytest.FixtureRequest, do_fixture_verification: bool, - evm_bin: Path, + evm_bin: Path | None, verify_fixtures_bin: Path | None, ) -> Generator[FixtureConsumer | None, None, None]: """ diff --git a/src/pytest_plugins/forks/forks.py b/src/pytest_plugins/forks/forks.py index 427d2d609f5..ed1e27e4e59 100644 --- a/src/pytest_plugins/forks/forks.py +++ b/src/pytest_plugins/forks/forks.py @@ -524,11 +524,15 @@ def get_fork_option(config, option_name: str, parameter_name: str) -> Set[Fork]: return evm_bin = config.getoption("evm_bin", None) - if evm_bin is not None: + if evm_bin is None: + assert TransitionTool.default_tool is not None, "No default transition tool found" + t8n = TransitionTool.default_tool() + elif evm_bin is not None: t8n = TransitionTool.from_binary_path(binary_path=evm_bin) - config.unsupported_forks = frozenset( # type: ignore - fork for fork in selected_fork_set if not t8n.is_fork_supported(fork) - ) + + config.unsupported_forks = frozenset( # type: ignore + fork for fork in selected_fork_set if not t8n.is_fork_supported(fork) + ) @pytest.hookimpl(trylast=True)