Skip to content

Commit dc31f96

Browse files
committed
add dual input option
1 parent bb826c6 commit dc31f96

File tree

5 files changed

+544
-48
lines changed

5 files changed

+544
-48
lines changed

src/ethereum_spec_tools/evm_tools/t8n/__init__.py

Lines changed: 116 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
import argparse
66
import fnmatch
7+
import json
78
import os
89
from functools import partial
9-
from typing import Any, TextIO
10+
from typing import Any, Optional, TextIO, Union
1011

1112
from ethereum_rlp import rlp
1213
from ethereum_types.numeric import U64, U256, Uint
@@ -23,6 +24,7 @@
2324
from ..utils import (
2425
FatalException,
2526
get_module_name,
27+
get_module_name_json_input,
2628
get_stream_logger,
2729
parse_hex_or_int,
2830
)
@@ -82,19 +84,73 @@ class T8N(Load):
8284
"""The class that carries out the transition"""
8385

8486
def __init__(
85-
self, options: Any, out_file: TextIO, in_file: TransitionToolRequest
87+
self,
88+
options: Any,
89+
in_file: Union[TransitionToolRequest, TextIO],
90+
out_file: Optional[TextIO] = None
8691
) -> None:
8792
self.out_file = out_file
8893
self.in_file = in_file
8994
self.options = options
9095
self.forks = Hardfork.discover()
9196

97+
if isinstance(in_file, TransitionToolRequest):
98+
self._init_from_pydantic(options, in_file)
99+
else:
100+
if out_file is None:
101+
raise ValueError("out_file is required for JSON file input")
102+
self._init_from_json(options, in_file, out_file)
103+
104+
def _init_from_pydantic(self, options: Any, in_file: TransitionToolRequest) -> None:
92105
fork_module, self.fork_block = get_module_name(
93-
self.forks, self.options, in_file.input.env
106+
self.forks, options, in_file.input.env
94107
)
95108
self.fork = ForkLoad(fork_module)
96109
self.exception_mapper = ExecutionSpecsExceptionMapper()
97110

111+
if options.trace:
112+
trace_memory = getattr(options, "trace.memory", False)
113+
trace_stack = not getattr(options, "trace.nostack", False)
114+
trace_return_data = getattr(options, "trace.returndata")
115+
trace.set_evm_trace(
116+
partial(
117+
evm_trace,
118+
trace_memory=trace_memory,
119+
trace_stack=trace_stack,
120+
trace_return_data=trace_return_data,
121+
output_basedir=options.output_basedir,
122+
)
123+
)
124+
self.logger = get_stream_logger("T8N")
125+
126+
super().__init__(
127+
options.state_fork,
128+
fork_module,
129+
)
130+
131+
self.chain_id = parse_hex_or_int(options.state_chainid, U64)
132+
self.alloc = Alloc(self, in_file.input.alloc)
133+
self.env = Env(self, in_file.input.env)
134+
self.txs = Txs(self, in_file.input.txs)
135+
self.result = Result(
136+
self.env.block_difficulty, self.env.base_fee_per_gas
137+
)
138+
139+
def _init_from_json(self, options: Any, in_file: TextIO, out_file: TextIO) -> None:
140+
if "stdin" in (
141+
options.input_env,
142+
options.input_alloc,
143+
options.input_txs,
144+
):
145+
stdin = json.load(in_file)
146+
else:
147+
stdin = None
148+
149+
fork_module, self.fork_block = get_module_name_json_input(
150+
self.forks, self.options, stdin
151+
)
152+
self.fork = ForkLoad(fork_module)
153+
98154
if self.options.trace:
99155
trace_memory = getattr(self.options, "trace.memory", False)
100156
trace_stack = not getattr(self.options, "trace.nostack", False)
@@ -116,9 +172,9 @@ def __init__(
116172
)
117173

118174
self.chain_id = parse_hex_or_int(self.options.state_chainid, U64)
119-
self.alloc = Alloc(self, in_file.input.alloc)
120-
self.env = Env(self, in_file.input.env)
121-
self.txs = Txs(self, in_file.input.txs)
175+
self.alloc = Alloc(self, stdin)
176+
self.env = Env(self, stdin)
177+
self.txs = Txs(self, stdin)
122178
self.result = Result(
123179
self.env.block_difficulty, self.env.base_fee_per_gas
124180
)
@@ -305,13 +361,59 @@ def run(self) -> int:
305361

306362
json_state = self.alloc.to_json()
307363
json_result = self.result.to_json()
364+
if isinstance(self.in_file, TransitionToolRequest):
365+
json_output = {}
366+
367+
txs_rlp = "0x" + rlp.encode(self.txs.all_txs).hex()
368+
json_output["body"] = txs_rlp
369+
json_output["alloc"] = json_state
370+
json_output["result"] = json_result
371+
output: TransitionToolOutput = TransitionToolOutput.model_validate(
372+
json_output, context={"exception_mapper": self.exception_mapper}
373+
)
374+
return output
375+
else:
376+
return self._write_json_output(json_state, json_result)
377+
378+
def _write_json_output(self, json_state: Any, json_result: Any) -> int:
308379
json_output = {}
309380

310-
txs_rlp = "0x" + rlp.encode(self.txs.all_txs).hex()
311-
json_output["body"] = txs_rlp
312-
json_output["alloc"] = json_state
313-
json_output["result"] = json_result
314-
output: TransitionToolOutput = TransitionToolOutput.model_validate(
315-
json_output, context={"exception_mapper": self.exception_mapper}
316-
)
317-
return output
381+
if self.options.output_body == "stdout":
382+
txs_rlp = "0x" + rlp.encode(self.txs.all_txs).hex()
383+
json_output["body"] = txs_rlp
384+
elif self.options.output_body is not None:
385+
txs_rlp_path = os.path.join(
386+
self.options.output_basedir,
387+
self.options.output_body,
388+
)
389+
txs_rlp = "0x" + rlp.encode(self.txs.all_txs).hex()
390+
with open(txs_rlp_path, "w") as f:
391+
json.dump(txs_rlp, f)
392+
self.logger.info(f"Wrote transaction rlp to {txs_rlp_path}")
393+
394+
if self.options.output_alloc == "stdout":
395+
json_output["alloc"] = json_state
396+
else:
397+
alloc_output_path = os.path.join(
398+
self.options.output_basedir,
399+
self.options.output_alloc,
400+
)
401+
with open(alloc_output_path, "w") as f:
402+
json.dump(json_state, f, indent=4)
403+
self.logger.info(f"Wrote alloc to {alloc_output_path}")
404+
405+
if self.options.output_result == "stdout":
406+
json_output["result"] = json_result
407+
else:
408+
result_output_path = os.path.join(
409+
self.options.output_basedir,
410+
self.options.output_result,
411+
)
412+
with open(result_output_path, "w") as f:
413+
json.dump(json_result, f, indent=4)
414+
self.logger.info(f"Wrote result to {result_output_path}")
415+
416+
if json_output:
417+
json.dump(json_output, self.out_file, indent=4)
418+
419+
return 0

0 commit comments

Comments
 (0)