-
Notifications
You must be signed in to change notification settings - Fork 330
utilize pydantic models from eest on t8n #1359
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
base: forks/osaka
Are you sure you want to change the base?
Changes from all commits
82b7956
1537b01
1f51eaf
7292acd
bb826c6
dc31f96
e1dc6a3
5a17bd9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,20 +7,24 @@ | |
import json | ||
import os | ||
from functools import partial | ||
from typing import Any, TextIO | ||
from typing import Any, Optional, TextIO, Union | ||
|
||
from ethereum_rlp import rlp | ||
from ethereum_types.numeric import U64, U256, Uint | ||
|
||
from ethereum import trace | ||
from ethereum.exceptions import EthereumException, InvalidBlock | ||
from ethereum_clis.types import TransitionToolRequest | ||
from ethereum_spec_tools.forks import Hardfork | ||
from ethereum_clis.types import TransitionToolOutput | ||
from ethereum_clis.clis.execution_specs import ExecutionSpecsExceptionMapper | ||
|
||
from ..loaders.fixture_loader import Load | ||
from ..loaders.fork_loader import ForkLoad | ||
from ..utils import ( | ||
FatalException, | ||
get_module_name, | ||
get_module_name_json_input, | ||
get_stream_logger, | ||
parse_hex_or_int, | ||
) | ||
|
@@ -80,13 +84,59 @@ class T8N(Load): | |
"""The class that carries out the transition""" | ||
|
||
def __init__( | ||
self, options: Any, out_file: TextIO, in_file: TextIO | ||
self, | ||
options: Any, | ||
in_file: Union[TransitionToolRequest, TextIO], | ||
out_file: Optional[TextIO] = None | ||
) -> None: | ||
self.out_file = out_file | ||
self.in_file = in_file | ||
self.options = options | ||
self.forks = Hardfork.discover() | ||
|
||
if isinstance(in_file, TransitionToolRequest): | ||
self._init_from_pydantic(options, in_file) | ||
else: | ||
if out_file is None: | ||
raise ValueError("out_file is required for JSON file input") | ||
self._init_from_json(options, in_file, out_file) | ||
|
||
def _init_from_pydantic(self, options: Any, in_file: TransitionToolRequest) -> None: | ||
fork_module, self.fork_block = get_module_name( | ||
self.forks, options, in_file.input.env | ||
) | ||
self.fork = ForkLoad(fork_module) | ||
self.exception_mapper = ExecutionSpecsExceptionMapper() | ||
|
||
if options.trace: | ||
trace_memory = getattr(options, "trace.memory", False) | ||
trace_stack = not getattr(options, "trace.nostack", False) | ||
trace_return_data = getattr(options, "trace.returndata") | ||
trace.set_evm_trace( | ||
partial( | ||
evm_trace, | ||
trace_memory=trace_memory, | ||
trace_stack=trace_stack, | ||
trace_return_data=trace_return_data, | ||
output_basedir=options.output_basedir, | ||
) | ||
) | ||
self.logger = get_stream_logger("T8N") | ||
|
||
super().__init__( | ||
options.state_fork, | ||
fork_module, | ||
) | ||
|
||
self.chain_id = parse_hex_or_int(options.state_chainid, U64) | ||
self.alloc = Alloc(self, in_file.input.alloc) | ||
self.env = Env(self, in_file.input.env) | ||
self.txs = Txs(self, in_file.input.txs) | ||
self.result = Result( | ||
self.env.block_difficulty, self.env.base_fee_per_gas | ||
) | ||
|
||
def _init_from_json(self, options: Any, in_file: TextIO, out_file: TextIO) -> None: | ||
if "stdin" in ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would we still be able to consume json files if needed? We will need to continue supporting that use case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes! with this commit dc31f96 I added the dual input option where we preserve the older json input route |
||
options.input_env, | ||
options.input_alloc, | ||
|
@@ -96,7 +146,7 @@ def __init__( | |
else: | ||
stdin = None | ||
|
||
fork_module, self.fork_block = get_module_name( | ||
fork_module, self.fork_block = get_module_name_json_input( | ||
self.forks, self.options, stdin | ||
) | ||
self.fork = ForkLoad(fork_module) | ||
|
@@ -311,7 +361,21 @@ def run(self) -> int: | |
|
||
json_state = self.alloc.to_json() | ||
json_result = self.result.to_json() | ||
if isinstance(self.in_file, TransitionToolRequest): | ||
json_output = {} | ||
|
||
txs_rlp = "0x" + rlp.encode(self.txs.all_txs).hex() | ||
json_output["body"] = txs_rlp | ||
json_output["alloc"] = json_state | ||
json_output["result"] = json_result | ||
output: TransitionToolOutput = TransitionToolOutput.model_validate( | ||
json_output, context={"exception_mapper": self.exception_mapper} | ||
) | ||
return output | ||
else: | ||
return self._write_json_output(json_state, json_result) | ||
|
||
def _write_json_output(self, json_state: Any, json_result: Any) -> int: | ||
json_output = {} | ||
|
||
if self.options.output_body == "stdout": | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should re-use the Alloc, Env and Txs types defined by EEST. And if the json inputs are provided, we could just serialize/de-serialize using pydantic. That way, we can get of a lot of redundant code in
env.py
andt8n_types.py
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right! :) The first thing i tried was to re-use the types (pydantic models) from EEST (to not have these intermediary classes at all) But seems like our execution-spec code isn't directly able to work with those (without some translations/conversions)? To be able to utilize the EEST types directly would definitely be the most efficient - any suggestions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would something like this work?
You might have to transform the EEST
Alloc
to the relevant fork'sState
dataclass but I think this is still much cleaner than what we currently have.