From 16f74d1e4c145c66cbdaea6a06395a6ebdee134e Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 10 Sep 2024 12:16:57 +0200 Subject: [PATCH] precompiles: Implement bls g1 mul --- circle.yml | 1 + lib/evmone_precompiles/bls.cpp | 30 +++++++++++++++++++++++++ lib/evmone_precompiles/bls.hpp | 6 +++++ test/state/precompiles.cpp | 17 ++++++++++---- test/unittests/precompiles_bls_test.cpp | 22 ++++++++++++++++++ 5 files changed, 72 insertions(+), 4 deletions(-) diff --git a/circle.yml b/circle.yml index 44bd6e496e..a856e6d7f5 100644 --- a/circle.yml +++ b/circle.yml @@ -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 - collect_coverage_gcc - upload_coverage: flags: execution_spec_tests diff --git a/lib/evmone_precompiles/bls.cpp b/lib/evmone_precompiles/bls.cpp index f8d0325b27..97d0265cdb 100644 --- a/lib/evmone_precompiles/bls.cpp +++ b/lib/evmone_precompiles/bls.cpp @@ -6,7 +6,12 @@ namespace evmone::crypto::bls { namespace { +using namespace intx::literals; + constexpr auto FP_BYTES_OFFSET = 64 - 48; +constexpr size_t BLS_MODULUS_BITS = 255; +constexpr auto MAIN_SUBGROUP_ORDER = + 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001_u256; [[nodiscard]] std::optional validate_point( const uint8_t _x[64], const uint8_t _y[64]) noexcept @@ -63,4 +68,29 @@ 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 +{ + const auto c = intx::be::unsafe::load(_c) % MAIN_SUBGROUP_ORDER; + blst_scalar scalar; + blst_scalar_from_uint64(&scalar, as_words(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.value()); + + if (!blst_p1_in_g1(&p)) + return false; + + blst_p1 out; + blst_p1_mult(&out, &p, scalar.b, BLS_MODULUS_BITS); + + store_result(_rx, _ry, &out); + + return true; +} } // namespace evmone::crypto::bls diff --git a/lib/evmone_precompiles/bls.hpp b/lib/evmone_precompiles/bls.hpp index a83666c3e1..410b3dedbc 100644 --- a/lib/evmone_precompiles/bls.hpp +++ b/lib/evmone_precompiles/bls.hpp @@ -16,4 +16,10 @@ 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 group. +/// +/// Computes [c]P for a point in affine coordinate on the bls12-381 curve, +[[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 diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index 21c8056037..61ff9f8849 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -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 @@ -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 diff --git a/test/unittests/precompiles_bls_test.cpp b/test/unittests/precompiles_bls_test.cpp index 4be6c631e8..794aa7ff58 100644 --- a/test/unittests/precompiles_bls_test.cpp +++ b/test/unittests/precompiles_bls_test.cpp @@ -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); +}