Skip to content

Commit edfe00d

Browse files
rodiazetchfast
andauthored
precompiles: Implement BLS pairing check (#1016)
Implementation of the `bls12_pairing_check` precompile: According to spec https://eips.ethereum.org/EIPS/eip-2537#abi-for-pairing-check Depends on: #1012 Co-authored-by: Paweł Bylica <pawel@ethereum.org>
1 parent f007e7c commit edfe00d

5 files changed

Lines changed: 104 additions & 14 deletions

File tree

circle.yml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -372,15 +372,7 @@ jobs:
372372
working_directory: ~/spec-tests/fixtures/state_tests
373373
command: >
374374
~/build/bin/evmone-statetest
375-
prague/eip2537_bls_12_381_precompiles/bls12_precompiles_before_fork
376-
prague/eip2537_bls_12_381_precompiles/bls12_g1add
377-
prague/eip2537_bls_12_381_precompiles/bls12_g1mul
378-
prague/eip2537_bls_12_381_precompiles/bls12_g2add
379-
prague/eip2537_bls_12_381_precompiles/bls12_g2mul
380-
prague/eip2537_bls_12_381_precompiles/bls12_g1msm
381-
prague/eip2537_bls_12_381_precompiles/bls12_g2msm
382-
prague/eip2537_bls_12_381_precompiles/bls12_map_fp_to_g1
383-
prague/eip2537_bls_12_381_precompiles/bls12_map_fp2_to_g2
375+
prague/eip2537_bls_12_381_precompiles
384376
- run:
385377
name: "Execution spec tests (develop, blockchain_tests)"
386378
# Tests for in-development EVM revision currently passing.

lib/evmone_precompiles/bls.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,63 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept
356356
return true;
357357
}
358358

359+
[[nodiscard]] bool pairing_check(uint8_t _r[32], const uint8_t* _pairs, size_t size) noexcept
360+
{
361+
static constexpr auto FP_SIZE = 64;
362+
static constexpr auto FP2_SIZE = 2 * FP_SIZE;
363+
static constexpr auto P1_SIZE = 2 * FP_SIZE;
364+
static constexpr auto P2_SIZE = 2 * FP2_SIZE;
365+
static constexpr auto PAIR_SIZE = P1_SIZE + P2_SIZE;
366+
assert(size % PAIR_SIZE == 0);
367+
368+
const auto npairs = size / PAIR_SIZE;
369+
auto ptr = _pairs;
370+
auto has_inf = false;
371+
blst_fp12 acc = *blst_fp12_one();
372+
373+
const auto Qlines = std::make_unique_for_overwrite<blst_fp6[]>(68);
374+
375+
for (size_t i = 0; i < npairs; ++i)
376+
{
377+
const auto P_affine = validate_p1(ptr, &ptr[FP_SIZE]);
378+
if (!P_affine.has_value())
379+
return false;
380+
381+
const auto Q_affine = validate_p2(&ptr[P1_SIZE], &ptr[P1_SIZE + FP2_SIZE]);
382+
if (!Q_affine.has_value())
383+
return false;
384+
385+
if (!blst_p1_affine_in_g1(&*P_affine))
386+
return false;
387+
388+
if (!blst_p2_affine_in_g2(&*Q_affine))
389+
return false;
390+
391+
if (blst_p1_affine_is_inf(&*P_affine) || blst_p2_affine_is_inf(&*Q_affine))
392+
has_inf = true;
393+
394+
if (!has_inf)
395+
{
396+
blst_precompute_lines(Qlines.get(), &*Q_affine);
397+
398+
blst_fp12 ml_res;
399+
blst_miller_loop_lines(&ml_res, Qlines.get(), &*P_affine);
400+
blst_fp12_mul(&acc, &acc, &ml_res);
401+
}
402+
403+
ptr += PAIR_SIZE;
404+
}
405+
406+
bool result = true;
407+
if (!has_inf) // if any point-at-infinity encountered the answer is 1, so skip final exp.
408+
{
409+
blst_final_exp(&acc, &acc);
410+
result = blst_fp12_is_one(&acc);
411+
}
412+
413+
std::memset(_r, 0, 31);
414+
_r[31] = result ? 1 : 0;
415+
return true;
416+
}
417+
359418
} // namespace evmone::crypto::bls

