Skip to content

Commit

Permalink
precompiles: Implement BLS pairing check (#1016)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rodiazet and chfast authored Sep 18, 2024
1 parent f007e7c commit edfe00d
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 14 deletions.
10 changes: 1 addition & 9 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -372,15 +372,7 @@ jobs:
working_directory: ~/spec-tests/fixtures/state_tests
command: >
~/build/bin/evmone-statetest
prague/eip2537_bls_12_381_precompiles/bls12_precompiles_before_fork
prague/eip2537_bls_12_381_precompiles/bls12_g1add
prague/eip2537_bls_12_381_precompiles/bls12_g1mul
prague/eip2537_bls_12_381_precompiles/bls12_g2add
prague/eip2537_bls_12_381_precompiles/bls12_g2mul
prague/eip2537_bls_12_381_precompiles/bls12_g1msm
prague/eip2537_bls_12_381_precompiles/bls12_g2msm
prague/eip2537_bls_12_381_precompiles/bls12_map_fp_to_g1
prague/eip2537_bls_12_381_precompiles/bls12_map_fp2_to_g2
prague/eip2537_bls_12_381_precompiles
- run:
name: "Execution spec tests (develop, blockchain_tests)"
# Tests for in-development EVM revision currently passing.
Expand Down
59 changes: 59 additions & 0 deletions lib/evmone_precompiles/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,63 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept
return true;
}

[[nodiscard]] bool pairing_check(uint8_t _r[32], const uint8_t* _pairs, size_t size) noexcept
{
static constexpr auto FP_SIZE = 64;
static constexpr auto FP2_SIZE = 2 * FP_SIZE;
static constexpr auto P1_SIZE = 2 * FP_SIZE;
static constexpr auto P2_SIZE = 2 * FP2_SIZE;
static constexpr auto PAIR_SIZE = P1_SIZE + P2_SIZE;
assert(size % PAIR_SIZE == 0);

const auto npairs = size / PAIR_SIZE;
auto ptr = _pairs;
auto has_inf = false;
blst_fp12 acc = *blst_fp12_one();

const auto Qlines = std::make_unique_for_overwrite<blst_fp6[]>(68);

for (size_t i = 0; i < npairs; ++i)
{
const auto P_affine = validate_p1(ptr, &ptr[FP_SIZE]);
if (!P_affine.has_value())
return false;

const auto Q_affine = validate_p2(&ptr[P1_SIZE], &ptr[P1_SIZE + FP2_SIZE]);
if (!Q_affine.has_value())
return false;

if (!blst_p1_affine_in_g1(&*P_affine))
return false;

if (!blst_p2_affine_in_g2(&*Q_affine))
return false;

if (blst_p1_affine_is_inf(&*P_affine) || blst_p2_affine_is_inf(&*Q_affine))
has_inf = true;

if (!has_inf)
{
blst_precompute_lines(Qlines.get(), &*Q_affine);

blst_fp12 ml_res;
blst_miller_loop_lines(&ml_res, Qlines.get(), &*P_affine);
blst_fp12_mul(&acc, &acc, &ml_res);
}

ptr += PAIR_SIZE;
}

bool result = true;
if (!has_inf) // if any point-at-infinity encountered the answer is 1, so skip final exp.
{
blst_final_exp(&acc, &acc);
result = blst_fp12_is_one(&acc);
}

std::memset(_r, 0, 31);
_r[31] = result ? 1 : 0;
return true;
}

} // namespace evmone::crypto::bls
6 changes: 6 additions & 0 deletions lib/evmone_precompiles/bls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,10 @@ inline constexpr auto BLS_FIELD_MODULUS =
[[nodiscard]] bool map_fp2_to_g2(
uint8_t _rx[128], uint8_t _ry[128], const uint8_t _fp[128]) noexcept;

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

} // namespace evmone::crypto::bls
29 changes: 24 additions & 5 deletions test/state/precompiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,20 @@ PrecompileAnalysis bls12_g2msm_analyze(bytes_view input, evmc_revision) noexcept
return {bls_msm_cost(input.size() / 288, BLS12_G2MUL_PRECOMPILE_GAS), 256};
}

PrecompileAnalysis bls12_pairing_check_analyze(bytes_view, evmc_revision) noexcept
PrecompileAnalysis bls12_pairing_check_analyze(bytes_view input, evmc_revision) noexcept
{
// TODO: Implement
return {GasCostMax, 0};
static constexpr auto PAIR_SIZE = 384;

if (input.empty() || input.size() % PAIR_SIZE != 0)
return {GasCostMax, 0};

const auto npairs = static_cast<int64_t>(input.size()) / PAIR_SIZE;

static constexpr auto BLS12_PAIRING_CHECK_BASE_FEE_PRECOMPILE_GAS = 65000;
static constexpr auto BLS12_PAIRING_CHECK_FEE_PRECOMPILE_GAS = 43000;
return {BLS12_PAIRING_CHECK_BASE_FEE_PRECOMPILE_GAS +
BLS12_PAIRING_CHECK_FEE_PRECOMPILE_GAS * npairs,
32};
}

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

ExecutionResult bls12_pairing_check_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept
ExecutionResult bls12_pairing_check_execute(const uint8_t* input, size_t input_size,
uint8_t* output, [[maybe_unused]] size_t output_size) noexcept
{
return {EVMC_PRECOMPILE_FAILURE, 0};
if (input_size % 384 != 0)
return {EVMC_PRECOMPILE_FAILURE, 0};

assert(output_size == 32);

if (!crypto::bls::pairing_check(output, input, input_size))
return {EVMC_PRECOMPILE_FAILURE, 0};

return {EVMC_SUCCESS, 32};
}

ExecutionResult bls12_map_fp_to_g1_execute(const uint8_t* input, size_t input_size, uint8_t* output,
Expand Down
14 changes: 14 additions & 0 deletions test/unittests/precompiles_bls_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,17 @@ TEST(bls, map_fp2_to_g2)
EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x);
EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y);
}

TEST(bls, paring_check)
{
using namespace evmc::literals;
auto input =
"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d0000000000000000000000000000000006d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a87002500000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed"_hex;
uint8_t r[32];

EXPECT_TRUE(evmone::crypto::bls::pairing_check(r, input.data(), input.size()));

const auto expected = "0000000000000000000000000000000000000000000000000000000000000001"_hex;

EXPECT_EQ(evmc::bytes_view(r, sizeof r), expected);
}

0 comments on commit edfe00d

Please sign in to comment.