Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EOF: efExample validInvalid tests #535

Merged
merged 9 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Test fixtures for use by clients are available for each release on the [Github r
### 🧪 Test Cases

- ✨ Add `test_double_kill` and `test_recreate` which test resurrection of accounts killed with `SELFDESTRUCT` ([#488](https://github.com/ethereum/execution-spec-tests/pull/488)).
- ✨ Add eof example valid invalid tests from ori, fetch EOF Container implementation ([#535](https://github.com/ethereum/execution-spec-tests/pull/535)).

### 🛠️ Framework

Expand Down
46 changes: 42 additions & 4 deletions src/ethereum_test_tools/eof/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,22 @@ class Section(CopyValidateModel):
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:
Expand Down Expand Up @@ -197,8 +213,18 @@ def list_header(sections: List["Section"]) -> bytes:
return b"".join(s.header for s in sections)

h = sections[0].kind.to_bytes(HEADER_SECTION_KIND_BYTE_LENGTH, "big")
h += len(sections).to_bytes(HEADER_SECTION_COUNT_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")

Expand Down Expand Up @@ -333,8 +359,20 @@ def bytecode(self) -> bytes:

# Add type section if needed
if self.auto_type_section.any() and count_sections(sections, SectionKind.TYPE) == 0:
type_section_data = b"".join(s.type_definition for s in sections)
sections = [Section(kind=SectionKind.TYPE, data=type_section_data)] + sections
# 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:
Expand Down Expand Up @@ -371,7 +409,7 @@ def bytecode(self) -> bytes:
for s in body_sections:
if s.kind == SectionKind.TYPE and self.auto_type_section == AutoSection.ONLY_HEADER:
continue
if s.data:
if s.data and not s.skip_body_listing:
c += s.data

# Add extra (garbage)
Expand Down
7 changes: 6 additions & 1 deletion src/ethereum_test_tools/exceptions/evmone_exceptions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Evmone eof exceptions ENUM -> str mapper
"""

from dataclasses import dataclass

from bidict import frozenbidict
Expand Down Expand Up @@ -39,11 +40,15 @@ class EvmoneExceptionMapper:
ExceptionMessage(
EOFException.INVALID_SECTION_BODIES_SIZE, "err: invalid_section_bodies_size"
),
ExceptionMessage(EOFException.INVALID_TYPE_SIZE, "err: invalid_type_section_size"),
ExceptionMessage(EOFException.INVALID_TYPE_SECTION_SIZE, "err: invalid_type_section_size"),
ExceptionMessage(EOFException.INCOMPLETE_SECTION_SIZE, "err: incomplete_section_size"),
ExceptionMessage(EOFException.INCOMPLETE_SECTION_NUMBER, "err: incomplete_section_number"),
ExceptionMessage(EOFException.TOO_MANY_CODE_SECTIONS, "err: too_many_code_sections"),
ExceptionMessage(EOFException.ZERO_SECTION_SIZE, "err: zero_section_size"),
ExceptionMessage(EOFException.UNDEFINED_INSTRUCTION, "err: undefined_instruction"),
ExceptionMessage(EOFException.UNREACHABLE_INSTRUCTIONS, "err: unreachable_instructions"),
ExceptionMessage(EOFException.INVALID_RJUMP_DESTINATION, "err: invalid_rjump_destination"),
ExceptionMessage(EOFException.UNREACHABLE_CODE_SECTIONS, "err: unreachable_code_sections"),
)

def __init__(self) -> None:
Expand Down
19 changes: 18 additions & 1 deletion src/ethereum_test_tools/exceptions/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ class EOFException(ExceptionBase):
Indicates that exception string is not mapped to an exception enum
"""

UNDEFINED_INSTRUCTION = auto()
"""
EOF container has undefined instruction in it's body code
"""

UNKNOWN_VERSION = auto()
"""
EOF container has an unknown version
Expand All @@ -214,11 +219,15 @@ class EOFException(ExceptionBase):
"""
EOF container version bytes mismatch
"""
INVALID_RJUMP_DESTINATION = auto()
"""
Code has RJUMP instruction with invalid parameters
"""
MISSING_TYPE_HEADER = auto()
"""
EOF container missing types section
"""
INVALID_TYPE_SIZE = auto()
INVALID_TYPE_SECTION_SIZE = auto()
"""
EOF container types section has wrong size
"""
Expand Down Expand Up @@ -286,6 +295,14 @@ class EOFException(ExceptionBase):
"""
EOF container's code missing STOP bytecode at it's end
"""
UNREACHABLE_INSTRUCTIONS = auto()
"""
EOF container's code have instructions that are unreachable
"""
UNREACHABLE_CODE_SECTIONS = auto()
"""
EOF container's body have code sections that are unreachable
"""


"""
Expand Down
8 changes: 4 additions & 4 deletions src/ethereum_test_tools/spec/eof/eof_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class UnexpectedEOFException(EOFBaseException):
def __init__(self, *, code: Bytes, got: str):
message = (
"Expected EOF code to be valid, but an exception occurred:\n"
f" Code: {self.format_code(code)}\n"
"Expected: No Exception\n"
f" Got: {got}"
f" Code: {self.format_code(code)}\n"
f"Expected: No Exception\n"
f" Got: {got}"
)
super().__init__(message)

Expand All @@ -64,7 +64,7 @@ def __init__(self, *, code: Bytes, expected: str):
"Expected EOF code to be invalid, but no exception was raised:\n"
f" Code: {self.format_code(code)}\n"
f"Expected: {expected}\n"
" Got: No Exception"
f" Got: No Exception"
)
super().__init__(message)

Expand Down
11 changes: 7 additions & 4 deletions src/ethereum_test_tools/tests/test_vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
[
Op.ORIGIN.int(),
Op.RJUMPV.int(),
0x03, # Data portion, defined by the [1, 2, 3] argument
0x02, # Data portion, defined by the [1, 2, 3] argument
0x00,
0x01,
0x00,
Expand All @@ -203,7 +203,7 @@
bytes(
[
Op.RJUMPV.int(),
0x03,
0x02,
0xFF,
0xFF,
0xFF,
Expand All @@ -218,7 +218,7 @@
bytes(
[
Op.RJUMPV.int(),
0x05,
0x04,
0x00,
0x00,
0x00,
Expand All @@ -238,7 +238,7 @@
[
Op.ORIGIN.int(),
Op.RJUMPV.int(),
0x03, # Data portion, defined by the [1, 2, 3] argument
0x02, # Data portion, defined by the [1, 2, 3] argument
0x00,
0x01,
0x00,
Expand All @@ -258,6 +258,9 @@
]
),
),
(Op.RJUMPV[0, 3, 6, 9], bytes.fromhex("e2030000000300060009")),
(Op.RJUMPV[2, 0], bytes.fromhex("e20100020000")),
(Op.RJUMPV[b"\x02\x00\x02\xFF\xFF"], bytes.fromhex("e2020002ffff")),
],
)
def test_opcodes(opcodes: bytes, expected: bytes):
Expand Down
6 changes: 3 additions & 3 deletions src/ethereum_test_tools/vm/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,14 @@ def _rjumpv_encoder(*args: int | bytes | Iterable[int]) -> bytes:
elif isinstance(args[0], Iterable):
int_args = list(args[0])
return b"".join(
[len(int_args).to_bytes(RJUMPV_MAX_INDEX_BYTE_LENGTH, "big")]
[(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).to_bytes(RJUMPV_MAX_INDEX_BYTE_LENGTH, "big")]
[(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
Expand Down Expand Up @@ -4932,7 +4932,7 @@ class Opcodes(Opcode, Enum):
3
"""

JUMPF = Opcode(0xB1, data_portion_length=2)
JUMPF = Opcode(0xE5, data_portion_length=2)
"""
!!! Note: This opcode is under development

Expand Down
12 changes: 6 additions & 6 deletions tests/prague/eip3540_eof_v1/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@
Section.Code(Op.STOP),
],
auto_type_section=AutoSection.NONE,
# TODO the exception must be about type section EOFException.INVALID_TYPE_SIZE,
# TODO the exception must be about type section EOFException.INVALID_TYPE_SECTION_SIZE,
validity_error=EOFException.ZERO_SECTION_SIZE,
),
Container(
Expand All @@ -435,7 +435,7 @@
Section.Code(Op.STOP),
],
auto_type_section=AutoSection.NONE,
validity_error=EOFException.INVALID_TYPE_SIZE,
validity_error=EOFException.INVALID_TYPE_SECTION_SIZE,
),
Container(
name="type_section_too_small_2",
Expand All @@ -444,7 +444,7 @@
Section.Code(Op.STOP),
],
auto_type_section=AutoSection.NONE,
validity_error=EOFException.INVALID_TYPE_SIZE,
validity_error=EOFException.INVALID_TYPE_SECTION_SIZE,
),
Container(
name="type_section_too_big",
Expand All @@ -453,7 +453,7 @@
Section.Code(Op.STOP),
],
auto_type_section=AutoSection.NONE,
validity_error=EOFException.INVALID_TYPE_SIZE,
validity_error=EOFException.INVALID_TYPE_SECTION_SIZE,
),
]

Expand Down Expand Up @@ -593,7 +593,7 @@
Section.Data(data="0x00", force_type_listing=True),
Section.Code(Op.STOP),
],
validity_error=EOFException.INVALID_TYPE_SIZE,
validity_error=EOFException.INVALID_TYPE_SECTION_SIZE,
),
Container(
name="code_sections_above_1024",
Expand All @@ -607,7 +607,7 @@
Section.Code(Op.STOP),
],
auto_type_section=AutoSection.NONE,
validity_error=EOFException.INVALID_TYPE_SIZE,
validity_error=EOFException.INVALID_TYPE_SECTION_SIZE,
),
Container(
name="single_code_section_incomplete_type_2",
Expand Down
Loading