From ef4a5e2ea1315e2e8576bed542e49e94b597cff0 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Sat, 22 Jun 2024 02:58:52 +0000 Subject: [PATCH 1/3] refactor(fw): refactor `ethereum_test_tools` submodules into libraries --- docs/CHANGELOG.md | 1 + setup.cfg | 22 +- src/cli/check_fixtures.py | 6 +- src/cli/evm_bytes_to_python.py | 4 +- src/cli/gen_index.py | 8 +- src/cli/gentest.py | 7 +- src/ethereum_test_base_types/__init__.py | 67 + .../base_types.py | 0 .../composite_types.py | 427 ++ .../constants.py | 19 - .../conversions.py | 0 .../json.py | 0 src/ethereum_test_base_types/py.typed | 0 src/ethereum_test_base_types/pydantic.py | 36 + .../reference_spec/__init__.py | 0 .../reference_spec/git_reference_spec.py | 0 .../reference_spec/reference_spec.py | 0 .../tests/__init__.py | 3 + .../tests/test_base_types.py | 2 +- .../tests/test_reference_spec.py | 2 +- .../__init__.py | 2 + src/ethereum_test_exceptions/engine_api.py | 23 + .../evmone_exceptions.py | 0 .../exceptions.py | 0 src/ethereum_test_exceptions/py.typed | 0 .../tests/__init__.py | 3 + .../tests/test_exceptions.py | 2 +- src/ethereum_test_fixtures/__init__.py | 33 + src/ethereum_test_fixtures/base.py | 71 + .../blockchain.py} | 249 +- .../collector.py} | 11 +- .../consume.py} | 10 +- .../eof.py} | 11 +- .../file.py} | 9 +- src/ethereum_test_fixtures/formats.py | 72 + src/ethereum_test_fixtures/py.typed | 0 .../state.py} | 13 +- src/ethereum_test_fixtures/tests/__init__.py | 3 + .../tests/test_base.py} | 4 +- .../tests/test_blockchain.py} | 989 +-- .../tests/test_state.py | 113 + src/ethereum_test_fixtures/verify.py | 31 + .../spec => ethereum_test_specs}/__init__.py | 13 +- .../base.py} | 73 +- .../blockchain.py} | 280 +- .../spec => ethereum_test_specs}/debugging.py | 0 .../eof.py} | 19 +- src/ethereum_test_specs/py.typed | 0 .../state.py} | 55 +- src/ethereum_test_specs/tests/__init__.py | 3 + .../blockchain_london_invalid_filled.json} | 545 +- .../blockchain_london_valid_filled.json | 421 ++ ...ckchain_shanghai_invalid_filled_hive.json} | 282 +- ...blockchain_shanghai_valid_filled_hive.json | 250 + .../chainid_istanbul_blockchain_test.json | 0 .../chainid_london_blockchain_test.json | 0 .../chainid_paris_blockchain_test_hive.json | 0 .../fixtures/chainid_paris_state_test.json | 0 ...chainid_shanghai_blockchain_test_hive.json | 0 .../fixtures/chainid_shanghai_state_test.json | 0 .../tests}/test_expect.py | 9 +- .../tests}/test_fixtures.py | 246 +- .../tests/test_types.py} | 13 +- src/ethereum_test_tools/__init__.py | 86 +- src/ethereum_test_tools/code/generators.py | 6 +- src/ethereum_test_tools/code/yul.py | 3 +- src/ethereum_test_tools/eof/__init__.py | 4 +- src/ethereum_test_tools/eof/constants.py | 31 +- src/ethereum_test_tools/eof/v1/__init__.py | 574 +- src/ethereum_test_tools/eof/v1/constants.py | 76 +- src/ethereum_test_tools/rpc/rpc.py | 2 +- src/ethereum_test_tools/spec/base/__init__.py | 3 - .../spec/blockchain/__init__.py | 3 - .../spec/consume/__init__.py | 3 - src/ethereum_test_tools/spec/eof/__init__.py | 3 - src/ethereum_test_tools/spec/file/__init__.py | 3 - .../spec/state/__init__.py | 3 - src/ethereum_test_tools/tests/test_code.py | 10 +- .../tests/test_filling/__init__.py | 3 - .../blockchain_london_invalid_filled.json | 1084 --- ...ockchain_shanghai_invalid_filled_hive.json | 594 -- src/ethereum_test_tools/vm/__init__.py | 4 +- src/ethereum_test_tools/vm/opcode.py | 5905 +---------------- .../__init__.py | 35 +- src/ethereum_test_types/eof/__init__.py | 6 + src/ethereum_test_types/eof/constants.py | 21 + src/ethereum_test_types/eof/v1/__init__.py | 564 ++ src/ethereum_test_types/eof/v1/constants.py | 39 + .../common => ethereum_test_types}/helpers.py | 5 +- src/ethereum_test_types/py.typed | 0 src/ethereum_test_types/tests/__init__.py | 3 + .../tests/test_eof_v1.py | 0 .../tests/test_helpers.py | 4 +- .../tests/test_post_alloc.py} | 5 +- .../tests/test_transactions.py | 4 +- src/ethereum_test_types/tests/test_types.py | 920 +++ .../common => ethereum_test_types}/types.py | 571 +- src/ethereum_test_vm/__init__.py | 16 + .../vm => ethereum_test_vm}/bytecode.py | 0 src/ethereum_test_vm/opcode.py | 5888 ++++++++++++++++ src/ethereum_test_vm/py.typed | 0 src/ethereum_test_vm/tests/__init__.py | 3 + .../tests/test_vm.py | 11 +- src/evm_transition_tool/__init__.py | 11 +- src/evm_transition_tool/besu.py | 55 +- .../tests/fixtures/1/exp.json | 17 +- .../tests/fixtures/1/txs.json | 4 +- .../tests/fixtures/3/exp.json | 18 +- .../tests/fixtures/3/txs.json | 2 +- .../tests/test_evaluate.py | 61 +- src/evm_transition_tool/transition_tool.py | 155 +- src/evm_transition_tool/types.py | 101 + src/pytest_plugins/consume/consume.py | 4 +- src/pytest_plugins/consume/direct.py | 6 +- .../consume/simulator_common.py | 14 +- src/pytest_plugins/test_filler/test_filler.py | 11 +- tests_consume/test_direct.py | 2 +- tests_consume/test_via_engine_api.py | 2 +- tests_consume/test_via_rlp.py | 5 +- whitelist.txt | 1 + 120 files changed, 10181 insertions(+), 11245 deletions(-) create mode 100644 src/ethereum_test_base_types/__init__.py rename src/{ethereum_test_tools/common => ethereum_test_base_types}/base_types.py (100%) create mode 100644 src/ethereum_test_base_types/composite_types.py rename src/{ethereum_test_tools/common => ethereum_test_base_types}/constants.py (63%) rename src/{ethereum_test_tools/common => ethereum_test_base_types}/conversions.py (100%) rename src/{ethereum_test_tools/common => ethereum_test_base_types}/json.py (100%) create mode 100644 src/ethereum_test_base_types/py.typed create mode 100644 src/ethereum_test_base_types/pydantic.py rename src/{ethereum_test_tools => ethereum_test_base_types}/reference_spec/__init__.py (100%) rename src/{ethereum_test_tools => ethereum_test_base_types}/reference_spec/git_reference_spec.py (100%) rename src/{ethereum_test_tools => ethereum_test_base_types}/reference_spec/reference_spec.py (100%) create mode 100644 src/ethereum_test_base_types/tests/__init__.py rename src/{ethereum_test_tools => ethereum_test_base_types}/tests/test_base_types.py (97%) rename src/{ethereum_test_tools => ethereum_test_base_types}/tests/test_reference_spec.py (98%) rename src/{ethereum_test_tools/exceptions => ethereum_test_exceptions}/__init__.py (89%) create mode 100644 src/ethereum_test_exceptions/engine_api.py rename src/{ethereum_test_tools/exceptions => ethereum_test_exceptions}/evmone_exceptions.py (100%) rename src/{ethereum_test_tools/exceptions => ethereum_test_exceptions}/exceptions.py (100%) create mode 100644 src/ethereum_test_exceptions/py.typed create mode 100644 src/ethereum_test_exceptions/tests/__init__.py rename src/{ethereum_test_tools => ethereum_test_exceptions}/tests/test_exceptions.py (98%) create mode 100644 src/ethereum_test_fixtures/__init__.py create mode 100644 src/ethereum_test_fixtures/base.py rename src/{ethereum_test_tools/spec/blockchain/types.py => ethereum_test_fixtures/blockchain.py} (62%) rename src/{ethereum_test_tools/spec/fixture_collector.py => ethereum_test_fixtures/collector.py} (96%) rename src/{ethereum_test_tools/spec/consume/types.py => ethereum_test_fixtures/consume.py} (94%) rename src/{ethereum_test_tools/spec/eof/types.py => ethereum_test_fixtures/eof.py} (81%) rename src/{ethereum_test_tools/spec/file/types.py => ethereum_test_fixtures/file.py} (95%) create mode 100644 src/ethereum_test_fixtures/formats.py create mode 100644 src/ethereum_test_fixtures/py.typed rename src/{ethereum_test_tools/spec/state/types.py => ethereum_test_fixtures/state.py} (91%) create mode 100644 src/ethereum_test_fixtures/tests/__init__.py rename src/{ethereum_test_tools/tests/test_spec_base.py => ethereum_test_fixtures/tests/test_base.py} (71%) rename src/{ethereum_test_tools/tests/test_types.py => ethereum_test_fixtures/tests/test_blockchain.py} (52%) create mode 100644 src/ethereum_test_fixtures/tests/test_state.py create mode 100644 src/ethereum_test_fixtures/verify.py rename src/{ethereum_test_tools/spec => ethereum_test_specs}/__init__.py (63%) rename src/{ethereum_test_tools/spec/base/base_test.py => ethereum_test_specs/base.py} (58%) rename src/{ethereum_test_tools/spec/blockchain/blockchain_test.py => ethereum_test_specs/blockchain.py} (67%) rename src/{ethereum_test_tools/spec => ethereum_test_specs}/debugging.py (100%) rename src/{ethereum_test_tools/spec/eof/eof_test.py => ethereum_test_specs/eof.py} (96%) create mode 100644 src/ethereum_test_specs/py.typed rename src/{ethereum_test_tools/spec/state/state_test.py => ethereum_test_specs/state.py} (82%) create mode 100644 src/ethereum_test_specs/tests/__init__.py rename src/{ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_valid_filled.json => ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json} (53%) create mode 100644 src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json rename src/{ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_valid_filled_hive.json => ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_hive.json} (58%) create mode 100644 src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_hive.json rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/fixtures/chainid_istanbul_blockchain_test.json (100%) rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/fixtures/chainid_london_blockchain_test.json (100%) rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/fixtures/chainid_paris_blockchain_test_hive.json (100%) rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/fixtures/chainid_paris_state_test.json (100%) rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/fixtures/chainid_shanghai_blockchain_test_hive.json (100%) rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/fixtures/chainid_shanghai_state_test.json (100%) rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/test_expect.py (97%) rename src/{ethereum_test_tools/tests/test_filling => ethereum_test_specs/tests}/test_fixtures.py (83%) rename src/{ethereum_test_tools/tests/test_types_blockchain_test.py => ethereum_test_specs/tests/test_types.py} (89%) delete mode 100644 src/ethereum_test_tools/spec/base/__init__.py delete mode 100644 src/ethereum_test_tools/spec/blockchain/__init__.py delete mode 100644 src/ethereum_test_tools/spec/consume/__init__.py delete mode 100644 src/ethereum_test_tools/spec/eof/__init__.py delete mode 100644 src/ethereum_test_tools/spec/file/__init__.py delete mode 100644 src/ethereum_test_tools/spec/state/__init__.py delete mode 100644 src/ethereum_test_tools/tests/test_filling/__init__.py delete mode 100644 src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_invalid_filled.json delete mode 100644 src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_hive.json rename src/{ethereum_test_tools/common => ethereum_test_types}/__init__.py (69%) create mode 100644 src/ethereum_test_types/eof/__init__.py create mode 100644 src/ethereum_test_types/eof/constants.py create mode 100644 src/ethereum_test_types/eof/v1/__init__.py create mode 100644 src/ethereum_test_types/eof/v1/constants.py rename src/{ethereum_test_tools/common => ethereum_test_types}/helpers.py (96%) create mode 100644 src/ethereum_test_types/py.typed create mode 100644 src/ethereum_test_types/tests/__init__.py rename src/{ethereum_test_tools => ethereum_test_types}/tests/test_eof_v1.py (100%) rename src/{ethereum_test_tools => ethereum_test_types}/tests/test_helpers.py (97%) rename src/{ethereum_test_tools/tests/test_specs.py => ethereum_test_types/tests/test_post_alloc.py} (95%) rename src/{ethereum_test_tools => ethereum_test_types}/tests/test_transactions.py (99%) create mode 100644 src/ethereum_test_types/tests/test_types.py rename src/{ethereum_test_tools/common => ethereum_test_types}/types.py (68%) create mode 100644 src/ethereum_test_vm/__init__.py rename src/{ethereum_test_tools/vm => ethereum_test_vm}/bytecode.py (100%) create mode 100644 src/ethereum_test_vm/opcode.py create mode 100644 src/ethereum_test_vm/py.typed create mode 100644 src/ethereum_test_vm/tests/__init__.py rename src/{ethereum_test_tools => ethereum_test_vm}/tests/test_vm.py (98%) create mode 100644 src/evm_transition_tool/types.py diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 40dcb16889..335839ffad 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -50,6 +50,7 @@ Test fixtures for use by clients are available for each release on the [Github r - ✨ Enable loading of [ethereum/tests/BlockchainTests](https://github.com/ethereum/tests/tree/develop/BlockchainTests) ([#596](https://github.com/ethereum/execution-spec-tests/pull/596)). - 🔀 Refactor `gentest` to use `ethereum_test_tools.rpc.rpc` by adding to `get_transaction_by_hash`, `debug_trace_call` to `EthRPC` ([#568](https://github.com/ethereum/execution-spec-tests/pull/568)). - ✨ Write a properties file to the output directory and enable direct generation of a fixture tarball from `fill` via `--output=fixtures.tgz`([#627](https://github.com/ethereum/execution-spec-tests/pull/627)). +- 🔀 `ethereum_test_tools` library has been split into multiple libraries ([#645](https://github.com/ethereum/execution-spec-tests/pull/645)). ### 🔧 EVM Tools diff --git a/setup.cfg b/setup.cfg index 50285a5608..810336a349 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,9 +12,15 @@ classifiers = [options] packages = - evm_transition_tool + ethereum_test_base_types + ethereum_test_exceptions + ethereum_test_fixtures ethereum_test_forks + ethereum_test_specs ethereum_test_tools + ethereum_test_types + ethereum_test_vm + evm_transition_tool pytest_plugins package_dir = @@ -47,11 +53,23 @@ install_requires = solc-select>=1.0.4 [options.package_data] -ethereum_test_tools = +ethereum_test_base_types = + py.typed +ethereum_test_exceptions = + py.typed +ethereum_test_fixtures = py.typed ethereum_test_forks = py.typed forks/contracts/*.bin +ethereum_test_specs = + py.typed +ethereum_test_tools = + py.typed +ethereum_test_types = + py.typed +ethereum_test_vm = + py.typed evm_transition_tool = py.typed pytest_plugins = diff --git a/src/cli/check_fixtures.py b/src/cli/check_fixtures.py index ff938c3253..ef7e39f5dc 100644 --- a/src/cli/check_fixtures.py +++ b/src/cli/check_fixtures.py @@ -8,9 +8,9 @@ import click from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeElapsedColumn -from ethereum_test_tools.common.json import to_json -from ethereum_test_tools.spec.base.base_test import HashMismatchException -from ethereum_test_tools.spec.file.types import Fixtures +from ethereum_test_base_types import to_json +from ethereum_test_fixtures.file import Fixtures +from ethereum_test_specs.base import HashMismatchException def count_json_files_exclude_index(start_path: Path) -> int: diff --git a/src/cli/evm_bytes_to_python.py b/src/cli/evm_bytes_to_python.py index 97b8d5fa28..243b69ccc0 100644 --- a/src/cli/evm_bytes_to_python.py +++ b/src/cli/evm_bytes_to_python.py @@ -6,8 +6,8 @@ import click -from ethereum_test_tools import Macro -from ethereum_test_tools import Opcodes as Op +from ethereum_test_vm import Macro +from ethereum_test_vm import Opcodes as Op def process_evm_bytes(evm_bytes_hex_string: Any) -> str: # noqa: D103 diff --git a/src/cli/gen_index.py b/src/cli/gen_index.py index eb461db4af..7ffaf338c1 100644 --- a/src/cli/gen_index.py +++ b/src/cli/gen_index.py @@ -18,10 +18,10 @@ TimeElapsedColumn, ) -from ethereum_test_tools.common.base_types import HexNumber -from ethereum_test_tools.spec.consume.types import IndexFile, TestCaseIndexFile -from ethereum_test_tools.spec.file.types import Fixtures -from evm_transition_tool import FixtureFormats +from ethereum_test_base_types import HexNumber +from ethereum_test_fixtures import FixtureFormats +from ethereum_test_fixtures.consume import IndexFile, TestCaseIndexFile +from ethereum_test_fixtures.file import Fixtures from .hasher import HashableItem diff --git a/src/cli/gentest.py b/src/cli/gentest.py index ede1050887..288e750cc4 100644 --- a/src/cli/gentest.py +++ b/src/cli/gentest.py @@ -59,8 +59,9 @@ import click -from ethereum_test_tools import Account, Address, Transaction, common +from ethereum_test_base_types import Account, Address, ZeroPaddedHexNumber from ethereum_test_tools.rpc.rpc import BlockNumberType, EthRPC +from ethereum_test_types import Transaction @click.command() @@ -165,8 +166,8 @@ def _make_pre_state( if account_obj.storage is not None: for record, value in account_obj.storage.root.items(): - pad_record = common.ZeroPaddedHexNumber(record) - pad_value = common.ZeroPaddedHexNumber(value) + pad_record = ZeroPaddedHexNumber(record) + pad_value = ZeroPaddedHexNumber(value) state_str += f'{pad} "{pad_record}" : "{pad_value}",\n' state_str += pad + "}\n" diff --git a/src/ethereum_test_base_types/__init__.py b/src/ethereum_test_base_types/__init__.py new file mode 100644 index 0000000000..3b4ee79fe1 --- /dev/null +++ b/src/ethereum_test_base_types/__init__.py @@ -0,0 +1,67 @@ +""" +Common definitions and types. +""" + +from .base_types import ( + Address, + Bloom, + BLSPublicKey, + BLSSignature, + Bytes, + FixedSizeBytes, + Hash, + HashInt, + HeaderNonce, + HexNumber, + Number, + NumberBoundTypeVar, + ZeroPaddedHexNumber, +) +from .composite_types import Account, Alloc, Storage, StorageRootType +from .constants import ( + AddrAA, + AddrBB, + EmptyOmmersRoot, + EmptyTrieRoot, + TestAddress, + TestAddress2, + TestPrivateKey, + TestPrivateKey2, +) +from .conversions import to_bytes, to_hex +from .json import to_json +from .pydantic import CamelModel +from .reference_spec import ReferenceSpec + +__all__ = ( + "Account", + "AddrAA", + "AddrBB", + "Address", + "Alloc", + "Bloom", + "BLSPublicKey", + "BLSSignature", + "Bytes", + "CamelModel", + "EmptyOmmersRoot", + "EmptyTrieRoot", + "FixedSizeBytes", + "Hash", + "HashInt", + "HeaderNonce", + "HexNumber", + "Number", + "NumberBoundTypeVar", + "ReferenceSpec", + "Storage", + "StorageRootType", + "TestAddress", + "TestAddress2", + "TestPrivateKey", + "TestPrivateKey2", + "ZeroPaddedHexNumber", + "to_bytes", + "to_hex", + "to_json", +) diff --git a/src/ethereum_test_tools/common/base_types.py b/src/ethereum_test_base_types/base_types.py similarity index 100% rename from src/ethereum_test_tools/common/base_types.py rename to src/ethereum_test_base_types/base_types.py diff --git a/src/ethereum_test_base_types/composite_types.py b/src/ethereum_test_base_types/composite_types.py new file mode 100644 index 0000000000..208e8e3575 --- /dev/null +++ b/src/ethereum_test_base_types/composite_types.py @@ -0,0 +1,427 @@ +""" +Base composite types for Ethereum test cases. +""" +from dataclasses import dataclass +from itertools import count +from typing import Any, ClassVar, Dict, Iterator, SupportsBytes, Type, TypeAlias + +from pydantic import Field, RootModel, TypeAdapter + +from .base_types import Address, Bytes, Hash, HashInt, HexNumber, ZeroPaddedHexNumber +from .conversions import BytesConvertible, NumberConvertible +from .pydantic import CamelModel + +StorageKeyValueTypeConvertible = NumberConvertible +StorageKeyValueType = HashInt +StorageKeyValueTypeAdapter = TypeAdapter(StorageKeyValueType) +StorageRootType = Dict[NumberConvertible, NumberConvertible] + + +class Storage(RootModel[Dict[StorageKeyValueType, StorageKeyValueType]]): + """ + Definition of a storage in pre or post state of a test + """ + + root: Dict[StorageKeyValueType, StorageKeyValueType] = Field(default_factory=dict) + + _current_slot: Iterator[int] = count(0) + + StorageDictType: ClassVar[TypeAlias] = Dict[ + str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes + ] + """ + Dictionary type to be used when defining an input to initialize a storage. + """ + + @dataclass(kw_only=True) + class InvalidType(Exception): + """ + Invalid type used when describing test's expected storage key or value. + """ + + key_or_value: Any + + def __init__(self, key_or_value: Any, *args): + super().__init__(args) + self.key_or_value = key_or_value + + def __str__(self): + """Print exception string""" + return f"invalid type for key/value: {self.key_or_value}" + + @dataclass(kw_only=True) + class InvalidValue(Exception): + """ + Invalid value used when describing test's expected storage key or + value. + """ + + key_or_value: Any + + def __init__(self, key_or_value: Any, *args): + super().__init__(args) + self.key_or_value = key_or_value + + def __str__(self): + """Print exception string""" + return f"invalid value for key/value: {self.key_or_value}" + + @dataclass(kw_only=True) + class MissingKey(Exception): + """ + Test expected to find a storage key set but key was missing. + """ + + key: int + + def __init__(self, key: int, *args): + super().__init__(args) + self.key = key + + def __str__(self): + """Print exception string""" + return "key {0} not found in storage".format(Hash(self.key)) + + @dataclass(kw_only=True) + class KeyValueMismatch(Exception): + """ + Test expected a certain value in a storage key but value found + was different. + """ + + address: Address + key: int + want: int + got: int + + def __init__(self, address: Address, key: int, want: int, got: int, *args): + super().__init__(args) + self.address = address + self.key = key + self.want = want + self.got = got + + def __str__(self): + """Print exception string""" + label_str = "" + if self.address.label is not None: + label_str = f" ({self.address.label})" + return ( + f"incorrect value in address {self.address}{label_str} for " + + f"key {Hash(self.key)}:" + + f" want {HexNumber(self.want)} (dec:{self.want})," + + f" got {HexNumber(self.got)} (dec:{self.got})" + ) + + def __contains__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType) -> bool: + """Checks for an item in the storage""" + return StorageKeyValueTypeAdapter.validate_python(key) in self.root + + def __getitem__( + self, key: StorageKeyValueTypeConvertible | StorageKeyValueType + ) -> StorageKeyValueType: + """Returns an item from the storage""" + return self.root[StorageKeyValueTypeAdapter.validate_python(key)] + + def __setitem__( + self, + key: StorageKeyValueTypeConvertible | StorageKeyValueType, + value: StorageKeyValueTypeConvertible | StorageKeyValueType, + ): # noqa: SC200 + """Sets an item in the storage""" + self.root[ + StorageKeyValueTypeAdapter.validate_python(key) + ] = StorageKeyValueTypeAdapter.validate_python(value) + + def __delitem__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType): + """Deletes an item from the storage""" + del self.root[StorageKeyValueTypeAdapter.validate_python(key)] + + def __iter__(self): + """Returns an iterator over the storage""" + return iter(self.root) + + def __eq__(self, other) -> bool: + """ + Returns True if both storages are equal. + """ + if not isinstance(other, Storage): + return False + return self.root == other.root + + def __ne__(self, other) -> bool: + """ + Returns True if both storages are not equal. + """ + if not isinstance(other, Storage): + return False + return self.root != other.root + + def __bool__(self) -> bool: + """Returns True if the storage is not empty""" + return any(v for v in self.root.values()) + + def keys(self) -> set[StorageKeyValueType]: + """Returns the keys of the storage""" + return set(self.root.keys()) + + def store_next( + self, value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool + ) -> StorageKeyValueType: + """ + Stores a value in the storage and returns the key where the value is stored. + + Increments the key counter so the next time this function is called, + the next key is used. + """ + slot = StorageKeyValueTypeAdapter.validate_python(next(self._current_slot)) + self[slot] = StorageKeyValueTypeAdapter.validate_python(value) + return slot + + def contains(self, other: "Storage") -> bool: + """ + Returns True if self contains all keys with equal value as + contained by second storage. + Used for comparison with test expected post state and alloc returned + by the transition tool. + """ + for key in other.keys(): + if key not in self: + return False + if self[key] != other[key]: + return False + return True + + def must_contain(self, address: Address, other: "Storage"): + """ + Succeeds only if self contains all keys with equal value as + contained by second storage. + Used for comparison with test expected post state and alloc returned + by the transition tool. + Raises detailed exception when a difference is found. + """ + for key in other.keys(): + if key not in self: + # storage[key]==0 is equal to missing storage + if other[key] != 0: + raise Storage.MissingKey(key=key) + elif self[key] != other[key]: + raise Storage.KeyValueMismatch( + address=address, key=key, want=self[key], got=other[key] + ) + + def must_be_equal(self, address: Address, other: "Storage | None"): + """ + Succeeds only if "self" is equal to "other" storage. + """ + # Test keys contained in both storage objects + if other is None: + other = Storage({}) + for key in self.keys() & other.keys(): + if self[key] != other[key]: + raise Storage.KeyValueMismatch( + address=address, key=key, want=self[key], got=other[key] + ) + + # Test keys contained in either one of the storage objects + for key in self.keys() ^ other.keys(): + if key in self: + if self[key] != 0: + raise Storage.KeyValueMismatch(address=address, key=key, want=self[key], got=0) + + elif other[key] != 0: + raise Storage.KeyValueMismatch(address=address, key=key, want=0, got=other[key]) + + def canary(self) -> "Storage": + """ + Returns a canary storage filled with non-zero values where the current storage expects + zero values, to guarantee that the test overwrites the storage. + """ + return Storage({key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0}) + + +class Account(CamelModel): + """ + State associated with an address. + """ + + nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) + """ + The scalar value equal to a) the number of transactions sent by + an Externally Owned Account, b) the amount of contracts created by a + contract. + """ + balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) + """ + The amount of Wei (10-18 Eth) the account has. + """ + code: Bytes = Bytes(b"") + """ + Bytecode contained by the account. + """ + storage: Storage = Field(default_factory=Storage) + """ + Storage within a contract. + """ + + NONEXISTENT: ClassVar[None] = None + """ + Sentinel object used to specify when an account should not exist in the + state. + """ + + @dataclass(kw_only=True) + class NonceMismatch(Exception): + """ + Test expected a certain nonce value for an account but a different + value was found. + """ + + address: Address + want: int | None + got: int | None + + def __init__(self, address: Address, want: int | None, got: int | None, *args): + super().__init__(args) + self.address = address + self.want = want + self.got = got + + def __str__(self): + """Print exception string""" + label_str = "" + if self.address.label is not None: + label_str = f" ({self.address.label})" + return ( + f"unexpected nonce for account {self.address}{label_str}: " + + f"want {self.want}, got {self.got}" + ) + + @dataclass(kw_only=True) + class BalanceMismatch(Exception): + """ + Test expected a certain balance for an account but a different + value was found. + """ + + address: Address + want: int | None + got: int | None + + def __init__(self, address: Address, want: int | None, got: int | None, *args): + super().__init__(args) + self.address = address + self.want = want + self.got = got + + def __str__(self): + """Print exception string""" + label_str = "" + if self.address.label is not None: + label_str = f" ({self.address.label})" + return ( + f"unexpected balance for account {self.address}{label_str}: " + + f"want {self.want}, got {self.got}" + ) + + @dataclass(kw_only=True) + class CodeMismatch(Exception): + """ + Test expected a certain bytecode for an account but a different + one was found. + """ + + address: Address + want: bytes | None + got: bytes | None + + def __init__(self, address: Address, want: bytes | None, got: bytes | None, *args): + super().__init__(args) + self.address = address + self.want = want + self.got = got + + def __str__(self): + """Print exception string""" + label_str = "" + if self.address.label is not None: + label_str = f" ({self.address.label})" + return ( + f"unexpected code for account {self.address}{label_str}: " + + f"want {self.want}, got {self.got}" + ) + + def check_alloc(self: "Account", address: Address, account: "Account"): + """ + Checks the returned alloc against an expected account in post state. + Raises exception on failure. + """ + if "nonce" in self.model_fields_set: + if self.nonce != account.nonce: + raise Account.NonceMismatch( + address=address, + want=self.nonce, + got=account.nonce, + ) + + if "balance" in self.model_fields_set: + if self.balance != account.balance: + raise Account.BalanceMismatch( + address=address, + want=self.balance, + got=account.balance, + ) + + if "code" in self.model_fields_set: + if self.code != account.code: + raise Account.CodeMismatch( + address=address, + want=self.code, + got=account.code, + ) + + if "storage" in self.model_fields_set: + self.storage.must_be_equal(address=address, other=account.storage) + + def __bool__(self: "Account") -> bool: + """ + Returns True on a non-empty account. + """ + return any((self.nonce, self.balance, self.code, self.storage)) + + @classmethod + def with_code(cls: Type, code: BytesConvertible) -> "Account": + """ + Create account with provided `code` and nonce of `1`. + """ + return Account(nonce=HexNumber(1), code=Bytes(code)) + + @classmethod + def merge( + cls: Type, account_1: "Dict | Account | None", account_2: "Dict | Account | None" + ) -> "Account": + """ + Create a merged account from two sources. + """ + + def to_kwargs_dict(account: "Dict | Account | None") -> Dict: + if account is None: + return {} + if isinstance(account, dict): + return account + elif isinstance(account, cls): + return account.model_dump(exclude_unset=True) + raise TypeError(f"Unexpected type for account merge: {type(account)}") + + kwargs = to_kwargs_dict(account_1) + kwargs.update(to_kwargs_dict(account_2)) + + return cls(**kwargs) + + +class Alloc(RootModel[Dict[Address, Account | None]]): + """ + Allocation of accounts in the state, pre and post test execution. + """ + + root: Dict[Address, Account | None] = Field(default_factory=dict, validate_default=True) diff --git a/src/ethereum_test_tools/common/constants.py b/src/ethereum_test_base_types/constants.py similarity index 63% rename from src/ethereum_test_tools/common/constants.py rename to src/ethereum_test_base_types/constants.py index 2eff979a90..cb0f60b80e 100644 --- a/src/ethereum_test_tools/common/constants.py +++ b/src/ethereum_test_base_types/constants.py @@ -2,7 +2,6 @@ Common values used in Ethereum tests. """ -from enum import IntEnum from .base_types import Address @@ -21,21 +20,3 @@ EmptyHash = bytes([0] * 32) EmptyNonce = bytes([0] * 8) ZeroAddress = Address(0x00) - - -class EngineAPIError(IntEnum): - """ - List of Engine API errors - """ - - ParseError = -32700 - InvalidRequest = -32600 - MethodNotFound = -32601 - InvalidParams = -32602 - InternalError = -32603 - ServerError = -32000 - UnknownPayload = -38001 - InvalidForkchoiceState = -38002 - InvalidPayloadAttributes = -38003 - TooLargeRequest = -38004 - UnsupportedFork = -38005 diff --git a/src/ethereum_test_tools/common/conversions.py b/src/ethereum_test_base_types/conversions.py similarity index 100% rename from src/ethereum_test_tools/common/conversions.py rename to src/ethereum_test_base_types/conversions.py diff --git a/src/ethereum_test_tools/common/json.py b/src/ethereum_test_base_types/json.py similarity index 100% rename from src/ethereum_test_tools/common/json.py rename to src/ethereum_test_base_types/json.py diff --git a/src/ethereum_test_base_types/py.typed b/src/ethereum_test_base_types/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ethereum_test_base_types/pydantic.py b/src/ethereum_test_base_types/pydantic.py new file mode 100644 index 0000000000..6ef2c2b0a4 --- /dev/null +++ b/src/ethereum_test_base_types/pydantic.py @@ -0,0 +1,36 @@ +""" +Base pydantic classes used to define the models for Ethereum tests. +""" +from typing import TypeVar + +from pydantic import BaseModel, ConfigDict +from pydantic.alias_generators import to_camel + +Model = TypeVar("Model", bound=BaseModel) + + +class CopyValidateModel(BaseModel): + """ + Base model for Ethereum tests. + """ + + def copy(self: Model, **kwargs) -> Model: + """ + Creates a copy of the model with the updated fields that are validated. + """ + return self.__class__(**(self.model_dump(exclude_unset=True) | kwargs)) + + +class CamelModel(CopyValidateModel): + """ + A base model that converts field names to camel case when serializing. + + For example, the field name `current_timestamp` in a Python model will be represented + as `currentTimestamp` when it is serialized to json. + """ + + model_config = ConfigDict( + alias_generator=to_camel, + populate_by_name=True, + validate_default=True, + ) diff --git a/src/ethereum_test_tools/reference_spec/__init__.py b/src/ethereum_test_base_types/reference_spec/__init__.py similarity index 100% rename from src/ethereum_test_tools/reference_spec/__init__.py rename to src/ethereum_test_base_types/reference_spec/__init__.py diff --git a/src/ethereum_test_tools/reference_spec/git_reference_spec.py b/src/ethereum_test_base_types/reference_spec/git_reference_spec.py similarity index 100% rename from src/ethereum_test_tools/reference_spec/git_reference_spec.py rename to src/ethereum_test_base_types/reference_spec/git_reference_spec.py diff --git a/src/ethereum_test_tools/reference_spec/reference_spec.py b/src/ethereum_test_base_types/reference_spec/reference_spec.py similarity index 100% rename from src/ethereum_test_tools/reference_spec/reference_spec.py rename to src/ethereum_test_base_types/reference_spec/reference_spec.py diff --git a/src/ethereum_test_base_types/tests/__init__.py b/src/ethereum_test_base_types/tests/__init__.py new file mode 100644 index 0000000000..c6162e8e0b --- /dev/null +++ b/src/ethereum_test_base_types/tests/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for the ethereum_test_base_types package. +""" diff --git a/src/ethereum_test_tools/tests/test_base_types.py b/src/ethereum_test_base_types/tests/test_base_types.py similarity index 97% rename from src/ethereum_test_tools/tests/test_base_types.py rename to src/ethereum_test_base_types/tests/test_base_types.py index d9b8971e78..0ef5f3b8ce 100644 --- a/src/ethereum_test_tools/tests/test_base_types.py +++ b/src/ethereum_test_base_types/tests/test_base_types.py @@ -6,7 +6,7 @@ import pytest -from ..common.base_types import Address, Hash +from ..base_types import Address, Hash @pytest.mark.parametrize( diff --git a/src/ethereum_test_tools/tests/test_reference_spec.py b/src/ethereum_test_base_types/tests/test_reference_spec.py similarity index 98% rename from src/ethereum_test_tools/tests/test_reference_spec.py rename to src/ethereum_test_base_types/tests/test_reference_spec.py index f6fe2310ae..14d04b49ba 100644 --- a/src/ethereum_test_tools/tests/test_reference_spec.py +++ b/src/ethereum_test_base_types/tests/test_reference_spec.py @@ -1,5 +1,5 @@ """ -Test suite for `ethereum_test_tools.common.reference_spec` module. +Test suite for `ethereum_test_base_types.reference_spec` module. """ # import pytest diff --git a/src/ethereum_test_tools/exceptions/__init__.py b/src/ethereum_test_exceptions/__init__.py similarity index 89% rename from src/ethereum_test_tools/exceptions/__init__.py rename to src/ethereum_test_exceptions/__init__.py index 377677dfcb..fbe45d2962 100644 --- a/src/ethereum_test_tools/exceptions/__init__.py +++ b/src/ethereum_test_exceptions/__init__.py @@ -2,6 +2,7 @@ Exceptions for invalid execution. """ +from .engine_api import EngineAPIError from .evmone_exceptions import EvmoneExceptionMapper from .exceptions import ( BlockException, @@ -15,6 +16,7 @@ __all__ = [ "BlockException", "BlockExceptionInstanceOrList", + "EngineAPIError", "EOFException", "ExceptionInstanceOrList", "TransactionException", diff --git a/src/ethereum_test_exceptions/engine_api.py b/src/ethereum_test_exceptions/engine_api.py new file mode 100644 index 0000000000..e736a4606a --- /dev/null +++ b/src/ethereum_test_exceptions/engine_api.py @@ -0,0 +1,23 @@ +""" +Engine API error defniitions +""" + +from enum import IntEnum + + +class EngineAPIError(IntEnum): + """ + List of Engine API errors + """ + + ParseError = -32700 + InvalidRequest = -32600 + MethodNotFound = -32601 + InvalidParams = -32602 + InternalError = -32603 + ServerError = -32000 + UnknownPayload = -38001 + InvalidForkchoiceState = -38002 + InvalidPayloadAttributes = -38003 + TooLargeRequest = -38004 + UnsupportedFork = -38005 diff --git a/src/ethereum_test_tools/exceptions/evmone_exceptions.py b/src/ethereum_test_exceptions/evmone_exceptions.py similarity index 100% rename from src/ethereum_test_tools/exceptions/evmone_exceptions.py rename to src/ethereum_test_exceptions/evmone_exceptions.py diff --git a/src/ethereum_test_tools/exceptions/exceptions.py b/src/ethereum_test_exceptions/exceptions.py similarity index 100% rename from src/ethereum_test_tools/exceptions/exceptions.py rename to src/ethereum_test_exceptions/exceptions.py diff --git a/src/ethereum_test_exceptions/py.typed b/src/ethereum_test_exceptions/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ethereum_test_exceptions/tests/__init__.py b/src/ethereum_test_exceptions/tests/__init__.py new file mode 100644 index 0000000000..2f43d06b52 --- /dev/null +++ b/src/ethereum_test_exceptions/tests/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for the ethereum_test_exceptions package. +""" diff --git a/src/ethereum_test_tools/tests/test_exceptions.py b/src/ethereum_test_exceptions/tests/test_exceptions.py similarity index 98% rename from src/ethereum_test_tools/tests/test_exceptions.py rename to src/ethereum_test_exceptions/tests/test_exceptions.py index 613125efda..1a4dcc7de4 100644 --- a/src/ethereum_test_tools/tests/test_exceptions.py +++ b/src/ethereum_test_exceptions/tests/test_exceptions.py @@ -1,5 +1,5 @@ """ -Test suite for ethereum_test_tools.exceptions +Test suite for ethereum_test_exceptions module. """ import pytest diff --git a/src/ethereum_test_fixtures/__init__.py b/src/ethereum_test_fixtures/__init__.py new file mode 100644 index 0000000000..2add0d2489 --- /dev/null +++ b/src/ethereum_test_fixtures/__init__.py @@ -0,0 +1,33 @@ +""" +Ethereum test fixture format definitions. +""" + +from typing import List, Type + +from .base import BaseFixture +from .blockchain import Fixture as BlockchainFixture +from .blockchain import HiveFixture as BlockchainHiveFixture +from .collector import FixtureCollector, TestInfo +from .eof import Fixture as EOFFixture +from .formats import FixtureFormats +from .state import Fixture as StateFixture +from .verify import FixtureVerifier + +FIXTURE_TYPES: List[Type[BaseFixture]] = [ + BlockchainFixture, + BlockchainHiveFixture, + EOFFixture, + StateFixture, +] +__all__ = [ + "FIXTURE_TYPES", + "BaseFixture", + "BlockchainFixture", + "BlockchainHiveFixture", + "EOFFixture", + "FixtureCollector", + "FixtureFormats", + "FixtureVerifier", + "StateFixture", + "TestInfo", +] diff --git a/src/ethereum_test_fixtures/base.py b/src/ethereum_test_fixtures/base.py new file mode 100644 index 0000000000..a512997ce0 --- /dev/null +++ b/src/ethereum_test_fixtures/base.py @@ -0,0 +1,71 @@ +""" +Base fixture definitions used to define all fixture types. +""" + +import hashlib +import json +from functools import cached_property +from typing import Any, ClassVar, Dict + +from pydantic import Field + +from ethereum_test_base_types import CamelModel, ReferenceSpec + +from .formats import FixtureFormats + + +class BaseFixture(CamelModel): + """Represents a base Ethereum test fixture of any type.""" + + info: Dict[str, str] = Field(default_factory=dict, alias="_info") + format: ClassVar[FixtureFormats] = FixtureFormats.UNSET_TEST_FORMAT + + @cached_property + def json_dict(self) -> Dict[str, Any]: + """ + Returns the JSON representation of the fixture. + """ + return self.model_dump(mode="json", by_alias=True, exclude_none=True, exclude={"info"}) + + @cached_property + def hash(self) -> str: + """ + Returns the hash of the fixture. + """ + json_str = json.dumps(self.json_dict, sort_keys=True, separators=(",", ":")) + h = hashlib.sha256(json_str.encode("utf-8")).hexdigest() + return f"0x{h}" + + def json_dict_with_info(self, hash_only: bool = False) -> Dict[str, Any]: + """ + Returns the JSON representation of the fixture with the info field. + """ + dict_with_info = self.json_dict.copy() + dict_with_info["_info"] = {"hash": self.hash} + if not hash_only: + dict_with_info["_info"].update(self.info) + return dict_with_info + + def fill_info( + self, + t8n_version: str, + fixture_description: str, + fixture_source_url: str, + ref_spec: ReferenceSpec | None, + ): + """ + Fill the info field for this fixture + """ + if "comment" not in self.info: + self.info["comment"] = "`execution-spec-tests` generated test" + self.info["filling-transition-tool"] = t8n_version + self.info["description"] = fixture_description + self.info["url"] = fixture_source_url + if ref_spec is not None: + ref_spec.write_info(self.info) + + def get_fork(self) -> str: + """ + Returns the fork of the fixture as a string. + """ + raise NotImplementedError diff --git a/src/ethereum_test_tools/spec/blockchain/types.py b/src/ethereum_test_fixtures/blockchain.py similarity index 62% rename from src/ethereum_test_tools/spec/blockchain/types.py rename to src/ethereum_test_fixtures/blockchain.py index 41dda76238..fb2504aee4 100644 --- a/src/ethereum_test_tools/spec/blockchain/types.py +++ b/src/ethereum_test_fixtures/blockchain.py @@ -3,51 +3,31 @@ """ from functools import cached_property -from typing import ( - Annotated, - Any, - ClassVar, - Dict, - List, - Literal, - Optional, - get_args, - get_type_hints, -) +from typing import Annotated, Any, ClassVar, List, Literal, Optional, get_args, get_type_hints from ethereum import rlp as eth_rlp from ethereum.base_types import Uint from ethereum.crypto.hash import keccak256 -from pydantic import ( - AliasChoices, - ConfigDict, - Field, - PlainSerializer, - computed_field, - field_validator, -) +from pydantic import AliasChoices, Field, PlainSerializer, computed_field -from ethereum_test_forks import Fork -from evm_transition_tool import FixtureFormats - -from ...common.base_types import ( +from ethereum_test_base_types import ( Address, + Alloc, Bloom, Bytes, + CamelModel, + EmptyOmmersRoot, Hash, HeaderNonce, HexNumber, Number, ZeroPaddedHexNumber, ) -from ...common.constants import EmptyOmmersRoot, EngineAPIError -from ...common.types import ( - Alloc, - CamelModel, +from ethereum_test_exceptions import EngineAPIError, ExceptionInstanceOrList +from ethereum_test_forks import Fork +from ethereum_test_types.types import ( DepositRequest, DepositRequestGeneric, - Environment, - Removable, Requests, Transaction, TransactionFixtureConverter, @@ -57,88 +37,9 @@ WithdrawalRequest, WithdrawalRequestGeneric, ) -from ...exceptions import BlockException, ExceptionInstanceOrList, TransactionException -from ..base.base_test import BaseFixture - -class Header(CamelModel): - """ - Header type used to describe block header properties in test specs. - """ - - parent_hash: Hash | None = None - ommers_hash: Hash | None = None - fee_recipient: Address | None = None - state_root: Hash | None = None - transactions_trie: Hash | None = None - receipts_root: Hash | None = None - logs_bloom: Bloom | None = None - difficulty: HexNumber | None = None - number: HexNumber | None = None - gas_limit: HexNumber | None = None - gas_used: HexNumber | None = None - timestamp: HexNumber | None = None - extra_data: Bytes | None = None - prev_randao: Hash | None = None - nonce: HeaderNonce | None = None - base_fee_per_gas: Removable | HexNumber | None = None - withdrawals_root: Removable | Hash | None = None - blob_gas_used: Removable | HexNumber | None = None - excess_blob_gas: Removable | HexNumber | None = None - parent_beacon_block_root: Removable | Hash | None = None - requests_root: Removable | Hash | None = None - - REMOVE_FIELD: ClassVar[Removable] = Removable() - """ - Sentinel object used to specify that a header field should be removed. - """ - EMPTY_FIELD: ClassVar[Removable] = Removable() - """ - Sentinel object used to specify that a header field must be empty during verification. - - This can be used in a test to explicitly skip a field in a block's RLP encoding. - included in the (json) output when the model is serialized. For example: - ``` - header_modifier = Header( - excess_blob_gas=Header.REMOVE_FIELD, - ) - block = Block( - timestamp=TIMESTAMP, - rlp_modifier=header_modifier, - exception=BlockException.INCORRECT_BLOCK_FORMAT, - engine_api_error_code=EngineAPIError.InvalidParams, - ) - ``` - """ - - model_config = ConfigDict( - arbitrary_types_allowed=True, - # explicitly set Removable items to None so they are not included in the serialization - # (in combination with exclude_None=True in model.dump()). - json_encoders={ - Removable: lambda x: None, - }, - ) - - @field_validator("withdrawals_root", mode="before") - @classmethod - def validate_withdrawals_root(cls, value): - """ - Helper validator to convert a list of withdrawals into the withdrawals root hash. - """ - if isinstance(value, list): - return Withdrawal.list_root(value) - return value - - @field_validator("requests_root", mode="before") - @classmethod - def validate_requests_root(cls, value): - """ - Helper validator to convert a list of requests into the requests root hash. - """ - if isinstance(value, list): - return Requests(root=value).trie_root - return value +from .base import BaseFixture +from .formats import FixtureFormats class HeaderForkRequirement(str): @@ -280,134 +181,6 @@ def block_hash(self) -> Hash: """ return Hash(keccak256(self.rlp)) - def join(self, modifier: Header) -> "FixtureHeader": - """ - Produces a fixture header copy with the set values from the modifier. - """ - return self.copy( - **{ - k: (v if v is not Header.REMOVE_FIELD else None) - for k, v in modifier.model_dump(exclude_none=True).items() - } - ) - - def verify(self, baseline: Header): - """ - Verifies that the header fields from the baseline are as expected. - """ - for field_name in baseline.model_fields: - baseline_value = getattr(baseline, field_name) - if baseline_value is not None: - assert baseline_value is not Header.REMOVE_FIELD, "invalid baseline header" - value = getattr(self, field_name) - if baseline_value is Header.EMPTY_FIELD: - assert ( - value is None - ), f"invalid header field {field_name}, got {value}, want None" - continue - assert value == baseline_value, ( - f"invalid header field ({field_name}) value, " - + f"got {value}, want {baseline_value}" - ) - - -class Block(Header): - """ - Block type used to describe block properties in test specs - """ - - rlp: Bytes | None = None - """ - If set, blockchain test will skip generating the block and will pass this value directly to - the Fixture. - - Only meant to be used to simulate blocks with bad formats, and therefore - requires the block to produce an exception. - """ - header_verify: Header | None = None - """ - If set, the block header will be verified against the specified values. - """ - rlp_modifier: Header | None = None - """ - An RLP modifying header which values would be used to override the ones - returned by the `evm_transition_tool`. - """ - exception: List[ - TransactionException | BlockException - ] | TransactionException | BlockException | None = None - """ - If set, the block is expected to be rejected by the client. - """ - engine_api_error_code: EngineAPIError | None = None - """ - If set, the block is expected to produce an error response from the Engine API. - """ - txs: List[Transaction] = Field(default_factory=list) - """ - List of transactions included in the block. - """ - ommers: List[Header] | None = None - """ - List of ommer headers included in the block. - """ - withdrawals: List[Withdrawal] | None = None - """ - List of withdrawals to perform for this block. - """ - requests: List[DepositRequest | WithdrawalRequest] | None = None - """ - Custom list of requests to embed in this block. - """ - - def set_environment(self, env: Environment) -> Environment: - """ - Creates a copy of the environment with the characteristics of this - specific block. - """ - new_env_values: Dict[str, Any] = {} - - """ - Values that need to be set in the environment and are `None` for - this block need to be set to their defaults. - """ - new_env_values["difficulty"] = self.difficulty - new_env_values["fee_recipient"] = ( - self.fee_recipient if self.fee_recipient is not None else Environment().fee_recipient - ) - new_env_values["gas_limit"] = ( - self.gas_limit or env.parent_gas_limit or Environment().gas_limit - ) - if not isinstance(self.base_fee_per_gas, Removable): - new_env_values["base_fee_per_gas"] = self.base_fee_per_gas - new_env_values["withdrawals"] = self.withdrawals - if not isinstance(self.excess_blob_gas, Removable): - new_env_values["excess_blob_gas"] = self.excess_blob_gas - if not isinstance(self.blob_gas_used, Removable): - new_env_values["blob_gas_used"] = self.blob_gas_used - if not isinstance(self.parent_beacon_block_root, Removable): - new_env_values["parent_beacon_block_root"] = self.parent_beacon_block_root - """ - These values are required, but they depend on the previous environment, - so they can be calculated here. - """ - if self.number is not None: - new_env_values["number"] = self.number - else: - # calculate the next block number for the environment - if len(env.block_hashes) == 0: - new_env_values["number"] = 0 - else: - new_env_values["number"] = max([Number(n) for n in env.block_hashes.keys()]) + 1 - - if self.timestamp is not None: - new_env_values["timestamp"] = self.timestamp - else: - assert env.parent_timestamp is not None - new_env_values["timestamp"] = int(Number(env.parent_timestamp) + 12) - - return env.copy(**new_env_values) - class FixtureExecutionPayload(CamelModel): """ diff --git a/src/ethereum_test_tools/spec/fixture_collector.py b/src/ethereum_test_fixtures/collector.py similarity index 96% rename from src/ethereum_test_tools/spec/fixture_collector.py rename to src/ethereum_test_fixtures/collector.py index 25a8d5277c..112a1033a6 100644 --- a/src/ethereum_test_tools/spec/fixture_collector.py +++ b/src/ethereum_test_fixtures/collector.py @@ -11,11 +11,12 @@ from pathlib import Path from typing import Dict, Literal, Optional, Tuple -from evm_transition_tool import FixtureFormats, TransitionTool +from ethereum_test_base_types import to_json -from ..common.json import to_json -from .base.base_test import BaseFixture -from .file.types import Fixtures +from .base import BaseFixture +from .file import Fixtures +from .formats import FixtureFormats +from .verify import FixtureVerifier def strip_test_prefix(name: str) -> str: @@ -166,7 +167,7 @@ def dump_fixtures(self) -> None: raise TypeError("All fixtures in a single file must have the same format.") fixtures.collect_into_file(fixture_path) - def verify_fixture_files(self, evm_fixture_verification: TransitionTool) -> None: + def verify_fixture_files(self, evm_fixture_verification: FixtureVerifier) -> None: """ Runs `evm [state|block]test` on each fixture. """ diff --git a/src/ethereum_test_tools/spec/consume/types.py b/src/ethereum_test_fixtures/consume.py similarity index 94% rename from src/ethereum_test_tools/spec/consume/types.py rename to src/ethereum_test_fixtures/consume.py index b246dc2134..5e15d2f5e1 100644 --- a/src/ethereum_test_tools/spec/consume/types.py +++ b/src/ethereum_test_fixtures/consume.py @@ -9,12 +9,12 @@ from pydantic import BaseModel, RootModel -from evm_transition_tool import FixtureFormats +from ethereum_test_base_types import HexNumber -from ...common.base_types import HexNumber -from ..blockchain.types import Fixture as BlockchainFixture -from ..file.types import Fixtures -from ..state.types import Fixture as StateFixture +from .blockchain import Fixture as BlockchainFixture +from .file import Fixtures +from .formats import FixtureFormats +from .state import Fixture as StateFixture class TestCaseBase(BaseModel): diff --git a/src/ethereum_test_tools/spec/eof/types.py b/src/ethereum_test_fixtures/eof.py similarity index 81% rename from src/ethereum_test_tools/spec/eof/types.py rename to src/ethereum_test_fixtures/eof.py index 7d6d9e9bcb..38035a0a24 100644 --- a/src/ethereum_test_tools/spec/eof/types.py +++ b/src/ethereum_test_fixtures/eof.py @@ -7,13 +7,12 @@ from pydantic import Field -from evm_transition_tool import FixtureFormats +from ethereum_test_base_types import Bytes, CamelModel, Number +from ethereum_test_exceptions import EOFException +from ethereum_test_types.eof.v1 import ContainerKind -from ...common.base_types import Bytes, Number -from ...common.types import CamelModel -from ...eof.v1 import ContainerKind -from ...exceptions import EOFException -from ..base.base_test import BaseFixture +from .base import BaseFixture +from .formats import FixtureFormats class Result(CamelModel): diff --git a/src/ethereum_test_tools/spec/file/types.py b/src/ethereum_test_fixtures/file.py similarity index 95% rename from src/ethereum_test_tools/spec/file/types.py rename to src/ethereum_test_fixtures/file.py index 608d94ab09..3ebba6b7f2 100644 --- a/src/ethereum_test_tools/spec/file/types.py +++ b/src/ethereum_test_fixtures/file.py @@ -7,11 +7,10 @@ from pydantic import RootModel -from evm_transition_tool import FixtureFormats - -from ..blockchain.types import Fixture as BlockchainFixture -from ..blockchain.types import HiveFixture as BlockchainHiveFixture -from ..state.types import Fixture as StateFixture +from .blockchain import Fixture as BlockchainFixture +from .blockchain import HiveFixture as BlockchainHiveFixture +from .formats import FixtureFormats +from .state import Fixture as StateFixture FixtureFormatsValues = Literal[ "blockchain_test_hive", "blockchain_test", "state_test", "unset_test_format" diff --git a/src/ethereum_test_fixtures/formats.py b/src/ethereum_test_fixtures/formats.py new file mode 100644 index 0000000000..22c65fa75b --- /dev/null +++ b/src/ethereum_test_fixtures/formats.py @@ -0,0 +1,72 @@ +""" +Fixture formats enum. +""" +from enum import Enum +from pathlib import Path + + +class FixtureFormats(Enum): + """ + Helper class to define fixture formats. + """ + + UNSET_TEST_FORMAT = "unset_test_format" + STATE_TEST = "state_test" + BLOCKCHAIN_TEST = "blockchain_test" + BLOCKCHAIN_TEST_HIVE = "blockchain_test_hive" + EOF_TEST = "eof_test" + + @classmethod + def is_state_test(cls, format): # noqa: D102 + return format == cls.STATE_TEST + + @classmethod + def is_blockchain_test(cls, format): # noqa: D102 + return format in (cls.BLOCKCHAIN_TEST, cls.BLOCKCHAIN_TEST_HIVE) + + @classmethod + def is_hive_format(cls, format): # noqa: D102 + return format == cls.BLOCKCHAIN_TEST_HIVE + + @classmethod + def is_standard_format(cls, format): # noqa: D102 + return format in (cls.STATE_TEST, cls.BLOCKCHAIN_TEST) + + @classmethod + def is_verifiable(cls, format): # noqa: D102 + return format in (cls.STATE_TEST, cls.BLOCKCHAIN_TEST) + + @classmethod + def get_format_description(cls, format): + """ + Returns a description of the fixture format. + + Used to add a description to the generated pytest marks. + """ + if format == cls.UNSET_TEST_FORMAT: + return "Unknown fixture format; it has not been set." + elif format == cls.STATE_TEST: + return "Tests that generate a state test fixture." + elif format == cls.BLOCKCHAIN_TEST: + return "Tests that generate a blockchain test fixture." + elif format == cls.BLOCKCHAIN_TEST_HIVE: + return "Tests that generate a blockchain test fixture in hive format." + elif format == cls.EOF_TEST: + return "Tests that generate an EOF test fixture." + raise Exception(f"Unknown fixture format: {format}.") + + @property + def output_base_dir_name(self) -> Path: + """ + Returns the name of the subdirectory where this type of fixture should be dumped to. + """ + return Path(self.value.replace("test", "tests")) + + @property + def output_file_extension(self) -> str: + """ + Returns the file extension for this type of fixture. + + By default, fixtures are dumped as JSON files. + """ + return ".json" diff --git a/src/ethereum_test_fixtures/py.typed b/src/ethereum_test_fixtures/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ethereum_test_tools/spec/state/types.py b/src/ethereum_test_fixtures/state.py similarity index 91% rename from src/ethereum_test_tools/spec/state/types.py rename to src/ethereum_test_fixtures/state.py index bd4de25974..514af9c8c7 100644 --- a/src/ethereum_test_tools/spec/state/types.py +++ b/src/ethereum_test_fixtures/state.py @@ -6,19 +6,18 @@ from pydantic import BaseModel, Field -from evm_transition_tool import FixtureFormats - -from ...common.base_types import Address, Bytes, Hash, ZeroPaddedHexNumber -from ...common.types import ( +from ethereum_test_base_types import Address, Alloc, Bytes, Hash, ZeroPaddedHexNumber +from ethereum_test_exceptions import TransactionExceptionInstanceOrList +from ethereum_test_types.types import ( AccessList, - Alloc, CamelModel, EnvironmentGeneric, Transaction, TransactionFixtureConverter, ) -from ...exceptions import TransactionExceptionInstanceOrList -from ..base.base_test import BaseFixture + +from .base import BaseFixture +from .formats import FixtureFormats class FixtureEnvironment(EnvironmentGeneric[ZeroPaddedHexNumber]): diff --git a/src/ethereum_test_fixtures/tests/__init__.py b/src/ethereum_test_fixtures/tests/__init__.py new file mode 100644 index 0000000000..b5221f0e20 --- /dev/null +++ b/src/ethereum_test_fixtures/tests/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for the ethereum_test_fixtures package. +""" diff --git a/src/ethereum_test_tools/tests/test_spec_base.py b/src/ethereum_test_fixtures/tests/test_base.py similarity index 71% rename from src/ethereum_test_tools/tests/test_spec_base.py rename to src/ethereum_test_fixtures/tests/test_base.py index 7ae99656c8..999ea370ac 100644 --- a/src/ethereum_test_tools/tests/test_spec_base.py +++ b/src/ethereum_test_fixtures/tests/test_base.py @@ -1,8 +1,8 @@ """ -Test cases for the ethereum_test_tools.spec.base. +Test cases for the ethereum_test_fixtures.base module. """ -from ..spec.base.base_test import BaseFixture +from ..base import BaseFixture def test_json_dict(): diff --git a/src/ethereum_test_tools/tests/test_types.py b/src/ethereum_test_fixtures/tests/test_blockchain.py similarity index 52% rename from src/ethereum_test_tools/tests/test_types.py rename to src/ethereum_test_fixtures/tests/test_blockchain.py index 154d80afaf..f28047e2ed 100644 --- a/src/ethereum_test_tools/tests/test_types.py +++ b/src/ethereum_test_fixtures/tests/test_blockchain.py @@ -1,28 +1,24 @@ """ -Test suite for `ethereum_test` module. +Test the blockchain test types. """ -from typing import Any, Dict, List +from typing import Any, Dict import pytest -from pydantic import TypeAdapter -from ..common import ( - AccessList, - Account, - EngineAPIError, - Environment, - Storage, - Transaction, - Withdrawal, +from ethereum_test_base_types import ( + Address, + Bloom, + Bytes, + Hash, + HeaderNonce, + ZeroPaddedHexNumber, + to_json, ) -from ..common.base_types import Address, Bloom, Bytes, Hash, HeaderNonce, ZeroPaddedHexNumber -from ..common.constants import TestAddress, TestAddress2, TestPrivateKey -from ..common.json import to_json -from ..common.types import Alloc, CopyValidateModel, DepositRequest, Requests -from ..eof.v1 import Container -from ..exceptions import BlockException, TransactionException -from ..spec.blockchain.types import ( +from ethereum_test_exceptions import BlockException, EngineAPIError, TransactionException +from ethereum_test_types import AccessList, Transaction, Withdrawal + +from ..blockchain import ( FixtureBlockBase, FixtureEngineNewPayload, FixtureExecutionPayload, @@ -30,652 +26,34 @@ FixtureTransaction, InvalidFixtureBlock, ) -from ..spec.state.types import FixtureForkPost -from ..vm.opcode import Opcodes as Op - - -def test_storage(): - """ - Test `ethereum_test.types.storage` parsing. - """ - s = Storage({"10": "0x10"}) - - assert 10 in s - assert s[10] == 16 - - s = Storage({"10": "10"}) - - assert 10 in s - assert s[10] == 10 - - s = Storage({10: 10}) - - assert 10 in s - assert s[10] == 10 - - iter_s = iter(Storage({10: 20, "11": "21"})) - assert next(iter_s) == 10 - assert next(iter_s) == 11 - - s["10"] = "0x10" - s["0x10"] = "10" - assert s[10] == 16 - assert s[16] == 10 - - assert "10" in s - assert "0xa" in s - assert 10 in s - - del s[10] - assert "10" not in s - assert "0xa" not in s - assert 10 not in s - - s = Storage({-1: -1, -2: -2}) - assert s[-1] == 2**256 - 1 - assert s[-2] == 2**256 - 2 - d = to_json(s) - assert ( - d["0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"] - == "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ) - assert ( - d["0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"] - == "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" - ) - # Try to add a duplicate key (negative and positive number at the same - # time) - # same value, ok - s[2**256 - 1] = 2**256 - 1 - to_json(s) - - # Check store counter - s = Storage({}) - s.store_next(0x100) - s.store_next("0x200") - s.store_next(b"\x03\x00".rjust(32, b"\x00")) - d = to_json(s) - assert d == { - "0x00": ("0x0100"), - "0x01": ("0x0200"), - "0x02": ("0x0300"), - } - - -@pytest.mark.parametrize( - ["account"], - [ - pytest.param( - Account(), - id="no_fields", - ), - pytest.param( - Account( - nonce=0, - ), - id="zero_nonce", - ), - pytest.param( - Account( - balance=0, - ), - id="zero_balance", - ), - pytest.param( - Account( - code="", - ), - id="empty_code", - ), - pytest.param( - Account( - storage={}, - ), - id="empty_storage", - ), - pytest.param( - Account( - nonce=0, - balance=0, - code="", - storage={ - 1: 0, - }, - ), - id="only_zero_storage_values", - ), - ], -) -def test_empty_accounts(account: Account): - """ - Test `ethereum_test.types.account` parsing. - """ - assert not bool(account) - - -@pytest.mark.parametrize( - ["account", "alloc_dict", "should_pass"], - [ - # All None: Pass - ( - Account(), - {"nonce": "1", "code": "0x123", "balance": "1", "storage": {0: 1}}, - True, - ), - # Storage must be empty: Fail - ( - Account(storage={}), - {"nonce": "1", "code": "0x123", "balance": "1", "storage": {0: 1}}, - False, - ), - # Storage must be empty: Pass - ( - Account(storage={}), - {"nonce": "1", "code": "0x123", "balance": "1", "storage": {}}, - True, - ), - # Storage must be empty: Pass - ( - Account(storage={}), - { - "nonce": "1", - "code": "0x123", - "balance": "1", - "storage": {0: 0, 1: 0}, - }, - True, - ), - # Storage must be empty: Pass - ( - Account(storage={0: 0}), - { - "nonce": "1", - "code": "0x123", - "balance": "1", - "storage": {}, - }, - True, - ), - # Storage must not be empty: Pass - ( - Account(storage={1: 1}), - { - "nonce": "1", - "code": "0x123", - "balance": "1", - "storage": {0: 0, 1: 1}, - }, - True, - ), - # Storage must not be empty: Fail - ( - Account(storage={1: 1}), - { - "nonce": "1", - "code": "0x123", - "balance": "1", - "storage": {0: 0, 1: 1, 2: 2}, - }, - False, - ), - # Code must be empty: Fail - ( - Account(code=""), - { - "nonce": "0", - "code": "0x123", - "balance": "0", - "storage": {}, - }, - False, - ), - # Code must be empty: Pass - ( - Account(code=""), - { - "nonce": "1", - "code": "0x", - "balance": "1", - "storage": {0: 0, 1: 1}, - }, - True, - ), - # Nonce must be empty: Fail - ( - Account(nonce=0), - { - "nonce": "1", - "code": "0x", - "balance": "0", - "storage": {}, - }, - False, - ), - # Nonce must be empty: Pass - ( - Account(nonce=0), - { - "nonce": "0", - "code": "0x1234", - "balance": "1", - "storage": {0: 0, 1: 1}, - }, - True, - ), - # Nonce must not be empty: Fail - ( - Account(nonce=1), - { - "code": "0x1234", - "balance": "1", - "storage": {0: 0, 1: 1}, - }, - False, - ), - # Nonce must not be empty: Pass - ( - Account(nonce=1), - { - "nonce": "1", - "code": "0x", - "balance": "0", - "storage": {}, - }, - True, - ), - # Balance must be empty: Fail - ( - Account(balance=0), - { - "nonce": "0", - "code": "0x", - "balance": "1", - "storage": {}, - }, - False, - ), - # Balance must be empty: Pass - ( - Account(balance=0), - { - "nonce": "1", - "code": "0x1234", - "balance": "0", - "storage": {0: 0, 1: 1}, - }, - True, - ), - # Balance must not be empty: Fail - ( - Account(balance=1), - { - "nonce": "1", - "code": "0x1234", - "storage": {0: 0, 1: 1}, - }, - False, - ), - # Balance must not be empty: Pass - ( - Account(balance=1), - { - "nonce": "0", - "code": "0x", - "balance": "1", - "storage": {}, - }, - True, - ), - ], -) -def test_account_check_alloc(account: Account, alloc_dict: Dict[Any, Any], should_pass: bool): - """ - Test `Account.check_alloc` method. - """ - alloc_account = Account(**alloc_dict) - if should_pass: - account.check_alloc(Address(1), alloc_account) - else: - with pytest.raises(Exception) as _: - account.check_alloc(Address(1), alloc_account) - - -@pytest.mark.parametrize( - ["alloc_1", "alloc_2", "expected_alloc"], - [ - pytest.param( - Alloc(), - Alloc(), - Alloc(), - id="empty_alloc", - ), - pytest.param( - Alloc({0x1: {"nonce": 1}}), # type: ignore - Alloc({0x2: {"nonce": 2}}), # type: ignore - Alloc({0x1: Account(nonce=1), 0x2: Account(nonce=2)}), # type: ignore - id="alloc_different_accounts", - ), - pytest.param( - Alloc({0x2: {"nonce": 1}}), # type: ignore - Alloc({"0x02": {"nonce": 2}}), # type: ignore - Alloc({0x2: Account(nonce=2)}), # type: ignore - id="overwrite_account", - ), - pytest.param( - Alloc({0x2: {"balance": 1}}), # type: ignore - Alloc({"0x02": {"nonce": 1}}), # type: ignore - Alloc({0x2: Account(balance=1, nonce=1)}), # type: ignore - id="mix_account", - ), - ], -) -def test_alloc_append(alloc_1: Alloc, alloc_2: Alloc, expected_alloc: Alloc): - """ - Test `ethereum_test.types.alloc` merging. - """ - assert Alloc.merge(alloc_1, alloc_2) == expected_alloc - - -def test_alloc_deploy_contract(): - """ - Test `Alloc.deploy_contract` functionallity. - """ - alloc = Alloc() - contract_1 = alloc.deploy_contract(Op.SSTORE(0, 1) + Op.STOP) - contract_2 = alloc.deploy_contract(Op.SSTORE(0, 2) + Op.STOP) - assert contract_1 != contract_2 - assert contract_1 in alloc - assert contract_2 in alloc - assert alloc[contract_1].code == bytes.fromhex("600160005500") - assert alloc[contract_2].code == bytes.fromhex("600260005500") - - -def test_alloc_fund_sender(): - """ - Test `Alloc.fund_eoa` functionallity. - """ - alloc = Alloc() - sender_1 = alloc.fund_eoa(10**18) - sender_2 = alloc.fund_eoa(10**18) - assert sender_1 != sender_2 - assert sender_1 in alloc - assert sender_2 in alloc - assert Address(sender_1) == TestAddress - assert Address(sender_2) == TestAddress2 - assert alloc[sender_1].balance == 10**18 - assert alloc[sender_2].balance == 10**18 - -@pytest.mark.parametrize( - ["account_1", "account_2", "expected_account"], - [ - pytest.param( - Account(), - Account(), - Account(), - id="empty_accounts", - ), - pytest.param( - None, - None, - Account(), - id="none_accounts", - ), - pytest.param( - Account(nonce=1), - Account(code="0x6000"), - Account(nonce=1, code="0x6000"), - id="accounts_with_different_fields", - ), - pytest.param( - Account(nonce=1), - Account(nonce=2), - Account(nonce=2), - id="accounts_with_different_nonce", - ), - ], +fixture_header_ones = FixtureHeader( + parent_hash=Hash(1), + ommers_hash=Hash(1), + fee_recipient=Address(1), + state_root=Hash(1), + transactions_trie=Hash(1), + receipts_root=Hash(1), + logs_bloom=Bloom(1), + difficulty=1, + number=1, + gas_limit=1, + gas_used=1, + timestamp=1, + extra_data=Bytes([1]), + prev_randao=Hash(1), + nonce=HeaderNonce(1), + base_fee_per_gas=1, + withdrawals_root=Hash(1), + blob_gas_used=1, + excess_blob_gas=1, + # hash=Hash(1), ) -def test_account_merge( - account_1: Account | None, account_2: Account | None, expected_account: Account -): - """ - Test `ethereum_test.types.account` merging. - """ - assert Account.merge(account_1, account_2) == expected_account - - -CHECKSUM_ADDRESS = "0x8a0A19589531694250d570040a0c4B74576919B8" @pytest.mark.parametrize( ["can_be_deserialized", "model_instance", "json"], [ - pytest.param( - True, - Address(CHECKSUM_ADDRESS), - CHECKSUM_ADDRESS, - marks=pytest.mark.xfail, - id="address_with_checksum_address", - ), - pytest.param( - True, - Account(), - { - "nonce": "0x00", - "balance": "0x00", - "code": "0x", - "storage": {}, - }, - id="account_1", - ), - pytest.param( - True, - Account( - nonce=1, - balance=2, - code="0x1234", - storage={ - 0: 0, - 1: 1, - }, - ), - { - "nonce": "0x01", - "balance": "0x02", - "code": "0x1234", - "storage": { - "0x00": "0x00", - "0x01": "0x01", - }, - }, - id="account_2", - ), - pytest.param( - True, - AccessList( - address=0x1234, - storage_keys=[0, 1], - ), - { - "address": "0x0000000000000000000000000000000000001234", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - }, - id="access_list", - ), - pytest.param( - True, - Withdrawal(index=0, validator_index=1, address=0x1234, amount=2), - { - "index": "0x0", - "validatorIndex": "0x1", - "address": "0x0000000000000000000000000000000000001234", - "amount": "0x2", - }, - id="withdrawal", - ), - pytest.param( - True, - Environment(), - { - "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentGasLimit": "100000000000000000", - "currentNumber": "1", - "currentTimestamp": "1000", - "blockHashes": {}, - "ommers": [], - "parentUncleHash": ( - "0x0000000000000000000000000000000000000000000000000000000000000000" - ), - }, - id="environment_1", - ), - pytest.param( - True, - Environment( - fee_recipient=0x1234, - difficulty=0x5, - prev_randao=0x6, - base_fee_per_gas=0x7, - parent_difficulty=0x8, - parent_timestamp=0x9, - parent_base_fee_per_gas=0xA, - parent_gas_used=0xB, - parent_gas_limit=0xC, - parent_ommers_hash=0xD, - withdrawals=[Withdrawal(index=0, validator_index=1, address=0x1234, amount=2)], - parent_blob_gas_used=0xE, - parent_excess_blob_gas=0xF, - blob_gas_used=0x10, - excess_blob_gas=0x11, - block_hashes={1: 2, 3: 4}, - ), - { - "currentCoinbase": "0x0000000000000000000000000000000000001234", - "currentGasLimit": "100000000000000000", - "currentNumber": "1", - "currentTimestamp": "1000", - "currentDifficulty": "5", - "currentRandom": "6", - "currentBaseFee": "7", - "parentDifficulty": "8", - "parentTimestamp": "9", - "parentBaseFee": "10", - "parentGasUsed": "11", - "parentGasLimit": "12", - "parentUncleHash": ( - "0x000000000000000000000000000000000000000000000000000000000000000d" - ), - "withdrawals": [ - { - "index": "0x0", - "validatorIndex": "0x1", - "address": "0x0000000000000000000000000000000000001234", - "amount": "0x2", - }, - ], - "parentBlobGasUsed": "14", - "parentExcessBlobGas": "15", - "currentBlobGasUsed": "16", - "currentExcessBlobGas": "17", - "blockHashes": { - "1": "0x0000000000000000000000000000000000000000000000000000000000000002", - "3": "0x0000000000000000000000000000000000000000000000000000000000000004", - }, - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000004", - "ommers": [], - }, - id="environment_2", - ), - pytest.param( - True, - Transaction().with_signature_and_sender(), - { - "type": "0x0", - "chainId": "0x1", - "nonce": "0x0", - "to": "0x00000000000000000000000000000000000000aa", - "value": "0x0", - "input": "0x", - "gas": "0x5208", - "gasPrice": "0xa", - "v": "0x26", - "r": "0xcc61d852649c34cc0b71803115f38036ace257d2914f087bf885e6806a664fbd", - "s": "0x2020cb35f5d7731ab540d62614503a7f2344301a86342f67daf011c1341551ff", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - }, - id="transaction_t8n_default_args", - ), - pytest.param( - True, - Transaction( - to=None, - ).with_signature_and_sender(), - { - "type": "0x0", - "chainId": "0x1", - "nonce": "0x0", - "to": None, - "value": "0x0", - "input": "0x", - "gas": "0x5208", - "gasPrice": "0xa", - "v": "0x25", - "r": "0x1cfe2cbb0c3577f74d9ae192a7f1ee2d670fe806a040f427af9cb768be3d07ce", - "s": "0xcbe2d029f52dbf93ade486625bed0603945d2c7358b31de99fe8786c00f13da", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - }, - id="transaction_t8n_to_none", - ), - pytest.param( - True, - Transaction( - to=0x1234, - data=b"\x01\x00", - access_list=[ - AccessList( - address=0x1234, - storage_keys=[0, 1], - ) - ], - max_priority_fee_per_gas=10, - max_fee_per_gas=20, - max_fee_per_blob_gas=30, - blob_versioned_hashes=[0, 1], - ).with_signature_and_sender(), - { - "type": "0x3", - "chainId": "0x1", - "nonce": "0x0", - "to": "0x0000000000000000000000000000000000001234", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000001234", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - } - ], - "value": "0x0", - "input": "0x0100", - "gas": "0x5208", - "maxPriorityFeePerGas": "0xa", - "maxFeePerGas": "0x14", - "maxFeePerBlobGas": "0x1e", - "blobVersionedHashes": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - "v": "0x0", - "r": "0x418bb557c43262375f80556cb09dac5e67396acf0eaaf2c2540523d1ce54b280", - "s": "0x4fa36090ea68a1138043d943ced123c0b0807d82ff3342a6977cbc09230e927c", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - }, - id="transaction_3", - ), pytest.param( True, FixtureTransaction.from_transaction(Transaction().with_signature_and_sender()), @@ -1430,77 +808,6 @@ def test_account_merge( }, id="fixture_engine_new_payload_2", ), - pytest.param( - True, - FixtureForkPost( - state_root="0x00", - logs_hash="0x01", - tx_bytes="0x02", - ), - { - "hash": Hash(0).hex(), - "logs": Hash(1).hex(), - "txbytes": Bytes(b"\x02").hex(), - "indexes": {"data": 0, "gas": 0, "value": 0}, - }, - id="state_fixture_fork_post", - ), - pytest.param( - True, - FixtureForkPost( - state_root="0x00", - logs_hash="0x01", - tx_bytes="0x02", - expect_exception=TransactionException.INITCODE_SIZE_EXCEEDED, - ), - { - "hash": Hash(0).hex(), - "logs": Hash(1).hex(), - "txbytes": Bytes(b"\x02").hex(), - "expectException": "TransactionException.INITCODE_SIZE_EXCEEDED", - "indexes": {"data": 0, "gas": 0, "value": 0}, - }, - id="state_fixture_fork_post_exception", - ), - pytest.param( - False, # Can not be deserialized: A single expect_exception str will not be - # deserialized as a list and therefore will not match the model_instance definition. - FixtureForkPost( - state_root="0x00", - logs_hash="0x01", - tx_bytes="0x02", - expect_exception=[TransactionException.INITCODE_SIZE_EXCEEDED], - ), - { - "hash": Hash(0).hex(), - "logs": Hash(1).hex(), - "txbytes": Bytes(b"\x02").hex(), - "expectException": "TransactionException.INITCODE_SIZE_EXCEEDED", - "indexes": {"data": 0, "gas": 0, "value": 0}, - }, - id="state_fixture_fork_post_exception_list_1", - ), - pytest.param( - True, - FixtureForkPost( - state_root="0x00", - logs_hash="0x01", - tx_bytes="0x02", - expect_exception=[ - TransactionException.INITCODE_SIZE_EXCEEDED, - TransactionException.INSUFFICIENT_ACCOUNT_FUNDS, - ], - ), - { - "hash": Hash(0).hex(), - "logs": Hash(1).hex(), - "txbytes": Bytes(b"\x02").hex(), - "expectException": "TransactionException.INITCODE_SIZE_EXCEEDED|" - "TransactionException.INSUFFICIENT_ACCOUNT_FUNDS", - "indexes": {"data": 0, "gas": 0, "value": 0}, - }, - id="state_fixture_fork_post_exception_list_2", - ), ], ) class TestPydanticModelConversion: @@ -1526,229 +833,3 @@ def test_json_deserialization( pytest.skip(reason="The model instance in this case can not be deserialized") model_type = type(model_instance) assert model_type(**json) == model_instance - - -@pytest.mark.parametrize( - ["invalid_tx_args", "expected_exception", "expected_exception_substring"], - [ - pytest.param( - {"gas_price": 1, "max_fee_per_gas": 2}, - Transaction.InvalidFeePayment, - "only one type of fee payment field can be used", - id="gas-price-and-max-fee-per-gas", - ), - pytest.param( - {"gas_price": 1, "max_priority_fee_per_gas": 2}, - Transaction.InvalidFeePayment, - "only one type of fee payment field can be used", - id="gas-price-and-max-priority-fee-per-gas", - ), - pytest.param( - {"gas_price": 1, "max_fee_per_blob_gas": 2}, - Transaction.InvalidFeePayment, - "only one type of fee payment field can be used", - id="gas-price-and-max-fee-per-blob-gas", - ), - pytest.param( - {"ty": 0, "v": 1, "secret_key": 2}, - Transaction.InvalidSignaturePrivateKey, - "can't define both 'signature' and 'private_key'", - id="type0-signature-and-secret-key", - ), - ], -) -def test_transaction_post_init_invalid_arg_combinations( # noqa: D103 - invalid_tx_args, expected_exception, expected_exception_substring -): - """ - Test that Transaction.__post_init__ raises the expected exceptions for - invalid constructor argument combinations. - """ - with pytest.raises(expected_exception) as exc_info: - Transaction(**invalid_tx_args) - assert expected_exception_substring in str(exc_info.value) - - -@pytest.mark.parametrize( - ["tx_args", "expected_attributes_and_values"], - [ - pytest.param( - {"max_fee_per_blob_gas": 10}, - [ - ("ty", 3), - ], - id="max_fee_per_blob_gas-adds-ty-3", - ), - pytest.param( - {}, - [ - ("gas_price", 10), - ], - id="no-fees-adds-gas_price", - ), - pytest.param( - {}, - [ - ("secret_key", TestPrivateKey), - ], - id="no-signature-adds-secret_key", - ), - pytest.param( - {"max_fee_per_gas": 10}, - [ - ("ty", 2), - ], - id="max_fee_per_gas-adds-ty-2", - ), - pytest.param( - {"access_list": [AccessList(address=0x1234, storage_keys=[0, 1])]}, - [ - ("ty", 1), - ], - id="access_list-adds-ty-1", - ), - pytest.param( - {"ty": 1}, - [ - ("access_list", []), - ], - id="ty-1-adds-empty-access_list", - ), - pytest.param( - {"ty": 2}, - [ - ("max_priority_fee_per_gas", 0), - ], - id="ty-2-adds-max_priority_fee_per_gas", - ), - ], -) -def test_transaction_post_init_defaults(tx_args, expected_attributes_and_values): - """ - Test that Transaction.__post_init__ sets the expected default values for - missing fields. - """ - tx = Transaction(**tx_args) - for attr, val in expected_attributes_and_values: - assert hasattr(tx, attr) - assert getattr(tx, attr) == val - - -@pytest.mark.parametrize( - ["withdrawals", "expected_root"], - [ - pytest.param( - [], - bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), - id="empty-withdrawals", - ), - pytest.param( - [ - Withdrawal( - index=0, - validator_index=1, - address=0x1234, - amount=2, - ) - ], - bytes.fromhex("dc3ead883fc17ea3802cd0f8e362566b07b223f82e52f94c76cf420444b8ff81"), - id="single-withdrawal", - ), - pytest.param( - [ - Withdrawal( - index=0, - validator_index=1, - address=0x1234, - amount=2, - ), - Withdrawal( - index=1, - validator_index=2, - address=0xABCD, - amount=0, - ), - ], - bytes.fromhex("069ab71e5d228db9b916880f02670c85682c46641bb9c95df84acc5075669e01"), - id="multiple-withdrawals", - ), - pytest.param( - [ - Withdrawal( - index=0, - validator_index=0, - address=0x100, - amount=0, - ), - Withdrawal( - index=0, - validator_index=0, - address=0x200, - amount=0, - ), - ], - bytes.fromhex("daacd8fe889693f7d20436d9c0c044b5e92cc17b57e379997273fc67fd2eb7b8"), - id="multiple-withdrawals", - ), - ], -) -def test_withdrawals_root(withdrawals: List[Withdrawal], expected_root: bytes): - """ - Test that withdrawals_root returns the expected hash. - """ - assert Withdrawal.list_root(withdrawals) == expected_root - - -@pytest.mark.parametrize( - ["json_str", "type_adapter", "expected"], - [ - pytest.param( - """ - [ - { - "type": "0x0", - "pubkey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "withdrawalCredentials": "0x0000000000000000000000000000000000000000000000000000000000000002", - "amount": "0x1234", - "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", - "index": "0x5678" - } - ] - """, # noqa: E501 - TypeAdapter(Requests), - Requests( - root=[ - DepositRequest( - pubkey=1, - withdrawal_credentials=2, - amount=0x1234, - signature=3, - index=0x5678, - ), - ] - ), - id="requests_1", - ), - ], -) -def test_parsing(json_str: str, type_adapter: TypeAdapter, expected: Any): - """ - Test that parsing the given JSON string returns the expected object. - """ - assert type_adapter.validate_json(json_str) == expected - - -@pytest.mark.parametrize( - "model", - [ - Environment(), - Container(), - ], - ids=lambda model: model.__class__.__name__, -) -def test_model_copy(model: CopyValidateModel): - """ - Test that the copy method returns a correct copy of the model. - """ - assert to_json(model.copy()) == to_json(model) - assert model.copy().model_fields_set == model.model_fields_set diff --git a/src/ethereum_test_fixtures/tests/test_state.py b/src/ethereum_test_fixtures/tests/test_state.py new file mode 100644 index 0000000000..c7b4cb584f --- /dev/null +++ b/src/ethereum_test_fixtures/tests/test_state.py @@ -0,0 +1,113 @@ +""" +Test state spec types. +""" + +from typing import Any, Dict + +import pytest + +from ethereum_test_base_types import Bytes, Hash, to_json +from ethereum_test_exceptions import TransactionException + +from ..state import FixtureForkPost + + +@pytest.mark.parametrize( + ["can_be_deserialized", "model_instance", "json"], + [ + pytest.param( + True, + FixtureForkPost( + state_root="0x00", + logs_hash="0x01", + tx_bytes="0x02", + ), + { + "hash": Hash(0).hex(), + "logs": Hash(1).hex(), + "txbytes": Bytes(b"\x02").hex(), + "indexes": {"data": 0, "gas": 0, "value": 0}, + }, + id="state_fixture_fork_post", + ), + pytest.param( + True, + FixtureForkPost( + state_root="0x00", + logs_hash="0x01", + tx_bytes="0x02", + expect_exception=TransactionException.INITCODE_SIZE_EXCEEDED, + ), + { + "hash": Hash(0).hex(), + "logs": Hash(1).hex(), + "txbytes": Bytes(b"\x02").hex(), + "expectException": "TransactionException.INITCODE_SIZE_EXCEEDED", + "indexes": {"data": 0, "gas": 0, "value": 0}, + }, + id="state_fixture_fork_post_exception", + ), + pytest.param( + False, # Can not be deserialized: A single expect_exception str will not be + # deserialized as a list and therefore will not match the model_instance definition. + FixtureForkPost( + state_root="0x00", + logs_hash="0x01", + tx_bytes="0x02", + expect_exception=[TransactionException.INITCODE_SIZE_EXCEEDED], + ), + { + "hash": Hash(0).hex(), + "logs": Hash(1).hex(), + "txbytes": Bytes(b"\x02").hex(), + "expectException": "TransactionException.INITCODE_SIZE_EXCEEDED", + "indexes": {"data": 0, "gas": 0, "value": 0}, + }, + id="state_fixture_fork_post_exception_list_1", + ), + pytest.param( + True, + FixtureForkPost( + state_root="0x00", + logs_hash="0x01", + tx_bytes="0x02", + expect_exception=[ + TransactionException.INITCODE_SIZE_EXCEEDED, + TransactionException.INSUFFICIENT_ACCOUNT_FUNDS, + ], + ), + { + "hash": Hash(0).hex(), + "logs": Hash(1).hex(), + "txbytes": Bytes(b"\x02").hex(), + "expectException": "TransactionException.INITCODE_SIZE_EXCEEDED|" + "TransactionException.INSUFFICIENT_ACCOUNT_FUNDS", + "indexes": {"data": 0, "gas": 0, "value": 0}, + }, + id="state_fixture_fork_post_exception_list_2", + ), + ], +) +class TestPydanticModelConversion: + """ + Test that Pydantic models are converted to and from JSON correctly. + """ + + def test_json_serialization( + self, can_be_deserialized: bool, model_instance: Any, json: str | Dict[str, Any] + ): + """ + Test that to_json returns the expected JSON for the given object. + """ + assert to_json(model_instance) == json + + def test_json_deserialization( + self, can_be_deserialized: bool, model_instance: Any, json: str | Dict[str, Any] + ): + """ + Test that to_json returns the expected JSON for the given object. + """ + if not can_be_deserialized: + pytest.skip(reason="The model instance in this case can not be deserialized") + model_type = type(model_instance) + assert model_type(**json) == model_instance diff --git a/src/ethereum_test_fixtures/verify.py b/src/ethereum_test_fixtures/verify.py new file mode 100644 index 0000000000..c3a6faced5 --- /dev/null +++ b/src/ethereum_test_fixtures/verify.py @@ -0,0 +1,31 @@ +""" +Ethereum test fixture verifyer abstract class. +""" + +from abc import ABC, abstractmethod +from pathlib import Path + +from .formats import FixtureFormats + + +class FixtureVerifier(ABC): + """ + Abstract class for verifying Ethereum test fixtures. + """ + + @abstractmethod + def verify_fixture( + self, + fixture_format: FixtureFormats, + fixture_path: Path, + fixture_name: str | None = None, + debug_output_path: Path | None = None, + ): + """ + Executes `evm [state|block]test` to verify the fixture at `fixture_path`. + + Currently only implemented by geth's evm. + """ + raise NotImplementedError( + "The `verify_fixture()` function is not supported by this tool. Use geth's evm tool." + ) diff --git a/src/ethereum_test_tools/spec/__init__.py b/src/ethereum_test_specs/__init__.py similarity index 63% rename from src/ethereum_test_tools/spec/__init__.py rename to src/ethereum_test_specs/__init__.py index 5ebe48aefa..6df10e103e 100644 --- a/src/ethereum_test_tools/spec/__init__.py +++ b/src/ethereum_test_specs/__init__.py @@ -4,9 +4,9 @@ from typing import List, Type -from .base.base_test import BaseFixture, BaseTest, TestSpec -from .blockchain.blockchain_test import BlockchainTest, BlockchainTestFiller, BlockchainTestSpec -from .eof.eof_test import ( +from .base import BaseTest, TestSpec +from .blockchain import BlockchainTest, BlockchainTestFiller, BlockchainTestSpec +from .eof import ( EOFStateTest, EOFStateTestFiller, EOFStateTestSpec, @@ -14,8 +14,7 @@ EOFTestFiller, EOFTestSpec, ) -from .fixture_collector import FixtureCollector, TestInfo -from .state.state_test import StateTest, StateTestFiller, StateTestOnly, StateTestSpec +from .state import StateTest, StateTestFiller, StateTestOnly, StateTestSpec SPEC_TYPES: List[Type[BaseTest]] = [ BlockchainTest, @@ -25,9 +24,9 @@ EOFStateTest, ] + __all__ = ( "SPEC_TYPES", - "BaseFixture", "BaseTest", "BlockchainTest", "BlockchainTestFiller", @@ -38,11 +37,9 @@ "EOFTest", "EOFTestFiller", "EOFTestSpec", - "FixtureCollector", "StateTest", "StateTestFiller", "StateTestOnly", "StateTestSpec", - "TestInfo", "TestSpec", ) diff --git a/src/ethereum_test_tools/spec/base/base_test.py b/src/ethereum_test_specs/base.py similarity index 58% rename from src/ethereum_test_tools/spec/base/base_test.py rename to src/ethereum_test_specs/base.py index fbd7021b87..f839a47b7a 100644 --- a/src/ethereum_test_tools/spec/base/base_test.py +++ b/src/ethereum_test_specs/base.py @@ -2,24 +2,20 @@ Base test class and helper functions for Ethereum state and blockchain tests. """ -import hashlib -import json from abc import abstractmethod -from functools import cached_property, reduce +from functools import reduce from itertools import count from os import path from pathlib import Path -from typing import Any, Callable, ClassVar, Dict, Generator, Iterator, List, Optional +from typing import Callable, ClassVar, Dict, Generator, Iterator, List, Optional from pydantic import BaseModel, Field +from ethereum_test_base_types import to_hex +from ethereum_test_fixtures import BaseFixture, FixtureFormats from ethereum_test_forks import Fork -from evm_transition_tool import FixtureFormats, TransitionTool - -from ...common import Environment, Transaction, Withdrawal -from ...common.conversions import to_hex -from ...common.types import CamelModel, Result -from ...reference_spec.reference_spec import ReferenceSpec +from ethereum_test_types import Environment, Transaction, Withdrawal +from evm_transition_tool import Result, TransitionTool class HashMismatchException(Exception): @@ -65,63 +61,6 @@ def verify_result(result: Result, env: Environment): assert result.withdrawals_root == to_hex(Withdrawal.list_root(env.withdrawals)) -class BaseFixture(CamelModel): - """Represents a base Ethereum test fixture of any type.""" - - info: Dict[str, str] = Field(default_factory=dict, alias="_info") - format: ClassVar[FixtureFormats] = FixtureFormats.UNSET_TEST_FORMAT - - @cached_property - def json_dict(self) -> Dict[str, Any]: - """ - Returns the JSON representation of the fixture. - """ - return self.model_dump(mode="json", by_alias=True, exclude_none=True, exclude={"info"}) - - @cached_property - def hash(self) -> str: - """ - Returns the hash of the fixture. - """ - json_str = json.dumps(self.json_dict, sort_keys=True, separators=(",", ":")) - h = hashlib.sha256(json_str.encode("utf-8")).hexdigest() - return f"0x{h}" - - def json_dict_with_info(self, hash_only: bool = False) -> Dict[str, Any]: - """ - Returns the JSON representation of the fixture with the info field. - """ - dict_with_info = self.json_dict.copy() - dict_with_info["_info"] = {"hash": self.hash} - if not hash_only: - dict_with_info["_info"].update(self.info) - return dict_with_info - - def fill_info( - self, - t8n: TransitionTool, - fixture_description: str, - fixture_source_url: str, - ref_spec: ReferenceSpec | None, - ): - """ - Fill the info field for this fixture - """ - if "comment" not in self.info: - self.info["comment"] = "`execution-spec-tests` generated test" - self.info["filling-transition-tool"] = t8n.version() - self.info["description"] = fixture_description - self.info["url"] = fixture_source_url - if ref_spec is not None: - ref_spec.write_info(self.info) - - def get_fork(self) -> str: - """ - Returns the fork of the fixture as a string. - """ - raise NotImplementedError - - class BaseTest(BaseModel): """ Represents a base Ethereum test which must return a single test fixture. diff --git a/src/ethereum_test_tools/spec/blockchain/blockchain_test.py b/src/ethereum_test_specs/blockchain.py similarity index 67% rename from src/ethereum_test_tools/spec/blockchain/blockchain_test.py rename to src/ethereum_test_specs/blockchain.py index 2cd1366d02..e701b959fd 100644 --- a/src/ethereum_test_tools/spec/blockchain/blockchain_test.py +++ b/src/ethereum_test_specs/blockchain.py @@ -5,20 +5,23 @@ from pprint import pprint from typing import Any, Callable, ClassVar, Dict, Generator, List, Optional, Tuple, Type -from pydantic import Field - -from ethereum_test_forks import Fork -from evm_transition_tool import FixtureFormats, TransitionTool - -from ...common import Alloc, EmptyTrieRoot, Environment, Hash, Requests, Transaction, Withdrawal -from ...common.constants import EmptyOmmersRoot -from ...common.json import to_json -from ...common.types import DepositRequest, TransitionToolOutput, WithdrawalRequest -from ..base.base_test import BaseFixture, BaseTest, verify_result, verify_transactions -from ..debugging import print_traces -from .types import ( - Block, - BlockException, +from pydantic import ConfigDict, Field, field_validator + +from ethereum_test_base_types import ( + Address, + Bloom, + Bytes, + CamelModel, + EmptyOmmersRoot, + EmptyTrieRoot, + Hash, + HeaderNonce, + HexNumber, + Number, +) +from ethereum_test_exceptions import BlockException, EngineAPIError, TransactionException +from ethereum_test_fixtures import BaseFixture, FixtureFormats +from ethereum_test_fixtures.blockchain import ( Fixture, FixtureBlock, FixtureBlockBase, @@ -31,6 +34,21 @@ HiveFixture, InvalidFixtureBlock, ) +from ethereum_test_forks import Fork +from ethereum_test_types import ( + Alloc, + DepositRequest, + Environment, + Removable, + Requests, + Transaction, + Withdrawal, + WithdrawalRequest, +) +from evm_transition_tool import TransitionTool + +from .base import BaseTest, verify_result, verify_transactions +from .debugging import print_traces def environment_from_parent_header(parent: "FixtureHeader") -> "Environment": @@ -78,6 +96,214 @@ def count_blobs(txs: List[Transaction]) -> int: ) +class Header(CamelModel): + """ + Header type used to describe block header properties in test specs. + """ + + parent_hash: Hash | None = None + ommers_hash: Hash | None = None + fee_recipient: Address | None = None + state_root: Hash | None = None + transactions_trie: Hash | None = None + receipts_root: Hash | None = None + logs_bloom: Bloom | None = None + difficulty: HexNumber | None = None + number: HexNumber | None = None + gas_limit: HexNumber | None = None + gas_used: HexNumber | None = None + timestamp: HexNumber | None = None + extra_data: Bytes | None = None + prev_randao: Hash | None = None + nonce: HeaderNonce | None = None + base_fee_per_gas: Removable | HexNumber | None = None + withdrawals_root: Removable | Hash | None = None + blob_gas_used: Removable | HexNumber | None = None + excess_blob_gas: Removable | HexNumber | None = None + parent_beacon_block_root: Removable | Hash | None = None + requests_root: Removable | Hash | None = None + + REMOVE_FIELD: ClassVar[Removable] = Removable() + """ + Sentinel object used to specify that a header field should be removed. + """ + EMPTY_FIELD: ClassVar[Removable] = Removable() + """ + Sentinel object used to specify that a header field must be empty during verification. + + This can be used in a test to explicitly skip a field in a block's RLP encoding. + included in the (json) output when the model is serialized. For example: + ``` + header_modifier = Header( + excess_blob_gas=Header.REMOVE_FIELD, + ) + block = Block( + timestamp=TIMESTAMP, + rlp_modifier=header_modifier, + exception=BlockException.INCORRECT_BLOCK_FORMAT, + engine_api_error_code=EngineAPIError.InvalidParams, + ) + ``` + """ + + model_config = ConfigDict( + arbitrary_types_allowed=True, + # explicitly set Removable items to None so they are not included in the serialization + # (in combination with exclude_None=True in model.dump()). + json_encoders={ + Removable: lambda x: None, + }, + ) + + @field_validator("withdrawals_root", mode="before") + @classmethod + def validate_withdrawals_root(cls, value): + """ + Helper validator to convert a list of withdrawals into the withdrawals root hash. + """ + if isinstance(value, list): + return Withdrawal.list_root(value) + return value + + @field_validator("requests_root", mode="before") + @classmethod + def validate_requests_root(cls, value): + """ + Helper validator to convert a list of requests into the requests root hash. + """ + if isinstance(value, list): + return Requests(root=value).trie_root + return value + + def apply(self, target: FixtureHeader) -> FixtureHeader: + """ + Produces a fixture header copy with the set values from the modifier. + """ + return target.copy( + **{ + k: (v if v is not Header.REMOVE_FIELD else None) + for k, v in self.model_dump(exclude_none=True).items() + } + ) + + def verify(self, target: FixtureHeader): + """ + Verifies that the header fields from self are as expected. + """ + for field_name in self.model_fields: + baseline_value = getattr(self, field_name) + if baseline_value is not None: + assert baseline_value is not Header.REMOVE_FIELD, "invalid header" + value = getattr(target, field_name) + if baseline_value is Header.EMPTY_FIELD: + assert ( + value is None + ), f"invalid header field {field_name}, got {value}, want None" + continue + assert value == baseline_value, ( + f"invalid header field ({field_name}) value, " + + f"got {value}, want {baseline_value}" + ) + + +class Block(Header): + """ + Block type used to describe block properties in test specs + """ + + rlp: Bytes | None = None + """ + If set, blockchain test will skip generating the block and will pass this value directly to + the Fixture. + + Only meant to be used to simulate blocks with bad formats, and therefore + requires the block to produce an exception. + """ + header_verify: Header | None = None + """ + If set, the block header will be verified against the specified values. + """ + rlp_modifier: Header | None = None + """ + An RLP modifying header which values would be used to override the ones + returned by the `evm_transition_tool`. + """ + exception: List[ + TransactionException | BlockException + ] | TransactionException | BlockException | None = None + """ + If set, the block is expected to be rejected by the client. + """ + engine_api_error_code: EngineAPIError | None = None + """ + If set, the block is expected to produce an error response from the Engine API. + """ + txs: List[Transaction] = Field(default_factory=list) + """ + List of transactions included in the block. + """ + ommers: List[Header] | None = None + """ + List of ommer headers included in the block. + """ + withdrawals: List[Withdrawal] | None = None + """ + List of withdrawals to perform for this block. + """ + requests: List[DepositRequest | WithdrawalRequest] | None = None + """ + Custom list of requests to embed in this block. + """ + + def set_environment(self, env: Environment) -> Environment: + """ + Creates a copy of the environment with the characteristics of this + specific block. + """ + new_env_values: Dict[str, Any] = {} + + """ + Values that need to be set in the environment and are `None` for + this block need to be set to their defaults. + """ + new_env_values["difficulty"] = self.difficulty + new_env_values["fee_recipient"] = ( + self.fee_recipient if self.fee_recipient is not None else Environment().fee_recipient + ) + new_env_values["gas_limit"] = ( + self.gas_limit or env.parent_gas_limit or Environment().gas_limit + ) + if not isinstance(self.base_fee_per_gas, Removable): + new_env_values["base_fee_per_gas"] = self.base_fee_per_gas + new_env_values["withdrawals"] = self.withdrawals + if not isinstance(self.excess_blob_gas, Removable): + new_env_values["excess_blob_gas"] = self.excess_blob_gas + if not isinstance(self.blob_gas_used, Removable): + new_env_values["blob_gas_used"] = self.blob_gas_used + if not isinstance(self.parent_beacon_block_root, Removable): + new_env_values["parent_beacon_block_root"] = self.parent_beacon_block_root + """ + These values are required, but they depend on the previous environment, + so they can be calculated here. + """ + if self.number is not None: + new_env_values["number"] = self.number + else: + # calculate the next block number for the environment + if len(env.block_hashes) == 0: + new_env_values["number"] = 0 + else: + new_env_values["number"] = max([Number(n) for n in env.block_hashes.keys()]) + 1 + + if self.timestamp is not None: + new_env_values["timestamp"] = self.timestamp + else: + assert env.parent_timestamp is not None + new_env_values["timestamp"] = int(Number(env.parent_timestamp) + 12) + + return env.copy(**new_env_values) + + class BlockchainTest(BaseTest): """ Filler type that tests multiple blocks (valid or invalid) in a chain. @@ -192,19 +418,15 @@ def generate_block_data( + "must be the last transaction in the block" ) - transition_tool_output = TransitionToolOutput( - **t8n.evaluate( - alloc=to_json(previous_alloc), - txs=[to_json(tx) for tx in txs], - env=to_json(env), - fork_name=fork.transition_tool_name( - block_number=env.number, timestamp=env.timestamp - ), - chain_id=self.chain_id, - reward=fork.get_reward(env.number, env.timestamp), - eips=eips, - debug_output_path=self.get_next_transition_tool_output_path(), - ) + transition_tool_output = t8n.evaluate( + alloc=previous_alloc, + txs=txs, + env=env, + fork=fork, + chain_id=self.chain_id, + reward=fork.get_reward(env.number, env.timestamp), + eips=eips, + debug_output_path=self.get_next_transition_tool_output_path(), ) try: @@ -250,12 +472,12 @@ def generate_block_data( if block.header_verify is not None: # Verify the header after transition tool processing. - header.verify(block.header_verify) + block.header_verify.verify(header) if block.rlp_modifier is not None: # Modify any parameter specified in the `rlp_modifier` after # transition tool processing. - header = header.join(block.rlp_modifier) + header = block.rlp_modifier.apply(header) requests = None if fork.header_requests_required(header.number, header.timestamp): diff --git a/src/ethereum_test_tools/spec/debugging.py b/src/ethereum_test_specs/debugging.py similarity index 100% rename from src/ethereum_test_tools/spec/debugging.py rename to src/ethereum_test_specs/debugging.py diff --git a/src/ethereum_test_tools/spec/eof/eof_test.py b/src/ethereum_test_specs/eof.py similarity index 96% rename from src/ethereum_test_tools/spec/eof/eof_test.py rename to src/ethereum_test_specs/eof.py index ab24884cbb..55234b6da4 100644 --- a/src/ethereum_test_tools/spec/eof/eof_test.py +++ b/src/ethereum_test_specs/eof.py @@ -11,16 +11,17 @@ from pydantic import Field, model_validator +from ethereum_test_base_types import Account, Bytes +from ethereum_test_exceptions import EOFException, EvmoneExceptionMapper +from ethereum_test_fixtures import BaseFixture, FixtureFormats +from ethereum_test_fixtures.eof import Fixture, Result, Vector from ethereum_test_forks import Fork -from evm_transition_tool import FixtureFormats, TransitionTool - -from ...common import Account, Alloc, Environment, Transaction -from ...common.base_types import Bytes -from ...eof.v1 import Container, ContainerKind -from ...exceptions import EOFException, EvmoneExceptionMapper -from ..base.base_test import BaseFixture, BaseTest -from ..state.state_test import StateTest -from .types import Fixture, Result, Vector +from ethereum_test_types import Alloc, Environment, Transaction +from ethereum_test_types.eof.v1 import Container, ContainerKind +from evm_transition_tool import TransitionTool + +from .base import BaseTest +from .state import StateTest class EOFBaseException(Exception): diff --git a/src/ethereum_test_specs/py.typed b/src/ethereum_test_specs/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ethereum_test_tools/spec/state/state_test.py b/src/ethereum_test_specs/state.py similarity index 82% rename from src/ethereum_test_tools/spec/state/state_test.py rename to src/ethereum_test_specs/state.py index 5d09144451..6fa6768b6b 100644 --- a/src/ethereum_test_tools/spec/state/state_test.py +++ b/src/ethereum_test_specs/state.py @@ -4,18 +4,21 @@ from typing import Any, Callable, ClassVar, Dict, Generator, List, Optional, Type +from ethereum_test_exceptions import EngineAPIError +from ethereum_test_fixtures import BaseFixture, FixtureFormats +from ethereum_test_fixtures.state import ( + Fixture, + FixtureEnvironment, + FixtureForkPost, + FixtureTransaction, +) from ethereum_test_forks import Fork -from evm_transition_tool import FixtureFormats, TransitionTool - -from ...common import Alloc, Environment, Transaction -from ...common.constants import EngineAPIError -from ...common.json import to_json -from ...common.types import TransitionToolOutput -from ..base.base_test import BaseFixture, BaseTest -from ..blockchain.blockchain_test import Block, BlockchainTest -from ..blockchain.types import Header -from ..debugging import print_traces -from .types import Fixture, FixtureEnvironment, FixtureForkPost, FixtureTransaction +from ethereum_test_types import Alloc, Environment, Transaction +from evm_transition_tool import TransitionTool + +from .base import BaseTest +from .blockchain import Block, BlockchainTest, Header +from .debugging import print_traces TARGET_BLOB_GAS_PER_BLOCK = 393216 @@ -122,26 +125,16 @@ def make_state_test_fixture( ) if empty_accounts := pre_alloc.empty_accounts(): raise Exception(f"Empty accounts in pre state: {empty_accounts}") - transition_tool_name = fork.transition_tool_name( - block_number=self.env.number, - timestamp=self.env.timestamp, - ) - fork_name = ( - "+".join([transition_tool_name] + [str(eip) for eip in eips]) - if eips - else transition_tool_name - ) - transition_tool_output = TransitionToolOutput( - **t8n.evaluate( - alloc=to_json(pre_alloc), - txs=[to_json(tx)], - env=to_json(env), - fork_name=fork_name, - chain_id=self.chain_id, - reward=0, # Reward on state tests is always zero - eips=eips, - debug_output_path=self.get_next_transition_tool_output_path(), - ) + + transition_tool_output = t8n.evaluate( + alloc=pre_alloc, + txs=[tx], + env=env, + fork=fork, + chain_id=self.chain_id, + reward=0, # Reward on state tests is always zero + eips=eips, + debug_output_path=self.get_next_transition_tool_output_path(), ) try: diff --git a/src/ethereum_test_specs/tests/__init__.py b/src/ethereum_test_specs/tests/__init__.py new file mode 100644 index 0000000000..4ba3839c5e --- /dev/null +++ b/src/ethereum_test_specs/tests/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for the ethereum_test_specs package. +""" diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_valid_filled.json b/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json similarity index 53% rename from src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_valid_filled.json rename to src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json index edee2a1b58..3ee643a0bc 100644 --- a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_valid_filled.json +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json @@ -1,7 +1,7 @@ { - "000/my_blockchain_test/London/solc=0.8.20": { + "000/my_blockchain_test/London": { "_info": { - "hash": "0x91032fb245f4488b204198312cbf16429c121435705ac3f9c6eb3943ec0bc36d" + "hash": "0x4de3f84e3cb1e678141d81ce96ce75edb53f1824a708e26098b610c3c1030e66" }, "network": "London", "genesisRLP": "0xf90200f901fba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a089a5be1d3306f6f05b42678ef13ac3dbc37bef9a2a80862c21eb22eee29194c2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008088016345785d8a0000808000a000000000000000000000000000000000000000000000000000000000000000008800000000000000008203e8c0c0", @@ -141,6 +141,67 @@ ], "uncleHeaders": [] }, + { + "rlp": "0xf902e1f901fea00e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a069f3a735c7a7e1ea24a03a7107eba6a880d2d0251aaf24eaa7f109ece7969bf9a07c6d7fe1d1734fca072880e563f763405dc362222d37487cb098a006f7db3b2ca0976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4efb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a0000830155442480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff8ddb86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86d02f86a0105830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820302c080a06c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715a01220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9bc0", + "expectException": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", + "rlp_decoded": { + "blockHeader": { + "parentHash": "0x0e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0x69f3a735c7a7e1ea24a03a7107eba6a880d2d0251aaf24eaa7f109ece7969bf9", + "transactionsTrie": "0x7c6d7fe1d1734fca072880e563f763405dc362222d37487cb098a006f7db3b2c", + "receiptTrie": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x020000", + "number": "0x03", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x015544", + "timestamp": "0x24", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x029f", + "hash": "0x0cb9b60de1bb3893d7b7b806562a78aca5e9fbff47bf62893a5f6c0afcc73b48" + }, + "blocknumber": "3", + "transactions": [ + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x04", + "maxPriorityFeePerGas": "0x03e8", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccc", + "value": "0x00", + "data": "0x0301", + "accessList": [], + "v": "0x01", + "r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63", + "s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x05", + "maxPriorityFeePerGas": "0x0186a0", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccd", + "value": "0x00", + "data": "0x0302", + "accessList": [], + "v": "0x00", + "r": "0x6c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715", + "s": "0x1220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9b", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "uncleHeaders": [] + } + }, { "rlp": "0xf9034ff901fea00e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0bb08d7ca9c904f3d01b78041a9d70f69e83b0a6ec7af471cbd00933a47fdacaea027f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652a0f42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a000083053c422480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff9014ab86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86a02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33b86e02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0cc0", "blockHeader": { @@ -215,6 +276,67 @@ ], "uncleHeaders": [] }, + { + "rlp": "0xf902e1f901fea05c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0e834ba6cd27f2702b0adf2ef6a85e2fbc340fb948c96e75b674e9a73a5dbc3d1a04722f7b17f27aee5dfa0d92ba40e16de960374a98ec63e728acaa1564d8a54f3a0976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4efb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a0000830155443080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf8ddb86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86d02f86a0108830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820402c001a0ebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23a0341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7c0", + "expectException": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", + "rlp_decoded": { + "blockHeader": { + "parentHash": "0x5c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8e", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0xe834ba6cd27f2702b0adf2ef6a85e2fbc340fb948c96e75b674e9a73a5dbc3d1", + "transactionsTrie": "0x4722f7b17f27aee5dfa0d92ba40e16de960374a98ec63e728acaa1564d8a54f3", + "receiptTrie": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x020000", + "number": "0x04", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x015544", + "timestamp": "0x30", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x024c", + "hash": "0x1f01f6d8ff3a461486c4c4334c94a05f114d161b1ac082c7374ad7ac51eea7f2" + }, + "blocknumber": "4", + "transactions": [ + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x07", + "maxPriorityFeePerGas": "0x03e8", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccc", + "value": "0x00", + "data": "0x0401", + "accessList": [], + "v": "0x01", + "r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c", + "s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x08", + "maxPriorityFeePerGas": "0x0186a0", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccd", + "value": "0x00", + "data": "0x0402", + "accessList": [], + "v": "0x01", + "r": "0xebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23", + "s": "0x341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "uncleHeaders": [] + } + }, { "rlp": "0xf9034ff901fea05c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0e2b2b992b108bcd0e036067ef693f2d1b94c2f48d074a4f6b9d98537bbf15e9aa07617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331a0f42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a000083053c423080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf9014ab86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86a02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29db86e02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0c0", "blockHeader": { @@ -417,424 +539,5 @@ } }, "sealEngine": "NoProof" - }, - "000/my_blockchain_test/London/solc=padding_version": { - "_info": { - "hash": "0xc85d9386344098d2323880c28797541e457eb5a34b16eaf6bc7ccaf469c2a382" - }, - "blocks": [ - { - "rlp": "0xf9026ef901fea0c552af8a2644e24df2f54d14aa70f207146dda49b746cc2e0af88e185f043d2ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a06bbd44292c9016cf53472d8ef579a1805a9008b898c5f159248ed106532b667ba0586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017ba029b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000188016345785d8a0000830155340c80a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082036bf86ab86802f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625bc0", - "blockHeader": { - "parentHash": "0xc552af8a2644e24df2f54d14aa70f207146dda49b746cc2e0af88e185f043d2e", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x6bbd44292c9016cf53472d8ef579a1805a9008b898c5f159248ed106532b667b", - "transactionsTrie": "0x586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017b", - "receiptTrie": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x01", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x015534", - "timestamp": "0x0c", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x036b", - "hash": "0x337a985aa58c1b900b9e77b29101a76d9d22366defe3f6f7c005c5cad0f70758" - }, - "blocknumber": "1", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x00", - "maxPriorityFeePerGas": "0x01", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x01", - "accessList": [], - "v": "0x00", - "r": "0x3351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58", - "s": "0x67817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf90349f901fea0337a985aa58c1b900b9e77b29101a76d9d22366defe3f6f7c005c5cad0f70758a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a015413d90c7cf94b4eb779f4b99cfed8cf296ffacf5a5c19557cdd83e7af3adcea05521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298a0d0f659459422a274c9cfc8b15ad25ea1def3ade376a5759b9a1cf97b185f0bd1b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000288016345785d8a000083053c391880a000000000000000000000000000000000000000000000000000000000000000008800000000000000008202fef90144b86a02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0b86a02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64db86a02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3ac0", - "blockHeader": { - "parentHash": "0x337a985aa58c1b900b9e77b29101a76d9d22366defe3f6f7c005c5cad0f70758", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x15413d90c7cf94b4eb779f4b99cfed8cf296ffacf5a5c19557cdd83e7af3adce", - "transactionsTrie": "0x5521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298", - "receiptTrie": "0xd0f659459422a274c9cfc8b15ad25ea1def3ade376a5759b9a1cf97b185f0bd1", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x02", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c39", - "timestamp": "0x18", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x02fe", - "hash": "0x15676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2d" - }, - "blocknumber": "2", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x01", - "maxPriorityFeePerGas": "0x0a", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0201", - "accessList": [], - "v": "0x00", - "r": "0x6ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050", - "s": "0x52f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x02", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0202", - "accessList": [], - "v": "0x00", - "r": "0x218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825d", - "s": "0x58b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x03", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0203", - "accessList": [], - "v": "0x01", - "r": "0x339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782a", - "s": "0x74004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf9034ff901fea015676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0f93e92966505fc44657cc1977ac7ad5b1b4f43c20145a5df18240e3341cfa379a027f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652a0ce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a000083053c392480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff9014ab86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86a02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33b86e02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0cc0", - "blockHeader": { - "parentHash": "0x15676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2d", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xf93e92966505fc44657cc1977ac7ad5b1b4f43c20145a5df18240e3341cfa379", - "transactionsTrie": "0x27f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652", - "receiptTrie": "0xce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7d", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x03", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c39", - "timestamp": "0x24", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x029f", - "hash": "0x0817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79ce" - }, - "blocknumber": "3", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x04", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0301", - "accessList": [], - "v": "0x01", - "r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63", - "s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x05", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0303", - "accessList": [], - "v": "0x00", - "r": "0x9c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512e", - "s": "0x7a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x06", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x0186a0", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0304", - "accessList": [], - "v": "0x01", - "r": "0xc8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6a", - "s": "0x3e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf9034ff901fea00817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79cea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a04c171c1cf8f4b8a91b4a78d28f6d48f3fe5152db79273f4565c78966b64bda6fa07617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331a0ce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a000083053c393080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf9014ab86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86a02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29db86e02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0c0", - "blockHeader": { - "parentHash": "0x0817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79ce", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x4c171c1cf8f4b8a91b4a78d28f6d48f3fe5152db79273f4565c78966b64bda6f", - "transactionsTrie": "0x7617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331", - "receiptTrie": "0xce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7d", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x04", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c39", - "timestamp": "0x30", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x024c", - "hash": "0x0dab5a127f8e5ee8bd43b00f777830e470d932d1b99836639faaabce4c0629ed" - }, - "blocknumber": "4", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x07", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0401", - "accessList": [], - "v": "0x01", - "r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c", - "s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x08", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0403", - "accessList": [], - "v": "0x00", - "r": "0x8d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15", - "s": "0x3cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x09", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x0186a0", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0404", - "accessList": [], - "v": "0x01", - "r": "0x54bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9", - "s": "0x6f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - } - ], - "genesisBlockHeader": { - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xde1557ffdf9765e61095937bf835742ca427008f33714bee743010ab2d1e0ba6", - "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x00", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x00", - "timestamp": "0x00", - "extraData": "0x00", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x03e8", - "hash": "0xc552af8a2644e24df2f54d14aa70f207146dda49b746cc2e0af88e185f043d2e" - }, - "genesisRLP": "0xf90200f901fba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0de1557ffdf9765e61095937bf835742ca427008f33714bee743010ab2d1e0ba6a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008088016345785d8a0000808000a000000000000000000000000000000000000000000000000000000000000000008800000000000000008203e8c0c0", - "lastblockhash": "0x0dab5a127f8e5ee8bd43b00f777830e470d932d1b99836639faaabce4c0629ed", - "network": "London", - "pre": { - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x00", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x600080808061100061c0de5af150600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - } - }, - "postState": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x3000", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x1000", - "0x2003": "0x2000", - "0x2004": "0x3000" - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x0a", - "balance": "0xfffffffffba0b646be", - "code": "0x", - "storage": {} - }, - "0xba5e000000000000000000000000000000000000": { - "nonce": "0x00", - "balance": "0x6f05b5a16c7221a5", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": { - "0x01": "0x036b", - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1001": "0x01", - "0x1002": "0x0a", - "0x1003": "0x0149", - "0x1004": "0x019c", - "0x2001": "0x010000000000", - "0x2002": "0x010000000000", - "0x2003": "0x010000000000", - "0x2004": "0x010000000000" - } - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x018401", - "0x1004": "0x018454", - "0x2002": "0x020000000000", - "0x2003": "0x020000000000", - "0x2004": "0x020000000000" - } - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x01ffffffd000", - "code": "0x600080808061100061c0de5af150600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x01fffffff000", - "0x2003": "0x01ffffffe000", - "0x2004": "0x01ffffffd000" - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "sealEngine": "NoProof" } } diff --git a/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json b/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json new file mode 100644 index 0000000000..d8e6edb3b7 --- /dev/null +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json @@ -0,0 +1,421 @@ +{ + "000/my_blockchain_test/London": { + "_info": { + "hash": "0x91032fb245f4488b204198312cbf16429c121435705ac3f9c6eb3943ec0bc36d" + }, + "network": "London", + "genesisRLP": "0xf90200f901fba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a089a5be1d3306f6f05b42678ef13ac3dbc37bef9a2a80862c21eb22eee29194c2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008088016345785d8a0000808000a000000000000000000000000000000000000000000000000000000000000000008800000000000000008203e8c0c0", + "genesisBlockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x89a5be1d3306f6f05b42678ef13ac3dbc37bef9a2a80862c21eb22eee29194c2", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x020000", + "number": "0x00", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x00", + "timestamp": "0x00", + "extraData": "0x00", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x03e8", + "hash": "0x6241b4534da26b654ec5bb30d29b1d5202454af544b05828433354da7471957c" + }, + "blocks": [ + { + "rlp": "0xf9026ef901fea06241b4534da26b654ec5bb30d29b1d5202454af544b05828433354da7471957ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a03eb2e72e8ed9a59768bb9ac05915b781a764f2582edcf111053fe6531e466613a0586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017ba029b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000188016345785d8a0000830155340c80a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082036bf86ab86802f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625bc0", + "blockHeader": { + "parentHash": "0x6241b4534da26b654ec5bb30d29b1d5202454af544b05828433354da7471957c", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0x3eb2e72e8ed9a59768bb9ac05915b781a764f2582edcf111053fe6531e466613", + "transactionsTrie": "0x586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017b", + "receiptTrie": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x020000", + "number": "0x01", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x015534", + "timestamp": "0x0c", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x036b", + "hash": "0x12bba91a7e1f277f1549e832e06820f8849308f70f8659acf846bdc15f5d586e" + }, + "blocknumber": "1", + "transactions": [ + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x00", + "maxPriorityFeePerGas": "0x01", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccc", + "value": "0x00", + "data": "0x01", + "accessList": [], + "v": "0x00", + "r": "0x3351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58", + "s": "0x67817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "uncleHeaders": [] + }, + { + "rlp": "0xf90349f901fea012bba91a7e1f277f1549e832e06820f8849308f70f8659acf846bdc15f5d586ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0d9d9cc8ae73834ba9dc75fe8c68d36e980c82fcaf887dc220a05f152a327ae55a05521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298a0e225d44649351c3dccc61c1d904451d6f0f5a407c072099fe1085cfad88447d6b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000288016345785d8a000083053c421880a000000000000000000000000000000000000000000000000000000000000000008800000000000000008202fef90144b86a02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0b86a02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64db86a02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3ac0", + "blockHeader": { + "parentHash": "0x12bba91a7e1f277f1549e832e06820f8849308f70f8659acf846bdc15f5d586e", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0xd9d9cc8ae73834ba9dc75fe8c68d36e980c82fcaf887dc220a05f152a327ae55", + "transactionsTrie": "0x5521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298", + "receiptTrie": "0xe225d44649351c3dccc61c1d904451d6f0f5a407c072099fe1085cfad88447d6", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x020000", + "number": "0x02", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x053c42", + "timestamp": "0x18", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x02fe", + "hash": "0x0e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010" + }, + "blocknumber": "2", + "transactions": [ + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x01", + "maxPriorityFeePerGas": "0x0a", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccc", + "value": "0x00", + "data": "0x0201", + "accessList": [], + "v": "0x00", + "r": "0x6ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050", + "s": "0x52f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x02", + "maxPriorityFeePerGas": "0x64", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccd", + "value": "0x00", + "data": "0x0202", + "accessList": [], + "v": "0x00", + "r": "0x218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825d", + "s": "0x58b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x03", + "maxPriorityFeePerGas": "0x64", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xccccccccccccccccccccccccccccccccccccccce", + "value": "0x00", + "data": "0x0203", + "accessList": [], + "v": "0x01", + "r": "0x339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782a", + "s": "0x74004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "uncleHeaders": [] + }, + { + "rlp": "0xf9034ff901fea00e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0bb08d7ca9c904f3d01b78041a9d70f69e83b0a6ec7af471cbd00933a47fdacaea027f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652a0f42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a000083053c422480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff9014ab86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86a02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33b86e02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0cc0", + "blockHeader": { + "parentHash": "0x0e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0xbb08d7ca9c904f3d01b78041a9d70f69e83b0a6ec7af471cbd00933a47fdacae", + "transactionsTrie": "0x27f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652", + "receiptTrie": "0xf42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2e", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x020000", + "number": "0x03", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x053c42", + "timestamp": "0x24", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x029f", + "hash": "0x5c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8e" + }, + "blocknumber": "3", + "transactions": [ + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x04", + "maxPriorityFeePerGas": "0x03e8", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccc", + "value": "0x00", + "data": "0x0301", + "accessList": [], + "v": "0x01", + "r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63", + "s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x05", + "maxPriorityFeePerGas": "0x64", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xccccccccccccccccccccccccccccccccccccccce", + "value": "0x00", + "data": "0x0303", + "accessList": [], + "v": "0x00", + "r": "0x9c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512e", + "s": "0x7a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x06", + "maxPriorityFeePerGas": "0x0186a0", + "maxFeePerGas": "0x0186a0", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccd", + "value": "0x00", + "data": "0x0304", + "accessList": [], + "v": "0x01", + "r": "0xc8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6a", + "s": "0x3e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "uncleHeaders": [] + }, + { + "rlp": "0xf9034ff901fea05c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0e2b2b992b108bcd0e036067ef693f2d1b94c2f48d074a4f6b9d98537bbf15e9aa07617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331a0f42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a000083053c423080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf9014ab86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86a02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29db86e02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0c0", + "blockHeader": { + "parentHash": "0x5c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8e", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0xe2b2b992b108bcd0e036067ef693f2d1b94c2f48d074a4f6b9d98537bbf15e9a", + "transactionsTrie": "0x7617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331", + "receiptTrie": "0xf42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2e", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x020000", + "number": "0x04", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x053c42", + "timestamp": "0x30", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x024c", + "hash": "0xf5e2f23d9a212edbb35a07bc9f582f4a632b694bd4ef8742de8ad6c6acacf72c" + }, + "blocknumber": "4", + "transactions": [ + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x07", + "maxPriorityFeePerGas": "0x03e8", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccc", + "value": "0x00", + "data": "0x0401", + "accessList": [], + "v": "0x01", + "r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c", + "s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x08", + "maxPriorityFeePerGas": "0x64", + "maxFeePerGas": "0x03e8", + "gasLimit": "0x0f4240", + "to": "0xccccccccccccccccccccccccccccccccccccccce", + "value": "0x00", + "data": "0x0403", + "accessList": [], + "v": "0x00", + "r": "0x8d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15", + "s": "0x3cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x02", + "chainId": "0x01", + "nonce": "0x09", + "maxPriorityFeePerGas": "0x0186a0", + "maxFeePerGas": "0x0186a0", + "gasLimit": "0x0f4240", + "to": "0xcccccccccccccccccccccccccccccccccccccccd", + "value": "0x00", + "data": "0x0404", + "accessList": [], + "v": "0x01", + "r": "0x54bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9", + "s": "0x6f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "uncleHeaders": [] + } + ], + "lastblockhash": "0xf5e2f23d9a212edbb35a07bc9f582f4a632b694bd4ef8742de8ad6c6acacf72c", + "pre": { + "0x000000000000000000000000000000000000c0de": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0x01000000000000000000", + "code": "0x", + "storage": {} + }, + "0xcccccccccccccccccccccccccccccccccccccccc": { + "nonce": "0x01", + "balance": "0x010000000000", + "code": "0x484355483a036110004301554761200043015500", + "storage": {} + }, + "0xcccccccccccccccccccccccccccccccccccccccd": { + "nonce": "0x01", + "balance": "0x020000000000", + "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": {} + }, + "0xccccccccccccccccccccccccccccccccccccccce": { + "nonce": "0x01", + "balance": "0x020000000000", + "code": "0x60008060008061100061c0de5af160008060008073cccccccccccccccccccccccccccccccccccccccc5af4905050", + "storage": {} + }, + "0xd02d72e067e77158444ef2020ff2d325f929b363": { + "nonce": "0x01", + "balance": "0x01000000000000000000", + "code": "0x", + "storage": {} + } + }, + "postState": { + "0x000000000000000000000000000000000000c0de": { + "nonce": "0x01", + "balance": "0x3000", + "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": { + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1002": "0x64", + "0x1003": "0x64", + "0x1004": "0x64", + "0x2002": "0x1000", + "0x2003": "0x2000", + "0x2004": "0x3000" + } + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x0a", + "balance": "0xfffffffffba0afe5e7", + "code": "0x", + "storage": {} + }, + "0xba5e000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x6f05b5a16c783b4b", + "code": "0x", + "storage": {} + }, + "0xcccccccccccccccccccccccccccccccccccccccc": { + "nonce": "0x01", + "balance": "0x010000000000", + "code": "0x484355483a036110004301554761200043015500", + "storage": { + "0x01": "0x036b", + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1001": "0x01", + "0x1002": "0x0a", + "0x1003": "0x0149", + "0x1004": "0x019c", + "0x2001": "0x010000000000", + "0x2002": "0x010000000000", + "0x2003": "0x010000000000", + "0x2004": "0x010000000000" + } + }, + "0xcccccccccccccccccccccccccccccccccccccccd": { + "nonce": "0x01", + "balance": "0x020000000000", + "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": { + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1002": "0x64", + "0x1003": "0x018401", + "0x1004": "0x018454", + "0x2002": "0x020000000000", + "0x2003": "0x020000000000", + "0x2004": "0x020000000000" + } + }, + "0xccccccccccccccccccccccccccccccccccccccce": { + "nonce": "0x01", + "balance": "0x01ffffffd000", + "code": "0x60008060008061100061c0de5af160008060008073cccccccccccccccccccccccccccccccccccccccc5af4905050", + "storage": { + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1002": "0x64", + "0x1003": "0x64", + "0x1004": "0x64", + "0x2002": "0x01fffffff000", + "0x2003": "0x01ffffffe000", + "0x2004": "0x01ffffffd000" + } + }, + "0xd02d72e067e77158444ef2020ff2d325f929b363": { + "nonce": "0x01", + "balance": "0x01000000000000000000", + "code": "0x", + "storage": {} + } + }, + "sealEngine": "NoProof" + } +} diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_valid_filled_hive.json b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_hive.json similarity index 58% rename from src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_valid_filled_hive.json rename to src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_hive.json index 61c340cc13..161b3cb607 100644 --- a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_valid_filled_hive.json +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_hive.json @@ -1,7 +1,7 @@ { - "000/my_blockchain_test/Shanghai/solc=0.8.20": { + "000/my_blockchain_test/Shanghai": { "_info": { - "hash": "0x8971fc0546c97b5ac2689030044a662960d422671ffbfe5ed2a6c90a1b6e3599" + "hash": "0x71e49d6df916284daddf3b8558e3f59a1450d3e27909dff15d966e732564a680" }, "network": "Shanghai", "genesisBlockHeader": { @@ -75,245 +75,45 @@ "executionPayload": { "parentHash": "0xdcf29a42e8b62c9c73e07b087f52175f9bf9485ee26a05aa7c0ffb580a28a0ef", "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xa41f7c61262aa715762926c769792ba94d73f79e965cc6c029aab1d5e05aa7a5", - "receiptsRoot": "0x2b276cfe779f83fc50afea9262628cfe97b3175ce1822a1871aba93000cc5061", + "stateRoot": "0xa50fd88fc2ee5cb861c1bf80806781dbf17b986a4956bb3ac906dfadb0c02b44", + "receiptsRoot": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "blockNumber": "0x3", "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c3a", + "gasUsed": "0x15544", "timestamp": "0x24", "extraData": "0x", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "baseFeePerGas": "0x29f", - "blockHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", + "blockHash": "0xeaa67ef33964d925aabc53e217e3f5f143615723970bfa07b80c46ef946ca293", "transactions": [ "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "0x02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", - "0x02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c" + "0x02f86a0105830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820302c080a06c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715a01220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9b" ], "withdrawals": [] }, + "validationError": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", "version": "2" }, { "executionPayload": { - "parentHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", + "parentHash": "0xdcf29a42e8b62c9c73e07b087f52175f9bf9485ee26a05aa7c0ffb580a28a0ef", "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x2abb36dc658a3d346d858b72dcc5f5f7defd9b6903c69a6bb9318ea866bd85df", + "stateRoot": "0xa41f7c61262aa715762926c769792ba94d73f79e965cc6c029aab1d5e05aa7a5", "receiptsRoot": "0x2b276cfe779f83fc50afea9262628cfe97b3175ce1822a1871aba93000cc5061", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4", + "blockNumber": "0x3", "gasLimit": "0x16345785d8a0000", "gasUsed": "0x53c3a", - "timestamp": "0x30", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x24c", - "blockHash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", - "transactions": [ - "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "0x02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", - "0x02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0" - ], - "withdrawals": [] - }, - "version": "2" - } - ], - "engineFcuVersion": "2", - "pre": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": {} - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x00", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": {} - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", - "storage": {} - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "postState": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x3000", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x1000", - "0x2003": "0x2000", - "0x2004": "0x3000" - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x0a", - "balance": "0xfffffffffba0b63da9", - "code": "0x", - "storage": {} - }, - "0xba5e000000000000000000000000000000000000": { - "nonce": "0x00", - "balance": "0x04315222d1", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": { - "0x01": "0x036b", - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1001": "0x01", - "0x1002": "0x0a", - "0x1003": "0x0149", - "0x1004": "0x019c", - "0x2001": "0x010000000000", - "0x2002": "0x010000000000", - "0x2003": "0x010000000000", - "0x2004": "0x010000000000" - } - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x018401", - "0x1004": "0x018454", - "0x2002": "0x020000000000", - "0x2003": "0x020000000000", - "0x2004": "0x020000000000" - } - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x01ffffffd000", - "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x01fffffff000", - "0x2003": "0x01ffffffe000", - "0x2004": "0x01ffffffd000" - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - } - }, - "000/my_blockchain_test/Shanghai/solc=padding_version": { - "_info": { - "hash": "0x421a4d6fd9ac4b33c24aa9851fb30c346a6eec483715976298b38b68a319e42b" - }, - "network": "Shanghai", - "genesisBlockHeader": { - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x44b459e04de1195475bf581bebb5ef8bb409cf38ce1146e0e60d60e5986bf871", - "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x00", - "number": "0x00", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x00", - "timestamp": "0x00", - "extraData": "0x00", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x03e8", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "hash": "0xdab34f5856809d953e1d5fa05c64f71f71438da0038b98a66b47d1f330e1f4f3" - }, - "engineNewPayloads": [ - { - "executionPayload": { - "parentHash": "0xdab34f5856809d953e1d5fa05c64f71f71438da0038b98a66b47d1f330e1f4f3", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x5e6c56e26e40ffe7bf6a8593ce6623889fe2385a75d742e9a1f17ea03ba6ba99", - "receiptsRoot": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x15534", - "timestamp": "0xc", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x36b", - "blockHash": "0x8666ae70e0d1fc947f4e13022a3dcc042d9428a4c96fd2572cffc2f6279f3c9e", - "transactions": [ - "0x02f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b" - ], - "withdrawals": [] - }, - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0x8666ae70e0d1fc947f4e13022a3dcc042d9428a4c96fd2572cffc2f6279f3c9e", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x54fdc3ec17732ae232d372e2a1e35e386ab4c08b2af95de853c7d2144d98516d", - "receiptsRoot": "0xbea3c90090e14495fed0113be1e981aa10850bfa1e994f4cc2bc0aada5fa1f5e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x2", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c35", - "timestamp": "0x18", + "timestamp": "0x24", "extraData": "0x", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x2fe", - "blockHash": "0x3959bb9eddd1d3b688753245f7e452cf881dd08e2cdd40bc6f35c55597a0fb40", + "baseFeePerGas": "0x29f", + "blockHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", "transactions": [ - "0x02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", - "0x02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", - "0x02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a" + "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", + "0x02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", + "0x02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c" ], "withdrawals": [] }, @@ -321,43 +121,43 @@ }, { "executionPayload": { - "parentHash": "0x3959bb9eddd1d3b688753245f7e452cf881dd08e2cdd40bc6f35c55597a0fb40", + "parentHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xdeab03fae811e52bb3adf96a3d6d84400bf72f37450e245a70488632169af968", - "receiptsRoot": "0x2fa0d45ad30c3b2adb11d0adc9c2890af19822c415abce6f98d87b66166b9897", + "stateRoot": "0x6f432f2ec9284d7d2e251294558b9859771d075dc6ce01603ea52727a433078d", + "receiptsRoot": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x3", + "blockNumber": "0x4", "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c35", - "timestamp": "0x24", + "gasUsed": "0x15544", + "timestamp": "0x30", "extraData": "0x", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x29f", - "blockHash": "0x85e4d9912e8ff49ff61f0b602d3db551a54bd35ab64f93e708b00ad685999e6f", + "baseFeePerGas": "0x24c", + "blockHash": "0xa8b4cee5dcb437faf9d815cbe99986f9000e32cf5ea86613b944ac285cac0187", "transactions": [ - "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "0x02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", - "0x02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c" + "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", + "0x02f86a0108830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820402c001a0ebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23a0341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7" ], "withdrawals": [] }, + "validationError": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", "version": "2" }, { "executionPayload": { - "parentHash": "0x85e4d9912e8ff49ff61f0b602d3db551a54bd35ab64f93e708b00ad685999e6f", + "parentHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xbd76d2b78a55dda5a1dfc2b89f25dedd1b28285b06b58e2edd5705178fc5e3b6", - "receiptsRoot": "0x2fa0d45ad30c3b2adb11d0adc9c2890af19822c415abce6f98d87b66166b9897", + "stateRoot": "0x2abb36dc658a3d346d858b72dcc5f5f7defd9b6903c69a6bb9318ea866bd85df", + "receiptsRoot": "0x2b276cfe779f83fc50afea9262628cfe97b3175ce1822a1871aba93000cc5061", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "blockNumber": "0x4", "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c35", + "gasUsed": "0x53c3a", "timestamp": "0x30", "extraData": "0x", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "baseFeePerGas": "0x24c", - "blockHash": "0x2c11f86ffa6571ad6c287e33baa3829280b13f39d6921a00f387796e863e42fc", + "blockHash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", "transactions": [ "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", "0x02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", @@ -373,7 +173,7 @@ "0x000000000000000000000000000000000000c0de": { "nonce": "0x01", "balance": "0x00", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", "storage": {} }, "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { @@ -391,13 +191,13 @@ "0xcccccccccccccccccccccccccccccccccccccccd": { "nonce": "0x01", "balance": "0x020000000000", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", "storage": {} }, "0xccccccccccccccccccccccccccccccccccccccce": { "nonce": "0x01", "balance": "0x020000000000", - "code": "0x5f80808061100061c0de5af1505f80808073cccccccccccccccccccccccccccccccccccccccc5af400", + "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", "storage": {} }, "0xd02d72e067e77158444ef2020ff2d325f929b363": { @@ -411,7 +211,7 @@ "0x000000000000000000000000000000000000c0de": { "nonce": "0x01", "balance": "0x3000", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", "storage": { "0x02": "0x02fe", "0x03": "0x029f", @@ -426,13 +226,13 @@ }, "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { "nonce": "0x0a", - "balance": "0xfffffffffba0b9729f", + "balance": "0xfffffffffba0b63da9", "code": "0x", "storage": {} }, "0xba5e000000000000000000000000000000000000": { "nonce": "0x00", - "balance": "0x04314f1568", + "balance": "0x04315222d1", "code": "0x", "storage": {} }, @@ -458,7 +258,7 @@ "0xcccccccccccccccccccccccccccccccccccccccd": { "nonce": "0x01", "balance": "0x020000000000", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", "storage": { "0x02": "0x02fe", "0x03": "0x029f", @@ -474,7 +274,7 @@ "0xccccccccccccccccccccccccccccccccccccccce": { "nonce": "0x01", "balance": "0x01ffffffd000", - "code": "0x5f80808061100061c0de5af1505f80808073cccccccccccccccccccccccccccccccccccccccc5af400", + "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", "storage": { "0x02": "0x02fe", "0x03": "0x029f", diff --git a/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_hive.json b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_hive.json new file mode 100644 index 0000000000..6087e8a520 --- /dev/null +++ b/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_hive.json @@ -0,0 +1,250 @@ +{ + "000/my_blockchain_test/Shanghai": { + "_info": { + "hash": "0x8971fc0546c97b5ac2689030044a662960d422671ffbfe5ed2a6c90a1b6e3599" + }, + "network": "Shanghai", + "genesisBlockHeader": { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0000000000000000000000000000000000000000", + "stateRoot": "0xba686b86cbe20f66e00f33c0a41d80d69f43bcc3322bfc5ed4905d7691886f73", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x00", + "number": "0x00", + "gasLimit": "0x016345785d8a0000", + "gasUsed": "0x00", + "timestamp": "0x00", + "extraData": "0x00", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x03e8", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "hash": "0xee9490b3af4ef92610c3d55270c3d2cab510331f4b0fa0b3c2a805eee1c454b0" + }, + "engineNewPayloads": [ + { + "executionPayload": { + "parentHash": "0xee9490b3af4ef92610c3d55270c3d2cab510331f4b0fa0b3c2a805eee1c454b0", + "feeRecipient": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0xfceb4d8747f80ac0f9acab704448018fe23c5577cea89a2877c3620f0763b807", + "receiptsRoot": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x16345785d8a0000", + "gasUsed": "0x15534", + "timestamp": "0xc", + "extraData": "0x", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x36b", + "blockHash": "0xef5d5d7782c5bd50ce1543fdd31dae7c4d079ebdffd330a6db5f777baf1b9b71", + "transactions": [ + "0x02f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b" + ], + "withdrawals": [] + }, + "version": "2" + }, + { + "executionPayload": { + "parentHash": "0xef5d5d7782c5bd50ce1543fdd31dae7c4d079ebdffd330a6db5f777baf1b9b71", + "feeRecipient": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0x7fda38fe964161eeed6c7e9fcf959794387c7e235f84e1eee887903b7e6de5e0", + "receiptsRoot": "0xabecd0c0c929d8339a0f55a2be4c3cdcb66f9de91de87109f351a7bd56a664e0", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x2", + "gasLimit": "0x16345785d8a0000", + "gasUsed": "0x53c3a", + "timestamp": "0x18", + "extraData": "0x", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x2fe", + "blockHash": "0xdcf29a42e8b62c9c73e07b087f52175f9bf9485ee26a05aa7c0ffb580a28a0ef", + "transactions": [ + "0x02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", + "0x02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", + "0x02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a" + ], + "withdrawals": [] + }, + "version": "2" + }, + { + "executionPayload": { + "parentHash": "0xdcf29a42e8b62c9c73e07b087f52175f9bf9485ee26a05aa7c0ffb580a28a0ef", + "feeRecipient": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0xa41f7c61262aa715762926c769792ba94d73f79e965cc6c029aab1d5e05aa7a5", + "receiptsRoot": "0x2b276cfe779f83fc50afea9262628cfe97b3175ce1822a1871aba93000cc5061", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x3", + "gasLimit": "0x16345785d8a0000", + "gasUsed": "0x53c3a", + "timestamp": "0x24", + "extraData": "0x", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x29f", + "blockHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", + "transactions": [ + "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", + "0x02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", + "0x02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c" + ], + "withdrawals": [] + }, + "version": "2" + }, + { + "executionPayload": { + "parentHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", + "feeRecipient": "0xba5e000000000000000000000000000000000000", + "stateRoot": "0x2abb36dc658a3d346d858b72dcc5f5f7defd9b6903c69a6bb9318ea866bd85df", + "receiptsRoot": "0x2b276cfe779f83fc50afea9262628cfe97b3175ce1822a1871aba93000cc5061", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x4", + "gasLimit": "0x16345785d8a0000", + "gasUsed": "0x53c3a", + "timestamp": "0x30", + "extraData": "0x", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x24c", + "blockHash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", + "transactions": [ + "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", + "0x02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", + "0x02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0" + ], + "withdrawals": [] + }, + "version": "2" + } + ], + "engineFcuVersion": "2", + "pre": { + "0x000000000000000000000000000000000000c0de": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0x01000000000000000000", + "code": "0x", + "storage": {} + }, + "0xcccccccccccccccccccccccccccccccccccccccc": { + "nonce": "0x01", + "balance": "0x010000000000", + "code": "0x484355483a036110004301554761200043015500", + "storage": {} + }, + "0xcccccccccccccccccccccccccccccccccccccccd": { + "nonce": "0x01", + "balance": "0x020000000000", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": {} + }, + "0xccccccccccccccccccccccccccccccccccccccce": { + "nonce": "0x01", + "balance": "0x020000000000", + "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", + "storage": {} + }, + "0xd02d72e067e77158444ef2020ff2d325f929b363": { + "nonce": "0x01", + "balance": "0x01000000000000000000", + "code": "0x", + "storage": {} + } + }, + "postState": { + "0x000000000000000000000000000000000000c0de": { + "nonce": "0x01", + "balance": "0x3000", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": { + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1002": "0x64", + "0x1003": "0x64", + "0x1004": "0x64", + "0x2002": "0x1000", + "0x2003": "0x2000", + "0x2004": "0x3000" + } + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x0a", + "balance": "0xfffffffffba0b63da9", + "code": "0x", + "storage": {} + }, + "0xba5e000000000000000000000000000000000000": { + "nonce": "0x00", + "balance": "0x04315222d1", + "code": "0x", + "storage": {} + }, + "0xcccccccccccccccccccccccccccccccccccccccc": { + "nonce": "0x01", + "balance": "0x010000000000", + "code": "0x484355483a036110004301554761200043015500", + "storage": { + "0x01": "0x036b", + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1001": "0x01", + "0x1002": "0x0a", + "0x1003": "0x0149", + "0x1004": "0x019c", + "0x2001": "0x010000000000", + "0x2002": "0x010000000000", + "0x2003": "0x010000000000", + "0x2004": "0x010000000000" + } + }, + "0xcccccccccccccccccccccccccccccccccccccccd": { + "nonce": "0x01", + "balance": "0x020000000000", + "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", + "storage": { + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1002": "0x64", + "0x1003": "0x018401", + "0x1004": "0x018454", + "0x2002": "0x020000000000", + "0x2003": "0x020000000000", + "0x2004": "0x020000000000" + } + }, + "0xccccccccccccccccccccccccccccccccccccccce": { + "nonce": "0x01", + "balance": "0x01ffffffd000", + "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", + "storage": { + "0x02": "0x02fe", + "0x03": "0x029f", + "0x04": "0x024c", + "0x1002": "0x64", + "0x1003": "0x64", + "0x1004": "0x64", + "0x2002": "0x01fffffff000", + "0x2003": "0x01ffffffe000", + "0x2004": "0x01ffffffd000" + } + }, + "0xd02d72e067e77158444ef2020ff2d325f929b363": { + "nonce": "0x01", + "balance": "0x01000000000000000000", + "code": "0x", + "storage": {} + } + } + } +} diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/chainid_istanbul_blockchain_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test.json similarity index 100% rename from src/ethereum_test_tools/tests/test_filling/fixtures/chainid_istanbul_blockchain_test.json rename to src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test.json diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/chainid_london_blockchain_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test.json similarity index 100% rename from src/ethereum_test_tools/tests/test_filling/fixtures/chainid_london_blockchain_test.json rename to src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test.json diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/chainid_paris_blockchain_test_hive.json b/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_hive.json similarity index 100% rename from src/ethereum_test_tools/tests/test_filling/fixtures/chainid_paris_blockchain_test_hive.json rename to src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_hive.json diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/chainid_paris_state_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test.json similarity index 100% rename from src/ethereum_test_tools/tests/test_filling/fixtures/chainid_paris_state_test.json rename to src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test.json diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/chainid_shanghai_blockchain_test_hive.json b/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_hive.json similarity index 100% rename from src/ethereum_test_tools/tests/test_filling/fixtures/chainid_shanghai_blockchain_test_hive.json rename to src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_hive.json diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/chainid_shanghai_state_test.json b/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test.json similarity index 100% rename from src/ethereum_test_tools/tests/test_filling/fixtures/chainid_shanghai_state_test.json rename to src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test.json diff --git a/src/ethereum_test_tools/tests/test_filling/test_expect.py b/src/ethereum_test_specs/tests/test_expect.py similarity index 97% rename from src/ethereum_test_tools/tests/test_filling/test_expect.py rename to src/ethereum_test_specs/tests/test_expect.py index 3973dd3e09..7c15e05d00 100644 --- a/src/ethereum_test_tools/tests/test_filling/test_expect.py +++ b/src/ethereum_test_specs/tests/test_expect.py @@ -6,12 +6,13 @@ import pytest +from ethereum_test_base_types import Account, Address +from ethereum_test_fixtures import FixtureFormats from ethereum_test_forks import Fork, get_deployed_forks -from evm_transition_tool import FixtureFormats, GethTransitionTool +from ethereum_test_types import Alloc, Environment, Storage, Transaction +from evm_transition_tool import GethTransitionTool -from ...common import Account, Address, Environment, Transaction -from ...common.types import Alloc, Storage -from ...spec import StateTest +from ..state import StateTest ADDRESS_UNDER_TEST = Address(0x01) diff --git a/src/ethereum_test_tools/tests/test_filling/test_fixtures.py b/src/ethereum_test_specs/tests/test_fixtures.py similarity index 83% rename from src/ethereum_test_tools/tests/test_filling/test_fixtures.py rename to src/ethereum_test_specs/tests/test_fixtures.py index 6bcfde5389..825b2e1f62 100644 --- a/src/ethereum_test_tools/tests/test_filling/test_fixtures.py +++ b/src/ethereum_test_specs/tests/test_fixtures.py @@ -1,5 +1,5 @@ """ -Test suite for `ethereum_test_tools.filling` fixture generation. +Test suite for `ethereum_test_specs` fixture generation. """ import json @@ -8,19 +8,19 @@ import pytest from click.testing import CliRunner -from semver import Version import cli.check_fixtures +from ethereum_test_base_types import Account, Hash +from ethereum_test_exceptions import TransactionException +from ethereum_test_fixtures import BlockchainFixture, FixtureFormats +from ethereum_test_fixtures.blockchain import FixtureCommon from ethereum_test_forks import Berlin, Fork, Istanbul, London, Paris, Shanghai -from evm_transition_tool import FixtureFormats, GethTransitionTool +from ethereum_test_types import Alloc, Environment, Transaction +from ethereum_test_vm import Opcodes as Op +from evm_transition_tool import GethTransitionTool -from ... import Header -from ...code import Yul -from ...common import Account, Alloc, Environment, Hash, Transaction -from ...exceptions import TransactionException -from ...spec import BlockchainTest, StateTest -from ...spec.blockchain.types import Block, Fixture, FixtureCommon -from ..conftest import SOLC_PADDING_VERSION +from ..blockchain import Block, BlockchainTest, Header +from ..state import StateTest def remove_info_metadata(fixture_json): # noqa: D103 @@ -33,20 +33,14 @@ def remove_info_metadata(fixture_json): # noqa: D103 @pytest.fixture() -def hash(request: pytest.FixtureRequest, solc_version: Version): +def hash(request: pytest.FixtureRequest): """ Set the hash based on the fork and solc version. """ - if solc_version == Version.parse("0.8.20"): - if request.node.funcargs["fork"] == Berlin: - return bytes.fromhex("8abb1c1dd7") - elif request.node.funcargs["fork"] == London: - return bytes.fromhex("1dfe81256f") - else: - if request.node.funcargs["fork"] == Berlin: - return bytes.fromhex("d45f416ad5") - elif request.node.funcargs["fork"] == London: - return bytes.fromhex("ccfc165586") + if request.node.funcargs["fork"] == Berlin: + return bytes.fromhex("0408c6a5c6") + elif request.node.funcargs["fork"] == London: + return bytes.fromhex("a1babd536a") def test_check_helper_fixtures(): @@ -58,7 +52,7 @@ def test_check_helper_fixtures(): runner = CliRunner() args = [ "--input", - "src/ethereum_test_tools/tests/test_filling/fixtures", + "src/ethereum_test_specs/tests/fixtures", "--quiet", "--stop-on-error", ] @@ -81,19 +75,7 @@ def test_make_genesis(fork: Fork, hash: bytes): # noqa: D103 pre = Alloc() pre.deploy_contract( - Yul( - """ - { - function f(a, b) -> c { - c := add(a, b) - } - - sstore(0, f(1, 2)) - return(0, 32) - } - """, - fork=fork, - ), + (Op.SSTORE(0, Op.ADD(1, 2)) + Op.RETURN(0, 32)), balance=0x0BA1A9CE0BA1A9CE, ) pre.fund_eoa(0x0BA1A9CE0BA1A9CE) @@ -106,7 +88,7 @@ def test_make_genesis(fork: Fork, hash: bytes): # noqa: D103 blocks=[], tag="some_state_test", ).generate(t8n, fork, fixture_format=FixtureFormats.BLOCKCHAIN_TEST) - assert isinstance(fixture, Fixture) + assert isinstance(fixture, BlockchainFixture) assert fixture.genesis is not None assert fixture.genesis.block_hash is not None @@ -181,9 +163,8 @@ def test_fill_state_test( with open( os.path.join( "src", - "ethereum_test_tools", + "ethereum_test_specs", "tests", - "test_filling", "fixtures", expected_json_file, ) @@ -225,60 +206,63 @@ def pre(self, fork: Fork): # noqa: D102 "0xcccccccccccccccccccccccccccccccccccccccc": Account( balance=0x10000000000, nonce=1, - code=Yul( - """ - { - sstore(number(), basefee()) - sstore(add(number(), 0x1000), sub(gasprice(), basefee())) - sstore(add(number(), 0x2000), selfbalance()) - stop() - } - """, - fork=fork, + code=( + Op.SSTORE(Op.NUMBER(), Op.BASEFEE()) + + Op.SSTORE(Op.ADD(Op.NUMBER(), 0x1000), Op.SUB(Op.GASPRICE(), Op.BASEFEE())) + + Op.SSTORE(Op.ADD(Op.NUMBER(), 0x2000), Op.SELFBALANCE()) + + Op.STOP() ), ), "0xcccccccccccccccccccccccccccccccccccccccd": Account( balance=0x20000000000, nonce=1, - code=Yul( - """ - { - let throwMe := delegatecall(gas(), - 0xcccccccccccccccccccccccccccccccccccccccc, - 0, 0, 0, 0) - } - """, - fork=fork, + code=( + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH20("0xcccccccccccccccccccccccccccccccccccccccc") + + Op.GAS + + Op.DELEGATECALL + + Op.POP ), ), 0xC0DE: Account( balance=0, nonce=1, - code=Yul( - """ - { - let throwMe := delegatecall(gas(), - 0xcccccccccccccccccccccccccccccccccccccccc, - 0, 0, 0, 0) - } - """, - fork=fork, + code=( + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH20("0xcccccccccccccccccccccccccccccccccccccccc") + + Op.GAS + + Op.DELEGATECALL + + Op.POP ), ), "0xccccccccccccccccccccccccccccccccccccccce": Account( balance=0x20000000000, nonce=1, - code=Yul( - """ - { - let throwMe := call(gas(), 0xC0DE, 0x1000, - 0, 0, 0, 0) - throwMe := delegatecall(gas(), - 0xcccccccccccccccccccccccccccccccccccccccc, - 0, 0, 0, 0) - } - """, - fork=fork, + code=( + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH2("0x1000") + + Op.PUSH2("0xc0de") + + Op.GAS + + Op.CALL + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH20("0xcccccccccccccccccccccccccccccccccccccccc") + + Op.GAS + + Op.DELEGATECALL + + Op.SWAP1 + + Op.POP + + Op.POP ), ), } @@ -507,19 +491,15 @@ def blockchain_test_fixture( # noqa: D102 def test_fill_blockchain_valid_txs( # noqa: D102 self, fork: Fork, - solc_version: str, check_hive: bool, fixture_format: FixtureFormats, expected_json_file: str, - blockchain_test_fixture: Fixture, + blockchain_test_fixture: BlockchainFixture, ): assert blockchain_test_fixture.format == fixture_format assert isinstance(blockchain_test_fixture, FixtureCommon) - if solc_version >= SOLC_PADDING_VERSION: - fixture_name = f"000/my_blockchain_test/{fork.name()}/solc=padding_version" - else: - fixture_name = f"000/my_blockchain_test/{fork.name()}/solc={solc_version}" + fixture_name = f"000/my_blockchain_test/{fork.name()}" fixture = { fixture_name: blockchain_test_fixture.json_dict_with_info(hash_only=True), @@ -528,9 +508,8 @@ def test_fill_blockchain_valid_txs( # noqa: D102 with open( os.path.join( "src", - "ethereum_test_tools", + "ethereum_test_specs", "tests", - "test_filling", "fixtures", expected_json_file, ) @@ -543,7 +522,7 @@ def test_fill_blockchain_valid_txs( # noqa: D102 assert fixture[fixture_name] == expected[fixture_name] @pytest.mark.parametrize("fork", [London], indirect=True) - def test_fixture_header_join(self, blockchain_test_fixture: Fixture): + def test_fixture_header_join(self, blockchain_test_fixture: BlockchainFixture): """ Test `FixtureHeader.join()`. """ @@ -559,7 +538,7 @@ def test_fixture_header_join(self, blockchain_test_fixture: Fixture): transactions_trie=new_transactions_root, ) - updated_block_header = block.header.join(header_new_fields) # type: ignore + updated_block_header = header_new_fields.apply(block.header) # type: ignore assert updated_block_header.difficulty == new_difficulty assert updated_block_header.state_root == new_state_root assert updated_block_header.transactions_trie == Hash(new_transactions_root) @@ -574,9 +553,7 @@ def test_fixture_header_join(self, blockchain_test_fixture: Fixture): (Shanghai, True, "blockchain_shanghai_invalid_filled_hive.json"), ], ) -def test_fill_blockchain_invalid_txs( - fork: Fork, solc_version: str, check_hive: bool, expected_json_file: str -): +def test_fill_blockchain_invalid_txs(fork: Fork, check_hive: bool, expected_json_file: str): """ Test `ethereum_test.filler.fill_fixtures` with `BlockchainTest`. """ @@ -588,60 +565,63 @@ def test_fill_blockchain_invalid_txs( "0xcccccccccccccccccccccccccccccccccccccccc": Account( balance=0x10000000000, nonce=1, - code=Yul( - """ - { - sstore(number(), basefee()) - sstore(add(number(), 0x1000), sub(gasprice(), basefee())) - sstore(add(number(), 0x2000), selfbalance()) - stop() - } - """, - fork=fork, + code=( + Op.SSTORE(Op.NUMBER(), Op.BASEFEE()) + + Op.SSTORE(Op.ADD(Op.NUMBER(), 0x1000), Op.SUB(Op.GASPRICE(), Op.BASEFEE())) + + Op.SSTORE(Op.ADD(Op.NUMBER(), 0x2000), Op.SELFBALANCE()) + + Op.STOP() ), ), "0xcccccccccccccccccccccccccccccccccccccccd": Account( balance=0x20000000000, nonce=1, - code=Yul( - """ - { - let throwMe := delegatecall(gas(), - 0xcccccccccccccccccccccccccccccccccccccccc, - 0, 0, 0, 0) - } - """, - fork=fork, + code=( + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH20("0xcccccccccccccccccccccccccccccccccccccccc") + + Op.GAS + + Op.DELEGATECALL + + Op.POP ), ), 0xC0DE: Account( balance=0, nonce=1, - code=Yul( - """ - { - let throwMe := delegatecall(gas(), - 0xcccccccccccccccccccccccccccccccccccccccc, - 0, 0, 0, 0) - } - """, - fork=fork, + code=( + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH20("0xcccccccccccccccccccccccccccccccccccccccc") + + Op.GAS + + Op.DELEGATECALL + + Op.POP ), ), "0xccccccccccccccccccccccccccccccccccccccce": Account( balance=0x20000000000, nonce=1, - code=Yul( - """ - { - let throwMe := call(gas(), 0xC0DE, 0x1000, - 0, 0, 0, 0) - throwMe := delegatecall(gas(), - 0xcccccccccccccccccccccccccccccccccccccccc, - 0, 0, 0, 0) - } - """, - fork=fork, + code=( + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH2("0x1000") + + Op.PUSH2("0xc0de") + + Op.GAS + + Op.CALL + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + (Op.PUSH1(0) if fork < Shanghai else Op.PUSH0) + + Op.DUP1 + + Op.PUSH20("0xcccccccccccccccccccccccccccccccccccccccc") + + Op.GAS + + Op.DELEGATECALL + + Op.SWAP1 + + Op.POP + + Op.POP ), ), } @@ -891,10 +871,7 @@ def test_fill_blockchain_invalid_txs( assert generated_fixture.format == fixture_format assert isinstance(generated_fixture, FixtureCommon) - if solc_version >= SOLC_PADDING_VERSION: - fixture_name = f"000/my_blockchain_test/{fork.name()}/solc=padding_version" - else: - fixture_name = f"000/my_blockchain_test/{fork.name()}/solc={solc_version}" + fixture_name = f"000/my_blockchain_test/{fork.name()}" fixture = { fixture_name: generated_fixture.json_dict_with_info(hash_only=True), @@ -903,9 +880,8 @@ def test_fill_blockchain_invalid_txs( with open( os.path.join( "src", - "ethereum_test_tools", + "ethereum_test_specs", "tests", - "test_filling", "fixtures", expected_json_file, ) diff --git a/src/ethereum_test_tools/tests/test_types_blockchain_test.py b/src/ethereum_test_specs/tests/test_types.py similarity index 89% rename from src/ethereum_test_tools/tests/test_types_blockchain_test.py rename to src/ethereum_test_specs/tests/test_types.py index ff7e41e352..72aff9eeaa 100644 --- a/src/ethereum_test_tools/tests/test_types_blockchain_test.py +++ b/src/ethereum_test_specs/tests/test_types.py @@ -1,11 +1,13 @@ """ -Test the blockchain test types. +Test types from ethereum_test_specs. """ import pytest -from ..common.base_types import Address, Bloom, Bytes, Hash, HeaderNonce -from ..spec.blockchain.types import FixtureHeader, Header +from ethereum_test_base_types import Address, Bloom, Bytes, Hash, HeaderNonce +from ethereum_test_fixtures.blockchain import FixtureHeader + +from ..blockchain import Header fixture_header_ones = FixtureHeader( parent_hash=Hash(1), @@ -103,4 +105,7 @@ def test_fixture_header_join( fixture_header: FixtureHeader, modifier: Header, fixture_header_expected: FixtureHeader ): - assert fixture_header.join(modifier) == fixture_header_expected + """ + Test that the join method works as expected. + """ + assert modifier.apply(fixture_header) == fixture_header_expected diff --git a/src/ethereum_test_tools/__init__.py b/src/ethereum_test_tools/__init__.py index 74025be7a4..78a721bc72 100644 --- a/src/ethereum_test_tools/__init__.py +++ b/src/ethereum_test_tools/__init__.py @@ -3,33 +3,45 @@ tests. """ -from .code import ( - CalldataCase, - Case, - CodeGasMeasure, - Conditional, - Initcode, - Switch, - Yul, - YulCompiler, +from ethereum_test_base_types import ( + Account, + Address, + Hash, + TestAddress, + TestAddress2, + TestPrivateKey, + TestPrivateKey2, +) +from ethereum_test_base_types.reference_spec import ReferenceSpec, ReferenceSpecTypes +from ethereum_test_exceptions import ( + BlockException, + EngineAPIError, + EOFException, + TransactionException, +) +from ethereum_test_fixtures import BaseFixture, FixtureCollector, TestInfo +from ethereum_test_specs import ( + SPEC_TYPES, + BaseTest, + BlockchainTest, + BlockchainTestFiller, + EOFStateTest, + EOFStateTestFiller, + EOFTest, + EOFTestFiller, + StateTest, + StateTestFiller, ) -from .common import ( +from ethereum_test_specs.blockchain import Block, Header +from ethereum_test_types import ( EOA, AccessList, - Account, - Address, Alloc, DepositRequest, - EngineAPIError, Environment, - Hash, Removable, Storage, - TestAddress, - TestAddress2, TestParameterGroup, - TestPrivateKey, - TestPrivateKey2, Transaction, Withdrawal, WithdrawalRequest, @@ -42,25 +54,26 @@ cost_memory_bytes, eip_2028_transaction_data_cost, ) -from .exceptions import BlockException, EOFException, TransactionException -from .reference_spec import ReferenceSpec, ReferenceSpecTypes -from .spec import ( - SPEC_TYPES, - BaseFixture, - BaseTest, - BlockchainTest, - BlockchainTestFiller, - EOFStateTest, - EOFStateTestFiller, - EOFTest, - EOFTestFiller, - FixtureCollector, - StateTest, - StateTestFiller, - TestInfo, +from ethereum_test_vm import ( + Bytecode, + Macro, + Macros, + Opcode, + OpcodeCallArg, + Opcodes, + UndefinedOpcodes, +) + +from .code import ( + CalldataCase, + Case, + CodeGasMeasure, + Conditional, + Initcode, + Switch, + Yul, + YulCompiler, ) -from .spec.blockchain.types import Block, Header -from .vm import Bytecode, Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes __all__ = ( "SPEC_TYPES", @@ -126,4 +139,5 @@ "cost_memory_bytes", "eip_2028_transaction_data_cost", "eip_2028_transaction_data_cost", + "vm", ) diff --git a/src/ethereum_test_tools/code/generators.py b/src/ethereum_test_tools/code/generators.py index d64e482791..97524100db 100644 --- a/src/ethereum_test_tools/code/generators.py +++ b/src/ethereum_test_tools/code/generators.py @@ -5,9 +5,9 @@ from dataclasses import dataclass, field from typing import List, SupportsBytes -from ..common.helpers import ceiling_division -from ..vm.opcode import Bytecode -from ..vm.opcode import Opcodes as Op +from ethereum_test_types import ceiling_division +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op GAS_PER_DEPLOYED_CODE_BYTE = 0xC8 diff --git a/src/ethereum_test_tools/code/yul.py b/src/ethereum_test_tools/code/yul.py index 1e1a07b47e..83e331a2af 100644 --- a/src/ethereum_test_tools/code/yul.py +++ b/src/ethereum_test_tools/code/yul.py @@ -13,8 +13,7 @@ from semver import Version from ethereum_test_forks import Fork - -from ..vm import Bytecode +from ethereum_test_vm import Bytecode DEFAULT_SOLC_ARGS = ("--assemble", "-") VERSION_PATTERN = re.compile(r"Version: (.*)") diff --git a/src/ethereum_test_tools/eof/__init__.py b/src/ethereum_test_tools/eof/__init__.py index dc97c8eaa7..5ac3f3fdc8 100644 --- a/src/ethereum_test_tools/eof/__init__.py +++ b/src/ethereum_test_tools/eof/__init__.py @@ -1,6 +1,6 @@ """ -EVM Object Format Libary to generate bytecode for testing purposes +Mirror module to import `ethereum_test_types.eof`. """ -from .constants import LATEST_EOF_VERSION +from ethereum_test_types.eof import LATEST_EOF_VERSION __all__ = ("LATEST_EOF_VERSION",) diff --git a/src/ethereum_test_tools/eof/constants.py b/src/ethereum_test_tools/eof/constants.py index 06b68c576d..cc89e3e21b 100644 --- a/src/ethereum_test_tools/eof/constants.py +++ b/src/ethereum_test_tools/eof/constants.py @@ -1,21 +1,12 @@ """ -EVM Object Format generic constants. -Applicable to all EOF versions. -""" -EOF_MAGIC = b"\xef\x00" -""" -The second byte found on every EOF formatted contract, which was chosen to -avoid clashes with three contracts which were deployed on Mainnet. -""" -EOF_HEADER_TERMINATOR = b"\x00" -""" -Byte that terminates the header of the EOF format. -""" -LATEST_EOF_VERSION = 1 -""" -Latest existing EOF version. -""" -VERSION_BYTE_LENGTH = 1 -""" -Length of the version byte. -""" +Mirror file to import constants from ethereum_test_types.eof.constants +""" + +from ethereum_test_types.eof.constants import ( + EOF_HEADER_TERMINATOR, + EOF_MAGIC, + LATEST_EOF_VERSION, + VERSION_BYTE_LENGTH, +) + +__all__ = ("EOF_MAGIC", "EOF_HEADER_TERMINATOR", "LATEST_EOF_VERSION", "VERSION_BYTE_LENGTH") diff --git a/src/ethereum_test_tools/eof/v1/__init__.py b/src/ethereum_test_tools/eof/v1/__init__.py index 204d77da74..a0e0f671b4 100644 --- a/src/ethereum_test_tools/eof/v1/__init__.py +++ b/src/ethereum_test_tools/eof/v1/__init__.py @@ -1,563 +1,23 @@ """ -EVM Object Format Version 1 Library to generate bytecode for testing purposes +Mirror module to import `ethereum_test_types.eof.v1`. """ -from dataclasses import dataclass -from enum import Enum, IntEnum, auto -from functools import cached_property -from typing import Any, Dict, List, Optional, Tuple - -from pydantic import Field, GetCoreSchemaHandler -from pydantic_core.core_schema import ( - PlainValidatorFunctionSchema, - no_info_plain_validator_function, - to_string_ser_schema, +from ethereum_test_types.eof.v1 import ( + VERSION_MAX_SECTION_KIND, + AutoSection, + Container, + ContainerKind, + Initcode, + Section, + SectionKind, ) -from ...common import Bytes -from ...common.conversions import BytesConvertible -from ...common.types import CopyValidateModel -from ...exceptions import EOFException -from ...vm.opcode import Bytecode -from ...vm.opcode import Opcodes as Op -from ..constants import EOF_HEADER_TERMINATOR, EOF_MAGIC -from .constants import ( - HEADER_SECTION_COUNT_BYTE_LENGTH, - HEADER_SECTION_KIND_BYTE_LENGTH, - HEADER_SECTION_SIZE_BYTE_LENGTH, - NON_RETURNING_SECTION, - TYPES_INPUTS_BYTE_LENGTH, - TYPES_OUTPUTS_BYTE_LENGTH, - TYPES_STACK_BYTE_LENGTH, - VERSION_NUMBER_BYTES, +__all__ = ( + "VERSION_MAX_SECTION_KIND", + "AutoSection", + "Container", + "ContainerKind", + "Initcode", + "Section", + "SectionKind", ) - -VERSION_MAX_SECTION_KIND = 3 - - -class SectionKind(IntEnum): - """ - Enum class of V1 valid section kind values - """ - - TYPE = 1 - CODE = 2 - CONTAINER = 3 - DATA = 4 - - def __str__(self) -> str: - """ - Returns the string representation of the section kind - """ - return self.name - - -class ContainerKind(Enum): - """ - Enum class of V1 valid container kind values. - """ - - RUNTIME = auto() - INITCODE = auto() - - @staticmethod - def __get_pydantic_core_schema__( - source_type: Any, handler: GetCoreSchemaHandler - ) -> PlainValidatorFunctionSchema: - """ - Calls the class constructor without info and appends the serialization schema. - """ - return no_info_plain_validator_function( - source_type, - serialization=to_string_ser_schema(), - ) - - def __str__(self) -> str: - """ - Returns the string representation of the container kind - """ - return self.name - - -class AutoSection(Enum): - """ - Enum class for auto section generation approach - """ - - AUTO = 1 - ONLY_HEADER = 2 - ONLY_BODY = 3 - NONE = 4 - - def any(self) -> bool: - """ - Returns True if the enum is not NONE - """ - return self != AutoSection.NONE - - def header(self) -> bool: - """ - Returns True if the enum is not ONLY_BODY - """ - return self != AutoSection.ONLY_BODY and self != AutoSection.NONE - - def body(self) -> bool: - """ - Returns True if the enum is not ONLY_HEADER - """ - return self != AutoSection.ONLY_HEADER and self != AutoSection.NONE - - -SUPPORT_MULTI_SECTION_HEADER = [SectionKind.CODE, SectionKind.CONTAINER] - - -class Section(CopyValidateModel): - """ - Class that represents a section in an EOF V1 container. - """ - - data: Bytes = Bytes(b"") - """ - Data to be contained by this section. - Can be SupportsBytes, another EOF container or any other abstract data. - """ - custom_size: int = 0 - """ - Custom size value to be used in the header. - If unset, the header is built with length of the data. - """ - kind: SectionKind | int - """ - Kind of section that is represented by this object. - Can be any `int` outside of the values defined by `SectionKind` - for testing purposes. - """ - force_type_listing: bool = False - """ - Forces this section to appear in the TYPE section at the beginning of the - container. - """ - code_inputs: int = 0 - """ - Data stack items consumed by this code section (function) - """ - code_outputs: int = NON_RETURNING_SECTION - """ - Data stack items produced by or expected at the end of this code section - (function) - """ - max_stack_height: int = 0 - """ - Maximum height data stack reaches during execution of code section. - """ - auto_max_stack_height: bool = False - """ - Whether to automatically compute the best suggestion for the - max_stack_height value for this code section. - """ - auto_code_inputs_outputs: bool = False - """ - Whether to automatically compute the best suggestion for the code_inputs, - code_outputs values for this code section. - """ - skip_header_listing: bool = False - """ - Skip section from listing in the header - """ - skip_body_listing: bool = False - """ - Skip section from listing in the body - """ - skip_types_body_listing: bool = False - """ - Skip section from listing in the types body (input, output, stack) bytes - """ - skip_types_header_listing: bool = False - """ - Skip section from listing in the types header (not calculating input, output, stack size) - """ - - @cached_property - def header(self) -> bytes: - """ - Get formatted header for this section according to its contents. - """ - size = self.custom_size if "custom_size" in self.model_fields_set else len(self.data) - if self.kind == SectionKind.CODE: - raise Exception("Need container-wide view of code sections to generate header") - return self.kind.to_bytes( - HEADER_SECTION_KIND_BYTE_LENGTH, byteorder="big" - ) + size.to_bytes(HEADER_SECTION_SIZE_BYTE_LENGTH, byteorder="big") - - @cached_property - def type_definition(self) -> bytes: - """ - Returns a serialized type section entry for this section. - """ - if self.kind != SectionKind.CODE and not self.force_type_listing: - return bytes() - - code_inputs, code_outputs, max_stack_height = ( - self.code_inputs, - self.code_outputs, - self.max_stack_height, - ) - if self.auto_max_stack_height or self.auto_code_inputs_outputs: - ( - auto_code_inputs, - auto_code_outputs, - auto_max_height, - ) = compute_code_stack_values(self.data) - if self.auto_max_stack_height: - max_stack_height = auto_max_height - if self.auto_code_inputs_outputs: - code_inputs, code_outputs = ( - auto_code_inputs, - auto_code_outputs, - ) - - return ( - code_inputs.to_bytes(length=TYPES_INPUTS_BYTE_LENGTH, byteorder="big") - + code_outputs.to_bytes(length=TYPES_OUTPUTS_BYTE_LENGTH, byteorder="big") - + max_stack_height.to_bytes(length=TYPES_STACK_BYTE_LENGTH, byteorder="big") - ) - - def with_max_stack_height(self, max_stack_height) -> "Section": - """ - Creates a copy of the section with `max_stack_height` set to the - specified value. - """ - return self.copy(max_stack_height=max_stack_height) - - def with_auto_max_stack_height(self) -> "Section": - """ - Creates a copy of the section with `auto_max_stack_height` set to True. - """ - return self.copy(auto_max_stack_height=True) - - def with_auto_code_inputs_outputs(self) -> "Section": - """ - Creates a copy of the section with `auto_code_inputs_outputs` set to - True. - """ - return self.copy(auto_code_inputs_outputs=True) - - @staticmethod - def list_header(sections: List["Section"]) -> bytes: - """ - Creates the single code header for all code sections contained in - the list. - """ - # Allow 'types section' to use skip_header_listing flag - if sections[0].skip_header_listing: - return b"" - - if sections[0].kind not in SUPPORT_MULTI_SECTION_HEADER: - return b"".join(s.header for s in sections) - - h = sections[0].kind.to_bytes(HEADER_SECTION_KIND_BYTE_LENGTH, "big") - - # Count only those sections that are not marked to be skipped for header calculation - header_registered_sections = 0 - for cs in sections: - if not cs.skip_header_listing: - header_registered_sections += 1 - - h += header_registered_sections.to_bytes(HEADER_SECTION_COUNT_BYTE_LENGTH, "big") - for cs in sections: - # If section is marked to skip the header calculation, don't make header for it - if cs.skip_header_listing: - continue - size = cs.custom_size if "custom_size" in cs.model_fields_set else len(cs.data) - h += size.to_bytes(HEADER_SECTION_SIZE_BYTE_LENGTH, "big") - - return h - - @classmethod - def Code( # noqa: N802 - cls, code: BytesConvertible | Bytecode = Bytecode(), **kwargs - ) -> "Section": - """ - Creates a new code section with the specified code. - """ - kwargs.pop("kind", None) - if "max_stack_height" not in kwargs and isinstance(code, Bytecode): - kwargs["max_stack_height"] = code.max_stack_height - return cls(kind=SectionKind.CODE, data=code, **kwargs) - - @classmethod - def Container( # noqa: N802 - cls, container: "Container" | BytesConvertible, **kwargs - ) -> "Section": - """ - Creates a new container section with the specified container. - """ - kwargs.pop("kind", None) - return cls(kind=SectionKind.CONTAINER, data=container, **kwargs) - - @classmethod - def Data(cls, data: BytesConvertible = b"", **kwargs) -> "Section": # noqa: N802 - """ - Creates a new data section with the specified data. - """ - kwargs.pop("kind", None) - return cls(kind=SectionKind.DATA, data=data, **kwargs) - - -class Container(CopyValidateModel): - """ - Class that represents an EOF V1 container. - """ - - name: Optional[str] = None - """ - Name of the container - """ - sections: List[Section] = Field(default_factory=list) - """ - List of sections in the container - """ - magic: Bytes = Bytes(EOF_MAGIC) - """ - Custom magic value used to override the mandatory EOF value for testing - purposes. - """ - version: Bytes = Bytes(VERSION_NUMBER_BYTES) - """ - Custom version value used to override the mandatory EOF V1 value - for testing purposes. - """ - header_terminator: Bytes = Bytes(EOF_HEADER_TERMINATOR) - """ - Bytes used to terminate the header. - """ - extra: Bytes = Bytes(b"") - """ - Extra data to be appended at the end of the container, which will - not be considered part of any of the sections, for testing purposes. - """ - auto_type_section: AutoSection = AutoSection.AUTO - """ - Automatically generate a `TYPE` section based on the - included `CODE` kind sections. - """ - auto_data_section: bool = True - """ - Automatically generate a `DATA` section. - """ - auto_sort_sections: AutoSection = AutoSection.AUTO - """ - Automatically sort sections for the header and body: - Headers: type section first, all code sections, container sections, last - data section(s) - Body: type section first, all code sections, data section(s), last - container sections - """ - validity_error: EOFException | str | None = None - """ - Optional error expected for the container. - - TODO: Remove str - """ - kind: ContainerKind = ContainerKind.RUNTIME - """ - Kind type of the container. - """ - raw_bytes: Optional[Bytes] = None - """ - Optional raw bytes that represent the container. - Used to have a cohesive type among all test cases, even those that do not - resemble a valid EOF V1 container. - """ - - @cached_property - def bytecode(self) -> bytes: - """ - Converts the EOF V1 Container into bytecode. - """ - if self.raw_bytes is not None: - assert len(self.sections) == 0 - return self.raw_bytes - - c = self.magic + self.version - - # Prepare auto-generated sections - sections = self.sections - - # Add type section if needed - if self.auto_type_section.any() and count_sections(sections, SectionKind.TYPE) == 0: - # Calculate skipping flags - types_header_size = 0 - type_section_data = b"" - for s in sections: - types_header_size += ( - len(s.type_definition) if not s.skip_types_header_listing else 0 - ) - type_section_data += s.type_definition if not s.skip_types_body_listing else b"" - - sections = [ - Section( - kind=SectionKind.TYPE, data=type_section_data, custom_size=types_header_size - ) - ] + sections - - # Add data section if needed - if self.auto_data_section and count_sections(sections, SectionKind.DATA) == 0: - sections = sections + [Section(kind=SectionKind.DATA, data="0x")] - - header_sections = [ - s - for s in sections - if s.kind != SectionKind.TYPE or self.auto_type_section != AutoSection.ONLY_BODY - ] - if self.auto_sort_sections.header(): - header_sections.sort(key=lambda x: x.kind) - - # Add headers - if header_sections: - # Join headers of the same kind in a list of lists, only if they are next to each other - concurrent_sections: List[List[Section]] = [[header_sections[0]]] - for s in header_sections[1:]: - if s.kind == concurrent_sections[-1][-1].kind: - concurrent_sections[-1].append(s) - else: - concurrent_sections.append([s]) - c += b"".join(Section.list_header(cs) for cs in concurrent_sections) - - # Add header terminator - c += self.header_terminator - - body_sections = sections[:] - if self.auto_sort_sections.body(): - # Sort sections for the body - body_sections.sort(key=lambda x: x.kind) - - # Add section bodies - for s in body_sections: - if s.kind == SectionKind.TYPE and self.auto_type_section == AutoSection.ONLY_HEADER: - continue - if s.data and not s.skip_body_listing: - c += s.data - - # Add extra (garbage) - c += self.extra - - return c - - @classmethod - def Code(cls, code: BytesConvertible = Bytecode(), **kwargs) -> "Container": # noqa: N802 - """ - Creates simple container with a single code section. - """ - kwargs.pop("kind", None) - return cls(sections=[Section.Code(code=code, **kwargs)]) - - def __bytes__(self) -> bytes: - """ - Returns the bytecode of the container. - """ - return self.bytecode - - def __len__(self) -> int: - """ - Returns the length of the container bytecode. - """ - return len(self.bytecode) - - -@dataclass(kw_only=True) -class Initcode(Bytecode): - """ - Helper class used to generate initcode for the specified deployment code, - using EOF V1 container as init code. - """ - - name: str = "EOF V1 Initcode" - """ - Name used to identify the initcode. - """ - deploy_container: Container - """ - Container to be deployed. - """ - - @cached_property - def init_container(self) -> Container: - """ - Generate a container that will be used as the initcode. - """ - return Container( - sections=[ - Section.Code( - code=Op.RETURNCONTRACT[0](0, 0), - max_stack_height=2, - ), - Section.Container( - container=self.deploy_container, - ), - ], - ) - - @cached_property - def bytecode(self) -> bytes: - """ - Generate an EOF container performs `EOFCREATE` with the specified code. - """ - initcode = Container( - sections=[ - Section.Code( - # TODO: Pass calldata - code=Op.EOFCREATE[0](0, 0, 0, 0) + Op.STOP(), - max_stack_height=4, - ), - Section.Container( - container=self.init_container, - ), - ] - ) - - return bytes(initcode) - - -def count_sections(sections: List[Section], kind: SectionKind | int) -> int: - """ - Counts sections from a list that match a specific kind - """ - return len([s for s in sections if s.kind == kind]) - - -OPCODE_MAP: Dict[int, Op] = {x.int(): x for x in Op} - - -def compute_code_stack_values(code: bytes) -> Tuple[int, int, int]: - """ - Computes the stack values for the given bytecode. - - TODO: THIS DOES NOT WORK WHEN THE RJUMP* JUMPS BACKWARDS (and many other - things). - """ - i = 0 - stack_height = 0 - min_stack_height = 0 - max_stack_height = 0 - - # compute type annotation - while i < len(code): - op = OPCODE_MAP.get(code[i]) - if op is None: - return (0, 0, 0) - elif op == Op.RJUMPV: - i += 1 - if i < len(code): - count = code[i] - i += count * 2 - else: - i += 1 + op.data_portion_length - - stack_height -= op.popped_stack_items - min_stack_height = min(stack_height, min_stack_height) - stack_height += op.pushed_stack_items - max_stack_height = max(stack_height, max_stack_height) - if stack_height < 0: - stack_height = 0 - return (abs(min_stack_height), stack_height, max_stack_height) diff --git a/src/ethereum_test_tools/eof/v1/constants.py b/src/ethereum_test_tools/eof/v1/constants.py index 6fa8072523..4160bcae27 100644 --- a/src/ethereum_test_tools/eof/v1/constants.py +++ b/src/ethereum_test_tools/eof/v1/constants.py @@ -1,39 +1,43 @@ """ -EVM Object Format generic constants. -Applicable to EOF version 1. +Mirror module to import `ethereum_test_types.eof.v1.constants`. """ -from ..constants import VERSION_BYTE_LENGTH -VERSION_NUMBER = 0x01 - -VERSION_NUMBER_BYTES = VERSION_NUMBER.to_bytes(VERSION_BYTE_LENGTH, "big") - -MAX_CODE_SECTIONS = 1024 - -MAX_RETURN_STACK_HEIGHT = 1024 - -MAX_OPERAND_STACK_HEIGHT = 1023 - -MAX_CODE_INPUTS = 127 - -MAX_CODE_OUTPUTS = 127 - -NON_RETURNING_SECTION = 0x80 - -MAX_RJUMPV_COUNT = 0xFF - -MAX_BYTECODE_SIZE = 24576 - -MAX_INITCODE_SIZE = MAX_BYTECODE_SIZE * 2 - -HEADER_SECTION_KIND_BYTE_LENGTH = 1 - -HEADER_SECTION_COUNT_BYTE_LENGTH = 2 - -HEADER_SECTION_SIZE_BYTE_LENGTH = 2 - -TYPES_INPUTS_BYTE_LENGTH = 1 - -TYPES_OUTPUTS_BYTE_LENGTH = 1 - -TYPES_STACK_BYTE_LENGTH = 2 +from ethereum_test_types.eof.v1.constants import ( + HEADER_SECTION_COUNT_BYTE_LENGTH, + HEADER_SECTION_KIND_BYTE_LENGTH, + HEADER_SECTION_SIZE_BYTE_LENGTH, + MAX_BYTECODE_SIZE, + MAX_CODE_INPUTS, + MAX_CODE_OUTPUTS, + MAX_CODE_SECTIONS, + MAX_INITCODE_SIZE, + MAX_OPERAND_STACK_HEIGHT, + MAX_RETURN_STACK_HEIGHT, + MAX_RJUMPV_COUNT, + NON_RETURNING_SECTION, + TYPES_INPUTS_BYTE_LENGTH, + TYPES_OUTPUTS_BYTE_LENGTH, + TYPES_STACK_BYTE_LENGTH, + VERSION_NUMBER, + VERSION_NUMBER_BYTES, +) + +__all__ = ( + "HEADER_SECTION_COUNT_BYTE_LENGTH", + "HEADER_SECTION_KIND_BYTE_LENGTH", + "HEADER_SECTION_SIZE_BYTE_LENGTH", + "MAX_BYTECODE_SIZE", + "MAX_CODE_INPUTS", + "MAX_CODE_OUTPUTS", + "MAX_CODE_SECTIONS", + "MAX_INITCODE_SIZE", + "MAX_OPERAND_STACK_HEIGHT", + "MAX_RETURN_STACK_HEIGHT", + "MAX_RJUMPV_COUNT", + "NON_RETURNING_SECTION", + "TYPES_INPUTS_BYTE_LENGTH", + "TYPES_OUTPUTS_BYTE_LENGTH", + "TYPES_STACK_BYTE_LENGTH", + "VERSION_NUMBER", + "VERSION_NUMBER_BYTES", +) diff --git a/src/ethereum_test_tools/rpc/rpc.py b/src/ethereum_test_tools/rpc/rpc.py index a5ebd30247..c438274199 100644 --- a/src/ethereum_test_tools/rpc/rpc.py +++ b/src/ethereum_test_tools/rpc/rpc.py @@ -8,7 +8,7 @@ import requests from tenacity import retry, stop_after_attempt, wait_exponential -from ethereum_test_tools import Address +from ethereum_test_base_types import Address BlockNumberType = Union[int, Literal["latest", "earliest", "pending"]] diff --git a/src/ethereum_test_tools/spec/base/__init__.py b/src/ethereum_test_tools/spec/base/__init__.py deleted file mode 100644 index 0519b8f7a2..0000000000 --- a/src/ethereum_test_tools/spec/base/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -BaseTest spec class and utilities. -""" diff --git a/src/ethereum_test_tools/spec/blockchain/__init__.py b/src/ethereum_test_tools/spec/blockchain/__init__.py deleted file mode 100644 index 4a58da648e..0000000000 --- a/src/ethereum_test_tools/spec/blockchain/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -BlockchainTest type definitions and logic -""" diff --git a/src/ethereum_test_tools/spec/consume/__init__.py b/src/ethereum_test_tools/spec/consume/__init__.py deleted file mode 100644 index c6378cbf8b..0000000000 --- a/src/ethereum_test_tools/spec/consume/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Defines pydantic models used by the consume commands. -""" diff --git a/src/ethereum_test_tools/spec/eof/__init__.py b/src/ethereum_test_tools/spec/eof/__init__.py deleted file mode 100644 index b080b6222d..0000000000 --- a/src/ethereum_test_tools/spec/eof/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -EOFTest type definitions and logic -""" diff --git a/src/ethereum_test_tools/spec/file/__init__.py b/src/ethereum_test_tools/spec/file/__init__.py deleted file mode 100644 index 56a9e21e6e..0000000000 --- a/src/ethereum_test_tools/spec/file/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Defines top-level types used in JSON fixture files. -""" diff --git a/src/ethereum_test_tools/spec/state/__init__.py b/src/ethereum_test_tools/spec/state/__init__.py deleted file mode 100644 index ed5114b881..0000000000 --- a/src/ethereum_test_tools/spec/state/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -StateTest type definitions and logic -""" diff --git a/src/ethereum_test_tools/tests/test_code.py b/src/ethereum_test_tools/tests/test_code.py index b37fb9f661..2a42ef2828 100644 --- a/src/ethereum_test_tools/tests/test_code.py +++ b/src/ethereum_test_tools/tests/test_code.py @@ -8,6 +8,8 @@ import pytest from semver import Version +from ethereum_test_base_types import Account, Bytes, Hash +from ethereum_test_fixtures import FixtureFormats from ethereum_test_forks import ( Cancun, Fork, @@ -16,12 +18,12 @@ get_closest_fork_with_solc_support, get_deployed_forks, ) -from evm_transition_tool import FixtureFormats, GethTransitionTool +from ethereum_test_specs import StateTest +from ethereum_test_types import Alloc, Environment, Transaction +from ethereum_test_vm import Opcodes as Op +from evm_transition_tool import GethTransitionTool from ..code import CalldataCase, Case, Conditional, Initcode, Solc, Switch, Yul -from ..common import Account, Alloc, Bytes, Environment, Hash, Transaction -from ..spec import StateTest -from ..vm.opcode import Opcodes as Op from .conftest import SOLC_PADDING_VERSION diff --git a/src/ethereum_test_tools/tests/test_filling/__init__.py b/src/ethereum_test_tools/tests/test_filling/__init__.py deleted file mode 100644 index 7ae47ad3a8..0000000000 --- a/src/ethereum_test_tools/tests/test_filling/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -`ethereum_test_tools.filling` verification tests. -""" diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_invalid_filled.json b/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_invalid_filled.json deleted file mode 100644 index 187e871947..0000000000 --- a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_london_invalid_filled.json +++ /dev/null @@ -1,1084 +0,0 @@ -{ - "000/my_blockchain_test/London/solc=0.8.20": { - "_info": { - "hash": "0x4de3f84e3cb1e678141d81ce96ce75edb53f1824a708e26098b610c3c1030e66" - }, - "network": "London", - "genesisRLP": "0xf90200f901fba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a089a5be1d3306f6f05b42678ef13ac3dbc37bef9a2a80862c21eb22eee29194c2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008088016345785d8a0000808000a000000000000000000000000000000000000000000000000000000000000000008800000000000000008203e8c0c0", - "genesisBlockHeader": { - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x89a5be1d3306f6f05b42678ef13ac3dbc37bef9a2a80862c21eb22eee29194c2", - "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x00", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x00", - "timestamp": "0x00", - "extraData": "0x00", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x03e8", - "hash": "0x6241b4534da26b654ec5bb30d29b1d5202454af544b05828433354da7471957c" - }, - "blocks": [ - { - "rlp": "0xf9026ef901fea06241b4534da26b654ec5bb30d29b1d5202454af544b05828433354da7471957ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a03eb2e72e8ed9a59768bb9ac05915b781a764f2582edcf111053fe6531e466613a0586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017ba029b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000188016345785d8a0000830155340c80a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082036bf86ab86802f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625bc0", - "blockHeader": { - "parentHash": "0x6241b4534da26b654ec5bb30d29b1d5202454af544b05828433354da7471957c", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x3eb2e72e8ed9a59768bb9ac05915b781a764f2582edcf111053fe6531e466613", - "transactionsTrie": "0x586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017b", - "receiptTrie": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x01", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x015534", - "timestamp": "0x0c", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x036b", - "hash": "0x12bba91a7e1f277f1549e832e06820f8849308f70f8659acf846bdc15f5d586e" - }, - "blocknumber": "1", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x00", - "maxPriorityFeePerGas": "0x01", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x01", - "accessList": [], - "v": "0x00", - "r": "0x3351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58", - "s": "0x67817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf90349f901fea012bba91a7e1f277f1549e832e06820f8849308f70f8659acf846bdc15f5d586ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0d9d9cc8ae73834ba9dc75fe8c68d36e980c82fcaf887dc220a05f152a327ae55a05521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298a0e225d44649351c3dccc61c1d904451d6f0f5a407c072099fe1085cfad88447d6b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000288016345785d8a000083053c421880a000000000000000000000000000000000000000000000000000000000000000008800000000000000008202fef90144b86a02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0b86a02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64db86a02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3ac0", - "blockHeader": { - "parentHash": "0x12bba91a7e1f277f1549e832e06820f8849308f70f8659acf846bdc15f5d586e", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xd9d9cc8ae73834ba9dc75fe8c68d36e980c82fcaf887dc220a05f152a327ae55", - "transactionsTrie": "0x5521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298", - "receiptTrie": "0xe225d44649351c3dccc61c1d904451d6f0f5a407c072099fe1085cfad88447d6", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x02", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c42", - "timestamp": "0x18", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x02fe", - "hash": "0x0e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010" - }, - "blocknumber": "2", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x01", - "maxPriorityFeePerGas": "0x0a", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0201", - "accessList": [], - "v": "0x00", - "r": "0x6ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050", - "s": "0x52f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x02", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0202", - "accessList": [], - "v": "0x00", - "r": "0x218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825d", - "s": "0x58b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x03", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0203", - "accessList": [], - "v": "0x01", - "r": "0x339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782a", - "s": "0x74004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf902e1f901fea00e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a069f3a735c7a7e1ea24a03a7107eba6a880d2d0251aaf24eaa7f109ece7969bf9a07c6d7fe1d1734fca072880e563f763405dc362222d37487cb098a006f7db3b2ca0976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4efb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a0000830155442480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff8ddb86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86d02f86a0105830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820302c080a06c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715a01220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9bc0", - "expectException": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "rlp_decoded": { - "blockHeader": { - "parentHash": "0x0e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x69f3a735c7a7e1ea24a03a7107eba6a880d2d0251aaf24eaa7f109ece7969bf9", - "transactionsTrie": "0x7c6d7fe1d1734fca072880e563f763405dc362222d37487cb098a006f7db3b2c", - "receiptTrie": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x03", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x015544", - "timestamp": "0x24", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x029f", - "hash": "0x0cb9b60de1bb3893d7b7b806562a78aca5e9fbff47bf62893a5f6c0afcc73b48" - }, - "blocknumber": "3", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x04", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0301", - "accessList": [], - "v": "0x01", - "r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63", - "s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x05", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0302", - "accessList": [], - "v": "0x00", - "r": "0x6c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715", - "s": "0x1220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9b", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - } - }, - { - "rlp": "0xf9034ff901fea00e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0bb08d7ca9c904f3d01b78041a9d70f69e83b0a6ec7af471cbd00933a47fdacaea027f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652a0f42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a000083053c422480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff9014ab86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86a02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33b86e02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0cc0", - "blockHeader": { - "parentHash": "0x0e043cb2eb0339900f6199c0ab517e5be3a81d898fa58078ed8b866ddc60b010", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xbb08d7ca9c904f3d01b78041a9d70f69e83b0a6ec7af471cbd00933a47fdacae", - "transactionsTrie": "0x27f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652", - "receiptTrie": "0xf42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2e", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x03", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c42", - "timestamp": "0x24", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x029f", - "hash": "0x5c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8e" - }, - "blocknumber": "3", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x04", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0301", - "accessList": [], - "v": "0x01", - "r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63", - "s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x05", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0303", - "accessList": [], - "v": "0x00", - "r": "0x9c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512e", - "s": "0x7a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x06", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x0186a0", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0304", - "accessList": [], - "v": "0x01", - "r": "0xc8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6a", - "s": "0x3e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf902e1f901fea05c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0e834ba6cd27f2702b0adf2ef6a85e2fbc340fb948c96e75b674e9a73a5dbc3d1a04722f7b17f27aee5dfa0d92ba40e16de960374a98ec63e728acaa1564d8a54f3a0976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4efb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a0000830155443080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf8ddb86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86d02f86a0108830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820402c001a0ebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23a0341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7c0", - "expectException": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "rlp_decoded": { - "blockHeader": { - "parentHash": "0x5c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8e", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xe834ba6cd27f2702b0adf2ef6a85e2fbc340fb948c96e75b674e9a73a5dbc3d1", - "transactionsTrie": "0x4722f7b17f27aee5dfa0d92ba40e16de960374a98ec63e728acaa1564d8a54f3", - "receiptTrie": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x04", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x015544", - "timestamp": "0x30", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x024c", - "hash": "0x1f01f6d8ff3a461486c4c4334c94a05f114d161b1ac082c7374ad7ac51eea7f2" - }, - "blocknumber": "4", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x07", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0401", - "accessList": [], - "v": "0x01", - "r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c", - "s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x08", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0402", - "accessList": [], - "v": "0x01", - "r": "0xebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23", - "s": "0x341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - } - }, - { - "rlp": "0xf9034ff901fea05c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0e2b2b992b108bcd0e036067ef693f2d1b94c2f48d074a4f6b9d98537bbf15e9aa07617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331a0f42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a000083053c423080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf9014ab86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86a02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29db86e02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0c0", - "blockHeader": { - "parentHash": "0x5c66e5b6d6513ec98e9d8ee88137f1a2418542550977ea02015439acd2bf8f8e", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xe2b2b992b108bcd0e036067ef693f2d1b94c2f48d074a4f6b9d98537bbf15e9a", - "transactionsTrie": "0x7617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331", - "receiptTrie": "0xf42d43454db7c51eadf004bd9e43522c4894f02c602b709cd45e67597c622f2e", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x04", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c42", - "timestamp": "0x30", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x024c", - "hash": "0xf5e2f23d9a212edbb35a07bc9f582f4a632b694bd4ef8742de8ad6c6acacf72c" - }, - "blocknumber": "4", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x07", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0401", - "accessList": [], - "v": "0x01", - "r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c", - "s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x08", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0403", - "accessList": [], - "v": "0x00", - "r": "0x8d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15", - "s": "0x3cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x09", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x0186a0", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0404", - "accessList": [], - "v": "0x01", - "r": "0x54bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9", - "s": "0x6f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - } - ], - "lastblockhash": "0xf5e2f23d9a212edbb35a07bc9f582f4a632b694bd4ef8742de8ad6c6acacf72c", - "pre": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": {} - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x00", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": {} - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x60008060008061100061c0de5af160008060008073cccccccccccccccccccccccccccccccccccccccc5af4905050", - "storage": {} - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "postState": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x3000", - "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x1000", - "0x2003": "0x2000", - "0x2004": "0x3000" - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x0a", - "balance": "0xfffffffffba0afe5e7", - "code": "0x", - "storage": {} - }, - "0xba5e000000000000000000000000000000000000": { - "nonce": "0x00", - "balance": "0x6f05b5a16c783b4b", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": { - "0x01": "0x036b", - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1001": "0x01", - "0x1002": "0x0a", - "0x1003": "0x0149", - "0x1004": "0x019c", - "0x2001": "0x010000000000", - "0x2002": "0x010000000000", - "0x2003": "0x010000000000", - "0x2004": "0x010000000000" - } - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x60008060008073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x018401", - "0x1004": "0x018454", - "0x2002": "0x020000000000", - "0x2003": "0x020000000000", - "0x2004": "0x020000000000" - } - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x01ffffffd000", - "code": "0x60008060008061100061c0de5af160008060008073cccccccccccccccccccccccccccccccccccccccc5af4905050", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x01fffffff000", - "0x2003": "0x01ffffffe000", - "0x2004": "0x01ffffffd000" - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "sealEngine": "NoProof" - }, - "000/my_blockchain_test/London/solc=padding_version": { - "_info": { - "hash": "0x8000076c72a719ca288d123862ae11108362a34268fa39c61228cf6e3667ca05" - }, - "network": "London", - "genesisRLP": "0xf90200f901fba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0de1557ffdf9765e61095937bf835742ca427008f33714bee743010ab2d1e0ba6a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008088016345785d8a0000808000a000000000000000000000000000000000000000000000000000000000000000008800000000000000008203e8c0c0", - "genesisBlockHeader": { - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xde1557ffdf9765e61095937bf835742ca427008f33714bee743010ab2d1e0ba6", - "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x00", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x00", - "timestamp": "0x00", - "extraData": "0x00", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x03e8", - "hash": "0xc552af8a2644e24df2f54d14aa70f207146dda49b746cc2e0af88e185f043d2e" - }, - "blocks": [ - { - "rlp": "0xf9026ef901fea0c552af8a2644e24df2f54d14aa70f207146dda49b746cc2e0af88e185f043d2ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a06bbd44292c9016cf53472d8ef579a1805a9008b898c5f159248ed106532b667ba0586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017ba029b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000188016345785d8a0000830155340c80a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082036bf86ab86802f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625bc0", - "blockHeader": { - "parentHash": "0xc552af8a2644e24df2f54d14aa70f207146dda49b746cc2e0af88e185f043d2e", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x6bbd44292c9016cf53472d8ef579a1805a9008b898c5f159248ed106532b667b", - "transactionsTrie": "0x586f963eea0fb4726f0f91f895f2aa5d67bffb5207a529b40d781244a0c7017b", - "receiptTrie": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x01", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x015534", - "timestamp": "0x0c", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x036b", - "hash": "0x337a985aa58c1b900b9e77b29101a76d9d22366defe3f6f7c005c5cad0f70758" - }, - "blocknumber": "1", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x00", - "maxPriorityFeePerGas": "0x01", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x01", - "accessList": [], - "v": "0x00", - "r": "0x3351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58", - "s": "0x67817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf90349f901fea0337a985aa58c1b900b9e77b29101a76d9d22366defe3f6f7c005c5cad0f70758a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a015413d90c7cf94b4eb779f4b99cfed8cf296ffacf5a5c19557cdd83e7af3adcea05521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298a0d0f659459422a274c9cfc8b15ad25ea1def3ade376a5759b9a1cf97b185f0bd1b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000288016345785d8a000083053c391880a000000000000000000000000000000000000000000000000000000000000000008800000000000000008202fef90144b86a02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0b86a02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64db86a02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3ac0", - "blockHeader": { - "parentHash": "0x337a985aa58c1b900b9e77b29101a76d9d22366defe3f6f7c005c5cad0f70758", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x15413d90c7cf94b4eb779f4b99cfed8cf296ffacf5a5c19557cdd83e7af3adce", - "transactionsTrie": "0x5521d9ad5adef72f021e4270a1f6851ca772dd56acaf4ff03362151bfb715298", - "receiptTrie": "0xd0f659459422a274c9cfc8b15ad25ea1def3ade376a5759b9a1cf97b185f0bd1", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x02", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c39", - "timestamp": "0x18", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x02fe", - "hash": "0x15676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2d" - }, - "blocknumber": "2", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x01", - "maxPriorityFeePerGas": "0x0a", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0201", - "accessList": [], - "v": "0x00", - "r": "0x6ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050", - "s": "0x52f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x02", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0202", - "accessList": [], - "v": "0x00", - "r": "0x218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825d", - "s": "0x58b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x03", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0203", - "accessList": [], - "v": "0x01", - "r": "0x339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782a", - "s": "0x74004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf902e1f901fea015676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0c12121517d65ac698ab8a67e75e208a9c11c3f02c1d380fc370375306e16971ea07c6d7fe1d1734fca072880e563f763405dc362222d37487cb098a006f7db3b2ca0976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4efb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a0000830155442480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff8ddb86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86d02f86a0105830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820302c080a06c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715a01220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9bc0", - "expectException": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "rlp_decoded": { - "blockHeader": { - "parentHash": "0x15676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2d", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xc12121517d65ac698ab8a67e75e208a9c11c3f02c1d380fc370375306e16971e", - "transactionsTrie": "0x7c6d7fe1d1734fca072880e563f763405dc362222d37487cb098a006f7db3b2c", - "receiptTrie": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x03", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x015544", - "timestamp": "0x24", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x029f", - "hash": "0xf3ad606edcdfb24e7b24e32328334b3ddf5149ecd6c45ccbd4d39628a4ef2a85" - }, - "blocknumber": "3", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x04", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0301", - "accessList": [], - "v": "0x01", - "r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63", - "s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x05", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0302", - "accessList": [], - "v": "0x00", - "r": "0x6c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715", - "s": "0x1220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9b", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - } - }, - { - "rlp": "0xf9034ff901fea015676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a0f93e92966505fc44657cc1977ac7ad5b1b4f43c20145a5df18240e3341cfa379a027f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652a0ce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000388016345785d8a000083053c392480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082029ff9014ab86c02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169b86a02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33b86e02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0cc0", - "blockHeader": { - "parentHash": "0x15676cbd68ac93fede6f8192b19868145f17d2f89e231de456925dea93664e2d", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xf93e92966505fc44657cc1977ac7ad5b1b4f43c20145a5df18240e3341cfa379", - "transactionsTrie": "0x27f7b224df1d270bfa03ba564cd4962071b89f91c965dbbfacff55e7ec66c652", - "receiptTrie": "0xce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7d", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x03", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c39", - "timestamp": "0x24", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x029f", - "hash": "0x0817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79ce" - }, - "blocknumber": "3", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x04", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0301", - "accessList": [], - "v": "0x01", - "r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63", - "s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x05", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0303", - "accessList": [], - "v": "0x00", - "r": "0x9c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512e", - "s": "0x7a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x06", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x0186a0", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0304", - "accessList": [], - "v": "0x01", - "r": "0xc8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6a", - "s": "0x3e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - }, - { - "rlp": "0xf902e1f901fea00817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79cea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a04a631519f4a7675eb6edb98719287ab1d1896111acd02dde544386ef63445fdaa04722f7b17f27aee5dfa0d92ba40e16de960374a98ec63e728acaa1564d8a54f3a0976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4efb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a0000830155443080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf8ddb86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86d02f86a0108830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820402c001a0ebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23a0341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7c0", - "expectException": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "rlp_decoded": { - "blockHeader": { - "parentHash": "0x0817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79ce", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x4a631519f4a7675eb6edb98719287ab1d1896111acd02dde544386ef63445fda", - "transactionsTrie": "0x4722f7b17f27aee5dfa0d92ba40e16de960374a98ec63e728acaa1564d8a54f3", - "receiptTrie": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x04", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x015544", - "timestamp": "0x30", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x024c", - "hash": "0xc80ae3f610a2adb971179fc1e1bc120f3b38c88ff388cf059809a579be6e5f2c" - }, - "blocknumber": "4", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x07", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0401", - "accessList": [], - "v": "0x01", - "r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c", - "s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x08", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0402", - "accessList": [], - "v": "0x01", - "r": "0xebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23", - "s": "0x341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - } - }, - { - "rlp": "0xf9034ff901fea00817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79cea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a04c171c1cf8f4b8a91b4a78d28f6d48f3fe5152db79273f4565c78966b64bda6fa07617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331a0ce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000488016345785d8a000083053c393080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000082024cf9014ab86c02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97b86a02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29db86e02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0c0", - "blockHeader": { - "parentHash": "0x0817157aaf7981caa63e995d4d45ee7e30c0b26e52fe668e1f8bcd2b457a79ce", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x4c171c1cf8f4b8a91b4a78d28f6d48f3fe5152db79273f4565c78966b64bda6f", - "transactionsTrie": "0x7617400c1efcb3e64b8cf55ccaaae8e335621bd6897b5e439d93b8dc011a4331", - "receiptTrie": "0xce231c76ee8cc58162d308386fe519040a398e2ecdb689c5ef9fd7ed56e67d7d", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x020000", - "number": "0x04", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x053c39", - "timestamp": "0x30", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x024c", - "hash": "0x0dab5a127f8e5ee8bd43b00f777830e470d932d1b99836639faaabce4c0629ed" - }, - "blocknumber": "4", - "transactions": [ - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x07", - "maxPriorityFeePerGas": "0x03e8", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccc", - "value": "0x00", - "data": "0x0401", - "accessList": [], - "v": "0x01", - "r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c", - "s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x08", - "maxPriorityFeePerGas": "0x64", - "maxFeePerGas": "0x03e8", - "gasLimit": "0x0f4240", - "to": "0xccccccccccccccccccccccccccccccccccccccce", - "value": "0x00", - "data": "0x0403", - "accessList": [], - "v": "0x00", - "r": "0x8d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15", - "s": "0x3cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - }, - { - "type": "0x02", - "chainId": "0x01", - "nonce": "0x09", - "maxPriorityFeePerGas": "0x0186a0", - "maxFeePerGas": "0x0186a0", - "gasLimit": "0x0f4240", - "to": "0xcccccccccccccccccccccccccccccccccccccccd", - "value": "0x00", - "data": "0x0404", - "accessList": [], - "v": "0x01", - "r": "0x54bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9", - "s": "0x6f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0", - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" - } - ], - "uncleHeaders": [] - } - ], - "lastblockhash": "0x0dab5a127f8e5ee8bd43b00f777830e470d932d1b99836639faaabce4c0629ed", - "pre": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x00", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x600080808061100061c0de5af150600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "postState": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x3000", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x1000", - "0x2003": "0x2000", - "0x2004": "0x3000" - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x0a", - "balance": "0xfffffffffba0b646be", - "code": "0x", - "storage": {} - }, - "0xba5e000000000000000000000000000000000000": { - "nonce": "0x00", - "balance": "0x6f05b5a16c7221a5", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": { - "0x01": "0x036b", - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1001": "0x01", - "0x1002": "0x0a", - "0x1003": "0x0149", - "0x1004": "0x019c", - "0x2001": "0x010000000000", - "0x2002": "0x010000000000", - "0x2003": "0x010000000000", - "0x2004": "0x010000000000" - } - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x018401", - "0x1004": "0x018454", - "0x2002": "0x020000000000", - "0x2003": "0x020000000000", - "0x2004": "0x020000000000" - } - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x01ffffffd000", - "code": "0x600080808061100061c0de5af150600080808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x01fffffff000", - "0x2003": "0x01ffffffe000", - "0x2004": "0x01ffffffd000" - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "sealEngine": "NoProof" - } -} diff --git a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_hive.json b/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_hive.json deleted file mode 100644 index 7a627f165c..0000000000 --- a/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_hive.json +++ /dev/null @@ -1,594 +0,0 @@ -{ - "000/my_blockchain_test/Shanghai/solc=0.8.20": { - "_info": { - "hash": "0x71e49d6df916284daddf3b8558e3f59a1450d3e27909dff15d966e732564a680" - }, - "network": "Shanghai", - "genesisBlockHeader": { - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xba686b86cbe20f66e00f33c0a41d80d69f43bcc3322bfc5ed4905d7691886f73", - "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x00", - "number": "0x00", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x00", - "timestamp": "0x00", - "extraData": "0x00", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x03e8", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "hash": "0xee9490b3af4ef92610c3d55270c3d2cab510331f4b0fa0b3c2a805eee1c454b0" - }, - "engineNewPayloads": [ - { - "executionPayload": { - "parentHash": "0xee9490b3af4ef92610c3d55270c3d2cab510331f4b0fa0b3c2a805eee1c454b0", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xfceb4d8747f80ac0f9acab704448018fe23c5577cea89a2877c3620f0763b807", - "receiptsRoot": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x15534", - "timestamp": "0xc", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x36b", - "blockHash": "0xef5d5d7782c5bd50ce1543fdd31dae7c4d079ebdffd330a6db5f777baf1b9b71", - "transactions": [ - "0x02f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b" - ], - "withdrawals": [] - }, - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0xef5d5d7782c5bd50ce1543fdd31dae7c4d079ebdffd330a6db5f777baf1b9b71", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x7fda38fe964161eeed6c7e9fcf959794387c7e235f84e1eee887903b7e6de5e0", - "receiptsRoot": "0xabecd0c0c929d8339a0f55a2be4c3cdcb66f9de91de87109f351a7bd56a664e0", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x2", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c3a", - "timestamp": "0x18", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x2fe", - "blockHash": "0xdcf29a42e8b62c9c73e07b087f52175f9bf9485ee26a05aa7c0ffb580a28a0ef", - "transactions": [ - "0x02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", - "0x02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", - "0x02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a" - ], - "withdrawals": [] - }, - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0xdcf29a42e8b62c9c73e07b087f52175f9bf9485ee26a05aa7c0ffb580a28a0ef", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xa50fd88fc2ee5cb861c1bf80806781dbf17b986a4956bb3ac906dfadb0c02b44", - "receiptsRoot": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x3", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x15544", - "timestamp": "0x24", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x29f", - "blockHash": "0xeaa67ef33964d925aabc53e217e3f5f143615723970bfa07b80c46ef946ca293", - "transactions": [ - "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "0x02f86a0105830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820302c080a06c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715a01220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9b" - ], - "withdrawals": [] - }, - "validationError": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0xdcf29a42e8b62c9c73e07b087f52175f9bf9485ee26a05aa7c0ffb580a28a0ef", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xa41f7c61262aa715762926c769792ba94d73f79e965cc6c029aab1d5e05aa7a5", - "receiptsRoot": "0x2b276cfe779f83fc50afea9262628cfe97b3175ce1822a1871aba93000cc5061", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x3", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c3a", - "timestamp": "0x24", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x29f", - "blockHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", - "transactions": [ - "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "0x02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", - "0x02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c" - ], - "withdrawals": [] - }, - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x6f432f2ec9284d7d2e251294558b9859771d075dc6ce01603ea52727a433078d", - "receiptsRoot": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x15544", - "timestamp": "0x30", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x24c", - "blockHash": "0xa8b4cee5dcb437faf9d815cbe99986f9000e32cf5ea86613b944ac285cac0187", - "transactions": [ - "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "0x02f86a0108830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820402c001a0ebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23a0341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7" - ], - "withdrawals": [] - }, - "validationError": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0xcfaf5dbee8cd1127dab018f35b197c29c9746954dfabf535cb106e41f5310af8", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x2abb36dc658a3d346d858b72dcc5f5f7defd9b6903c69a6bb9318ea866bd85df", - "receiptsRoot": "0x2b276cfe779f83fc50afea9262628cfe97b3175ce1822a1871aba93000cc5061", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c3a", - "timestamp": "0x30", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x24c", - "blockHash": "0xfc75f11c05ec814a890141bef919bb7c20dd29245e37e9bcea66008dfde98526", - "transactions": [ - "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "0x02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", - "0x02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0" - ], - "withdrawals": [] - }, - "version": "2" - } - ], - "engineFcuVersion": "2", - "pre": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": {} - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x00", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": {} - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", - "storage": {} - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "postState": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x3000", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x1000", - "0x2003": "0x2000", - "0x2004": "0x3000" - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x0a", - "balance": "0xfffffffffba0b63da9", - "code": "0x", - "storage": {} - }, - "0xba5e000000000000000000000000000000000000": { - "nonce": "0x00", - "balance": "0x04315222d1", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": { - "0x01": "0x036b", - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1001": "0x01", - "0x1002": "0x0a", - "0x1003": "0x0149", - "0x1004": "0x019c", - "0x2001": "0x010000000000", - "0x2002": "0x010000000000", - "0x2003": "0x010000000000", - "0x2004": "0x010000000000" - } - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f805f8073cccccccccccccccccccccccccccccccccccccccc5af450", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x018401", - "0x1004": "0x018454", - "0x2002": "0x020000000000", - "0x2003": "0x020000000000", - "0x2004": "0x020000000000" - } - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x01ffffffd000", - "code": "0x5f805f8061100061c0de5af15f805f8073cccccccccccccccccccccccccccccccccccccccc5af4905050", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x01fffffff000", - "0x2003": "0x01ffffffe000", - "0x2004": "0x01ffffffd000" - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - } - }, - "000/my_blockchain_test/Shanghai/solc=padding_version": { - "_info": { - "hash": "0xf31b47bd164b70a7f4c6da99e3af028a3bac1ec0a163d8d58b721817824dc989" - }, - "network": "Shanghai", - "genesisBlockHeader": { - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x44b459e04de1195475bf581bebb5ef8bb409cf38ce1146e0e60d60e5986bf871", - "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x00", - "number": "0x00", - "gasLimit": "0x016345785d8a0000", - "gasUsed": "0x00", - "timestamp": "0x00", - "extraData": "0x00", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x03e8", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "hash": "0xdab34f5856809d953e1d5fa05c64f71f71438da0038b98a66b47d1f330e1f4f3" - }, - "engineNewPayloads": [ - { - "executionPayload": { - "parentHash": "0xdab34f5856809d953e1d5fa05c64f71f71438da0038b98a66b47d1f330e1f4f3", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x5e6c56e26e40ffe7bf6a8593ce6623889fe2385a75d742e9a1f17ea03ba6ba99", - "receiptsRoot": "0x29b0562f7140574dd0d50dee8a271b22e1a0a7b78fca58f7c60370d8317ba2a9", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x15534", - "timestamp": "0xc", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x36b", - "blockHash": "0x8666ae70e0d1fc947f4e13022a3dcc042d9428a4c96fd2572cffc2f6279f3c9e", - "transactions": [ - "0x02f8650180018203e8830f424094cccccccccccccccccccccccccccccccccccccccc8001c080a03351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58a067817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b" - ], - "withdrawals": [] - }, - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0x8666ae70e0d1fc947f4e13022a3dcc042d9428a4c96fd2572cffc2f6279f3c9e", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0x54fdc3ec17732ae232d372e2a1e35e386ab4c08b2af95de853c7d2144d98516d", - "receiptsRoot": "0xbea3c90090e14495fed0113be1e981aa10850bfa1e994f4cc2bc0aada5fa1f5e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x2", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c35", - "timestamp": "0x18", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x2fe", - "blockHash": "0x3959bb9eddd1d3b688753245f7e452cf881dd08e2cdd40bc6f35c55597a0fb40", - "transactions": [ - "0x02f86701010a8203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820201c080a06ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050a052f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0", - "0x02f8670102648203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820202c080a0218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825da058b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d", - "0x02f8670103648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820203c001a0339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782aa074004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a" - ], - "withdrawals": [] - }, - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0x3959bb9eddd1d3b688753245f7e452cf881dd08e2cdd40bc6f35c55597a0fb40", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xca8bbf62574cef39c1a04f3fcca690dbc4021a1079be8e084141ed47f80c7160", - "receiptsRoot": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x3", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x15544", - "timestamp": "0x24", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x29f", - "blockHash": "0x5c16738a8a828e396bc356b54716694ac63cce50e27c4cb270727af80b6a6a8a", - "transactions": [ - "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "0x02f86a0105830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820302c080a06c7fb2be7e001a210d72480522b9ebecade52d721360ce5242e34a6c05a02715a01220e3cb7418cd6294443b38d05f5ed9f2967b182d25c784e11e7863454b8f9b" - ], - "withdrawals": [] - }, - "validationError": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0x3959bb9eddd1d3b688753245f7e452cf881dd08e2cdd40bc6f35c55597a0fb40", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xdeab03fae811e52bb3adf96a3d6d84400bf72f37450e245a70488632169af968", - "receiptsRoot": "0x2fa0d45ad30c3b2adb11d0adc9c2890af19822c415abce6f98d87b66166b9897", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x3", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c35", - "timestamp": "0x24", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x29f", - "blockHash": "0x85e4d9912e8ff49ff61f0b602d3db551a54bd35ab64f93e708b00ad685999e6f", - "transactions": [ - "0x02f86901048203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820301c001a0720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63a04448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169", - "0x02f8670105648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820303c080a09c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512ea07a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33", - "0x02f86b0106830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820304c001a0c8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6aa03e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c" - ], - "withdrawals": [] - }, - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0x85e4d9912e8ff49ff61f0b602d3db551a54bd35ab64f93e708b00ad685999e6f", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xf4a67ba5e7bf9b023a635f28cd3456a0fa6fe04c93b8969a146a45524adc7d38", - "receiptsRoot": "0x976beb67b634171d419ef326220dfdda98074e3495940240a105e17643f0a4ef", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x15544", - "timestamp": "0x30", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x24c", - "blockHash": "0x1498909af4d98e8ad23020f9a8055ce5ec7cc6264ca84c710a8bc2a93cffeffc", - "transactions": [ - "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "0x02f86a0108830186a08203e8830f424094cccccccccccccccccccccccccccccccccccccccd80820402c001a0ebc8ad530ec3d510998aa2485763fcd1c6958c900c8d8ae6eaf86e1eddde8b23a0341e4a021f7b77da28d853c07d11253b92331ab640ad3f28f5d7b2cdbc7ceca7" - ], - "withdrawals": [] - }, - "validationError": "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS", - "version": "2" - }, - { - "executionPayload": { - "parentHash": "0x85e4d9912e8ff49ff61f0b602d3db551a54bd35ab64f93e708b00ad685999e6f", - "feeRecipient": "0xba5e000000000000000000000000000000000000", - "stateRoot": "0xbd76d2b78a55dda5a1dfc2b89f25dedd1b28285b06b58e2edd5705178fc5e3b6", - "receiptsRoot": "0x2fa0d45ad30c3b2adb11d0adc9c2890af19822c415abce6f98d87b66166b9897", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4", - "gasLimit": "0x16345785d8a0000", - "gasUsed": "0x53c35", - "timestamp": "0x30", - "extraData": "0x", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": "0x24c", - "blockHash": "0x2c11f86ffa6571ad6c287e33baa3829280b13f39d6921a00f387796e863e42fc", - "transactions": [ - "0x02f86901078203e88203e8830f424094cccccccccccccccccccccccccccccccccccccccc80820401c001a0113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602ca0548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97", - "0x02f8670108648203e8830f424094ccccccccccccccccccccccccccccccccccccccce80820403c080a08d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15a03cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d", - "0x02f86b0109830186a0830186a0830f424094cccccccccccccccccccccccccccccccccccccccd80820404c001a054bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9a06f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0" - ], - "withdrawals": [] - }, - "version": "2" - } - ], - "engineFcuVersion": "2", - "pre": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x00", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f80808061100061c0de5af1505f80808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": {} - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - }, - "postState": { - "0x000000000000000000000000000000000000c0de": { - "nonce": "0x01", - "balance": "0x3000", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x1000", - "0x2003": "0x2000", - "0x2004": "0x3000" - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x0a", - "balance": "0xfffffffffba0b9729f", - "code": "0x", - "storage": {} - }, - "0xba5e000000000000000000000000000000000000": { - "nonce": "0x00", - "balance": "0x04314f1568", - "code": "0x", - "storage": {} - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "nonce": "0x01", - "balance": "0x010000000000", - "code": "0x484355483a036110004301554761200043015500", - "storage": { - "0x01": "0x036b", - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1001": "0x01", - "0x1002": "0x0a", - "0x1003": "0x0149", - "0x1004": "0x019c", - "0x2001": "0x010000000000", - "0x2002": "0x010000000000", - "0x2003": "0x010000000000", - "0x2004": "0x010000000000" - } - }, - "0xcccccccccccccccccccccccccccccccccccccccd": { - "nonce": "0x01", - "balance": "0x020000000000", - "code": "0x5f80808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x018401", - "0x1004": "0x018454", - "0x2002": "0x020000000000", - "0x2003": "0x020000000000", - "0x2004": "0x020000000000" - } - }, - "0xccccccccccccccccccccccccccccccccccccccce": { - "nonce": "0x01", - "balance": "0x01ffffffd000", - "code": "0x5f80808061100061c0de5af1505f80808073cccccccccccccccccccccccccccccccccccccccc5af400", - "storage": { - "0x02": "0x02fe", - "0x03": "0x029f", - "0x04": "0x024c", - "0x1002": "0x64", - "0x1003": "0x64", - "0x1004": "0x64", - "0x2002": "0x01fffffff000", - "0x2003": "0x01ffffffe000", - "0x2004": "0x01ffffffd000" - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "nonce": "0x01", - "balance": "0x01000000000000000000", - "code": "0x", - "storage": {} - } - } - } -} diff --git a/src/ethereum_test_tools/vm/__init__.py b/src/ethereum_test_tools/vm/__init__.py index a4acbf2ce8..c29b2f03de 100644 --- a/src/ethereum_test_tools/vm/__init__.py +++ b/src/ethereum_test_tools/vm/__init__.py @@ -1,14 +1,14 @@ """ -Ethereum Virtual Machine related definitions and utilities. +Mirror module to import `ethereum_test_vm`. """ from .opcode import Bytecode, Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes __all__ = ( "Bytecode", - "Opcode", "Macro", "Macros", + "Opcode", "OpcodeCallArg", "Opcodes", "UndefinedOpcodes", diff --git a/src/ethereum_test_tools/vm/opcode.py b/src/ethereum_test_tools/vm/opcode.py index c26427dcf0..12e5e80314 100644 --- a/src/ethereum_test_tools/vm/opcode.py +++ b/src/ethereum_test_tools/vm/opcode.py @@ -1,5887 +1,22 @@ """ -Ethereum Virtual Machine opcode definitions. - -Acknowledgments: The individual opcode documentation below is due to the work by -[smlXL](https://github.com/smlxl) on [evm.codes](https://www.evm.codes/), available as open -source [github.com/smlxl/evm.codes](https://github.com/smlxl/evm.codes) - thank you! And thanks -to @ThreeHrSleep for integrating it in the docstrings. +Import shortcuts for the ethereum_test_vm package. """ - -from enum import Enum -from typing import Any, Callable, Iterable, List, Mapping, Optional, SupportsBytes - -from ..common.conversions import to_bytes -from .bytecode import Bytecode - - -def _get_int_size(n: int) -> int: - """ - Returns the size of an integer in bytes. - """ - if n < 0: - # Negative numbers in the EVM are represented as two's complement of 32 bytes - return 32 - byte_count = 0 - while n: - byte_count += 1 - n >>= 8 - return byte_count - - -KW_ARGS_DEFAULTS_TYPE = Mapping[str, "int | bytes | str | Opcode | Bytecode"] - - -def _stack_argument_to_bytecode( - arg: "int | bytes | str | Opcode | Bytecode | Iterable[int]", -) -> Bytecode: - """ - Converts a stack argument in an opcode or macro to bytecode. - """ - if isinstance(arg, Bytecode): - return arg - - # We are going to push a constant to the stack. - data_size = 0 - if isinstance(arg, int): - signed = arg < 0 - data_size = _get_int_size(arg) - if data_size > 32: - raise ValueError("Opcode stack data must be less than 32 bytes") - elif data_size == 0: - # Pushing 0 is done with the PUSH1 opcode for compatibility reasons. - data_size = 1 - arg = arg.to_bytes( - length=data_size, - byteorder="big", - signed=signed, - ) - else: - arg = to_bytes(arg).lstrip(b"\0") # type: ignore - if arg == b"": - # Pushing 0 is done with the PUSH1 opcode for compatibility reasons. - arg = b"\x00" - data_size = len(arg) - - assert isinstance(arg, bytes) - assert data_size > 0 - new_opcode = _push_opcodes_byte_list[data_size - 1][arg] - return new_opcode - - -class Opcode(Bytecode): - """ - Represents a single Opcode instruction in the EVM, with extra metadata useful to parametrize - tests. - - Parameters - ---------- - - data_portion_length: number of bytes after the opcode in the bytecode - that represent data - - data_portion_formatter: function to format the data portion of the opcode, if any - - stack_properties_modifier: function to modify the stack properties of the opcode after the - data portion has been processed - - kwargs: list of keyword arguments that can be passed to the opcode, in the order they are - meant to be placed in the stack - - kwargs_defaults: default values for the keyword arguments if any, otherwise 0 - - unchecked_stack: whether the bytecode should ignore stack checks when being called - """ - - data_portion_length: int - data_portion_formatter: Optional[Callable[[Any], bytes]] - stack_properties_modifier: Optional[Callable[[Any], tuple[int, int, int, int]]] - kwargs: List[str] | None - kwargs_defaults: KW_ARGS_DEFAULTS_TYPE - unchecked_stack: bool = False - - def __new__( - cls, - opcode_or_byte: "int | bytes | Opcode", - *, - popped_stack_items: int = 0, - pushed_stack_items: int = 0, - max_stack_height: int | None = None, - min_stack_height: int | None = None, - data_portion_length: int = 0, - data_portion_formatter=None, - stack_properties_modifier=None, - unchecked_stack=False, - kwargs: List[str] | None = None, - kwargs_defaults: KW_ARGS_DEFAULTS_TYPE = {}, - ): - """ - Creates a new opcode instance. - """ - if type(opcode_or_byte) is Opcode: - # Required because Enum class calls the base class with the instantiated object as - # parameter. - return opcode_or_byte - elif isinstance(opcode_or_byte, int) or isinstance(opcode_or_byte, bytes): - - obj_bytes = ( - bytes([opcode_or_byte]) if isinstance(opcode_or_byte, int) else opcode_or_byte - ) - if min_stack_height is None: - min_stack_height = popped_stack_items - if max_stack_height is None: - max_stack_height = max( - min_stack_height - popped_stack_items + pushed_stack_items, min_stack_height - ) - obj = super().__new__( - cls, - obj_bytes, - popped_stack_items=popped_stack_items, - pushed_stack_items=pushed_stack_items, - max_stack_height=max_stack_height, - min_stack_height=min_stack_height, - ) - obj.data_portion_length = data_portion_length - obj.data_portion_formatter = data_portion_formatter - obj.stack_properties_modifier = stack_properties_modifier - obj.unchecked_stack = unchecked_stack - obj.kwargs = kwargs - obj.kwargs_defaults = kwargs_defaults - return obj - raise TypeError("Opcode constructor '__new__' didn't return an instance!") - - def __getitem__(self, *args: "int | bytes | str | Iterable[int]") -> "Opcode": - """ - Initialize a new instance of the opcode with the data portion set, and also clear - the data portion variables to avoid reusing them. - """ - if self.data_portion_formatter is None and self.data_portion_length == 0: - raise ValueError("Opcode does not have a data portion or has already been set") - data_portion = bytes() - - if self.data_portion_formatter is not None: - if len(args) == 1 and isinstance(args[0], Iterable) and not isinstance(args[0], bytes): - data_portion = self.data_portion_formatter(*args[0]) - else: - data_portion = self.data_portion_formatter(*args) - elif self.data_portion_length > 0: - # For opcodes with a data portion, the first argument is the data and the rest of the - # arguments form the stack. - assert len(args) == 1, "Opcode with data portion requires exactly one argument" - data = args[0] - if isinstance(data, bytes) or isinstance(data, SupportsBytes) or isinstance(data, str): - if isinstance(data, str): - if data.startswith("0x"): - data = data[2:] - data = bytes.fromhex(data) - elif isinstance(data, SupportsBytes): - data = bytes(data) - assert len(data) <= self.data_portion_length - data_portion = data.rjust(self.data_portion_length, b"\x00") - elif isinstance(data, int): - signed = data < 0 - data_portion = data.to_bytes( - length=self.data_portion_length, - byteorder="big", - signed=signed, - ) - else: - raise TypeError("Opcode data portion must be either an int or bytes/hex string") - popped_stack_items = self.popped_stack_items - pushed_stack_items = self.pushed_stack_items - min_stack_height = self.min_stack_height - max_stack_height = self.max_stack_height - assert ( - popped_stack_items is not None - and pushed_stack_items is not None - and min_stack_height is not None - ) - if self.stack_properties_modifier is not None: - ( - popped_stack_items, - pushed_stack_items, - min_stack_height, - max_stack_height, - ) = self.stack_properties_modifier(data_portion) - - new_opcode = Opcode( - bytes(self) + data_portion, - popped_stack_items=popped_stack_items, - pushed_stack_items=pushed_stack_items, - min_stack_height=min_stack_height, - max_stack_height=max_stack_height, - data_portion_length=0, - data_portion_formatter=None, - unchecked_stack=self.unchecked_stack, - kwargs=self.kwargs, - kwargs_defaults=self.kwargs_defaults, - ) - new_opcode._name_ = f"{self._name_}[0x{data_portion.hex()}]" - return new_opcode - - def __call__( - self, - *args_t: "int | bytes | str | Opcode | Bytecode | Iterable[int]", - unchecked: bool = False, - **kwargs: "int | bytes | str | Opcode | Bytecode", - ) -> Bytecode: - """ - Makes all opcode instances callable to return formatted bytecode, which constitutes a data - portion, that is located after the opcode byte, and pre-opcode bytecode, which is normally - used to set up the stack. - - This useful to automatically format, e.g., call opcodes and their stack arguments as - `Opcodes.CALL(Opcodes.GAS, 0x1234, 0x0, 0x0, 0x0, 0x0, 0x0)`. - - Data sign is automatically detected but for this reason the range of the input must be: - `[-2^(data_portion_bits-1), 2^(data_portion_bits)]` where: `data_portion_bits == - data_portion_length * 8` - - For the stack, the arguments are set up in the opposite order they are given, so the first - argument is the last item pushed to the stack. - - The resulting stack arrangement does not take into account opcode stack element - consumption, so the stack height is not guaranteed to be correct and the user must take - this into consideration. - - Integers can also be used as stack elements, in which case they are automatically converted - to PUSH operations, and negative numbers always use a PUSH32 operation. - - Hex-strings will be automatically converted to bytes. - """ - args: List["int | bytes | str | Opcode | Bytecode | Iterable[int]"] = list(args_t) - - if self.has_data_portion(): - if len(args) == 0: - raise ValueError("Opcode with data portion requires at least one argument") - assert type(self) is Opcode - get_item_arg = args.pop() - assert not isinstance(get_item_arg, Bytecode) - return self[get_item_arg](*args) - - if self.kwargs is not None and len(kwargs) > 0: - assert len(args) == 0, f"Cannot mix positional and keyword arguments {args} {kwargs}" - for kw in self.kwargs: - args.append(kwargs[kw] if kw in kwargs else self.kwargs_defaults.get(kw, 0)) - - # The rest of the arguments form the stack. - if len(args) != self.popped_stack_items and not (unchecked or self.unchecked_stack): - raise ValueError( - f"Opcode {self._name_} requires {self.popped_stack_items} stack elements, but " - f"{len(args)} were provided. Use 'unchecked=True' parameter to ignore this check." - ) - - pre_opcode_bytecode = Bytecode() - while len(args) > 0: - pre_opcode_bytecode += _stack_argument_to_bytecode(args.pop()) - return pre_opcode_bytecode + self - - def __lt__(self, other: "Opcode") -> bool: - """ - Compares two opcodes by their integer value. - """ - return self.int() < other.int() - - def __gt__(self, other: "Opcode") -> bool: - """ - Compares two opcodes by their integer value. - """ - return self.int() > other.int() - - def int(self) -> int: - """ - Returns the integer representation of the opcode. - """ - return int.from_bytes(self, byteorder="big") - - def has_data_portion(self) -> bool: - """ - Returns whether the opcode has a data portion. - """ - return self.data_portion_length > 0 or self.data_portion_formatter is not None - - -OpcodeCallArg = int | bytes | str | Bytecode | Iterable[int] - - -class Macro(Bytecode): - """ - Represents opcode macro replacement, basically holds bytes - """ - - lambda_operation: Callable[..., Bytecode] | None - - def __new__( - cls, - macro_or_bytes: "Bytecode | Macro" = Bytecode(), - *, - lambda_operation: Callable[..., Bytecode] | None = None, - ): - """ - Creates a new opcode macro instance. - """ - if isinstance(macro_or_bytes, Macro): - # Required because Enum class calls the base class with the instantiated object as - # parameter. - return macro_or_bytes - else: - instance = super().__new__(cls, macro_or_bytes) - instance.lambda_operation = lambda_operation - return instance - - def __call__(self, *args_t: OpcodeCallArg) -> Bytecode: - """ - Performs the macro operation if any. - Otherwise is a no-op. - """ - if self.lambda_operation is not None: - return self.lambda_operation(*args_t) - - pre_opcode_bytecode = Bytecode() - for arg in args_t: - pre_opcode_bytecode += _stack_argument_to_bytecode(arg) - return pre_opcode_bytecode + self - - -# Constants - -RJUMPV_MAX_INDEX_BYTE_LENGTH = 1 -RJUMPV_BRANCH_OFFSET_BYTE_LENGTH = 2 - - -# TODO: Allowing Iterable here is a hacky way to support `range`, because Python 3.11+ will allow -# `Op.RJUMPV[*range(5)]`. This is a temporary solution until Python 3.11+ is the minimum required -# version. - - -def _rjumpv_encoder(*args: int | bytes | Iterable[int]) -> bytes: - if len(args) == 1: - if isinstance(args[0], bytes) or isinstance(args[0], SupportsBytes): - return bytes(args[0]) - elif isinstance(args[0], Iterable): - int_args = list(args[0]) - return b"".join( - [(len(int_args) - 1).to_bytes(RJUMPV_MAX_INDEX_BYTE_LENGTH, "big")] - + [ - i.to_bytes(RJUMPV_BRANCH_OFFSET_BYTE_LENGTH, "big", signed=True) - for i in int_args - ] - ) - return b"".join( - [(len(args) - 1).to_bytes(RJUMPV_MAX_INDEX_BYTE_LENGTH, "big")] - + [ - i.to_bytes(RJUMPV_BRANCH_OFFSET_BYTE_LENGTH, "big", signed=True) - for i in args - if isinstance(i, int) - ] - ) - - -def _exchange_encoder(*args: int) -> bytes: - assert 1 <= len(args) <= 2, f"Exchange opcode requires one or two arguments, got {len(args)}" - if len(args) == 1: - return int.to_bytes(args[0], 1, "big") - # n = imm >> 4 + 1 - # m = imm & 0xF + 1 - # x = n + 1 - # y = n + m + 1 - # ... - # n = x - 1 - # m = y - x - # m = y - n - 1 - x, y = args - assert 2 <= x <= 0x11 - assert x + 1 <= y <= x + 0x10 - n = x - 1 - m = y - x - imm = (n - 1) << 4 | m - 1 - return int.to_bytes(imm, 1, "big") - - -def _swapn_stack_properties_modifier(data: bytes) -> tuple[int, int, int, int]: - imm = int.from_bytes(data, "big") - n = imm + 1 - min_stack_height = n + 1 - return 0, 0, min_stack_height, min_stack_height - - -def _dupn_stack_properties_modifier(data: bytes) -> tuple[int, int, int, int]: - imm = int.from_bytes(data, "big") - n = imm + 1 - min_stack_height = n - return 0, 1, min_stack_height, min_stack_height + 1 - - -def _exchange_stack_properties_modifier(data: bytes) -> tuple[int, int, int, int]: - imm = int.from_bytes(data, "big") - n = (imm >> 4) + 1 - m = (imm & 0x0F) + 1 - min_stack_height = n + m + 1 - return 0, 0, min_stack_height, min_stack_height - - -class Opcodes(Opcode, Enum): - """ - Enum containing all known opcodes. - - Contains deprecated and not yet implemented opcodes. - - This enum is !! NOT !! meant to be iterated over by the tests. Instead, create a list with - cherry-picked opcodes from this Enum within the test if iteration is needed. - - Do !! NOT !! remove or modify existing opcodes from this list. - """ - - STOP = Opcode(0x00) - """ - STOP() - ---- - - Description - ---- - Stop execution - - Inputs - ---- - - None - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - 0 - - Source: [evm.codes/#00](https://www.evm.codes/#00) - """ - - ADD = Opcode(0x01, popped_stack_items=2, pushed_stack_items=1) - """ - ADD(a, b) = c - ---- - - Description - ---- - Addition operation - - Inputs - ---- - - a: first integer value to add - - b: second integer value to add - - Outputs - ---- - - c: integer result of the addition modulo 2**256 - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#01](https://www.evm.codes/#01) - """ - - MUL = Opcode(0x02, popped_stack_items=2, pushed_stack_items=1) - """ - MUL(a, b) = c - ---- - - Description - ---- - Multiplication operation - - Inputs - ---- - - a: first integer value to multiply - - b: second integer value to multiply - - Outputs - ---- - - c: integer result of the multiplication modulo 2**256 - - Fork - ---- - Frontier - - Gas - ---- - 5 - - Source: [evm.codes/#02](https://www.evm.codes/#02) - """ - - SUB = Opcode(0x03, popped_stack_items=2, pushed_stack_items=1) - """ - SUB(a, b) = c - ---- - - Description - ---- - Subtraction operation - - Inputs - ---- - - a: first integer value - - b: second integer value - - Outputs - ---- - - c: integer result of the subtraction modulo 2**256 - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#03](https://www.evm.codes/#03) - """ - - DIV = Opcode(0x04, popped_stack_items=2, pushed_stack_items=1) - """ - DIV(a, b) = c - ---- - - Description - ---- - Division operation - - Inputs - ---- - - a: numerator - - b: denominator (must be non-zero) - - Outputs - ---- - - c: integer result of the division - - Fork - ---- - Frontier - - Gas - ---- - 5 - - Source: [evm.codes/#04](https://www.evm.codes/#04) - """ - - SDIV = Opcode(0x05, popped_stack_items=2, pushed_stack_items=1) - """ - SDIV(a, b) = c - ---- - - Description - ---- - Signed division operation - - Inputs - ---- - - a: signed numerator - - b: signed denominator - - Outputs - ---- - - c: signed integer result of the division. If the denominator is 0, the result will be 0 - ---- - - Fork - ---- - Frontier - - Gas - ---- - 5 - - Source: [evm.codes/#05](https://www.evm.codes/#05) - """ - - MOD = Opcode(0x06, popped_stack_items=2, pushed_stack_items=1) - """ - MOD(a, b) = c - ---- - - Description - ---- - Modulo operation - - Inputs - ---- - - a: integer numerator - - b: integer denominator - - Outputs - ---- - - a % b: integer result of the integer modulo. If the denominator is 0, the result will be 0 - - Fork - ---- - Frontier - - Gas - ---- - 5 - - Source: [evm.codes/#06](https://www.evm.codes/#06) - """ - - SMOD = Opcode(0x07, popped_stack_items=2, pushed_stack_items=1) - """ - SMOD(a, b) = c - ---- - - Description - ---- - Signed modulo remainder operation - - Inputs - ---- - - a: integer numerator - - b: integer denominator - - Outputs - ---- - - a % b: integer result of the signed integer modulo. If the denominator is 0, the result will - be 0 - - Fork - ---- - Frontier - - Gas - ---- - 5 - - Source: [evm.codes/#07](https://www.evm.codes/#07) - """ - - ADDMOD = Opcode(0x08, popped_stack_items=3, pushed_stack_items=1) - """ - ADDMOD(a, b, c) = d - ---- - - Description - ---- - Modular addition operation with overflow check - - Inputs - ---- - - a: first integer value - - b: second integer value - - c: integer denominator - - Outputs - ---- - - (a + b) % N: integer result of the addition followed by a modulo. If the denominator is 0, - the result will be 0 - - Fork - ---- - Frontier - - Gas - ---- - 8 - - Source: [evm.codes/#08](https://www.evm.codes/#08) - """ - - MULMOD = Opcode(0x09, popped_stack_items=3, pushed_stack_items=1) - """ - MULMOD(a, b, N) = d - ---- - - Description - ---- - Modulo multiplication operation - - Inputs - ---- - - a: first integer value to multiply - - b: second integer value to multiply - - N: integer denominator - - Outputs - ---- - - (a * b) % N: integer result of the multiplication followed by a modulo. If the denominator - is 0, the result will be 0 - - Fork - ---- - Frontier - - Gas - ---- - 8 - - Source: [evm.codes/#09](https://www.evm.codes/#09) - """ - - EXP = Opcode(0x0A, popped_stack_items=2, pushed_stack_items=1) - """ - EXP(a, exponent) = a ** exponent - ---- - - Description - ---- - Exponential operation - - Inputs - ---- - - a: integer base - - exponent: integer exponent - - Outputs - ---- - - a ** exponent: integer result of the exponential operation modulo 2**256 - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 10 - - dynamic_gas = 50 * exponent_byte_size - - Source: [evm.codes/#0A](https://www.evm.codes/#0A) - """ - - SIGNEXTEND = Opcode(0x0B, popped_stack_items=2, pushed_stack_items=1) - """ - SIGNEXTEND(b, x) = y - ---- - - Description - ---- - Sign extension operation - - Inputs - ---- - - b: size in byte - 1 of the integer to sign extend - - x: integer value to sign extend - - Outputs - ---- - - y: integer result of the sign extend - - Fork - ---- - Frontier - - Gas - ---- - 5 - - Source: [evm.codes/#0B](https://www.evm.codes/#0B) - """ - - LT = Opcode(0x10, popped_stack_items=2, pushed_stack_items=1) - """ - LT(a, b) = a < b - ---- - - Description - ---- - Less-than comparison - - Inputs - ---- - - a: left side integer value - - b: right side integer value - - Outputs - ---- - - a < b: 1 if the left side is smaller, 0 otherwise - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#10](https://www.evm.codes/#10) - """ - - GT = Opcode(0x11, popped_stack_items=2, pushed_stack_items=1) - """ - GT(a, b) = a > b - ---- - - Description - ---- - Greater-than comparison - - Inputs - ---- - - a: left side integer - - b: right side integer - - Outputs - ---- - - a > b: 1 if the left side is bigger, 0 otherwise - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#11](https://www.evm.codes/#11) - """ - - SLT = Opcode(0x12, popped_stack_items=2, pushed_stack_items=1) - """ - SLT(a, b) = a < b - ---- - - Description - ---- - Signed less-than comparison - - Inputs - ---- - - a: left side signed integer - - b: right side signed integer - - Outputs - ---- - - a < b: 1 if the left side is smaller, 0 otherwise - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#12](https://www.evm.codes/#12) - """ - - SGT = Opcode(0x13, popped_stack_items=2, pushed_stack_items=1) - """ - SGT(a, b) = a > b - ---- - - Description - ---- - Signed greater-than comparison - - Inputs - ---- - - a: left side signed integer - - b: right side signed integer - - Outputs - ---- - - a > b: 1 if the left side is bigger, 0 otherwise - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#13](https://www.evm.codes/#13) - """ - - EQ = Opcode(0x14, popped_stack_items=2, pushed_stack_items=1) - """ - EQ(a, b) = a == b - ---- - - Description - ---- - Equality comparison - - Inputs - ---- - - a: left side integer - - b: right side integer - - Outputs - ---- - - a == b: 1 if the left side is equal to the right side, 0 otherwise - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#14](https://www.evm.codes/#14) - """ - - ISZERO = Opcode(0x15, popped_stack_items=1, pushed_stack_items=1) - """ - ISZERO(a) = a == 0 - ---- - - Description - ---- - Is-zero comparison - - Inputs - ---- - - a: integer - - Outputs - ---- - - a == 0: 1 if a is 0, 0 otherwise - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#15](https://www.evm.codes/#15) - """ - - AND = Opcode(0x16, popped_stack_items=2, pushed_stack_items=1) - """ - AND(a, b) = a & b - ---- - - Description - ---- - Bitwise AND operation - - Inputs - ---- - - a: first binary value - - b: second binary value - - Outputs - ---- - - a & b: the bitwise AND result - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#16](https://www.evm.codes/#16) - """ - - OR = Opcode(0x17, popped_stack_items=2, pushed_stack_items=1) - """ - OR(a, b) = a | b - ---- - - Description - ---- - Bitwise OR operation - - Inputs - ---- - - a: first binary value - - b: second binary value - - Outputs - ---- - - a | b: the bitwise OR result - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#17](https://www.evm.codes/#17) - """ - - XOR = Opcode(0x18, popped_stack_items=2, pushed_stack_items=1) - """ - XOR(a, b) = a ^ b - ---- - - Description - ---- - Bitwise XOR operation - - Inputs - ---- - - a: first binary value - - b: second binary value - - Outputs - ---- - - a ^ b: the bitwise XOR result - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#18](https://www.evm.codes/#18) - """ - - NOT = Opcode(0x19, popped_stack_items=1, pushed_stack_items=1) - """ - NOT(a) = ~a - ---- - - Description - ---- - Bitwise NOT operation - - Inputs - ---- - - a: binary value - - Outputs - ---- - - ~a: the bitwise NOT result - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#19](https://www.evm.codes/#19) - """ - - BYTE = Opcode(0x1A, popped_stack_items=2, pushed_stack_items=1) - """ - BYTE(i, x) = y - ---- - - Description - ---- - Extract a byte from the given position in the value - - Inputs - ---- - - i: byte offset starting from the most significant byte - - x: 32-byte value - - Outputs - ---- - - y: the indicated byte at the least significant position. If the byte offset is out of range, - the result is 0 - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#1A](https://www.evm.codes/#1A) - """ - - SHL = Opcode(0x1B, popped_stack_items=2, pushed_stack_items=1) - """ - SHL(shift, value) = value << shift - ---- - - Description - ---- - Shift left operation - - Inputs - ---- - - shift: number of bits to shift to the left - - value: 32 bytes to shift - - Outputs - ---- - - value << shift: the shifted value. If shift is bigger than 255, returns 0 - - Fork - ---- - Constantinople - - Gas - ---- - 3 - - Source: [evm.codes/#1B](https://www.evm.codes/#1B) - """ - - SHR = Opcode(0x1C, popped_stack_items=2, pushed_stack_items=1) - """ - SHR(shift, value) = value >> shift - ---- - - Description - ---- - Logical shift right operation - - Inputs - ---- - - shift: number of bits to shift to the right. - - value: 32 bytes to shift - - Outputs - ---- - - value >> shift: the shifted value. If shift is bigger than 255, returns 0 - - Fork - ---- - Constantinople - - Gas - ---- - 3 - - Source: [evm.codes/#1C](https://www.evm.codes/#1C) - """ - - SAR = Opcode(0x1D, popped_stack_items=2, pushed_stack_items=1) - """ - SAR(shift, value) = value >> shift - ---- - - Description - ---- - Arithmetic shift right operation - - Inputs - ---- - - shift: number of bits to shift to the right - - value: integer to shift - - Outputs - ---- - - value >> shift: the shifted value - - Fork - ---- - Constantinople - - Gas - ---- - 3 - - Source: [evm.codes/#1D](https://www.evm.codes/#1D) - """ - - SHA3 = Opcode(0x20, popped_stack_items=2, pushed_stack_items=1, kwargs=["offset", "size"]) - """ - SHA3(offset, size) = hash - ---- - - Description - ---- - Compute Keccak-256 hash - - Inputs - ---- - - offset: byte offset in the memory - - size: byte size to read in the memory - - Outputs - ---- - - hash: Keccak-256 hash of the given data in memory - - Fork - ---- - Frontier - - Gas - ---- - - minimum_word_size = (size + 31) / 32 - - static_gas = 30 - - dynamic_gas = 6 * minimum_word_size + memory_expansion_cost - - Source: [evm.codes/#20](https://www.evm.codes/#20) - """ - - ADDRESS = Opcode(0x30, pushed_stack_items=1) - """ - ADDRESS() = address - ---- - - Description - ---- - Get address of currently executing account - - Inputs - ---- - - None - - Outputs - ---- - - address: the 20-byte address of the current account - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#30](https://www.evm.codes/#30) - """ - - BALANCE = Opcode(0x31, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"]) - """ - BALANCE(address) = balance - ---- - - Description - ---- - Get the balance of the specified account - - Inputs - ---- - - address: 20-byte address of the account to check - - Outputs - ---- - - balance: balance of the given account in wei. Returns 0 if the account doesn't exist - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 0 - - dynamic_gas = 100 if warm_address, 2600 if cold_address - - Source: [evm.codes/#31](https://www.evm.codes/#31) - """ - - ORIGIN = Opcode(0x32, pushed_stack_items=1) - """ - ORIGIN() = address - ---- - - Description - ---- - Get execution origination address - - Inputs - ---- - - None - - Outputs - ---- - - address: the 20-byte address of the sender of the transaction. It can only be an account - without code - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#32](https://www.evm.codes/#32) - """ - - CALLER = Opcode(0x33, pushed_stack_items=1) - """ - CALLER() = address - ---- - - Description - ---- - Get caller address - - Inputs - ---- - - None - - Outputs - ---- - - address: the 20-byte address of the caller account. This is the account that did the last - call (except delegate call) - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#33](https://www.evm.codes/#33) - """ - - CALLVALUE = Opcode(0x34, pushed_stack_items=1) - """ - CALLVALUE() = value - ---- - - Description - ---- - Get deposited value by the instruction/transaction responsible for this execution - - Inputs - ---- - - None - - Outputs - ---- - - value: the value of the current call in wei - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#34](https://www.evm.codes/#34) - """ - - CALLDATALOAD = Opcode(0x35, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"]) - """ - CALLDATALOAD(offset) = data[offset] - ---- - - Description - ---- - Get input data of current environment - - Inputs - ---- - - offset: byte offset in the calldata - - Outputs - ---- - - data[offset]: 32-byte value starting from the given offset of the calldata. All bytes after - the end of the calldata are set to 0 - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#35](https://www.evm.codes/#35) - """ - - CALLDATASIZE = Opcode(0x36, pushed_stack_items=1) - """ - CALLDATASIZE() = size - ---- - - Description - ---- - Get size of input data in current environment - - Inputs - ---- - - None - - Outputs - ---- - - size: byte size of the calldata - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#36](https://www.evm.codes/#36) - """ - - CALLDATACOPY = Opcode(0x37, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) - """ - CALLDATACOPY(dest_offset, offset, size) - ---- - - Description - ---- - Copy input data in current environment to memory - - Inputs - ---- - - dest_offset: byte offset in the memory where the result will be copied - - offset: byte offset in the calldata to copy - - size: byte size to copy - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - minimum_word_size = (size + 31) / 32 - - static_gas = 3 - - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost - - Source: [evm.codes/#37](https://www.evm.codes/#37) - """ - - CODESIZE = Opcode(0x38, pushed_stack_items=1) - """ - CODESIZE() = size - ---- - - Description - ---- - Get size of code running in current environment - - Inputs - ---- - - None - - Outputs - ---- - - size: byte size of the code - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#38](https://www.evm.codes/#38) - """ - - CODECOPY = Opcode(0x39, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) - """ - CODECOPY(dest_offset, offset, size) - ---- - - Description - ---- - Copy code running in current environment to memory - - Inputs - ---- - - dest_offset: byte offset in the memory where the result will be copied. - - offset: byte offset in the code to copy. - - size: byte size to copy - - Fork - ---- - Frontier - - Gas - ---- - - minimum_word_size = (size + 31) / 32 - - static_gas = 3 - - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost - - Source: [evm.codes/#39](https://www.evm.codes/#39) - """ - - GASPRICE = Opcode(0x3A, pushed_stack_items=1) - """ - GASPRICE() = price - ---- - - Description - ---- - Get price of gas in current environment - - Outputs - ---- - - price: gas price in wei per gas - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#3A](https://www.evm.codes/#3A) - """ - - EXTCODESIZE = Opcode(0x3B, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"]) - """ - EXTCODESIZE(address) = size - ---- - - Description - ---- - Get size of an account's code - - Inputs - ---- - - address: 20-byte address of the contract to query - - Outputs - ---- - - size: byte size of the code - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 0 - - dynamic_gas = 100 if warm_address, 2600 if cold_address - - Source: [evm.codes/#3B](https://www.evm.codes/#3B) - """ - - EXTCODECOPY = Opcode( - 0x3C, popped_stack_items=4, kwargs=["address", "dest_offset", "offset", "size"] - ) - """ - EXTCODECOPY(address, dest_offset, offset, size) - ---- - - Description - ---- - Copy an account's code to memory - - Inputs - ---- - - address: 20-byte address of the contract to query - - dest_offset: byte offset in the memory where the result will be copied - - offset: byte offset in the code to copy - - size: byte size to copy - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - minimum_word_size = (size + 31) / 32 - - static_gas = 0 - - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost - - Source: [evm.codes/#3C](https://www.evm.codes/#3C) - """ - - RETURNDATASIZE = Opcode(0x3D, pushed_stack_items=1) - """ - RETURNDATASIZE() = size - ---- - - Description - ---- - Get size of output data from the previous call from the current environment - - Outputs - ---- - - size: byte size of the return data from the last executed sub context - - Fork - ---- - Byzantium - - Gas - ---- - 2 - - Source: [evm.codes/#3D](https://www.evm.codes/#3D) - """ - - RETURNDATACOPY = Opcode(0x3E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) - """ - RETURNDATACOPY(dest_offset, offset, size) - ---- - - Description - ---- - Copy output data from the previous call to memory - - Inputs - ---- - - dest_offset: byte offset in the memory where the result will be copied - - offset: byte offset in the return data from the last executed sub context to copy - - size: byte size to copy - - Fork - ---- - Byzantium - - Gas - ---- - - minimum_word_size = (size + 31) / 32 - - static_gas = 3 - - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost - - Source: [evm.codes/#3E](https://www.evm.codes/#3E) - """ - - EXTCODEHASH = Opcode(0x3F, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"]) - """ - EXTCODEHASH(address) = hash - ---- - - Description - ---- - Get hash of an account's code - - Inputs - ---- - - address: 20-byte address of the account - - Outputs - ---- - - hash: hash of the chosen account's code, the empty hash (0xc5d24601...) if the account has no - code, or 0 if the account does not exist or has been destroyed - - Fork - ---- - Constantinople - - Gas - ---- - - static_gas = 0 - - dynamic_gas = 100 if warm_address, 2600 if cold_address - - Source: [evm.codes/#3F](https://www.evm.codes/#3F) - """ - - BLOCKHASH = Opcode(0x40, popped_stack_items=1, pushed_stack_items=1, kwargs=["block_number"]) - """ - BLOCKHASH(block_number) = hash - ---- - - Description - ---- - Get the hash of one of the 256 most recent complete blocks - - Inputs - ---- - - blockNumber: block number to get the hash from. Valid range is the last 256 blocks (not - including the current one). Current block number can be queried with NUMBER - - Outputs - ---- - - hash: hash of the chosen block, or 0 if the block number is not in the valid range - - Fork - ---- - Frontier - - Gas - ---- - 20 - - Source: [evm.codes/#40](https://www.evm.codes/#40) - """ - - COINBASE = Opcode(0x41, pushed_stack_items=1) - """ - COINBASE() = address - ---- - - Description - ---- - Get the block's beneficiary address - - Inputs - ---- - - None - - Outputs - ---- - - address: miner's 20-byte address - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#41](https://www.evm.codes/#41) - """ - - TIMESTAMP = Opcode(0x42, pushed_stack_items=1) - """ - TIMESTAMP() = timestamp - ---- - - Description - ---- - Get the block's timestamp - - Inputs - ---- - - None - - Outputs - ---- - - timestamp: unix timestamp of the current block - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#42](https://www.evm.codes/#42) - """ - - NUMBER = Opcode(0x43, pushed_stack_items=1) - """ - NUMBER() = blockNumber - ---- - - Description - ---- - Get the block's number - - Inputs - ---- - - None - - Outputs - ---- - - blockNumber: current block number - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#43](https://www.evm.codes/#43) - """ - - PREVRANDAO = Opcode(0x44, pushed_stack_items=1) - """ - PREVRANDAO() = prevRandao - ---- - - Description - ---- - Get the previous block's RANDAO mix - - Inputs - ---- - - None - - Outputs - ---- - - prevRandao: previous block's RANDAO mix - - Fork - ---- - Merge - - Gas - ---- - 2 - - Source: [evm.codes/#44](https://www.evm.codes/#44) - """ - - GASLIMIT = Opcode(0x45, pushed_stack_items=1) - """ - GASLIMIT() = gasLimit - ---- - - Description - ---- - Get the block's gas limit - - Inputs - ---- - - None - - Outputs - ---- - - gasLimit: gas limit - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#45](https://www.evm.codes/#45) - """ - - CHAINID = Opcode(0x46, pushed_stack_items=1) - """ - CHAINID() = chainId - ---- - - Description - ---- - Get the chain ID - - Inputs - ---- - - None - - Outputs - ---- - - chainId: chain id of the network - - Fork - ---- - Istanbul - - Gas - ---- - 2 - - Source: [evm.codes/#46](https://www.evm.codes/#46) - """ - - SELFBALANCE = Opcode(0x47, pushed_stack_items=1) - """ - SELFBALANCE() = balance - ---- - - Description - ---- - Get balance of currently executing account - - Inputs - ---- - - None - - Outputs - ---- - - balance: balance of the current account in wei - - Fork - ---- - Istanbul - - Gas - ---- - 5 - - Source: [evm.codes/#47](https://www.evm.codes/#47) - """ - - BASEFEE = Opcode(0x48, pushed_stack_items=1) - """ - BASEFEE() = baseFee - ---- - - Description - ---- - Get the base fee - - Outputs - ---- - - baseFee: base fee in wei - - Fork - ---- - London - - Gas - ---- - 2 - - Source: [evm.codes/#48](https://www.evm.codes/#48) - """ - - BLOBHASH = Opcode(0x49, popped_stack_items=1, pushed_stack_items=1, kwargs=["index"]) - """ - BLOBHASH(index) = versionedHash - ---- - - Description - ---- - Returns the versioned hash of a single blob contained in the type-3 transaction - - Inputs - ---- - - index: index of the blob - - Outputs - ---- - - versionedHash: versioned hash of the blob - - Fork - ---- - Cancun - - Gas - ---- - 3 - - Source: [eips.ethereum.org/EIPS/eip-4844](https://eips.ethereum.org/EIPS/eip-4844) - """ - - BLOBBASEFEE = Opcode(0x4A, popped_stack_items=0, pushed_stack_items=1) - """ - BLOBBASEFEE() = fee - ---- - - Description - ---- - Returns the value of the blob base fee of the block it is executing in - - Inputs - ---- - - None - - Outputs - ---- - - baseFeePerBlobGas: base fee for the blob gas in wei - - Fork - ---- - Cancun - - Gas - ---- - 2 - - Source: [eips.ethereum.org/EIPS/eip-7516](https://eips.ethereum.org/EIPS/eip-7516) - """ - - POP = Opcode(0x50, popped_stack_items=1) - """ - POP() - ---- - - Description - ---- - Remove item from stack - - Inputs - ---- - - None - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#50](https://www.evm.codes/#50) - """ - - MLOAD = Opcode(0x51, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"]) - """ - MLOAD(offset) = value - ---- - - Description - ---- - Load word from memory - - Inputs - ---- - - offset: offset in the memory in bytes - - Outputs - ---- - - value: the 32 bytes in memory starting at that offset. If it goes beyond its current size - (see MSIZE), writes 0s - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 3 - - dynamic_gas = memory_expansion_cost - - Source: [evm.codes/#51](https://www.evm.codes/#51) - """ - - MSTORE = Opcode(0x52, popped_stack_items=2, kwargs=["offset", "value"]) - """ - MSTORE(offset, value) - ---- - - Description - ---- - Save word to memory - - Inputs - ---- - - offset: offset in the memory in bytes - - value: 32-byte value to write in the memory - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 3 - - dynamic_gas = memory_expansion_cost - - Source: [evm.codes/#52](https://www.evm.codes/#52) - """ - - MSTORE8 = Opcode(0x53, popped_stack_items=2, kwargs=["offset", "value"]) - """ - MSTORE8(offset, value) - ---- - - Description - ---- - Save byte to memory - - Inputs - ---- - - offset: offset in the memory in bytes - - value: 1-byte value to write in the memory (the least significant byte of the 32-byte stack - value) - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 3 - - dynamic_gas = memory_expansion_cost - - Source: [evm.codes/#53](https://www.evm.codes/#53) - """ - - SLOAD = Opcode(0x54, popped_stack_items=1, pushed_stack_items=1, kwargs=["key"]) - """ - SLOAD(key) = value - ---- - - Description - ---- - Load word from storage - - Inputs - ---- - - key: 32-byte key in storage - - Outputs - ---- - - value: 32-byte value corresponding to that key. 0 if that key was never written before - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 0 - - dynamic_gas = 100 if warm_address, 2600 if cold_address - - Source: [evm.codes/#54](https://www.evm.codes/#54) - """ - - SSTORE = Opcode(0x55, popped_stack_items=2, kwargs=["key", "value"]) - """ - SSTORE(key, value) - ---- - - Description - ---- - Save word to storage - - Inputs - ---- - - key: 32-byte key in storage - - value: 32-byte value to store - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - ``` - static_gas = 0 - - if value == current_value - if key is warm - base_dynamic_gas = 100 - else - base_dynamic_gas = 100 - else if current_value == original_value - if original_value == 0 - base_dynamic_gas = 20000 - else - base_dynamic_gas = 2900 - else - base_dynamic_gas = 100 - - if key is cold: - base_dynamic_gas += 2100 - ``` - - Source: [evm.codes/#55](https://www.evm.codes/#55) - """ - - JUMP = Opcode(0x56, popped_stack_items=1, kwargs=["pc"]) - """ - JUMP(pc) - ---- - - Description - ---- - Alter the program counter - - Inputs - ---- - - pc: byte offset in the deployed code where execution will continue from. Must be a - JUMPDEST instruction - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - 8 - - Source: [evm.codes/#56](https://www.evm.codes/#56) - """ - - JUMPI = Opcode(0x57, popped_stack_items=2, kwargs=["pc", "condition"]) - """ - JUMPI(pc, condition) - ---- - - Description - ---- - Conditionally alter the program counter - - Inputs - ---- - - pc: byte offset in the deployed code where execution will continue from. Must be a - JUMPDEST instruction - - condition: the program counter will be altered with the new value only if this value is - different from 0. Otherwise, the program counter is simply incremented and the next - instruction will be executed - - Fork - ---- - Frontier - - Gas - ---- - 10 - - Source: [evm.codes/#57](https://www.evm.codes/#57) - """ - - PC = Opcode(0x58, pushed_stack_items=1) - """ - PC() = counter - ---- - - Description - ---- - Get the value of the program counter prior to the increment corresponding to this instruction - - Inputs - ---- - - None - - Outputs - ---- - - counter: PC of this instruction in the current program. - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#58](https://www.evm.codes/#58) - """ - - MSIZE = Opcode(0x59, pushed_stack_items=1) - """ - MSIZE() = size - ---- - - Description - ---- - Get the size of active memory in bytes - - Outputs - ---- - - size: current memory size in bytes (higher offset accessed until now + 1) - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#59](https://www.evm.codes/#59) - """ - - GAS = Opcode(0x5A, pushed_stack_items=1) - """ - GAS() = gas_remaining - ---- - - Description - ---- - Get the amount of available gas, including the corresponding reduction for the cost of this - instruction - - Inputs - ---- - - None - - Outputs - ---- - - gas: remaining gas (after this instruction) - - Fork - ---- - Frontier - - Gas - ---- - 2 - - Source: [evm.codes/#5A](https://www.evm.codes/#5A) - """ - - JUMPDEST = Opcode(0x5B) - """ - JUMPDEST() - ---- - - Description - ---- - Mark a valid destination for jumps - - Inputs - ---- - - None - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - 1 - - Source: [evm.codes/#5B](https://www.evm.codes/#5B) - """ - - NOOP = Opcode(0x5B) - """ - NOOP() - ---- - - Description - ---- - Synonym for JUMPDEST. Performs no operation. - - Inputs - ---- - - None - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - 1 - - Source: [evm.codes/#5B](https://www.evm.codes/#5B) - """ - - TLOAD = Opcode(0x5C, popped_stack_items=1, pushed_stack_items=1, kwargs=["key"]) - """ - TLOAD(key) = value - ---- - - Description - ---- - Load word from transient storage - - Inputs - ---- - - key: 32-byte key in transient storage - - Outputs - ---- - - value: 32-byte value corresponding to that key. 0 if that key was never written - - Fork - ---- - Cancun - - Gas - ---- - 100 - - Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/eip-1153) - """ - - TSTORE = Opcode(0x5D, popped_stack_items=2, kwargs=["key", "value"]) - """ - TSTORE(key, value) - ---- - - Description - ---- - Save word to transient storage - - Inputs - ---- - - key: 32-byte key in transient storage - - value: 32-byte value to store - - Fork - ---- - Cancun - - Gas - ---- - 100 - - Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/eip-1153) - """ - - MCOPY = Opcode(0x5E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) - """ - MCOPY(dest_offset, offset, size) - ---- - - Description - ---- - Copies areas in memory - - Inputs - ---- - - dest_offset: byte offset in the memory where the result will be copied - - offset: byte offset in the calldata to copy - - size: byte size to copy - - Outputs - ---- - - None - - Fork - ---- - Cancun - - Gas - ---- - - minimum_word_size = (size + 31) / 32 - - static_gas = 3 - - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost - - Source: [eips.ethereum.org/EIPS/eip-5656](https://eips.ethereum.org/EIPS/eip-5656) - """ - - PUSH0 = Opcode(0x5F, pushed_stack_items=1) - """ - PUSH0() = value - ---- - - Description - ---- - Place value 0 on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, equal to 0 - - Fork - ---- - Shanghai - - Gas - ---- - 2 - - Source: [evm.codes/#5F](https://www.evm.codes/#5F) - """ - - PUSH1 = Opcode(0x60, pushed_stack_items=1, data_portion_length=1) - """ - PUSH1() = value - ---- - - Description - ---- - Place 1 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#60](https://www.evm.codes/#60) - """ - - PUSH2 = Opcode(0x61, pushed_stack_items=1, data_portion_length=2) - """ - PUSH2() = value - ---- - - Description - ---- - Place 2 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#61](https://www.evm.codes/#61) - """ - - PUSH3 = Opcode(0x62, pushed_stack_items=1, data_portion_length=3) - """ - PUSH3() = value - ---- - - Description - ---- - Place 3 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#62](https://www.evm.codes/#62) - """ - - PUSH4 = Opcode(0x63, pushed_stack_items=1, data_portion_length=4) - """ - PUSH4() = value - ---- - - Description - ---- - Place 4 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#63](https://www.evm.codes/#63) - """ - - PUSH5 = Opcode(0x64, pushed_stack_items=1, data_portion_length=5) - """ - PUSH5() = value - ---- - - Description - ---- - Place 5 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#64](https://www.evm.codes/#64) - """ - - PUSH6 = Opcode(0x65, pushed_stack_items=1, data_portion_length=6) - """ - PUSH6() = value - ---- - - Description - ---- - Place 6 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#65](https://www.evm.codes/#65) - """ - - PUSH7 = Opcode(0x66, pushed_stack_items=1, data_portion_length=7) - """ - PUSH7() = value - ---- - - Description - ---- - Place 7 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#66](https://www.evm.codes/#66) - """ - - PUSH8 = Opcode(0x67, pushed_stack_items=1, data_portion_length=8) - """ - PUSH8() = value - ---- - - Description - ---- - Place 8 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#67](https://www.evm.codes/#67) - """ - - PUSH9 = Opcode(0x68, pushed_stack_items=1, data_portion_length=9) - """ - PUSH9() = value - ---- - - Description - ---- - Place 9 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#68](https://www.evm.codes/#68) - """ - - PUSH10 = Opcode(0x69, pushed_stack_items=1, data_portion_length=10) - """ - PUSH10() = value - ---- - - Description - ---- - Place 10 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#69](https://www.evm.codes/#69) - """ - - PUSH11 = Opcode(0x6A, pushed_stack_items=1, data_portion_length=11) - """ - PUSH11() = value - ---- - - Description - ---- - Place 11 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#6A](https://www.evm.codes/#6A) - """ - - PUSH12 = Opcode(0x6B, pushed_stack_items=1, data_portion_length=12) - """ - PUSH12() = value - ---- - - Description - ---- - Place 12 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#6B](https://www.evm.codes/#6B) - """ - - PUSH13 = Opcode(0x6C, pushed_stack_items=1, data_portion_length=13) - """ - PUSH13() = value - ---- - - Description - ---- - Place 13 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#6C](https://www.evm.codes/#6C) - """ - - PUSH14 = Opcode(0x6D, pushed_stack_items=1, data_portion_length=14) - """ - PUSH14() = value - ---- - - Description - ---- - Place 14 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - - Gas - ---- - 3 - - Source: [evm.codes/#6D](https://www.evm.codes/#6D) - """ - - PUSH15 = Opcode(0x6E, pushed_stack_items=1, data_portion_length=15) - """ - PUSH15() = value - ---- - - Description - ---- - Place 15 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#6E](https://www.evm.codes/#6E) - """ - - PUSH16 = Opcode(0x6F, pushed_stack_items=1, data_portion_length=16) - """ - PUSH16() = value - ---- - - Description - ---- - Place 16 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#6F](https://www.evm.codes/#6F) - """ - - PUSH17 = Opcode(0x70, pushed_stack_items=1, data_portion_length=17) - """ - PUSH17() = value - ---- - - Description - ---- - Place 17 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#70](https://www.evm.codes/#70) - """ - - PUSH18 = Opcode(0x71, pushed_stack_items=1, data_portion_length=18) - """ - PUSH18() = value - ---- - - Description - ---- - Place 18 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#71](https://www.evm.codes/#71) - """ - - PUSH19 = Opcode(0x72, pushed_stack_items=1, data_portion_length=19) - """ - PUSH19() = value - ---- - - Description - ---- - Place 19 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#72](https://www.evm.codes/#72) - """ - - PUSH20 = Opcode(0x73, pushed_stack_items=1, data_portion_length=20) - """ - PUSH20() = value - ---- - - Description - ---- - Place 20 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#73](https://www.evm.codes/#73) - """ - - PUSH21 = Opcode(0x74, pushed_stack_items=1, data_portion_length=21) - """ - PUSH21() = value - ---- - - Description - ---- - Place 21 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#74](https://www.evm.codes/#74) - """ - - PUSH22 = Opcode(0x75, pushed_stack_items=1, data_portion_length=22) - """ - PUSH22() = value - ---- - - Description - ---- - Place 22 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#75](https://www.evm.codes/#75) - """ - - PUSH23 = Opcode(0x76, pushed_stack_items=1, data_portion_length=23) - """ - PUSH23() = value - ---- - - Description - ---- - Place 23 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#76](https://www.evm.codes/#76) - """ - - PUSH24 = Opcode(0x77, pushed_stack_items=1, data_portion_length=24) - """ - PUSH24() = value - ---- - - Description - ---- - Place 24 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#77](https://www.evm.codes/#77) - """ - - PUSH25 = Opcode(0x78, pushed_stack_items=1, data_portion_length=25) - """ - PUSH25() = value - ---- - - Description - ---- - Place 25 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#78](https://www.evm.codes/#78) - """ - - PUSH26 = Opcode(0x79, pushed_stack_items=1, data_portion_length=26) - """ - PUSH26() = value - ---- - - Description - ---- - Place 26 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#79](https://www.evm.codes/#79) - """ - - PUSH27 = Opcode(0x7A, pushed_stack_items=1, data_portion_length=27) - """ - PUSH27() = value - ---- - - Description - ---- - Place 27 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#7A](https://www.evm.codes/#7A) - """ - - PUSH28 = Opcode(0x7B, pushed_stack_items=1, data_portion_length=28) - """ - PUSH28() = value - ---- - - Description - ---- - Place 28 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#7B](https://www.evm.codes/#7B) - """ - - PUSH29 = Opcode(0x7C, pushed_stack_items=1, data_portion_length=29) - """ - PUSH29() = value - ---- - - Description - ---- - Place 29 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#7C](https://www.evm.codes/#7C) - """ - - PUSH30 = Opcode(0x7D, pushed_stack_items=1, data_portion_length=30) - """ - PUSH30() = value - ---- - - Description - ---- - Place 30 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#7D](https://www.evm.codes/#7D) - """ - - PUSH31 = Opcode(0x7E, pushed_stack_items=1, data_portion_length=31) - """ - PUSH31() = value - ---- - - Description - ---- - Place 31 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#7E](https://www.evm.codes/#7E) - """ - - PUSH32 = Opcode(0x7F, pushed_stack_items=1, data_portion_length=32) - """ - PUSH32() = value - ---- - - Description - ---- - Place 32 byte item on stack - - Inputs - ---- - - None - - Outputs - ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#7F](https://www.evm.codes/#7F) - """ - - DUP1 = Opcode(0x80, pushed_stack_items=1, min_stack_height=1) - """ - DUP1(value) = value, value - ---- - - Description - ---- - Duplicate 1st stack item - - Inputs - ---- - - value: value to duplicate - - Outputs - ---- - - value: duplicated value - - value: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#80](https://www.evm.codes/#80) - """ - - DUP2 = Opcode(0x81, pushed_stack_items=1, min_stack_height=2) - """ - DUP2(v1, v2) = v2, v1, v2 - ---- - - Description - ---- - Duplicate 2nd stack item - - Inputs - ---- - - v1: ignored value - - v2: value to duplicate - - Outputs - ---- - - v2: duplicated value - - v1: ignored value - - v2: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#81](https://www.evm.codes/#81) - """ - - DUP3 = Opcode(0x82, pushed_stack_items=1, min_stack_height=3) - """ - DUP3(v1, v2, v3) = v3, v1, v2, v3 - ---- - - Description - ---- - Duplicate 3rd stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - v3: value to duplicate - - Outputs - ---- - - v3: duplicated value - - v1: ignored value - - v2: ignored value - - v3: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#82](https://www.evm.codes/#82) - """ - - DUP4 = Opcode(0x83, pushed_stack_items=1, min_stack_height=4) - """ - DUP4(v1, v2, v3, v4) = v4, v1, v2, v3, v4 - ---- - - Description - ---- - Duplicate 4th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - v3: ignored value - - v4: value to duplicate - - Outputs - ---- - - v4: duplicated value - - v1: ignored value - - v2: ignored value - - v3: ignored value - - v4: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#83](https://www.evm.codes/#83) - """ - - DUP5 = Opcode(0x84, pushed_stack_items=1, min_stack_height=5) - """ - DUP5(v1, v2, v3, v4, v5) = v5, v1, v2, v3, v4, v5 - ---- - - Description - ---- - Duplicate 5th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - v3: ignored value - - v4: ignored value - - v5: value to duplicate - - Outputs - ---- - - v5: duplicated value - - v1: ignored value - - v2: ignored value - - v3: ignored value - - v4: ignored value - - v5: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#84](https://www.evm.codes/#84) - """ - - DUP6 = Opcode(0x85, pushed_stack_items=1, min_stack_height=6) - """ - DUP6(v1, v2, ..., v5, v6) = v6, v1, v2, ..., v5, v6 - ---- - - Description - ---- - Duplicate 6th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v5: ignored value - - v6: value to duplicate - - Outputs - ---- - - v6: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v5: ignored value - - v6: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#85](https://www.evm.codes/#85) - """ - - DUP7 = Opcode(0x86, pushed_stack_items=1, min_stack_height=7) - """ - DUP7(v1, v2, ..., v6, v7) = v7, v1, v2, ..., v6, v7 - ---- - - Description - ---- - Duplicate 7th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v6: ignored value - - v7: value to duplicate - - Outputs - ---- - - v7: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v6: ignored value - - v7: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#86](https://www.evm.codes/#86) - """ - - DUP8 = Opcode(0x87, pushed_stack_items=1, min_stack_height=8) - """ - DUP8(v1, v2, ..., v7, v8) = v8, v1, v2, ..., v7, v8 - ---- - - Description - ---- - Duplicate 8th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v7: ignored value - - v8: value to duplicate - - Outputs - ---- - - v8: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v7: ignored value - - v8: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#87](https://www.evm.codes/#87) - """ - - DUP9 = Opcode(0x88, pushed_stack_items=1, min_stack_height=9) - """ - DUP9(v1, v2, ..., v8, v9) = v9, v1, v2, ..., v8, v9 - ---- - - Description - ---- - Duplicate 9th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v8: ignored value - - v9: value to duplicate - - Outputs - ---- - - v9: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v8: ignored value - - v9: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#88](https://www.evm.codes/#88) - """ - DUP10 = Opcode(0x89, pushed_stack_items=1, min_stack_height=10) - """ - DUP10(v1, v2, ..., v9, v10) = v10, v1, v2, ..., v9, v10 - ---- - - Description - ---- - Duplicate 10th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v9: ignored value - - v10: value to duplicate - - Outputs - ---- - - v10: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v9: ignored value - - v10: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#89](https://www.evm.codes/#89) - """ - - DUP11 = Opcode(0x8A, pushed_stack_items=1, min_stack_height=11) - """ - DUP11(v1, v2, ..., v10, v11) = v11, v1, v2, ..., v10, v11 - ---- - - Description - ---- - Duplicate 11th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v10: ignored value - - v11: value to duplicate - - Outputs - ---- - - v11: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v10: ignored value - - v11: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#8A](https://www.evm.codes/#8A) - """ - - DUP12 = Opcode(0x8B, pushed_stack_items=1, min_stack_height=12) - """ - DUP12(v1, v2, ..., v11, v12) = v12, v1, v2, ..., v11, v12 - ---- - - Description - ---- - Duplicate 12th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v11: ignored value - - v12: value to duplicate - - Outputs - ---- - - v12: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v11: ignored value - - v12: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#8B](https://www.evm.codes/#8B) - """ - - DUP13 = Opcode(0x8C, pushed_stack_items=1, min_stack_height=13) - """ - DUP13(v1, v2, ..., v12, v13) = v13, v1, v2, ..., v12, v13 - ---- - - Description - ---- - Duplicate 13th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v12: ignored value - - v13: value to duplicate - - Outputs - ---- - - v13: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v12: ignored value - - v13: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#8C](https://www.evm.codes/#8C) - """ - - DUP14 = Opcode(0x8D, pushed_stack_items=1, min_stack_height=14) - """ - DUP14(v1, v2, ..., v13, v14) = v14, v1, v2, ..., v13, v14 - ---- - - Description - ---- - Duplicate 14th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v13: ignored value - - v14: value to duplicate - - Outputs - ---- - - v14: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v13: ignored value - - v14: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#8D](https://www.evm.codes/#8D) - """ - - DUP15 = Opcode(0x8E, pushed_stack_items=1, min_stack_height=15) - """ - DUP15(v1, v2, ..., v14, v15) = v15, v1, v2, ..., v14, v15 - ---- - - Description - ---- - Duplicate 15th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v14: ignored value - - v15: value to duplicate - - Outputs - ---- - - v15: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v14: ignored value - - v15: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#8E](https://www.evm.codes/#8E) - """ - - DUP16 = Opcode(0x8F, pushed_stack_items=1, min_stack_height=16) - """ - DUP16(v1, v2, ..., v15, v16) = v16, v1, v2, ..., v15, v16 - ---- - - Description - ---- - Duplicate 16th stack item - - Inputs - ---- - - v1: ignored value - - v2: ignored value - - ... - - v15: ignored value - - v16: value to duplicate - - Outputs - ---- - - v16: duplicated value - - v1: ignored value - - v2: ignored value - - ... - - v15: ignored value - - v16: original value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#8F](https://www.evm.codes/#8F) - """ - - SWAP1 = Opcode(0x90, min_stack_height=2) - """ - SWAP1(v1, v2) = v2, v1 - ---- - - Description - ---- - Exchange the top stack item with the second stack item. - - Inputs - ---- - - v1: value to swap - - v2: value to swap - - Outputs - ---- - - v1: swapped value - - v2: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#90](https://www.evm.codes/#90) - """ - - SWAP2 = Opcode(0x91, min_stack_height=3) - """ - SWAP2(v1, v2, v3) = v3, v2, v1 - ---- - - Description - ---- - Exchange 1st and 3rd stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - v3: value to swap - - Outputs - ---- - - v3: swapped value - - v2: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#91](https://www.evm.codes/#91) - """ - - SWAP3 = Opcode(0x92, min_stack_height=4) - """ - SWAP3(v1, v2, v3, v4) = v4, v2, v3, v1 - ---- - - Description - ---- - Exchange 1st and 4th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - v3: ignored value - - v4: value to swap - - Outputs - ---- - - v4: swapped value - - v2: ignored value - - v3: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#92](https://www.evm.codes/#92) - """ - - SWAP4 = Opcode(0x93, min_stack_height=5) - """ - SWAP4(v1, v2, ..., v4, v5) = v5, v2, ..., v4, v1 - ---- - - Description - ---- - Exchange 1st and 5th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v4: ignored value - - v5: value to swap - - Outputs - ---- - - v5: swapped value - - v2: ignored value - - ... - - v4: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#93](https://www.evm.codes/#93) - """ - - SWAP5 = Opcode(0x94, min_stack_height=6) - """ - SWAP5(v1, v2, ..., v5, v6) = v6, v2, ..., v5, v1 - ---- - - Description - ---- - Exchange 1st and 6th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v5: ignored value - - v6: value to swap - - Outputs - ---- - - v6: swapped value - - v2: ignored value - - ... - - v5: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#94](https://www.evm.codes/#94) - """ - - SWAP6 = Opcode(0x95, min_stack_height=7) - """ - SWAP6(v1, v2, ..., v6, v7) = v7, v2, ..., v6, v1 - ---- - - Description - ---- - Exchange 1st and 7th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v6: ignored value - - v7: value to swap - - Outputs - ---- - - v7: swapped value - - v2: ignored value - - ... - - v6: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#95](https://www.evm.codes/#95) - """ - - SWAP7 = Opcode(0x96, min_stack_height=8) - """ - SWAP7(v1, v2, ..., v7, v8) = v8, v2, ..., v7, v1 - ---- - - Description - ---- - Exchange 1st and 8th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v7: ignored value - - v8: value to swap - - Outputs - ---- - - v8: swapped value - - v2: ignored value - - ... - - v7: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#96](https://www.evm.codes/#96) - """ - - SWAP8 = Opcode(0x97, min_stack_height=9) - """ - SWAP8(v1, v2, ..., v8, v9) = v9, v2, ..., v8, v1 - ---- - - Description - ---- - Exchange 1st and 9th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v8: ignored value - - v9: value to swap - - Outputs - ---- - - v9: swapped value - - v2: ignored value - - ... - - v8: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#97](https://www.evm.codes/#97) - """ - - SWAP9 = Opcode(0x98, min_stack_height=10) - """ - SWAP9(v1, v2, ..., v9, v10) = v10, v2, ..., v9, v1 - ---- - - Description - ---- - Exchange 1st and 10th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v9: ignored value - - v10: value to swap - - Outputs - ---- - - v10: swapped value - - v2: ignored value - - ... - - v9: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#98](https://www.evm.codes/#98) - """ - - SWAP10 = Opcode(0x99, min_stack_height=11) - """ - SWAP10(v1, v2, ..., v10, v11) = v11, v2, ..., v10, v1 - ---- - - Description - ---- - Exchange 1st and 11th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v10: ignored value - - v11: value to swap - - Outputs - ---- - - v11: swapped value - - v2: ignored value - - ... - - v10: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#99](https://www.evm.codes/#99) - """ - - SWAP11 = Opcode(0x9A, min_stack_height=12) - """ - SWAP11(v1, v2, ..., v11, v12) = v12, v2, ..., v11, v1 - ---- - - Description - ---- - Exchange 1st and 12th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v11: ignored value - - v12: value to swap - - Outputs - ---- - - v12: swapped value - - v2: ignored value - - ... - - v11: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#9A](https://www.evm.codes/#9A) - """ - - SWAP12 = Opcode(0x9B, min_stack_height=13) - """ - SWAP12(v1, v2, ..., v12, v13) = v13, v2, ..., v12, v1 - ---- - - Description - ---- - Exchange 1st and 13th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v12: ignored value - - v13: value to swap - - Outputs - ---- - - v13: swapped value - - v2: ignored value - - ... - - v12: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#9B](https://www.evm.codes/#9B) - """ - - SWAP13 = Opcode(0x9C, min_stack_height=14) - """ - SWAP13(v1, v2, ..., v13, v14) = v14, v2, ..., v13, v1 - ---- - - Description - ---- - Exchange 1st and 14th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v13: ignored value - - v14: value to swap - - Outputs - ---- - - v14: swapped value - - v2: ignored value - - ... - - v13: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#9C](https://www.evm.codes/#9C) - """ - - SWAP14 = Opcode(0x9D, min_stack_height=15) - """ - SWAP14(v1, v2, ..., v14, v15) = v15, v2, ..., v14, v1 - ---- - - Description - ---- - Exchange 1st and 15th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v14: ignored value - - v15: value to swap - - Outputs - ---- - - v15: swapped value - - v2: ignored value - - ... - - v14: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#9D](https://www.evm.codes/#9D) - """ - - SWAP15 = Opcode(0x9E, min_stack_height=16) - """ - SWAP15(v1, v2, ..., v15, v16) = v16, v2, ..., v15, v1 - ---- - - Description - ---- - Exchange 1st and 16th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v15: ignored value - - v16: value to swap - - Outputs - ---- - - v16: swapped value - - v2: ignored value - - ... - - v15: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#9E](https://www.evm.codes/#9E) - """ - - SWAP16 = Opcode(0x9F, min_stack_height=17) - """ - SWAP16(v1, v2, ..., v16, v17) = v17, v2, ..., v16, v1 - ---- - - Description - ---- - Exchange 1st and 17th stack items - - Inputs - ---- - - v1: value to swap - - v2: ignored value - - ... - - v16: ignored value - - v17: value to swap - - Outputs - ---- - - v17: swapped value - - v2: ignored value - - ... - - v16: ignored value - - v1: swapped value - - Fork - ---- - Frontier - - Gas - ---- - 3 - - Source: [evm.codes/#9F](https://www.evm.codes/#9F) - """ - - LOG0 = Opcode(0xA0, popped_stack_items=2, kwargs=["offset", "size"]) - """ - LOG0(offset, size) - ---- - - Description - ---- - Append log record with no topics - - Inputs - ---- - - offset: byte offset in the memory in bytes - - size: byte size to copy - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 375 - - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost - - Source: [evm.codes/#A0](https://www.evm.codes/#A0) - """ - - LOG1 = Opcode(0xA1, popped_stack_items=3, kwargs=["offset", "size", "topic_1"]) - """ - LOG1(offset, size, topic_1) - ---- - - Description - ---- - Append log record with one topic - - Inputs - ---- - - offset: byte offset in the memory in bytes - - size: byte size to copy - - topic_1: 32-byte value - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 375 - - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost - - Source: [evm.codes/#A1](https://www.evm.codes/#A1) - """ - - LOG2 = Opcode(0xA2, popped_stack_items=4, kwargs=["offset", "size", "topic_1", "topic_2"]) - """ - LOG2(offset, size, topic_1, topic_2) - ---- - - Description - ---- - Append log record with two topics - - Inputs - ---- - - offset: byte offset in the memory in bytes - - size: byte size to copy - - topic_1: 32-byte value - - topic_2: 32-byte value - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 375 - - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost - - Source: [evm.codes/#A2](https://www.evm.codes/#A2) - """ - - LOG3 = Opcode( - 0xA3, popped_stack_items=5, kwargs=["offset", "size", "topic_1", "topic_2", "topic_3"] - ) - """ - LOG3(offset, size, topic_1, topic_2, topic_3) - ---- - - Description - ---- - Append log record with three topics - - Inputs - ---- - - offset: byte offset in the memory in bytes - - size: byte size to copy - - topic_1: 32-byte value - - topic_2: 32-byte value - - topic_3: 32-byte value - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 375 - - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost - - Source: [evm.codes/#A3](https://www.evm.codes/#A3) - """ - - LOG4 = Opcode( - 0xA4, - popped_stack_items=6, - kwargs=["offset", "size", "topic_1", "topic_2", "topic_3", "topic_4"], - ) - """ - LOG4(offset, size, topic_1, topic_2, topic_3, topic_4) - ---- - - Description - ---- - Append log record with four topics - - Inputs - ---- - - offset: byte offset in the memory in bytes - - size: byte size to copy - - topic_1: 32-byte value - - topic_2: 32-byte value - - topic_3: 32-byte value - - topic_4: 32-byte value - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 375 - - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost - - Source: [evm.codes/#A4](https://www.evm.codes/#A4) - """ - - RJUMP = Opcode(0xE0, data_portion_length=2) - """ - !!! Note: This opcode is under development - - RJUMP() - ---- - - Description - ---- - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - EOF Fork - - Gas - ---- - - Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) - """ - - DATALOAD = Opcode(0xD0, popped_stack_items=1, kwargs=["offset"]) - """ - !!! Note: This opcode is under development - - DATALOAD(offset) - ---- - - Description - ---- - Reads 32 bytes of data at offset onto the stack - - Inputs - ---- - - offset: offset within the data section to start copying - - Outputs - ---- - none - - Fork - ---- - EOF Fork - - Gas - ---- - 4 - - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) - """ - - DATALOADN = Opcode(0xD1, pushed_stack_items=1, data_portion_length=2) - """ - !!! Note: This opcode is under development - - DATALOADN() - ---- - - Description - ---- - Reads 32 bytes of data at offset onto the stack - - Immediates - ---- - 2 bytes forming a UInt16, which is the offset into the data section. - - Inputs - ---- - none - - Outputs - ---- - none - - Fork - ---- - EOF Fork - - Gas - ---- - 3 - - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) - """ - - DATASIZE = Opcode(0xD2, pushed_stack_items=1) - """ - !!! Note: This opcode is under development - - DATASIZE() - ---- - - Description - ---- - Returns the size of the data section - - Inputs - ---- - - Outputs - ---- - The size of the data section. If there is no data section, returns 0. - - Fork - ---- - EOF Fork - - Gas - ---- - 2 - - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) - """ - - DATACOPY = Opcode(0xD3, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) - """ - !!! Note: This opcode is under development - - DATACOPY(dest_offset, offset, size) - ---- - - Description - ---- - Copies data from the data section into call frame memory - - Inputs - ---- - - dest_offset: The offset within the memory section to start copying to - - offset: The offset within the data section to start copying from - - size: The number of bytes to copy - - Outputs - ---- - none - - Fork - ---- - EOF Fork - - Gas - ---- - - minimum_word_size = (size + 31) / 32 - - static_gas = 3 - - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost - - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) - """ - - RJUMPI = Opcode(0xE1, popped_stack_items=1, data_portion_length=2) - """ - !!! Note: This opcode is under development - - RJUMPI() - ---- - - Description - ---- - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - EOF Fork - - Gas - ---- - - Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) - """ - - RJUMPV = Opcode( - 0xE2, - popped_stack_items=1, - data_portion_formatter=_rjumpv_encoder, - ) - """ - !!! Note: This opcode is under development - - RJUMPV() - ---- - - Description - ---- - Relative jump with variable offset. - - When calling this opcode to generate bytecode, the first argument is used to format the data - portion of the opcode, and it can be either of two types: - - A bytes type, and in this instance the bytes are used verbatim as the data portion. - - An integer iterable, list or tuple or any other iterable, where each element is a - jump offset. - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - EOF Fork - - Gas - ---- - - Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) - """ - - CALLF = Opcode(0xE3, data_portion_length=2, unchecked_stack=True) - """ - !!! Note: This opcode is under development - - CALLF() - ---- - - Description - ---- - - - deduct 5 gas - - read uint16 operand idx - - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in - an exceptional halt - - if 1024 <= len(return_stack), execution results in an exceptional halt - - push new element to return_stack (current_code_idx, pc+3) - - update current_code_idx to idx and set pc to 0 - - Inputs - ---- - Any: The inputs are not checked because we cannot know how many inputs the callee - function/section requires - - Outputs - ---- - Any: The outputs are variable because we cannot know how many outputs the callee - function/section produces - - Fork - ---- - EOF Fork - - Gas - ---- - 5 - - Source: - [ipsilon/eof/blob/main/spec/eof.md](https://github.com/ipsilon/eof/blob/main/spec/eof.md) - """ - - RETF = Opcode(0xE4) - """ - !!! Note: This opcode is under development - - RETF() - ---- - - Description - ---- - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - EOF Fork - - Gas - ---- - 3 - """ - - JUMPF = Opcode(0xE5, data_portion_length=2) - """ - !!! Note: This opcode is under development - - JUMPF() - ---- - - Description - ---- - - - deduct 5 gas - - read uint16 operand idx - - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in - an exceptional halt - - set current_code_idx to idx - - set pc = 0 - - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - EOF Fork - - Gas - ---- - 5 - - """ - - DUPN = Opcode( - 0xE6, - pushed_stack_items=1, - data_portion_length=1, - stack_properties_modifier=_dupn_stack_properties_modifier, - ) - """ - !!! Note: This opcode is under development - - DUPN() - ---- - - Description - ---- - - - deduct 3 gas - - read uint8 operand imm - - n = imm + 1 - - n‘th (1-based) stack item is duplicated at the top of the stack - - Stack validation: stack_height >= n - - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - EOF Fork - - Gas - ---- - - """ - - SWAPN = Opcode( - 0xE7, data_portion_length=1, stack_properties_modifier=_swapn_stack_properties_modifier - ) - """ - !!! Note: This opcode is under development - - SWAPN() - ---- - - Description - ---- - - - deduct 3 gas - - read uint8 operand imm - - n = imm + 1 - - n + 1th stack item is swapped with the top stack item (1-based). - - Stack validation: stack_height >= n + 1 - - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - EOF Fork - - Gas - ---- - - """ - - EXCHANGE = Opcode( - 0xE8, - data_portion_formatter=_exchange_encoder, - stack_properties_modifier=_exchange_stack_properties_modifier, - ) - """ - !!! Note: This opcode is under development - - EXCHANGE[x, y] - ---- - - Description - ---- - Exchanges two stack positions. Two nybbles, n is high 4 bits + 1, then m is 4 low bits + 1. - Exchanges tne n+1'th item with the n + m + 1 item. - - Inputs x and y when the opcode is used as `EXCHANGE[x, y]`, are equal to: - - x = n + 1 - - y = n + m + 1 - Which each equals to 1-based stack positions swapped. - - Inputs - ---- - n + m + 1, or ((imm >> 4) + (imm &0x0F) + 3) from the raw immediate, - - Outputs - ---- - n + m + 1, or ((imm >> 4) + (imm &0x0F) + 3) from the raw immediate, - - Fork - ---- - EOF_FORK - - Gas - ---- - 3 - - """ - - EOFCREATE = Opcode( - 0xEC, - popped_stack_items=4, - pushed_stack_items=1, - data_portion_length=1, - kwargs=["value", "salt", "input_offset", "input_size"], - ) - """ - !!! Note: This opcode is under development - - EOFCREATE[initcontainer_index](value, salt, input_offset, input_size) - ---- - - Description - ---- - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - - Gas - ---- - - """ - - RETURNCONTRACT = Opcode(0xEE, popped_stack_items=2, data_portion_length=1) - """ - !!! Note: This opcode is under development - - RETURNCONTRACT() - ---- - - Description - ---- - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - - Gas - ---- - - """ - - CREATE = Opcode( - 0xF0, popped_stack_items=3, pushed_stack_items=1, kwargs=["value", "offset", "size"] - ) - """ - CREATE(value, offset, size) = address - ---- - - Description - ---- - Create a new contract with the given code - - Inputs - ---- - - value: value in wei to send to the new account - - offset: byte offset in the memory in bytes, the initialization code for the new account - - size: byte size to copy (size of the initialization code) - - Outputs - ---- - - address: the address of the deployed contract, 0 if the deployment failed - - Fork - ---- - Frontier - - Gas - ---- - ``` - minimum_word_size = (size + 31) / 32 - init_code_cost = 2 * minimum_word_size - code_deposit_cost = 200 * deployed_code_size - - static_gas = 32000 - dynamic_gas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost - + code_deposit_cost - ``` - - Source: [evm.codes/#F0](https://www.evm.codes/#F0) - """ - - CALL = Opcode( - 0xF1, - popped_stack_items=7, - pushed_stack_items=1, - kwargs=["gas", "address", "value", "args_offset", "args_size", "ret_offset", "ret_size"], - kwargs_defaults={"gas": GAS}, - ) - """ - CALL(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success - ---- - - Description - ---- - Message-call into an account - - Inputs - ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one - - address: the account which context to execute - - value: value in wei to send to the account - - args_offset: byte offset in the memory in bytes, the calldata of the sub context - - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context - - ret_size: byte size to copy (size of the return data) - - Outputs - ---- - - success: return 0 if the sub context reverted, 1 otherwise - - Fork - ---- - Frontier - - Gas - ---- - ``` - static_gas = 0 - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - + positive_value_cost + value_to_empty_account_cost - ``` - - Source: [evm.codes/#F1](https://www.evm.codes/#F1) - """ - - CALLCODE = Opcode( - 0xF2, - popped_stack_items=7, - pushed_stack_items=1, - kwargs=["gas", "address", "value", "args_offset", "args_size", "ret_offset", "ret_size"], - kwargs_defaults={"gas": GAS}, - ) - """ - CALLCODE(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success - ---- - - Description - ---- - Message-call into this account with an alternative account's code. Executes code starting at - the address to which the call is made. - - Inputs - ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one - - address: the account which code to execute - - value: value in wei to send to the account - - args_offset: byte offset in the memory in bytes, the calldata of the sub context - - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context - - ret_size: byte size to copy (size of the return data) - - Outputs - ---- - - success: return 0 if the sub context reverted, 1 otherwise - - Fork - ---- - Frontier - - Gas - ---- - ``` - static_gas = 0 - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - + positive_value_cost - ``` - - Source: [evm.codes/#F2](https://www.evm.codes/#F2) - """ - - RETURN = Opcode(0xF3, popped_stack_items=2, kwargs=["offset", "size"]) - """ - RETURN(offset, size) - ---- - - Description - ---- - Halt execution returning output data - - Inputs - ---- - - offset: byte offset in the memory in bytes, to copy what will be the return data of this - context - - size: byte size to copy (size of the return data) - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - - static_gas = 0 - - dynamic_gas = memory_expansion_cost - - Source: [evm.codes/#F3](https://www.evm.codes/#F3) - """ - - DELEGATECALL = Opcode( - 0xF4, - popped_stack_items=6, - pushed_stack_items=1, - kwargs=["gas", "address", "args_offset", "args_size", "ret_offset", "ret_size"], - kwargs_defaults={"gas": GAS}, - ) - """ - DELEGATECALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success - ---- - - Description - ---- - Message-call into this account with an alternative account's code, but persisting the current - values for sender and value - - Inputs - ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one - - address: the account which code to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context - - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context - - ret_size: byte size to copy (size of the return data) - - Outputs - ---- - - success: return 0 if the sub context reverted, 1 otherwise - - Fork - ---- - Byzantium - - Gas - ---- - - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - - Source: [evm.codes/#F4](https://www.evm.codes/#F4) - """ - - CREATE2 = Opcode( - 0xF5, - popped_stack_items=4, - pushed_stack_items=1, - kwargs=["value", "offset", "size", "salt"], - ) - """ - CREATE2(value, offset, size, salt) = address - ---- - - Description - ---- - Creates a new contract - - Inputs - ---- - - value: value in wei to send to the new account - - offset: byte offset in the memory in bytes, the initialization code of the new account - - size: byte size to copy (size of the initialization code) - - salt: 32-byte value used to create the new account at a deterministic address - - Outputs - ---- - - address: the address of the deployed contract, 0 if the deployment failed - - Fork - ---- - Constantinople - - Gas - ---- - ``` - minimum_word_size = (size + 31) / 32 - init_code_cost = 2 * minimum_word_size - hash_cost = 6 * minimum_word_size - code_deposit_cost = 200 * deployed_code_size - - static_gas = 32000 - dynamic_gas = init_code_cost + hash_cost + memory_expansion_cost - + deployment_code_execution_cost + code_deposit_cost - ``` - - Source: [evm.codes/#F5](https://www.evm.codes/#F5) - """ - - EXTCALL = Opcode( - 0xF8, - popped_stack_items=4, - pushed_stack_items=1, - kwargs=["address", "args_offset", "args_size", "value"], - ) - """ - EXTCALL(address, args_offset, args_size, value) = address - ---- - - Description - ---- - Message-call into an account - - Inputs - ---- - - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context - - args_size: byte size to copy (size of the calldata) - - value: value in wei to send to the account - - Outputs - ---- - - success: - - `0` if the call was successful. - - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). - - `2` if the call has failed. - - Fork - ---- - Prague - - Gas - ---- - ``` - static_gas = 0 - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - + positive_value_cost + value_to_empty_account_cost - ``` - - Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) - """ - - EXTDELEGATECALL = Opcode( - 0xF9, - popped_stack_items=3, - pushed_stack_items=1, - kwargs=["address", "args_offset", "args_size"], - ) - """ - EXTDELEGATECALL(address, args_offset, args_size) = address - ---- - - Description - ---- - Message-call into this account with an alternative account's code, but persisting the current - values for sender and value - - Inputs - ---- - - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context - - args_size: byte size to copy (size of the calldata) - - Outputs - ---- - - success: - - `0` if the call was successful. - - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). - - `2` if the call has failed. - - Fork - ---- - Prague - - Gas - ---- - - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - - Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) - """ - - STATICCALL = Opcode( - 0xFA, - popped_stack_items=6, - pushed_stack_items=1, - kwargs=["gas", "address", "args_offset", "args_size", "ret_offset", "ret_size"], - kwargs_defaults={"gas": GAS}, - ) - """ - STATICCALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success - ---- - - Description - ---- - Static message-call into an account - - Inputs - ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one - - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context - - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context - - ret_size: byte size to copy (size of the return data) - - Outputs - ---- - - success: return 0 if the sub context reverted, 1 otherwise - - Fork - ---- - Byzantium - - Gas - ---- - - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - - Source: [evm.codes/#FA](https://www.evm.codes/#FA) - """ - - EXTSTATICCALL = Opcode( - 0xFB, - popped_stack_items=3, - pushed_stack_items=1, - kwargs=["address", "args_offset", "args_size"], - ) - """ - EXTSTATICCALL(address, args_offset, args_size) = address - ---- - - Description - ---- - Static message-call into an account - - Inputs - ---- - - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context - - args_size: byte size to copy (size of the calldata) - - Outputs - ---- - - success: - - `0` if the call was successful. - - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). - - `2` if the call has failed. - - Fork - ---- - Prague - - Gas - ---- - - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - - Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) - """ - - RETURNDATALOAD = Opcode(0xF7, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"]) - """ - RETURNDATALOAD(offset) - ---- - - Description - ---- - Copy 32 bytes from returndata at offset onto the stack - - Inputs - ---- - - offset: byte offset in the return data from the last executed sub context to copy - - Fork - ---- - EOF - - Gas - ---- - 3 - """ - - REVERT = Opcode(0xFD, popped_stack_items=2, kwargs=["offset", "size"]) - """ - REVERT(offset, size) - ---- - - Description - ---- - Halt execution reverting state changes but returning data and remaining gas - - Inputs - ---- - - offset: byte offset in the memory in bytes. The return data of the calling context - - size: byte size to copy (size of the return data) - - Fork - ---- - Byzantium - - Gas - ---- - static_gas = 0 - dynamic_gas = memory_expansion_cost - - Source: [evm.codes/#FD](https://www.evm.codes/#FD) - """ - - INVALID = Opcode(0xFE) - """ - INVALID() - ---- - - Description - ---- - Designated invalid instruction - - Inputs - ---- - None - - Outputs - ---- - None - - Fork - ---- - Frontier - - Gas - ---- - All the remaining gas in this context is consumed - - Source: [evm.codes/#FE](https://www.evm.codes/#FE) - """ - - SELFDESTRUCT = Opcode(0xFF, popped_stack_items=1, kwargs=["address"]) - """ - SELFDESTRUCT(address) - ---- - - Description - ---- - Halt execution and register the account for later deletion - - Inputs - ---- - - address: account to send the current balance to - - Fork - ---- - Frontier - - Gas - ---- - 5000 - - Source: [evm.codes/#FF](https://www.evm.codes/#FF) - """ - - -_push_opcodes_byte_list: List[Opcode] = [ - Opcodes.PUSH1, - Opcodes.PUSH2, - Opcodes.PUSH3, - Opcodes.PUSH4, - Opcodes.PUSH5, - Opcodes.PUSH6, - Opcodes.PUSH7, - Opcodes.PUSH8, - Opcodes.PUSH9, - Opcodes.PUSH10, - Opcodes.PUSH11, - Opcodes.PUSH12, - Opcodes.PUSH13, - Opcodes.PUSH14, - Opcodes.PUSH15, - Opcodes.PUSH16, - Opcodes.PUSH17, - Opcodes.PUSH18, - Opcodes.PUSH19, - Opcodes.PUSH20, - Opcodes.PUSH21, - Opcodes.PUSH22, - Opcodes.PUSH23, - Opcodes.PUSH24, - Opcodes.PUSH25, - Opcodes.PUSH26, - Opcodes.PUSH27, - Opcodes.PUSH28, - Opcodes.PUSH29, - Opcodes.PUSH30, - Opcodes.PUSH31, - Opcodes.PUSH32, -] - - -def _mstore_operation(data: OpcodeCallArg = b"", offset: OpcodeCallArg = 0) -> Bytecode: - """ - Helper function to generate the bytecode that stores an arbitrary amount of data in memory. - """ - assert isinstance(offset, int) - if isinstance(data, int): - data = data.to_bytes(32, "big") - data = to_bytes(data) # type: ignore - bytecode = Bytecode() - for i in range(0, len(data), 32): - chunk = data[i : i + 32] - if len(chunk) == 32: - bytecode += Opcodes.MSTORE(offset, chunk) - else: - # We need to MLOAD the existing data at the offset and then do a bitwise OR with the - # new data to store it in memory. - bytecode += Opcodes.MLOAD(offset) - # Create a mask to zero out the leftmost bytes of the existing data. - mask_size = 32 - len(chunk) - bytecode += _push_opcodes_byte_list[mask_size - 1][-1] - bytecode += Opcodes.AND - bytecode += Opcodes.PUSH32[chunk.ljust(32, b"\x00")] - bytecode += Opcodes.OR - bytecode += _stack_argument_to_bytecode(offset) - bytecode += Opcodes.MSTORE - offset += len(chunk) - return bytecode - - -class Macros(Macro, Enum): - """ - Enum containing all macros. - """ - - OOG = Macro(Opcodes.SHA3(0, 100000000000)) - """ - OOG() - ---- - - Halt execution by consuming all available gas. - - Inputs - ---- - - None. Any input arguments are ignored. - - Outputs - ---- - - None - - Fork - ---- - Frontier - - Gas - ---- - `SHA3(0, 100000000000)` results in 19073514453125027 gas used and an OOG - exception. - - Note: - If a value > `100000000000` is used as second argument, the resulting geth - trace reports gas `30` and an OOG exception. - `SHA3(0, SUB(0, 1))` causes a gas > u64 exception and an OOG exception. - - Bytecode - ---- - SHA3(0, 100000000000) - """ - - MSTORE = Macro(lambda_operation=_mstore_operation) - """ - MSTORE(data, offset) - ---- - - Place data of arbitrary length into memory at a given offset. - - Inputs - ---- - - data: The data to store in memory. Can be an integer or bytes. - - offset: The offset in memory to store the data. - - Outputs - ---- - - None - """ - - -class UndefinedOpcodes(Opcode, Enum): - """ - Enum containing all unknown opcodes (88 at the moment). - """ - - OPCODE_0C = Opcode(0x0C) - OPCODE_0D = Opcode(0x0D) - OPCODE_0E = Opcode(0x0E) - OPCODE_0F = Opcode(0x0F) - OPCODE_1E = Opcode(0x1E) - OPCODE_1F = Opcode(0x1F) - OPCODE_21 = Opcode(0x21) - OPCODE_22 = Opcode(0x22) - OPCODE_23 = Opcode(0x23) - OPCODE_24 = Opcode(0x24) - OPCODE_25 = Opcode(0x25) - OPCODE_26 = Opcode(0x26) - OPCODE_27 = Opcode(0x27) - OPCODE_28 = Opcode(0x28) - OPCODE_29 = Opcode(0x29) - OPCODE_2A = Opcode(0x2A) - OPCODE_2B = Opcode(0x2B) - OPCODE_2C = Opcode(0x2C) - OPCODE_2D = Opcode(0x2D) - OPCODE_2E = Opcode(0x2E) - OPCODE_2F = Opcode(0x2F) - OPCODE_4B = Opcode(0x4B) - OPCODE_4C = Opcode(0x4C) - OPCODE_4D = Opcode(0x4D) - OPCODE_4E = Opcode(0x4E) - OPCODE_4F = Opcode(0x4F) - OPCODE_A5 = Opcode(0xA5) - OPCODE_A6 = Opcode(0xA6) - OPCODE_A7 = Opcode(0xA7) - OPCODE_A8 = Opcode(0xA8) - OPCODE_A9 = Opcode(0xA9) - OPCODE_AA = Opcode(0xAA) - OPCODE_AB = Opcode(0xAB) - OPCODE_AC = Opcode(0xAC) - OPCODE_AD = Opcode(0xAD) - OPCODE_AE = Opcode(0xAE) - OPCODE_AF = Opcode(0xAF) - OPCODE_B0 = Opcode(0xB0) - OPCODE_B1 = Opcode(0xB1) - OPCODE_B2 = Opcode(0xB2) - OPCODE_B3 = Opcode(0xB3) - OPCODE_B4 = Opcode(0xB4) - OPCODE_B5 = Opcode(0xB5) - OPCODE_B6 = Opcode(0xB6) - OPCODE_B7 = Opcode(0xB7) - OPCODE_B8 = Opcode(0xB8) - OPCODE_B9 = Opcode(0xB9) - OPCODE_BA = Opcode(0xBA) - OPCODE_BB = Opcode(0xBB) - OPCODE_BC = Opcode(0xBC) - OPCODE_BD = Opcode(0xBD) - OPCODE_BE = Opcode(0xBE) - OPCODE_BF = Opcode(0xBF) - OPCODE_C0 = Opcode(0xC0) - OPCODE_C1 = Opcode(0xC1) - OPCODE_C2 = Opcode(0xC2) - OPCODE_C3 = Opcode(0xC3) - OPCODE_C4 = Opcode(0xC4) - OPCODE_C5 = Opcode(0xC5) - OPCODE_C6 = Opcode(0xC6) - OPCODE_C7 = Opcode(0xC7) - OPCODE_C8 = Opcode(0xC8) - OPCODE_C9 = Opcode(0xC9) - OPCODE_CA = Opcode(0xCA) - OPCODE_CB = Opcode(0xCB) - OPCODE_CC = Opcode(0xCC) - OPCODE_CD = Opcode(0xCD) - OPCODE_CE = Opcode(0xCE) - OPCODE_CF = Opcode(0xCF) - OPCODE_D4 = Opcode(0xD4) - OPCODE_D5 = Opcode(0xD5) - OPCODE_D6 = Opcode(0xD6) - OPCODE_D7 = Opcode(0xD7) - OPCODE_D8 = Opcode(0xD8) - OPCODE_D9 = Opcode(0xD9) - OPCODE_DA = Opcode(0xDA) - OPCODE_DB = Opcode(0xDB) - OPCODE_DC = Opcode(0xDC) - OPCODE_DD = Opcode(0xDD) - OPCODE_DE = Opcode(0xDE) - OPCODE_DF = Opcode(0xDF) - OPCODE_E9 = Opcode(0xE9) - OPCODE_EA = Opcode(0xEA) - OPCODE_EB = Opcode(0xEB) - OPCODE_ED = Opcode(0xED) - OPCODE_EF = Opcode(0xEF) - OPCODE_F6 = Opcode(0xF6) - OPCODE_FC = Opcode(0xFC) +from ethereum_test_vm import ( + Bytecode, + Macro, + Macros, + Opcode, + OpcodeCallArg, + Opcodes, + UndefinedOpcodes, +) + +__all__ = ( + "Bytecode", + "Macro", + "Macros", + "Opcode", + "OpcodeCallArg", + "Opcodes", + "UndefinedOpcodes", +) diff --git a/src/ethereum_test_tools/common/__init__.py b/src/ethereum_test_types/__init__.py similarity index 69% rename from src/ethereum_test_tools/common/__init__.py rename to src/ethereum_test_types/__init__.py index 1812f1111b..3af9724b61 100644 --- a/src/ethereum_test_tools/common/__init__.py +++ b/src/ethereum_test_types/__init__.py @@ -2,27 +2,6 @@ Common definitions and types. """ -from .base_types import ( - Address, - Bloom, - Bytes, - Hash, - HeaderNonce, - HexNumber, - Number, - ZeroPaddedHexNumber, -) -from .constants import ( - AddrAA, - AddrBB, - EmptyOmmersRoot, - EmptyTrieRoot, - EngineAPIError, - TestAddress, - TestAddress2, - TestPrivateKey, - TestPrivateKey2, -) from .helpers import ( TestParameterGroup, add_kzg_version, @@ -34,12 +13,12 @@ cost_memory_bytes, eip_2028_transaction_data_cost, ) -from .json import to_json from .types import ( EOA, AccessList, Account, Alloc, + CamelModel, DepositRequest, Environment, Removable, @@ -53,28 +32,20 @@ __all__ = ( "AccessList", "Account", - "Address", - "AddrAA", - "AddrBB", "Alloc", - "Bloom", - "Bytes", + "CamelModel", "DepositRequest", - "EngineAPIError", - "EmptyOmmersRoot", "EmptyTrieRoot", "Environment", + "EOA", "Hash", "HeaderNonce", "HexNumber", "Number", "Removable", "Requests", - "EOA", "Storage", "TestParameterGroup", - "TestAddress", - "TestAddress2", "TestPrivateKey", "TestPrivateKey2", "Transaction", diff --git a/src/ethereum_test_types/eof/__init__.py b/src/ethereum_test_types/eof/__init__.py new file mode 100644 index 0000000000..dc97c8eaa7 --- /dev/null +++ b/src/ethereum_test_types/eof/__init__.py @@ -0,0 +1,6 @@ +""" +EVM Object Format Libary to generate bytecode for testing purposes +""" +from .constants import LATEST_EOF_VERSION + +__all__ = ("LATEST_EOF_VERSION",) diff --git a/src/ethereum_test_types/eof/constants.py b/src/ethereum_test_types/eof/constants.py new file mode 100644 index 0000000000..06b68c576d --- /dev/null +++ b/src/ethereum_test_types/eof/constants.py @@ -0,0 +1,21 @@ +""" +EVM Object Format generic constants. +Applicable to all EOF versions. +""" +EOF_MAGIC = b"\xef\x00" +""" +The second byte found on every EOF formatted contract, which was chosen to +avoid clashes with three contracts which were deployed on Mainnet. +""" +EOF_HEADER_TERMINATOR = b"\x00" +""" +Byte that terminates the header of the EOF format. +""" +LATEST_EOF_VERSION = 1 +""" +Latest existing EOF version. +""" +VERSION_BYTE_LENGTH = 1 +""" +Length of the version byte. +""" diff --git a/src/ethereum_test_types/eof/v1/__init__.py b/src/ethereum_test_types/eof/v1/__init__.py new file mode 100644 index 0000000000..7e25bf7c94 --- /dev/null +++ b/src/ethereum_test_types/eof/v1/__init__.py @@ -0,0 +1,564 @@ +""" +EVM Object Format Version 1 Library to generate bytecode for testing purposes +""" + +from dataclasses import dataclass +from enum import Enum, IntEnum, auto +from functools import cached_property +from typing import Any, Dict, List, Optional, Tuple + +from pydantic import Field, GetCoreSchemaHandler +from pydantic_core.core_schema import ( + PlainValidatorFunctionSchema, + no_info_plain_validator_function, + to_string_ser_schema, +) + +from ethereum_test_base_types import Bytes +from ethereum_test_base_types.conversions import BytesConvertible +from ethereum_test_base_types.pydantic import CopyValidateModel +from ethereum_test_exceptions import EOFException +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op + +from ..constants import EOF_HEADER_TERMINATOR, EOF_MAGIC +from .constants import ( + HEADER_SECTION_COUNT_BYTE_LENGTH, + HEADER_SECTION_KIND_BYTE_LENGTH, + HEADER_SECTION_SIZE_BYTE_LENGTH, + NON_RETURNING_SECTION, + TYPES_INPUTS_BYTE_LENGTH, + TYPES_OUTPUTS_BYTE_LENGTH, + TYPES_STACK_BYTE_LENGTH, + VERSION_NUMBER_BYTES, +) + +VERSION_MAX_SECTION_KIND = 3 + + +class SectionKind(IntEnum): + """ + Enum class of V1 valid section kind values + """ + + TYPE = 1 + CODE = 2 + CONTAINER = 3 + DATA = 4 + + def __str__(self) -> str: + """ + Returns the string representation of the section kind + """ + return self.name + + +class ContainerKind(Enum): + """ + Enum class of V1 valid container kind values. + """ + + RUNTIME = auto() + INITCODE = auto() + + @staticmethod + def __get_pydantic_core_schema__( + source_type: Any, handler: GetCoreSchemaHandler + ) -> PlainValidatorFunctionSchema: + """ + Calls the class constructor without info and appends the serialization schema. + """ + return no_info_plain_validator_function( + source_type, + serialization=to_string_ser_schema(), + ) + + def __str__(self) -> str: + """ + Returns the string representation of the container kind + """ + return self.name + + +class AutoSection(Enum): + """ + Enum class for auto section generation approach + """ + + AUTO = 1 + ONLY_HEADER = 2 + ONLY_BODY = 3 + NONE = 4 + + def any(self) -> bool: + """ + Returns True if the enum is not NONE + """ + return self != AutoSection.NONE + + def header(self) -> bool: + """ + Returns True if the enum is not ONLY_BODY + """ + return self != AutoSection.ONLY_BODY and self != AutoSection.NONE + + def body(self) -> bool: + """ + Returns True if the enum is not ONLY_HEADER + """ + return self != AutoSection.ONLY_HEADER and self != AutoSection.NONE + + +SUPPORT_MULTI_SECTION_HEADER = [SectionKind.CODE, SectionKind.CONTAINER] + + +class Section(CopyValidateModel): + """ + Class that represents a section in an EOF V1 container. + """ + + data: Bytes = Bytes(b"") + """ + Data to be contained by this section. + Can be SupportsBytes, another EOF container or any other abstract data. + """ + custom_size: int = 0 + """ + Custom size value to be used in the header. + If unset, the header is built with length of the data. + """ + kind: SectionKind | int + """ + Kind of section that is represented by this object. + Can be any `int` outside of the values defined by `SectionKind` + for testing purposes. + """ + force_type_listing: bool = False + """ + Forces this section to appear in the TYPE section at the beginning of the + container. + """ + code_inputs: int = 0 + """ + Data stack items consumed by this code section (function) + """ + code_outputs: int = NON_RETURNING_SECTION + """ + Data stack items produced by or expected at the end of this code section + (function) + """ + max_stack_height: int = 0 + """ + Maximum height data stack reaches during execution of code section. + """ + auto_max_stack_height: bool = False + """ + Whether to automatically compute the best suggestion for the + max_stack_height value for this code section. + """ + auto_code_inputs_outputs: bool = False + """ + Whether to automatically compute the best suggestion for the code_inputs, + code_outputs values for this code section. + """ + skip_header_listing: bool = False + """ + Skip section from listing in the header + """ + skip_body_listing: bool = False + """ + Skip section from listing in the body + """ + skip_types_body_listing: bool = False + """ + Skip section from listing in the types body (input, output, stack) bytes + """ + skip_types_header_listing: bool = False + """ + Skip section from listing in the types header (not calculating input, output, stack size) + """ + + @cached_property + def header(self) -> bytes: + """ + Get formatted header for this section according to its contents. + """ + size = self.custom_size if "custom_size" in self.model_fields_set else len(self.data) + if self.kind == SectionKind.CODE: + raise Exception("Need container-wide view of code sections to generate header") + return self.kind.to_bytes( + HEADER_SECTION_KIND_BYTE_LENGTH, byteorder="big" + ) + size.to_bytes(HEADER_SECTION_SIZE_BYTE_LENGTH, byteorder="big") + + @cached_property + def type_definition(self) -> bytes: + """ + Returns a serialized type section entry for this section. + """ + if self.kind != SectionKind.CODE and not self.force_type_listing: + return bytes() + + code_inputs, code_outputs, max_stack_height = ( + self.code_inputs, + self.code_outputs, + self.max_stack_height, + ) + if self.auto_max_stack_height or self.auto_code_inputs_outputs: + ( + auto_code_inputs, + auto_code_outputs, + auto_max_height, + ) = compute_code_stack_values(self.data) + if self.auto_max_stack_height: + max_stack_height = auto_max_height + if self.auto_code_inputs_outputs: + code_inputs, code_outputs = ( + auto_code_inputs, + auto_code_outputs, + ) + + return ( + code_inputs.to_bytes(length=TYPES_INPUTS_BYTE_LENGTH, byteorder="big") + + code_outputs.to_bytes(length=TYPES_OUTPUTS_BYTE_LENGTH, byteorder="big") + + max_stack_height.to_bytes(length=TYPES_STACK_BYTE_LENGTH, byteorder="big") + ) + + def with_max_stack_height(self, max_stack_height) -> "Section": + """ + Creates a copy of the section with `max_stack_height` set to the + specified value. + """ + return self.copy(max_stack_height=max_stack_height) + + def with_auto_max_stack_height(self) -> "Section": + """ + Creates a copy of the section with `auto_max_stack_height` set to True. + """ + return self.copy(auto_max_stack_height=True) + + def with_auto_code_inputs_outputs(self) -> "Section": + """ + Creates a copy of the section with `auto_code_inputs_outputs` set to + True. + """ + return self.copy(auto_code_inputs_outputs=True) + + @staticmethod + def list_header(sections: List["Section"]) -> bytes: + """ + Creates the single code header for all code sections contained in + the list. + """ + # Allow 'types section' to use skip_header_listing flag + if sections[0].skip_header_listing: + return b"" + + if sections[0].kind not in SUPPORT_MULTI_SECTION_HEADER: + return b"".join(s.header for s in sections) + + h = sections[0].kind.to_bytes(HEADER_SECTION_KIND_BYTE_LENGTH, "big") + + # Count only those sections that are not marked to be skipped for header calculation + header_registered_sections = 0 + for cs in sections: + if not cs.skip_header_listing: + header_registered_sections += 1 + + h += header_registered_sections.to_bytes(HEADER_SECTION_COUNT_BYTE_LENGTH, "big") + for cs in sections: + # If section is marked to skip the header calculation, don't make header for it + if cs.skip_header_listing: + continue + size = cs.custom_size if "custom_size" in cs.model_fields_set else len(cs.data) + h += size.to_bytes(HEADER_SECTION_SIZE_BYTE_LENGTH, "big") + + return h + + @classmethod + def Code( # noqa: N802 + cls, code: BytesConvertible | Bytecode = Bytecode(), **kwargs + ) -> "Section": + """ + Creates a new code section with the specified code. + """ + kwargs.pop("kind", None) + if "max_stack_height" not in kwargs and isinstance(code, Bytecode): + kwargs["max_stack_height"] = code.max_stack_height + return cls(kind=SectionKind.CODE, data=code, **kwargs) + + @classmethod + def Container( # noqa: N802 + cls, container: "Container" | BytesConvertible, **kwargs + ) -> "Section": + """ + Creates a new container section with the specified container. + """ + kwargs.pop("kind", None) + return cls(kind=SectionKind.CONTAINER, data=container, **kwargs) + + @classmethod + def Data(cls, data: BytesConvertible = b"", **kwargs) -> "Section": # noqa: N802 + """ + Creates a new data section with the specified data. + """ + kwargs.pop("kind", None) + return cls(kind=SectionKind.DATA, data=data, **kwargs) + + +class Container(CopyValidateModel): + """ + Class that represents an EOF V1 container. + """ + + name: Optional[str] = None + """ + Name of the container + """ + sections: List[Section] = Field(default_factory=list) + """ + List of sections in the container + """ + magic: Bytes = Bytes(EOF_MAGIC) + """ + Custom magic value used to override the mandatory EOF value for testing + purposes. + """ + version: Bytes = Bytes(VERSION_NUMBER_BYTES) + """ + Custom version value used to override the mandatory EOF V1 value + for testing purposes. + """ + header_terminator: Bytes = Bytes(EOF_HEADER_TERMINATOR) + """ + Bytes used to terminate the header. + """ + extra: Bytes = Bytes(b"") + """ + Extra data to be appended at the end of the container, which will + not be considered part of any of the sections, for testing purposes. + """ + auto_type_section: AutoSection = AutoSection.AUTO + """ + Automatically generate a `TYPE` section based on the + included `CODE` kind sections. + """ + auto_data_section: bool = True + """ + Automatically generate a `DATA` section. + """ + auto_sort_sections: AutoSection = AutoSection.AUTO + """ + Automatically sort sections for the header and body: + Headers: type section first, all code sections, container sections, last + data section(s) + Body: type section first, all code sections, data section(s), last + container sections + """ + validity_error: EOFException | str | None = None + """ + Optional error expected for the container. + + TODO: Remove str + """ + kind: ContainerKind = ContainerKind.RUNTIME + """ + Kind type of the container. + """ + raw_bytes: Optional[Bytes] = None + """ + Optional raw bytes that represent the container. + Used to have a cohesive type among all test cases, even those that do not + resemble a valid EOF V1 container. + """ + + @cached_property + def bytecode(self) -> bytes: + """ + Converts the EOF V1 Container into bytecode. + """ + if self.raw_bytes is not None: + assert len(self.sections) == 0 + return self.raw_bytes + + c = self.magic + self.version + + # Prepare auto-generated sections + sections = self.sections + + # Add type section if needed + if self.auto_type_section.any() and count_sections(sections, SectionKind.TYPE) == 0: + # Calculate skipping flags + types_header_size = 0 + type_section_data = b"" + for s in sections: + types_header_size += ( + len(s.type_definition) if not s.skip_types_header_listing else 0 + ) + type_section_data += s.type_definition if not s.skip_types_body_listing else b"" + + sections = [ + Section( + kind=SectionKind.TYPE, data=type_section_data, custom_size=types_header_size + ) + ] + sections + + # Add data section if needed + if self.auto_data_section and count_sections(sections, SectionKind.DATA) == 0: + sections = sections + [Section(kind=SectionKind.DATA, data="0x")] + + header_sections = [ + s + for s in sections + if s.kind != SectionKind.TYPE or self.auto_type_section != AutoSection.ONLY_BODY + ] + if self.auto_sort_sections.header(): + header_sections.sort(key=lambda x: x.kind) + + # Add headers + if header_sections: + # Join headers of the same kind in a list of lists, only if they are next to each other + concurrent_sections: List[List[Section]] = [[header_sections[0]]] + for s in header_sections[1:]: + if s.kind == concurrent_sections[-1][-1].kind: + concurrent_sections[-1].append(s) + else: + concurrent_sections.append([s]) + c += b"".join(Section.list_header(cs) for cs in concurrent_sections) + + # Add header terminator + c += self.header_terminator + + body_sections = sections[:] + if self.auto_sort_sections.body(): + # Sort sections for the body + body_sections.sort(key=lambda x: x.kind) + + # Add section bodies + for s in body_sections: + if s.kind == SectionKind.TYPE and self.auto_type_section == AutoSection.ONLY_HEADER: + continue + if s.data and not s.skip_body_listing: + c += s.data + + # Add extra (garbage) + c += self.extra + + return c + + @classmethod + def Code(cls, code: BytesConvertible = Bytecode(), **kwargs) -> "Container": # noqa: N802 + """ + Creates simple container with a single code section. + """ + kwargs.pop("kind", None) + return cls(sections=[Section.Code(code=code, **kwargs)]) + + def __bytes__(self) -> bytes: + """ + Returns the bytecode of the container. + """ + return self.bytecode + + def __len__(self) -> int: + """ + Returns the length of the container bytecode. + """ + return len(self.bytecode) + + +@dataclass(kw_only=True) +class Initcode(Bytecode): + """ + Helper class used to generate initcode for the specified deployment code, + using EOF V1 container as init code. + """ + + name: str = "EOF V1 Initcode" + """ + Name used to identify the initcode. + """ + deploy_container: Container + """ + Container to be deployed. + """ + + @cached_property + def init_container(self) -> Container: + """ + Generate a container that will be used as the initcode. + """ + return Container( + sections=[ + Section.Code( + code=Op.RETURNCONTRACT[0](0, 0), + max_stack_height=2, + ), + Section.Container( + container=self.deploy_container, + ), + ], + ) + + @cached_property + def bytecode(self) -> bytes: + """ + Generate an EOF container performs `EOFCREATE` with the specified code. + """ + initcode = Container( + sections=[ + Section.Code( + # TODO: Pass calldata + code=Op.EOFCREATE[0](0, 0, 0, 0) + Op.STOP(), + max_stack_height=4, + ), + Section.Container( + container=self.init_container, + ), + ] + ) + + return bytes(initcode) + + +def count_sections(sections: List[Section], kind: SectionKind | int) -> int: + """ + Counts sections from a list that match a specific kind + """ + return len([s for s in sections if s.kind == kind]) + + +OPCODE_MAP: Dict[int, Op] = {x.int(): x for x in Op} + + +def compute_code_stack_values(code: bytes) -> Tuple[int, int, int]: + """ + Computes the stack values for the given bytecode. + + TODO: THIS DOES NOT WORK WHEN THE RJUMP* JUMPS BACKWARDS (and many other + things). + """ + i = 0 + stack_height = 0 + min_stack_height = 0 + max_stack_height = 0 + + # compute type annotation + while i < len(code): + op = OPCODE_MAP.get(code[i]) + if op is None: + return (0, 0, 0) + elif op == Op.RJUMPV: + i += 1 + if i < len(code): + count = code[i] + i += count * 2 + else: + i += 1 + op.data_portion_length + + stack_height -= op.popped_stack_items + min_stack_height = min(stack_height, min_stack_height) + stack_height += op.pushed_stack_items + max_stack_height = max(stack_height, max_stack_height) + if stack_height < 0: + stack_height = 0 + return (abs(min_stack_height), stack_height, max_stack_height) diff --git a/src/ethereum_test_types/eof/v1/constants.py b/src/ethereum_test_types/eof/v1/constants.py new file mode 100644 index 0000000000..6fa8072523 --- /dev/null +++ b/src/ethereum_test_types/eof/v1/constants.py @@ -0,0 +1,39 @@ +""" +EVM Object Format generic constants. +Applicable to EOF version 1. +""" +from ..constants import VERSION_BYTE_LENGTH + +VERSION_NUMBER = 0x01 + +VERSION_NUMBER_BYTES = VERSION_NUMBER.to_bytes(VERSION_BYTE_LENGTH, "big") + +MAX_CODE_SECTIONS = 1024 + +MAX_RETURN_STACK_HEIGHT = 1024 + +MAX_OPERAND_STACK_HEIGHT = 1023 + +MAX_CODE_INPUTS = 127 + +MAX_CODE_OUTPUTS = 127 + +NON_RETURNING_SECTION = 0x80 + +MAX_RJUMPV_COUNT = 0xFF + +MAX_BYTECODE_SIZE = 24576 + +MAX_INITCODE_SIZE = MAX_BYTECODE_SIZE * 2 + +HEADER_SECTION_KIND_BYTE_LENGTH = 1 + +HEADER_SECTION_COUNT_BYTE_LENGTH = 2 + +HEADER_SECTION_SIZE_BYTE_LENGTH = 2 + +TYPES_INPUTS_BYTE_LENGTH = 1 + +TYPES_OUTPUTS_BYTE_LENGTH = 1 + +TYPES_STACK_BYTE_LENGTH = 2 diff --git a/src/ethereum_test_tools/common/helpers.py b/src/ethereum_test_types/helpers.py similarity index 96% rename from src/ethereum_test_tools/common/helpers.py rename to src/ethereum_test_types/helpers.py index 0cc9d3742f..e1cb67c90a 100644 --- a/src/ethereum_test_tools/common/helpers.py +++ b/src/ethereum_test_types/helpers.py @@ -8,8 +8,9 @@ from ethereum.crypto.hash import keccak256 from ethereum.rlp import encode -from .base_types import Address, Bytes, Hash -from .conversions import BytesConvertible, FixedSizeBytesConvertible +from ethereum_test_base_types.base_types import Address, Bytes, Hash +from ethereum_test_base_types.conversions import BytesConvertible, FixedSizeBytesConvertible + from .types import EOA """ diff --git a/src/ethereum_test_types/py.typed b/src/ethereum_test_types/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ethereum_test_types/tests/__init__.py b/src/ethereum_test_types/tests/__init__.py new file mode 100644 index 0000000000..14a7e04523 --- /dev/null +++ b/src/ethereum_test_types/tests/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for the ethereum_test_types package. +""" diff --git a/src/ethereum_test_tools/tests/test_eof_v1.py b/src/ethereum_test_types/tests/test_eof_v1.py similarity index 100% rename from src/ethereum_test_tools/tests/test_eof_v1.py rename to src/ethereum_test_types/tests/test_eof_v1.py diff --git a/src/ethereum_test_tools/tests/test_helpers.py b/src/ethereum_test_types/tests/test_helpers.py similarity index 97% rename from src/ethereum_test_tools/tests/test_helpers.py rename to src/ethereum_test_types/tests/test_helpers.py index bf65d4e81d..343ecdd747 100644 --- a/src/ethereum_test_tools/tests/test_helpers.py +++ b/src/ethereum_test_types/tests/test_helpers.py @@ -4,7 +4,9 @@ import pytest -from ..common import Address, compute_create2_address, compute_create_address +from ethereum_test_base_types import Address + +from ..helpers import compute_create2_address, compute_create_address def test_address(): diff --git a/src/ethereum_test_tools/tests/test_specs.py b/src/ethereum_test_types/tests/test_post_alloc.py similarity index 95% rename from src/ethereum_test_tools/tests/test_specs.py rename to src/ethereum_test_types/tests/test_post_alloc.py index 6f8a11315b..2145c67ff7 100644 --- a/src/ethereum_test_tools/tests/test_specs.py +++ b/src/ethereum_test_types/tests/test_post_alloc.py @@ -6,7 +6,8 @@ import pytest -from ..common import Account, Alloc +from ethereum_test_base_types import Account +from ethereum_test_types import Alloc @pytest.fixture() @@ -106,7 +107,7 @@ def test_verify_post_alloc( post: Alloc, alloc: Alloc, expected_exception_type: Type[Exception] | None ): """ - Test `verify_post_alloc` method of `ethereum_test_tools.spec.common.post`. + Test `verify_post_alloc` method of `Alloc`. """ if expected_exception_type is None: post.verify_post_alloc(alloc) diff --git a/src/ethereum_test_tools/tests/test_transactions.py b/src/ethereum_test_types/tests/test_transactions.py similarity index 99% rename from src/ethereum_test_tools/tests/test_transactions.py rename to src/ethereum_test_types/tests/test_transactions.py index 29eaa07597..d830e1fde5 100644 --- a/src/ethereum_test_tools/tests/test_transactions.py +++ b/src/ethereum_test_types/tests/test_transactions.py @@ -6,7 +6,7 @@ import pytest -from ..common import AccessList, Address, Transaction +from ..types import AccessList, Transaction @pytest.mark.parametrize( @@ -258,6 +258,6 @@ def test_transaction_signing( assert signature is not None assert signature == expected_signature - assert type(tx.sender) == Address + assert tx.sender is not None assert tx.sender.hex() == expected_sender assert ("0x" + tx.rlp.hex()) == expected_serialized diff --git a/src/ethereum_test_types/tests/test_types.py b/src/ethereum_test_types/tests/test_types.py new file mode 100644 index 0000000000..076d38c241 --- /dev/null +++ b/src/ethereum_test_types/tests/test_types.py @@ -0,0 +1,920 @@ +""" +Test suite for `ethereum_test` module. +""" + +from typing import Any, Dict, List + +import pytest +from pydantic import TypeAdapter + +from ethereum_test_base_types import Address, TestAddress, TestAddress2, TestPrivateKey, to_json +from ethereum_test_base_types.pydantic import CopyValidateModel +from ethereum_test_vm import Opcodes as Op + +from ..eof.v1 import Container +from ..types import ( + AccessList, + Account, + Alloc, + DepositRequest, + Environment, + Requests, + Storage, + Transaction, + Withdrawal, +) + + +def test_storage(): + """ + Test `ethereum_test.types.storage` parsing. + """ + s = Storage({"10": "0x10"}) + + assert 10 in s + assert s[10] == 16 + + s = Storage({"10": "10"}) + + assert 10 in s + assert s[10] == 10 + + s = Storage({10: 10}) + + assert 10 in s + assert s[10] == 10 + + iter_s = iter(Storage({10: 20, "11": "21"})) + assert next(iter_s) == 10 + assert next(iter_s) == 11 + + s["10"] = "0x10" + s["0x10"] = "10" + assert s[10] == 16 + assert s[16] == 10 + + assert "10" in s + assert "0xa" in s + assert 10 in s + + del s[10] + assert "10" not in s + assert "0xa" not in s + assert 10 not in s + + s = Storage({-1: -1, -2: -2}) + assert s[-1] == 2**256 - 1 + assert s[-2] == 2**256 - 2 + d = to_json(s) + assert ( + d["0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"] + == "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ) + assert ( + d["0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"] + == "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + ) + # Try to add a duplicate key (negative and positive number at the same + # time) + # same value, ok + s[2**256 - 1] = 2**256 - 1 + to_json(s) + + # Check store counter + s = Storage({}) + s.store_next(0x100) + s.store_next("0x200") + s.store_next(b"\x03\x00".rjust(32, b"\x00")) + d = to_json(s) + assert d == { + "0x00": ("0x0100"), + "0x01": ("0x0200"), + "0x02": ("0x0300"), + } + + +@pytest.mark.parametrize( + ["account"], + [ + pytest.param( + Account(), + id="no_fields", + ), + pytest.param( + Account( + nonce=0, + ), + id="zero_nonce", + ), + pytest.param( + Account( + balance=0, + ), + id="zero_balance", + ), + pytest.param( + Account( + code="", + ), + id="empty_code", + ), + pytest.param( + Account( + storage={}, + ), + id="empty_storage", + ), + pytest.param( + Account( + nonce=0, + balance=0, + code="", + storage={ + 1: 0, + }, + ), + id="only_zero_storage_values", + ), + ], +) +def test_empty_accounts(account: Account): + """ + Test `ethereum_test.types.account` parsing. + """ + assert not bool(account) + + +@pytest.mark.parametrize( + ["account", "alloc_dict", "should_pass"], + [ + # All None: Pass + ( + Account(), + {"nonce": "1", "code": "0x123", "balance": "1", "storage": {0: 1}}, + True, + ), + # Storage must be empty: Fail + ( + Account(storage={}), + {"nonce": "1", "code": "0x123", "balance": "1", "storage": {0: 1}}, + False, + ), + # Storage must be empty: Pass + ( + Account(storage={}), + {"nonce": "1", "code": "0x123", "balance": "1", "storage": {}}, + True, + ), + # Storage must be empty: Pass + ( + Account(storage={}), + { + "nonce": "1", + "code": "0x123", + "balance": "1", + "storage": {0: 0, 1: 0}, + }, + True, + ), + # Storage must be empty: Pass + ( + Account(storage={0: 0}), + { + "nonce": "1", + "code": "0x123", + "balance": "1", + "storage": {}, + }, + True, + ), + # Storage must not be empty: Pass + ( + Account(storage={1: 1}), + { + "nonce": "1", + "code": "0x123", + "balance": "1", + "storage": {0: 0, 1: 1}, + }, + True, + ), + # Storage must not be empty: Fail + ( + Account(storage={1: 1}), + { + "nonce": "1", + "code": "0x123", + "balance": "1", + "storage": {0: 0, 1: 1, 2: 2}, + }, + False, + ), + # Code must be empty: Fail + ( + Account(code=""), + { + "nonce": "0", + "code": "0x123", + "balance": "0", + "storage": {}, + }, + False, + ), + # Code must be empty: Pass + ( + Account(code=""), + { + "nonce": "1", + "code": "0x", + "balance": "1", + "storage": {0: 0, 1: 1}, + }, + True, + ), + # Nonce must be empty: Fail + ( + Account(nonce=0), + { + "nonce": "1", + "code": "0x", + "balance": "0", + "storage": {}, + }, + False, + ), + # Nonce must be empty: Pass + ( + Account(nonce=0), + { + "nonce": "0", + "code": "0x1234", + "balance": "1", + "storage": {0: 0, 1: 1}, + }, + True, + ), + # Nonce must not be empty: Fail + ( + Account(nonce=1), + { + "code": "0x1234", + "balance": "1", + "storage": {0: 0, 1: 1}, + }, + False, + ), + # Nonce must not be empty: Pass + ( + Account(nonce=1), + { + "nonce": "1", + "code": "0x", + "balance": "0", + "storage": {}, + }, + True, + ), + # Balance must be empty: Fail + ( + Account(balance=0), + { + "nonce": "0", + "code": "0x", + "balance": "1", + "storage": {}, + }, + False, + ), + # Balance must be empty: Pass + ( + Account(balance=0), + { + "nonce": "1", + "code": "0x1234", + "balance": "0", + "storage": {0: 0, 1: 1}, + }, + True, + ), + # Balance must not be empty: Fail + ( + Account(balance=1), + { + "nonce": "1", + "code": "0x1234", + "storage": {0: 0, 1: 1}, + }, + False, + ), + # Balance must not be empty: Pass + ( + Account(balance=1), + { + "nonce": "0", + "code": "0x", + "balance": "1", + "storage": {}, + }, + True, + ), + ], +) +def test_account_check_alloc(account: Account, alloc_dict: Dict[Any, Any], should_pass: bool): + """ + Test `Account.check_alloc` method. + """ + alloc_account = Account(**alloc_dict) + if should_pass: + account.check_alloc(Address(1), alloc_account) + else: + with pytest.raises(Exception) as _: + account.check_alloc(Address(1), alloc_account) + + +@pytest.mark.parametrize( + ["alloc_1", "alloc_2", "expected_alloc"], + [ + pytest.param( + Alloc(), + Alloc(), + Alloc(), + id="empty_alloc", + ), + pytest.param( + Alloc({0x1: {"nonce": 1}}), # type: ignore + Alloc({0x2: {"nonce": 2}}), # type: ignore + Alloc({0x1: Account(nonce=1), 0x2: Account(nonce=2)}), # type: ignore + id="alloc_different_accounts", + ), + pytest.param( + Alloc({0x2: {"nonce": 1}}), # type: ignore + Alloc({"0x02": {"nonce": 2}}), # type: ignore + Alloc({0x2: Account(nonce=2)}), # type: ignore + id="overwrite_account", + ), + pytest.param( + Alloc({0x2: {"balance": 1}}), # type: ignore + Alloc({"0x02": {"nonce": 1}}), # type: ignore + Alloc({0x2: Account(balance=1, nonce=1)}), # type: ignore + id="mix_account", + ), + ], +) +def test_alloc_append(alloc_1: Alloc, alloc_2: Alloc, expected_alloc: Alloc): + """ + Test `ethereum_test.types.alloc` merging. + """ + assert Alloc.merge(alloc_1, alloc_2) == expected_alloc + + +def test_alloc_deploy_contract(): + """ + Test `Alloc.deploy_contract` functionallity. + """ + alloc = Alloc() + contract_1 = alloc.deploy_contract(Op.SSTORE(0, 1) + Op.STOP) + contract_2 = alloc.deploy_contract(Op.SSTORE(0, 2) + Op.STOP) + assert contract_1 != contract_2 + assert contract_1 in alloc + assert contract_2 in alloc + assert alloc[contract_1].code == bytes.fromhex("600160005500") + assert alloc[contract_2].code == bytes.fromhex("600260005500") + + +def test_alloc_fund_sender(): + """ + Test `Alloc.fund_eoa` functionallity. + """ + alloc = Alloc() + sender_1 = alloc.fund_eoa(10**18) + sender_2 = alloc.fund_eoa(10**18) + assert sender_1 != sender_2 + assert sender_1 in alloc + assert sender_2 in alloc + assert Address(sender_1) == TestAddress + assert Address(sender_2) == TestAddress2 + assert alloc[sender_1].balance == 10**18 + assert alloc[sender_2].balance == 10**18 + + +@pytest.mark.parametrize( + ["account_1", "account_2", "expected_account"], + [ + pytest.param( + Account(), + Account(), + Account(), + id="empty_accounts", + ), + pytest.param( + None, + None, + Account(), + id="none_accounts", + ), + pytest.param( + Account(nonce=1), + Account(code="0x6000"), + Account(nonce=1, code="0x6000"), + id="accounts_with_different_fields", + ), + pytest.param( + Account(nonce=1), + Account(nonce=2), + Account(nonce=2), + id="accounts_with_different_nonce", + ), + ], +) +def test_account_merge( + account_1: Account | None, account_2: Account | None, expected_account: Account +): + """ + Test `ethereum_test.types.account` merging. + """ + assert Account.merge(account_1, account_2) == expected_account + + +CHECKSUM_ADDRESS = "0x8a0A19589531694250d570040a0c4B74576919B8" + + +@pytest.mark.parametrize( + ["can_be_deserialized", "model_instance", "json"], + [ + pytest.param( + True, + Address(CHECKSUM_ADDRESS), + CHECKSUM_ADDRESS, + marks=pytest.mark.xfail, + id="address_with_checksum_address", + ), + pytest.param( + True, + Account(), + { + "nonce": "0x00", + "balance": "0x00", + "code": "0x", + "storage": {}, + }, + id="account_1", + ), + pytest.param( + True, + Account( + nonce=1, + balance=2, + code="0x1234", + storage={ + 0: 0, + 1: 1, + }, + ), + { + "nonce": "0x01", + "balance": "0x02", + "code": "0x1234", + "storage": { + "0x00": "0x00", + "0x01": "0x01", + }, + }, + id="account_2", + ), + pytest.param( + True, + AccessList( + address=0x1234, + storage_keys=[0, 1], + ), + { + "address": "0x0000000000000000000000000000000000001234", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001", + ], + }, + id="access_list", + ), + pytest.param( + True, + Withdrawal(index=0, validator_index=1, address=0x1234, amount=2), + { + "index": "0x0", + "validatorIndex": "0x1", + "address": "0x0000000000000000000000000000000000001234", + "amount": "0x2", + }, + id="withdrawal", + ), + pytest.param( + True, + Environment(), + { + "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentGasLimit": "100000000000000000", + "currentNumber": "1", + "currentTimestamp": "1000", + "blockHashes": {}, + "ommers": [], + "parentUncleHash": ( + "0x0000000000000000000000000000000000000000000000000000000000000000" + ), + }, + id="environment_1", + ), + pytest.param( + True, + Environment( + fee_recipient=0x1234, + difficulty=0x5, + prev_randao=0x6, + base_fee_per_gas=0x7, + parent_difficulty=0x8, + parent_timestamp=0x9, + parent_base_fee_per_gas=0xA, + parent_gas_used=0xB, + parent_gas_limit=0xC, + parent_ommers_hash=0xD, + withdrawals=[Withdrawal(index=0, validator_index=1, address=0x1234, amount=2)], + parent_blob_gas_used=0xE, + parent_excess_blob_gas=0xF, + blob_gas_used=0x10, + excess_blob_gas=0x11, + block_hashes={1: 2, 3: 4}, + ), + { + "currentCoinbase": "0x0000000000000000000000000000000000001234", + "currentGasLimit": "100000000000000000", + "currentNumber": "1", + "currentTimestamp": "1000", + "currentDifficulty": "5", + "currentRandom": "6", + "currentBaseFee": "7", + "parentDifficulty": "8", + "parentTimestamp": "9", + "parentBaseFee": "10", + "parentGasUsed": "11", + "parentGasLimit": "12", + "parentUncleHash": ( + "0x000000000000000000000000000000000000000000000000000000000000000d" + ), + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x1", + "address": "0x0000000000000000000000000000000000001234", + "amount": "0x2", + }, + ], + "parentBlobGasUsed": "14", + "parentExcessBlobGas": "15", + "currentBlobGasUsed": "16", + "currentExcessBlobGas": "17", + "blockHashes": { + "1": "0x0000000000000000000000000000000000000000000000000000000000000002", + "3": "0x0000000000000000000000000000000000000000000000000000000000000004", + }, + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000004", + "ommers": [], + }, + id="environment_2", + ), + pytest.param( + True, + Transaction().with_signature_and_sender(), + { + "type": "0x0", + "chainId": "0x1", + "nonce": "0x0", + "to": "0x00000000000000000000000000000000000000aa", + "value": "0x0", + "input": "0x", + "gas": "0x5208", + "gasPrice": "0xa", + "v": "0x26", + "r": "0xcc61d852649c34cc0b71803115f38036ace257d2914f087bf885e6806a664fbd", + "s": "0x2020cb35f5d7731ab540d62614503a7f2344301a86342f67daf011c1341551ff", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + }, + id="transaction_t8n_default_args", + ), + pytest.param( + True, + Transaction( + to=None, + ).with_signature_and_sender(), + { + "type": "0x0", + "chainId": "0x1", + "nonce": "0x0", + "to": None, + "value": "0x0", + "input": "0x", + "gas": "0x5208", + "gasPrice": "0xa", + "v": "0x25", + "r": "0x1cfe2cbb0c3577f74d9ae192a7f1ee2d670fe806a040f427af9cb768be3d07ce", + "s": "0xcbe2d029f52dbf93ade486625bed0603945d2c7358b31de99fe8786c00f13da", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + }, + id="transaction_t8n_to_none", + ), + pytest.param( + True, + Transaction( + to=0x1234, + data=b"\x01\x00", + access_list=[ + AccessList( + address=0x1234, + storage_keys=[0, 1], + ) + ], + max_priority_fee_per_gas=10, + max_fee_per_gas=20, + max_fee_per_blob_gas=30, + blob_versioned_hashes=[0, 1], + ).with_signature_and_sender(), + { + "type": "0x3", + "chainId": "0x1", + "nonce": "0x0", + "to": "0x0000000000000000000000000000000000001234", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000001234", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001", + ], + } + ], + "value": "0x0", + "input": "0x0100", + "gas": "0x5208", + "maxPriorityFeePerGas": "0xa", + "maxFeePerGas": "0x14", + "maxFeePerBlobGas": "0x1e", + "blobVersionedHashes": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001", + ], + "v": "0x0", + "r": "0x418bb557c43262375f80556cb09dac5e67396acf0eaaf2c2540523d1ce54b280", + "s": "0x4fa36090ea68a1138043d943ced123c0b0807d82ff3342a6977cbc09230e927c", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + }, + id="transaction_3", + ), + ], +) +class TestPydanticModelConversion: + """ + Test that Pydantic models are converted to and from JSON correctly. + """ + + def test_json_serialization( + self, can_be_deserialized: bool, model_instance: Any, json: str | Dict[str, Any] + ): + """ + Test that to_json returns the expected JSON for the given object. + """ + assert to_json(model_instance) == json + + def test_json_deserialization( + self, can_be_deserialized: bool, model_instance: Any, json: str | Dict[str, Any] + ): + """ + Test that to_json returns the expected JSON for the given object. + """ + if not can_be_deserialized: + pytest.skip(reason="The model instance in this case can not be deserialized") + model_type = type(model_instance) + assert model_type(**json) == model_instance + + +@pytest.mark.parametrize( + ["invalid_tx_args", "expected_exception", "expected_exception_substring"], + [ + pytest.param( + {"gas_price": 1, "max_fee_per_gas": 2}, + Transaction.InvalidFeePayment, + "only one type of fee payment field can be used", + id="gas-price-and-max-fee-per-gas", + ), + pytest.param( + {"gas_price": 1, "max_priority_fee_per_gas": 2}, + Transaction.InvalidFeePayment, + "only one type of fee payment field can be used", + id="gas-price-and-max-priority-fee-per-gas", + ), + pytest.param( + {"gas_price": 1, "max_fee_per_blob_gas": 2}, + Transaction.InvalidFeePayment, + "only one type of fee payment field can be used", + id="gas-price-and-max-fee-per-blob-gas", + ), + pytest.param( + {"ty": 0, "v": 1, "secret_key": 2}, + Transaction.InvalidSignaturePrivateKey, + "can't define both 'signature' and 'private_key'", + id="type0-signature-and-secret-key", + ), + ], +) +def test_transaction_post_init_invalid_arg_combinations( # noqa: D103 + invalid_tx_args, expected_exception, expected_exception_substring +): + """ + Test that Transaction.__post_init__ raises the expected exceptions for + invalid constructor argument combinations. + """ + with pytest.raises(expected_exception) as exc_info: + Transaction(**invalid_tx_args) + assert expected_exception_substring in str(exc_info.value) + + +@pytest.mark.parametrize( + ["tx_args", "expected_attributes_and_values"], + [ + pytest.param( + {"max_fee_per_blob_gas": 10}, + [ + ("ty", 3), + ], + id="max_fee_per_blob_gas-adds-ty-3", + ), + pytest.param( + {}, + [ + ("gas_price", 10), + ], + id="no-fees-adds-gas_price", + ), + pytest.param( + {}, + [ + ("secret_key", TestPrivateKey), + ], + id="no-signature-adds-secret_key", + ), + pytest.param( + {"max_fee_per_gas": 10}, + [ + ("ty", 2), + ], + id="max_fee_per_gas-adds-ty-2", + ), + pytest.param( + {"access_list": [AccessList(address=0x1234, storage_keys=[0, 1])]}, + [ + ("ty", 1), + ], + id="access_list-adds-ty-1", + ), + pytest.param( + {"ty": 1}, + [ + ("access_list", []), + ], + id="ty-1-adds-empty-access_list", + ), + pytest.param( + {"ty": 2}, + [ + ("max_priority_fee_per_gas", 0), + ], + id="ty-2-adds-max_priority_fee_per_gas", + ), + ], +) +def test_transaction_post_init_defaults(tx_args, expected_attributes_and_values): + """ + Test that Transaction.__post_init__ sets the expected default values for + missing fields. + """ + tx = Transaction(**tx_args) + for attr, val in expected_attributes_and_values: + assert hasattr(tx, attr) + assert getattr(tx, attr) == val + + +@pytest.mark.parametrize( + ["withdrawals", "expected_root"], + [ + pytest.param( + [], + bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + id="empty-withdrawals", + ), + pytest.param( + [ + Withdrawal( + index=0, + validator_index=1, + address=0x1234, + amount=2, + ) + ], + bytes.fromhex("dc3ead883fc17ea3802cd0f8e362566b07b223f82e52f94c76cf420444b8ff81"), + id="single-withdrawal", + ), + pytest.param( + [ + Withdrawal( + index=0, + validator_index=1, + address=0x1234, + amount=2, + ), + Withdrawal( + index=1, + validator_index=2, + address=0xABCD, + amount=0, + ), + ], + bytes.fromhex("069ab71e5d228db9b916880f02670c85682c46641bb9c95df84acc5075669e01"), + id="multiple-withdrawals", + ), + pytest.param( + [ + Withdrawal( + index=0, + validator_index=0, + address=0x100, + amount=0, + ), + Withdrawal( + index=0, + validator_index=0, + address=0x200, + amount=0, + ), + ], + bytes.fromhex("daacd8fe889693f7d20436d9c0c044b5e92cc17b57e379997273fc67fd2eb7b8"), + id="multiple-withdrawals", + ), + ], +) +def test_withdrawals_root(withdrawals: List[Withdrawal], expected_root: bytes): + """ + Test that withdrawals_root returns the expected hash. + """ + assert Withdrawal.list_root(withdrawals) == expected_root + + +@pytest.mark.parametrize( + ["json_str", "type_adapter", "expected"], + [ + pytest.param( + """ + [ + { + "type": "0x0", + "pubkey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "withdrawalCredentials": "0x0000000000000000000000000000000000000000000000000000000000000002", + "amount": "0x1234", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", + "index": "0x5678" + } + ] + """, # noqa: E501 + TypeAdapter(Requests), + Requests( + root=[ + DepositRequest( + pubkey=1, + withdrawal_credentials=2, + amount=0x1234, + signature=3, + index=0x5678, + ), + ] + ), + id="requests_1", + ), + ], +) +def test_parsing(json_str: str, type_adapter: TypeAdapter, expected: Any): + """ + Test that parsing the given JSON string returns the expected object. + """ + assert type_adapter.validate_json(json_str) == expected + + +@pytest.mark.parametrize( + "model", + [ + Environment(), + Container(), + ], + ids=lambda model: model.__class__.__name__, +) +def test_model_copy(model: CopyValidateModel): + """ + Test that the copy method returns a correct copy of the model. + """ + assert to_json(model.copy()) == to_json(model) + assert model.copy().model_fields_set == model.model_fields_set diff --git a/src/ethereum_test_tools/common/types.py b/src/ethereum_test_types/types.py similarity index 68% rename from src/ethereum_test_tools/common/types.py rename to src/ethereum_test_types/types.py index c26df8cfa0..30388a2d79 100644 --- a/src/ethereum_test_tools/common/types.py +++ b/src/ethereum_test_types/types.py @@ -7,19 +7,7 @@ from enum import IntEnum from functools import cache, cached_property from itertools import count -from typing import ( - Any, - ClassVar, - Dict, - Generic, - Iterator, - List, - Sequence, - SupportsBytes, - Type, - TypeAlias, - TypeVar, -) +from typing import Any, Dict, Generic, Iterator, List, Sequence from coincurve.keys import PrivateKey, PublicKey from ethereum import rlp as eth_rlp @@ -34,32 +22,37 @@ Field, PrivateAttr, RootModel, - TypeAdapter, computed_field, model_serializer, model_validator, ) -from pydantic.alias_generators import to_camel from trie import HexaryTrie -from ethereum_test_forks import Fork - -from ..exceptions import TransactionException -from .base_types import ( - Address, - Bloom, +from ethereum_test_base_types import Account, Address +from ethereum_test_base_types import Alloc as BaseAlloc +from ethereum_test_base_types import ( BLSPublicKey, BLSSignature, Bytes, + CamelModel, Hash, - HashInt, HexNumber, Number, NumberBoundTypeVar, + Storage, + StorageRootType, + TestAddress, + TestPrivateKey, + TestPrivateKey2, ZeroPaddedHexNumber, ) -from .constants import TestAddress, TestPrivateKey, TestPrivateKey2 -from .conversions import BytesConvertible, FixedSizeBytesConvertible, NumberConvertible +from ethereum_test_base_types.conversions import ( + BytesConvertible, + FixedSizeBytesConvertible, + NumberConvertible, +) +from ethereum_test_exceptions import TransactionException +from ethereum_test_forks import Fork # Sentinel classes @@ -72,445 +65,6 @@ class Removable: pass -# Base Models - -Model = TypeVar("Model", bound=BaseModel) - - -class CopyValidateModel(BaseModel): - """ - Base model for Ethereum tests. - """ - - def copy(self: Model, **kwargs) -> Model: - """ - Creates a copy of the model with the updated fields that are validated. - """ - return self.__class__(**(self.model_dump(exclude_unset=True) | kwargs)) - - -class CamelModel(CopyValidateModel): - """ - A base model that converts field names to camel case when serializing. - - For example, the field name `current_timestamp` in a Python model will be represented - as `currentTimestamp` when it is serialized to json. - """ - - model_config = ConfigDict( - alias_generator=to_camel, - populate_by_name=True, - validate_default=True, - ) - - -StorageKeyValueTypeConvertible = NumberConvertible -StorageKeyValueType = HashInt -StorageKeyValueTypeAdapter = TypeAdapter(StorageKeyValueType) - - -class Storage(RootModel[Dict[StorageKeyValueType, StorageKeyValueType]]): - """ - Definition of a storage in pre or post state of a test - """ - - root: Dict[StorageKeyValueType, StorageKeyValueType] = Field(default_factory=dict) - - _current_slot: Iterator[int] = count(0) - - StorageDictType: ClassVar[TypeAlias] = Dict[ - str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes - ] - """ - Dictionary type to be used when defining an input to initialize a storage. - """ - - @dataclass(kw_only=True) - class InvalidType(Exception): - """ - Invalid type used when describing test's expected storage key or value. - """ - - key_or_value: Any - - def __init__(self, key_or_value: Any, *args): - super().__init__(args) - self.key_or_value = key_or_value - - def __str__(self): - """Print exception string""" - return f"invalid type for key/value: {self.key_or_value}" - - @dataclass(kw_only=True) - class InvalidValue(Exception): - """ - Invalid value used when describing test's expected storage key or - value. - """ - - key_or_value: Any - - def __init__(self, key_or_value: Any, *args): - super().__init__(args) - self.key_or_value = key_or_value - - def __str__(self): - """Print exception string""" - return f"invalid value for key/value: {self.key_or_value}" - - @dataclass(kw_only=True) - class MissingKey(Exception): - """ - Test expected to find a storage key set but key was missing. - """ - - key: int - - def __init__(self, key: int, *args): - super().__init__(args) - self.key = key - - def __str__(self): - """Print exception string""" - return "key {0} not found in storage".format(Hash(self.key)) - - @dataclass(kw_only=True) - class KeyValueMismatch(Exception): - """ - Test expected a certain value in a storage key but value found - was different. - """ - - address: Address - key: int - want: int - got: int - - def __init__(self, address: Address, key: int, want: int, got: int, *args): - super().__init__(args) - self.address = address - self.key = key - self.want = want - self.got = got - - def __str__(self): - """Print exception string""" - label_str = "" - if self.address.label is not None: - label_str = f" ({self.address.label})" - return ( - f"incorrect value in address {self.address}{label_str} for " - + f"key {Hash(self.key)}:" - + f" want {HexNumber(self.want)} (dec:{self.want})," - + f" got {HexNumber(self.got)} (dec:{self.got})" - ) - - def __contains__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType) -> bool: - """Checks for an item in the storage""" - return StorageKeyValueTypeAdapter.validate_python(key) in self.root - - def __getitem__( - self, key: StorageKeyValueTypeConvertible | StorageKeyValueType - ) -> StorageKeyValueType: - """Returns an item from the storage""" - return self.root[StorageKeyValueTypeAdapter.validate_python(key)] - - def __setitem__( - self, - key: StorageKeyValueTypeConvertible | StorageKeyValueType, - value: StorageKeyValueTypeConvertible | StorageKeyValueType, - ): # noqa: SC200 - """Sets an item in the storage""" - self.root[ - StorageKeyValueTypeAdapter.validate_python(key) - ] = StorageKeyValueTypeAdapter.validate_python(value) - - def __delitem__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType): - """Deletes an item from the storage""" - del self.root[StorageKeyValueTypeAdapter.validate_python(key)] - - def __iter__(self): - """Returns an iterator over the storage""" - return iter(self.root) - - def __eq__(self, other) -> bool: - """ - Returns True if both storages are equal. - """ - if not isinstance(other, Storage): - return False - return self.root == other.root - - def __ne__(self, other) -> bool: - """ - Returns True if both storages are not equal. - """ - if not isinstance(other, Storage): - return False - return self.root != other.root - - def __bool__(self) -> bool: - """Returns True if the storage is not empty""" - return any(v for v in self.root.values()) - - def keys(self) -> set[StorageKeyValueType]: - """Returns the keys of the storage""" - return set(self.root.keys()) - - def store_next( - self, value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool - ) -> StorageKeyValueType: - """ - Stores a value in the storage and returns the key where the value is stored. - - Increments the key counter so the next time this function is called, - the next key is used. - """ - slot = StorageKeyValueTypeAdapter.validate_python(next(self._current_slot)) - self[slot] = StorageKeyValueTypeAdapter.validate_python(value) - return slot - - def contains(self, other: "Storage") -> bool: - """ - Returns True if self contains all keys with equal value as - contained by second storage. - Used for comparison with test expected post state and alloc returned - by the transition tool. - """ - for key in other.keys(): - if key not in self: - return False - if self[key] != other[key]: - return False - return True - - def must_contain(self, address: Address, other: "Storage"): - """ - Succeeds only if self contains all keys with equal value as - contained by second storage. - Used for comparison with test expected post state and alloc returned - by the transition tool. - Raises detailed exception when a difference is found. - """ - for key in other.keys(): - if key not in self: - # storage[key]==0 is equal to missing storage - if other[key] != 0: - raise Storage.MissingKey(key=key) - elif self[key] != other[key]: - raise Storage.KeyValueMismatch( - address=address, key=key, want=self[key], got=other[key] - ) - - def must_be_equal(self, address: Address, other: "Storage | None"): - """ - Succeeds only if "self" is equal to "other" storage. - """ - # Test keys contained in both storage objects - if other is None: - other = Storage({}) - for key in self.keys() & other.keys(): - if self[key] != other[key]: - raise Storage.KeyValueMismatch( - address=address, key=key, want=self[key], got=other[key] - ) - - # Test keys contained in either one of the storage objects - for key in self.keys() ^ other.keys(): - if key in self: - if self[key] != 0: - raise Storage.KeyValueMismatch(address=address, key=key, want=self[key], got=0) - - elif other[key] != 0: - raise Storage.KeyValueMismatch(address=address, key=key, want=0, got=other[key]) - - def canary(self) -> "Storage": - """ - Returns a canary storage filled with non-zero values where the current storage expects - zero values, to guarantee that the test overwrites the storage. - """ - return Storage({key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0}) - - -class Account(CopyValidateModel): - """ - State associated with an address. - """ - - nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) - """ - The scalar value equal to a) the number of transactions sent by - an Externally Owned Account, b) the amount of contracts created by a - contract. - """ - balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) - """ - The amount of Wei (10-18 Eth) the account has. - """ - code: Bytes = Bytes(b"") - """ - Bytecode contained by the account. - """ - storage: Storage = Field(default_factory=Storage) - """ - Storage within a contract. - """ - - NONEXISTENT: ClassVar[None] = None - """ - Sentinel object used to specify when an account should not exist in the - state. - """ - - @dataclass(kw_only=True) - class NonceMismatch(Exception): - """ - Test expected a certain nonce value for an account but a different - value was found. - """ - - address: Address - want: int | None - got: int | None - - def __init__(self, address: Address, want: int | None, got: int | None, *args): - super().__init__(args) - self.address = address - self.want = want - self.got = got - - def __str__(self): - """Print exception string""" - label_str = "" - if self.address.label is not None: - label_str = f" ({self.address.label})" - return ( - f"unexpected nonce for account {self.address}{label_str}: " - + f"want {self.want}, got {self.got}" - ) - - @dataclass(kw_only=True) - class BalanceMismatch(Exception): - """ - Test expected a certain balance for an account but a different - value was found. - """ - - address: Address - want: int | None - got: int | None - - def __init__(self, address: Address, want: int | None, got: int | None, *args): - super().__init__(args) - self.address = address - self.want = want - self.got = got - - def __str__(self): - """Print exception string""" - label_str = "" - if self.address.label is not None: - label_str = f" ({self.address.label})" - return ( - f"unexpected balance for account {self.address}{label_str}: " - + f"want {self.want}, got {self.got}" - ) - - @dataclass(kw_only=True) - class CodeMismatch(Exception): - """ - Test expected a certain bytecode for an account but a different - one was found. - """ - - address: Address - want: bytes | None - got: bytes | None - - def __init__(self, address: Address, want: bytes | None, got: bytes | None, *args): - super().__init__(args) - self.address = address - self.want = want - self.got = got - - def __str__(self): - """Print exception string""" - label_str = "" - if self.address.label is not None: - label_str = f" ({self.address.label})" - return ( - f"unexpected code for account {self.address}{label_str}: " - + f"want {self.want}, got {self.got}" - ) - - def check_alloc(self: "Account", address: Address, account: "Account"): - """ - Checks the returned alloc against an expected account in post state. - Raises exception on failure. - """ - if "nonce" in self.model_fields_set: - if self.nonce != account.nonce: - raise Account.NonceMismatch( - address=address, - want=self.nonce, - got=account.nonce, - ) - - if "balance" in self.model_fields_set: - if self.balance != account.balance: - raise Account.BalanceMismatch( - address=address, - want=self.balance, - got=account.balance, - ) - - if "code" in self.model_fields_set: - if self.code != account.code: - raise Account.CodeMismatch( - address=address, - want=self.code, - got=account.code, - ) - - if "storage" in self.model_fields_set: - self.storage.must_be_equal(address=address, other=account.storage) - - def __bool__(self: "Account") -> bool: - """ - Returns True on a non-empty account. - """ - return any((self.nonce, self.balance, self.code, self.storage)) - - @classmethod - def with_code(cls: Type, code: BytesConvertible) -> "Account": - """ - Create account with provided `code` and nonce of `1`. - """ - return Account(nonce=HexNumber(1), code=Bytes(code)) - - @classmethod - def merge( - cls: Type, account_1: "Dict | Account | None", account_2: "Dict | Account | None" - ) -> "Account": - """ - Create a merged account from two sources. - """ - - def to_kwargs_dict(account: "Dict | Account | None") -> Dict: - if account is None: - return {} - if isinstance(account, dict): - return account - elif isinstance(account, cls): - return account.model_dump(exclude_unset=True) - raise TypeError(f"Unexpected type for account merge: {type(account)}") - - kwargs = to_kwargs_dict(account_1) - kwargs.update(to_kwargs_dict(account_2)) - - return cls(**kwargs) - - class EOA(Address): """ An Externally Owned Account (EOA) is an account controlled by a private key. @@ -592,13 +146,11 @@ class AllocMode(IntEnum): STRICT = 1 -class Alloc(RootModel[Dict[Address, Account | None]]): +class Alloc(BaseAlloc): """ Allocation of accounts in the state, pre and post test execution. """ - root: Dict[Address, Account | None] = Field(default_factory=dict, validate_default=True) - _alloc_mode: AllocMode = PrivateAttr(default=AllocMode.PERMISSIVE) _contract_address_iterator: Iterator[Address] = PrivateAttr( default_factory=contract_address_iterator @@ -758,8 +310,7 @@ def deploy_contract( self, code: BytesConvertible, *, - storage: Storage - | Dict[StorageKeyValueTypeConvertible, StorageKeyValueTypeConvertible] = {}, + storage: Storage | StorageRootType = {}, balance: NumberConvertible = 0, nonce: NumberConvertible = 1, address: Address | None = None, @@ -1584,87 +1135,3 @@ def withdrawal_requests(self) -> List[WithdrawalRequest]: Returns the list of withdrawal requests. """ return [w for w in self.root if isinstance(w, WithdrawalRequest)] - - -# TODO: Move to other file -# Transition tool models - - -class TransactionLog(CamelModel): - """ - Transaction log - """ - - address: Address - topics: List[Hash] - data: Bytes - block_number: HexNumber - transaction_hash: Hash - transaction_index: HexNumber - block_hash: Hash - log_index: HexNumber - removed: bool - - -class TransactionReceipt(CamelModel): - """ - Transaction receipt - """ - - transaction_hash: Hash - gas_used: HexNumber - root: Bytes | None = None - status: HexNumber | None = None - cumulative_gas_used: HexNumber | None = None - logs_bloom: Bloom | None = None - logs: List[TransactionLog] | None = None - contract_address: Address | None = None - effective_gas_price: HexNumber | None = None - block_hash: Hash | None = None - transaction_index: HexNumber | None = None - blob_gas_used: HexNumber | None = None - blob_gas_price: HexNumber | None = None - - -class RejectedTransaction(CamelModel): - """ - Rejected transaction - """ - - index: HexNumber - error: str - - -class Result(CamelModel): - """ - Result of a t8n - """ - - state_root: Hash - ommers_hash: Hash | None = Field(None, validation_alias="sha3Uncles") - transactions_trie: Hash = Field(..., alias="txRoot") - receipts_root: Hash - logs_hash: Hash - logs_bloom: Bloom - receipts: List[TransactionReceipt] - rejected_transactions: List[RejectedTransaction] = Field( - default_factory=list, alias="rejected" - ) - difficulty: HexNumber | None = Field(None, alias="currentDifficulty") - gas_used: HexNumber - base_fee_per_gas: HexNumber | None = Field(None, alias="currentBaseFee") - withdrawals_root: Hash | None = None - excess_blob_gas: HexNumber | None = Field(None, alias="currentExcessBlobGas") - blob_gas_used: HexNumber | None = None - requests_root: Hash | None = None - deposit_requests: List[DepositRequest] | None = None - withdrawal_requests: List[WithdrawalRequest] | None = None - - -class TransitionToolOutput(CamelModel): - """ - Transition tool output - """ - - alloc: Alloc - result: Result diff --git a/src/ethereum_test_vm/__init__.py b/src/ethereum_test_vm/__init__.py new file mode 100644 index 0000000000..58b4640b5b --- /dev/null +++ b/src/ethereum_test_vm/__init__.py @@ -0,0 +1,16 @@ +""" +Ethereum Virtual Machine related definitions and utilities. +""" + +from .bytecode import Bytecode +from .opcode import Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes + +__all__ = ( + "Bytecode", + "Opcode", + "Macro", + "Macros", + "OpcodeCallArg", + "Opcodes", + "UndefinedOpcodes", +) diff --git a/src/ethereum_test_tools/vm/bytecode.py b/src/ethereum_test_vm/bytecode.py similarity index 100% rename from src/ethereum_test_tools/vm/bytecode.py rename to src/ethereum_test_vm/bytecode.py diff --git a/src/ethereum_test_vm/opcode.py b/src/ethereum_test_vm/opcode.py new file mode 100644 index 0000000000..1b44b46c40 --- /dev/null +++ b/src/ethereum_test_vm/opcode.py @@ -0,0 +1,5888 @@ +""" +Ethereum Virtual Machine opcode definitions. + +Acknowledgments: The individual opcode documentation below is due to the work by +[smlXL](https://github.com/smlxl) on [evm.codes](https://www.evm.codes/), available as open +source [github.com/smlxl/evm.codes](https://github.com/smlxl/evm.codes) - thank you! And thanks +to @ThreeHrSleep for integrating it in the docstrings. +""" + +from enum import Enum +from typing import Any, Callable, Iterable, List, Mapping, Optional, SupportsBytes + +from ethereum_test_base_types import to_bytes + +from .bytecode import Bytecode + + +def _get_int_size(n: int) -> int: + """ + Returns the size of an integer in bytes. + """ + if n < 0: + # Negative numbers in the EVM are represented as two's complement of 32 bytes + return 32 + byte_count = 0 + while n: + byte_count += 1 + n >>= 8 + return byte_count + + +KW_ARGS_DEFAULTS_TYPE = Mapping[str, "int | bytes | str | Opcode | Bytecode"] + + +def _stack_argument_to_bytecode( + arg: "int | bytes | str | Opcode | Bytecode | Iterable[int]", +) -> Bytecode: + """ + Converts a stack argument in an opcode or macro to bytecode. + """ + if isinstance(arg, Bytecode): + return arg + + # We are going to push a constant to the stack. + data_size = 0 + if isinstance(arg, int): + signed = arg < 0 + data_size = _get_int_size(arg) + if data_size > 32: + raise ValueError("Opcode stack data must be less than 32 bytes") + elif data_size == 0: + # Pushing 0 is done with the PUSH1 opcode for compatibility reasons. + data_size = 1 + arg = arg.to_bytes( + length=data_size, + byteorder="big", + signed=signed, + ) + else: + arg = to_bytes(arg).lstrip(b"\0") # type: ignore + if arg == b"": + # Pushing 0 is done with the PUSH1 opcode for compatibility reasons. + arg = b"\x00" + data_size = len(arg) + + assert isinstance(arg, bytes) + assert data_size > 0 + new_opcode = _push_opcodes_byte_list[data_size - 1][arg] + return new_opcode + + +class Opcode(Bytecode): + """ + Represents a single Opcode instruction in the EVM, with extra metadata useful to parametrize + tests. + + Parameters + ---------- + - data_portion_length: number of bytes after the opcode in the bytecode + that represent data + - data_portion_formatter: function to format the data portion of the opcode, if any + - stack_properties_modifier: function to modify the stack properties of the opcode after the + data portion has been processed + - kwargs: list of keyword arguments that can be passed to the opcode, in the order they are + meant to be placed in the stack + - kwargs_defaults: default values for the keyword arguments if any, otherwise 0 + - unchecked_stack: whether the bytecode should ignore stack checks when being called + """ + + data_portion_length: int + data_portion_formatter: Optional[Callable[[Any], bytes]] + stack_properties_modifier: Optional[Callable[[Any], tuple[int, int, int, int]]] + kwargs: List[str] | None + kwargs_defaults: KW_ARGS_DEFAULTS_TYPE + unchecked_stack: bool = False + + def __new__( + cls, + opcode_or_byte: "int | bytes | Opcode", + *, + popped_stack_items: int = 0, + pushed_stack_items: int = 0, + max_stack_height: int | None = None, + min_stack_height: int | None = None, + data_portion_length: int = 0, + data_portion_formatter=None, + stack_properties_modifier=None, + unchecked_stack=False, + kwargs: List[str] | None = None, + kwargs_defaults: KW_ARGS_DEFAULTS_TYPE = {}, + ): + """ + Creates a new opcode instance. + """ + if type(opcode_or_byte) is Opcode: + # Required because Enum class calls the base class with the instantiated object as + # parameter. + return opcode_or_byte + elif isinstance(opcode_or_byte, int) or isinstance(opcode_or_byte, bytes): + + obj_bytes = ( + bytes([opcode_or_byte]) if isinstance(opcode_or_byte, int) else opcode_or_byte + ) + if min_stack_height is None: + min_stack_height = popped_stack_items + if max_stack_height is None: + max_stack_height = max( + min_stack_height - popped_stack_items + pushed_stack_items, min_stack_height + ) + obj = super().__new__( + cls, + obj_bytes, + popped_stack_items=popped_stack_items, + pushed_stack_items=pushed_stack_items, + max_stack_height=max_stack_height, + min_stack_height=min_stack_height, + ) + obj.data_portion_length = data_portion_length + obj.data_portion_formatter = data_portion_formatter + obj.stack_properties_modifier = stack_properties_modifier + obj.unchecked_stack = unchecked_stack + obj.kwargs = kwargs + obj.kwargs_defaults = kwargs_defaults + return obj + raise TypeError("Opcode constructor '__new__' didn't return an instance!") + + def __getitem__(self, *args: "int | bytes | str | Iterable[int]") -> "Opcode": + """ + Initialize a new instance of the opcode with the data portion set, and also clear + the data portion variables to avoid reusing them. + """ + if self.data_portion_formatter is None and self.data_portion_length == 0: + raise ValueError("Opcode does not have a data portion or has already been set") + data_portion = bytes() + + if self.data_portion_formatter is not None: + if len(args) == 1 and isinstance(args[0], Iterable) and not isinstance(args[0], bytes): + data_portion = self.data_portion_formatter(*args[0]) + else: + data_portion = self.data_portion_formatter(*args) + elif self.data_portion_length > 0: + # For opcodes with a data portion, the first argument is the data and the rest of the + # arguments form the stack. + assert len(args) == 1, "Opcode with data portion requires exactly one argument" + data = args[0] + if isinstance(data, bytes) or isinstance(data, SupportsBytes) or isinstance(data, str): + if isinstance(data, str): + if data.startswith("0x"): + data = data[2:] + data = bytes.fromhex(data) + elif isinstance(data, SupportsBytes): + data = bytes(data) + assert len(data) <= self.data_portion_length + data_portion = data.rjust(self.data_portion_length, b"\x00") + elif isinstance(data, int): + signed = data < 0 + data_portion = data.to_bytes( + length=self.data_portion_length, + byteorder="big", + signed=signed, + ) + else: + raise TypeError("Opcode data portion must be either an int or bytes/hex string") + popped_stack_items = self.popped_stack_items + pushed_stack_items = self.pushed_stack_items + min_stack_height = self.min_stack_height + max_stack_height = self.max_stack_height + assert ( + popped_stack_items is not None + and pushed_stack_items is not None + and min_stack_height is not None + ) + if self.stack_properties_modifier is not None: + ( + popped_stack_items, + pushed_stack_items, + min_stack_height, + max_stack_height, + ) = self.stack_properties_modifier(data_portion) + + new_opcode = Opcode( + bytes(self) + data_portion, + popped_stack_items=popped_stack_items, + pushed_stack_items=pushed_stack_items, + min_stack_height=min_stack_height, + max_stack_height=max_stack_height, + data_portion_length=0, + data_portion_formatter=None, + unchecked_stack=self.unchecked_stack, + kwargs=self.kwargs, + kwargs_defaults=self.kwargs_defaults, + ) + new_opcode._name_ = f"{self._name_}[0x{data_portion.hex()}]" + return new_opcode + + def __call__( + self, + *args_t: "int | bytes | str | Opcode | Bytecode | Iterable[int]", + unchecked: bool = False, + **kwargs: "int | bytes | str | Opcode | Bytecode", + ) -> Bytecode: + """ + Makes all opcode instances callable to return formatted bytecode, which constitutes a data + portion, that is located after the opcode byte, and pre-opcode bytecode, which is normally + used to set up the stack. + + This useful to automatically format, e.g., call opcodes and their stack arguments as + `Opcodes.CALL(Opcodes.GAS, 0x1234, 0x0, 0x0, 0x0, 0x0, 0x0)`. + + Data sign is automatically detected but for this reason the range of the input must be: + `[-2^(data_portion_bits-1), 2^(data_portion_bits)]` where: `data_portion_bits == + data_portion_length * 8` + + For the stack, the arguments are set up in the opposite order they are given, so the first + argument is the last item pushed to the stack. + + The resulting stack arrangement does not take into account opcode stack element + consumption, so the stack height is not guaranteed to be correct and the user must take + this into consideration. + + Integers can also be used as stack elements, in which case they are automatically converted + to PUSH operations, and negative numbers always use a PUSH32 operation. + + Hex-strings will be automatically converted to bytes. + """ + args: List["int | bytes | str | Opcode | Bytecode | Iterable[int]"] = list(args_t) + + if self.has_data_portion(): + if len(args) == 0: + raise ValueError("Opcode with data portion requires at least one argument") + assert type(self) is Opcode + get_item_arg = args.pop() + assert not isinstance(get_item_arg, Bytecode) + return self[get_item_arg](*args) + + if self.kwargs is not None and len(kwargs) > 0: + assert len(args) == 0, f"Cannot mix positional and keyword arguments {args} {kwargs}" + for kw in self.kwargs: + args.append(kwargs[kw] if kw in kwargs else self.kwargs_defaults.get(kw, 0)) + + # The rest of the arguments form the stack. + if len(args) != self.popped_stack_items and not (unchecked or self.unchecked_stack): + raise ValueError( + f"Opcode {self._name_} requires {self.popped_stack_items} stack elements, but " + f"{len(args)} were provided. Use 'unchecked=True' parameter to ignore this check." + ) + + pre_opcode_bytecode = Bytecode() + while len(args) > 0: + pre_opcode_bytecode += _stack_argument_to_bytecode(args.pop()) + return pre_opcode_bytecode + self + + def __lt__(self, other: "Opcode") -> bool: + """ + Compares two opcodes by their integer value. + """ + return self.int() < other.int() + + def __gt__(self, other: "Opcode") -> bool: + """ + Compares two opcodes by their integer value. + """ + return self.int() > other.int() + + def int(self) -> int: + """ + Returns the integer representation of the opcode. + """ + return int.from_bytes(self, byteorder="big") + + def has_data_portion(self) -> bool: + """ + Returns whether the opcode has a data portion. + """ + return self.data_portion_length > 0 or self.data_portion_formatter is not None + + +OpcodeCallArg = int | bytes | str | Bytecode | Iterable[int] + + +class Macro(Bytecode): + """ + Represents opcode macro replacement, basically holds bytes + """ + + lambda_operation: Callable[..., Bytecode] | None + + def __new__( + cls, + macro_or_bytes: "Bytecode | Macro" = Bytecode(), + *, + lambda_operation: Callable[..., Bytecode] | None = None, + ): + """ + Creates a new opcode macro instance. + """ + if isinstance(macro_or_bytes, Macro): + # Required because Enum class calls the base class with the instantiated object as + # parameter. + return macro_or_bytes + else: + instance = super().__new__(cls, macro_or_bytes) + instance.lambda_operation = lambda_operation + return instance + + def __call__(self, *args_t: OpcodeCallArg) -> Bytecode: + """ + Performs the macro operation if any. + Otherwise is a no-op. + """ + if self.lambda_operation is not None: + return self.lambda_operation(*args_t) + + pre_opcode_bytecode = Bytecode() + for arg in args_t: + pre_opcode_bytecode += _stack_argument_to_bytecode(arg) + return pre_opcode_bytecode + self + + +# Constants + +RJUMPV_MAX_INDEX_BYTE_LENGTH = 1 +RJUMPV_BRANCH_OFFSET_BYTE_LENGTH = 2 + + +# TODO: Allowing Iterable here is a hacky way to support `range`, because Python 3.11+ will allow +# `Op.RJUMPV[*range(5)]`. This is a temporary solution until Python 3.11+ is the minimum required +# version. + + +def _rjumpv_encoder(*args: int | bytes | Iterable[int]) -> bytes: + if len(args) == 1: + if isinstance(args[0], bytes) or isinstance(args[0], SupportsBytes): + return bytes(args[0]) + elif isinstance(args[0], Iterable): + int_args = list(args[0]) + return b"".join( + [(len(int_args) - 1).to_bytes(RJUMPV_MAX_INDEX_BYTE_LENGTH, "big")] + + [ + i.to_bytes(RJUMPV_BRANCH_OFFSET_BYTE_LENGTH, "big", signed=True) + for i in int_args + ] + ) + return b"".join( + [(len(args) - 1).to_bytes(RJUMPV_MAX_INDEX_BYTE_LENGTH, "big")] + + [ + i.to_bytes(RJUMPV_BRANCH_OFFSET_BYTE_LENGTH, "big", signed=True) + for i in args + if isinstance(i, int) + ] + ) + + +def _exchange_encoder(*args: int) -> bytes: + assert 1 <= len(args) <= 2, f"Exchange opcode requires one or two arguments, got {len(args)}" + if len(args) == 1: + return int.to_bytes(args[0], 1, "big") + # n = imm >> 4 + 1 + # m = imm & 0xF + 1 + # x = n + 1 + # y = n + m + 1 + # ... + # n = x - 1 + # m = y - x + # m = y - n - 1 + x, y = args + assert 2 <= x <= 0x11 + assert x + 1 <= y <= x + 0x10 + n = x - 1 + m = y - x + imm = (n - 1) << 4 | m - 1 + return int.to_bytes(imm, 1, "big") + + +def _swapn_stack_properties_modifier(data: bytes) -> tuple[int, int, int, int]: + imm = int.from_bytes(data, "big") + n = imm + 1 + min_stack_height = n + 1 + return 0, 0, min_stack_height, min_stack_height + + +def _dupn_stack_properties_modifier(data: bytes) -> tuple[int, int, int, int]: + imm = int.from_bytes(data, "big") + n = imm + 1 + min_stack_height = n + return 0, 1, min_stack_height, min_stack_height + 1 + + +def _exchange_stack_properties_modifier(data: bytes) -> tuple[int, int, int, int]: + imm = int.from_bytes(data, "big") + n = (imm >> 4) + 1 + m = (imm & 0x0F) + 1 + min_stack_height = n + m + 1 + return 0, 0, min_stack_height, min_stack_height + + +class Opcodes(Opcode, Enum): + """ + Enum containing all known opcodes. + + Contains deprecated and not yet implemented opcodes. + + This enum is !! NOT !! meant to be iterated over by the tests. Instead, create a list with + cherry-picked opcodes from this Enum within the test if iteration is needed. + + Do !! NOT !! remove or modify existing opcodes from this list. + """ + + STOP = Opcode(0x00) + """ + STOP() + ---- + + Description + ---- + Stop execution + + Inputs + ---- + - None + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + 0 + + Source: [evm.codes/#00](https://www.evm.codes/#00) + """ + + ADD = Opcode(0x01, popped_stack_items=2, pushed_stack_items=1) + """ + ADD(a, b) = c + ---- + + Description + ---- + Addition operation + + Inputs + ---- + - a: first integer value to add + - b: second integer value to add + + Outputs + ---- + - c: integer result of the addition modulo 2**256 + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#01](https://www.evm.codes/#01) + """ + + MUL = Opcode(0x02, popped_stack_items=2, pushed_stack_items=1) + """ + MUL(a, b) = c + ---- + + Description + ---- + Multiplication operation + + Inputs + ---- + - a: first integer value to multiply + - b: second integer value to multiply + + Outputs + ---- + - c: integer result of the multiplication modulo 2**256 + + Fork + ---- + Frontier + + Gas + ---- + 5 + + Source: [evm.codes/#02](https://www.evm.codes/#02) + """ + + SUB = Opcode(0x03, popped_stack_items=2, pushed_stack_items=1) + """ + SUB(a, b) = c + ---- + + Description + ---- + Subtraction operation + + Inputs + ---- + - a: first integer value + - b: second integer value + + Outputs + ---- + - c: integer result of the subtraction modulo 2**256 + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#03](https://www.evm.codes/#03) + """ + + DIV = Opcode(0x04, popped_stack_items=2, pushed_stack_items=1) + """ + DIV(a, b) = c + ---- + + Description + ---- + Division operation + + Inputs + ---- + - a: numerator + - b: denominator (must be non-zero) + + Outputs + ---- + - c: integer result of the division + + Fork + ---- + Frontier + + Gas + ---- + 5 + + Source: [evm.codes/#04](https://www.evm.codes/#04) + """ + + SDIV = Opcode(0x05, popped_stack_items=2, pushed_stack_items=1) + """ + SDIV(a, b) = c + ---- + + Description + ---- + Signed division operation + + Inputs + ---- + - a: signed numerator + - b: signed denominator + + Outputs + ---- + - c: signed integer result of the division. If the denominator is 0, the result will be 0 + ---- + + Fork + ---- + Frontier + + Gas + ---- + 5 + + Source: [evm.codes/#05](https://www.evm.codes/#05) + """ + + MOD = Opcode(0x06, popped_stack_items=2, pushed_stack_items=1) + """ + MOD(a, b) = c + ---- + + Description + ---- + Modulo operation + + Inputs + ---- + - a: integer numerator + - b: integer denominator + + Outputs + ---- + - a % b: integer result of the integer modulo. If the denominator is 0, the result will be 0 + + Fork + ---- + Frontier + + Gas + ---- + 5 + + Source: [evm.codes/#06](https://www.evm.codes/#06) + """ + + SMOD = Opcode(0x07, popped_stack_items=2, pushed_stack_items=1) + """ + SMOD(a, b) = c + ---- + + Description + ---- + Signed modulo remainder operation + + Inputs + ---- + - a: integer numerator + - b: integer denominator + + Outputs + ---- + - a % b: integer result of the signed integer modulo. If the denominator is 0, the result will + be 0 + + Fork + ---- + Frontier + + Gas + ---- + 5 + + Source: [evm.codes/#07](https://www.evm.codes/#07) + """ + + ADDMOD = Opcode(0x08, popped_stack_items=3, pushed_stack_items=1) + """ + ADDMOD(a, b, c) = d + ---- + + Description + ---- + Modular addition operation with overflow check + + Inputs + ---- + - a: first integer value + - b: second integer value + - c: integer denominator + + Outputs + ---- + - (a + b) % N: integer result of the addition followed by a modulo. If the denominator is 0, + the result will be 0 + + Fork + ---- + Frontier + + Gas + ---- + 8 + + Source: [evm.codes/#08](https://www.evm.codes/#08) + """ + + MULMOD = Opcode(0x09, popped_stack_items=3, pushed_stack_items=1) + """ + MULMOD(a, b, N) = d + ---- + + Description + ---- + Modulo multiplication operation + + Inputs + ---- + - a: first integer value to multiply + - b: second integer value to multiply + - N: integer denominator + + Outputs + ---- + - (a * b) % N: integer result of the multiplication followed by a modulo. If the denominator + is 0, the result will be 0 + + Fork + ---- + Frontier + + Gas + ---- + 8 + + Source: [evm.codes/#09](https://www.evm.codes/#09) + """ + + EXP = Opcode(0x0A, popped_stack_items=2, pushed_stack_items=1) + """ + EXP(a, exponent) = a ** exponent + ---- + + Description + ---- + Exponential operation + + Inputs + ---- + - a: integer base + - exponent: integer exponent + + Outputs + ---- + - a ** exponent: integer result of the exponential operation modulo 2**256 + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 10 + - dynamic_gas = 50 * exponent_byte_size + + Source: [evm.codes/#0A](https://www.evm.codes/#0A) + """ + + SIGNEXTEND = Opcode(0x0B, popped_stack_items=2, pushed_stack_items=1) + """ + SIGNEXTEND(b, x) = y + ---- + + Description + ---- + Sign extension operation + + Inputs + ---- + - b: size in byte - 1 of the integer to sign extend + - x: integer value to sign extend + + Outputs + ---- + - y: integer result of the sign extend + + Fork + ---- + Frontier + + Gas + ---- + 5 + + Source: [evm.codes/#0B](https://www.evm.codes/#0B) + """ + + LT = Opcode(0x10, popped_stack_items=2, pushed_stack_items=1) + """ + LT(a, b) = a < b + ---- + + Description + ---- + Less-than comparison + + Inputs + ---- + - a: left side integer value + - b: right side integer value + + Outputs + ---- + - a < b: 1 if the left side is smaller, 0 otherwise + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#10](https://www.evm.codes/#10) + """ + + GT = Opcode(0x11, popped_stack_items=2, pushed_stack_items=1) + """ + GT(a, b) = a > b + ---- + + Description + ---- + Greater-than comparison + + Inputs + ---- + - a: left side integer + - b: right side integer + + Outputs + ---- + - a > b: 1 if the left side is bigger, 0 otherwise + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#11](https://www.evm.codes/#11) + """ + + SLT = Opcode(0x12, popped_stack_items=2, pushed_stack_items=1) + """ + SLT(a, b) = a < b + ---- + + Description + ---- + Signed less-than comparison + + Inputs + ---- + - a: left side signed integer + - b: right side signed integer + + Outputs + ---- + - a < b: 1 if the left side is smaller, 0 otherwise + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#12](https://www.evm.codes/#12) + """ + + SGT = Opcode(0x13, popped_stack_items=2, pushed_stack_items=1) + """ + SGT(a, b) = a > b + ---- + + Description + ---- + Signed greater-than comparison + + Inputs + ---- + - a: left side signed integer + - b: right side signed integer + + Outputs + ---- + - a > b: 1 if the left side is bigger, 0 otherwise + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#13](https://www.evm.codes/#13) + """ + + EQ = Opcode(0x14, popped_stack_items=2, pushed_stack_items=1) + """ + EQ(a, b) = a == b + ---- + + Description + ---- + Equality comparison + + Inputs + ---- + - a: left side integer + - b: right side integer + + Outputs + ---- + - a == b: 1 if the left side is equal to the right side, 0 otherwise + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#14](https://www.evm.codes/#14) + """ + + ISZERO = Opcode(0x15, popped_stack_items=1, pushed_stack_items=1) + """ + ISZERO(a) = a == 0 + ---- + + Description + ---- + Is-zero comparison + + Inputs + ---- + - a: integer + + Outputs + ---- + - a == 0: 1 if a is 0, 0 otherwise + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#15](https://www.evm.codes/#15) + """ + + AND = Opcode(0x16, popped_stack_items=2, pushed_stack_items=1) + """ + AND(a, b) = a & b + ---- + + Description + ---- + Bitwise AND operation + + Inputs + ---- + - a: first binary value + - b: second binary value + + Outputs + ---- + - a & b: the bitwise AND result + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#16](https://www.evm.codes/#16) + """ + + OR = Opcode(0x17, popped_stack_items=2, pushed_stack_items=1) + """ + OR(a, b) = a | b + ---- + + Description + ---- + Bitwise OR operation + + Inputs + ---- + - a: first binary value + - b: second binary value + + Outputs + ---- + - a | b: the bitwise OR result + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#17](https://www.evm.codes/#17) + """ + + XOR = Opcode(0x18, popped_stack_items=2, pushed_stack_items=1) + """ + XOR(a, b) = a ^ b + ---- + + Description + ---- + Bitwise XOR operation + + Inputs + ---- + - a: first binary value + - b: second binary value + + Outputs + ---- + - a ^ b: the bitwise XOR result + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#18](https://www.evm.codes/#18) + """ + + NOT = Opcode(0x19, popped_stack_items=1, pushed_stack_items=1) + """ + NOT(a) = ~a + ---- + + Description + ---- + Bitwise NOT operation + + Inputs + ---- + - a: binary value + + Outputs + ---- + - ~a: the bitwise NOT result + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#19](https://www.evm.codes/#19) + """ + + BYTE = Opcode(0x1A, popped_stack_items=2, pushed_stack_items=1) + """ + BYTE(i, x) = y + ---- + + Description + ---- + Extract a byte from the given position in the value + + Inputs + ---- + - i: byte offset starting from the most significant byte + - x: 32-byte value + + Outputs + ---- + - y: the indicated byte at the least significant position. If the byte offset is out of range, + the result is 0 + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#1A](https://www.evm.codes/#1A) + """ + + SHL = Opcode(0x1B, popped_stack_items=2, pushed_stack_items=1) + """ + SHL(shift, value) = value << shift + ---- + + Description + ---- + Shift left operation + + Inputs + ---- + - shift: number of bits to shift to the left + - value: 32 bytes to shift + + Outputs + ---- + - value << shift: the shifted value. If shift is bigger than 255, returns 0 + + Fork + ---- + Constantinople + + Gas + ---- + 3 + + Source: [evm.codes/#1B](https://www.evm.codes/#1B) + """ + + SHR = Opcode(0x1C, popped_stack_items=2, pushed_stack_items=1) + """ + SHR(shift, value) = value >> shift + ---- + + Description + ---- + Logical shift right operation + + Inputs + ---- + - shift: number of bits to shift to the right. + - value: 32 bytes to shift + + Outputs + ---- + - value >> shift: the shifted value. If shift is bigger than 255, returns 0 + + Fork + ---- + Constantinople + + Gas + ---- + 3 + + Source: [evm.codes/#1C](https://www.evm.codes/#1C) + """ + + SAR = Opcode(0x1D, popped_stack_items=2, pushed_stack_items=1) + """ + SAR(shift, value) = value >> shift + ---- + + Description + ---- + Arithmetic shift right operation + + Inputs + ---- + - shift: number of bits to shift to the right + - value: integer to shift + + Outputs + ---- + - value >> shift: the shifted value + + Fork + ---- + Constantinople + + Gas + ---- + 3 + + Source: [evm.codes/#1D](https://www.evm.codes/#1D) + """ + + SHA3 = Opcode(0x20, popped_stack_items=2, pushed_stack_items=1, kwargs=["offset", "size"]) + """ + SHA3(offset, size) = hash + ---- + + Description + ---- + Compute Keccak-256 hash + + Inputs + ---- + - offset: byte offset in the memory + - size: byte size to read in the memory + + Outputs + ---- + - hash: Keccak-256 hash of the given data in memory + + Fork + ---- + Frontier + + Gas + ---- + - minimum_word_size = (size + 31) / 32 + - static_gas = 30 + - dynamic_gas = 6 * minimum_word_size + memory_expansion_cost + + Source: [evm.codes/#20](https://www.evm.codes/#20) + """ + + ADDRESS = Opcode(0x30, pushed_stack_items=1) + """ + ADDRESS() = address + ---- + + Description + ---- + Get address of currently executing account + + Inputs + ---- + - None + + Outputs + ---- + - address: the 20-byte address of the current account + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#30](https://www.evm.codes/#30) + """ + + BALANCE = Opcode(0x31, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"]) + """ + BALANCE(address) = balance + ---- + + Description + ---- + Get the balance of the specified account + + Inputs + ---- + - address: 20-byte address of the account to check + + Outputs + ---- + - balance: balance of the given account in wei. Returns 0 if the account doesn't exist + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 0 + - dynamic_gas = 100 if warm_address, 2600 if cold_address + + Source: [evm.codes/#31](https://www.evm.codes/#31) + """ + + ORIGIN = Opcode(0x32, pushed_stack_items=1) + """ + ORIGIN() = address + ---- + + Description + ---- + Get execution origination address + + Inputs + ---- + - None + + Outputs + ---- + - address: the 20-byte address of the sender of the transaction. It can only be an account + without code + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#32](https://www.evm.codes/#32) + """ + + CALLER = Opcode(0x33, pushed_stack_items=1) + """ + CALLER() = address + ---- + + Description + ---- + Get caller address + + Inputs + ---- + - None + + Outputs + ---- + - address: the 20-byte address of the caller account. This is the account that did the last + call (except delegate call) + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#33](https://www.evm.codes/#33) + """ + + CALLVALUE = Opcode(0x34, pushed_stack_items=1) + """ + CALLVALUE() = value + ---- + + Description + ---- + Get deposited value by the instruction/transaction responsible for this execution + + Inputs + ---- + - None + + Outputs + ---- + - value: the value of the current call in wei + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#34](https://www.evm.codes/#34) + """ + + CALLDATALOAD = Opcode(0x35, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"]) + """ + CALLDATALOAD(offset) = data[offset] + ---- + + Description + ---- + Get input data of current environment + + Inputs + ---- + - offset: byte offset in the calldata + + Outputs + ---- + - data[offset]: 32-byte value starting from the given offset of the calldata. All bytes after + the end of the calldata are set to 0 + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#35](https://www.evm.codes/#35) + """ + + CALLDATASIZE = Opcode(0x36, pushed_stack_items=1) + """ + CALLDATASIZE() = size + ---- + + Description + ---- + Get size of input data in current environment + + Inputs + ---- + - None + + Outputs + ---- + - size: byte size of the calldata + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#36](https://www.evm.codes/#36) + """ + + CALLDATACOPY = Opcode(0x37, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) + """ + CALLDATACOPY(dest_offset, offset, size) + ---- + + Description + ---- + Copy input data in current environment to memory + + Inputs + ---- + - dest_offset: byte offset in the memory where the result will be copied + - offset: byte offset in the calldata to copy + - size: byte size to copy + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - minimum_word_size = (size + 31) / 32 + - static_gas = 3 + - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + + Source: [evm.codes/#37](https://www.evm.codes/#37) + """ + + CODESIZE = Opcode(0x38, pushed_stack_items=1) + """ + CODESIZE() = size + ---- + + Description + ---- + Get size of code running in current environment + + Inputs + ---- + - None + + Outputs + ---- + - size: byte size of the code + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#38](https://www.evm.codes/#38) + """ + + CODECOPY = Opcode(0x39, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) + """ + CODECOPY(dest_offset, offset, size) + ---- + + Description + ---- + Copy code running in current environment to memory + + Inputs + ---- + - dest_offset: byte offset in the memory where the result will be copied. + - offset: byte offset in the code to copy. + - size: byte size to copy + + Fork + ---- + Frontier + + Gas + ---- + - minimum_word_size = (size + 31) / 32 + - static_gas = 3 + - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + + Source: [evm.codes/#39](https://www.evm.codes/#39) + """ + + GASPRICE = Opcode(0x3A, pushed_stack_items=1) + """ + GASPRICE() = price + ---- + + Description + ---- + Get price of gas in current environment + + Outputs + ---- + - price: gas price in wei per gas + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#3A](https://www.evm.codes/#3A) + """ + + EXTCODESIZE = Opcode(0x3B, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"]) + """ + EXTCODESIZE(address) = size + ---- + + Description + ---- + Get size of an account's code + + Inputs + ---- + - address: 20-byte address of the contract to query + + Outputs + ---- + - size: byte size of the code + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 0 + - dynamic_gas = 100 if warm_address, 2600 if cold_address + + Source: [evm.codes/#3B](https://www.evm.codes/#3B) + """ + + EXTCODECOPY = Opcode( + 0x3C, popped_stack_items=4, kwargs=["address", "dest_offset", "offset", "size"] + ) + """ + EXTCODECOPY(address, dest_offset, offset, size) + ---- + + Description + ---- + Copy an account's code to memory + + Inputs + ---- + - address: 20-byte address of the contract to query + - dest_offset: byte offset in the memory where the result will be copied + - offset: byte offset in the code to copy + - size: byte size to copy + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - minimum_word_size = (size + 31) / 32 + - static_gas = 0 + - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost + + Source: [evm.codes/#3C](https://www.evm.codes/#3C) + """ + + RETURNDATASIZE = Opcode(0x3D, pushed_stack_items=1) + """ + RETURNDATASIZE() = size + ---- + + Description + ---- + Get size of output data from the previous call from the current environment + + Outputs + ---- + - size: byte size of the return data from the last executed sub context + + Fork + ---- + Byzantium + + Gas + ---- + 2 + + Source: [evm.codes/#3D](https://www.evm.codes/#3D) + """ + + RETURNDATACOPY = Opcode(0x3E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) + """ + RETURNDATACOPY(dest_offset, offset, size) + ---- + + Description + ---- + Copy output data from the previous call to memory + + Inputs + ---- + - dest_offset: byte offset in the memory where the result will be copied + - offset: byte offset in the return data from the last executed sub context to copy + - size: byte size to copy + + Fork + ---- + Byzantium + + Gas + ---- + - minimum_word_size = (size + 31) / 32 + - static_gas = 3 + - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + + Source: [evm.codes/#3E](https://www.evm.codes/#3E) + """ + + EXTCODEHASH = Opcode(0x3F, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"]) + """ + EXTCODEHASH(address) = hash + ---- + + Description + ---- + Get hash of an account's code + + Inputs + ---- + - address: 20-byte address of the account + + Outputs + ---- + - hash: hash of the chosen account's code, the empty hash (0xc5d24601...) if the account has no + code, or 0 if the account does not exist or has been destroyed + + Fork + ---- + Constantinople + + Gas + ---- + - static_gas = 0 + - dynamic_gas = 100 if warm_address, 2600 if cold_address + + Source: [evm.codes/#3F](https://www.evm.codes/#3F) + """ + + BLOCKHASH = Opcode(0x40, popped_stack_items=1, pushed_stack_items=1, kwargs=["block_number"]) + """ + BLOCKHASH(block_number) = hash + ---- + + Description + ---- + Get the hash of one of the 256 most recent complete blocks + + Inputs + ---- + - blockNumber: block number to get the hash from. Valid range is the last 256 blocks (not + including the current one). Current block number can be queried with NUMBER + + Outputs + ---- + - hash: hash of the chosen block, or 0 if the block number is not in the valid range + + Fork + ---- + Frontier + + Gas + ---- + 20 + + Source: [evm.codes/#40](https://www.evm.codes/#40) + """ + + COINBASE = Opcode(0x41, pushed_stack_items=1) + """ + COINBASE() = address + ---- + + Description + ---- + Get the block's beneficiary address + + Inputs + ---- + - None + + Outputs + ---- + - address: miner's 20-byte address + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#41](https://www.evm.codes/#41) + """ + + TIMESTAMP = Opcode(0x42, pushed_stack_items=1) + """ + TIMESTAMP() = timestamp + ---- + + Description + ---- + Get the block's timestamp + + Inputs + ---- + - None + + Outputs + ---- + - timestamp: unix timestamp of the current block + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#42](https://www.evm.codes/#42) + """ + + NUMBER = Opcode(0x43, pushed_stack_items=1) + """ + NUMBER() = blockNumber + ---- + + Description + ---- + Get the block's number + + Inputs + ---- + - None + + Outputs + ---- + - blockNumber: current block number + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#43](https://www.evm.codes/#43) + """ + + PREVRANDAO = Opcode(0x44, pushed_stack_items=1) + """ + PREVRANDAO() = prevRandao + ---- + + Description + ---- + Get the previous block's RANDAO mix + + Inputs + ---- + - None + + Outputs + ---- + - prevRandao: previous block's RANDAO mix + + Fork + ---- + Merge + + Gas + ---- + 2 + + Source: [evm.codes/#44](https://www.evm.codes/#44) + """ + + GASLIMIT = Opcode(0x45, pushed_stack_items=1) + """ + GASLIMIT() = gasLimit + ---- + + Description + ---- + Get the block's gas limit + + Inputs + ---- + - None + + Outputs + ---- + - gasLimit: gas limit + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#45](https://www.evm.codes/#45) + """ + + CHAINID = Opcode(0x46, pushed_stack_items=1) + """ + CHAINID() = chainId + ---- + + Description + ---- + Get the chain ID + + Inputs + ---- + - None + + Outputs + ---- + - chainId: chain id of the network + + Fork + ---- + Istanbul + + Gas + ---- + 2 + + Source: [evm.codes/#46](https://www.evm.codes/#46) + """ + + SELFBALANCE = Opcode(0x47, pushed_stack_items=1) + """ + SELFBALANCE() = balance + ---- + + Description + ---- + Get balance of currently executing account + + Inputs + ---- + - None + + Outputs + ---- + - balance: balance of the current account in wei + + Fork + ---- + Istanbul + + Gas + ---- + 5 + + Source: [evm.codes/#47](https://www.evm.codes/#47) + """ + + BASEFEE = Opcode(0x48, pushed_stack_items=1) + """ + BASEFEE() = baseFee + ---- + + Description + ---- + Get the base fee + + Outputs + ---- + - baseFee: base fee in wei + + Fork + ---- + London + + Gas + ---- + 2 + + Source: [evm.codes/#48](https://www.evm.codes/#48) + """ + + BLOBHASH = Opcode(0x49, popped_stack_items=1, pushed_stack_items=1, kwargs=["index"]) + """ + BLOBHASH(index) = versionedHash + ---- + + Description + ---- + Returns the versioned hash of a single blob contained in the type-3 transaction + + Inputs + ---- + - index: index of the blob + + Outputs + ---- + - versionedHash: versioned hash of the blob + + Fork + ---- + Cancun + + Gas + ---- + 3 + + Source: [eips.ethereum.org/EIPS/eip-4844](https://eips.ethereum.org/EIPS/eip-4844) + """ + + BLOBBASEFEE = Opcode(0x4A, popped_stack_items=0, pushed_stack_items=1) + """ + BLOBBASEFEE() = fee + ---- + + Description + ---- + Returns the value of the blob base fee of the block it is executing in + + Inputs + ---- + - None + + Outputs + ---- + - baseFeePerBlobGas: base fee for the blob gas in wei + + Fork + ---- + Cancun + + Gas + ---- + 2 + + Source: [eips.ethereum.org/EIPS/eip-7516](https://eips.ethereum.org/EIPS/eip-7516) + """ + + POP = Opcode(0x50, popped_stack_items=1) + """ + POP() + ---- + + Description + ---- + Remove item from stack + + Inputs + ---- + - None + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#50](https://www.evm.codes/#50) + """ + + MLOAD = Opcode(0x51, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"]) + """ + MLOAD(offset) = value + ---- + + Description + ---- + Load word from memory + + Inputs + ---- + - offset: offset in the memory in bytes + + Outputs + ---- + - value: the 32 bytes in memory starting at that offset. If it goes beyond its current size + (see MSIZE), writes 0s + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 3 + - dynamic_gas = memory_expansion_cost + + Source: [evm.codes/#51](https://www.evm.codes/#51) + """ + + MSTORE = Opcode(0x52, popped_stack_items=2, kwargs=["offset", "value"]) + """ + MSTORE(offset, value) + ---- + + Description + ---- + Save word to memory + + Inputs + ---- + - offset: offset in the memory in bytes + - value: 32-byte value to write in the memory + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 3 + - dynamic_gas = memory_expansion_cost + + Source: [evm.codes/#52](https://www.evm.codes/#52) + """ + + MSTORE8 = Opcode(0x53, popped_stack_items=2, kwargs=["offset", "value"]) + """ + MSTORE8(offset, value) + ---- + + Description + ---- + Save byte to memory + + Inputs + ---- + - offset: offset in the memory in bytes + - value: 1-byte value to write in the memory (the least significant byte of the 32-byte stack + value) + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 3 + - dynamic_gas = memory_expansion_cost + + Source: [evm.codes/#53](https://www.evm.codes/#53) + """ + + SLOAD = Opcode(0x54, popped_stack_items=1, pushed_stack_items=1, kwargs=["key"]) + """ + SLOAD(key) = value + ---- + + Description + ---- + Load word from storage + + Inputs + ---- + - key: 32-byte key in storage + + Outputs + ---- + - value: 32-byte value corresponding to that key. 0 if that key was never written before + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 0 + - dynamic_gas = 100 if warm_address, 2600 if cold_address + + Source: [evm.codes/#54](https://www.evm.codes/#54) + """ + + SSTORE = Opcode(0x55, popped_stack_items=2, kwargs=["key", "value"]) + """ + SSTORE(key, value) + ---- + + Description + ---- + Save word to storage + + Inputs + ---- + - key: 32-byte key in storage + - value: 32-byte value to store + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + ``` + static_gas = 0 + + if value == current_value + if key is warm + base_dynamic_gas = 100 + else + base_dynamic_gas = 100 + else if current_value == original_value + if original_value == 0 + base_dynamic_gas = 20000 + else + base_dynamic_gas = 2900 + else + base_dynamic_gas = 100 + + if key is cold: + base_dynamic_gas += 2100 + ``` + + Source: [evm.codes/#55](https://www.evm.codes/#55) + """ + + JUMP = Opcode(0x56, popped_stack_items=1, kwargs=["pc"]) + """ + JUMP(pc) + ---- + + Description + ---- + Alter the program counter + + Inputs + ---- + - pc: byte offset in the deployed code where execution will continue from. Must be a + JUMPDEST instruction + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + 8 + + Source: [evm.codes/#56](https://www.evm.codes/#56) + """ + + JUMPI = Opcode(0x57, popped_stack_items=2, kwargs=["pc", "condition"]) + """ + JUMPI(pc, condition) + ---- + + Description + ---- + Conditionally alter the program counter + + Inputs + ---- + - pc: byte offset in the deployed code where execution will continue from. Must be a + JUMPDEST instruction + - condition: the program counter will be altered with the new value only if this value is + different from 0. Otherwise, the program counter is simply incremented and the next + instruction will be executed + + Fork + ---- + Frontier + + Gas + ---- + 10 + + Source: [evm.codes/#57](https://www.evm.codes/#57) + """ + + PC = Opcode(0x58, pushed_stack_items=1) + """ + PC() = counter + ---- + + Description + ---- + Get the value of the program counter prior to the increment corresponding to this instruction + + Inputs + ---- + - None + + Outputs + ---- + - counter: PC of this instruction in the current program. + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#58](https://www.evm.codes/#58) + """ + + MSIZE = Opcode(0x59, pushed_stack_items=1) + """ + MSIZE() = size + ---- + + Description + ---- + Get the size of active memory in bytes + + Outputs + ---- + - size: current memory size in bytes (higher offset accessed until now + 1) + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#59](https://www.evm.codes/#59) + """ + + GAS = Opcode(0x5A, pushed_stack_items=1) + """ + GAS() = gas_remaining + ---- + + Description + ---- + Get the amount of available gas, including the corresponding reduction for the cost of this + instruction + + Inputs + ---- + - None + + Outputs + ---- + - gas: remaining gas (after this instruction) + + Fork + ---- + Frontier + + Gas + ---- + 2 + + Source: [evm.codes/#5A](https://www.evm.codes/#5A) + """ + + JUMPDEST = Opcode(0x5B) + """ + JUMPDEST() + ---- + + Description + ---- + Mark a valid destination for jumps + + Inputs + ---- + - None + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + 1 + + Source: [evm.codes/#5B](https://www.evm.codes/#5B) + """ + + NOOP = Opcode(0x5B) + """ + NOOP() + ---- + + Description + ---- + Synonym for JUMPDEST. Performs no operation. + + Inputs + ---- + - None + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + 1 + + Source: [evm.codes/#5B](https://www.evm.codes/#5B) + """ + + TLOAD = Opcode(0x5C, popped_stack_items=1, pushed_stack_items=1, kwargs=["key"]) + """ + TLOAD(key) = value + ---- + + Description + ---- + Load word from transient storage + + Inputs + ---- + - key: 32-byte key in transient storage + + Outputs + ---- + - value: 32-byte value corresponding to that key. 0 if that key was never written + + Fork + ---- + Cancun + + Gas + ---- + 100 + + Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/eip-1153) + """ + + TSTORE = Opcode(0x5D, popped_stack_items=2, kwargs=["key", "value"]) + """ + TSTORE(key, value) + ---- + + Description + ---- + Save word to transient storage + + Inputs + ---- + - key: 32-byte key in transient storage + - value: 32-byte value to store + + Fork + ---- + Cancun + + Gas + ---- + 100 + + Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/eip-1153) + """ + + MCOPY = Opcode(0x5E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) + """ + MCOPY(dest_offset, offset, size) + ---- + + Description + ---- + Copies areas in memory + + Inputs + ---- + - dest_offset: byte offset in the memory where the result will be copied + - offset: byte offset in the calldata to copy + - size: byte size to copy + + Outputs + ---- + - None + + Fork + ---- + Cancun + + Gas + ---- + - minimum_word_size = (size + 31) / 32 + - static_gas = 3 + - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + + Source: [eips.ethereum.org/EIPS/eip-5656](https://eips.ethereum.org/EIPS/eip-5656) + """ + + PUSH0 = Opcode(0x5F, pushed_stack_items=1) + """ + PUSH0() = value + ---- + + Description + ---- + Place value 0 on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, equal to 0 + + Fork + ---- + Shanghai + + Gas + ---- + 2 + + Source: [evm.codes/#5F](https://www.evm.codes/#5F) + """ + + PUSH1 = Opcode(0x60, pushed_stack_items=1, data_portion_length=1) + """ + PUSH1() = value + ---- + + Description + ---- + Place 1 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#60](https://www.evm.codes/#60) + """ + + PUSH2 = Opcode(0x61, pushed_stack_items=1, data_portion_length=2) + """ + PUSH2() = value + ---- + + Description + ---- + Place 2 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#61](https://www.evm.codes/#61) + """ + + PUSH3 = Opcode(0x62, pushed_stack_items=1, data_portion_length=3) + """ + PUSH3() = value + ---- + + Description + ---- + Place 3 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#62](https://www.evm.codes/#62) + """ + + PUSH4 = Opcode(0x63, pushed_stack_items=1, data_portion_length=4) + """ + PUSH4() = value + ---- + + Description + ---- + Place 4 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#63](https://www.evm.codes/#63) + """ + + PUSH5 = Opcode(0x64, pushed_stack_items=1, data_portion_length=5) + """ + PUSH5() = value + ---- + + Description + ---- + Place 5 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#64](https://www.evm.codes/#64) + """ + + PUSH6 = Opcode(0x65, pushed_stack_items=1, data_portion_length=6) + """ + PUSH6() = value + ---- + + Description + ---- + Place 6 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#65](https://www.evm.codes/#65) + """ + + PUSH7 = Opcode(0x66, pushed_stack_items=1, data_portion_length=7) + """ + PUSH7() = value + ---- + + Description + ---- + Place 7 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#66](https://www.evm.codes/#66) + """ + + PUSH8 = Opcode(0x67, pushed_stack_items=1, data_portion_length=8) + """ + PUSH8() = value + ---- + + Description + ---- + Place 8 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#67](https://www.evm.codes/#67) + """ + + PUSH9 = Opcode(0x68, pushed_stack_items=1, data_portion_length=9) + """ + PUSH9() = value + ---- + + Description + ---- + Place 9 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#68](https://www.evm.codes/#68) + """ + + PUSH10 = Opcode(0x69, pushed_stack_items=1, data_portion_length=10) + """ + PUSH10() = value + ---- + + Description + ---- + Place 10 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#69](https://www.evm.codes/#69) + """ + + PUSH11 = Opcode(0x6A, pushed_stack_items=1, data_portion_length=11) + """ + PUSH11() = value + ---- + + Description + ---- + Place 11 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#6A](https://www.evm.codes/#6A) + """ + + PUSH12 = Opcode(0x6B, pushed_stack_items=1, data_portion_length=12) + """ + PUSH12() = value + ---- + + Description + ---- + Place 12 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#6B](https://www.evm.codes/#6B) + """ + + PUSH13 = Opcode(0x6C, pushed_stack_items=1, data_portion_length=13) + """ + PUSH13() = value + ---- + + Description + ---- + Place 13 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#6C](https://www.evm.codes/#6C) + """ + + PUSH14 = Opcode(0x6D, pushed_stack_items=1, data_portion_length=14) + """ + PUSH14() = value + ---- + + Description + ---- + Place 14 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + + Gas + ---- + 3 + + Source: [evm.codes/#6D](https://www.evm.codes/#6D) + """ + + PUSH15 = Opcode(0x6E, pushed_stack_items=1, data_portion_length=15) + """ + PUSH15() = value + ---- + + Description + ---- + Place 15 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#6E](https://www.evm.codes/#6E) + """ + + PUSH16 = Opcode(0x6F, pushed_stack_items=1, data_portion_length=16) + """ + PUSH16() = value + ---- + + Description + ---- + Place 16 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#6F](https://www.evm.codes/#6F) + """ + + PUSH17 = Opcode(0x70, pushed_stack_items=1, data_portion_length=17) + """ + PUSH17() = value + ---- + + Description + ---- + Place 17 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#70](https://www.evm.codes/#70) + """ + + PUSH18 = Opcode(0x71, pushed_stack_items=1, data_portion_length=18) + """ + PUSH18() = value + ---- + + Description + ---- + Place 18 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#71](https://www.evm.codes/#71) + """ + + PUSH19 = Opcode(0x72, pushed_stack_items=1, data_portion_length=19) + """ + PUSH19() = value + ---- + + Description + ---- + Place 19 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#72](https://www.evm.codes/#72) + """ + + PUSH20 = Opcode(0x73, pushed_stack_items=1, data_portion_length=20) + """ + PUSH20() = value + ---- + + Description + ---- + Place 20 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#73](https://www.evm.codes/#73) + """ + + PUSH21 = Opcode(0x74, pushed_stack_items=1, data_portion_length=21) + """ + PUSH21() = value + ---- + + Description + ---- + Place 21 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#74](https://www.evm.codes/#74) + """ + + PUSH22 = Opcode(0x75, pushed_stack_items=1, data_portion_length=22) + """ + PUSH22() = value + ---- + + Description + ---- + Place 22 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#75](https://www.evm.codes/#75) + """ + + PUSH23 = Opcode(0x76, pushed_stack_items=1, data_portion_length=23) + """ + PUSH23() = value + ---- + + Description + ---- + Place 23 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#76](https://www.evm.codes/#76) + """ + + PUSH24 = Opcode(0x77, pushed_stack_items=1, data_portion_length=24) + """ + PUSH24() = value + ---- + + Description + ---- + Place 24 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#77](https://www.evm.codes/#77) + """ + + PUSH25 = Opcode(0x78, pushed_stack_items=1, data_portion_length=25) + """ + PUSH25() = value + ---- + + Description + ---- + Place 25 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#78](https://www.evm.codes/#78) + """ + + PUSH26 = Opcode(0x79, pushed_stack_items=1, data_portion_length=26) + """ + PUSH26() = value + ---- + + Description + ---- + Place 26 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#79](https://www.evm.codes/#79) + """ + + PUSH27 = Opcode(0x7A, pushed_stack_items=1, data_portion_length=27) + """ + PUSH27() = value + ---- + + Description + ---- + Place 27 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#7A](https://www.evm.codes/#7A) + """ + + PUSH28 = Opcode(0x7B, pushed_stack_items=1, data_portion_length=28) + """ + PUSH28() = value + ---- + + Description + ---- + Place 28 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#7B](https://www.evm.codes/#7B) + """ + + PUSH29 = Opcode(0x7C, pushed_stack_items=1, data_portion_length=29) + """ + PUSH29() = value + ---- + + Description + ---- + Place 29 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#7C](https://www.evm.codes/#7C) + """ + + PUSH30 = Opcode(0x7D, pushed_stack_items=1, data_portion_length=30) + """ + PUSH30() = value + ---- + + Description + ---- + Place 30 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#7D](https://www.evm.codes/#7D) + """ + + PUSH31 = Opcode(0x7E, pushed_stack_items=1, data_portion_length=31) + """ + PUSH31() = value + ---- + + Description + ---- + Place 31 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#7E](https://www.evm.codes/#7E) + """ + + PUSH32 = Opcode(0x7F, pushed_stack_items=1, data_portion_length=32) + """ + PUSH32() = value + ---- + + Description + ---- + Place 32 byte item on stack + + Inputs + ---- + - None + + Outputs + ---- + - value: pushed value, aligned to the right (put in the lowest significant bytes) + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#7F](https://www.evm.codes/#7F) + """ + + DUP1 = Opcode(0x80, pushed_stack_items=1, min_stack_height=1) + """ + DUP1(value) = value, value + ---- + + Description + ---- + Duplicate 1st stack item + + Inputs + ---- + - value: value to duplicate + + Outputs + ---- + - value: duplicated value + - value: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#80](https://www.evm.codes/#80) + """ + + DUP2 = Opcode(0x81, pushed_stack_items=1, min_stack_height=2) + """ + DUP2(v1, v2) = v2, v1, v2 + ---- + + Description + ---- + Duplicate 2nd stack item + + Inputs + ---- + - v1: ignored value + - v2: value to duplicate + + Outputs + ---- + - v2: duplicated value + - v1: ignored value + - v2: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#81](https://www.evm.codes/#81) + """ + + DUP3 = Opcode(0x82, pushed_stack_items=1, min_stack_height=3) + """ + DUP3(v1, v2, v3) = v3, v1, v2, v3 + ---- + + Description + ---- + Duplicate 3rd stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - v3: value to duplicate + + Outputs + ---- + - v3: duplicated value + - v1: ignored value + - v2: ignored value + - v3: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#82](https://www.evm.codes/#82) + """ + + DUP4 = Opcode(0x83, pushed_stack_items=1, min_stack_height=4) + """ + DUP4(v1, v2, v3, v4) = v4, v1, v2, v3, v4 + ---- + + Description + ---- + Duplicate 4th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - v3: ignored value + - v4: value to duplicate + + Outputs + ---- + - v4: duplicated value + - v1: ignored value + - v2: ignored value + - v3: ignored value + - v4: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#83](https://www.evm.codes/#83) + """ + + DUP5 = Opcode(0x84, pushed_stack_items=1, min_stack_height=5) + """ + DUP5(v1, v2, v3, v4, v5) = v5, v1, v2, v3, v4, v5 + ---- + + Description + ---- + Duplicate 5th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - v3: ignored value + - v4: ignored value + - v5: value to duplicate + + Outputs + ---- + - v5: duplicated value + - v1: ignored value + - v2: ignored value + - v3: ignored value + - v4: ignored value + - v5: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#84](https://www.evm.codes/#84) + """ + + DUP6 = Opcode(0x85, pushed_stack_items=1, min_stack_height=6) + """ + DUP6(v1, v2, ..., v5, v6) = v6, v1, v2, ..., v5, v6 + ---- + + Description + ---- + Duplicate 6th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v5: ignored value + - v6: value to duplicate + + Outputs + ---- + - v6: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v5: ignored value + - v6: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#85](https://www.evm.codes/#85) + """ + + DUP7 = Opcode(0x86, pushed_stack_items=1, min_stack_height=7) + """ + DUP7(v1, v2, ..., v6, v7) = v7, v1, v2, ..., v6, v7 + ---- + + Description + ---- + Duplicate 7th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v6: ignored value + - v7: value to duplicate + + Outputs + ---- + - v7: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v6: ignored value + - v7: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#86](https://www.evm.codes/#86) + """ + + DUP8 = Opcode(0x87, pushed_stack_items=1, min_stack_height=8) + """ + DUP8(v1, v2, ..., v7, v8) = v8, v1, v2, ..., v7, v8 + ---- + + Description + ---- + Duplicate 8th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v7: ignored value + - v8: value to duplicate + + Outputs + ---- + - v8: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v7: ignored value + - v8: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#87](https://www.evm.codes/#87) + """ + + DUP9 = Opcode(0x88, pushed_stack_items=1, min_stack_height=9) + """ + DUP9(v1, v2, ..., v8, v9) = v9, v1, v2, ..., v8, v9 + ---- + + Description + ---- + Duplicate 9th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v8: ignored value + - v9: value to duplicate + + Outputs + ---- + - v9: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v8: ignored value + - v9: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#88](https://www.evm.codes/#88) + """ + DUP10 = Opcode(0x89, pushed_stack_items=1, min_stack_height=10) + """ + DUP10(v1, v2, ..., v9, v10) = v10, v1, v2, ..., v9, v10 + ---- + + Description + ---- + Duplicate 10th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v9: ignored value + - v10: value to duplicate + + Outputs + ---- + - v10: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v9: ignored value + - v10: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#89](https://www.evm.codes/#89) + """ + + DUP11 = Opcode(0x8A, pushed_stack_items=1, min_stack_height=11) + """ + DUP11(v1, v2, ..., v10, v11) = v11, v1, v2, ..., v10, v11 + ---- + + Description + ---- + Duplicate 11th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v10: ignored value + - v11: value to duplicate + + Outputs + ---- + - v11: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v10: ignored value + - v11: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#8A](https://www.evm.codes/#8A) + """ + + DUP12 = Opcode(0x8B, pushed_stack_items=1, min_stack_height=12) + """ + DUP12(v1, v2, ..., v11, v12) = v12, v1, v2, ..., v11, v12 + ---- + + Description + ---- + Duplicate 12th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v11: ignored value + - v12: value to duplicate + + Outputs + ---- + - v12: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v11: ignored value + - v12: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#8B](https://www.evm.codes/#8B) + """ + + DUP13 = Opcode(0x8C, pushed_stack_items=1, min_stack_height=13) + """ + DUP13(v1, v2, ..., v12, v13) = v13, v1, v2, ..., v12, v13 + ---- + + Description + ---- + Duplicate 13th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v12: ignored value + - v13: value to duplicate + + Outputs + ---- + - v13: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v12: ignored value + - v13: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#8C](https://www.evm.codes/#8C) + """ + + DUP14 = Opcode(0x8D, pushed_stack_items=1, min_stack_height=14) + """ + DUP14(v1, v2, ..., v13, v14) = v14, v1, v2, ..., v13, v14 + ---- + + Description + ---- + Duplicate 14th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v13: ignored value + - v14: value to duplicate + + Outputs + ---- + - v14: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v13: ignored value + - v14: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#8D](https://www.evm.codes/#8D) + """ + + DUP15 = Opcode(0x8E, pushed_stack_items=1, min_stack_height=15) + """ + DUP15(v1, v2, ..., v14, v15) = v15, v1, v2, ..., v14, v15 + ---- + + Description + ---- + Duplicate 15th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v14: ignored value + - v15: value to duplicate + + Outputs + ---- + - v15: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v14: ignored value + - v15: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#8E](https://www.evm.codes/#8E) + """ + + DUP16 = Opcode(0x8F, pushed_stack_items=1, min_stack_height=16) + """ + DUP16(v1, v2, ..., v15, v16) = v16, v1, v2, ..., v15, v16 + ---- + + Description + ---- + Duplicate 16th stack item + + Inputs + ---- + - v1: ignored value + - v2: ignored value + - ... + - v15: ignored value + - v16: value to duplicate + + Outputs + ---- + - v16: duplicated value + - v1: ignored value + - v2: ignored value + - ... + - v15: ignored value + - v16: original value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#8F](https://www.evm.codes/#8F) + """ + + SWAP1 = Opcode(0x90, min_stack_height=2) + """ + SWAP1(v1, v2) = v2, v1 + ---- + + Description + ---- + Exchange the top stack item with the second stack item. + + Inputs + ---- + - v1: value to swap + - v2: value to swap + + Outputs + ---- + - v1: swapped value + - v2: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#90](https://www.evm.codes/#90) + """ + + SWAP2 = Opcode(0x91, min_stack_height=3) + """ + SWAP2(v1, v2, v3) = v3, v2, v1 + ---- + + Description + ---- + Exchange 1st and 3rd stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - v3: value to swap + + Outputs + ---- + - v3: swapped value + - v2: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#91](https://www.evm.codes/#91) + """ + + SWAP3 = Opcode(0x92, min_stack_height=4) + """ + SWAP3(v1, v2, v3, v4) = v4, v2, v3, v1 + ---- + + Description + ---- + Exchange 1st and 4th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - v3: ignored value + - v4: value to swap + + Outputs + ---- + - v4: swapped value + - v2: ignored value + - v3: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#92](https://www.evm.codes/#92) + """ + + SWAP4 = Opcode(0x93, min_stack_height=5) + """ + SWAP4(v1, v2, ..., v4, v5) = v5, v2, ..., v4, v1 + ---- + + Description + ---- + Exchange 1st and 5th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v4: ignored value + - v5: value to swap + + Outputs + ---- + - v5: swapped value + - v2: ignored value + - ... + - v4: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#93](https://www.evm.codes/#93) + """ + + SWAP5 = Opcode(0x94, min_stack_height=6) + """ + SWAP5(v1, v2, ..., v5, v6) = v6, v2, ..., v5, v1 + ---- + + Description + ---- + Exchange 1st and 6th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v5: ignored value + - v6: value to swap + + Outputs + ---- + - v6: swapped value + - v2: ignored value + - ... + - v5: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#94](https://www.evm.codes/#94) + """ + + SWAP6 = Opcode(0x95, min_stack_height=7) + """ + SWAP6(v1, v2, ..., v6, v7) = v7, v2, ..., v6, v1 + ---- + + Description + ---- + Exchange 1st and 7th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v6: ignored value + - v7: value to swap + + Outputs + ---- + - v7: swapped value + - v2: ignored value + - ... + - v6: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#95](https://www.evm.codes/#95) + """ + + SWAP7 = Opcode(0x96, min_stack_height=8) + """ + SWAP7(v1, v2, ..., v7, v8) = v8, v2, ..., v7, v1 + ---- + + Description + ---- + Exchange 1st and 8th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v7: ignored value + - v8: value to swap + + Outputs + ---- + - v8: swapped value + - v2: ignored value + - ... + - v7: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#96](https://www.evm.codes/#96) + """ + + SWAP8 = Opcode(0x97, min_stack_height=9) + """ + SWAP8(v1, v2, ..., v8, v9) = v9, v2, ..., v8, v1 + ---- + + Description + ---- + Exchange 1st and 9th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v8: ignored value + - v9: value to swap + + Outputs + ---- + - v9: swapped value + - v2: ignored value + - ... + - v8: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#97](https://www.evm.codes/#97) + """ + + SWAP9 = Opcode(0x98, min_stack_height=10) + """ + SWAP9(v1, v2, ..., v9, v10) = v10, v2, ..., v9, v1 + ---- + + Description + ---- + Exchange 1st and 10th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v9: ignored value + - v10: value to swap + + Outputs + ---- + - v10: swapped value + - v2: ignored value + - ... + - v9: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#98](https://www.evm.codes/#98) + """ + + SWAP10 = Opcode(0x99, min_stack_height=11) + """ + SWAP10(v1, v2, ..., v10, v11) = v11, v2, ..., v10, v1 + ---- + + Description + ---- + Exchange 1st and 11th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v10: ignored value + - v11: value to swap + + Outputs + ---- + - v11: swapped value + - v2: ignored value + - ... + - v10: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#99](https://www.evm.codes/#99) + """ + + SWAP11 = Opcode(0x9A, min_stack_height=12) + """ + SWAP11(v1, v2, ..., v11, v12) = v12, v2, ..., v11, v1 + ---- + + Description + ---- + Exchange 1st and 12th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v11: ignored value + - v12: value to swap + + Outputs + ---- + - v12: swapped value + - v2: ignored value + - ... + - v11: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#9A](https://www.evm.codes/#9A) + """ + + SWAP12 = Opcode(0x9B, min_stack_height=13) + """ + SWAP12(v1, v2, ..., v12, v13) = v13, v2, ..., v12, v1 + ---- + + Description + ---- + Exchange 1st and 13th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v12: ignored value + - v13: value to swap + + Outputs + ---- + - v13: swapped value + - v2: ignored value + - ... + - v12: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#9B](https://www.evm.codes/#9B) + """ + + SWAP13 = Opcode(0x9C, min_stack_height=14) + """ + SWAP13(v1, v2, ..., v13, v14) = v14, v2, ..., v13, v1 + ---- + + Description + ---- + Exchange 1st and 14th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v13: ignored value + - v14: value to swap + + Outputs + ---- + - v14: swapped value + - v2: ignored value + - ... + - v13: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#9C](https://www.evm.codes/#9C) + """ + + SWAP14 = Opcode(0x9D, min_stack_height=15) + """ + SWAP14(v1, v2, ..., v14, v15) = v15, v2, ..., v14, v1 + ---- + + Description + ---- + Exchange 1st and 15th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v14: ignored value + - v15: value to swap + + Outputs + ---- + - v15: swapped value + - v2: ignored value + - ... + - v14: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#9D](https://www.evm.codes/#9D) + """ + + SWAP15 = Opcode(0x9E, min_stack_height=16) + """ + SWAP15(v1, v2, ..., v15, v16) = v16, v2, ..., v15, v1 + ---- + + Description + ---- + Exchange 1st and 16th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v15: ignored value + - v16: value to swap + + Outputs + ---- + - v16: swapped value + - v2: ignored value + - ... + - v15: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#9E](https://www.evm.codes/#9E) + """ + + SWAP16 = Opcode(0x9F, min_stack_height=17) + """ + SWAP16(v1, v2, ..., v16, v17) = v17, v2, ..., v16, v1 + ---- + + Description + ---- + Exchange 1st and 17th stack items + + Inputs + ---- + - v1: value to swap + - v2: ignored value + - ... + - v16: ignored value + - v17: value to swap + + Outputs + ---- + - v17: swapped value + - v2: ignored value + - ... + - v16: ignored value + - v1: swapped value + + Fork + ---- + Frontier + + Gas + ---- + 3 + + Source: [evm.codes/#9F](https://www.evm.codes/#9F) + """ + + LOG0 = Opcode(0xA0, popped_stack_items=2, kwargs=["offset", "size"]) + """ + LOG0(offset, size) + ---- + + Description + ---- + Append log record with no topics + + Inputs + ---- + - offset: byte offset in the memory in bytes + - size: byte size to copy + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 375 + - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost + + Source: [evm.codes/#A0](https://www.evm.codes/#A0) + """ + + LOG1 = Opcode(0xA1, popped_stack_items=3, kwargs=["offset", "size", "topic_1"]) + """ + LOG1(offset, size, topic_1) + ---- + + Description + ---- + Append log record with one topic + + Inputs + ---- + - offset: byte offset in the memory in bytes + - size: byte size to copy + - topic_1: 32-byte value + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 375 + - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost + + Source: [evm.codes/#A1](https://www.evm.codes/#A1) + """ + + LOG2 = Opcode(0xA2, popped_stack_items=4, kwargs=["offset", "size", "topic_1", "topic_2"]) + """ + LOG2(offset, size, topic_1, topic_2) + ---- + + Description + ---- + Append log record with two topics + + Inputs + ---- + - offset: byte offset in the memory in bytes + - size: byte size to copy + - topic_1: 32-byte value + - topic_2: 32-byte value + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 375 + - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost + + Source: [evm.codes/#A2](https://www.evm.codes/#A2) + """ + + LOG3 = Opcode( + 0xA3, popped_stack_items=5, kwargs=["offset", "size", "topic_1", "topic_2", "topic_3"] + ) + """ + LOG3(offset, size, topic_1, topic_2, topic_3) + ---- + + Description + ---- + Append log record with three topics + + Inputs + ---- + - offset: byte offset in the memory in bytes + - size: byte size to copy + - topic_1: 32-byte value + - topic_2: 32-byte value + - topic_3: 32-byte value + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 375 + - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost + + Source: [evm.codes/#A3](https://www.evm.codes/#A3) + """ + + LOG4 = Opcode( + 0xA4, + popped_stack_items=6, + kwargs=["offset", "size", "topic_1", "topic_2", "topic_3", "topic_4"], + ) + """ + LOG4(offset, size, topic_1, topic_2, topic_3, topic_4) + ---- + + Description + ---- + Append log record with four topics + + Inputs + ---- + - offset: byte offset in the memory in bytes + - size: byte size to copy + - topic_1: 32-byte value + - topic_2: 32-byte value + - topic_3: 32-byte value + - topic_4: 32-byte value + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 375 + - dynamic_gas = 375 * topic_count + 8 * size + memory_expansion_cost + + Source: [evm.codes/#A4](https://www.evm.codes/#A4) + """ + + RJUMP = Opcode(0xE0, data_portion_length=2) + """ + !!! Note: This opcode is under development + + RJUMP() + ---- + + Description + ---- + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + EOF Fork + + Gas + ---- + + Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) + """ + + DATALOAD = Opcode(0xD0, popped_stack_items=1, kwargs=["offset"]) + """ + !!! Note: This opcode is under development + + DATALOAD(offset) + ---- + + Description + ---- + Reads 32 bytes of data at offset onto the stack + + Inputs + ---- + - offset: offset within the data section to start copying + + Outputs + ---- + none + + Fork + ---- + EOF Fork + + Gas + ---- + 4 + + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + """ + + DATALOADN = Opcode(0xD1, pushed_stack_items=1, data_portion_length=2) + """ + !!! Note: This opcode is under development + + DATALOADN() + ---- + + Description + ---- + Reads 32 bytes of data at offset onto the stack + + Immediates + ---- + 2 bytes forming a UInt16, which is the offset into the data section. + + Inputs + ---- + none + + Outputs + ---- + none + + Fork + ---- + EOF Fork + + Gas + ---- + 3 + + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + """ + + DATASIZE = Opcode(0xD2, pushed_stack_items=1) + """ + !!! Note: This opcode is under development + + DATASIZE() + ---- + + Description + ---- + Returns the size of the data section + + Inputs + ---- + + Outputs + ---- + The size of the data section. If there is no data section, returns 0. + + Fork + ---- + EOF Fork + + Gas + ---- + 2 + + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + """ + + DATACOPY = Opcode(0xD3, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) + """ + !!! Note: This opcode is under development + + DATACOPY(dest_offset, offset, size) + ---- + + Description + ---- + Copies data from the data section into call frame memory + + Inputs + ---- + - dest_offset: The offset within the memory section to start copying to + - offset: The offset within the data section to start copying from + - size: The number of bytes to copy + + Outputs + ---- + none + + Fork + ---- + EOF Fork + + Gas + ---- + - minimum_word_size = (size + 31) / 32 + - static_gas = 3 + - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + """ + + RJUMPI = Opcode(0xE1, popped_stack_items=1, data_portion_length=2) + """ + !!! Note: This opcode is under development + + RJUMPI() + ---- + + Description + ---- + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + EOF Fork + + Gas + ---- + + Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) + """ + + RJUMPV = Opcode( + 0xE2, + popped_stack_items=1, + data_portion_formatter=_rjumpv_encoder, + ) + """ + !!! Note: This opcode is under development + + RJUMPV() + ---- + + Description + ---- + Relative jump with variable offset. + + When calling this opcode to generate bytecode, the first argument is used to format the data + portion of the opcode, and it can be either of two types: + - A bytes type, and in this instance the bytes are used verbatim as the data portion. + - An integer iterable, list or tuple or any other iterable, where each element is a + jump offset. + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + EOF Fork + + Gas + ---- + + Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) + """ + + CALLF = Opcode(0xE3, data_portion_length=2, unchecked_stack=True) + """ + !!! Note: This opcode is under development + + CALLF() + ---- + + Description + ---- + + - deduct 5 gas + - read uint16 operand idx + - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in + an exceptional halt + - if 1024 <= len(return_stack), execution results in an exceptional halt + - push new element to return_stack (current_code_idx, pc+3) + - update current_code_idx to idx and set pc to 0 + + Inputs + ---- + Any: The inputs are not checked because we cannot know how many inputs the callee + function/section requires + + Outputs + ---- + Any: The outputs are variable because we cannot know how many outputs the callee + function/section produces + + Fork + ---- + EOF Fork + + Gas + ---- + 5 + + Source: + [ipsilon/eof/blob/main/spec/eof.md](https://github.com/ipsilon/eof/blob/main/spec/eof.md) + """ + + RETF = Opcode(0xE4) + """ + !!! Note: This opcode is under development + + RETF() + ---- + + Description + ---- + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + EOF Fork + + Gas + ---- + 3 + """ + + JUMPF = Opcode(0xE5, data_portion_length=2) + """ + !!! Note: This opcode is under development + + JUMPF() + ---- + + Description + ---- + + - deduct 5 gas + - read uint16 operand idx + - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in + an exceptional halt + - set current_code_idx to idx + - set pc = 0 + + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + EOF Fork + + Gas + ---- + 5 + + """ + + DUPN = Opcode( + 0xE6, + pushed_stack_items=1, + data_portion_length=1, + stack_properties_modifier=_dupn_stack_properties_modifier, + ) + """ + !!! Note: This opcode is under development + + DUPN() + ---- + + Description + ---- + + - deduct 3 gas + - read uint8 operand imm + - n = imm + 1 + - n‘th (1-based) stack item is duplicated at the top of the stack + - Stack validation: stack_height >= n + + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + EOF Fork + + Gas + ---- + + """ + + SWAPN = Opcode( + 0xE7, data_portion_length=1, stack_properties_modifier=_swapn_stack_properties_modifier + ) + """ + !!! Note: This opcode is under development + + SWAPN() + ---- + + Description + ---- + + - deduct 3 gas + - read uint8 operand imm + - n = imm + 1 + - n + 1th stack item is swapped with the top stack item (1-based). + - Stack validation: stack_height >= n + 1 + + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + EOF Fork + + Gas + ---- + + """ + + EXCHANGE = Opcode( + 0xE8, + data_portion_formatter=_exchange_encoder, + stack_properties_modifier=_exchange_stack_properties_modifier, + ) + """ + !!! Note: This opcode is under development + + EXCHANGE[x, y] + ---- + + Description + ---- + Exchanges two stack positions. Two nybbles, n is high 4 bits + 1, then m is 4 low bits + 1. + Exchanges tne n+1'th item with the n + m + 1 item. + + Inputs x and y when the opcode is used as `EXCHANGE[x, y]`, are equal to: + - x = n + 1 + - y = n + m + 1 + Which each equals to 1-based stack positions swapped. + + Inputs + ---- + n + m + 1, or ((imm >> 4) + (imm &0x0F) + 3) from the raw immediate, + + Outputs + ---- + n + m + 1, or ((imm >> 4) + (imm &0x0F) + 3) from the raw immediate, + + Fork + ---- + EOF_FORK + + Gas + ---- + 3 + + """ + + EOFCREATE = Opcode( + 0xEC, + popped_stack_items=4, + pushed_stack_items=1, + data_portion_length=1, + kwargs=["value", "salt", "input_offset", "input_size"], + ) + """ + !!! Note: This opcode is under development + + EOFCREATE[initcontainer_index](value, salt, input_offset, input_size) + ---- + + Description + ---- + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + + Gas + ---- + + """ + + RETURNCONTRACT = Opcode(0xEE, popped_stack_items=2, data_portion_length=1) + """ + !!! Note: This opcode is under development + + RETURNCONTRACT() + ---- + + Description + ---- + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + + Gas + ---- + + """ + + CREATE = Opcode( + 0xF0, popped_stack_items=3, pushed_stack_items=1, kwargs=["value", "offset", "size"] + ) + """ + CREATE(value, offset, size) = address + ---- + + Description + ---- + Create a new contract with the given code + + Inputs + ---- + - value: value in wei to send to the new account + - offset: byte offset in the memory in bytes, the initialization code for the new account + - size: byte size to copy (size of the initialization code) + + Outputs + ---- + - address: the address of the deployed contract, 0 if the deployment failed + + Fork + ---- + Frontier + + Gas + ---- + ``` + minimum_word_size = (size + 31) / 32 + init_code_cost = 2 * minimum_word_size + code_deposit_cost = 200 * deployed_code_size + + static_gas = 32000 + dynamic_gas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + + code_deposit_cost + ``` + + Source: [evm.codes/#F0](https://www.evm.codes/#F0) + """ + + CALL = Opcode( + 0xF1, + popped_stack_items=7, + pushed_stack_items=1, + kwargs=["gas", "address", "value", "args_offset", "args_size", "ret_offset", "ret_size"], + kwargs_defaults={"gas": GAS}, + ) + """ + CALL(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success + ---- + + Description + ---- + Message-call into an account + + Inputs + ---- + - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub + context is returned to this one + - address: the account which context to execute + - value: value in wei to send to the account + - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_size: byte size to copy (size of the calldata) + - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub + context + - ret_size: byte size to copy (size of the return data) + + Outputs + ---- + - success: return 0 if the sub context reverted, 1 otherwise + + Fork + ---- + Frontier + + Gas + ---- + ``` + static_gas = 0 + dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + + positive_value_cost + value_to_empty_account_cost + ``` + + Source: [evm.codes/#F1](https://www.evm.codes/#F1) + """ + + CALLCODE = Opcode( + 0xF2, + popped_stack_items=7, + pushed_stack_items=1, + kwargs=["gas", "address", "value", "args_offset", "args_size", "ret_offset", "ret_size"], + kwargs_defaults={"gas": GAS}, + ) + """ + CALLCODE(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success + ---- + + Description + ---- + Message-call into this account with an alternative account's code. Executes code starting at + the address to which the call is made. + + Inputs + ---- + - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub + context is returned to this one + - address: the account which code to execute + - value: value in wei to send to the account + - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_size: byte size to copy (size of the calldata) + - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub + context + - ret_size: byte size to copy (size of the return data) + + Outputs + ---- + - success: return 0 if the sub context reverted, 1 otherwise + + Fork + ---- + Frontier + + Gas + ---- + ``` + static_gas = 0 + dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + + positive_value_cost + ``` + + Source: [evm.codes/#F2](https://www.evm.codes/#F2) + """ + + RETURN = Opcode(0xF3, popped_stack_items=2, kwargs=["offset", "size"]) + """ + RETURN(offset, size) + ---- + + Description + ---- + Halt execution returning output data + + Inputs + ---- + - offset: byte offset in the memory in bytes, to copy what will be the return data of this + context + - size: byte size to copy (size of the return data) + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + - static_gas = 0 + - dynamic_gas = memory_expansion_cost + + Source: [evm.codes/#F3](https://www.evm.codes/#F3) + """ + + DELEGATECALL = Opcode( + 0xF4, + popped_stack_items=6, + pushed_stack_items=1, + kwargs=["gas", "address", "args_offset", "args_size", "ret_offset", "ret_size"], + kwargs_defaults={"gas": GAS}, + ) + """ + DELEGATECALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success + ---- + + Description + ---- + Message-call into this account with an alternative account's code, but persisting the current + values for sender and value + + Inputs + ---- + - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub + context is returned to this one + - address: the account which code to execute + - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_size: byte size to copy (size of the calldata) + - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub + context + - ret_size: byte size to copy (size of the return data) + + Outputs + ---- + - success: return 0 if the sub context reverted, 1 otherwise + + Fork + ---- + Byzantium + + Gas + ---- + - static_gas = 0 + - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + + Source: [evm.codes/#F4](https://www.evm.codes/#F4) + """ + + CREATE2 = Opcode( + 0xF5, + popped_stack_items=4, + pushed_stack_items=1, + kwargs=["value", "offset", "size", "salt"], + ) + """ + CREATE2(value, offset, size, salt) = address + ---- + + Description + ---- + Creates a new contract + + Inputs + ---- + - value: value in wei to send to the new account + - offset: byte offset in the memory in bytes, the initialization code of the new account + - size: byte size to copy (size of the initialization code) + - salt: 32-byte value used to create the new account at a deterministic address + + Outputs + ---- + - address: the address of the deployed contract, 0 if the deployment failed + + Fork + ---- + Constantinople + + Gas + ---- + ``` + minimum_word_size = (size + 31) / 32 + init_code_cost = 2 * minimum_word_size + hash_cost = 6 * minimum_word_size + code_deposit_cost = 200 * deployed_code_size + + static_gas = 32000 + dynamic_gas = init_code_cost + hash_cost + memory_expansion_cost + + deployment_code_execution_cost + code_deposit_cost + ``` + + Source: [evm.codes/#F5](https://www.evm.codes/#F5) + """ + + EXTCALL = Opcode( + 0xF8, + popped_stack_items=4, + pushed_stack_items=1, + kwargs=["address", "args_offset", "args_size", "value"], + ) + """ + EXTCALL(address, args_offset, args_size, value) = address + ---- + + Description + ---- + Message-call into an account + + Inputs + ---- + - address: the account which context to execute + - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_size: byte size to copy (size of the calldata) + - value: value in wei to send to the account + + Outputs + ---- + - success: + - `0` if the call was successful. + - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). + - `2` if the call has failed. + + Fork + ---- + Prague + + Gas + ---- + ``` + static_gas = 0 + dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + + positive_value_cost + value_to_empty_account_cost + ``` + + Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) + """ + + EXTDELEGATECALL = Opcode( + 0xF9, + popped_stack_items=3, + pushed_stack_items=1, + kwargs=["address", "args_offset", "args_size"], + ) + """ + EXTDELEGATECALL(address, args_offset, args_size) = address + ---- + + Description + ---- + Message-call into this account with an alternative account's code, but persisting the current + values for sender and value + + Inputs + ---- + - address: the account which context to execute + - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_size: byte size to copy (size of the calldata) + + Outputs + ---- + - success: + - `0` if the call was successful. + - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). + - `2` if the call has failed. + + Fork + ---- + Prague + + Gas + ---- + - static_gas = 0 + - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + + Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) + """ + + STATICCALL = Opcode( + 0xFA, + popped_stack_items=6, + pushed_stack_items=1, + kwargs=["gas", "address", "args_offset", "args_size", "ret_offset", "ret_size"], + kwargs_defaults={"gas": GAS}, + ) + """ + STATICCALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success + ---- + + Description + ---- + Static message-call into an account + + Inputs + ---- + - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub + context is returned to this one + - address: the account which context to execute + - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_size: byte size to copy (size of the calldata) + - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub + context + - ret_size: byte size to copy (size of the return data) + + Outputs + ---- + - success: return 0 if the sub context reverted, 1 otherwise + + Fork + ---- + Byzantium + + Gas + ---- + - static_gas = 0 + - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + + Source: [evm.codes/#FA](https://www.evm.codes/#FA) + """ + + EXTSTATICCALL = Opcode( + 0xFB, + popped_stack_items=3, + pushed_stack_items=1, + kwargs=["address", "args_offset", "args_size"], + ) + """ + EXTSTATICCALL(address, args_offset, args_size) = address + ---- + + Description + ---- + Static message-call into an account + + Inputs + ---- + - address: the account which context to execute + - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_size: byte size to copy (size of the calldata) + + Outputs + ---- + - success: + - `0` if the call was successful. + - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). + - `2` if the call has failed. + + Fork + ---- + Prague + + Gas + ---- + - static_gas = 0 + - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + + Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) + """ + + RETURNDATALOAD = Opcode(0xF7, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"]) + """ + RETURNDATALOAD(offset) + ---- + + Description + ---- + Copy 32 bytes from returndata at offset onto the stack + + Inputs + ---- + - offset: byte offset in the return data from the last executed sub context to copy + + Fork + ---- + EOF + + Gas + ---- + 3 + """ + + REVERT = Opcode(0xFD, popped_stack_items=2, kwargs=["offset", "size"]) + """ + REVERT(offset, size) + ---- + + Description + ---- + Halt execution reverting state changes but returning data and remaining gas + + Inputs + ---- + - offset: byte offset in the memory in bytes. The return data of the calling context + - size: byte size to copy (size of the return data) + + Fork + ---- + Byzantium + + Gas + ---- + static_gas = 0 + dynamic_gas = memory_expansion_cost + + Source: [evm.codes/#FD](https://www.evm.codes/#FD) + """ + + INVALID = Opcode(0xFE) + """ + INVALID() + ---- + + Description + ---- + Designated invalid instruction + + Inputs + ---- + None + + Outputs + ---- + None + + Fork + ---- + Frontier + + Gas + ---- + All the remaining gas in this context is consumed + + Source: [evm.codes/#FE](https://www.evm.codes/#FE) + """ + + SELFDESTRUCT = Opcode(0xFF, popped_stack_items=1, kwargs=["address"]) + """ + SELFDESTRUCT(address) + ---- + + Description + ---- + Halt execution and register the account for later deletion + + Inputs + ---- + - address: account to send the current balance to + + Fork + ---- + Frontier + + Gas + ---- + 5000 + + Source: [evm.codes/#FF](https://www.evm.codes/#FF) + """ + + +_push_opcodes_byte_list: List[Opcode] = [ + Opcodes.PUSH1, + Opcodes.PUSH2, + Opcodes.PUSH3, + Opcodes.PUSH4, + Opcodes.PUSH5, + Opcodes.PUSH6, + Opcodes.PUSH7, + Opcodes.PUSH8, + Opcodes.PUSH9, + Opcodes.PUSH10, + Opcodes.PUSH11, + Opcodes.PUSH12, + Opcodes.PUSH13, + Opcodes.PUSH14, + Opcodes.PUSH15, + Opcodes.PUSH16, + Opcodes.PUSH17, + Opcodes.PUSH18, + Opcodes.PUSH19, + Opcodes.PUSH20, + Opcodes.PUSH21, + Opcodes.PUSH22, + Opcodes.PUSH23, + Opcodes.PUSH24, + Opcodes.PUSH25, + Opcodes.PUSH26, + Opcodes.PUSH27, + Opcodes.PUSH28, + Opcodes.PUSH29, + Opcodes.PUSH30, + Opcodes.PUSH31, + Opcodes.PUSH32, +] + + +def _mstore_operation(data: OpcodeCallArg = b"", offset: OpcodeCallArg = 0) -> Bytecode: + """ + Helper function to generate the bytecode that stores an arbitrary amount of data in memory. + """ + assert isinstance(offset, int) + if isinstance(data, int): + data = data.to_bytes(32, "big") + data = to_bytes(data) # type: ignore + bytecode = Bytecode() + for i in range(0, len(data), 32): + chunk = data[i : i + 32] + if len(chunk) == 32: + bytecode += Opcodes.MSTORE(offset, chunk) + else: + # We need to MLOAD the existing data at the offset and then do a bitwise OR with the + # new data to store it in memory. + bytecode += Opcodes.MLOAD(offset) + # Create a mask to zero out the leftmost bytes of the existing data. + mask_size = 32 - len(chunk) + bytecode += _push_opcodes_byte_list[mask_size - 1][-1] + bytecode += Opcodes.AND + bytecode += Opcodes.PUSH32[chunk.ljust(32, b"\x00")] + bytecode += Opcodes.OR + bytecode += _stack_argument_to_bytecode(offset) + bytecode += Opcodes.MSTORE + offset += len(chunk) + return bytecode + + +class Macros(Macro, Enum): + """ + Enum containing all macros. + """ + + OOG = Macro(Opcodes.SHA3(0, 100000000000)) + """ + OOG() + ---- + + Halt execution by consuming all available gas. + + Inputs + ---- + - None. Any input arguments are ignored. + + Outputs + ---- + - None + + Fork + ---- + Frontier + + Gas + ---- + `SHA3(0, 100000000000)` results in 19073514453125027 gas used and an OOG + exception. + + Note: + If a value > `100000000000` is used as second argument, the resulting geth + trace reports gas `30` and an OOG exception. + `SHA3(0, SUB(0, 1))` causes a gas > u64 exception and an OOG exception. + + Bytecode + ---- + SHA3(0, 100000000000) + """ + + MSTORE = Macro(lambda_operation=_mstore_operation) + """ + MSTORE(data, offset) + ---- + + Place data of arbitrary length into memory at a given offset. + + Inputs + ---- + - data: The data to store in memory. Can be an integer or bytes. + - offset: The offset in memory to store the data. + + Outputs + ---- + - None + """ + + +class UndefinedOpcodes(Opcode, Enum): + """ + Enum containing all unknown opcodes (88 at the moment). + """ + + OPCODE_0C = Opcode(0x0C) + OPCODE_0D = Opcode(0x0D) + OPCODE_0E = Opcode(0x0E) + OPCODE_0F = Opcode(0x0F) + OPCODE_1E = Opcode(0x1E) + OPCODE_1F = Opcode(0x1F) + OPCODE_21 = Opcode(0x21) + OPCODE_22 = Opcode(0x22) + OPCODE_23 = Opcode(0x23) + OPCODE_24 = Opcode(0x24) + OPCODE_25 = Opcode(0x25) + OPCODE_26 = Opcode(0x26) + OPCODE_27 = Opcode(0x27) + OPCODE_28 = Opcode(0x28) + OPCODE_29 = Opcode(0x29) + OPCODE_2A = Opcode(0x2A) + OPCODE_2B = Opcode(0x2B) + OPCODE_2C = Opcode(0x2C) + OPCODE_2D = Opcode(0x2D) + OPCODE_2E = Opcode(0x2E) + OPCODE_2F = Opcode(0x2F) + OPCODE_4B = Opcode(0x4B) + OPCODE_4C = Opcode(0x4C) + OPCODE_4D = Opcode(0x4D) + OPCODE_4E = Opcode(0x4E) + OPCODE_4F = Opcode(0x4F) + OPCODE_A5 = Opcode(0xA5) + OPCODE_A6 = Opcode(0xA6) + OPCODE_A7 = Opcode(0xA7) + OPCODE_A8 = Opcode(0xA8) + OPCODE_A9 = Opcode(0xA9) + OPCODE_AA = Opcode(0xAA) + OPCODE_AB = Opcode(0xAB) + OPCODE_AC = Opcode(0xAC) + OPCODE_AD = Opcode(0xAD) + OPCODE_AE = Opcode(0xAE) + OPCODE_AF = Opcode(0xAF) + OPCODE_B0 = Opcode(0xB0) + OPCODE_B1 = Opcode(0xB1) + OPCODE_B2 = Opcode(0xB2) + OPCODE_B3 = Opcode(0xB3) + OPCODE_B4 = Opcode(0xB4) + OPCODE_B5 = Opcode(0xB5) + OPCODE_B6 = Opcode(0xB6) + OPCODE_B7 = Opcode(0xB7) + OPCODE_B8 = Opcode(0xB8) + OPCODE_B9 = Opcode(0xB9) + OPCODE_BA = Opcode(0xBA) + OPCODE_BB = Opcode(0xBB) + OPCODE_BC = Opcode(0xBC) + OPCODE_BD = Opcode(0xBD) + OPCODE_BE = Opcode(0xBE) + OPCODE_BF = Opcode(0xBF) + OPCODE_C0 = Opcode(0xC0) + OPCODE_C1 = Opcode(0xC1) + OPCODE_C2 = Opcode(0xC2) + OPCODE_C3 = Opcode(0xC3) + OPCODE_C4 = Opcode(0xC4) + OPCODE_C5 = Opcode(0xC5) + OPCODE_C6 = Opcode(0xC6) + OPCODE_C7 = Opcode(0xC7) + OPCODE_C8 = Opcode(0xC8) + OPCODE_C9 = Opcode(0xC9) + OPCODE_CA = Opcode(0xCA) + OPCODE_CB = Opcode(0xCB) + OPCODE_CC = Opcode(0xCC) + OPCODE_CD = Opcode(0xCD) + OPCODE_CE = Opcode(0xCE) + OPCODE_CF = Opcode(0xCF) + OPCODE_D4 = Opcode(0xD4) + OPCODE_D5 = Opcode(0xD5) + OPCODE_D6 = Opcode(0xD6) + OPCODE_D7 = Opcode(0xD7) + OPCODE_D8 = Opcode(0xD8) + OPCODE_D9 = Opcode(0xD9) + OPCODE_DA = Opcode(0xDA) + OPCODE_DB = Opcode(0xDB) + OPCODE_DC = Opcode(0xDC) + OPCODE_DD = Opcode(0xDD) + OPCODE_DE = Opcode(0xDE) + OPCODE_DF = Opcode(0xDF) + OPCODE_E9 = Opcode(0xE9) + OPCODE_EA = Opcode(0xEA) + OPCODE_EB = Opcode(0xEB) + OPCODE_ED = Opcode(0xED) + OPCODE_EF = Opcode(0xEF) + OPCODE_F6 = Opcode(0xF6) + OPCODE_FC = Opcode(0xFC) diff --git a/src/ethereum_test_vm/py.typed b/src/ethereum_test_vm/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ethereum_test_vm/tests/__init__.py b/src/ethereum_test_vm/tests/__init__.py new file mode 100644 index 0000000000..0c5cdf9b13 --- /dev/null +++ b/src/ethereum_test_vm/tests/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for the ethereum_test_vm package. +""" diff --git a/src/ethereum_test_tools/tests/test_vm.py b/src/ethereum_test_vm/tests/test_vm.py similarity index 98% rename from src/ethereum_test_tools/tests/test_vm.py rename to src/ethereum_test_vm/tests/test_vm.py index 6b0a60ec05..562190f176 100644 --- a/src/ethereum_test_tools/tests/test_vm.py +++ b/src/ethereum_test_vm/tests/test_vm.py @@ -1,13 +1,14 @@ """ -Test suite for `ethereum_test_tools.vm` module. +Test suite for `ethereum_test_vm` module. """ import pytest -from ..common.base_types import Address -from ..vm.opcode import Bytecode -from ..vm.opcode import Macros as Om -from ..vm.opcode import Opcodes as Op +from ethereum_test_base_types import Address + +from ..opcode import Bytecode +from ..opcode import Macros as Om +from ..opcode import Opcodes as Op @pytest.mark.parametrize( diff --git a/src/evm_transition_tool/__init__.py b/src/evm_transition_tool/__init__.py index 5b494b3884..6d9937fad9 100644 --- a/src/evm_transition_tool/__init__.py +++ b/src/evm_transition_tool/__init__.py @@ -7,12 +7,8 @@ from .execution_specs import ExecutionSpecsTransitionTool from .geth import GethTransitionTool from .nimbus import NimbusTransitionTool -from .transition_tool import ( - FixtureFormats, - TransitionTool, - TransitionToolNotFoundInPath, - UnknownTransitionTool, -) +from .transition_tool import TransitionTool, TransitionToolNotFoundInPath, UnknownTransitionTool +from .types import Result, TransitionToolOutput TransitionTool.set_default_tool(GethTransitionTool) @@ -20,10 +16,11 @@ "BesuTransitionTool", "EvmOneTransitionTool", "ExecutionSpecsTransitionTool", - "FixtureFormats", "GethTransitionTool", "NimbusTransitionTool", + "Result", "TransitionTool", + "TransitionToolOutput", "TransitionToolNotFoundInPath", "UnknownTransitionTool", ) diff --git a/src/evm_transition_tool/besu.py b/src/evm_transition_tool/besu.py index 5c38f76d01..86f226a4bc 100644 --- a/src/evm_transition_tool/besu.py +++ b/src/evm_transition_tool/besu.py @@ -10,13 +10,15 @@ import textwrap from pathlib import Path from re import compile -from typing import Any, Dict, List, Optional +from typing import List, Optional import requests from ethereum_test_forks import Fork +from ethereum_test_types import Alloc, Environment, Transaction -from .transition_tool import TransitionTool, dump_files_to_directory +from .transition_tool import TransitionTool, dump_files_to_directory, model_dump_config +from .types import TransitionToolInput, TransitionToolOutput class BesuTransitionTool(TransitionTool): @@ -92,29 +94,35 @@ def shutdown(self): def evaluate( self, - alloc: Any, - txs: Any, - env: Any, - fork_name: str, + *, + alloc: Alloc, + txs: List[Transaction], + env: Environment, + fork: Fork, chain_id: int = 1, reward: int = 0, eips: Optional[List[int]] = None, debug_output_path: str = "", - ) -> Dict[str, Any]: + ) -> TransitionToolOutput: """ Executes `evm t8n` with the specified arguments. """ if not self.process: self.start_server() + fork_name = fork.transition_tool_name( + block_number=env.number, + timestamp=env.timestamp, + ) if eips is not None: fork_name = "+".join([fork_name] + [str(eip) for eip in eips]) - input_json = { - "alloc": alloc, - "txs": txs, - "env": env, - } + input_json = TransitionToolInput( + alloc=alloc, + txs=txs, + env=env, + ).model_dump(mode="json", **model_dump_config) + state_json = { "fork": fork_name, "chainid": chain_id, @@ -151,7 +159,7 @@ def evaluate( response = requests.post(self.server_url, json=post_data, timeout=5) response.raise_for_status() # exception visible in pytest failure output - output = response.json() + output: TransitionToolOutput = TransitionToolOutput.model_validate(response.json()) if debug_output_path: dump_files_to_directory( @@ -168,28 +176,23 @@ def evaluate( f"t8n-server returned status code {response.status_code}, " f"response: {response.text}" ) - if not all([x in output for x in ["alloc", "result", "body"]]): - raise Exception( - "Malformed t8n output: missing 'alloc', 'result' or 'body', server response: " - f"{response.text}" - ) if debug_output_path: dump_files_to_directory( debug_output_path, { - "output/alloc.json": output["alloc"], - "output/result.json": output["result"], - "output/txs.rlp": output["body"], + "output/alloc.json": output.alloc.model_dump(mode="json", **model_dump_config), + "output/result.json": output.result.model_dump( + mode="json", **model_dump_config + ), + "output/txs.rlp": str(output.body), }, ) if self.trace and self.besu_trace_dir: - self.collect_traces( - output["result"]["receipts"], self.besu_trace_dir, debug_output_path - ) - for i, r in enumerate(output["result"]["receipts"]): - trace_file_name = f"trace-{i}-{r['transactionHash']}.jsonl" + self.collect_traces(output.result.receipts, self.besu_trace_dir, debug_output_path) + for i, r in enumerate(output.result.receipts): + trace_file_name = f"trace-{i}-{r.transaction_hash}.jsonl" os.remove(os.path.join(self.besu_trace_dir.name, trace_file_name)) return output diff --git a/src/evm_transition_tool/tests/fixtures/1/exp.json b/src/evm_transition_tool/tests/fixtures/1/exp.json index dc2eebe8e0..f3a4d02aa6 100644 --- a/src/evm_transition_tool/tests/fixtures/1/exp.json +++ b/src/evm_transition_tool/tests/fixtures/1/exp.json @@ -2,14 +2,21 @@ "alloc": { "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { "balance": "0xfeed1a9d", - "nonce": "0x1" + "nonce": "0x01", + "code": "0x", + "storage": {} }, "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { "balance": "0x5ffd4878be161d74", - "nonce": "0xac" + "nonce": "0xac", + "code": "0x", + "storage": {} }, "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xa410" + "balance": "0xa410", + "nonce": "0x00", + "code": "0x", + "storage": {} } }, "result": { @@ -24,18 +31,16 @@ "status": "0x1", "cumulativeGasUsed": "0x5208", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", "contractAddress": "0x0000000000000000000000000000000000000000", "gasUsed": "0x5208", - "effectiveGasPrice": null, "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "transactionIndex": "0x0" } ], "rejected": [ { - "index": 1, + "index": "0x1", "error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1" } ], diff --git a/src/evm_transition_tool/tests/fixtures/1/txs.json b/src/evm_transition_tool/tests/fixtures/1/txs.json index 50b31ff31b..527e842a90 100644 --- a/src/evm_transition_tool/tests/fixtures/1/txs.json +++ b/src/evm_transition_tool/tests/fixtures/1/txs.json @@ -1,6 +1,6 @@ [ { - "gas": "0x5208", + "gasLimit": "0x5208", "gasPrice": "0x2", "hash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", "input": "0x", @@ -12,7 +12,7 @@ "value": "0x1" }, { - "gas": "0x5208", + "gasLimit": "0x5208", "gasPrice": "0x2", "hash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", "input": "0x", diff --git a/src/evm_transition_tool/tests/fixtures/3/exp.json b/src/evm_transition_tool/tests/fixtures/3/exp.json index 57e63cea85..6238b76ecb 100644 --- a/src/evm_transition_tool/tests/fixtures/3/exp.json +++ b/src/evm_transition_tool/tests/fixtures/3/exp.json @@ -2,14 +2,21 @@ "alloc": { "0x095e7baea6a6c7c4c2dfeb977efac326af552d87": { "code": "0x600140", - "balance": "0xde0b6b3a76586a0" + "balance": "0x0de0b6b3a76586a0", + "nonce": "0x00", + "storage": {} }, "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { - "balance": "0x521f" + "code": "0x", + "balance": "0x521f", + "nonce": "0x00", + "storage": {} }, "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xde0b6b3a7622741", - "nonce": "0x1" + "code": "0x", + "balance": "0x0de0b6b3a7622741", + "nonce": "0x01", + "storage": {} } }, "result": { @@ -18,17 +25,16 @@ "receiptsRoot": "0xd0d26df80374a327c025d405ebadc752b1bbd089d864801ae78ab704bcad8086", "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "rejected": [], "receipts": [ { "root": "0x", "status": "0x1", "cumulativeGasUsed": "0x521f", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, "transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81", "contractAddress": "0x0000000000000000000000000000000000000000", "gasUsed": "0x521f", - "effectiveGasPrice": null, "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "transactionIndex": "0x0" } diff --git a/src/evm_transition_tool/tests/fixtures/3/txs.json b/src/evm_transition_tool/tests/fixtures/3/txs.json index 3044458588..00015e78f3 100644 --- a/src/evm_transition_tool/tests/fixtures/3/txs.json +++ b/src/evm_transition_tool/tests/fixtures/3/txs.json @@ -1,7 +1,7 @@ [ { "input" : "0x", - "gas" : "0x5f5e100", + "gasLimit" : "0x5f5e100", "gasPrice" : "0x1", "nonce" : "0x0", "to" : "0x095e7baea6a6c7c4c2dfeb977efac326af552d87", diff --git a/src/evm_transition_tool/tests/test_evaluate.py b/src/evm_transition_tool/tests/test_evaluate.py index 67255f249a..b72996100e 100644 --- a/src/evm_transition_tool/tests/test_evaluate.py +++ b/src/evm_transition_tool/tests/test_evaluate.py @@ -2,12 +2,14 @@ import os from pathlib import Path from shutil import which -from typing import Dict +from typing import Dict, List import pytest +from pydantic import TypeAdapter +from ethereum_test_base_types import to_json from ethereum_test_forks import Berlin, Fork, Istanbul, London -from ethereum_test_tools.common import Alloc +from ethereum_test_types import Alloc, Environment, Transaction from evm_transition_tool import GethTransitionTool, TransitionTool FIXTURES_ROOT = Path(os.path.join("src", "evm_transition_tool", "tests", "fixtures")) @@ -99,34 +101,49 @@ def test_evm_tool_binary_arg(evm_tool, binary_arg): # noqa: D103 raise Exception("unknown test parameter") -@pytest.mark.parametrize("t8n", [GethTransitionTool()]) -@pytest.mark.parametrize("test_dir", os.listdir(path=FIXTURES_ROOT)) -def test_evm_t8n(t8n: TransitionTool, test_dir: str) -> None: # noqa: D103 +transaction_type_adapter = TypeAdapter(List[Transaction]) + + +@pytest.fixture +def alloc(test_dir: str) -> Alloc: # noqa: D103 alloc_path = Path(FIXTURES_ROOT, test_dir, "alloc.json") + with open(alloc_path, "r") as f: + return Alloc.model_validate_json(f.read()) + + +@pytest.fixture +def txs(test_dir: str) -> List[Transaction]: # noqa: D103 txs_path = Path(FIXTURES_ROOT, test_dir, "txs.json") + with open(txs_path, "r") as f: + return transaction_type_adapter.validate_json(f.read()) + + +@pytest.fixture +def env(test_dir: str) -> Environment: # noqa: D103 env_path = Path(FIXTURES_ROOT, test_dir, "env.json") + with open(env_path, "r") as f: + return Environment.model_validate_json(f.read()) + + +@pytest.mark.parametrize("t8n", [GethTransitionTool()]) +@pytest.mark.parametrize("test_dir", os.listdir(path=FIXTURES_ROOT)) +def test_evm_t8n( # noqa: D103 + t8n: TransitionTool, + alloc: Alloc, + txs: List[Transaction], + env: Environment, + test_dir: str, +) -> None: expected_path = Path(FIXTURES_ROOT, test_dir, "exp.json") - with open(alloc_path, "r") as alloc, open(txs_path, "r") as txs, open( - env_path, "r" - ) as env, open(expected_path, "r") as exp: - print(expected_path) - alloc = json.load(alloc) - txs = json.load(txs) - env_json = json.load(env) + with open(expected_path, "r") as exp: expected = json.load(exp) t8n_output = t8n.evaluate( alloc=alloc, txs=txs, - env=env_json, - fork_name=Berlin.transition_tool_name( - block_number=int(env_json["currentNumber"], 0), - timestamp=int(env_json["currentTimestamp"], 0), - ), + env=env, + fork=Berlin, ) - result_alloc, result = t8n_output["alloc"], t8n_output["result"] - print(result) - print(expected.get("result")) - assert result_alloc == expected.get("alloc") - assert result == expected.get("result") + assert to_json(t8n_output.alloc) == expected.get("alloc") + assert to_json(t8n_output.result) == expected.get("result") diff --git a/src/evm_transition_tool/transition_tool.py b/src/evm_transition_tool/transition_tool.py index db611bca2a..fb811dfa3a 100644 --- a/src/evm_transition_tool/transition_tool.py +++ b/src/evm_transition_tool/transition_tool.py @@ -10,15 +10,17 @@ import textwrap from abc import abstractmethod from dataclasses import dataclass, field -from enum import Enum from itertools import groupby from pathlib import Path from re import Pattern -from typing import Any, Dict, List, Optional, Type +from typing import Dict, List, Mapping, Optional, Type +from ethereum_test_fixtures import FixtureFormats, FixtureVerifier from ethereum_test_forks import Fork +from ethereum_test_types import Alloc, Environment, Transaction from .file_utils import dump_files_to_directory, write_json_file +from .types import TransactionReceipt, TransitionToolInput, TransitionToolOutput class UnknownTransitionTool(Exception): @@ -36,74 +38,10 @@ def __init__(self, message="The transition tool was not found in the path", bina super().__init__(message) -class FixtureFormats(Enum): - """ - Helper class to define fixture formats. - """ - - UNSET_TEST_FORMAT = "unset_test_format" - STATE_TEST = "state_test" - BLOCKCHAIN_TEST = "blockchain_test" - BLOCKCHAIN_TEST_HIVE = "blockchain_test_hive" - EOF_TEST = "eof_test" - - @classmethod - def is_state_test(cls, format): # noqa: D102 - return format == cls.STATE_TEST - - @classmethod - def is_blockchain_test(cls, format): # noqa: D102 - return format in (cls.BLOCKCHAIN_TEST, cls.BLOCKCHAIN_TEST_HIVE) - - @classmethod - def is_hive_format(cls, format): # noqa: D102 - return format == cls.BLOCKCHAIN_TEST_HIVE +model_dump_config: Mapping = {"by_alias": True, "exclude_none": True} - @classmethod - def is_standard_format(cls, format): # noqa: D102 - return format in (cls.STATE_TEST, cls.BLOCKCHAIN_TEST) - - @classmethod - def is_verifiable(cls, format): # noqa: D102 - return format in (cls.STATE_TEST, cls.BLOCKCHAIN_TEST) - - @classmethod - def get_format_description(cls, format): - """ - Returns a description of the fixture format. - - Used to add a description to the generated pytest marks. - """ - if format == cls.UNSET_TEST_FORMAT: - return "Unknown fixture format; it has not been set." - elif format == cls.STATE_TEST: - return "Tests that generate a state test fixture." - elif format == cls.BLOCKCHAIN_TEST: - return "Tests that generate a blockchain test fixture." - elif format == cls.BLOCKCHAIN_TEST_HIVE: - return "Tests that generate a blockchain test fixture in hive format." - elif format == cls.EOF_TEST: - return "Tests that generate an EOF test fixture." - raise Exception(f"Unknown fixture format: {format}.") - @property - def output_base_dir_name(self) -> Path: - """ - Returns the name of the subdirectory where this type of fixture should be dumped to. - """ - return Path(self.value.replace("test", "tests")) - - @property - def output_file_extension(self) -> str: - """ - Returns the file extension for this type of fixture. - - By default, fixtures are dumped as JSON files. - """ - return ".json" - - -class TransitionTool: +class TransitionTool(FixtureVerifier): """ Transition tool abstract base class which should be inherited by all transition tool implementations. @@ -285,7 +223,7 @@ def get_traces(self) -> List[List[List[Dict]]] | None: def collect_traces( self, - receipts: List[Any], + receipts: List[TransactionReceipt], temp_dir: tempfile.TemporaryDirectory, debug_output_path: str = "", ) -> None: @@ -294,7 +232,7 @@ def collect_traces( """ traces: List[List[Dict]] = [] for i, r in enumerate(receipts): - trace_file_name = f"trace-{i}-{r['transactionHash']}.jsonl" + trace_file_name = f"trace-{i}-{r.transaction_hash}.jsonl" if debug_output_path: shutil.copy( os.path.join(temp_dir.name, trace_file_name), @@ -313,9 +251,9 @@ class TransitionToolData: Transition tool files and data to pass between methods """ - alloc: Any - txs: Any - env: Any + alloc: Alloc + txs: List[Transaction] + env: Environment fork_name: str chain_id: int = field(default=1) reward: int = field(default=0) @@ -329,12 +267,22 @@ def __post_init__(self): for tx in self.txs: tx["to"] = tx.get("to") or "" + def to_input(self) -> TransitionToolInput: + """ + Convert the data to a TransactionToolInput object + """ + return TransitionToolInput( + alloc=self.alloc, + txs=self.txs, + env=self.env, + ) + def _evaluate_filesystem( self, *, t8n_data: TransitionToolData, debug_output_path: str = "", - ) -> Dict[str, Any]: + ) -> TransitionToolOutput: """ Executes a transition tool using the filesystem for its inputs and outputs. """ @@ -342,11 +290,7 @@ def _evaluate_filesystem( os.mkdir(os.path.join(temp_dir.name, "input")) os.mkdir(os.path.join(temp_dir.name, "output")) - input_contents = { - "alloc": t8n_data.alloc, - "env": t8n_data.env, - "txs": t8n_data.txs, - } + input_contents = t8n_data.to_input().model_dump(mode="json", **model_dump_config) input_paths = { k: os.path.join(temp_dir.name, "input", f"{k}.json") for k in input_contents.keys() @@ -444,29 +388,25 @@ def _evaluate_filesystem( temp_dir.cleanup() - return output_contents + return TransitionToolOutput(**output_contents) def _evaluate_stream( self, *, t8n_data: TransitionToolData, debug_output_path: str = "", - ) -> Dict[str, Any]: + ) -> TransitionToolOutput: """ Executes a transition tool using stdin and stdout for its inputs and outputs. """ temp_dir = tempfile.TemporaryDirectory() args = self.construct_args_stream(t8n_data, temp_dir) - stdin = { - "alloc": t8n_data.alloc, - "txs": t8n_data.txs, - "env": t8n_data.env, - } + stdin = t8n_data.to_input() result = subprocess.run( args, - input=str.encode(json.dumps(stdin)), + input=stdin.model_dump_json(**model_dump_config).encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) @@ -476,23 +416,22 @@ def _evaluate_stream( if result.returncode != 0: raise Exception("failed to evaluate: " + result.stderr.decode()) - output = json.loads(result.stdout) - - if not all([x in output for x in ["alloc", "result", "body"]]): - raise Exception("Malformed t8n output: missing 'alloc', 'result' or 'body'.") + output: TransitionToolOutput = TransitionToolOutput.model_validate_json(result.stdout) if debug_output_path: dump_files_to_directory( debug_output_path, { - "output/alloc.json": output["alloc"], - "output/result.json": output["result"], - "output/txs.rlp": output["body"], + "output/alloc.json": output.alloc.model_dump(mode="json", **model_dump_config), + "output/result.json": output.result.model_dump( + mode="json", **model_dump_config + ), + "output/txs.rlp": str(output.body), }, ) if self.trace: - self.collect_traces(output["result"]["receipts"], temp_dir, debug_output_path) + self.collect_traces(output.result.receipts, temp_dir, debug_output_path) temp_dir.cleanup() return output @@ -528,7 +467,7 @@ def dump_debug_stream( self, debug_output_path: str, temp_dir: tempfile.TemporaryDirectory, - stdin: Dict[str, Any], + stdin: TransitionToolInput, args: List[str], result: subprocess.CompletedProcess, ): @@ -554,9 +493,11 @@ def dump_debug_stream( debug_output_path, { "args.py": args, - "input/alloc.json": stdin["alloc"], - "input/env.json": stdin["env"], - "input/txs.json": stdin["txs"], + "input/alloc.json": stdin.alloc.model_dump(mode="json", **model_dump_config), + "input/env.json": stdin.env.model_dump(mode="json", **model_dump_config), + "input/txs.json": [ + tx.model_dump(mode="json", **model_dump_config) for tx in stdin.txs + ], "returncode.txt": result.returncode, "stdin.txt": stdin, "stdout.txt": result.stdout.decode(), @@ -568,24 +509,28 @@ def dump_debug_stream( def evaluate( self, *, - alloc: Any, - txs: Any, - env: Any, - fork_name: str, + alloc: Alloc, + txs: List[Transaction], + env: Environment, + fork: Fork, chain_id: int = 1, reward: int = 0, eips: Optional[List[int]] = None, debug_output_path: str = "", - ) -> Dict[str, Any]: + ) -> TransitionToolOutput: """ Executes the relevant evaluate method as required by the `t8n` tool. If a client's `t8n` tool varies from the default behavior, this method can be overridden. """ + fork_name = fork.transition_tool_name( + block_number=env.number, + timestamp=env.timestamp, + ) if eips is not None: fork_name = "+".join([fork_name] + [str(eip) for eip in eips]) - if int(env["currentNumber"], 0) == 0: + if env.number == 0: reward = -1 t8n_data = TransitionTool.TransitionToolData( alloc=alloc, diff --git a/src/evm_transition_tool/types.py b/src/evm_transition_tool/types.py new file mode 100644 index 0000000000..83fcf45f64 --- /dev/null +++ b/src/evm_transition_tool/types.py @@ -0,0 +1,101 @@ +""" +Types used in the transition tool interactions. +""" + +from typing import List + +from pydantic import Field + +from ethereum_test_base_types import Address, Bloom, Bytes, CamelModel, Hash, HexNumber +from ethereum_test_types import Alloc, DepositRequest, Environment, Transaction, WithdrawalRequest + + +class TransactionLog(CamelModel): + """ + Transaction log + """ + + address: Address + topics: List[Hash] + data: Bytes + block_number: HexNumber + transaction_hash: Hash + transaction_index: HexNumber + block_hash: Hash + log_index: HexNumber + removed: bool + + +class TransactionReceipt(CamelModel): + """ + Transaction receipt + """ + + transaction_hash: Hash + gas_used: HexNumber + root: Bytes | None = None + status: HexNumber | None = None + cumulative_gas_used: HexNumber | None = None + logs_bloom: Bloom | None = None + logs: List[TransactionLog] | None = None + contract_address: Address | None = None + effective_gas_price: HexNumber | None = None + block_hash: Hash | None = None + transaction_index: HexNumber | None = None + blob_gas_used: HexNumber | None = None + blob_gas_price: HexNumber | None = None + + +class RejectedTransaction(CamelModel): + """ + Rejected transaction + """ + + index: HexNumber + error: str + + +class Result(CamelModel): + """ + Result of a t8n + """ + + state_root: Hash + ommers_hash: Hash | None = Field(None, validation_alias="sha3Uncles") + transactions_trie: Hash = Field(..., alias="txRoot") + receipts_root: Hash + logs_hash: Hash + logs_bloom: Bloom + receipts: List[TransactionReceipt] + rejected_transactions: List[RejectedTransaction] = Field( + default_factory=list, alias="rejected" + ) + difficulty: HexNumber | None = Field(None, alias="currentDifficulty") + gas_used: HexNumber + base_fee_per_gas: HexNumber | None = Field(None, alias="currentBaseFee") + withdrawals_root: Hash | None = None + excess_blob_gas: HexNumber | None = Field(None, alias="currentExcessBlobGas") + blob_gas_used: HexNumber | None = None + requests_root: Hash | None = None + deposit_requests: List[DepositRequest] | None = None + withdrawal_requests: List[WithdrawalRequest] | None = None + + +class TransitionToolInput(CamelModel): + """ + Transition tool input + """ + + alloc: Alloc + txs: List[Transaction] + env: Environment + + +class TransitionToolOutput(CamelModel): + """ + Transition tool output + """ + + alloc: Alloc + result: Result + body: Bytes diff --git a/src/pytest_plugins/consume/consume.py b/src/pytest_plugins/consume/consume.py index c53615a48d..fb0d8aa039 100644 --- a/src/pytest_plugins/consume/consume.py +++ b/src/pytest_plugins/consume/consume.py @@ -14,8 +14,8 @@ import rich from cli.gen_index import generate_fixtures_index -from ethereum_test_tools.spec.consume.types import TestCases -from evm_transition_tool import FixtureFormats +from ethereum_test_fixtures import FixtureFormats +from ethereum_test_fixtures.consume import TestCases cached_downloads_directory = Path("./cached_downloads") diff --git a/src/pytest_plugins/consume/direct.py b/src/pytest_plugins/consume/direct.py index 45f7e5305a..997adc3a36 100644 --- a/src/pytest_plugins/consume/direct.py +++ b/src/pytest_plugins/consume/direct.py @@ -12,9 +12,9 @@ import pytest -from ethereum_test_tools.common.json import to_json -from ethereum_test_tools.spec.consume.types import TestCaseIndexFile, TestCaseStream -from ethereum_test_tools.spec.file.types import Fixtures +from ethereum_test_base_types import to_json +from ethereum_test_fixtures.consume import TestCaseIndexFile, TestCaseStream +from ethereum_test_fixtures.file import Fixtures from evm_transition_tool import TransitionTool diff --git a/src/pytest_plugins/consume/simulator_common.py b/src/pytest_plugins/consume/simulator_common.py index c0b2a8348a..4e1e9a5272 100644 --- a/src/pytest_plugins/consume/simulator_common.py +++ b/src/pytest_plugins/consume/simulator_common.py @@ -7,16 +7,16 @@ import pytest -from ethereum_test_tools.spec.blockchain.types import Fixture -from ethereum_test_tools.spec.consume.types import TestCaseIndexFile, TestCaseStream -from ethereum_test_tools.spec.file.types import BlockchainFixtures +from ethereum_test_fixtures import BlockchainFixture +from ethereum_test_fixtures.consume import TestCaseIndexFile, TestCaseStream +from ethereum_test_fixtures.file import BlockchainFixtures from pytest_plugins.consume.consume import JsonSource TestCase = TestCaseIndexFile | TestCaseStream @pytest.fixture(scope="function") -def fixture(fixture_source: JsonSource, test_case: TestCase) -> Fixture: +def fixture(fixture_source: JsonSource, test_case: TestCase) -> BlockchainFixture: """ Return the blockchain fixture's pydantic model for the current test case. @@ -26,7 +26,9 @@ def fixture(fixture_source: JsonSource, test_case: TestCase) -> Fixture: """ if fixture_source == "stdin": assert isinstance(test_case, TestCaseStream), "Expected a stream test case" - assert isinstance(test_case.fixture, Fixture), "Expected a blockchain test fixture" + assert isinstance( + test_case.fixture, BlockchainFixture + ), "Expected a blockchain test fixture" fixture = test_case.fixture else: assert isinstance(test_case, TestCaseIndexFile), "Expected an index file test case" @@ -39,7 +41,7 @@ def fixture(fixture_source: JsonSource, test_case: TestCase) -> Fixture: @pytest.fixture(scope="function") -def fixture_description(fixture: Fixture, test_case: TestCase) -> str: +def fixture_description(fixture: BlockchainFixture, test_case: TestCase) -> str: """ Return the description of the current test case. """ diff --git a/src/pytest_plugins/test_filler/test_filler.py b/src/pytest_plugins/test_filler/test_filler.py index c653943583..298caef3a1 100644 --- a/src/pytest_plugins/test_filler/test_filler.py +++ b/src/pytest_plugins/test_filler/test_filler.py @@ -17,6 +17,7 @@ import pytest from pytest_metadata.plugin import metadata_key # type: ignore +from ethereum_test_fixtures import FixtureCollector, FixtureFormats, TestInfo from ethereum_test_forks import ( Fork, Frontier, @@ -24,14 +25,16 @@ get_closest_fork_with_solc_support, get_forks_with_solc_support, ) -from ethereum_test_tools import SPEC_TYPES, Alloc, BaseTest, FixtureCollector, TestInfo, Yul +from ethereum_test_specs import SPEC_TYPES, BaseTest +from ethereum_test_tools import Yul from ethereum_test_tools.code import Solc -from ethereum_test_tools.common.types import AllocMode, contract_address_iterator from ethereum_test_tools.utility.versioning import ( generate_github_url, get_current_commit_hash_or_tag, ) -from evm_transition_tool import FixtureFormats, TransitionTool +from ethereum_test_types import Alloc +from ethereum_test_types.types import AllocMode, contract_address_iterator +from evm_transition_tool import TransitionTool from pytest_plugins.spec_version_checker.spec_version_checker import EIPSpecTestItem @@ -817,7 +820,7 @@ def __init__(self, *args, **kwargs): eips=eips, ) fixture.fill_info( - t8n, + t8n.version(), fixture_description, fixture_source_url=fixture_source_url, ref_spec=reference_spec, diff --git a/tests_consume/test_direct.py b/tests_consume/test_direct.py index dbc1f5f2ad..9e94aeeeeb 100644 --- a/tests_consume/test_direct.py +++ b/tests_consume/test_direct.py @@ -9,7 +9,7 @@ import pytest -from ethereum_test_tools.spec.consume.types import TestCaseIndexFile, TestCaseStream +from ethereum_test_fixtures.consume import TestCaseIndexFile, TestCaseStream from evm_transition_tool import TransitionTool statetest_results: dict[Path, List[dict[str, Any]]] = {} diff --git a/tests_consume/test_via_engine_api.py b/tests_consume/test_via_engine_api.py index c520000f91..92396423d2 100644 --- a/tests_consume/test_via_engine_api.py +++ b/tests_consume/test_via_engine_api.py @@ -8,7 +8,7 @@ import pytest -from ethereum_test_tools.spec.blockchain.types import HiveFixture +from ethereum_test_fixtures.blockchain import HiveFixture @pytest.mark.skip(reason="Not implemented yet.") diff --git a/tests_consume/test_via_rlp.py b/tests_consume/test_via_rlp.py index f86a253bc9..4020ab0f7b 100644 --- a/tests_consume/test_via_rlp.py +++ b/tests_consume/test_via_rlp.py @@ -22,10 +22,9 @@ from hive.testing import HiveTest from pydantic import BaseModel -from ethereum_test_tools.common.base_types import Bytes -from ethereum_test_tools.common.json import to_json +from ethereum_test_base_types import Bytes, to_json +from ethereum_test_fixtures.blockchain import Fixture, FixtureHeader from ethereum_test_tools.rpc import EthRPC -from ethereum_test_tools.spec.blockchain.types import Fixture, FixtureHeader from pytest_plugins.consume.hive_ruleset import ruleset diff --git a/whitelist.txt b/whitelist.txt index 52d4df4889..9293b6ddc7 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -479,6 +479,7 @@ tmpdir tryfirst trylast usefixtures +verifier writelines xfail ZeroPaddedHexNumber From 899df1abd597086a58deb95265594f69ce36f8f1 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Sat, 22 Jun 2024 02:59:13 +0000 Subject: [PATCH 2/3] fix(tests): required import modifications --- .../eip5656_mcopy/test_mcopy_memory_expansion.py | 3 +-- .../eip7692_eof_v1/eip3540_eof_v1/container.py | 2 +- .../test_all_opcodes_in_container.py | 4 ++-- .../eip3540_eof_v1/test_container_size.py | 4 ++-- .../eip3540_eof_v1/test_container_validation.py | 3 +-- .../eip3540_eof_v1/test_eof_example.py | 16 +++++----------- .../eip3540_eof_v1/test_example_valid_invalid.py | 6 +++--- .../eip3540_eof_v1/test_section_order.py | 13 +++---------- .../eip3540_eof_v1/test_section_size.py | 4 ++-- .../eip7069_extcall/test_returndataload.py | 3 +-- .../test_datacopy_memory_expansion.py | 4 ++-- .../eip7620_eof_create/test_returncontract.py | 3 +-- 12 files changed, 24 insertions(+), 41 deletions(-) diff --git a/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py b/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py index d855c9f811..88d3b32472 100644 --- a/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py +++ b/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py @@ -8,10 +8,9 @@ import pytest -from ethereum_test_tools import Account, Alloc, Bytecode, Environment +from ethereum_test_tools import Account, Address, Alloc, Bytecode, Environment from ethereum_test_tools import Opcodes as Op from ethereum_test_tools import StateTestFiller, Storage, Transaction, cost_memory_bytes -from ethereum_test_tools.common.base_types import Address from .common import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py index 4fe4ee5bd3..910688096c 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/container.py @@ -4,6 +4,7 @@ from typing import List +from ethereum_test_tools import EOFException from ethereum_test_tools.eof.v1 import ( VERSION_MAX_SECTION_KIND, AutoSection, @@ -17,7 +18,6 @@ MAX_CODE_SECTIONS, MAX_OPERAND_STACK_HEIGHT, ) -from ethereum_test_tools.exceptions import EOFException from ethereum_test_tools.vm.opcode import Opcodes as Op INVALID: List[Container] = [ diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py index 22dd9d273c..14149e069b 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py @@ -5,10 +5,10 @@ import pytest -from ethereum_test_tools import EOFTestFiller, Opcode +from ethereum_test_tools import EOFException, EOFTestFiller, Opcode from ethereum_test_tools import Opcodes as Op from ethereum_test_tools import UndefinedOpcodes -from ethereum_test_tools.eof.v1 import Container, ContainerKind, EOFException, Section +from ethereum_test_tools.eof.v1 import Container, ContainerKind, Section from ethereum_test_tools.eof.v1.constants import MAX_OPERAND_STACK_HEIGHT from .. import EOF_FORK_NAME diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py index ea3771c4a1..d31fdc445e 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py @@ -4,9 +4,9 @@ import pytest -from ethereum_test_tools import EOFTestFiller +from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op -from ethereum_test_tools.eof.v1 import Container, EOFException, Section +from ethereum_test_tools.eof.v1 import Container, Section from ethereum_test_tools.eof.v1.constants import MAX_INITCODE_SIZE from .. import EOF_FORK_NAME diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py index 84a96f3cba..3bb3424689 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py @@ -5,11 +5,10 @@ import pytest -from ethereum_test_tools import EOFTestFiller +from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op from ethereum_test_tools.eof.v1 import Container, ContainerKind, Section from ethereum_test_tools.eof.v1.constants import MAX_CODE_SECTIONS -from ethereum_test_tools.exceptions import EOFException from .. import EOF_FORK_NAME diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py index 31e79578d2..0ecaad8228 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py @@ -4,15 +4,9 @@ import pytest -from ethereum_test_tools import EOFTestFiller +from ethereum_test_tools import Bytecode, EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op -from ethereum_test_tools.eof.v1 import ( - AutoSection, - BytesConvertible, - Container, - EOFException, - Section, -) +from ethereum_test_tools.eof.v1 import AutoSection, Container, Section from .. import EOF_FORK_NAME @@ -129,7 +123,7 @@ def test_eof_example_custom_fields(eof_test: EOFTestFiller): @pytest.mark.parametrize( "data_section_bytes", - ("0x01", "0xef"), + (b"\x01", b"\xef"), ) @pytest.mark.parametrize( "code_section_code, exception", @@ -137,8 +131,8 @@ def test_eof_example_custom_fields(eof_test: EOFTestFiller): ) def test_eof_example_parameters( eof_test: EOFTestFiller, - data_section_bytes: BytesConvertible, - code_section_code: BytesConvertible, + data_section_bytes: bytes, + code_section_code: Bytecode, exception: EOFException, ): """ diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py index 5f8f8fa7f2..e90e386ef2 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_example_valid_invalid.py @@ -4,9 +4,9 @@ import pytest -from ethereum_test_tools import EOFTestFiller +from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op -from ethereum_test_tools.eof.v1 import Bytes, Container, EOFException, Section +from ethereum_test_tools.eof.v1 import Container, Section from .. import EOF_FORK_NAME @@ -59,7 +59,7 @@ ), Section.Data("0xef"), ], - header_terminator=Bytes(b"\xFF"), + header_terminator=b"\xFF", ), "ef00010100040200010003040001ff00800001305000ef", EOFException.MISSING_TERMINATOR, diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py index 294ef9237a..d0f3703617 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py @@ -7,16 +7,9 @@ import pytest -from ethereum_test_tools import EOFTestFiller +from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op -from ethereum_test_tools.eof.v1 import ( - AutoSection, - Bytes, - Container, - EOFException, - Section, - SectionKind, -) +from ethereum_test_tools.eof.v1 import AutoSection, Container, Section, SectionKind from .. import EOF_FORK_NAME @@ -175,7 +168,7 @@ def make_section_order(kind) -> List[Section]: ) section_type = Section( kind=SectionKind.TYPE, - data=Bytes.fromhex("00800001"), + data=bytes.fromhex("00800001"), custom_size=4, skip_header_listing=calculate_skip_flag(SectionKind.TYPE, CasePosition.HEADER), skip_body_listing=calculate_skip_flag(SectionKind.TYPE, CasePosition.BODY), diff --git a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py index ab767c074b..96eb30def0 100644 --- a/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py @@ -6,9 +6,9 @@ import pytest -from ethereum_test_tools import EOFTestFiller +from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools import Opcodes as Op -from ethereum_test_tools.eof.v1 import Container, EOFException, Section, SectionKind +from ethereum_test_tools.eof.v1 import Container, Section, SectionKind from .. import EOF_FORK_NAME diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_returndataload.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_returndataload.py index 3a7d42ae41..4cffc50514 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_returndataload.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_returndataload.py @@ -6,8 +6,7 @@ import pytest -from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.common.types import Storage +from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Storage, Transaction from ethereum_test_tools.eof.v1 import Container, Section from ethereum_test_tools.vm.opcode import Opcodes as Op diff --git a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py index a8e35aea2b..49491e90d8 100644 --- a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py +++ b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py @@ -7,15 +7,15 @@ from ethereum_test_tools import ( Account, + Address, Alloc, Bytecode, Environment, StateTestFiller, Storage, Transaction, + cost_memory_bytes, ) -from ethereum_test_tools.common.base_types import Address -from ethereum_test_tools.common.helpers import cost_memory_bytes from ethereum_test_tools.eof.v1 import Container, Section from ethereum_test_tools.vm.opcode import Opcodes as Op diff --git a/tests/prague/eip7692_eof_v1/eip7620_eof_create/test_returncontract.py b/tests/prague/eip7692_eof_v1/eip7620_eof_create/test_returncontract.py index b2786bc8f1..432bfae1af 100644 --- a/tests/prague/eip7692_eof_v1/eip7620_eof_create/test_returncontract.py +++ b/tests/prague/eip7692_eof_v1/eip7620_eof_create/test_returncontract.py @@ -3,9 +3,8 @@ """ import pytest -from ethereum_test_tools import EOFTestFiller +from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools.eof.v1 import Container, ContainerKind, Section -from ethereum_test_tools.exceptions import EOFException from ethereum_test_tools.vm.opcode import Opcodes as Op from .. import EOF_FORK_NAME From a74b028eae2a709d95bcb63fe4bcb0adae3ba5a3 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Sat, 22 Jun 2024 20:18:46 +0000 Subject: [PATCH 3/3] fix(docs): update library reference --- docs/consuming_tests/exceptions.md | 8 ++++++-- docs/library/ethereum_test_base_types.md | 3 +++ docs/library/ethereum_test_exceptions.md | 3 +++ docs/library/ethereum_test_fixtures.md | 3 +++ docs/library/ethereum_test_specs.md | 3 +++ docs/library/ethereum_test_types.md | 3 +++ docs/library/ethereum_test_vm.md | 3 +++ docs/library/index.md | 10 ++++++++-- docs/navigation.md | 10 ++++++++-- docs/writing_tests/exception_tests.md | 2 +- docs/writing_tests/writing_a_new_test.md | 2 +- 11 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 docs/library/ethereum_test_base_types.md create mode 100644 docs/library/ethereum_test_exceptions.md create mode 100644 docs/library/ethereum_test_fixtures.md create mode 100644 docs/library/ethereum_test_specs.md create mode 100644 docs/library/ethereum_test_types.md create mode 100644 docs/library/ethereum_test_vm.md diff --git a/docs/consuming_tests/exceptions.md b/docs/consuming_tests/exceptions.md index 76dcec5672..de9c4e18e2 100644 --- a/docs/consuming_tests/exceptions.md +++ b/docs/consuming_tests/exceptions.md @@ -15,8 +15,12 @@ the exceptions. ## `TransactionException` -::: ethereum_test_tools.TransactionException +::: ethereum_test_exceptions.TransactionException ## `BlockException` -::: ethereum_test_tools.BlockException +::: ethereum_test_exceptions.BlockException + +## `EOFException` + +::: ethereum_test_exceptions.EOFException diff --git a/docs/library/ethereum_test_base_types.md b/docs/library/ethereum_test_base_types.md new file mode 100644 index 0000000000..e1bca5d489 --- /dev/null +++ b/docs/library/ethereum_test_base_types.md @@ -0,0 +1,3 @@ +# Ethereum Test Base Types package + +::: ethereum_test_base_types diff --git a/docs/library/ethereum_test_exceptions.md b/docs/library/ethereum_test_exceptions.md new file mode 100644 index 0000000000..e0cfd17a32 --- /dev/null +++ b/docs/library/ethereum_test_exceptions.md @@ -0,0 +1,3 @@ +# Ethereum Test Exceptions package + +::: ethereum_test_exceptions diff --git a/docs/library/ethereum_test_fixtures.md b/docs/library/ethereum_test_fixtures.md new file mode 100644 index 0000000000..89ed5ff703 --- /dev/null +++ b/docs/library/ethereum_test_fixtures.md @@ -0,0 +1,3 @@ +# Ethereum Test Fixtures package + +::: ethereum_test_fixtures diff --git a/docs/library/ethereum_test_specs.md b/docs/library/ethereum_test_specs.md new file mode 100644 index 0000000000..525ff84e0a --- /dev/null +++ b/docs/library/ethereum_test_specs.md @@ -0,0 +1,3 @@ +# Ethereum Test Specs package + +::: ethereum_test_specs diff --git a/docs/library/ethereum_test_types.md b/docs/library/ethereum_test_types.md new file mode 100644 index 0000000000..ef83eac6ae --- /dev/null +++ b/docs/library/ethereum_test_types.md @@ -0,0 +1,3 @@ +# Ethereum Test Types package + +::: ethereum_test_types diff --git a/docs/library/ethereum_test_vm.md b/docs/library/ethereum_test_vm.md new file mode 100644 index 0000000000..20712b314b --- /dev/null +++ b/docs/library/ethereum_test_vm.md @@ -0,0 +1,3 @@ +# Ethereum Test VM package + +::: ethereum_test_vm diff --git a/docs/library/index.md b/docs/library/index.md index 5abae31724..1d29d8eded 100644 --- a/docs/library/index.md +++ b/docs/library/index.md @@ -2,7 +2,13 @@ Execution spec tests consists of several packages that implement helper classes and tools that enable and simplify test case implementation. This section contains their reference documentation: -- [`evm_transition_tool`](./evm_transition_tool.md) - a wrapper for the transition (`t8n`) tool. -- [`ethereum_test_tools`](./ethereum_test_tools.md) - provides primitives and helpers to test Ethereum execution clients. +- [`ethereum_test_base_types`](./ethereum_test_base_types.md) - provides the basic types on top of which other testing libraries are built. +- [`ethereum_test_exceptions`](./ethereum_test_exceptions.md) - provides definitions for exceptions used in all tests. +- [`ethereum_test_fixtures`](./ethereum_test_fixtures.md) - provides definitions of all test fixture types that are produced in this repository and can be consumed by clients. - [`ethereum_test_forks`](./ethereum_test_forks.md) - provides definitions for supported forks used in tests. +- [`ethereum_test_specs`](./ethereum_test_specs.md) - provides definitions for all spec types used to define test cases, and generate different kinds of test fixtures. +- [`ethereum_test_tools`](./ethereum_test_tools.md) - provides primitives and helpers to test Ethereum execution clients. +- [`ethereum_test_types`](./ethereum_test_types.md) - provides Ethereum types built on top of the base types which are used to define test cases and interact with other libraries. +- [`ethereum_test_vm`](./ethereum_test_vm.md) - provides definitions for the Ethereum Virtual Machine (EVM) as used to define bytecode in test cases. +- [`evm_transition_tool`](./evm_transition_tool.md) - a wrapper for the transition (`t8n`) tool. - [`pytest_plugins`](./pytest_plugins/index.md) - contains pytest customizations that provide additional functionality for generating test fixtures. diff --git a/docs/navigation.md b/docs/navigation.md index 4bb2a588f9..9e3409cb87 100644 --- a/docs/navigation.md +++ b/docs/navigation.md @@ -34,7 +34,13 @@ * [Enabling Precommit Checks](dev/precommit.md) * [Changelog](CHANGELOG.md) * [Library Reference](library/index.md) - * [EVM Transition Tool Package](library/evm_transition_tool.md) - * [Ethereum Test Tools Package](library/ethereum_test_tools.md) + * [Ethereum Test Base Types Package](library/ethereum_test_base_types.md) + * [Ethereum Test Exceptions Package](library/ethereum_test_exceptions.md) + * [Ethereum Test Fixtures Package](library/ethereum_test_fixtures.md) * [Ethereum Test Forks Package](library/ethereum_test_forks.md) + * [Ethereum Test Specs Package](library/ethereum_test_specs.md) + * [Ethereum Test Tools Package](library/ethereum_test_tools.md) + * [Ethereum Test Types Package](library/ethereum_test_types.md) + * [Ethereum Test VM Package](library/ethereum_test_vm.md) + * [EVM Transition Tool Package](library/evm_transition_tool.md) * [Pytest Plugins](library/pytest_plugins/index.md) diff --git a/docs/writing_tests/exception_tests.md b/docs/writing_tests/exception_tests.md index 07568dcca0..a77d4e6cb3 100644 --- a/docs/writing_tests/exception_tests.md +++ b/docs/writing_tests/exception_tests.md @@ -4,7 +4,7 @@ Exception tests are a special type of test which verify that an invalid transact ## Creating an Exception Test -To test for an exception, the test can use either of the following types from `ethereum_test_tools` library: +To test for an exception, the test can use either of the following types from `ethereum_test_exceptions` library: 1. [`TransactionException`](../consuming_tests/exceptions.md#transactionexception): To be added to the `error` field of the `Transaction` object, and to the `exception` field of the `Block` object that includes the transaction; this exception type is used when a transaction is invalid, and therefore when included in a block, the block is expected to be invalid too. This is different from valid transactions where an exception during EVM execution is expected (e.g. a revert, or out-of-gas), which can be included in valid blocks. diff --git a/docs/writing_tests/writing_a_new_test.md b/docs/writing_tests/writing_a_new_test.md index 04a91c7277..16f5c49d1b 100644 --- a/docs/writing_tests/writing_a_new_test.md +++ b/docs/writing_tests/writing_a_new_test.md @@ -181,7 +181,7 @@ Within the `post` dictionary object, an account address can be: The `Account` object is used to specify the properties of an account to be verified in the post state. -The python representation can be found in [src/ethereum_test_tools/common/types.py](https://github.com/ethereum/execution-spec-tests/blob/main/src/ethereum_test_tools/common/types.py). +The python representation can be found in [src/ethereum_test_types/types.py](https://github.com/ethereum/execution-spec-tests/blob/main/src/ethereum_test_types/types.py). It can verify the following properties of an account: