diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 85079f5ece0..9cd286862ee 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -41,6 +41,7 @@ This release additionally includes fixes for tests in hive, as well as new test - ✨ Added `--watch` flag that monitors test files for changes and automatically re-runs the fill command when developing tests ([#2173](https://github.com/ethereum/execution-spec-tests/pull/2173)). - 🔀 Upgraded ckzg version to 2.1.3 or newer for correct handling of points at infinity ([#2171](https://github.com/ethereum/execution-spec-tests/pull/2171)). - 🔀 Move pytest marker registration for `fill` and `execute-*` from their respective ini files to the shared `pytest_plugins.shared.execute_fill` pytest plugin ([#2110](https://github.com/ethereum/execution-spec-tests/pull/2110)). +- ✨ Added an `--input.blobParams` CLI argument to the transition tool (`t8n`) invocation ([#2264](https://github.com/ethereum/execution-spec-tests/pull/2264)). #### `consume` diff --git a/src/ethereum_clis/cli_types.py b/src/ethereum_clis/cli_types.py index c1b1ba8385b..2093f5563bc 100644 --- a/src/ethereum_clis/cli_types.py +++ b/src/ethereum_clis/cli_types.py @@ -7,7 +7,6 @@ from pydantic import Field, PlainSerializer, PlainValidator from ethereum_test_base_types import ( - BlobSchedule, Bloom, Bytes, CamelModel, @@ -15,6 +14,7 @@ Hash, HexNumber, ) +from ethereum_test_base_types.composite_types import ForkBlobSchedule from ethereum_test_exceptions import ( BlockException, ExceptionMapperValidator, @@ -259,6 +259,7 @@ class TransitionToolInput(CamelModel): alloc: Alloc txs: List[Transaction] env: Environment + blob_params: ForkBlobSchedule | None = None class TransitionToolOutput(CamelModel): @@ -275,7 +276,6 @@ class TransitionToolContext(CamelModel): fork: str chain_id: int = Field(..., alias="chainid") reward: int - blob_schedule: BlobSchedule | None class TransitionToolRequest(CamelModel): diff --git a/src/ethereum_clis/clis/evmone.py b/src/ethereum_clis/clis/evmone.py index 9fc8fe85887..82add116439 100644 --- a/src/ethereum_clis/clis/evmone.py +++ b/src/ethereum_clis/clis/evmone.py @@ -40,6 +40,7 @@ class EvmOneTransitionTool(TransitionTool): cached_version: Optional[str] = None trace: bool supports_opcode_count: ClassVar[bool] = True + supports_blob_params: ClassVar[bool] = True def __init__( self, @@ -329,6 +330,7 @@ class EvmoneExceptionMapper(ExceptionMapper): ), TransactionException.NONCE_MISMATCH_TOO_LOW: "nonce too low", TransactionException.NONCE_MISMATCH_TOO_HIGH: "nonce too high", + TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: "max gas limit exceeded", # TODO EVMONE needs to differentiate when the section is missing in the # header or body EOFException.MISSING_STOP_OPCODE: "err: no_terminating_instruction", diff --git a/src/ethereum_clis/transition_tool.py b/src/ethereum_clis/transition_tool.py index 1f72824306f..3ace151b6ac 100644 --- a/src/ethereum_clis/transition_tool.py +++ b/src/ethereum_clis/transition_tool.py @@ -19,6 +19,7 @@ from requests_unixsocket import Session # type: ignore from ethereum_test_base_types import BlobSchedule +from ethereum_test_base_types.composite_types import ForkBlobSchedule from ethereum_test_exceptions import ExceptionMapper from ethereum_test_forks import Fork from ethereum_test_forks.helpers import get_development_forks, get_forks @@ -75,6 +76,7 @@ class TransitionTool(EthereumCLI): supports_opcode_count: ClassVar[bool] = False supports_xdist: ClassVar[bool] = True + supports_blob_params: ClassVar[bool] = False @abstractmethod def __init__( @@ -175,6 +177,36 @@ def fork_name(self) -> str: timestamp=self.env.timestamp, ) + @property + def fork_name_if_supports_blob_params(self) -> str: + """Return the fork name.""" + fork = self.fork.fork_at( + block_number=self.env.number, + timestamp=self.env.timestamp, + ) + + # For tools that support blob_params, return base fork for BPO + # forks. + if fork.bpo_fork(): + return fork.non_bpo_ancestor().transition_tool_name() + else: + return self.fork.transition_tool_name( + block_number=self.env.number, + timestamp=self.env.timestamp, + ) + + @property + def blob_params(self) -> ForkBlobSchedule | None: + """Return the blob parameters for the current fork.""" + if self.blob_schedule: + fork_name = self.fork.fork_at( + block_number=self.env.number, timestamp=self.env.timestamp + ).name() + # Only return blob params if this fork has them + if fork_name in self.blob_schedule.root: + return self.blob_schedule[fork_name] + return None + def __post_init__(self) -> None: """Modify the reward if the environment number is 0.""" if self.env.number == 0: @@ -186,6 +218,7 @@ def to_input(self) -> TransitionToolInput: alloc=self.alloc, txs=self.txs, env=self.env, + blob_params=self.blob_params, ) def get_request_data(self) -> TransitionToolRequest: @@ -195,7 +228,6 @@ def get_request_data(self) -> TransitionToolRequest: fork=self.fork_name, chain_id=self.chain_id, reward=self.reward, - blob_schedule=self.blob_schedule, ), input=self.to_input(), ) @@ -231,7 +263,9 @@ def _evaluate_filesystem( args = [ str(self.binary), "--state.fork", - t8n_data.fork_name, + t8n_data.fork_name_if_supports_blob_params + if self.supports_blob_params + else t8n_data.fork_name, "--input.alloc", input_paths["alloc"], "--input.env", @@ -258,6 +292,13 @@ def _evaluate_filesystem( "opcodes.json", ] ) + if self.supports_blob_params and input_paths.get("blobParams"): + args.extend( + [ + "--input.blobParams", + input_paths["blobParams"], + ] + ) if self.trace: args.append("--trace") @@ -419,6 +460,7 @@ def _evaluate_server( tx.model_dump(mode="json", **model_dump_config) for tx in request_data.input.txs ], + "input/blob_params.json": request_data.input.blob_params, "request_info.txt": request_info, }, ) diff --git a/src/ethereum_test_forks/base_fork.py b/src/ethereum_test_forks/base_fork.py index a278682c25e..7ef11b89f5e 100644 --- a/src/ethereum_test_forks/base_fork.py +++ b/src/ethereum_test_forks/base_fork.py @@ -828,6 +828,17 @@ def parent(cls) -> Type["BaseFork"] | None: return None return base_class + @classmethod + def non_bpo_ancestor(cls) -> Type["BaseFork"]: + """Return the nearest non-BPO ancestor fork.""" + ancestor = cls + while ancestor.bpo_fork(): + parent = ancestor.parent() + if parent is None: + break + ancestor = parent + return ancestor + @classmethod def children(cls) -> Set[Type["BaseFork"]]: """Return the children forks."""