Skip to content

Commit

Permalink
feat(fw): allow adding verbatim bytes to Bytecode (#1119)
Browse files Browse the repository at this point in the history
* feat(fw): allow adding verbatim bytes to Bytecode

* fix: linting, tests

---------

Co-authored-by: Mario Vega <marioevz@gmail.com>
  • Loading branch information
chfast and marioevz authored Jan 27, 2025
1 parent 2aa8e12 commit b8edede
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 4 deletions.
11 changes: 9 additions & 2 deletions src/ethereum_test_vm/bytecode.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def __eq__(self, other):
and self.max_stack_height == other.max_stack_height
and self.min_stack_height == other.min_stack_height
)
if isinstance(other, SupportsBytes):
if isinstance(other, SupportsBytes) or isinstance(other, bytes):
return bytes(self) == bytes(other)
raise NotImplementedError(f"Unsupported type for comparison: {type(other)}")

Expand All @@ -134,11 +134,18 @@ def __hash__(self):
)
)

def __add__(self, other: "Bytecode | int | None") -> "Bytecode":
def __add__(self, other: "Bytecode | bytes | int | None") -> "Bytecode":
"""Concatenate the bytecode representation with another bytecode object."""
if other is None or (isinstance(other, int) and other == 0):
# Edge case for sum() function
return self

if isinstance(other, bytes):
c = Bytecode(self)
c._bytes_ += other
c._name_ = ""
return c

assert isinstance(other, Bytecode), "Can only concatenate Bytecode instances"
# Figure out the stack height after executing the two opcodes.
a_pop, a_push = self.popped_stack_items, self.pushed_stack_items
Expand Down
19 changes: 19 additions & 0 deletions src/ethereum_test_vm/tests/test_vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,3 +412,22 @@ def test_opcode_comparison():
assert Op.ADD == Op.ADD
assert Op.ADD != Op.STOP
assert Op.ADD > Op.STOP


def test_bytecode_concatenation_with_bytes():
"""
Test that the bytecode can be concatenated with bytes.
Bytes work as verbatim code and don't affect the bytecode properties.
"""
base = Op.PUSH1[0xFF] + Op.NOT
assert str(base) == ""

code = base + b"\x01\x02"
assert code == bytes([0x60, 0xFF, 0x19, 0x01, 0x02])

assert str(code) == ""
assert code.popped_stack_items == code.popped_stack_items
assert code.pushed_stack_items == code.pushed_stack_items
assert code.max_stack_height == code.max_stack_height
assert code.min_stack_height == code.min_stack_height
assert code.terminating == code.terminating
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def test_rjump_truncated_rjump_2(
):
"""EOF1I4200_0002 (Invalid) EOF code containing truncated RJUMP."""
eof_test(
data=Container.Code(Op.RJUMP + Op.STOP),
data=Container.Code(Op.RJUMP + b"\x00"),
expect_exception=EOFException.TRUNCATED_INSTRUCTION,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def test_rjumpi_truncated_2(
data=Container(
sections=[
Section.Code(
code=Op.PUSH1(0) + Op.RJUMPI + Op.STOP,
code=Op.PUSH1(0) + Op.RJUMPI + b"\x00",
)
],
),
Expand Down

0 comments on commit b8edede

Please sign in to comment.