Skip to content

Commit acfc76d

Browse files
committed
precompiles: Implement bls g1 mul
1 parent 12766de commit acfc76d

File tree

5 files changed

+68
-4
lines changed

5 files changed

+68
-4
lines changed

circle.yml

+1
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ jobs:
374374
~/build/bin/evmone-statetest
375375
prague/eip2537_bls_12_381_precompiles/bls12_precompiles_before_fork
376376
prague/eip2537_bls_12_381_precompiles/bls12_g1add
377+
prague/eip2537_bls_12_381_precompiles/bls12_g1mul
377378
- collect_coverage_gcc
378379
- upload_coverage:
379380
flags: execution_spec_tests

lib/evmone_precompiles/bls.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ namespace evmone::crypto::bls
66
{
77
namespace
88
{
9+
using namespace intx::literals;
10+
911
/// Offset of the beginning of field element. First 16 bytes must be zero according to spec
1012
/// https://eips.ethereum.org/EIPS/eip-2537#field-elements-encoding
1113
constexpr auto FP_BYTES_OFFSET = 64 - 48;
@@ -68,4 +70,28 @@ void store_result(uint8_t _rx[64], uint8_t _ry[64], const blst_p1* out) noexcept
6870

6971
return true;
7072
}
73+
74+
[[nodiscard]] bool g1_mul(uint8_t _rx[64], uint8_t _ry[64], const uint8_t _x[64],
75+
const uint8_t _y[64], const uint8_t _c[32]) noexcept
76+
{
77+
blst_scalar scalar;
78+
blst_scalar_from_bendian(&scalar, _c);
79+
80+
const auto p_affine = validate_point(_x, _y);
81+
if (!p_affine.has_value())
82+
return false;
83+
84+
blst_p1 p;
85+
blst_p1_from_affine(&p, &*p_affine);
86+
87+
if (!blst_p1_in_g1(&p))
88+
return false;
89+
90+
blst_p1 out;
91+
blst_p1_mult(&out, &p, scalar.b, 256);
92+
93+
store_result(_rx, _ry, &out);
94+
95+
return true;
96+
}
7197
} // namespace evmone::crypto::bls

lib/evmone_precompiles/bls.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,10 @@ inline constexpr auto BLS_FIELD_MODULUS =
1616
[[nodiscard]] bool g1_add(uint8_t _rx[64], uint8_t _ry[64], const uint8_t _x0[64],
1717
const uint8_t _y0[64], const uint8_t _x1[64], const uint8_t _y1[64]) noexcept;
1818

19+
/// Scalar multiplication in BLS12-381 curve group.
20+
///
21+
/// Computes [c]P for a point in affine coordinate on the BLS12-381 curve,
22+
[[nodiscard]] bool g1_mul(uint8_t _rx[64], uint8_t _ry[64], const uint8_t _x[64],
23+
const uint8_t _y[64], const uint8_t _c[32]) noexcept;
24+
1925
} // namespace evmone::crypto::bls

test/state/precompiles.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ PrecompileAnalysis bls12_g1add_analyze(bytes_view, evmc_revision) noexcept
162162

163163
PrecompileAnalysis bls12_g1mul_analyze(bytes_view, evmc_revision) noexcept
164164
{
165-
// TODO: Implement
166-
return {GasCostMax, 0};
165+
static constexpr auto BLS12_G1MUL_PRECOMPILE_GAS = 12000;
166+
return {BLS12_G1MUL_PRECOMPILE_GAS, 128};
167167
}
168168

169169
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
361361
return {EVMC_SUCCESS, 128};
362362
}
363363

364-
ExecutionResult bls12_g1mul_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept
364+
ExecutionResult bls12_g1mul_execute(const uint8_t* input, size_t input_size, uint8_t* output,
365+
[[maybe_unused]] size_t output_size) noexcept
365366
{
366-
return {EVMC_PRECOMPILE_FAILURE, 0};
367+
if (input_size != 160)
368+
return {EVMC_PRECOMPILE_FAILURE, 0};
369+
370+
assert(output_size == 128);
371+
372+
if (!crypto::bls::g1_mul(output, &output[64], input, &input[64], &input[128]))
373+
return {EVMC_PRECOMPILE_FAILURE, 0};
374+
375+
return {EVMC_SUCCESS, 128};
367376
}
368377

369378
ExecutionResult bls12_g1msm_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept

test/unittests/precompiles_bls_test.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,25 @@ TEST(bls, g1_add_not_on_curve)
7070
evmone::crypto::bls::g1_add(rx, ry, x0.data(), y0.data(), x1.data(), y1.data()));
7171
}
7272
}
73+
74+
TEST(bls, g1_mul)
75+
{
76+
const auto x =
77+
"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"_hex;
78+
const auto y =
79+
"0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"_hex;
80+
const auto c = "0000000000000000000000000000000000000000000000000000000000000002"_hex;
81+
82+
uint8_t rx[64];
83+
uint8_t ry[64];
84+
85+
EXPECT_TRUE(evmone::crypto::bls::g1_mul(rx, ry, x.data(), y.data(), c.data()));
86+
87+
const auto expected_x =
88+
"000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e"_hex;
89+
const auto expected_y =
90+
"00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28"_hex;
91+
92+
EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x);
93+
EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y);
94+
}

0 commit comments

Comments
 (0)