@@ -348,6 +348,55 @@ ExecutionResult ecmul_execute(const uint8_t* input, size_t input_size, uint8_t*
348
348
return {EVMC_PRECOMPILE_FAILURE, 0 };
349
349
}
350
350
351
+ ExecutionResult ecpairing_execute (const uint8_t * input, size_t input_size, uint8_t * output,
352
+ [[maybe_unused]] size_t output_size) noexcept
353
+ {
354
+ assert (output_size >= 32 );
355
+
356
+ static constexpr size_t PAIR_SIZE = 192 ;
357
+
358
+ if (input_size % PAIR_SIZE != 0 )
359
+ return {EVMC_PRECOMPILE_FAILURE, 0 };
360
+
361
+ if (const auto n_pairs = input_size / PAIR_SIZE; n_pairs > 0 )
362
+ {
363
+ std::vector<std::pair<evmmax::bn254::Point , evmmax::bn254::ExtPoint>> pairs;
364
+ pairs.reserve (n_pairs);
365
+ auto input_idx = input;
366
+ for (size_t i = 0 ; i < n_pairs; ++i)
367
+ {
368
+ const evmmax::bn254::Point p{
369
+ intx::be::unsafe::load<intx::uint256>(input_idx),
370
+ intx::be::unsafe::load<intx::uint256>(input_idx + 32 ),
371
+ };
372
+
373
+ const evmmax::bn254::ExtPoint q{
374
+ {intx::be::unsafe::load<intx::uint256>(input_idx + 96 ),
375
+ intx::be::unsafe::load<intx::uint256>(input_idx + 64 )},
376
+ {intx::be::unsafe::load<intx::uint256>(input_idx + 160 ),
377
+ intx::be::unsafe::load<intx::uint256>(input_idx + 128 )},
378
+ };
379
+ pairs.emplace_back (p, q);
380
+ input_idx += PAIR_SIZE;
381
+ }
382
+
383
+ const auto res = evmmax::bn254::pairing_check (pairs);
384
+
385
+ if (res.has_value ())
386
+ {
387
+ intx::be::unsafe::store (output, res.value () ? intx::uint256{1 } : intx::uint256{0 });
388
+ return {EVMC_SUCCESS, 64 };
389
+ }
390
+ else
391
+ return {EVMC_PRECOMPILE_FAILURE, 0 };
392
+ }
393
+ else
394
+ {
395
+ intx::be::unsafe::store (output, intx::uint256{1 });
396
+ return {EVMC_SUCCESS, 32 };
397
+ }
398
+ }
399
+
351
400
ExecutionResult identity_execute (const uint8_t * input, size_t input_size, uint8_t * output,
352
401
[[maybe_unused]] size_t output_size) noexcept
353
402
{
0 commit comments