Skip to content

Commit

Permalink
precompiles: Implement bls g1 add
Browse files Browse the repository at this point in the history
  • Loading branch information
rodiazet committed Sep 10, 2024
1 parent 07d2f7a commit fde4252
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 6 deletions.
4 changes: 3 additions & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,9 @@ jobs:
# Tests for in-development EVM revision currently passing.
working_directory: ~/spec-tests/fixtures/state_tests
command: >
~/build/bin/evmone-statetest prague/eip2537_bls_12_381_precompiles/bls12_precompiles_before_fork
~/build/bin/evmone-statetest
prague/eip2537_bls_12_381_precompiles/bls12_precompiles_before_fork
prague/eip2537_bls_12_381_precompiles/bls12_g1add
- collect_coverage_gcc
- upload_coverage:
flags: execution_spec_tests
Expand Down
4 changes: 3 additions & 1 deletion lib/evmone_precompiles/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ include(blst)

add_library(evmone_precompiles STATIC)
add_library(evmone::precompiles ALIAS evmone_precompiles)
target_link_libraries(evmone_precompiles PUBLIC evmc::evmc_cpp PRIVATE evmone::evmmax)
target_link_libraries(evmone_precompiles PUBLIC evmc::evmc_cpp PRIVATE evmone::evmmax blst::blst)
target_sources(
evmone_precompiles PRIVATE
blake2b.hpp
blake2b.cpp
bls.hpp
bls.cpp
bn254.hpp
bn254.cpp
ecc.hpp
Expand Down
66 changes: 66 additions & 0 deletions lib/evmone_precompiles/bls.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "bls.hpp"
#include <blst.h>
#include <optional>

namespace evmone::crypto::bls
{
namespace
{
constexpr auto FP_BYTES_OFFSET = 64 - 48;

[[nodiscard]] std::optional<blst_p1_affine> validate_point(
const uint8_t _x[64], const uint8_t _y[64]) noexcept
{
constexpr auto is_field_element = [](const uint8_t _p[64]) {
return intx::be::unsafe::load<intx::uint512>(_p) < crypto::bls::BLS_FIELD_MODULUS;
};

if (!is_field_element(_x))
return std::nullopt;
if (!is_field_element(_y))
return std::nullopt;

blst_fp x;
blst_fp y;
blst_fp_from_bendian(&x, &_x[FP_BYTES_OFFSET]);
blst_fp_from_bendian(&y, &_y[FP_BYTES_OFFSET]);

const blst_p1_affine p0_affine{x, y};
if (!blst_p1_affine_on_curve(&p0_affine))
return std::nullopt;

return p0_affine;
}

void store_result(uint8_t _rx[64], uint8_t _ry[64], const blst_p1* out) noexcept
{
blst_p1_affine result;
blst_p1_to_affine(&result, out);

std::memset(_rx, 0, FP_BYTES_OFFSET);
blst_bendian_from_fp(&_rx[FP_BYTES_OFFSET], &result.x);
std::memset(_ry, 0, FP_BYTES_OFFSET);
blst_bendian_from_fp(&_ry[FP_BYTES_OFFSET], &result.y);
}
} // namespace

[[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
{
const auto p0_affine = validate_point(_x0, _y0);
const auto p1_affine = validate_point(_x1, _y1);

if (!p0_affine.has_value() || !p1_affine.has_value())
return false;

blst_p1 p0;
blst_p1_from_affine(&p0, &*p0_affine);

blst_p1 out;
blst_p1_add_or_double_affine(&out, &p0, &*p1_affine);

store_result(_rx, _ry, &out);

return true;
}
} // namespace evmone::crypto::bls
19 changes: 19 additions & 0 deletions lib/evmone_precompiles/bls.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <intx/intx.hpp>

using namespace intx::literals;

namespace evmone::crypto::bls
{
/// The BLS12-381 field prime number.
inline constexpr auto BLS_FIELD_MODULUS =
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab_u384;

/// Addition in BLS12-381 curve group.
///
/// Computes P ⊕ Q for two points in affine coordinates on the BLS12-381 curve,
[[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;

} // namespace evmone::crypto::bls
18 changes: 14 additions & 4 deletions test/state/precompiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "precompiles_internal.hpp"
#include "precompiles_stubs.hpp"
#include <evmone_precompiles/blake2b.hpp>
#include <evmone_precompiles/bls.hpp>
#include <evmone_precompiles/bn254.hpp>
#include <evmone_precompiles/ripemd160.hpp>
#include <evmone_precompiles/secp256k1.hpp>
Expand Down Expand Up @@ -155,8 +156,8 @@ PrecompileAnalysis point_evaluation_analyze(bytes_view, evmc_revision) noexcept

PrecompileAnalysis bls12_g1add_analyze(bytes_view, evmc_revision) noexcept
{
// TODO: Implement
return {GasCostMax, 0};
static constexpr auto BLS12_G1ADD_PRECOMPILE_GAS = 500;
return {BLS12_G1ADD_PRECOMPILE_GAS, 128};
}

PrecompileAnalysis bls12_g1mul_analyze(bytes_view, evmc_revision) noexcept
Expand Down Expand Up @@ -346,9 +347,18 @@ ExecutionResult blake2bf_execute(const uint8_t* input, [[maybe_unused]] size_t i
return {EVMC_SUCCESS, sizeof(h)};
}

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

assert(output_size == 128);

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

return {EVMC_SUCCESS, 128};
}

ExecutionResult bls12_g1mul_execute(const uint8_t*, size_t, uint8_t*, size_t) noexcept
Expand Down
1 change: 1 addition & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ target_sources(
exportable_fixture.cpp
instructions_test.cpp
precompiles_blake2b_test.cpp
precompiles_bls_test.cpp
precompiles_ripemd160_test.cpp
precompiles_sha256_test.cpp
state_block_test.cpp
Expand Down
72 changes: 72 additions & 0 deletions test/unittests/precompiles_bls_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2024 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include <evmc/bytes.hpp>
#include <evmone_precompiles/bls.hpp>
#include <gtest/gtest.h>
#include <test/utils/utils.hpp>
#include <array>

using evmone::test::operator""_hex;

TEST(bls, g1_add)
{
const auto x0 =
"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"_hex;
const auto y0 =
"0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"_hex;
const auto x1 =
"00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca9426"_hex;
const auto y1 =
"00000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21"_hex;

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

EXPECT_TRUE(evmone::crypto::bls::g1_add(rx, ry, x0.data(), y0.data(), x1.data(), y1.data()));

const auto expected_x =
"000000000000000000000000000000000a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d"_hex;
const auto expected_y =
"0000000000000000000000000000000006d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a870025"_hex;

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

TEST(bls, g1_add_not_on_curve)
{
{
const auto x0 =
"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6ba"_hex;
const auto y0 =
"0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"_hex;
const auto x1 =
"00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca9426"_hex;
const auto y1 =
"00000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21"_hex;

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

EXPECT_FALSE(
evmone::crypto::bls::g1_add(rx, ry, x0.data(), y0.data(), x1.data(), y1.data()));
}
{
const auto x0 =
"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"_hex;
const auto y0 =
"0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"_hex;
const auto x1 =
"00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca9426"_hex;
const auto y1 =
"00000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a22"_hex;

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

EXPECT_FALSE(
evmone::crypto::bls::g1_add(rx, ry, x0.data(), y0.data(), x1.data(), y1.data()));
}
}

0 comments on commit fde4252

Please sign in to comment.