Skip to content

Commit 7236173

Browse files
refactor: optimize benchmark cases
1 parent f23e4ab commit 7236173

File tree

3 files changed

+115
-86
lines changed

3 files changed

+115
-86
lines changed

packages/testing/src/execution_testing/specs/benchmark.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,6 @@ def generate_repeated_code(
151151
if self.fixed_opcode_count is not None:
152152
max_iterations = min(max_iterations, 1000)
153153

154-
print(f"max_iterations: {max_iterations}")
155-
156154
# TODO: Unify the PUSH0 and PUSH1 usage.
157155
code = setup + Op.JUMPDEST + repeated_code * max_iterations
158156
if self.fixed_opcode_count is None:

tests/benchmark/compute/instruction/test_account_query.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -327,31 +327,20 @@ def test_extcodecopy_warm(
327327
benchmark_test: BenchmarkTestFiller,
328328
pre: Alloc,
329329
copied_size: int,
330-
gas_benchmark_value: int,
331330
) -> None:
332331
"""Benchmark EXTCODECOPY instruction."""
333332
copied_contract_address = pre.deploy_contract(
334333
code=Op.JUMPDEST * copied_size,
335334
)
336335

337-
execution_code = (
338-
Op.PUSH10(copied_size)
339-
+ Op.PUSH20(copied_contract_address)
340-
+ While(
341-
body=Op.EXTCODECOPY(Op.DUP4, 0, 0, Op.DUP2),
342-
)
343-
)
344-
execution_code_address = pre.deploy_contract(code=execution_code)
345-
tx = Transaction(
346-
to=execution_code_address,
347-
gas_limit=gas_benchmark_value,
348-
sender=pre.fund_eoa(),
336+
benchmark_test(
337+
code_generator=JumpLoopGenerator(
338+
setup=Op.PUSH10(copied_size) + Op.PUSH20(copied_contract_address),
339+
attack_block=Op.EXTCODECOPY(Op.DUP4, 0, 0, Op.DUP2),
340+
),
349341
)
350342

351-
benchmark_test(tx=tx)
352-
353343

354-
@pytest.mark.repricing(absent_target=False)
355344
@pytest.mark.parametrize(
356345
"opcode",
357346
[

tests/benchmark/compute/instruction/test_call_context.py

Lines changed: 110 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@
2222
Fork,
2323
JumpLoopGenerator,
2424
Op,
25-
Transaction,
2625
)
2726

2827
from tests.benchmark.compute.helpers import (
29-
CallDataOrigin,
3028
ReturnDataStyle,
3129
)
3230

@@ -64,44 +62,50 @@ def test_calldatasize(
6462
)
6563

6664

67-
@pytest.mark.repricing(non_zero_value=True, from_origin=True)
6865
@pytest.mark.parametrize("non_zero_value", [True, False])
69-
@pytest.mark.parametrize("from_origin", [True, False])
70-
def test_callvalue(
66+
def test_callvalue_from_origin(
7167
benchmark_test: BenchmarkTestFiller,
72-
pre: Alloc,
73-
fork: Fork,
7468
non_zero_value: bool,
75-
from_origin: bool,
7669
) -> None:
7770
"""
78-
Benchmark CALLVALUE instruction.
79-
80-
- non_zero_value: whether opcode must return non-zero value.
81-
- from_origin: whether the call frame is the immediate one
82-
from the transaction or a previous CALL.
71+
Benchmark CALLVALUE instruction from origin.
8372
"""
84-
code_address = JumpLoopGenerator(
85-
attack_block=Op.POP(Op.CALLVALUE)
86-
).deploy_contracts(pre=pre, fork=fork)
73+
benchmark_test(
74+
code_generator=JumpLoopGenerator(
75+
attack_block=Op.POP(Op.CALLVALUE),
76+
tx_kwargs={"value": int(non_zero_value)},
77+
),
78+
)
8779

88-
if from_origin:
89-
tx_to = code_address
90-
else:
91-
entry_code = (
92-
Op.JUMPDEST
93-
+ Op.CALL(address=code_address, value=1 if non_zero_value else 0)
94-
+ Op.JUMP(Op.PUSH0)
95-
)
96-
tx_to = pre.deploy_contract(code=entry_code, balance=1_000_000)
9780

98-
tx = Transaction(
99-
to=tx_to,
100-
value=1 if non_zero_value and from_origin else 0,
101-
sender=pre.fund_eoa(),
81+
@pytest.mark.parametrize("non_zero_value", [True, False])
82+
def test_callvalue_from_call(
83+
benchmark_test: BenchmarkTestFiller,
84+
pre: Alloc,
85+
non_zero_value: bool,
86+
fork: Fork,
87+
) -> None:
88+
"""
89+
Benchmark CALLVALUE instruction from call.
90+
"""
91+
code_address = pre.deploy_contract(
92+
code=Op.CALLVALUE * fork.max_stack_height()
93+
)
94+
benchmark_test(
95+
code_generator=JumpLoopGenerator(
96+
attack_block=Op.POP(
97+
Op.CALL(
98+
address=code_address,
99+
value=int(non_zero_value),
100+
args_offset=Op.PUSH0,
101+
args_size=Op.PUSH0,
102+
ret_offset=Op.PUSH0,
103+
ret_size=Op.PUSH0,
104+
)
105+
),
106+
tx_kwargs={"value": 10**18},
107+
),
102108
)
103-
104-
benchmark_test(tx=tx)
105109

106110

107111
@pytest.mark.repricing(calldata=b"")
@@ -128,12 +132,77 @@ def test_calldataload(
128132

129133

130134
@pytest.mark.parametrize(
131-
"origin",
135+
"size",
136+
[
137+
pytest.param(0, id="0 bytes"),
138+
pytest.param(100, id="100 bytes"),
139+
pytest.param(10 * 1024, id="10KiB"),
140+
pytest.param(1024 * 1024, id="1MiB"),
141+
],
142+
)
143+
@pytest.mark.parametrize(
144+
"fixed_src_dst",
132145
[
133-
pytest.param(CallDataOrigin.TRANSACTION, id="transaction"),
134-
pytest.param(CallDataOrigin.CALL, id="call"),
146+
True,
147+
False,
135148
],
136149
)
150+
@pytest.mark.parametrize(
151+
"non_zero_data",
152+
[
153+
True,
154+
False,
155+
],
156+
)
157+
def test_calldatacopy_from_origin(
158+
benchmark_test: BenchmarkTestFiller,
159+
fork: Fork,
160+
size: int,
161+
fixed_src_dst: bool,
162+
non_zero_data: bool,
163+
tx_gas_limit: int,
164+
) -> None:
165+
"""Benchmark CALLDATACOPY instruction."""
166+
if size == 0 and non_zero_data:
167+
pytest.skip("Non-zero data with size 0 is not applicable.")
168+
169+
# If `non_zero_data` is True, we fill the calldata with deterministic
170+
# random data. Note that if `size == 0` and `non_zero_data` is a skipped
171+
# case.
172+
data = Bytes([i % 256 for i in range(size)]) if non_zero_data else Bytes()
173+
174+
intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
175+
min_gas = intrinsic_gas_calculator(calldata=data)
176+
if min_gas > tx_gas_limit:
177+
pytest.skip(
178+
"Minimum gas required for calldata ({min_gas}) is greater "
179+
"than the gas limit"
180+
)
181+
182+
# We create the contract that will be doing the CALLDATACOPY multiple
183+
# times.
184+
#
185+
# If `non_zero_data` is True, we leverage CALLDATASIZE for the copy
186+
# length. Otherwise, since we
187+
# don't send zero data explicitly via calldata, PUSH the target size and
188+
# use DUP1 to copy it.
189+
setup = Op.CALLDATASIZE if non_zero_data or size == 0 else Op.PUSH3(size)
190+
src_dst = 0 if fixed_src_dst else Op.AND(Op.GAS, 7)
191+
attack_block = Op.CALLDATACOPY(
192+
src_dst,
193+
src_dst,
194+
Op.DUP1,
195+
)
196+
197+
benchmark_test(
198+
code_generator=JumpLoopGenerator(
199+
setup=setup,
200+
attack_block=attack_block,
201+
tx_kwargs={"data": data},
202+
)
203+
)
204+
205+
137206
@pytest.mark.parametrize(
138207
"size",
139208
[
@@ -157,11 +226,9 @@ def test_calldataload(
157226
False,
158227
],
159228
)
160-
def test_calldatacopy(
229+
def test_calldatacopy_from_call(
161230
benchmark_test: BenchmarkTestFiller,
162-
pre: Alloc,
163231
fork: Fork,
164-
origin: CallDataOrigin,
165232
size: int,
166233
fixed_src_dst: bool,
167234
non_zero_data: bool,
@@ -192,46 +259,21 @@ def test_calldatacopy(
192259
# don't send zero data explicitly via calldata, PUSH the target size and
193260
# use DUP1 to copy it.
194261
setup = Bytecode() if non_zero_data or size == 0 else Op.PUSH3(size)
195-
src_dst = 0 if fixed_src_dst else Op.MOD(Op.GAS, 7)
262+
src_dst = 0 if fixed_src_dst else Op.AND(Op.GAS, 7)
196263
attack_block = Op.CALLDATACOPY(
197264
src_dst,
198265
src_dst,
199266
Op.CALLDATASIZE if non_zero_data or size == 0 else Op.DUP1,
200267
)
201268

202-
code_address = JumpLoopGenerator(
203-
setup=setup, attack_block=attack_block
204-
).deploy_contracts(pre=pre, fork=fork)
205-
206-
tx_target = code_address
207-
208-
# If the origin is CALL, we need to create a contract that will call the
209-
# target contract with the calldata.
210-
if origin == CallDataOrigin.CALL:
211-
# If `non_zero_data` is False we leverage just using zeroed memory.
212-
# Otherwise, we copy the calldata received from the transaction.
213-
setup = (
214-
Op.CALLDATACOPY(Op.PUSH0, Op.PUSH0, Op.CALLDATASIZE)
215-
if non_zero_data
216-
else Bytecode()
217-
) + Op.JUMPDEST
218-
arg_size = Op.CALLDATASIZE if non_zero_data else size
219-
attack_block = Op.STATICCALL(
220-
address=code_address, args_offset=Op.PUSH0, args_size=arg_size
269+
benchmark_test(
270+
code_generator=ExtCallGenerator(
271+
setup=setup,
272+
attack_block=attack_block,
273+
tx_kwargs={"data": data},
221274
)
222-
223-
tx_target = JumpLoopGenerator(
224-
setup=setup, attack_block=attack_block
225-
).deploy_contracts(pre=pre, fork=fork)
226-
227-
tx = Transaction(
228-
to=tx_target,
229-
data=data,
230-
sender=pre.fund_eoa(),
231275
)
232276

233-
benchmark_test(tx=tx)
234-
235277

236278
@pytest.mark.repricing(
237279
returned_size=1,

0 commit comments

Comments
 (0)