From 1358b17b8cb2cc0cc615af632be7dc84dd45beba Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 13 Sep 2024 15:44:01 +0200 Subject: [PATCH] precompiles: Implement EIP-2537's `bls12_g2mul` (#999) Implementation of the `bls12_g2mul` precompile: E2 affine point's multiplication from BLS12-381 curve according to the EIP-2537 spec https://eips.ethereum.org/EIPS/eip-2537#abi-for-g2-multiplication. Depends on https://github.com/ethereum/evmone/pull/995 --- circle.yml | 1 + lib/evmone_precompiles/bls.cpp | 27 +++++++++++++++++++++++++ lib/evmone_precompiles/bls.hpp | 8 ++++++++ test/state/precompiles.cpp | 17 ++++++++++++---- test/unittests/precompiles_bls_test.cpp | 22 ++++++++++++++++++++ 5 files changed, 71 insertions(+), 4 deletions(-) diff --git a/circle.yml b/circle.yml index 3c1d5c183e..3aa950f73b 100644 --- a/circle.yml +++ b/circle.yml @@ -376,6 +376,7 @@ jobs: 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 - run: name: "Execution spec tests (develop, blockchain_tests)" # Tests for in-development EVM revision currently passing. diff --git a/lib/evmone_precompiles/bls.cpp b/lib/evmone_precompiles/bls.cpp index 4312e4470b..49eb5af0b7 100644 --- a/lib/evmone_precompiles/bls.cpp +++ b/lib/evmone_precompiles/bls.cpp @@ -156,4 +156,31 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept return true; } +[[nodiscard]] bool g2_mul(uint8_t _rx[128], uint8_t _ry[128], const uint8_t _x[128], + const uint8_t _y[128], const uint8_t _c[32]) noexcept +{ + blst_scalar scalar; + blst_scalar_from_bendian(&scalar, _c); + + const auto p_affine = validate_p2(_x, _y); + if (!p_affine.has_value()) + return false; + + blst_p2 p; + blst_p2_from_affine(&p, &*p_affine); + + if (!blst_p2_in_g2(&p)) + return false; + + blst_p2 out; + blst_p2_mult(&out, &p, scalar.b, 256); + + blst_p2_affine result; + blst_p2_to_affine(&result, &out); + store(_rx, result.x); + store(_ry, result.y); + + return true; +} + } // namespace evmone::crypto::bls diff --git a/lib/evmone_precompiles/bls.hpp b/lib/evmone_precompiles/bls.hpp index 4e18b38fec..1a139a5376 100644 --- a/lib/evmone_precompiles/bls.hpp +++ b/lib/evmone_precompiles/bls.hpp @@ -31,4 +31,12 @@ inline constexpr auto BLS_FIELD_MODULUS = [[nodiscard]] bool g2_add(uint8_t _rx[128], uint8_t _ry[128], const uint8_t _x0[128], const uint8_t _y0[128], const uint8_t _x1[128], const uint8_t _y1[128]) noexcept; +/// Scalar multiplication in BLS12-381 curve group over G2 extension field +/// +/// Computes [c]P for a point in affine coordinate on the BLS12-381 curve over G2 extension +/// field, performs subgroup check according to spec +/// https://eips.ethereum.org/EIPS/eip-2537#abi-for-g2-multiplication +[[nodiscard]] bool g2_mul(uint8_t _rx[128], uint8_t _ry[128], const uint8_t _x[128], + const uint8_t _y[128], const uint8_t _c[32]) noexcept; + } // namespace evmone::crypto::bls diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index 6a6e96095a..31a93a57ff 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -180,8 +180,8 @@ PrecompileAnalysis bls12_g2add_analyze(bytes_view, evmc_revision) noexcept PrecompileAnalysis bls12_g2mul_analyze(bytes_view, evmc_revision) noexcept { - // TODO: Implement - return {GasCostMax, 0}; + static constexpr auto BLS12_G2MUL_PRECOMPILE_GAS = 45000; + return {BLS12_G2MUL_PRECOMPILE_GAS, 256}; } PrecompileAnalysis bls12_g2msm_analyze(bytes_view, evmc_revision) noexcept @@ -394,9 +394,18 @@ ExecutionResult bls12_g2add_execute(const uint8_t* input, size_t input_size, uin return {EVMC_SUCCESS, 256}; } -ExecutionResult bls12_g2mul_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept +ExecutionResult bls12_g2mul_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 != 288) + return {EVMC_PRECOMPILE_FAILURE, 0}; + + assert(output_size == 256); + + if (!crypto::bls::g2_mul(output, &output[128], input, &input[128], &input[256])) + return {EVMC_PRECOMPILE_FAILURE, 0}; + + return {EVMC_SUCCESS, 256}; } ExecutionResult bls12_g2msm_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept diff --git a/test/unittests/precompiles_bls_test.cpp b/test/unittests/precompiles_bls_test.cpp index c50a047784..fd4ae58116 100644 --- a/test/unittests/precompiles_bls_test.cpp +++ b/test/unittests/precompiles_bls_test.cpp @@ -117,3 +117,25 @@ TEST(bls, g2_add) EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x); EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y); } + +TEST(bls, g2_mul) +{ + const auto x = + "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e"_hex; + const auto y = + "000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be"_hex; + const auto c = "0000000000000000000000000000000000000000000000000000000000000002"_hex; + + uint8_t rx[128]; + uint8_t ry[128]; + + EXPECT_TRUE(evmone::crypto::bls::g2_mul(rx, ry, x.data(), y.data(), c.data())); + + const auto expected_x = + "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577"_hex; + const auto expected_y = + "000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3"_hex; + + EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x); + EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y); +}