Skip to content

Commit e188a6c

Browse files
feat(test): add gas formula egde cases
1 parent 289811a commit e188a6c

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,90 @@ def test_modexp_entry_points(
292292
gas_limit=tx_gas_limit,
293293
)
294294
state_test(pre=pre, tx=tx, post={})
295+
296+
297+
def create_modexp_variable_gas_test_cases():
298+
"""
299+
Create test cases for ModExp variable gas cost testing.
300+
301+
Returns:
302+
List of pytest.param objects for the test cases
303+
304+
"""
305+
# Test case definitions: (base, exponent, modulus, expected_result, test_id)
306+
test_cases = [
307+
("", "", "", "", "Z0"),
308+
("01" * 16, "00" * 16, "02" * 16, "00" * 15 + "01", "S0"),
309+
("01" * 16, "00" * 15 + "03", "02" * 16, "01" * 16, "S1"),
310+
("01" * 32, "FF" * 32, "02" * 32, "01" * 32, "S2"),
311+
("01" * 16, "00" * 40, "02" * 16, "00" * 15 + "01", "S3"),
312+
("01" * 16, "00" * 39 + "01", "02" * 16, "01" * 16, "S4"),
313+
("01" * 24, "00", "02" * 8, "00" * 7 + "01", "S5"),
314+
("01" * 8, "01", "02" * 24, "00" * 16 + "01" * 8, "S6"),
315+
("01" * 40, "00" * 16, "02" * 40, "00" * 39 + "01", "L0"),
316+
("01" * 40, "FF" * 32, "02" * 40, "01" * 40, "L1"),
317+
("01" * 40, "00" * 40, "02" * 40, "00" * 39 + "01", "L2"),
318+
("01" * 40, "00" * 39 + "01", "02" * 40, "01" * 40, "L3"),
319+
("01" * 48, "01", "02" * 16, "01" * 16, "L4"),
320+
("01" * 16, "00" * 40, "02" * 48, "00" * 47 + "01", "L5"),
321+
]
322+
323+
# Gas calculation parameters:
324+
#
325+
# Please refer to EIP-7883 for details of each function in the gas calculation.
326+
# Link: https://eips.ethereum.org/EIPS/eip-7883
327+
#
328+
# - calculate_multiplication_complexity:
329+
# - Comp: if max_length <= 32 bytes, it is Small (S), otherwise it is Large (L)
330+
# - Rel (Length Relation): base < modulus (<), base = modulus (=), base > modulus (>)
331+
#
332+
# - calculate_iteration_count
333+
# - Iter (Iteration Case):
334+
# - A: exp≤32 and exp=0
335+
# - B: exp≤32 and exp≠0
336+
# - C: exp>32 and low256=0
337+
# - D: exp>32 and low256≠0
338+
#
339+
# - calculate_gas_cost
340+
# - Clamp: True if raw gas < 500 (clamped to 500), False if raw gas ≥ 500 (no clamping)
341+
342+
# Test case coverage table:
343+
# ┌─────┬──────┬─────┬──────┬───────┬─────────┬─────────────────────────────────────────────┐
344+
# │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │
345+
# ├─────┼──────┼─────┼──────┼───────┼─────────┼─────────────────────────────────────────────┤
346+
# │ Z0 │ - │ - │ - │ - │ 500 │ Zero case - empty inputs │
347+
# │ S0 │ S │ = │ A │ True │ 500 │ Small, equal, zero exponent, clamped │
348+
# │ S1 │ S │ = │ B │ True │ 500 │ Small, equal, small exp, clamped │
349+
# │ S2 │ S │ = │ B │ False │ 4080 │ Small, equal, large exp, unclamped │
350+
# │ S3 │ S │ = │ C │ False │ 2032 │ Small, equal, large exp+zero low256 │
351+
# │ S4 │ S │ = │ D │ False │ 2048 │ Small, equal, large exp+non-zero low256 │
352+
# │ S5 │ S │ > │ A │ True │ 500 │ Small, base>mod, zero exp, clamped │
353+
# │ S6 │ S │ < │ B │ True │ 500 │ Small, base<mod, small exp, clamped │
354+
# │ L0 │ L │ = │ A │ True │ 500 │ Large, equal, zero exp, clamped │
355+
# │ L1 │ L │ = │ B │ False │ 12750 │ Large, equal, large exp, unclamped │
356+
# │ L2 │ L │ = │ C │ False │ 6350 │ Large, equal, large exp+zero low256 │
357+
# │ L3 │ L │ = │ D │ False │ 6400 │ Large, equal, large exp+non-zero low256 │
358+
# │ L4 │ L │ > │ B │ True │ 500 │ Large, base>mod, small exp, clamped │
359+
# │ L5 │ L │ < │ C │ False │ 9144 │ Large, base<mod, large exp+zero low256 │
360+
# └─────┴──────┴─────┴──────┴───────┴─────────┴─────────────────────────────────────────────┘
361+
362+
for base, exponent, modulus, expected_result, test_id in test_cases:
363+
yield pytest.param(
364+
ModExpInput(base=base, exponent=exponent, modulus=modulus),
365+
bytes.fromhex(expected_result),
366+
id=test_id,
367+
)
368+
369+
370+
@pytest.mark.parametrize(
371+
"modexp_input,modexp_expected",
372+
create_modexp_variable_gas_test_cases(),
373+
)
374+
def test_modexp_variable_gas_cost(
375+
state_test: StateTestFiller,
376+
pre: Alloc,
377+
tx: Transaction,
378+
post: Dict,
379+
):
380+
"""Test ModExp variable gas cost."""
381+
state_test(pre=pre, tx=tx, post=post)

0 commit comments

Comments
 (0)