Skip to content

Commit 91687b7

Browse files
authored
feat(fw): add max_stack_increase to EOF Section.Code (#1446)
The `max_stack_increase` is complementary but preferred to `max_stack_height`. Both cannot be set at the same time.
1 parent a1c4eef commit 91687b7

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

src/ethereum_test_types/eof/v1/__init__.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ class Section(CopyValidateModel):
133133
Data stack items produced by or expected at the end of this code section
134134
(function)
135135
"""
136-
max_stack_height: int = 0
136+
max_stack_increase: int | None = None
137+
"""
138+
Maximum operand stack height increase above the code section inputs.
139+
"""
140+
max_stack_height: int | None = None
137141
"""
138142
Maximum height data stack reaches during execution of code section.
139143
"""
@@ -180,9 +184,10 @@ def type_definition(self) -> bytes:
180184
if self.kind != SectionKind.CODE and not self.force_type_listing:
181185
return bytes()
182186

183-
code_inputs, code_outputs, max_stack_height = (
187+
code_inputs, code_outputs, max_stack_increase, max_stack_height = (
184188
self.code_inputs,
185189
self.code_outputs,
190+
self.max_stack_increase,
186191
self.max_stack_height,
187192
)
188193
if self.auto_max_stack_height or self.auto_code_inputs_outputs:
@@ -191,15 +196,20 @@ def type_definition(self) -> bytes:
191196
auto_code_outputs,
192197
auto_max_height,
193198
) = compute_code_stack_values(self.data)
194-
if self.auto_max_stack_height:
195-
max_stack_height = auto_max_height
196199
if self.auto_code_inputs_outputs:
197200
code_inputs, code_outputs = (
198201
auto_code_inputs,
199202
auto_code_outputs,
200203
)
204+
if self.auto_max_stack_height:
205+
max_stack_increase = auto_max_height - code_inputs
201206

202-
max_stack_increase = max_stack_height - code_inputs
207+
if max_stack_increase is not None:
208+
assert max_stack_height is None
209+
elif max_stack_height is not None:
210+
max_stack_increase = max_stack_height - code_inputs
211+
else:
212+
max_stack_increase = 0
203213
assert max_stack_increase >= 0, "incorrect max stack height value"
204214
return (
205215
code_inputs.to_bytes(length=TYPES_INPUTS_BYTE_LENGTH, byteorder="big")
@@ -269,8 +279,13 @@ def Code( # noqa: N802
269279
if code is None:
270280
code = Bytecode()
271281
kwargs.pop("kind", None)
272-
if "max_stack_height" not in kwargs and isinstance(code, Bytecode):
273-
kwargs["max_stack_height"] = code.max_stack_height
282+
if (
283+
"max_stack_height" not in kwargs
284+
and "max_stack_increase" not in kwargs
285+
and isinstance(code, Bytecode)
286+
):
287+
# If not specified, take the max_stack_increase from the Bytecode.
288+
kwargs["max_stack_increase"] = code.max_stack_height - kwargs.get("code_inputs", 0)
274289
return cls(kind=SectionKind.CODE, data=code, **kwargs)
275290

276291
@classmethod

tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,28 @@ def test_eof_example(eof_test: EOFTestFiller):
2525
Section.Code(
2626
code=Op.CALLF[1](Op.PUSH0) + Op.STOP, # bytecode to be deployed in the body
2727
# Code: call section 1 with a single zero as input, then stop.
28-
max_stack_height=1, # define code header (in body) stack size
28+
max_stack_increase=1, # define code header (in body) stack size
2929
),
3030
# There can be multiple code sections
3131
Section.Code(
3232
# Remove input and call section 2 with no inputs, then remove output and return
3333
code=Op.POP + Op.CALLF[2]() + Op.POP + Op.RETF,
3434
code_inputs=1,
3535
code_outputs=0,
36-
max_stack_height=1,
36+
max_stack_increase=0,
3737
),
3838
Section.Code(
3939
# Call section 3 with two inputs (address twice), return
4040
code=Op.CALLF[3](Op.DUP1, Op.ADDRESS) + Op.POP + Op.POP + Op.RETF,
4141
code_outputs=1,
42-
max_stack_height=3,
42+
max_stack_increase=3,
4343
),
4444
Section.Code(
4545
# Duplicate one input and return
4646
code=Op.DUP1 + Op.RETF,
4747
code_inputs=2,
4848
code_outputs=3,
49-
max_stack_height=3,
49+
max_stack_increase=1,
5050
),
5151
# DATA section
5252
Section.Data("0xef"),

tests/osaka/eip7692_eof_v1/eip4750_functions/test_code_validation.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ def test_callf_stack_overflow_variable_stack_3(eof_test: EOFTestFiller, stack_he
787787
),
788788
],
789789
)
790+
assert container.sections[0].max_stack_height is not None
790791
stack_overflow = (
791792
container.sections[0].max_stack_height + stack_height > MAX_RUNTIME_OPERAND_STACK_HEIGHT
792793
)
@@ -925,6 +926,7 @@ def test_callf_with_inputs_stack_overflow(
925926
code_section,
926927
],
927928
)
929+
assert code_section.max_stack_height is not None
928930
exception = None
929931
if (
930932
push_stack + code_section.max_stack_height - code_section.code_inputs
@@ -1055,6 +1057,7 @@ def test_callf_with_inputs_stack_overflow_variable_stack(
10551057
],
10561058
)
10571059
initial_stack = 3 # Initial items in the scak
1060+
assert code_section.max_stack_height is not None
10581061
exception = None
10591062
if (
10601063
push_stack + initial_stack + code_section.max_stack_height - code_section.code_inputs

0 commit comments

Comments
 (0)