Skip to content

Commit e1f2df6

Browse files
pdobaczspencer-tb
andauthored
feat(tests): tests for modexp and ripemd (#1691)
Co-authored-by: spencer <[email protected]>
1 parent 60a4cf2 commit e1f2df6

File tree

3 files changed

+208
-1
lines changed

3 files changed

+208
-1
lines changed

docs/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ Test fixtures for use by clients are available for each release on the [Github r
2727
- ✨ Expand EIP-6110 modified contract tests, where the extra event log has no topics at all ([#1693](https://github.com/ethereum/execution-specs/pull/1693)).
2828
- ✨ Add a CREATE/2 test cases for when it runs OOG on code deposit ([#1705](https://github.com/ethereum/execution-specs/pull/1705)).
2929
- ✨ Expand cases to test *CALL opcodes causing OOG ([#1703](https://github.com/ethereum/execution-specs/pull/1703)).
30-
- ✨ Add `ecrecover` precompile tests originating form `evmone` unittests ([#1685](https://github.com/ethereum/execution-specs/pull/1685))
30+
- ✨ Add tests for `modexp` and `ripemd` precompiled contracts ([#1691](https://github.com/ethereum/execution-specs/pull/1691)).
31+
- ✨ Add `ecrecover` precompile tests originating form `evmone` unittests ([#1685](https://github.com/ethereum/execution-specs/pull/1685)).
3132

3233
## [v5.3.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v5.3.0) - 2025-10-09
3334

tests/byzantium/eip198_modexp_precompile/test_modexp.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,37 @@
145145
),
146146
id="EIP-198-case5-raw-input",
147147
),
148+
# different declared moduli lengths and parities
149+
pytest.param(
150+
ModExpInput(
151+
base="1234",
152+
exponent="234",
153+
modulus="1000",
154+
declared_modulus_length=256,
155+
),
156+
ModExpOutput(
157+
returned_data=Bytes(
158+
"07be9ec040921bf6ffa9faad54b5e88c503ea4511cc15505e36fc9569cf20698"
159+
"933819b8c4b15e52a51f64261954708f55432c5a7011dc7d1787c64a8ece6f20"
160+
"65772d1dbc3ea9e96e3f55eeec7477bc92cb587ae416c8316fb3fa825ee25410"
161+
"811fad4f98ade2eaa665b48e930247bb30b25100000000000000000000000000"
162+
+ (256 - 4 * 32)
163+
* "00"
164+
)
165+
),
166+
id="EIP-198-case1-mod-power2-declared-length-256-bytes",
167+
),
168+
pytest.param(
169+
ModExpInput(
170+
base="1234",
171+
exponent="234",
172+
modulus="1010",
173+
declared_modulus_length=128,
174+
),
175+
ModExpOutput(returned_data=Bytes("00") + Bytes(hex(2**1014))),
176+
id="EIP-198-case1-mod-even-declared-length-128-bytes",
177+
),
178+
# out of gas cases
148179
pytest.param(
149180
Bytes(
150181
"0000000000000000000000000000000000000000000000000000000000000001"
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""Tests RIPEMD-160 precompiled contract."""
2+
3+
import pytest
4+
from execution_testing import (
5+
Account,
6+
Alloc,
7+
Environment,
8+
StateTestFiller,
9+
Transaction,
10+
)
11+
from execution_testing.forks.forks.forks import Byzantium
12+
from execution_testing.forks.helpers import Fork
13+
from execution_testing.vm import Opcodes as Op
14+
15+
16+
@pytest.mark.valid_from("Frontier")
17+
@pytest.mark.parametrize(
18+
"msg, output",
19+
[
20+
pytest.param(
21+
b"abc",
22+
bytes.fromhex("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"),
23+
id="ripemd_abc",
24+
),
25+
pytest.param(
26+
b"message digest",
27+
bytes.fromhex("5d0689ef49d2fae572b881b123a85ffa21595f36"),
28+
id="ripemd_message_digest",
29+
),
30+
pytest.param(
31+
b"abcdefghijklmnopqrstuvwxyz",
32+
bytes.fromhex("f71c27109c692c1b56bbdceb5b9d2865b3708dbc"),
33+
id="ripemd_alphabet",
34+
),
35+
pytest.param(
36+
b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
37+
bytes.fromhex("12a053384a9c0c88e405a06c27dcf49ada62eb2b"),
38+
id="ripemd_long",
39+
),
40+
pytest.param(
41+
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
42+
bytes.fromhex("b0e20b6e3116640286ed3a87a5713079b21f5189"),
43+
id="ripemd_alnum",
44+
),
45+
pytest.param(
46+
b"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
47+
bytes.fromhex("9b752e45573d4b39f4dbd3323cab82bf63326bfb"),
48+
id="ripemd_numeric",
49+
),
50+
pytest.param(
51+
b"The quick brown fox jumps over the lazy dog",
52+
bytes.fromhex("37f332f68db77bd9d7edd4969571ad671cf9dd3b"),
53+
id="ripemd_quick_brown_fox",
54+
),
55+
pytest.param(
56+
b"a" * 0,
57+
bytes.fromhex("9c1185a5c5e9fc54612808977ee8f548b2258d31"),
58+
id="ripemd_a_0",
59+
),
60+
pytest.param(
61+
b"a" * 1,
62+
bytes.fromhex("0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"),
63+
id="ripemd_a_1",
64+
),
65+
pytest.param(
66+
b"a" * 54,
67+
bytes.fromhex("a57fa1577740fd73b6859dd20e090cdac4d2af36"),
68+
id="ripemd_a_54",
69+
),
70+
pytest.param(
71+
b"a" * 55,
72+
bytes.fromhex("0d8a8c9063a48576a7c97e9f95253a6e53ff6765"),
73+
id="length fits into the first block",
74+
),
75+
pytest.param(
76+
b"a" * 56,
77+
bytes.fromhex("e72334b46c83cc70bef979e15453706c95b888be"),
78+
id="ripemd_a_56",
79+
),
80+
pytest.param(
81+
b"a" * 57,
82+
bytes.fromhex("eed82d19d597ab275b550ff3d6e0bc2a75350388"),
83+
id="ripemd_a_57",
84+
),
85+
pytest.param(
86+
b"a" * 63,
87+
bytes.fromhex("e640041293fe663b9bf3f8c21ffecac03819e6b2"),
88+
id="ripemd_a_63",
89+
),
90+
pytest.param(
91+
b"a" * 64,
92+
bytes.fromhex("9dfb7d374ad924f3f88de96291c33e9abed53e32"),
93+
id="full block",
94+
),
95+
pytest.param(
96+
b"a" * 65,
97+
bytes.fromhex("99724bb11811e7166af38f671b6a082d8ab4960b"),
98+
id="ripemd_a_65",
99+
),
100+
pytest.param(
101+
b"a" * 119,
102+
bytes.fromhex("23e398ff2bac815aa1bbb57ca2a669c841872919"),
103+
id="ripemd_a_119",
104+
),
105+
pytest.param(
106+
b"a" * 120,
107+
bytes.fromhex("c476770a6dae31fcee8d25efe6559a05c8024595"),
108+
id="ripemd_a_120",
109+
),
110+
pytest.param(
111+
b"a" * 121,
112+
bytes.fromhex("725c88a6f41605e99477a1478607d3fe25ced606"),
113+
id="ripemd_a_121",
114+
),
115+
pytest.param(
116+
b"a" * 127,
117+
bytes.fromhex("64f2d68b85f394e2e4f49009c4bd50224c2698ed"),
118+
id="ripemd_a_127",
119+
),
120+
pytest.param(
121+
b"a" * 128,
122+
bytes.fromhex("8dfdfb32b2ed5cb41a73478b4fd60cc5b4648b15"),
123+
id="two blocks",
124+
),
125+
pytest.param(
126+
b"a" * 129,
127+
bytes.fromhex("62bb9091f499f294f15aa5b951df4d9744d50cf2"),
128+
id="ripemd_a_129",
129+
),
130+
pytest.param(
131+
b"a" * 10_000,
132+
bytes.fromhex("eb33e86b2400cc0a11707be717a35a9acf074a58"),
133+
id="ripemd_a_10000",
134+
),
135+
],
136+
)
137+
def test_precompiles(
138+
state_test: StateTestFiller,
139+
pre: Alloc,
140+
fork: Fork,
141+
msg: bytes,
142+
output: bytes,
143+
) -> None:
144+
"""
145+
Tests the behavior of `RIPEMD-160` precompiled contract.
146+
"""
147+
env = Environment()
148+
149+
account = pre.deploy_contract(
150+
code=Op.CALLDATACOPY(0, 0, len(msg))
151+
+ Op.MLOAD(0)
152+
+ Op.CALL(
153+
gas=50_000,
154+
address="0x03", # RIPEMD-160 precompile address
155+
args_offset=0,
156+
args_size=len(msg),
157+
ret_offset=len(msg),
158+
ret_size=32,
159+
)
160+
+ Op.SSTORE(0, Op.MLOAD(len(msg)))
161+
+ Op.STOP,
162+
storage={0: 0xDEADBEEF},
163+
)
164+
165+
tx = Transaction(
166+
to=account,
167+
sender=pre.fund_eoa(),
168+
gas_limit=1_000_0000,
169+
data=msg,
170+
protected=fork >= Byzantium,
171+
)
172+
173+
post = {account: Account(storage={0: output})}
174+
175+
state_test(env=env, pre=pre, post=post, tx=tx)

0 commit comments

Comments
 (0)