diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e26aeddaf57..cbe44b3d8db 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -69,6 +69,41 @@ jobs: EOF uvx --from actionlint-py actionlint + packaging: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: ./.github/actions/setup-uv + with: + python-version: "3.14" + # Build every workspace member, so a dependency on a sibling package + # resolves against the wheel built here rather than against an index. + - name: Build the workspace wheels + run: uv build --wheel --all-packages --out-dir dist + # Install into a bare venv, deliberately outside the uv workspace. + # Both wheels are passed by explicit path: resolving either through an + # index could silently substitute a published PyPI version for the + # branch's own build. + - name: Install the wheels into a clean environment + run: | + uv venv "$RUNNER_TEMP/wheel-venv" + uv pip install --python "$RUNNER_TEMP/wheel-venv/bin/python" \ + dist/ethereum_execution_testing-*.whl \ + dist/ethereum_execution-*.whl + # Run a real transition rather than `--help`, which returns inside + # argparse without ever reaching the imports that t8n needs. The output + # basedir is emptied before the run, so keep it out of the source tree. + - name: Smoke-test ethereum-spec-evm t8n + run: | + mkdir -p "$RUNNER_TEMP/t8n-out" + "$RUNNER_TEMP/wheel-venv/bin/ethereum-spec-evm" t8n \ + --state.fork=Frontier \ + --input.alloc=tests/evm_tools/t8n_build/alloc.json \ + --input.env=tests/evm_tools/t8n_build/env.json \ + --input.txs=tests/evm_tools/t8n_build/txs.json \ + --output.basedir="$RUNNER_TEMP/t8n-out" + test -s "$RUNNER_TEMP/t8n-out/result.json" + fill: name: fill (${{ matrix.label }}) runs-on: [self-hosted-ghr, size-xl-x64] diff --git a/Justfile b/Justfile index 01467ef46fe..f39ca4f174d 100644 --- a/Justfile +++ b/Justfile @@ -215,7 +215,6 @@ spec-tools *args: (_tmp "spec-tools") uv run pytest \ -n {{ xdist_workers }} \ --basetemp="{{ output_dir }}/spec-tools/tmp" \ - --ignore=tests/evm_tools/test_count_opcodes.py \ "$@" \ tests/evm_tools @@ -227,6 +226,7 @@ test-tests *args: (_tmp "test-tests") cd packages/testing && uv run pytest \ -n {{ xdist_workers }} \ --basetemp="{{ output_dir }}/test-tests/tmp" \ + --ignore=src/execution_testing/evm_tools/tests/test_count_opcodes.py \ "$@" \ src @@ -237,6 +237,7 @@ test-tests-pypy *args: (_tmp "test-tests-pypy") -n auto --maxprocesses 6 \ --basetemp="{{ output_dir }}/test-tests-pypy/tmp" \ --ignore=src/execution_testing/cli/pytest_commands/plugins/filler/tests/test_benchmarking.py \ + --ignore=src/execution_testing/evm_tools/tests/test_count_opcodes.py \ "$@" \ src diff --git a/README.md b/README.md index 06b61ff278f..f38aa34efb9 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,10 @@ just shell-completions Python 3.11–3.14 are supported; 3.12 tends to be the smoothest for local setup (pre-built wheels are available across the dependency set). For alternative `just` installation paths, macOS-specific installation notes, and troubleshooting, see [Installation](docs/getting_started/installation.md). +## Reference EVM CLI + +`ethereum-spec-evm` — a `t8n` transition tool, `b11r` block builder, and state-test runner that execute the spec directly — is provided by the `ethereum-execution-testing` workspace package rather than by `ethereum-execution`. Within a checkout it is available as `uv run ethereum-spec-evm`; for standalone installation (e.g. in client CI or fuzzing setups), see [packages/testing/README.md](packages/testing/README.md). + ## Documentation - **Repo documentation (default branch/fork)**: diff --git a/docs/dev/deps_and_packaging.md b/docs/dev/deps_and_packaging.md index c04e4d01b4b..26bd435e9d5 100644 --- a/docs/dev/deps_and_packaging.md +++ b/docs/dev/deps_and_packaging.md @@ -8,8 +8,8 @@ The repo is a `uv` workspace with two members, each defined by its own `pyprojec | Package | `pyproject.toml` | Contents | | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | -| `ethereum-execution` | [`pyproject.toml`](https://github.com/ethereum/execution-specs/blob/a830dab6f130151ab9023a473b7543120aa21961/pyproject.toml) | The Python specs (`src/ethereum/`) and associated tools. | -| `ethereum-execution-testing` | [`packages/testing/pyproject.toml`](https://github.com/ethereum/execution-specs/blob/a830dab6f130151ab9023a473b7543120aa21961/packages/testing/pyproject.toml) | The EEST test framework under `packages/testing/`. | +| `ethereum-execution` | [`pyproject.toml`](https://github.com/ethereum/execution-specs/blob/a830dab6f130151ab9023a473b7543120aa21961/pyproject.toml) | The Python specs (`src/ethereum/`) and spec-maintenance tools (`src/ethereum_spec_tools/`). | +| `ethereum-execution-testing` | [`packages/testing/pyproject.toml`](https://github.com/ethereum/execution-specs/blob/a830dab6f130151ab9023a473b7543120aa21961/packages/testing/pyproject.toml) | The EEST test framework under `packages/testing/`, including the `ethereum-spec-evm` CLI (`t8n`, `b11r`, state-test runner). | A single [`uv.lock`](https://github.com/ethereum/execution-specs/blob/a830dab6f130151ab9023a473b7543120aa21961/uv.lock) at the repo root pins dependencies for both packages. diff --git a/docs/filling_tests/transition_tool_support.md b/docs/filling_tests/transition_tool_support.md index 5a404f5dd07..6a52031a9ba 100644 --- a/docs/filling_tests/transition_tool_support.md +++ b/docs/filling_tests/transition_tool_support.md @@ -5,7 +5,7 @@ The following transition tools are supported by the framework: | Client | `t8n` Tool | Tracing Support | | -------| ---------- | --------------- | | [ethereum/evmone](https://github.com/ethereum/evmone) | `evmone t8n` | Yes | -| [ethereum/execution-specs](https://github.com/ethereum/execution-specs) | [`ethereum-spec-evm t8n`](https://github.com/ethereum/execution-specs/tree/a48e0b381d5225a6c3de2d06cd9ee7ae0b6ca9bb/src/ethereum_spec_tools/evm_tools/t8n) | Yes | +| [ethereum/execution-specs](https://github.com/ethereum/execution-specs) | [`ethereum-spec-evm t8n`](https://github.com/ethereum/execution-specs/tree/forks/amsterdam/packages/testing/src/execution_testing/evm_tools/t8n) | Yes | | [ethereumjs](https://github.com/ethereumjs/ethereumjs-monorepo) | [`ethereumjs-t8ntool.sh`](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/vm/test/t8n) | No | | [ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) | [`evm t8n`](https://github.com/ethereum/go-ethereum/tree/master/cmd/evm) | Yes | | [besu-eth/besu](https://github.com/besu-eth/besu/tree/main/ethereum/evmtool) | [`evmtool t8n-server`](https://github.com/besu-eth/besu/tree/main/ethereum/evmtool) | Yes | diff --git a/docs/getting_started/repository_overview.md b/docs/getting_started/repository_overview.md index 260052099a2..4a6c01c79ea 100644 --- a/docs/getting_started/repository_overview.md +++ b/docs/getting_started/repository_overview.md @@ -39,7 +39,7 @@ Contains the implementation of the Ethereum consensus tests available in this re #### `packages/execution_testing/` -Contains the `execution_testing` package which provides tools to define test cases and to interface with `t8n` command interfaces that are required to generate tests. Additionally, it contains packages that enable test case execution by customizing pytest which acts as the test framework. +Contains the `execution_testing` package which provides tools to define test cases and to interface with `t8n` command interfaces that are required to generate tests. Additionally, it contains packages that enable test case execution by customizing pytest which acts as the test framework. It also ships the reference EVM `t8n` implementation, which `fill` runs in-process to generate the fixtures in this repository, and which external consumers can drive through the `ethereum-spec-evm` CLI. #### `docs/` diff --git a/docs/library/execution_testing_evm_tools.md b/docs/library/execution_testing_evm_tools.md new file mode 100644 index 00000000000..c9d6d09bcb9 --- /dev/null +++ b/docs/library/execution_testing_evm_tools.md @@ -0,0 +1,3 @@ +# EVM Tools Package + +::: execution_testing.evm_tools diff --git a/docs/library/index.md b/docs/library/index.md index ebb258b04e9..34d7bffddff 100644 --- a/docs/library/index.md +++ b/docs/library/index.md @@ -11,4 +11,5 @@ Execution spec tests consists of several packages that implement helper classes - [`execution_testing.test_types`](./execution_testing_test_types.md) - provides Ethereum types built on top of the base types which are used to define test cases and interact with other libraries. - [`execution_testing.vm`](./execution_testing_vm.md) - provides definitions for the Ethereum Virtual Machine (EVM) as used to define bytecode in test cases. - [`execution_testing.client_clis`](./execution_testing_client_clis.md) - a wrapper for the transition (`t8n`) tool. +- [`execution_testing.evm_tools`](./execution_testing_evm_tools.md) - the `ethereum-spec-evm` CLI: `t8n`, `b11r`, and state-test tools that run the execution specs directly. - [`pytest_plugins`](./pytest_plugins/index.md) - contains pytest customizations that provide additional functionality for generating test fixtures. diff --git a/docs/navigation.md b/docs/navigation.md index db82611d077..aa61e2bd46e 100644 --- a/docs/navigation.md +++ b/docs/navigation.md @@ -98,6 +98,7 @@ * [Execution Testing Test Types Package](library/execution_testing_test_types.md) * [Execution Testing VM Package](library/execution_testing_vm.md) * [Execution Testing Client CLIs Package](library/execution_testing_client_clis.md) + * [Execution Testing EVM Tools Package](library/execution_testing_evm_tools.md) * [Pytest Plugins](library/pytest_plugins/index.md) * [Filler](library/pytest_plugins/filler.md) * [Forks](library/pytest_plugins/forks.md) diff --git a/packages/testing/README.md b/packages/testing/README.md new file mode 100644 index 00000000000..0ec1f44a035 --- /dev/null +++ b/packages/testing/README.md @@ -0,0 +1,37 @@ +# The `ethereum-execution-testing` Package + +Test generation and execution framework for the [Ethereum Execution Layer Specifications (EELS)](https://github.com/ethereum/execution-specs), derived from [ethereum/execution-spec-tests](https://github.com/ethereum/execution-spec-tests). + +The package provides: + +- The `execution_testing` library: base types, fork definitions, and test-spec primitives used to write consensus test cases. +- The pytest-based commands that generate and run test fixtures against execution clients: `fill`, `execute`, `consume`, and friends. +- `ethereum-spec-evm` — the reference EVM CLI that executes the spec directly: a `t8n` transition tool (also available as a daemon), a `b11r` block builder, and a state-test runner. + +## Installing `ethereum-spec-evm` standalone + +This package depends on `ethereum-execution` (the spec itself), and the two are developed in lockstep: the spec releases published on PyPI only carry forks that are live on mainnet and generally cannot satisfy this package's dependency pins. Install both packages from the same clone. + +With `uv` (resolves the sibling spec package from the checkout automatically): + +```console +git clone https://github.com/ethereum/execution-specs +uv tool install ./execution-specs/packages/testing +``` + +With `pip`, in a virtual environment: + +```console +pip install ./execution-specs ./execution-specs/packages/testing +``` + +With `pipx`: + +```console +pipx install ./execution-specs +pipx inject --include-apps ethereum-execution ./execution-specs/packages/testing +``` + +## Documentation + +Repository documentation, including this framework's reference documentation: diff --git a/packages/testing/pyproject.toml b/packages/testing/pyproject.toml index bca724ebe52..ea993a65dfc 100644 --- a/packages/testing/pyproject.toml +++ b/packages/testing/pyproject.toml @@ -78,6 +78,7 @@ dev = [ ] [project.scripts] +ethereum-spec-evm = "execution_testing.evm_tools:main" fill = "execution_testing.cli.pytest_commands.fill:fill" phil = "execution_testing.cli.pytest_commands.fill:phil" execute = "execution_testing.cli.pytest_commands.execute:execute" @@ -143,6 +144,7 @@ markers = [ "some_mark: Test marker for parametrizer tests", "eip_checklist: Custom marker for EIP checklist tests", "slow: Marks tests as slow running", + "evm_tools: marks tests as evm_tools (deselect with '-m \"not evm_tools\"')", ] [tool.uv] diff --git a/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py b/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py index 4d5d7d81865..7d007cca02a 100644 --- a/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py +++ b/packages/testing/src/execution_testing/client_clis/clis/execution_specs.py @@ -29,7 +29,7 @@ from execution_testing.forks import Fork if TYPE_CHECKING: - from ethereum_spec_tools.evm_tools.t8n import ForkCache + from execution_testing.evm_tools.t8n import ForkCache class ExecutionSpecsTransitionTool(TransitionTool): @@ -60,7 +60,7 @@ def __init__( def fork_cache(self) -> "ForkCache": """Lazily import and instantiate the EELS fork cache on first use.""" if self._fork_cache is None: - from ethereum_spec_tools.evm_tools.t8n import ForkCache + from execution_testing.evm_tools.t8n import ForkCache self._fork_cache = ForkCache() return self._fork_cache @@ -80,7 +80,7 @@ def version(self) -> str: def is_fork_supported(self, fork: Fork) -> bool: """Return True if the fork is supported by the tool.""" - from ethereum_spec_tools.evm_tools.utils import get_supported_forks + from ethereum_spec_tools.utils import get_supported_forks return fork.transition_tool_name() in get_supported_forks() @@ -100,14 +100,14 @@ def _evaluate( — and ``T8N.run()`` returns the ``TransitionToolOutput`` directly. """ - from ethereum_spec_tools.evm_tools.t8n import T8N - from ethereum_spec_tools.evm_tools.t8n.evm_trace.count import ( + from execution_testing.evm_tools.t8n import T8N + from execution_testing.evm_tools.t8n.evm_trace.count import ( CountTracer, ) - from ethereum_spec_tools.evm_tools.t8n.evm_trace.eip3155 import ( + from execution_testing.evm_tools.t8n.evm_trace.eip3155 import ( Eip3155Tracer, ) - from ethereum_spec_tools.evm_tools.t8n.evm_trace.group import ( + from execution_testing.evm_tools.t8n.evm_trace.group import ( GroupTracer, ) diff --git a/src/ethereum_spec_tools/evm_tools/__init__.py b/packages/testing/src/execution_testing/evm_tools/__init__.py similarity index 98% rename from src/ethereum_spec_tools/evm_tools/__init__.py rename to packages/testing/src/execution_testing/evm_tools/__init__.py index bf854c088cd..14165c170de 100644 --- a/src/ethereum_spec_tools/evm_tools/__init__.py +++ b/packages/testing/src/execution_testing/evm_tools/__init__.py @@ -10,13 +10,13 @@ from typing import Optional, Sequence, Text, TextIO from ethereum import __version__ +from ethereum_spec_tools.utils import get_supported_forks from .b11r import B11R, b11r_arguments from .daemon import Daemon, daemon_arguments from .statetest import StateTest, state_test_arguments from .t8n import ForkCache from .t8n.cli import run_t8n_cli, t8n_arguments -from .utils import get_supported_forks DESCRIPTION = """ This is the EVM tool for execution specs. The EVM tool diff --git a/src/ethereum_spec_tools/evm_tools/__main__.py b/packages/testing/src/execution_testing/evm_tools/__main__.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/__main__.py rename to packages/testing/src/execution_testing/evm_tools/__main__.py diff --git a/src/ethereum_spec_tools/evm_tools/b11r/__init__.py b/packages/testing/src/execution_testing/evm_tools/b11r/__init__.py similarity index 98% rename from src/ethereum_spec_tools/evm_tools/b11r/__init__.py rename to packages/testing/src/execution_testing/evm_tools/b11r/__init__.py index e106af5cd76..96af1938bf4 100644 --- a/src/ethereum_spec_tools/evm_tools/b11r/__init__.py +++ b/packages/testing/src/execution_testing/evm_tools/b11r/__init__.py @@ -6,12 +6,11 @@ import json from typing import Optional, TextIO +from ethereum.crypto.hash import keccak256 from ethereum_rlp import rlp +from ethereum_spec_tools.utils import get_stream_logger from ethereum_types.bytes import Bytes32 -from ethereum.crypto.hash import keccak256 - -from ..utils import get_stream_logger from .b11r_types import Body, Header diff --git a/src/ethereum_spec_tools/evm_tools/b11r/b11r_types.py b/packages/testing/src/execution_testing/evm_tools/b11r/b11r_types.py similarity index 99% rename from src/ethereum_spec_tools/evm_tools/b11r/b11r_types.py rename to packages/testing/src/execution_testing/evm_tools/b11r/b11r_types.py index f15a1ce5473..ddac99ac490 100644 --- a/src/ethereum_spec_tools/evm_tools/b11r/b11r_types.py +++ b/packages/testing/src/execution_testing/evm_tools/b11r/b11r_types.py @@ -5,15 +5,13 @@ import json from typing import Any, List, Optional, Tuple +from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.utils.hexadecimal import hex_to_bytes, hex_to_bytes8 from ethereum_rlp import rlp +from ethereum_spec_tools.utils import parse_hex_or_int from ethereum_types.bytes import Bytes, Bytes8, Bytes20, Bytes32, Bytes256 from ethereum_types.numeric import U64, U256, Uint -from ethereum.crypto.hash import Hash32, keccak256 -from ethereum.utils.hexadecimal import hex_to_bytes, hex_to_bytes8 - -from ..utils import parse_hex_or_int - DEFAULT_TRIE_ROOT = ( "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" ) diff --git a/src/ethereum_spec_tools/evm_tools/daemon.py b/packages/testing/src/execution_testing/evm_tools/daemon.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/daemon.py rename to packages/testing/src/execution_testing/evm_tools/daemon.py diff --git a/src/ethereum_spec_tools/evm_tools/statetest/__init__.py b/packages/testing/src/execution_testing/evm_tools/statetest/__init__.py similarity index 99% rename from src/ethereum_spec_tools/evm_tools/statetest/__init__.py rename to packages/testing/src/execution_testing/evm_tools/statetest/__init__.py index e9b74e62e65..51c6192a90e 100644 --- a/src/ethereum_spec_tools/evm_tools/statetest/__init__.py +++ b/packages/testing/src/execution_testing/evm_tools/statetest/__init__.py @@ -21,10 +21,10 @@ ) from ethereum.utils.hexadecimal import hex_to_bytes +from ethereum_spec_tools.utils import get_supported_forks from ..t8n import ForkCache from ..t8n.cli import build_t8n_from_cli_options -from ..utils import get_supported_forks if TYPE_CHECKING: from execution_testing.client_clis.cli_types import ( diff --git a/src/ethereum_spec_tools/evm_tools/t8n/__init__.py b/packages/testing/src/execution_testing/evm_tools/t8n/__init__.py similarity index 98% rename from src/ethereum_spec_tools/evm_tools/t8n/__init__.py rename to packages/testing/src/execution_testing/evm_tools/t8n/__init__.py index 5d263f3fc34..8469f0667f2 100644 --- a/src/ethereum_spec_tools/evm_tools/t8n/__init__.py +++ b/packages/testing/src/execution_testing/evm_tools/t8n/__init__.py @@ -18,23 +18,25 @@ TypeVar, ) -from ethereum_rlp import rlp -from ethereum_types.bytes import Bytes -from ethereum_types.numeric import U64, U256, Uint -from typing_extensions import override - from ethereum import trace from ethereum.exceptions import EthereumException, InvalidBlock from ethereum.fork_criteria import ByBlockNumber, ByTimestamp, Unscheduled +from ethereum_rlp import rlp from ethereum_spec_tools.forks import ( ForkOverrides, Hardfork, TemporaryHardfork, ) +from ethereum_spec_tools.loaders.fixture_loader import Load +from ethereum_spec_tools.loaders.transaction_loader import ( + TransactionLoad, + UnsupportedTxError, +) +from ethereum_spec_tools.utils import get_stream_logger, resolve_fork +from ethereum_types.bytes import Bytes +from ethereum_types.numeric import U64, U256, Uint +from typing_extensions import override -from ..loaders.fixture_loader import Load -from ..loaders.transaction_loader import TransactionLoad, UnsupportedTxError -from ..utils import get_stream_logger, resolve_fork from .block_environment import Ommer, build_block_environment from .evm_trace.group import GroupTracer from .result import build_result, record_rejected_tx diff --git a/src/ethereum_spec_tools/evm_tools/t8n/block_environment.py b/packages/testing/src/execution_testing/evm_tools/t8n/block_environment.py similarity index 99% rename from src/ethereum_spec_tools/evm_tools/t8n/block_environment.py rename to packages/testing/src/execution_testing/evm_tools/t8n/block_environment.py index aab52779c9d..3a602b9c6c4 100644 --- a/src/ethereum_spec_tools/evm_tools/t8n/block_environment.py +++ b/packages/testing/src/execution_testing/evm_tools/t8n/block_environment.py @@ -6,16 +6,15 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Any, List, Optional +from ethereum.crypto.hash import Hash32, keccak256 from ethereum_rlp import rlp from ethereum_types.bytes import Bytes8, Bytes20, Bytes32, Bytes256 from ethereum_types.numeric import U64, U256, Uint -from ethereum.crypto.hash import Hash32, keccak256 - if TYPE_CHECKING: - from execution_testing.test_types import Environment as TestingEnvironment + from ethereum_spec_tools.loaders.fork_loader import ForkLoad - from ..loaders.fork_loader import ForkLoad + from execution_testing.test_types import Environment as TestingEnvironment @dataclass diff --git a/src/ethereum_spec_tools/evm_tools/t8n/cli.py b/packages/testing/src/execution_testing/evm_tools/t8n/cli.py similarity index 97% rename from src/ethereum_spec_tools/evm_tools/t8n/cli.py rename to packages/testing/src/execution_testing/evm_tools/t8n/cli.py index 14fb0e737c3..1cbb8d9fa07 100644 --- a/src/ethereum_spec_tools/evm_tools/t8n/cli.py +++ b/packages/testing/src/execution_testing/evm_tools/t8n/cli.py @@ -22,13 +22,12 @@ from typing import Any, Dict, List, Optional, TextIO, Tuple from ethereum_rlp import rlp +from ethereum_spec_tools.forks import Hardfork +from ethereum_spec_tools.loaders.fork_loader import ForkLoad +from ethereum_spec_tools.utils import FatalError, find_fork, parse_hex_or_int from ethereum_types.bytes import Bytes from ethereum_types.numeric import U64 -from ethereum_spec_tools.forks import Hardfork - -from ..loaders.fork_loader import ForkLoad -from ..utils import FatalError, find_fork, parse_hex_or_int from . import T8N, ForkCache from .block_environment import Ommer from .evm_trace.count import CountTracer @@ -307,10 +306,6 @@ def build_t8n_from_cli_options( testing pydantic types, bundles them into a ``TransitionToolData``, builds the tracer group, and hands them to ``T8N``. """ - # Function-scoped imports: ``execution_testing/__init__`` eagerly - # imports ``.specs`` which transitively imports ``client_clis``, - # which imports ``ExecutionSpecsTransitionTool`` — top-level imports - # from ``execution_testing`` would cycle back into spec-tools. from execution_testing.base_types.composite_types import BlobSchedule from execution_testing.client_clis.transition_tool import TransitionTool from execution_testing.test_types import ( diff --git a/src/ethereum_spec_tools/evm_tools/t8n/evm_trace/__init__.py b/packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/__init__.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/t8n/evm_trace/__init__.py rename to packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/__init__.py diff --git a/src/ethereum_spec_tools/evm_tools/t8n/evm_trace/count.py b/packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/count.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/t8n/evm_trace/count.py rename to packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/count.py diff --git a/src/ethereum_spec_tools/evm_tools/t8n/evm_trace/eip3155.py b/packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/eip3155.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/t8n/evm_trace/eip3155.py rename to packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/eip3155.py diff --git a/src/ethereum_spec_tools/evm_tools/t8n/evm_trace/group.py b/packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/group.py similarity index 99% rename from src/ethereum_spec_tools/evm_tools/t8n/evm_trace/group.py rename to packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/group.py index 72e9858d83c..7a7d378b245 100644 --- a/src/ethereum_spec_tools/evm_tools/t8n/evm_trace/group.py +++ b/packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/group.py @@ -4,9 +4,8 @@ from typing import Final -from typing_extensions import override - from ethereum.trace import EvmTracer, TraceEvent +from typing_extensions import override class GroupTracer(EvmTracer): diff --git a/src/ethereum_spec_tools/evm_tools/t8n/evm_trace/protocols.py b/packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/protocols.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/t8n/evm_trace/protocols.py rename to packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/protocols.py diff --git a/src/ethereum_spec_tools/evm_tools/t8n/result.py b/packages/testing/src/execution_testing/evm_tools/t8n/result.py similarity index 96% rename from src/ethereum_spec_tools/evm_tools/t8n/result.py rename to packages/testing/src/execution_testing/evm_tools/t8n/result.py index 5bab2af3b75..0b07a60a20e 100644 --- a/src/ethereum_spec_tools/evm_tools/t8n/result.py +++ b/packages/testing/src/execution_testing/evm_tools/t8n/result.py @@ -8,10 +8,9 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional -from ethereum_rlp import rlp - from ethereum.crypto.hash import keccak256 from ethereum.merkle_patricia_trie import root, trie_get +from ethereum_rlp import rlp if TYPE_CHECKING: from execution_testing.client_clis.cli_types import ( @@ -24,9 +23,9 @@ def get_receipts_from_output(t8n: "T8N", block_output: Any) -> List[Any]: """Build testing-side `TransactionReceipt`s from the block output tries.""" # Function-scoped: ``execution_testing/__init__`` eagerly imports - # ``.specs`` which transitively imports ``client_clis``, which - # imports ``ExecutionSpecsTransitionTool`` — top-level import would - # cycle back into ``t8n``. + # ``.specs`` -> ``client_clis`` -> ``ExecutionSpecsTransitionTool``, + # which imports ``t8n`` to run it in-process. A top-level import here + # would run while ``client_clis`` is still mid-initialization. from execution_testing.test_types.receipt_types import ( TransactionLog, TransactionReceipt, diff --git a/tests/evm_tools/test_count_opcodes.py b/packages/testing/src/execution_testing/evm_tools/tests/test_count_opcodes.py similarity index 88% rename from tests/evm_tools/test_count_opcodes.py rename to packages/testing/src/execution_testing/evm_tools/tests/test_count_opcodes.py index 0ced37e51f5..4ecece77c49 100644 --- a/tests/evm_tools/test_count_opcodes.py +++ b/packages/testing/src/execution_testing/evm_tools/tests/test_count_opcodes.py @@ -10,9 +10,9 @@ import pytest -from ethereum_spec_tools.evm_tools import create_parser -from ethereum_spec_tools.evm_tools.t8n import ForkCache -from ethereum_spec_tools.evm_tools.t8n.cli import run_t8n_cli +from execution_testing.evm_tools import create_parser +from execution_testing.evm_tools.t8n import ForkCache +from execution_testing.evm_tools.t8n.cli import run_t8n_cli parser = create_parser() diff --git a/tests/evm_tools/test_daemon.py b/packages/testing/src/execution_testing/evm_tools/tests/test_daemon.py similarity index 81% rename from tests/evm_tools/test_daemon.py rename to packages/testing/src/execution_testing/evm_tools/tests/test_daemon.py index 6d4d08b74c3..caa6f2ec976 100644 --- a/tests/evm_tools/test_daemon.py +++ b/packages/testing/src/execution_testing/evm_tools/tests/test_daemon.py @@ -4,8 +4,8 @@ import pytest -from ethereum_spec_tools.evm_tools import daemon -from ethereum_spec_tools.evm_tools.daemon import Daemon +from execution_testing.evm_tools import daemon +from execution_testing.evm_tools.daemon import Daemon def test_daemon_run_rejects_windows( diff --git a/tests/evm_tools/test_fork_cache.py b/packages/testing/src/execution_testing/evm_tools/tests/test_fork_cache.py similarity index 99% rename from tests/evm_tools/test_fork_cache.py rename to packages/testing/src/execution_testing/evm_tools/tests/test_fork_cache.py index 516943aac5c..618de35f702 100644 --- a/tests/evm_tools/test_fork_cache.py +++ b/packages/testing/src/execution_testing/evm_tools/tests/test_fork_cache.py @@ -4,16 +4,16 @@ from typing import Any import pytest -from ethereum_types.numeric import U64, Uint -from typing_extensions import assert_never - from ethereum.fork_criteria import ( ByBlockNumber, ByTimestamp, Unscheduled, ) -from ethereum_spec_tools.evm_tools.t8n import ForkCache from ethereum_spec_tools.forks import ForkOverrides, Hardfork +from ethereum_types.numeric import U64, Uint +from typing_extensions import assert_never + +from execution_testing.evm_tools.t8n import ForkCache pytestmark = pytest.mark.evm_tools diff --git a/pyproject.toml b/pyproject.toml index 23a1eff6527..f2d18881d36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,12 +37,7 @@ dependencies = [ [tool.setuptools] packages = [ "ethereum_spec_tools", - "ethereum_spec_tools.evm_tools", - "ethereum_spec_tools.evm_tools.t8n", - "ethereum_spec_tools.evm_tools.t8n.evm_trace", - "ethereum_spec_tools.evm_tools.b11r", - "ethereum_spec_tools.evm_tools.statetest", - "ethereum_spec_tools.evm_tools.loaders", + "ethereum_spec_tools.loaders", "ethereum_spec_tools.lint", "ethereum_spec_tools.lint.lints", "ethereum_spec_tools.new_fork", @@ -272,7 +267,6 @@ ethereum-spec-lint = "ethereum_spec_tools.lint:main" ethereum-spec-sync = "ethereum_spec_tools.sync:main" ethereum-spec-new-fork = "ethereum_spec_tools.new_fork.cli:main" ethereum-spec-patch = "ethereum_spec_tools.patch_tool:main" -ethereum-spec-evm = "ethereum_spec_tools.evm_tools:main" whitelist = "ethereum_spec_tools.whitelist:main" [project.entry-points."docc.plugins"] @@ -293,7 +287,6 @@ whitelist = "ethereum_spec_tools.whitelist:main" markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", "bigmem: marks tests as big memory (deselect with '-m \"not bigmem\"')", - "evm_tools: marks tests as evm_tools (deselect with '-m \"not evm_tools\"')", "json_blockchain_tests: marks tests as json_blockchain_tests (deselect with '-m \"not json_blockchain_tests\"')", "json_state_tests: marks tests as json_state_tests (deselect with '-m \"not json_state_tests\"')", "vm_test: marks tests as vm_test (deselect with '-m \"not vm_test\"')", @@ -424,7 +417,7 @@ ignore = [ ] [tool.ruff.lint.per-file-ignores] -"src/ethereum_spec_tools/evm_tools/loaders/fork_loader.py" = [ +"src/ethereum_spec_tools/loaders/fork_loader.py" = [ "N802" # Property names do not need to be lowercase ] "src/ethereum_spec_tools/lint/*" = [ @@ -434,13 +427,11 @@ ignore = [ "N806", # Special crypto code absolved of variable naming reqs "N802" # Special crypto code absolved of function naming reqs ] -"src/ethereum_spec_tools/evm_tools/t8n/evm_trace/eip3155.py" = [ - "N815" # The traces must use camel case in JSON property names -] -"src/ethereum_spec_tools/evm_tools/t8n/evm_trace.py" = [ +"packages/testing/src/execution_testing/evm_tools/t8n/evm_trace/eip3155.py" = [ "N815" # The traces must use camel case in JSON property names ] "tests/*" = ["ARG001"] +"packages/testing/src/execution_testing/evm_tools/tests/*" = ["ARG001"] "vulture_whitelist.py" = [ "B018", # Useless expression (intentional for Vulture whitelisting) "E402", # Module-level imports throughout file (needed for whitelisting) diff --git a/src/ethereum_spec_tools/evm_tools/loaders/__init__.py b/src/ethereum_spec_tools/loaders/__init__.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/loaders/__init__.py rename to src/ethereum_spec_tools/loaders/__init__.py diff --git a/src/ethereum_spec_tools/evm_tools/loaders/fixture_loader.py b/src/ethereum_spec_tools/loaders/fixture_loader.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/loaders/fixture_loader.py rename to src/ethereum_spec_tools/loaders/fixture_loader.py diff --git a/src/ethereum_spec_tools/evm_tools/loaders/fork_loader.py b/src/ethereum_spec_tools/loaders/fork_loader.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/loaders/fork_loader.py rename to src/ethereum_spec_tools/loaders/fork_loader.py diff --git a/src/ethereum_spec_tools/evm_tools/loaders/transaction_loader.py b/src/ethereum_spec_tools/loaders/transaction_loader.py similarity index 99% rename from src/ethereum_spec_tools/evm_tools/loaders/transaction_loader.py rename to src/ethereum_spec_tools/loaders/transaction_loader.py index da882c94d99..ae2cab3ba41 100644 --- a/src/ethereum_spec_tools/evm_tools/loaders/transaction_loader.py +++ b/src/ethereum_spec_tools/loaders/transaction_loader.py @@ -19,7 +19,7 @@ hex_to_u256, hex_to_uint, ) -from ethereum_spec_tools.evm_tools.utils import parse_hex_or_int +from ethereum_spec_tools.utils import parse_hex_or_int class UnsupportedTxError(Exception): diff --git a/src/ethereum_spec_tools/evm_tools/utils.py b/src/ethereum_spec_tools/utils.py similarity index 100% rename from src/ethereum_spec_tools/evm_tools/utils.py rename to src/ethereum_spec_tools/utils.py diff --git a/tests/evm_tools/t8n_build/alloc.json b/tests/evm_tools/t8n_build/alloc.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/tests/evm_tools/t8n_build/alloc.json @@ -0,0 +1 @@ +{} diff --git a/tests/evm_tools/t8n_build/env.json b/tests/evm_tools/t8n_build/env.json new file mode 100644 index 00000000000..468fd210bf1 --- /dev/null +++ b/tests/evm_tools/t8n_build/env.json @@ -0,0 +1,7 @@ +{ + "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentGasLimit": "0x016345785d8a0000", + "currentNumber": "0x01", + "currentTimestamp": "0x03e8", + "currentDifficulty": "0x020000" +} diff --git a/tests/evm_tools/t8n_build/txs.json b/tests/evm_tools/t8n_build/txs.json new file mode 100644 index 00000000000..fe51488c706 --- /dev/null +++ b/tests/evm_tools/t8n_build/txs.json @@ -0,0 +1 @@ +[] diff --git a/tests/json_loader/conftest.py b/tests/json_loader/conftest.py index e5faa6b1532..f2027c4faa3 100644 --- a/tests/json_loader/conftest.py +++ b/tests/json_loader/conftest.py @@ -5,10 +5,9 @@ from _pytest.config.argparsing import Parser from _pytest.nodes import Item +from execution_testing.evm_tools.t8n import ForkCache from pytest import Collector, Config, Session, fixture -from ethereum_spec_tools.evm_tools.t8n import ForkCache - from . import FORKS from .helpers import FixturesFile, FixtureTestItem from .helpers.select_tests import extract_affected_forks @@ -119,11 +118,12 @@ def pytest_configure(config: Config) -> None: ethereum_optimized.monkey_patch(None) if config.getoption("evm_trace"): - import ethereum.trace - from ethereum_spec_tools.evm_tools.t8n.evm_trace.eip3155 import ( + from execution_testing.evm_tools.t8n.evm_trace.eip3155 import ( Eip3155Tracer, ) + import ethereum.trace + # Replace the function in the module ethereum.trace.set_evm_trace(Eip3155Tracer()) diff --git a/tests/json_loader/helpers/load_blockchain_tests.py b/tests/json_loader/helpers/load_blockchain_tests.py index feec8e44b0f..0ff4b8c36a1 100644 --- a/tests/json_loader/helpers/load_blockchain_tests.py +++ b/tests/json_loader/helpers/load_blockchain_tests.py @@ -14,7 +14,7 @@ from ethereum.exceptions import EthereumException, StateWithEmptyAccount from ethereum.state_mpt import close_state from ethereum.utils.hexadecimal import hex_to_bytes -from ethereum_spec_tools.evm_tools.loaders.fixture_loader import Load +from ethereum_spec_tools.loaders.fixture_loader import Load from .. import FORKS from ..stash_keys import desired_forks_key diff --git a/tests/json_loader/helpers/load_state_tests.py b/tests/json_loader/helpers/load_state_tests.py index 52a4557ff53..b645be0be0b 100644 --- a/tests/json_loader/helpers/load_state_tests.py +++ b/tests/json_loader/helpers/load_state_tests.py @@ -7,14 +7,14 @@ import pytest from _pytest.config import Config from _pytest.nodes import Item +from execution_testing.evm_tools import create_parser +from execution_testing.evm_tools.statetest import read_test_case +from execution_testing.evm_tools.t8n import ForkCache +from execution_testing.evm_tools.t8n.cli import build_t8n_from_cli_options from pytest import Collector from ethereum.exceptions import StateWithEmptyAccount from ethereum.utils.hexadecimal import hex_to_bytes -from ethereum_spec_tools.evm_tools import create_parser -from ethereum_spec_tools.evm_tools.statetest import read_test_case -from ethereum_spec_tools.evm_tools.t8n import ForkCache -from ethereum_spec_tools.evm_tools.t8n.cli import build_t8n_from_cli_options from .. import FORKS from ..stash_keys import desired_forks_key, fork_cache_key diff --git a/tests/json_loader/helpers/select_tests.py b/tests/json_loader/helpers/select_tests.py index 452a782e6c0..ff77a3d6018 100644 --- a/tests/json_loader/helpers/select_tests.py +++ b/tests/json_loader/helpers/select_tests.py @@ -70,10 +70,18 @@ def extract_affected_forks( # Run all forks if something changes in the test # framework return all_forks - if file_path.is_relative_to("src/ethereum_spec_tools/evm_tools"): + if file_path.is_relative_to( + "packages/testing/src/execution_testing/evm_tools" + ): # Run all forks if something changes in the evm # tools return all_forks + if file_path.is_relative_to( + "src/ethereum_spec_tools/loaders" + ) or file_path == Path("src/ethereum_spec_tools/utils.py"): + # Run all forks if something changes in the fixture/fork + # loading or shared helpers the evm tools depend on + return all_forks if optimized and file_path.is_relative_to("src/ethereum_optimized"): # Run all forks if something changes in the optimized tools and # while running optimized environment. diff --git a/tests/json_loader/stash_keys.py b/tests/json_loader/stash_keys.py index 63002ce3ab0..ae242c9a3d2 100644 --- a/tests/json_loader/stash_keys.py +++ b/tests/json_loader/stash_keys.py @@ -1,8 +1,7 @@ """Shared StashKey definitions for json_loader tests.""" +from execution_testing.evm_tools.t8n import ForkCache from pytest import StashKey -from ethereum_spec_tools.evm_tools.t8n import ForkCache - desired_forks_key = StashKey[list[str]]() fork_cache_key = StashKey[ForkCache]() diff --git a/vulture_whitelist.py b/vulture_whitelist.py index e944b4e3f7c..7608c553732 100644 --- a/vulture_whitelist.py +++ b/vulture_whitelist.py @@ -7,7 +7,6 @@ """ from ethereum.cancun.blocks import Withdrawal -from ethereum_spec_tools.evm_tools.t8n.transition_tool import EELST8N from ethereum.ethash import * from ethereum.fork_criteria import Unscheduled @@ -15,15 +14,6 @@ from ethereum.utils.hexadecimal import hex_to_bytes256 from ethereum_optimized.state_db import State from ethereum_spec_tools.docc import * -from ethereum_spec_tools.evm_tools.daemon import _EvmToolHandler -from ethereum_spec_tools.evm_tools.loaders.transaction_loader import ( - TransactionLoad, -) -from ethereum_spec_tools.evm_tools.t8n.block_environment import Ommer -from ethereum_spec_tools.evm_tools.t8n.evm_trace.eip3155 import ( - FinalTrace, - Trace, -) from ethereum_spec_tools.lint.lints.final_decorator import ( FinalDecoratorHygiene, ) @@ -32,6 +22,9 @@ ) from ethereum_spec_tools.lint.lints.import_hygiene import ImportHygiene from ethereum_spec_tools.lint.lints.uint_len import UintLenHygiene +from ethereum_spec_tools.loaders.transaction_loader import ( + TransactionLoad, +) from ethereum_spec_tools.new_fork.codemod.comment import CommentReplaceCommand from ethereum_spec_tools.new_fork.codemod.constant import SetConstantCommand from ethereum_spec_tools.new_fork.codemod.string_replace import ( @@ -91,17 +84,6 @@ docc.render_before_after docc._EthereumListingSource.listing_order_key -# src/ethereum_spec_tools/evm_tools/daemon.py -_EvmToolHandler.do_POST -_EvmToolHandler.log_request - -# src/ethereum_spec_tools/evm_tools/transition_tool.py -EELST8N -EELST8N._info_metadata -EELST8N.version -EELST8N.is_fork_supported -EELST8N.evaluate - # src/ethereum_spec_tools/loaders/transaction_loader.py TransactionLoad.json_to_authorizations TransactionLoad.json_to_chain_id @@ -121,25 +103,6 @@ TransactionLoad.json_to_r TransactionLoad.json_to_s -# src/ethereum_spec_tools/evm_tools/t8n/block_environment.py -Ommer.delta - -# src/ethereum_spec_tools/evm_tools/t8n/__init__.py -# `protected` is a field on the testing-package `Transaction` model; -# T8N flips it to False for pre-EIP-155 forks before calling `sign()`. -_unused_protected_marker = None -_unused_protected_marker.protected # type: ignore[attr-defined] - -# src/ethereum_spec_tools/evm_tools/t8n/evm_trace/eip3155.py -Trace.gasCost -Trace.memSize -Trace.returnData -Trace.refund -Trace.opName -Trace.stateGas -Trace.stateGasCost -FinalTrace.gasUsed - # src/ethereum_spec_tools/lint/lints/final_decorator.py FinalDecoratorHygiene @@ -173,8 +136,8 @@ _children # unused attribute (src/ethereum_spec_tools/docc.py:751) -# evm_tools/loaders/fixture_loader.py - abstract methods -from ethereum_spec_tools.evm_tools.loaders.fixture_loader import BaseLoad +# loaders/fixture_loader.py - abstract methods +from ethereum_spec_tools.loaders.fixture_loader import BaseLoad BaseLoad.json_to_header BaseLoad.json_to_state @@ -202,3 +165,40 @@ _configure_client_manager # autouse fixture test_suite_name # hive test suite name fixture genesis_header # genesis header fixture + +# Symbols whose only consumers live in the testing package +# (`execution_testing.evm_tools`), which Vulture does not scan. + +# src/ethereum/forks/*/blocks.py - read by the t8n receipt handling +Receipt.succeeded + +# src/ethereum/forks/*/vm/__init__.py - set by the t8n tracers +TransactionEnvironment.index_in_block +TransactionEnvironment.tx_hash + +# src/ethereum/trace.py - used by the t8n EIP-3155 tracer +StateGasAndRefund.state_gas_cost +set_evm_trace + +# src/ethereum_spec_tools/forks.py - used by the t8n fork cache +Hardfork.matches_template +Hardfork.clone + +# src/ethereum_spec_tools/loaders/fixture_loader.py - used by the t8n +Load + +# src/ethereum_spec_tools/loaders/fork_loader.py - used by the t8n +ForkLoad.has_beacon_roots_address +ForkLoad.calculate_block_difficulty_arity +ForkLoad.has_calculate_base_fee_per_gas +ForkLoad.has_hash_block_access_list +ForkLoad.has_compute_requests_hash +ForkLoad.has_withdrawal +ForkLoad.has_slot_number + +# src/ethereum_spec_tools/utils.py - used by the evm_tools CLI +FatalError +find_fork +resolve_fork +get_supported_forks +get_stream_logger