@@ -150,3 +150,233 @@ TEST(secp256k1, point_to_address)
150
150
// https://etherscan.io/address/0x3f17f1962b36e491b30a40b2405849e597ba5fb5
151
151
EXPECT_EQ (to_address (Point{}), 0x3f17f1962B36e491b30A40b2405849e597Ba5FB5_address);
152
152
}
153
+
154
+ TEST (evmmax, secp256k1_calculate_u1)
155
+ {
156
+ // u1 = -zr^(-1)
157
+ const auto z = 0x31d6fb860f6d12cee6e5b640646089bd5883d586e43de3dedc75695c11ac2da9_u256;
158
+ const auto r = 0x71cd6bfc24665312ff489aba9279710a560eda74aca333bf298785dc3cd72f6e_u256;
159
+ const auto expected = 0xd80ea4db5200c96e969270ab7c105e16abb9fc18a6e01cc99575dd3f5ce41eed_u256;
160
+
161
+ const evmmax::ModArith m{evmmax::secp256k1::FieldPrime};
162
+ const auto z_mont = m.to_mont (z);
163
+ const auto r_mont = m.to_mont (r);
164
+ const auto r_inv = field_inv (m, r_mont);
165
+ const auto z_neg = m.sub (0 , z_mont);
166
+ const auto u1_mont = m.mul (z_neg, r_inv);
167
+ const auto u1 = m.from_mont (u1_mont);
168
+ EXPECT_EQ (u1, expected);
169
+ }
170
+
171
+ TEST (evmmax, secp256k1_calculate_u2)
172
+ {
173
+ // u2 = sr^(-1)
174
+ const auto r = 0x27bc00995393e969525f2d02e731437402aa12a9a09125d1e322d62f05a2b54f_u256;
175
+ const auto s = 0x7ce91fc325f28e78a016fa674a80d85581cc278d15453ea2fede2471b1adaada_u256;
176
+ const auto expected = 0xf888ea06899abc190fa37a165c98e6d4b00b13c50db1d1c34f38f0ab8fd9c29b_u256;
177
+
178
+ const evmmax::ModArith m{evmmax::secp256k1::FieldPrime};
179
+ const auto s_mont = m.to_mont (s);
180
+ const auto r_mont = m.to_mont (r);
181
+ const auto r_inv = field_inv (m, r_mont);
182
+ const auto u2_mont = m.mul (s_mont, r_inv);
183
+ const auto u2 = m.from_mont (u2_mont);
184
+ EXPECT_EQ (u2, expected);
185
+ }
186
+
187
+ TEST (evmmax, secp256k1_hash_to_number)
188
+ {
189
+ const auto max_h = ~uint256{};
190
+ const auto hm = max_h % evmmax::secp256k1::FieldPrime;
191
+
192
+ // Optimized mod.
193
+ const auto hm2 = max_h - evmmax::secp256k1::FieldPrime;
194
+ EXPECT_EQ (hm2, hm);
195
+ }
196
+
197
+ TEST (evmmax, secp256k1_pt_add_inf)
198
+ {
199
+ const Point p1{0x18f4057699e2d9679421de8f4e11d7df9fa4b9e7cb841ea48aed75f1567b9731_u256,
200
+ 0x6db5b7ecd8e226c06f538d15173267bf1e78acc02bb856e83b3d6daec6a68144_u256};
201
+ const Point inf;
202
+ ASSERT_TRUE (inf.is_inf ());
203
+
204
+ EXPECT_EQ (add (p1, inf), p1);
205
+ EXPECT_EQ (add (inf, p1), p1);
206
+ EXPECT_EQ (add (inf, inf), inf);
207
+ }
208
+
209
+ TEST (evmmax, secp256k1_pt_add)
210
+ {
211
+ const evmmax::ModArith s{evmmax::secp256k1::FieldPrime};
212
+
213
+ const Point p1{0x18f4057699e2d9679421de8f4e11d7df9fa4b9e7cb841ea48aed75f1567b9731_u256,
214
+ 0x6db5b7ecd8e226c06f538d15173267bf1e78acc02bb856e83b3d6daec6a68144_u256};
215
+ const Point p2{0xf929e07c83d65da3569113ae03998d13359ba982216285a686f4d66e721a0beb_u256,
216
+ 0xb6d73966107b10526e2e140c17f343ee0a373351f2b1408923151b027f55b82_u256};
217
+ const Point p3{0xf929e07c83d65da3569113ae03998d13359ba982216285a686f4d66e721a0beb_u256,
218
+ 0xf4928c699ef84efad91d1ebf3e80cbc11f5c8ccae0d4ebf76dceae4ed80aa0ad_u256};
219
+ const Point p4{
220
+ 0x1_u256, 0xbde70df51939b94c9c24979fa7dd04ebd9b3572da7802290438af2a681895441_u256};
221
+
222
+ {
223
+ const Point e = {0x40468d7704db3d11961ab9c222e35919d7e5d1baef59e0f46255d66bec3bd1d3_u256,
224
+ 0x6fff88d9f575236b6cc5c74e7d074832a460c2792fba888aea7b9986429dd7f7_u256};
225
+ EXPECT_EQ (add (p1, p2), e);
226
+ }
227
+ {
228
+ const Point e = {0xd8e7b42b8c82e185bf0669ce0754697a6eb46c156497d5d1971bd6a23f38ed9e_u256,
229
+ 0x628c3107fc73c92e7b8c534e239257fb2de95bd6b965dc1021f636da086a7e99_u256};
230
+ EXPECT_EQ (add (p1, p1), e);
231
+ }
232
+ {
233
+ const Point e = {0xdf592d726f42759020da10d3106db3880e514c783d6970d2a9085fb16879b37f_u256,
234
+ 0x10aa0ef9fe224e3797792b4b286b9f63542d4c11fe26d449a845b9db0f5993f9_u256};
235
+ EXPECT_EQ (add (p1, p3), e);
236
+ }
237
+ {
238
+ const Point e = {0x12a5fd099bcd30e7290e58d63f8d5008287239500e6d0108020040497c5cb9c9_u256,
239
+ 0x7f6bd83b5ac46e3b59e24af3bc9bfbb213ed13e21d754e4950ae635961742574_u256};
240
+ EXPECT_EQ (add (p1, p4), e);
241
+ }
242
+ }
243
+
244
+ TEST (evmmax, secp256k1_pt_mul_inf)
245
+ {
246
+ const Point p1{0x18f4057699e2d9679421de8f4e11d7df9fa4b9e7cb841ea48aed75f1567b9731_u256,
247
+ 0x6db5b7ecd8e226c06f538d15173267bf1e78acc02bb856e83b3d6daec6a68144_u256};
248
+ const Point inf;
249
+ ASSERT_TRUE (inf.is_inf ());
250
+
251
+ EXPECT_EQ (mul (p1, 0 ), inf);
252
+ EXPECT_EQ (mul (p1, evmmax::secp256k1::Order), inf);
253
+ EXPECT_EQ (mul (inf, 0 ), inf);
254
+ EXPECT_EQ (mul (inf, 1 ), inf);
255
+ EXPECT_EQ (mul (inf, evmmax::secp256k1::Order - 1 ), inf);
256
+ EXPECT_EQ (mul (inf, evmmax::secp256k1::Order), inf);
257
+ }
258
+
259
+ TEST (evmmax, secp256k1_pt_mul)
260
+ {
261
+ const evmmax::ModArith s{evmmax::secp256k1::FieldPrime};
262
+
263
+ const Point p1{0x18f4057699e2d9679421de8f4e11d7df9fa4b9e7cb841ea48aed75f1567b9731_u256,
264
+ 0x6db5b7ecd8e226c06f538d15173267bf1e78acc02bb856e83b3d6daec6a68144_u256};
265
+
266
+ {
267
+ const auto d{100000000000000000000_u256};
268
+ const Point e{0x4c34e6dc48badd579d1ce4702fd490fb98fa0e666417bfc2d4ff8e957d99c565_u256,
269
+ 0xb53da5be179d80c7f07226ba79b6bce643d89496b37d6bc2d111b009e37cc28b_u256};
270
+ auto r = mul (p1, d);
271
+ EXPECT_EQ (r, e);
272
+ }
273
+
274
+ {
275
+ const auto d{100000000000000000000000000000000_u256};
276
+ const Point e{0xf86902594c8a4e4fc5f6dfb27886784271302c6bab3dc4350a0fe7c5b056af66_u256,
277
+ 0xb5748aa8f9122bfdcbf5846f6f8ec76f41626642a3f2ea0f483c92bf915847ad_u256};
278
+ auto r = mul (p1, d);
279
+ EXPECT_EQ (r, e);
280
+ }
281
+
282
+ {
283
+ const auto u1 = 0xd17a4c1f283fa5d67656ea81367b520eaa689207e5665620d4f51c7cf85fa220_u256;
284
+ const Point G{0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798_u256,
285
+ 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8_u256};
286
+ const Point e{0x39cb41b2567f68137aae52e99dbe91cd38d9faa3ba6be536a04355b63a7964fe_u256,
287
+ 0xf31e6abd08cbd8e4896c9e0304b25000edcd52a9f6d2bac7cfbdad2c835c9a35_u256};
288
+ auto r = mul (G, u1);
289
+ EXPECT_EQ (r, e);
290
+ }
291
+ }
292
+
293
+
294
+ struct TestCaseECR
295
+ {
296
+ evmc::bytes32 hash;
297
+ uint256 r;
298
+ uint256 s;
299
+ bool parity = false ;
300
+ Point pubkey;
301
+ };
302
+
303
+ static const TestCaseECR test_cases_ecr[] = {
304
+ {0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c_bytes32,
305
+ 0x7af9e73057870458f03c143483bc5fcb6f39d01c9b26d28ed9f3fe23714f6628_u256,
306
+ 0x3134a4ba8fafe11b351a720538398a5635e235c0b3258dce19942000731079ec_u256, false ,
307
+ {0x43ec87f8ee6f58605d947dac51b5e4cfe26705f509e5dad058212aadda180835_u256,
308
+ 0x90ebad786ce091f5af1719bf30ee236a4e6ce8a7ab6c36a16c93c6177aa109df_u256}},
309
+ };
310
+
311
+ TEST (evmmax, ecr)
312
+ {
313
+ for (const auto & t : test_cases_ecr)
314
+ {
315
+ const auto h = std::bit_cast<ethash::hash256>(t.hash );
316
+ const auto result = secp256k1_ecdsa_recover (h, t.r , t.s , t.parity );
317
+ ASSERT_TRUE (result.has_value ());
318
+ EXPECT_EQ (result->x , t.pubkey .x );
319
+ EXPECT_EQ (result->y , t.pubkey .y );
320
+ // EXPECT_EQ(*result, t.pubkey);
321
+ }
322
+ }
323
+
324
+
325
+ struct TestCaseECRecovery
326
+ {
327
+ bytes input;
328
+ bytes expected_output;
329
+ };
330
+
331
+ static const TestCaseECRecovery test_cases[] = {
332
+ {" 18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" _hex,
333
+ " 000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b" _hex},
334
+ {" 18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001b7af9e73057870458f03c143483bc5fcb6f39d01c9b26d28ed9f3fe23714f66283134a4ba8fafe11b351a720538398a5635e235c0b3258dce19942000731079ec" _hex,
335
+ " 0000000000000000000000009a04aede774152f135315670f562c19c5726df2c" _hex},
336
+ // z >= Order
337
+ {" fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141000000000000000000000000000000000000000000000000000000000000001b7af9e73057870458f03c143483bc5fcb6f39d01c9b26d28ed9f3fe23714f66283134a4ba8fafe11b351a720538398a5635e235c0b3258dce19942000731079ec" _hex,
338
+ " 000000000000000000000000b32CF3C8616537a28583FC00D29a3e8C9614cD61" _hex},
339
+ {" 6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9000000000000000000000000000000000000000000000000000000000000001b79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9" _hex,
340
+ {}},
341
+ {" 18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" _hex,
342
+ {}},
343
+ {" 18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f0000000000000000000000000000000000000000000000000000000000000000" _hex,
344
+ {}},
345
+ // r >= Order
346
+ {" 18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001cfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549" _hex,
347
+ {}},
348
+ // s >= Order
349
+ {" 18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" _hex,
350
+ {}},
351
+ };
352
+
353
+ TEST (evmmax, ecrecovery)
354
+ {
355
+ for (const auto & t : test_cases)
356
+ {
357
+ ASSERT_EQ (t.input .size (), 128 );
358
+
359
+ ethash::hash256 hash;
360
+ std::memcpy (hash.bytes , t.input .data (), 32 );
361
+ const auto v{be::unsafe::load<uint256>(&t.input [32 ])};
362
+ ASSERT_TRUE (v == 27 || v == 28 );
363
+ const auto r{be::unsafe::load<uint256>(&t.input [64 ])};
364
+ const auto s{be::unsafe::load<uint256>(&t.input [96 ])};
365
+ const bool parity = v == 28 ;
366
+
367
+ const auto result = ecrecover (hash, r, s, parity);
368
+
369
+ if (t.expected_output .empty ())
370
+ {
371
+ EXPECT_FALSE (result.has_value ());
372
+ }
373
+ else
374
+ {
375
+ ASSERT_EQ (t.expected_output .size (), 32 );
376
+ evmc::address e;
377
+ memcpy (&e.bytes [0 ], &t.expected_output [12 ], 20 );
378
+ ASSERT_TRUE (result.has_value ());
379
+ EXPECT_EQ (*result, e);
380
+ }
381
+ }
382
+ }
0 commit comments