lib/evmone_precompiles/bls.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,10 @@ inline constexpr auto BLS_FIELD_MODULUS =
7070
[[nodiscard]] bool map_fp2_to_g2(
7171
uint8_t _rx[128], uint8_t _ry[128], const uint8_t _fp[128]) noexcept;
7272

73+
/// Computes pairing for pairs of P and Q point from G1 and G2 accordingly.
74+
///
75+
/// Performs filed and groups check for both input points. Returns 'false' if any of requirement is
76+
/// not met according to spec https://eips.ethereum.org/EIPS/eip-2537#abi-for-pairing-check
77+
[[nodiscard]] bool pairing_check(uint8_t _r[32], const uint8_t* _pairs, size_t size) noexcept;
78+
7379
} // namespace evmone::crypto::bls

test/state/precompiles.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,20 @@ PrecompileAnalysis bls12_g2msm_analyze(bytes_view input, evmc_revision) noexcept
215215
return {bls_msm_cost(input.size() / 288, BLS12_G2MUL_PRECOMPILE_GAS), 256};
216216
}
217217

218-
PrecompileAnalysis bls12_pairing_check_analyze(bytes_view, evmc_revision) noexcept
218+
PrecompileAnalysis bls12_pairing_check_analyze(bytes_view input, evmc_revision) noexcept
219219
{
220-
// TODO: Implement
221-
return {GasCostMax, 0};
220+
static constexpr auto PAIR_SIZE = 384;
221+
222+
if (input.empty() || input.size() % PAIR_SIZE != 0)
223+
return {GasCostMax, 0};
224+
225+
const auto npairs = static_cast<int64_t>(input.size()) / PAIR_SIZE;
226+
227+
static constexpr auto BLS12_PAIRING_CHECK_BASE_FEE_PRECOMPILE_GAS = 65000;
228+
static constexpr auto BLS12_PAIRING_CHECK_FEE_PRECOMPILE_GAS = 43000;
229+
return {BLS12_PAIRING_CHECK_BASE_FEE_PRECOMPILE_GAS +
230+
BLS12_PAIRING_CHECK_FEE_PRECOMPILE_GAS * npairs,
231+
32};
222232
}
223233

224234
PrecompileAnalysis bls12_map_fp_to_g1_analyze(bytes_view, evmc_revision) noexcept
@@ -456,9 +466,18 @@ ExecutionResult bls12_g2msm_execute(const uint8_t* input, size_t input_size, uin
456466
return {EVMC_SUCCESS, 256};
457467
}
458468

459-
ExecutionResult bls12_pairing_check_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept
469+
ExecutionResult bls12_pairing_check_execute(const uint8_t* input, size_t input_size,
470+
uint8_t* output, [[maybe_unused]] size_t output_size) noexcept
460471
{
461-
return {EVMC_PRECOMPILE_FAILURE, 0};
472+
if (input_size % 384 != 0)
473+
return {EVMC_PRECOMPILE_FAILURE, 0};
474+
475+
assert(output_size == 32);
476+
477+
if (!crypto::bls::pairing_check(output, input, input_size))
478+
return {EVMC_PRECOMPILE_FAILURE, 0};
479+
480+
return {EVMC_SUCCESS, 32};
462481
}
463482

464483
ExecutionResult bls12_map_fp_to_g1_execute(const uint8_t* input, size_t input_size, uint8_t* output,

test/unittests/precompiles_bls_test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,17 @@ TEST(bls, map_fp2_to_g2)
294294
EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x);
295295
EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y);
296296
}
297+
298+
TEST(bls, paring_check)
299+
{
300+
using namespace evmc::literals;
301+
auto input =
302+
"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d0000000000000000000000000000000006d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a87002500000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed"_hex;
303+
uint8_t r[32];
304+
305+
EXPECT_TRUE(evmone::crypto::bls::pairing_check(r, input.data(), input.size()));
306+
307+
const auto expected = "0000000000000000000000000000000000000000000000000000000000000001"_hex;
308+
309+
EXPECT_EQ(evmc::bytes_view(r, sizeof r), expected);
310+
}

0 commit comments

Comments
 (0)