Skip to content

Commit 8195dfe

Browse files
authored
new(tests): add EOF execution at maximum stack height (#1443)
Add new tests for validation and execution at the maximum runtime operand stack height (1024).
1 parent 13aeeed commit 8195dfe

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""Test execution of EOF code in the context of the operand stack height."""
2+
3+
import pytest
4+
5+
from ethereum_test_exceptions import EOFException
6+
from ethereum_test_tools import Account, EOFStateTestFiller
7+
from ethereum_test_tools.vm.opcode import Opcodes as Op
8+
from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT
9+
from ethereum_test_types.eof.v1 import Container, Section
10+
from ethereum_test_types.eof.v1.constants import (
11+
MAX_CODE_INPUTS,
12+
MAX_STACK_INCREASE_LIMIT,
13+
NON_RETURNING_SECTION,
14+
)
15+
16+
from .. import EOF_FORK_NAME
17+
18+
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-5450.md"
19+
REFERENCE_SPEC_VERSION = "f20b164b00ae5553f7536a6d7a83a0f254455e09"
20+
21+
pytestmark = pytest.mark.valid_from(EOF_FORK_NAME)
22+
23+
24+
@pytest.mark.parametrize("code_inputs", [0, 1, 16, 127, 128])
25+
@pytest.mark.parametrize("call_op", [Op.CALLF, Op.JUMPF])
26+
def test_execution_at_max_stack_height(
27+
eof_state_test: EOFStateTestFiller, code_inputs: int, call_op: Op
28+
):
29+
"""
30+
Test execution at the maximum runtime operand stack height (1024).
31+
EOF doesn't allow to increase the stack height of a single code section more than 1023.
32+
The effect of the maximum runtime stack height is achieved by using non-zero number
33+
of the code section inputs and increasing the runtime stack to the limit accordingly.
34+
The test pushes consecutive numbers starting from 0 (including inputs).
35+
At the maximum stack height SSTORE is used so it should store 1022 at key 1023.
36+
"""
37+
max_stack_increase = MAX_RUNTIME_STACK_HEIGHT - code_inputs
38+
container = Container(
39+
sections=[
40+
Section.Code(
41+
(
42+
sum(Op.PUSH1(x) for x in range(code_inputs))
43+
+ call_op[1]
44+
+ (Op.STOP if call_op == Op.CALLF else b"")
45+
),
46+
),
47+
Section.Code(
48+
sum(Op.PUSH2(x) for x in range(code_inputs, MAX_RUNTIME_STACK_HEIGHT))
49+
+ Op.SSTORE
50+
+ Op.POP * (MAX_RUNTIME_STACK_HEIGHT - Op.SSTORE.popped_stack_items)
51+
+ (Op.RETF if call_op == Op.CALLF else Op.STOP),
52+
code_inputs=code_inputs,
53+
code_outputs=0 if call_op == Op.CALLF else NON_RETURNING_SECTION,
54+
max_stack_increase=max_stack_increase,
55+
),
56+
],
57+
)
58+
59+
exception = None
60+
if max_stack_increase > MAX_STACK_INCREASE_LIMIT:
61+
exception = EOFException.MAX_STACK_INCREASE_ABOVE_LIMIT
62+
elif code_inputs > MAX_CODE_INPUTS:
63+
exception = EOFException.INPUTS_OUTPUTS_NUM_ABOVE_LIMIT
64+
65+
eof_state_test(
66+
container=container,
67+
expect_exception=exception,
68+
container_post=Account(
69+
storage={MAX_RUNTIME_STACK_HEIGHT - 1: MAX_RUNTIME_STACK_HEIGHT - 2}
70+
),
71+
)

0 commit comments

Comments
 (0)