Skip to content

Commit

Permalink
new(tests): EOF - EIP-7620: Add more tests for validating EOF subcont…
Browse files Browse the repository at this point in the history
…ainer kinds (ethereum#676)

* fix(tests): Fix invalid EOF container combos test

Make sure the case is invalid only for one reason.

* new(tests): Add more cases for invalid subcontainer kind combos

* new(tests): Add test for valid subcontainer kinds on a deeper nesting level

* new(tests): Add test for valid subcontainer kinds in a non-first code section

* Update changelog
  • Loading branch information
gumb0 authored Jul 11, 2024
1 parent 8bf86bd commit a60adc2
Show file tree
Hide file tree
Showing 2 changed files with 215 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Test fixtures for use by clients are available for each release on the [Github r
- 🔀 Update EIP-7002 tests to match spec changes in [ethereum/execution-apis#549](https://github.com/ethereum/execution-apis/pull/549) ([#600](https://github.com/ethereum/execution-spec-tests/pull/600))
- ✨ Convert a few eip1153 tests from ethereum/tests repo into .py ([#440](https://github.com/ethereum/execution-spec-tests/pull/440)).
- ✨ Add tests for [EIP-7480: EOF - Data section access instructions](https://eips.ethereum.org/EIPS/eip-7480) ([#518](https://github.com/ethereum/execution-spec-tests/pull/518), [#664](https://github.com/ethereum/execution-spec-tests/pull/664)).
- ✨ Add tests for subcontainer kind validation from [EIP-7620: EOF Contract Creation](https://eips.ethereum.org/EIPS/eip-7620) for the cases with deeply nested containers and non-first code sections ([#676](https://github.com/ethereum/execution-spec-tests/pull/676)).

### 🛠️ Framework

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""
EOF Subcontainer tests covering simple cases.
"""

import pytest

from ethereum_test_tools import Account, EOFException, EOFStateTestFiller, EOFTestFiller
from ethereum_test_tools.eof.v1 import Container, ContainerKind, Section
from ethereum_test_tools.eof.v1.constants import MAX_BYTECODE_SIZE
from ethereum_test_tools.vm.opcode import Opcodes as Op

from .. import EOF_FORK_NAME
Expand All @@ -19,6 +21,9 @@
code=Op.EOFCREATE[0](0, 0, 0, 0) + Op.SSTORE(slot_code_worked, value_code_worked) + Op.STOP,
max_stack_height=4,
)
eofcreate_revert_code_section = Section.Code(
code=Op.EOFCREATE[0](0, 0, 0, 0) + Op.REVERT(0, 0),
)
returncontract_code_section = Section.Code(
code=Op.SSTORE(slot_code_worked, value_code_worked) + Op.RETURNCONTRACT[0](0, 0),
max_stack_height=2,
Expand Down Expand Up @@ -90,9 +95,11 @@ def test_reverting_container(
zero_section,
revert_sub_container,
],
kind=ContainerKind.INITCODE
if zero_section == returncontract_code_section
else ContainerKind.RUNTIME,
kind=(
ContainerKind.INITCODE
if zero_section == returncontract_code_section
else ContainerKind.RUNTIME
),
),
container_post=Account(storage={slot_code_worked: value_code_worked}),
)
Expand Down Expand Up @@ -187,21 +194,24 @@ def test_container_combos_valid(


@pytest.mark.parametrize(
"code_section,first_sub_container",
"code_section,first_sub_container,container_kind",
[
pytest.param(
eofcreate_code_section,
stop_sub_container,
ContainerKind.RUNTIME,
id="EOFCREATE/STOP",
),
pytest.param(
eofcreate_code_section,
return_sub_container,
ContainerKind.RUNTIME,
id="EOFCREATE/RETURN",
),
pytest.param(
returncontract_code_section,
returncontract_sub_container,
ContainerKind.INITCODE,
id="RETURNCONTRACT/RETURNCONTRACT",
),
],
Expand All @@ -210,6 +220,7 @@ def test_container_combos_invalid(
eof_test: EOFTestFiller,
code_section: Section,
first_sub_container: Container,
container_kind: ContainerKind,
):
"""Test invalid subcontainer reference / opcode combos"""
eof_test(
Expand All @@ -218,6 +229,205 @@ def test_container_combos_invalid(
code_section,
first_sub_container,
],
kind=container_kind,
),
expect_exception=EOFException.INCOMPATIBLE_CONTAINER_KIND,
)


@pytest.mark.parametrize(
"code_section,first_sub_container",
[
pytest.param(
eofcreate_revert_code_section,
returncontract_sub_container,
id="EOFCREATE/RETURNCONTRACT",
),
pytest.param(
returncontract_code_section,
stop_sub_container,
id="RETURNCONTRACT/STOP",
),
pytest.param(
returncontract_code_section,
return_sub_container,
id="RETURNCONTRACT/RETURN",
),
pytest.param(
eofcreate_revert_code_section,
revert_sub_container,
id="EOFCREATE/REVERT",
),
pytest.param(
returncontract_code_section,
revert_sub_container,
id="RETURNCONTRACT/REVERT",
),
],
)
def test_container_combos_deeply_nested_valid(
eof_test: EOFTestFiller,
code_section: Section,
first_sub_container: Container,
):
"""Test valid subcontainer reference / opcode combos on a deep container nesting level"""
valid_container = Container(
sections=[
code_section,
first_sub_container,
],
kind=ContainerKind.INITCODE,
)

container = valid_container
while len(container) < MAX_BYTECODE_SIZE:
container = Container(
sections=[
eofcreate_revert_code_section,
Section.Container(container=container.copy()),
],
kind=ContainerKind.INITCODE,
)

eof_test(data=container)


@pytest.mark.parametrize(
"code_section,first_sub_container",
[
pytest.param(
eofcreate_revert_code_section,
stop_sub_container,
id="EOFCREATE/STOP",
),
pytest.param(
eofcreate_revert_code_section,
return_sub_container,
id="EOFCREATE/RETURN",
),
pytest.param(
returncontract_code_section,
returncontract_sub_container,
id="RETURNCONTRACT/RETURNCONTRACT",
),
],
)
def test_container_combos_deeply_nested_invalid(
eof_test: EOFTestFiller,
code_section: Section,
first_sub_container: Container,
):
"""Test invalid subcontainer reference / opcode combos on a deep container nesting level"""
invalid_container = Container(
sections=[
code_section,
first_sub_container,
],
kind=ContainerKind.INITCODE,
)

container = invalid_container
while len(container) < MAX_BYTECODE_SIZE:
container = Container(
sections=[
eofcreate_revert_code_section,
Section.Container(container=container.copy()),
],
kind=ContainerKind.INITCODE,
)

eof_test(
data=container,
expect_exception=EOFException.INCOMPATIBLE_CONTAINER_KIND,
)


@pytest.mark.parametrize(
"code_section,first_sub_container,container_kind",
[
pytest.param(
eofcreate_code_section,
returncontract_sub_container,
ContainerKind.RUNTIME,
id="EOFCREATE/RETURNCONTRACT",
),
pytest.param(
returncontract_code_section,
stop_sub_container,
ContainerKind.INITCODE,
id="RETURNCONTRACT/STOP",
),
pytest.param(
returncontract_code_section,
return_sub_container,
ContainerKind.INITCODE,
id="RETURNCONTRACT/RETURN",
),
pytest.param(
eofcreate_code_section,
revert_sub_container,
ContainerKind.RUNTIME,
id="EOFCREATE/REVERT",
),
pytest.param(
returncontract_code_section,
revert_sub_container,
ContainerKind.INITCODE,
id="RETURNCONTRACT/REVERT",
),
],
)
def test_container_combos_non_first_code_sections_valid(
eof_test: EOFTestFiller,
code_section: Section,
first_sub_container: Container,
container_kind: ContainerKind,
):
"""Test valid subcontainer reference / opcode combos in a non-first code section"""
eof_test(
data=Container(
sections=[Section.Code(Op.JUMPF[i]) for i in range(1, 1024)]
+ [code_section, first_sub_container],
kind=container_kind,
),
)


@pytest.mark.parametrize(
"code_section,first_sub_container,container_kind",
[
pytest.param(
eofcreate_code_section,
stop_sub_container,
ContainerKind.RUNTIME,
id="EOFCREATE/STOP",
),
pytest.param(
eofcreate_code_section,
return_sub_container,
ContainerKind.RUNTIME,
id="EOFCREATE/RETURN",
),
pytest.param(
returncontract_code_section,
returncontract_sub_container,
ContainerKind.INITCODE,
id="RETURNCONTRACT/RETURNCONTRACT",
),
],
)
def test_container_combos_non_first_code_sections_invalid(
eof_test: EOFTestFiller,
code_section: Section,
first_sub_container: Container,
container_kind: ContainerKind,
):
"""Test invalid subcontainer reference / opcode combos in a non-first code section"""
eof_test(
data=Container(
sections=[Section.Code(Op.JUMPF[i]) for i in range(1, 1024)]
+ [code_section, first_sub_container],
kind=container_kind,
),
expect_exception=EOFException.INCOMPATIBLE_CONTAINER_KIND,
)
Expand Down

0 comments on commit a60adc2

Please sign in to comment.