Skip to content

Commit 9fbb29b

Browse files
committed
feat(tests): tests for ecrecover precompile
sourced from `evmone` unit tests
1 parent abd7612 commit 9fbb29b

File tree

1 file changed

+278
-0
lines changed

1 file changed

+278
-0
lines changed
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
"""Tests ecrecover 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.vm import Opcodes as Op
12+
13+
14+
@pytest.mark.valid_from("Frontier")
15+
@pytest.mark.parametrize(
16+
"msg_hash, v, r, s, output",
17+
[
18+
pytest.param(
19+
bytes.fromhex(
20+
"18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
21+
),
22+
bytes.fromhex(
23+
"000000000000000000000000000000000000000000000000000000000000001c"
24+
),
25+
bytes.fromhex(
26+
"73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"
27+
),
28+
bytes.fromhex(
29+
"eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"
30+
),
31+
bytes.fromhex(
32+
"000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"
33+
),
34+
id="valid_signature_1",
35+
),
36+
pytest.param(
37+
bytes.fromhex(
38+
"18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
39+
),
40+
bytes.fromhex(
41+
"000000000000000000000000000000000000000000000000000000000000001b"
42+
),
43+
bytes.fromhex(
44+
"7af9e73057870458f03c143483bc5fcb6f39d01c9b26d28ed9f3fe23714f6628"
45+
),
46+
bytes.fromhex(
47+
"3134a4ba8fafe11b351a720538398a5635e235c0b3258dce19942000731079ec"
48+
),
49+
bytes.fromhex(
50+
"0000000000000000000000009a04aede774152f135315670f562c19c5726df2c"
51+
),
52+
id="valid_signature_2",
53+
),
54+
# z >= Order
55+
pytest.param(
56+
bytes.fromhex(
57+
"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
58+
),
59+
bytes.fromhex(
60+
"000000000000000000000000000000000000000000000000000000000000001b"
61+
),
62+
bytes.fromhex(
63+
"7af9e73057870458f03c143483bc5fcb6f39d01c9b26d28ed9f3fe23714f6628"
64+
),
65+
bytes.fromhex(
66+
"3134a4ba8fafe11b351a720538398a5635e235c0b3258dce19942000731079ec"
67+
),
68+
bytes.fromhex(
69+
"000000000000000000000000b32cf3c8616537a28583fc00d29a3e8c9614cd61"
70+
),
71+
id="z_gte_order",
72+
),
73+
pytest.param(
74+
bytes.fromhex(
75+
"6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9"
76+
),
77+
bytes.fromhex(
78+
"000000000000000000000000000000000000000000000000000000000000001b"
79+
),
80+
bytes.fromhex(
81+
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
82+
),
83+
bytes.fromhex(
84+
"6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9"
85+
),
86+
b"",
87+
id="invalid_signature_1",
88+
),
89+
pytest.param(
90+
bytes.fromhex(
91+
"18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
92+
),
93+
bytes.fromhex(
94+
"000000000000000000000000000000000000000000000000000000000000001c"
95+
),
96+
bytes.fromhex(
97+
"0000000000000000000000000000000000000000000000000000000000000000"
98+
),
99+
bytes.fromhex(
100+
"eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"
101+
),
102+
b"",
103+
id="invalid_signature_2",
104+
),
105+
pytest.param(
106+
bytes.fromhex(
107+
"18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
108+
),
109+
bytes.fromhex(
110+
"000000000000000000000000000000000000000000000000000000000000001c"
111+
),
112+
bytes.fromhex(
113+
"73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"
114+
),
115+
bytes.fromhex(
116+
"0000000000000000000000000000000000000000000000000000000000000000"
117+
),
118+
b"",
119+
id="invalid_signature_3",
120+
),
121+
# r >= Order
122+
pytest.param(
123+
bytes.fromhex(
124+
"18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
125+
),
126+
bytes.fromhex(
127+
"000000000000000000000000000000000000000000000000000000000000001c"
128+
),
129+
bytes.fromhex(
130+
"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
131+
),
132+
bytes.fromhex(
133+
"eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"
134+
),
135+
b"",
136+
id="invalid_signature_3",
137+
),
138+
# s >= Order
139+
pytest.param(
140+
bytes.fromhex(
141+
"18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
142+
),
143+
bytes.fromhex(
144+
"000000000000000000000000000000000000000000000000000000000000001c"
145+
),
146+
bytes.fromhex(
147+
"73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"
148+
),
149+
bytes.fromhex(
150+
"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
151+
),
152+
b"",
153+
id="s_gte_order",
154+
),
155+
# u1 == u2 && R == G
156+
pytest.param(
157+
bytes.fromhex(
158+
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
159+
),
160+
bytes.fromhex(
161+
"000000000000000000000000000000000000000000000000000000000000001b"
162+
),
163+
bytes.fromhex(
164+
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
165+
),
166+
bytes.fromhex(
167+
"3a2db9fe7908dcc36d81824d2338fc3dd5ae2692e4c6790043d7868872b09cd1"
168+
),
169+
bytes.fromhex(
170+
"0000000000000000000000002e4db28b1f03ec8acfc2865e0c08308730e7ddf2"
171+
),
172+
id="u1_eq_u2_R_eq_G",
173+
),
174+
# u1 == -u2 && R == -G
175+
pytest.param(
176+
bytes.fromhex(
177+
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
178+
),
179+
bytes.fromhex(
180+
"000000000000000000000000000000000000000000000000000000000000001c"
181+
),
182+
bytes.fromhex(
183+
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
184+
),
185+
bytes.fromhex(
186+
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
187+
),
188+
bytes.fromhex(
189+
"0000000000000000000000002e4db28b1f03ec8acfc2865e0c08308730e7ddf2"
190+
),
191+
id="u1_eq_neg_u2_R_eq_neg_G",
192+
),
193+
# 13u1 == u2 && R == -13G
194+
pytest.param(
195+
bytes.fromhex(
196+
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
197+
),
198+
bytes.fromhex(
199+
"000000000000000000000000000000000000000000000000000000000000001b"
200+
),
201+
bytes.fromhex(
202+
"f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8"
203+
),
204+
bytes.fromhex(
205+
"533e9827446324ac92450a05ef04622bc0081f8d5b394e4d7b514ed35c946ee9"
206+
),
207+
b"",
208+
id="13u1_eq_u2_R_eq_neg_13G",
209+
),
210+
# 13u1 == u2 && R == 13G
211+
pytest.param(
212+
bytes.fromhex(
213+
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
214+
),
215+
bytes.fromhex(
216+
"000000000000000000000000000000000000000000000000000000000000001c"
217+
),
218+
bytes.fromhex(
219+
"f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8"
220+
),
221+
bytes.fromhex(
222+
"533e9827446324ac92450a05ef04622bc0081f8d5b394e4d7b514ed35c946ee9"
223+
),
224+
bytes.fromhex(
225+
"000000000000000000000000fc4b7e97f115ac81f9a6997254892b45e8159d46"
226+
),
227+
id="13u1_eq_u2_R_eq_13G",
228+
),
229+
],
230+
)
231+
def test_precompiles(
232+
state_test: StateTestFiller,
233+
pre: Alloc,
234+
msg_hash: bytes,
235+
v: bytes,
236+
r: bytes,
237+
s: bytes,
238+
output: bytes,
239+
) -> None:
240+
"""
241+
Tests the behavior of `ecrecover` precompiled contract.
242+
"""
243+
env = Environment()
244+
245+
# Memory
246+
hash_offset = 0
247+
v_offset = 32
248+
r_offset = 64
249+
s_offset = 96
250+
ret_offset = 128
251+
252+
account = pre.deploy_contract(
253+
Op.MSTORE(hash_offset, msg_hash)
254+
+ Op.MSTORE(v_offset, v)
255+
+ Op.MSTORE(r_offset, r)
256+
+ Op.MSTORE(s_offset, s)
257+
+ Op.CALL(
258+
gas=50_000,
259+
address="0x01", # ecrecover precompile address
260+
args_offset=hash_offset,
261+
args_size=4 * 32,
262+
ret_offset=ret_offset,
263+
ret_size=32,
264+
)
265+
+ Op.SSTORE(0, Op.MLOAD(ret_offset))
266+
+ Op.STOP,
267+
storage={0: 0xDEADBEEF},
268+
)
269+
270+
tx = Transaction(
271+
to=account,
272+
sender=pre.fund_eoa(),
273+
gas_limit=1_000_000,
274+
)
275+
276+
post = {account: Account(storage={0: output})}
277+
278+
state_test(env=env, pre=pre, post=post, tx=tx)

0 commit comments

Comments
 (0)