Skip to content

Commit 41d4d35

Browse files
committed
add modexp tests
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
1 parent 283ca18 commit 41d4d35

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

0 commit comments

Comments
 (0)