Skip to content

Commit 37d7c4d

Browse files
committed
precompiles: Implement bls g2 mul
1 parent 8653852 commit 37d7c4d

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
@@ -376,6 +376,7 @@ jobs:
376376
prague/eip2537_bls_12_381_precompiles/bls12_g1add
377377
prague/eip2537_bls_12_381_precompiles/bls12_g1mul
378378
prague/eip2537_bls_12_381_precompiles/bls12_g2add
379+
prague/eip2537_bls_12_381_precompiles/bls12_g2mul
379380
- run:
380381
name: "Execution spec tests (develop, blockchain_tests)"
381382
# Tests for in-development EVM revision currently passing.

lib/evmone_precompiles/bls.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,28 @@ void store_result_g2(uint8_t _rx[128], uint8_t _ry[128], const blst_p2* out) noe
162162
return true;
163163
}
164164

165+
[[nodiscard]] bool g2_mul(uint8_t _rx[128], uint8_t _ry[128], const uint8_t _x[128],
166+
const uint8_t _y[128], const uint8_t _c[32]) noexcept
167+
{
168+
blst_scalar scalar;
169+
blst_scalar_from_bendian(&scalar, _c);
170+
171+
const auto p_affine = validate_p2(_x, _y);
172+
if (!p_affine.has_value())
173+
return false;
174+
175+
blst_p2 p;
176+
blst_p2_from_affine(&p, &*p_affine);
177+
178+
if (!blst_p2_in_g2(&p))
179+
return false;
180+
181+
blst_p2 out;
182+
blst_p2_mult(&out, &p, scalar.b, 256);
183+
184+
store_result_g2(_rx, _ry, &out);
185+
186+
return true;
187+
}
188+
165189
} // namespace evmone::crypto::bls

lib/evmone_precompiles/bls.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ inline constexpr auto BLS_FIELD_MODULUS =
3131
[[nodiscard]] bool g2_add(uint8_t _rx[128], uint8_t _ry[128], const uint8_t _x0[128],
3232
const uint8_t _y0[128], const uint8_t _x1[128], const uint8_t _y1[128]) noexcept;
3333

34+
/// Scalar multiplication in BLS12-381 curve group over G2 extension field
35+
///
36+
/// Computes [c]P for a point in affine coordinate on the BLS12-381 curve over G2 extension
37+
/// field, performs subgroup check according to spec
38+
/// https://eips.ethereum.org/EIPS/eip-2537#abi-for-g2-multiplication
39+
[[nodiscard]] bool g2_mul(uint8_t _rx[128], uint8_t _ry[128], const uint8_t _x[128],
40+
const uint8_t _y[128], const uint8_t _c[32]) noexcept;
41+
3442
} // namespace evmone::crypto::bls

test/state/precompiles.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ PrecompileAnalysis bls12_g2add_analyze(bytes_view, evmc_revision) noexcept
180180

181181
PrecompileAnalysis bls12_g2mul_analyze(bytes_view, evmc_revision) noexcept
182182
{
183-
// TODO: Implement
184-
return {GasCostMax, 0};
183+
static constexpr auto BLS12_G2MUL_PRECOMPILE_GAS = 45000;
184+
return {BLS12_G2MUL_PRECOMPILE_GAS, 256};
185185
}
186186

187187
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
394394
return {EVMC_SUCCESS, 256};
395395
}
396396

397-
ExecutionResult bls12_g2mul_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept
397+
ExecutionResult bls12_g2mul_execute(const uint8_t* input, size_t input_size, uint8_t* output,
398+
[[maybe_unused]] size_t output_size) noexcept
398399
{
399-
return {EVMC_PRECOMPILE_FAILURE, 0};
400+
if (input_size != 288)
401+
return {EVMC_PRECOMPILE_FAILURE, 0};
402+
403+
assert(output_size == 256);
404+
405+
if (!crypto::bls::g2_mul(output, &output[128], input, &input[128], &input[256]))
406+
return {EVMC_PRECOMPILE_FAILURE, 0};
407+
408+
return {EVMC_SUCCESS, 256};
400409
}
401410

402411
ExecutionResult bls12_g2msm_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
@@ -117,3 +117,25 @@ TEST(bls, g2_add)
117117
EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x);
118118
EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y);
119119
}
120+
121+
TEST(bls, g2_mul)
122+
{
123+
const auto x =
124+
"00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e"_hex;
125+
const auto y =
126+
"000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be"_hex;
127+
const auto c = "0000000000000000000000000000000000000000000000000000000000000002"_hex;
128+
129+
uint8_t rx[128];
130+
uint8_t ry[128];
131+
132+
EXPECT_TRUE(evmone::crypto::bls::g2_mul(rx, ry, x.data(), y.data(), c.data()));
133+
134+
const auto expected_x =
135+
"000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577"_hex;
136+
const auto expected_y =
137+
"000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3"_hex;
138+
139+
EXPECT_EQ(evmc::bytes_view(rx, sizeof rx), expected_x);
140+
EXPECT_EQ(evmc::bytes_view(ry, sizeof ry), expected_y);
141+
}

0 commit comments

Comments
 (0)