Skip to content

Commit 117f257

Browse files
committed
add modexp tests
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
1 parent d3deb14 commit 117f257

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

tests/zkevm/test_worst_compute.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,80 @@ def test_worst_keccak(
104104
post={},
105105
blocks=[Block(txs=[tx])],
106106
)
107+
108+
109+
@pytest.mark.zkevm
110+
@pytest.mark.valid_from("Cancun")
111+
@pytest.mark.parametrize(
112+
"gas_limit",
113+
[
114+
36_000_000,
115+
60_000_000,
116+
100_000_000,
117+
300_000_000,
118+
],
119+
)
120+
@pytest.mark.parametrize(
121+
"base_mod_length, exp_length",
122+
[
123+
(32, 32),
124+
],
125+
)
126+
def test_worst_modexp(
127+
blockchain_test: BlockchainTestFiller,
128+
pre: Alloc,
129+
fork: Fork,
130+
gas_limit: int,
131+
base_mod_length: int,
132+
exp_length: int,
133+
):
134+
"""Test running a block with as many MODEXP calls as possible."""
135+
env = Environment(gas_limit=gas_limit)
136+
137+
base = 2 ** (8 * base_mod_length) - 1
138+
mod = 2 ** (8 * base_mod_length) - 1
139+
exp = 2 ** (8 * exp_length) - 1
140+
141+
# EIP-7883 (TODO: generalize)
142+
mul_complexity = math.ceil(base_mod_length / 8) ** 2
143+
iter_complexity = exp.bit_length() - 1
144+
gas_cost = math.floor((mul_complexity * iter_complexity) / 3)
145+
146+
mem_prep = (
147+
Op.MSTORE(0 * 32, 32)
148+
+ Op.MSTORE(1 * 32, 32)
149+
+ Op.MSTORE(2 * 32, 32)
150+
+ Op.MSTORE(3 * 32, base)
151+
+ Op.MSTORE(4 * 32, exp)
152+
+ Op.MSTORE(5 * 32, mod)
153+
)
154+
155+
attack_block = Op.STATICCALL(gas_cost, 0x5, 0, 32 * 6, 0, 0) + Op.POP
156+
157+
jumpdest = Op.JUMPDEST
158+
jump_back = Op.JUMP(len(mem_prep))
159+
max_iters_loop = (MAX_CODE_SIZE - len(mem_prep) - len(jumpdest) - len(jump_back)) // len(
160+
attack_block
161+
)
162+
code = mem_prep + jumpdest + sum([attack_block] * max_iters_loop) + jump_back
163+
if len(code) > MAX_CODE_SIZE:
164+
# Must never happen, but keep it as a sanity check.
165+
raise ValueError(f"Code size {len(code)} exceeds maximum code size {MAX_CODE_SIZE}")
166+
167+
code_address = pre.deploy_contract(code=bytes(code))
168+
169+
tx = Transaction(
170+
to=code_address,
171+
gas_limit=gas_limit,
172+
gas_price=10,
173+
sender=pre.fund_eoa(),
174+
data=[],
175+
value=0,
176+
)
177+
178+
blockchain_test(
179+
env=env,
180+
pre=pre,
181+
post={},
182+
blocks=[Block(txs=[tx])],
183+
)

0 commit comments

Comments
 (0)