From cb472ef009fb312c8f3b713b32b508ea0425b3f0 Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Fri, 14 Jun 2024 17:29:47 +0200 Subject: [PATCH 1/5] new(tests): EOF - EIP-3540 container size Tests https://github.com/ipsilon/eof/pull/125 --- .../exceptions/evmone_exceptions.py | 3 + .../exceptions/exceptions.py | 4 + .../eip3540_eof_v1/test_container_size.py | 114 ++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py diff --git a/src/ethereum_test_tools/exceptions/evmone_exceptions.py b/src/ethereum_test_tools/exceptions/evmone_exceptions.py index 23deb5d490..7e1da13411 100644 --- a/src/ethereum_test_tools/exceptions/evmone_exceptions.py +++ b/src/ethereum_test_tools/exceptions/evmone_exceptions.py @@ -74,6 +74,9 @@ class EvmoneExceptionMapper: EOFException.TOPLEVEL_CONTAINER_TRUNCATED, "err: toplevel_container_truncated" ), ExceptionMessage(EOFException.ORPHAN_SUBCONTAINER, "err: unreferenced_subcontainer"), + ExceptionMessage( + EOFException.CONTAINER_SIZE_ABOVE_LIMIT, "err: container_size_above_limit" + ), ) def __init__(self) -> None: diff --git a/src/ethereum_test_tools/exceptions/exceptions.py b/src/ethereum_test_tools/exceptions/exceptions.py index 46e64c60fa..d1d5113879 100644 --- a/src/ethereum_test_tools/exceptions/exceptions.py +++ b/src/ethereum_test_tools/exceptions/exceptions.py @@ -692,6 +692,10 @@ class EOFException(ExceptionBase): """ EOF container has an unreferenced subcontainer. '""" + CONTAINER_SIZE_ABOVE_LIMIT = auto() + """ + EOF container is above size limit + """ """ 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 new file mode 100644 index 0000000000..f576772549 --- /dev/null +++ b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py @@ -0,0 +1,114 @@ +""" +EOF validation tests for EIP-3540 container size +""" + +import pytest + +from ethereum_test_tools import 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.constants import MAX_INITCODE_SIZE + +from .. import EOF_FORK_NAME + +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-3540.md" +REFERENCE_SPEC_VERSION = "" # todo + +pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) + +VALID_CONTAINER = Container(sections=[Section.Code(code=Op.STOP)]) + + +@pytest.mark.parametrize( + "over_limit", + [0, 1, 2, 2**16 - MAX_INITCODE_SIZE], +) +def test_max_size( + eof_test: EOFTestFiller, + over_limit: int, +): + """ + Verify EOF container valid at maximum size, invalid above + """ + minimal_code = bytearray(bytes(VALID_CONTAINER)) + # Expand the minimal EOF code by more noop code, reaching the desired target container size. + code = Container( + sections=[ + Section.Code( + code=Op.JUMPDEST * (MAX_INITCODE_SIZE - len(minimal_code) + over_limit) + Op.STOP + ) + ] + ) + assert len(code) == MAX_INITCODE_SIZE + over_limit + eof_test( + data=bytes(code), + expect_exception=None if over_limit == 0 else EOFException.CONTAINER_SIZE_ABOVE_LIMIT, + ) + + +@pytest.mark.parametrize( + "size", + [MAX_INITCODE_SIZE + 1, MAX_INITCODE_SIZE * 2], +) +def test_above_max_size_raw( + eof_test: EOFTestFiller, + size: int, +): + """ + Verify EOF container invalid above maximum size, regardless of header contents + """ + code = Op.INVALID * size + eof_test( + data=bytes(code), + expect_exception=EOFException.CONTAINER_SIZE_ABOVE_LIMIT, + ) + + +@pytest.mark.parametrize( + "code", + [ + pytest.param( + Container(sections=[Section.Code(code=Op.STOP, custom_size=MAX_INITCODE_SIZE)]), + id="1st_code_section", + ), + pytest.param( + Container( + sections=[ + Section.Code(code=Op.STOP), + Section.Code(code=Op.STOP, custom_size=MAX_INITCODE_SIZE), + ] + ), + id="2nd_code_section", + ), + pytest.param( + Container( + sections=[ + Section.Code(code=Op.STOP), + Section.Container(container=Op.STOP, custom_size=MAX_INITCODE_SIZE), + ] + ), + id="1st_container_section", + ), + pytest.param( + Container( + sections=[ + Section.Code(code=Op.STOP), + Section.Container(container=Op.STOP), + Section.Container(container=Op.STOP, custom_size=MAX_INITCODE_SIZE), + ] + ), + id="2nd_container_section", + ), + ], +) +def test_section_after_end_of_container( + eof_test: EOFTestFiller, + code: Container, +): + """ + Verify EOF container is invalid if any of sections declares above container size + """ + eof_test( + data=bytes(code), + expect_exception=EOFException.INVALID_SECTION_BODIES_SIZE, + ) From 3e0bbe28364aba7bf604d29aa9a46816f6ae42f6 Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:37:05 +0200 Subject: [PATCH 2/5] fix(tests): Adjust to container size limit --- .../eip3540_eof_v1/test_container_size.py | 4 +-- .../test_code_validation.py | 32 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) 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 f576772549..d382364548 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 @@ -30,12 +30,12 @@ def test_max_size( """ Verify EOF container valid at maximum size, invalid above """ - minimal_code = bytearray(bytes(VALID_CONTAINER)) # Expand the minimal EOF code by more noop code, reaching the desired target container size. code = Container( sections=[ Section.Code( - code=Op.JUMPDEST * (MAX_INITCODE_SIZE - len(minimal_code) + over_limit) + Op.STOP + code=Op.JUMPDEST * (MAX_INITCODE_SIZE - len(VALID_CONTAINER) + over_limit) + + Op.STOP ) ] ) diff --git a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py index 0ed7f755c3..816a6735c4 100644 --- a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py +++ b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py @@ -17,6 +17,13 @@ pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) +smallest_runtime_subcontainer = Container( + name="Runtime Subcontainer", + sections=[ + Section.Code(code=Op.STOP), + ], +) + VALID: List[Container] = [ Container( name="empty_data_section", @@ -48,10 +55,9 @@ Container( name="max_data_section", sections=[ - Section.Code( - code=Op.ADDRESS + Op.POP + Op.STOP, - ), - Section.Data(data=("1122334455667788" * 8 * 1024)[2:]), + Section.Code(code=Op.STOP), + # Hits the 49152 bytes limit for the entire container + Section.Data(data=(b"12345678" * 6 * 1024)[len(smallest_runtime_subcontainer) :]), ], ), Container( @@ -81,15 +87,6 @@ Section.Data(data="1122334455667788" * 16), ], ), - Container( - name="DATALOADN_max", - sections=[ - Section.Code( - code=Op.DATALOADN[0xFFFF - 32] + Op.POP + Op.STOP, - ), - Section.Data(data=("1122334455667788" * 8 * 1024)[2:]), - ], - ), ] INVALID: List[Container] = [ @@ -122,6 +119,15 @@ ], validity_error=EOFException.INVALID_DATALOADN_INDEX, ), + Container( + name="data_section_over_container_limit", + sections=[ + Section.Code(code=Op.STOP), + # Over the 49152 bytes limit for the entire container + Section.Data(data=(b"12345678" * 6 * 1024)[len(smallest_runtime_subcontainer) - 1 :]), + ], + validity_error=EOFException.CONTAINER_SIZE_ABOVE_LIMIT, + ), ] From 940d919ccfed046490316f79ca169017e941f923 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Thu, 27 Jun 2024 09:26:47 -0600 Subject: [PATCH 3/5] Update tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py --- .../prague/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d382364548..ea3771c4a1 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 @@ -12,7 +12,7 @@ from .. import EOF_FORK_NAME REFERENCE_SPEC_GIT_PATH = "EIPS/eip-3540.md" -REFERENCE_SPEC_VERSION = "" # todo +REFERENCE_SPEC_VERSION = "6b313505c75afa49a4f34de39c609ebebc7be87f" pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) From 54f13acf8db918ca253d8a19fb7448f39915624c Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Thu, 27 Jun 2024 09:34:46 -0600 Subject: [PATCH 4/5] Update tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py --- .../eip7692_eof_v1/eip7480_data_section/test_code_validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py index 816a6735c4..9e83c442ab 100644 --- a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py +++ b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py @@ -57,7 +57,7 @@ sections=[ Section.Code(code=Op.STOP), # Hits the 49152 bytes limit for the entire container - Section.Data(data=(b"12345678" * 6 * 1024)[len(smallest_runtime_subcontainer) :]), + Section.Data(data=b"\x00" * (MAX_INITCODE_SIZE - len(smallest_runtime_subcontainer))), ], ), Container( From 1f98d7dd69442c3f4eb1756fe1093ec0d34b25b0 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Thu, 27 Jun 2024 15:36:07 +0000 Subject: [PATCH 5/5] fix(tests): import --- .../eip7692_eof_v1/eip7480_data_section/test_code_validation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py index 9e83c442ab..fae49d0676 100644 --- a/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py +++ b/tests/prague/eip7692_eof_v1/eip7480_data_section/test_code_validation.py @@ -8,6 +8,7 @@ from ethereum_test_tools import EOFException, EOFTestFiller from ethereum_test_tools.eof.v1 import Container, Section +from ethereum_test_tools.eof.v1.constants import MAX_INITCODE_SIZE from ethereum_test_tools.vm.opcode import Opcodes as Op from .. import EOF_FORK_NAME