Skip to content
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

feat(exceptions,specs): class to verify exception strings #795

Merged
merged 9 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/ethereum_clis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from .clis.besu import BesuTransitionTool
from .clis.ethereumjs import EthereumJSTransitionTool
from .clis.evmone import EvmOneTransitionTool
from .clis.evmone import EvmoneExceptionMapper, EvmOneTransitionTool
from .clis.execution_specs import ExecutionSpecsTransitionTool
from .clis.geth import GethTransitionTool
from .clis.nimbus import NimbusTransitionTool
Expand All @@ -20,6 +20,7 @@
"EvmOneTransitionTool",
"ExecutionSpecsTransitionTool",
"GethTransitionTool",
"EvmoneExceptionMapper",
"NimbusTransitionTool",
"Result",
"TransitionTool",
Expand Down
142 changes: 141 additions & 1 deletion src/ethereum_clis/clis/besu.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

import requests

from ethereum_test_exceptions import (
EOFException,
ExceptionMapper,
ExceptionMessage,
TransactionException,
)
from ethereum_test_forks import Fork
from ethereum_test_types import Alloc, Environment, Transaction

Expand Down Expand Up @@ -41,7 +47,7 @@ def __init__(
binary: Optional[Path] = None,
trace: bool = False,
):
super().__init__(binary=binary, trace=trace)
super().__init__(exception_mapper=BesuExceptionMapper(), binary=binary, trace=trace)
args = [str(self.binary), "t8n", "--help"]
try:
result = subprocess.run(args, capture_output=True, text=True)
Expand Down Expand Up @@ -201,3 +207,137 @@ def is_fork_supported(self, fork: Fork) -> bool:
Returns True if the fork is supported by the tool
"""
return fork.transition_tool_name() in self.help_string


class BesuExceptionMapper(ExceptionMapper):
"""
Translate between EEST exceptions and error strings returned by nimbus.
"""

@property
def _mapping_data(self):
return [
ExceptionMessage(
TransactionException.TYPE_4_TX_CONTRACT_CREATION,
"set code transaction must not be a create transaction",
),
ExceptionMessage(
TransactionException.INSUFFICIENT_ACCOUNT_FUNDS,
"exceeds transaction sender account balance",
),
ExceptionMessage(
TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED,
"would exceed block maximum",
),
ExceptionMessage(
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
"max fee per blob gas less than block blob gas fee",
),
ExceptionMessage(
TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS,
"gasPrice is less than the current BaseFee",
),
ExceptionMessage(
TransactionException.TYPE_3_TX_PRE_FORK,
"Transaction type BLOB is invalid, accepted transaction types are [EIP1559, ACCESS_LIST, FRONTIER]", # noqa: E501
),
ExceptionMessage(
TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH,
"Only supported hash version is 0x01, sha256 hash.",
),
# This message is the same as TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED
ExceptionMessage(
TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED,
"exceed block maximum",
),
ExceptionMessage(
TransactionException.TYPE_3_TX_ZERO_BLOBS,
"Blob transaction must have at least one versioned hash",
),
ExceptionMessage(
TransactionException.INTRINSIC_GAS_TOO_LOW,
"intrinsic gas too low",
),
ExceptionMessage(
TransactionException.INITCODE_SIZE_EXCEEDED,
"max initcode size exceeded",
),
# TODO EVMONE needs to differentiate when the section is missing in the header or body
ExceptionMessage(EOFException.MISSING_STOP_OPCODE, "err: no_terminating_instruction"),
ExceptionMessage(EOFException.MISSING_CODE_HEADER, "err: code_section_missing"),
ExceptionMessage(EOFException.MISSING_TYPE_HEADER, "err: type_section_missing"),
# TODO EVMONE these exceptions are too similar, this leeds to ambiguity
ExceptionMessage(EOFException.MISSING_TERMINATOR, "err: header_terminator_missing"),
ExceptionMessage(
EOFException.MISSING_HEADERS_TERMINATOR, "err: section_headers_not_terminated"
),
ExceptionMessage(EOFException.INVALID_VERSION, "err: eof_version_unknown"),
ExceptionMessage(
EOFException.INVALID_NON_RETURNING_FLAG, "err: invalid_non_returning_flag"
),
ExceptionMessage(EOFException.INVALID_MAGIC, "err: invalid_prefix"),
ExceptionMessage(
EOFException.INVALID_FIRST_SECTION_TYPE, "err: invalid_first_section_type"
),
ExceptionMessage(
EOFException.INVALID_SECTION_BODIES_SIZE, "err: invalid_section_bodies_size"
),
ExceptionMessage(
EOFException.INVALID_TYPE_SECTION_SIZE, "err: invalid_type_section_size"
),
ExceptionMessage(EOFException.INCOMPLETE_SECTION_SIZE, "err: incomplete_section_size"),
ExceptionMessage(
EOFException.INCOMPLETE_SECTION_NUMBER, "err: incomplete_section_number"
),
ExceptionMessage(EOFException.TOO_MANY_CODE_SECTIONS, "err: too_many_code_sections"),
ExceptionMessage(EOFException.ZERO_SECTION_SIZE, "err: zero_section_size"),
ExceptionMessage(EOFException.MISSING_DATA_SECTION, "err: data_section_missing"),
ExceptionMessage(EOFException.UNDEFINED_INSTRUCTION, "err: undefined_instruction"),
ExceptionMessage(
EOFException.INPUTS_OUTPUTS_NUM_ABOVE_LIMIT, "err: inputs_outputs_num_above_limit"
),
ExceptionMessage(
EOFException.UNREACHABLE_INSTRUCTIONS, "err: unreachable_instructions"
),
ExceptionMessage(
EOFException.INVALID_RJUMP_DESTINATION, "err: invalid_rjump_destination"
),
ExceptionMessage(
EOFException.UNREACHABLE_CODE_SECTIONS, "err: unreachable_code_sections"
),
ExceptionMessage(EOFException.STACK_UNDERFLOW, "err: stack_underflow"),
ExceptionMessage(
EOFException.MAX_STACK_HEIGHT_ABOVE_LIMIT, "err: max_stack_height_above_limit"
),
ExceptionMessage(
EOFException.STACK_HIGHER_THAN_OUTPUTS, "err: stack_higher_than_outputs_required"
),
ExceptionMessage(
EOFException.JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS,
"err: jumpf_destination_incompatible_outputs",
),
ExceptionMessage(
EOFException.INVALID_MAX_STACK_HEIGHT, "err: invalid_max_stack_height"
),
ExceptionMessage(EOFException.INVALID_DATALOADN_INDEX, "err: invalid_dataloadn_index"),
ExceptionMessage(EOFException.TRUNCATED_INSTRUCTION, "err: truncated_instruction"),
ExceptionMessage(
EOFException.TOPLEVEL_CONTAINER_TRUNCATED, "err: toplevel_container_truncated"
),
ExceptionMessage(EOFException.ORPHAN_SUBCONTAINER, "err: unreferenced_subcontainer"),
ExceptionMessage(
EOFException.CONTAINER_SIZE_ABOVE_LIMIT, "err: container_size_above_limit"
),
ExceptionMessage(
EOFException.INVALID_CONTAINER_SECTION_INDEX,
"err: invalid_container_section_index",
),
ExceptionMessage(
EOFException.INCOMPATIBLE_CONTAINER_KIND, "err: incompatible_container_kind"
),
ExceptionMessage(EOFException.STACK_HEIGHT_MISMATCH, "err: stack_height_mismatch"),
ExceptionMessage(EOFException.TOO_MANY_CONTAINERS, "err: too_many_container_sections"),
ExceptionMessage(
EOFException.INVALID_CODE_SECTION_INDEX, "err: invalid_code_section_index"
),
]
142 changes: 141 additions & 1 deletion src/ethereum_clis/clis/ethereumjs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
from re import compile
from typing import Optional

from ethereum_test_exceptions import (
EOFException,
ExceptionMapper,
ExceptionMessage,
TransactionException,
)
from ethereum_test_forks import Fork

from ..transition_tool import TransitionTool
Expand All @@ -31,11 +37,145 @@ def __init__(
binary: Optional[Path] = None,
trace: bool = False,
):
super().__init__(binary=binary, trace=trace)
super().__init__(exception_mapper=EthereumJSExceptionMapper(), binary=binary, trace=trace)

def is_fork_supported(self, fork: Fork) -> bool:
"""
Returns True if the fork is supported by the tool.
Currently, EthereumJS-t8n provides no way to determine supported forks.
"""
return True


class EthereumJSExceptionMapper(ExceptionMapper):
"""
Translate between EEST exceptions and error strings returned by ethereum-js.
"""

@property
def _mapping_data(self):
return [
ExceptionMessage(
TransactionException.TYPE_4_TX_CONTRACT_CREATION,
"set code transaction must not be a create transaction",
),
ExceptionMessage(
TransactionException.INSUFFICIENT_ACCOUNT_FUNDS,
"insufficient funds for gas * price + value",
),
ExceptionMessage(
TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED,
"would exceed maximum allowance",
),
ExceptionMessage(
TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
"max fee per blob gas less than block blob gas fee",
),
ExceptionMessage(
TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS,
"max fee per gas less than block base fee",
),
ExceptionMessage(
TransactionException.TYPE_3_TX_PRE_FORK,
"blob tx used but field env.ExcessBlobGas missing",
),
ExceptionMessage(
TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH,
"has invalid hash version",
),
# This message is the same as TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED
ExceptionMessage(
TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED,
"exceed maximum allowance",
),
ExceptionMessage(
TransactionException.TYPE_3_TX_ZERO_BLOBS,
"blob transaction missing blob hashes",
),
ExceptionMessage(
TransactionException.INTRINSIC_GAS_TOO_LOW,
"is lower than the minimum gas limit of",
),
ExceptionMessage(
TransactionException.INITCODE_SIZE_EXCEEDED,
"max initcode size exceeded",
),
# TODO EVMONE needs to differentiate when the section is missing in the header or body
ExceptionMessage(EOFException.MISSING_STOP_OPCODE, "err: no_terminating_instruction"),
ExceptionMessage(EOFException.MISSING_CODE_HEADER, "err: code_section_missing"),
ExceptionMessage(EOFException.MISSING_TYPE_HEADER, "err: type_section_missing"),
# TODO EVMONE these exceptions are too similar, this leeds to ambiguity
ExceptionMessage(EOFException.MISSING_TERMINATOR, "err: header_terminator_missing"),
ExceptionMessage(
EOFException.MISSING_HEADERS_TERMINATOR, "err: section_headers_not_terminated"
),
ExceptionMessage(EOFException.INVALID_VERSION, "err: eof_version_unknown"),
ExceptionMessage(
EOFException.INVALID_NON_RETURNING_FLAG, "err: invalid_non_returning_flag"
),
ExceptionMessage(EOFException.INVALID_MAGIC, "err: invalid_prefix"),
ExceptionMessage(
EOFException.INVALID_FIRST_SECTION_TYPE, "err: invalid_first_section_type"
),
ExceptionMessage(
EOFException.INVALID_SECTION_BODIES_SIZE, "err: invalid_section_bodies_size"
),
ExceptionMessage(
EOFException.INVALID_TYPE_SECTION_SIZE, "err: invalid_type_section_size"
),
ExceptionMessage(EOFException.INCOMPLETE_SECTION_SIZE, "err: incomplete_section_size"),
ExceptionMessage(
EOFException.INCOMPLETE_SECTION_NUMBER, "err: incomplete_section_number"
),
ExceptionMessage(EOFException.TOO_MANY_CODE_SECTIONS, "err: too_many_code_sections"),
ExceptionMessage(EOFException.ZERO_SECTION_SIZE, "err: zero_section_size"),
ExceptionMessage(EOFException.MISSING_DATA_SECTION, "err: data_section_missing"),
ExceptionMessage(EOFException.UNDEFINED_INSTRUCTION, "err: undefined_instruction"),
ExceptionMessage(
EOFException.INPUTS_OUTPUTS_NUM_ABOVE_LIMIT, "err: inputs_outputs_num_above_limit"
),
ExceptionMessage(
EOFException.UNREACHABLE_INSTRUCTIONS, "err: unreachable_instructions"
),
ExceptionMessage(
EOFException.INVALID_RJUMP_DESTINATION, "err: invalid_rjump_destination"
),
ExceptionMessage(
EOFException.UNREACHABLE_CODE_SECTIONS, "err: unreachable_code_sections"
),
ExceptionMessage(EOFException.STACK_UNDERFLOW, "err: stack_underflow"),
ExceptionMessage(
EOFException.MAX_STACK_HEIGHT_ABOVE_LIMIT, "err: max_stack_height_above_limit"
),
ExceptionMessage(
EOFException.STACK_HIGHER_THAN_OUTPUTS, "err: stack_higher_than_outputs_required"
),
ExceptionMessage(
EOFException.JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS,
"err: jumpf_destination_incompatible_outputs",
),
ExceptionMessage(
EOFException.INVALID_MAX_STACK_HEIGHT, "err: invalid_max_stack_height"
),
ExceptionMessage(EOFException.INVALID_DATALOADN_INDEX, "err: invalid_dataloadn_index"),
ExceptionMessage(EOFException.TRUNCATED_INSTRUCTION, "err: truncated_instruction"),
ExceptionMessage(
EOFException.TOPLEVEL_CONTAINER_TRUNCATED, "err: toplevel_container_truncated"
),
ExceptionMessage(EOFException.ORPHAN_SUBCONTAINER, "err: unreferenced_subcontainer"),
ExceptionMessage(
EOFException.CONTAINER_SIZE_ABOVE_LIMIT, "err: container_size_above_limit"
),
ExceptionMessage(
EOFException.INVALID_CONTAINER_SECTION_INDEX,
"err: invalid_container_section_index",
),
ExceptionMessage(
EOFException.INCOMPATIBLE_CONTAINER_KIND, "err: incompatible_container_kind"
),
ExceptionMessage(EOFException.STACK_HEIGHT_MISMATCH, "err: stack_height_mismatch"),
ExceptionMessage(EOFException.TOO_MANY_CONTAINERS, "err: too_many_container_sections"),
ExceptionMessage(
EOFException.INVALID_CODE_SECTION_INDEX, "err: invalid_code_section_index"
),
]
Loading