Skip to content

Commit 247c312

Browse files
winsvegamarioevz
andauthored
feat(exceptions,specs): class to verify exception strings (#795)
* feat(exception mapper): class to verify exception strings * add GethExceptionMapper * refactor exception mapper parse expected exception lists * integrate other t8n's exception maps * implement None ins exception_to_message * fix rebase * fix tox * add exception classes, add exception verification into state tests * fix(specs): tests --------- Co-authored-by: Mario Vega <[email protected]>
1 parent e317fd0 commit 247c312

20 files changed

+1163
-161
lines changed

src/ethereum_clis/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from .clis.besu import BesuTransitionTool
66
from .clis.ethereumjs import EthereumJSTransitionTool
7-
from .clis.evmone import EvmOneTransitionTool
7+
from .clis.evmone import EvmoneExceptionMapper, EvmOneTransitionTool
88
from .clis.execution_specs import ExecutionSpecsTransitionTool
99
from .clis.geth import GethTransitionTool
1010
from .clis.nimbus import NimbusTransitionTool
@@ -20,6 +20,7 @@
2020
"EvmOneTransitionTool",
2121
"ExecutionSpecsTransitionTool",
2222
"GethTransitionTool",
23+
"EvmoneExceptionMapper",
2324
"NimbusTransitionTool",
2425
"Result",
2526
"TransitionTool",

src/ethereum_clis/clis/besu.py

+141-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414

1515
import requests
1616

17+
from ethereum_test_exceptions import (
18+
EOFException,
19+
ExceptionMapper,
20+
ExceptionMessage,
21+
TransactionException,
22+
)
1723
from ethereum_test_forks import Fork
1824
from ethereum_test_types import Alloc, Environment, Transaction
1925

@@ -41,7 +47,7 @@ def __init__(
4147
binary: Optional[Path] = None,
4248
trace: bool = False,
4349
):
44-
super().__init__(binary=binary, trace=trace)
50+
super().__init__(exception_mapper=BesuExceptionMapper(), binary=binary, trace=trace)
4551
args = [str(self.binary), "t8n", "--help"]
4652
try:
4753
result = subprocess.run(args, capture_output=True, text=True)
@@ -201,3 +207,137 @@ def is_fork_supported(self, fork: Fork) -> bool:
201207
Returns True if the fork is supported by the tool
202208
"""
203209
return fork.transition_tool_name() in self.help_string
210+
211+
212+
class BesuExceptionMapper(ExceptionMapper):
213+
"""
214+
Translate between EEST exceptions and error strings returned by nimbus.
215+
"""
216+
217+
@property
218+
def _mapping_data(self):
219+
return [
220+
ExceptionMessage(
221+
TransactionException.TYPE_4_TX_CONTRACT_CREATION,
222+
"set code transaction must not be a create transaction",
223+
),
224+
ExceptionMessage(
225+
TransactionException.INSUFFICIENT_ACCOUNT_FUNDS,
226+
"exceeds transaction sender account balance",
227+
),
228+
ExceptionMessage(
229+
TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED,
230+
"would exceed block maximum",
231+
),
232+
ExceptionMessage(
233+
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
234+
"max fee per blob gas less than block blob gas fee",
235+
),
236+
ExceptionMessage(
237+
TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS,
238+
"gasPrice is less than the current BaseFee",
239+
),
240+
ExceptionMessage(
241+
TransactionException.TYPE_3_TX_PRE_FORK,
242+
"Transaction type BLOB is invalid, accepted transaction types are [EIP1559, ACCESS_LIST, FRONTIER]", # noqa: E501
243+
),
244+
ExceptionMessage(
245+
TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH,
246+
"Only supported hash version is 0x01, sha256 hash.",
247+
),
248+
# This message is the same as TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED
249+
ExceptionMessage(
250+
TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED,
251+
"exceed block maximum",
252+
),
253+
ExceptionMessage(
254+
TransactionException.TYPE_3_TX_ZERO_BLOBS,
255+
"Blob transaction must have at least one versioned hash",
256+
),
257+
ExceptionMessage(
258+
TransactionException.INTRINSIC_GAS_TOO_LOW,
259+
"intrinsic gas too low",
260+
),
261+
ExceptionMessage(
262+
TransactionException.INITCODE_SIZE_EXCEEDED,
263+
"max initcode size exceeded",
264+
),
265+
# TODO EVMONE needs to differentiate when the section is missing in the header or body
266+
ExceptionMessage(EOFException.MISSING_STOP_OPCODE, "err: no_terminating_instruction"),
267+
ExceptionMessage(EOFException.MISSING_CODE_HEADER, "err: code_section_missing"),
268+
ExceptionMessage(EOFException.MISSING_TYPE_HEADER, "err: type_section_missing"),
269+
# TODO EVMONE these exceptions are too similar, this leeds to ambiguity
270+
ExceptionMessage(EOFException.MISSING_TERMINATOR, "err: header_terminator_missing"),
271+
ExceptionMessage(
272+
EOFException.MISSING_HEADERS_TERMINATOR, "err: section_headers_not_terminated"
273+
),
274+
ExceptionMessage(EOFException.INVALID_VERSION, "err: eof_version_unknown"),
275+
ExceptionMessage(
276+
EOFException.INVALID_NON_RETURNING_FLAG, "err: invalid_non_returning_flag"
277+
),
278+
ExceptionMessage(EOFException.INVALID_MAGIC, "err: invalid_prefix"),
279+
ExceptionMessage(
280+
EOFException.INVALID_FIRST_SECTION_TYPE, "err: invalid_first_section_type"
281+
),
282+
ExceptionMessage(
283+
EOFException.INVALID_SECTION_BODIES_SIZE, "err: invalid_section_bodies_size"
284+
),
285+
ExceptionMessage(
286+
EOFException.INVALID_TYPE_SECTION_SIZE, "err: invalid_type_section_size"
287+
),
288+
ExceptionMessage(EOFException.INCOMPLETE_SECTION_SIZE, "err: incomplete_section_size"),
289+
ExceptionMessage(
290+
EOFException.INCOMPLETE_SECTION_NUMBER, "err: incomplete_section_number"
291+
),
292+
ExceptionMessage(EOFException.TOO_MANY_CODE_SECTIONS, "err: too_many_code_sections"),
293+
ExceptionMessage(EOFException.ZERO_SECTION_SIZE, "err: zero_section_size"),
294+
ExceptionMessage(EOFException.MISSING_DATA_SECTION, "err: data_section_missing"),
295+
ExceptionMessage(EOFException.UNDEFINED_INSTRUCTION, "err: undefined_instruction"),
296+
ExceptionMessage(
297+
EOFException.INPUTS_OUTPUTS_NUM_ABOVE_LIMIT, "err: inputs_outputs_num_above_limit"
298+
),
299+
ExceptionMessage(
300+
EOFException.UNREACHABLE_INSTRUCTIONS, "err: unreachable_instructions"
301+
),
302+
ExceptionMessage(
303+
EOFException.INVALID_RJUMP_DESTINATION, "err: invalid_rjump_destination"
304+
),
305+
ExceptionMessage(
306+
EOFException.UNREACHABLE_CODE_SECTIONS, "err: unreachable_code_sections"
307+
),
308+
ExceptionMessage(EOFException.STACK_UNDERFLOW, "err: stack_underflow"),
309+
ExceptionMessage(
310+
EOFException.MAX_STACK_HEIGHT_ABOVE_LIMIT, "err: max_stack_height_above_limit"
311+
),
312+
ExceptionMessage(
313+
EOFException.STACK_HIGHER_THAN_OUTPUTS, "err: stack_higher_than_outputs_required"
314+
),
315+
ExceptionMessage(
316+
EOFException.JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS,
317+
"err: jumpf_destination_incompatible_outputs",
318+
),
319+
ExceptionMessage(
320+
EOFException.INVALID_MAX_STACK_HEIGHT, "err: invalid_max_stack_height"
321+
),
322+
ExceptionMessage(EOFException.INVALID_DATALOADN_INDEX, "err: invalid_dataloadn_index"),
323+
ExceptionMessage(EOFException.TRUNCATED_INSTRUCTION, "err: truncated_instruction"),
324+
ExceptionMessage(
325+
EOFException.TOPLEVEL_CONTAINER_TRUNCATED, "err: toplevel_container_truncated"
326+
),
327+
ExceptionMessage(EOFException.ORPHAN_SUBCONTAINER, "err: unreferenced_subcontainer"),
328+
ExceptionMessage(
329+
EOFException.CONTAINER_SIZE_ABOVE_LIMIT, "err: container_size_above_limit"
330+
),
331+
ExceptionMessage(
332+
EOFException.INVALID_CONTAINER_SECTION_INDEX,
333+
"err: invalid_container_section_index",
334+
),
335+
ExceptionMessage(
336+
EOFException.INCOMPATIBLE_CONTAINER_KIND, "err: incompatible_container_kind"
337+
),
338+
ExceptionMessage(EOFException.STACK_HEIGHT_MISMATCH, "err: stack_height_mismatch"),
339+
ExceptionMessage(EOFException.TOO_MANY_CONTAINERS, "err: too_many_container_sections"),
340+
ExceptionMessage(
341+
EOFException.INVALID_CODE_SECTION_INDEX, "err: invalid_code_section_index"
342+
),
343+
]

src/ethereum_clis/clis/ethereumjs.py

+141-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
from re import compile
77
from typing import Optional
88

9+
from ethereum_test_exceptions import (
10+
EOFException,
11+
ExceptionMapper,
12+
ExceptionMessage,
13+
TransactionException,
14+
)
915
from ethereum_test_forks import Fork
1016

1117
from ..transition_tool import TransitionTool
@@ -31,11 +37,145 @@ def __init__(
3137
binary: Optional[Path] = None,
3238
trace: bool = False,
3339
):
34-
super().__init__(binary=binary, trace=trace)
40+
super().__init__(exception_mapper=EthereumJSExceptionMapper(), binary=binary, trace=trace)
3541

3642
def is_fork_supported(self, fork: Fork) -> bool:
3743
"""
3844
Returns True if the fork is supported by the tool.
3945
Currently, EthereumJS-t8n provides no way to determine supported forks.
4046
"""
4147
return True
48+
49+
50+
class EthereumJSExceptionMapper(ExceptionMapper):
51+
"""
52+
Translate between EEST exceptions and error strings returned by ethereum-js.
53+
"""
54+
55+
@property
56+
def _mapping_data(self):
57+
return [
58+
ExceptionMessage(
59+
TransactionException.TYPE_4_TX_CONTRACT_CREATION,
60+
"set code transaction must not be a create transaction",
61+
),
62+
ExceptionMessage(
63+
TransactionException.INSUFFICIENT_ACCOUNT_FUNDS,
64+
"insufficient funds for gas * price + value",
65+
),
66+
ExceptionMessage(
67+
TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED,
68+
"would exceed maximum allowance",
69+
),
70+
ExceptionMessage(
71+
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
72+
"max fee per blob gas less than block blob gas fee",
73+
),
74+
ExceptionMessage(
75+
TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS,
76+
"max fee per gas less than block base fee",
77+
),
78+
ExceptionMessage(
79+
TransactionException.TYPE_3_TX_PRE_FORK,
80+
"blob tx used but field env.ExcessBlobGas missing",
81+
),
82+
ExceptionMessage(
83+
TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH,
84+
"has invalid hash version",
85+
),
86+
# This message is the same as TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED
87+
ExceptionMessage(
88+
TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED,
89+
"exceed maximum allowance",
90+
),
91+
ExceptionMessage(
92+
TransactionException.TYPE_3_TX_ZERO_BLOBS,
93+
"blob transaction missing blob hashes",
94+
),
95+
ExceptionMessage(
96+
TransactionException.INTRINSIC_GAS_TOO_LOW,
97+
"is lower than the minimum gas limit of",
98+
),
99+
ExceptionMessage(
100+
TransactionException.INITCODE_SIZE_EXCEEDED,
101+
"max initcode size exceeded",
102+
),
103+
# TODO EVMONE needs to differentiate when the section is missing in the header or body
104+
ExceptionMessage(EOFException.MISSING_STOP_OPCODE, "err: no_terminating_instruction"),
105+
ExceptionMessage(EOFException.MISSING_CODE_HEADER, "err: code_section_missing"),
106+
ExceptionMessage(EOFException.MISSING_TYPE_HEADER, "err: type_section_missing"),
107+
# TODO EVMONE these exceptions are too similar, this leeds to ambiguity
108+
ExceptionMessage(EOFException.MISSING_TERMINATOR, "err: header_terminator_missing"),
109+
ExceptionMessage(
110+
EOFException.MISSING_HEADERS_TERMINATOR, "err: section_headers_not_terminated"
111+
),
112+
ExceptionMessage(EOFException.INVALID_VERSION, "err: eof_version_unknown"),
113+
ExceptionMessage(
114+
EOFException.INVALID_NON_RETURNING_FLAG, "err: invalid_non_returning_flag"
115+
),
116+
ExceptionMessage(EOFException.INVALID_MAGIC, "err: invalid_prefix"),
117+
ExceptionMessage(
118+
EOFException.INVALID_FIRST_SECTION_TYPE, "err: invalid_first_section_type"
119+
),
120+
ExceptionMessage(
121+
EOFException.INVALID_SECTION_BODIES_SIZE, "err: invalid_section_bodies_size"
122+
),
123+
ExceptionMessage(
124+
EOFException.INVALID_TYPE_SECTION_SIZE, "err: invalid_type_section_size"
125+
),
126+
ExceptionMessage(EOFException.INCOMPLETE_SECTION_SIZE, "err: incomplete_section_size"),
127+
ExceptionMessage(
128+
EOFException.INCOMPLETE_SECTION_NUMBER, "err: incomplete_section_number"
129+
),
130+
ExceptionMessage(EOFException.TOO_MANY_CODE_SECTIONS, "err: too_many_code_sections"),
131+
ExceptionMessage(EOFException.ZERO_SECTION_SIZE, "err: zero_section_size"),
132+
ExceptionMessage(EOFException.MISSING_DATA_SECTION, "err: data_section_missing"),
133+
ExceptionMessage(EOFException.UNDEFINED_INSTRUCTION, "err: undefined_instruction"),
134+
ExceptionMessage(
135+
EOFException.INPUTS_OUTPUTS_NUM_ABOVE_LIMIT, "err: inputs_outputs_num_above_limit"
136+
),
137+
ExceptionMessage(
138+
EOFException.UNREACHABLE_INSTRUCTIONS, "err: unreachable_instructions"
139+
),
140+
ExceptionMessage(
141+
EOFException.INVALID_RJUMP_DESTINATION, "err: invalid_rjump_destination"
142+
),
143+
ExceptionMessage(
144+
EOFException.UNREACHABLE_CODE_SECTIONS, "err: unreachable_code_sections"
145+
),
146+
ExceptionMessage(EOFException.STACK_UNDERFLOW, "err: stack_underflow"),
147+
ExceptionMessage(
148+
EOFException.MAX_STACK_HEIGHT_ABOVE_LIMIT, "err: max_stack_height_above_limit"
149+
),
150+
ExceptionMessage(
151+
EOFException.STACK_HIGHER_THAN_OUTPUTS, "err: stack_higher_than_outputs_required"
152+
),
153+
ExceptionMessage(
154+
EOFException.JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS,
155+
"err: jumpf_destination_incompatible_outputs",
156+
),
157+
ExceptionMessage(
158+
EOFException.INVALID_MAX_STACK_HEIGHT, "err: invalid_max_stack_height"
159+
),
160+
ExceptionMessage(EOFException.INVALID_DATALOADN_INDEX, "err: invalid_dataloadn_index"),
161+
ExceptionMessage(EOFException.TRUNCATED_INSTRUCTION, "err: truncated_instruction"),
162+
ExceptionMessage(
163+
EOFException.TOPLEVEL_CONTAINER_TRUNCATED, "err: toplevel_container_truncated"
164+
),
165+
ExceptionMessage(EOFException.ORPHAN_SUBCONTAINER, "err: unreferenced_subcontainer"),
166+
ExceptionMessage(
167+
EOFException.CONTAINER_SIZE_ABOVE_LIMIT, "err: container_size_above_limit"
168+
),
169+
ExceptionMessage(
170+
EOFException.INVALID_CONTAINER_SECTION_INDEX,
171+
"err: invalid_container_section_index",
172+
),
173+
ExceptionMessage(
174+
EOFException.INCOMPATIBLE_CONTAINER_KIND, "err: incompatible_container_kind"
175+
),
176+
ExceptionMessage(EOFException.STACK_HEIGHT_MISMATCH, "err: stack_height_mismatch"),
177+
ExceptionMessage(EOFException.TOO_MANY_CONTAINERS, "err: too_many_container_sections"),
178+
ExceptionMessage(
179+
EOFException.INVALID_CODE_SECTION_INDEX, "err: invalid_code_section_index"
180+
),
181+
]

0 commit comments

Comments
 (0)