Skip to content

Commit

Permalink
feat(fw): EOF support (ethereum#512)
Browse files Browse the repository at this point in the history
* feat(all): add EOF fixture format and test spec

* feat(tests): add EOF example

* feat(fw): EOF library

tools/vm: EOF opcode changes

tools: CREATE3 helper

tox: EOF Keywords

post rebase changes: align EOF tests with main.

Co-authored-by: spencer-tb <[email protected]>

post rebase: tox fixes.

Co-authored-by: spencer-tb <[email protected]>

Fix existing EOF tests (ethereum#11)

Co-authored-by: Hugo <[email protected]>

* new(tests): prague: EOF V1 tests

tests/eof: move to prague

tests/eof: fixes

post rebase changes: align EOF tests with main. (tests)

Co-authored-by: spencer-tb <[email protected]>

post rebase: tox fixes (tests).

Co-authored-by: spencer-tb <[email protected]>

Fix existing EOF tests (tests) (ethereum#11)

Co-authored-by: Hugo <[email protected]>

* refactor(fw): EOF container code

* fix(fw): vm: re-order JUMPDEST, NOOP

* fix(fw): cli tests

* fix(tests): refactor fixes

* fix(fw): eof: fix raw bytes processing

* fix(tests): eof: change `test_code_validation.py` to use `EOFTestFiller`

* eof unit tests

* fix eof exceptions

* refactor(fw): compute_create3_address

* fix(tests): tox

* refactor(fw): eof_v1: use pydantic

* fix(fw): tpx

* fix(fw): RJUMPV custom dataportion parser

* fix(tests): eofv1: RJUMPI calls

* new(fw): RJUMPV unit test

* feat(fw): subscriptable opcodes

* fix(fw): Opcode add, mul

* fix(tests): test hardcoding bytecode of initcode

* fix(fw): fix

* fix(tests): eof: fix RJUMP*, CALLF data portions

* hack(fw): Add str as allowed EOF exception

* fix(tests): eof: fix test_execution_function.py

* changelog

* chore: add unknown words to dictionary

* fetch exceptions with evmone
lots of TODOs

* eof .py test example

* fix(fw): add unchecked_stack opcode property (CALLF)

* refactor(fw): eof: refactor and add section creation helpers

* fix: tox

* fix(tests): eof: refactor

* refactor(tests): replace Section(kind=, with Section.Code, Section.Data

* fix(fw): eof: consistent magic, version, and header terminator types.

* fix(fw): eof: proper magic

* rm(tests): eof: duplicate prague folder with redundant examples

* fix(fw): eof: data-container body order

* docs: add EOF

* fix(docs): word

* fix(tests): eof: file rename

---------

Co-authored-by: Mario Vega <[email protected]>
Co-authored-by: Hugo <[email protected]>
Co-authored-by: danceratopz <[email protected]>
  • Loading branch information
4 people authored Apr 18, 2024
1 parent 6820baf commit e7d677b
Show file tree
Hide file tree
Showing 34 changed files with 5,535 additions and 34 deletions.
2 changes: 2 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Test fixtures for use by clients are available for each release on the [Github r
- ✨ Add Macro enum that represents byte sequence of Op instructions ([#457](https://github.com/ethereum/execution-spec-tests/pull/457))
- ✨ Number of parameters used to call opcodes (to generate bytecode) is now checked ([#492](https://github.com/ethereum/execution-spec-tests/pull/492)).
- ✨ Libraries have been refactored to use `pydantic` for type checking in most test types ([#486](https://github.com/ethereum/execution-spec-tests/pull/486), [#501](https://github.com/ethereum/execution-spec-tests/pull/501), [#508](https://github.com/ethereum/execution-spec-tests/pull/508)).
- ✨ Opcodes are now subscriptable and it's used to define the data portion of the opcode: `Op.PUSH1(1) == Op.PUSH1[1] == b"\x60\x01"` ([#513](https://github.com/ethereum/execution-spec-tests/pull/513))
- ✨ Added EOF fixture format ([#512](https://github.com/ethereum/execution-spec-tests/pull/512)).

### 🔧 EVM Tools

Expand Down
19 changes: 19 additions & 0 deletions docs/consuming_tests/eof_test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# EOF Tests <!-- markdownlint-disable MD051 (MD051=link-fragments "Link fragments should be valid") -->

The EOF Test fixture format tests are included in the fixtures subdirectory `eof_tests`.

These are produced by the `EOFTest` test spec.

## Description

The EOF test fixture format is used to test the EOF container validation function of the Ethereum Virtual Machine (EVM).

It simply defines a binary code in hexadecimal format and a boolean value that indicates whether the code is valid or not.

## Consumption

TODO: Update this section

## Structures

TODO: Update this section
1 change: 1 addition & 0 deletions docs/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* [State Tests](consuming_tests/state_test.md)
* [Blockchain Tests](consuming_tests/blockchain_test.md)
* [Blockchain Hive Tests](consuming_tests/blockchain_test_hive.md)
* [EOF Tests](consuming_tests/eof_test.md)
* [Common Types](consuming_tests/common_types.md)
* [Exceptions](consuming_tests/exceptions.md)
* [Getting Help](getting_help/index.md)
Expand Down
10 changes: 8 additions & 2 deletions src/cli/tests/test_evm_bytes_to_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import pytest

from ethereum_test_tools import Macro
from ethereum_test_tools import Opcodes as Op

from ..evm_bytes_to_python import process_evm_bytes
Expand Down Expand Up @@ -33,7 +32,14 @@ def test_evm_bytes_to_python(evm_bytes, python_opcodes):
assert process_evm_bytes(evm_bytes) == python_opcodes


@pytest.mark.parametrize("opcode", [op for op in Op if not isinstance(op, Macro)])
DUPLICATES = [Op.NOOP]


@pytest.mark.parametrize(
"opcode",
[op for op in Op if op not in DUPLICATES],
ids=lambda op: op._name_,
)
def test_individual_opcodes(opcode):
"""Test each opcode individually"""
if opcode.data_portion_length > 0:
Expand Down
11 changes: 9 additions & 2 deletions src/ethereum_test_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,22 @@
add_kzg_version,
ceiling_division,
compute_create2_address,
compute_create3_address,
compute_create_address,
copy_opcode_cost,
cost_memory_bytes,
eip_2028_transaction_data_cost,
)
from .exceptions import BlockException, TransactionException
from .exceptions import BlockException, EOFException, TransactionException
from .reference_spec import ReferenceSpec, ReferenceSpecTypes
from .spec import (
SPEC_TYPES,
BaseFixture,
BaseTest,
BlockchainTest,
BlockchainTestFiller,
EOFTest,
EOFTestFiller,
FixtureCollector,
StateTest,
StateTestFiller,
Expand Down Expand Up @@ -74,12 +77,15 @@
"Conditional",
"EngineAPIError",
"Environment",
"EOFException",
"EOFTest",
"EOFTestFiller",
"FixtureCollector",
"Hash",
"Header",
"Initcode",
"Opcode",
"Macro",
"Opcode",
"OpcodeCallArg",
"Opcodes",
"ReferenceSpec",
Expand All @@ -104,6 +110,7 @@
"ceiling_division",
"compute_create_address",
"compute_create2_address",
"compute_create3_address",
"copy_opcode_cost",
"cost_memory_bytes",
"eip_2028_transaction_data_cost",
Expand Down
2 changes: 2 additions & 0 deletions src/ethereum_test_tools/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
add_kzg_version,
ceiling_division,
compute_create2_address,
compute_create3_address,
compute_create_address,
copy_opcode_cost,
cost_memory_bytes,
Expand Down Expand Up @@ -76,6 +77,7 @@
"ceiling_division",
"compute_create_address",
"compute_create2_address",
"compute_create3_address",
"copy_opcode_cost",
"cost_memory_bytes",
"eip_2028_transaction_data_cost",
Expand Down
13 changes: 13 additions & 0 deletions src/ethereum_test_tools/common/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ def copy_opcode_cost(length: int) -> int:
return 3 + (ceiling_division(length, 32) * 3) + cost_memory_bytes(length, 0)


def compute_create3_address(
address: FixedSizeBytesConvertible,
salt: FixedSizeBytesConvertible,
init_container: BytesConvertible,
) -> Address:
"""
Compute address of the resulting contract created using the `CREATE3`
opcode.
"""
hash = keccak256(b"\xff" + Address(address) + Hash(salt) + keccak256(Bytes(init_container)))
return Address(hash[-20:])


def eip_2028_transaction_data_cost(data: BytesConvertible) -> int:
"""
Calculates the cost of a given data as part of a transaction, based on the
Expand Down
6 changes: 6 additions & 0 deletions src/ethereum_test_tools/eof/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""
EVM Object Format Libary to generate bytecode for testing purposes
"""
from .constants import LATEST_EOF_VERSION

__all__ = ("LATEST_EOF_VERSION",)
21 changes: 21 additions & 0 deletions src/ethereum_test_tools/eof/constants.py
Original file line number Diff line number Diff line change
@@ -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.
"""
Loading

0 comments on commit e7d677b

Please sign in to comment.