Skip to content

Commit

Permalink
precompiles: Implement EIP-2537's bls12_g1mul (#994)
Browse files Browse the repository at this point in the history
Implementation of the `bls12_g1mul` precompile: E1 affine point's
multiplication from BLS12-381 curve by a scalar according to the
EIP-2537 spec
https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-multiplication.

Depends on #982
  • Loading branch information
rodiazet authored Sep 11, 2024
1 parent 35b7475 commit 07c8a0e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 4 deletions.
1 change: 1 addition & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ jobs:
~/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
- run:
name: "Execution spec tests (develop, blockchain_tests)"
# Tests for in-development EVM revision currently passing.
Expand Down
24 changes: 24 additions & 0 deletions lib/evmone_precompiles/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,28 @@ void store_result(uint8_t _rx[64], uint8_t _ry[64], const blst_p1* out) noexcept

return true;
}

[[nodiscard]] bool g1_mul(uint8_t _rx[64], uint8_t _ry[64], const uint8_t _x[64],
const uint8_t _y[64], const uint8_t _c[32]) noexcept
{
blst_scalar scalar;
blst_scalar_from_bendian(&scalar, _c);

const auto p_affine = validate_point(_x, _y);
if (!p_affine.has_value())
return false;

blst_p1 p;
blst_p1_from_affine(&p, &*p_affine);

if (!blst_p1_in_g1(&p))
return false;

blst_p1 out;
blst_p1_mult(&out, &p, scalar.b, 256);

store_result(_rx, _ry, &out);

return true;
}
} // namespace evmone::crypto::bls
7 changes: 7 additions & 0 deletions lib/evmone_precompiles/bls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ inline constexpr auto BLS_FIELD_MODULUS =
[[nodiscard]] bool g1_add(uint8_t _rx[64], uint8_t _ry[64], const uint8_t _x0[64],
const uint8_t _y0[64], const uint8_t _x1[64], const uint8_t _y1[64]) noexcept;

/// Scalar multiplication in BLS12-381 curve G1 subgroup.
///
/// Computes [c]P for a point in affine coordinate on the BLS12-381 curve, performs subgroup check
/// according to spec https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-multiplication
[[nodiscard]] bool g1_mul(uint8_t _rx[64], uint8_t _ry[64], const uint8_t _x[64],
const uint8_t _y[64], const uint8_t _c[32]) noexcept;

} // namespace evmone::crypto::bls
17 changes: 13 additions & 4 deletions test/state/precompiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ PrecompileAnalysis bls12_g1add_analyze(bytes_view, evmc_revision) noexcept

PrecompileAnalysis bls12_g1mul_analyze(bytes_view, evmc_revision) noexcept
{
// TODO: Implement
return {GasCostMax, 0};
static constexpr auto BLS12_G1MUL_PRECOMPILE_GAS = 12000;
return {BLS12_G1MUL_PRECOMPILE_GAS, 128};
}

PrecompileAnalysis bls12_g1msm_analyze(bytes_view, evmc_revision) noexcept
Expand Down Expand Up @@ -361,9 +361,18 @@ ExecutionResult bls12_g1add_execute(const uint8_t* input, size_t input_size, uin
return {EVMC_SUCCESS, 128};
}

ExecutionResult bls12_g1mul_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept
ExecutionResult bls12_g1mul_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 != 160)
return {EVMC_PRECOMPILE_FAILURE, 0};

assert(output_size == 128);

if (!crypto::bls::g1_mul(output, &output[64], input, &input[64], &input[128]))
return {EVMC_PRECOMPILE_FAILURE, 0};

return {EVMC_SUCCESS, 128};
}

ExecutionResult bls12_g1msm_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept
Expand Down
22 changes: 22 additions & 0 deletions test/unittests/precompiles_bls_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,25 @@ TEST(bls, g1_add_not_on_curve)
evmone::crypto::bls::g1_add(rx, ry, x0.data(), y0.data(), x1.data(), y1.data()));
}
}

TEST(bls, g1_mul)
{
const auto x =
"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"_hex;
const auto y =
"0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"_hex;
const auto c = "0000000000000000000000000000000000000000000000000000000000000002"_hex;

uint8_t rx[64];
uint8_t ry[64];

EXPECT_TRUE(evmone::crypto::bls::g1_mul(rx, ry, x.data(), y.data(), c.data()));

const auto expected_x =
"000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e"_hex;
const auto expected_y =
"00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28"_hex;

EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x);
EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y);
}

0 comments on commit 07c8a0e

Please sign in to comment.