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 2, 2024
1 parent 112147e commit 90fcdc7
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 3 deletions.
2 changes: 1 addition & 1 deletion cmake/blst.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ if(MSVC)
set(BLST_BUILD_SCRIPT build.bat)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# Don't pass CC to the script because it doesn't work.
set(BLST_BUILD_SCRIPT ./build.sh -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET})
set(BLST_BUILD_SCRIPT ./build.sh)
else()
# Pass CC and AR, this supports cross-compilation.
# Pass CFLAGS as part of CC (e.g. to pass -m32). Using CFLAGS directly overwrites blst's default.
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
42 changes: 42 additions & 0 deletions lib/evmone_precompiles/bls.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "bls.hpp"
#include <blst.hpp>

namespace evmone::crypto::bls
{
bool g1_add(uint8_t* _rx, uint8_t* _ry, const uint8_t _x0[48], const uint8_t _y0[48],
const uint8_t _x1[48], const uint8_t _y1[48])
{
blst::blst_fp x0;
blst::blst_fp y0;
blst::blst_fp x1;
blst::blst_fp y1;
blst::blst_fp_from_bendian(&x0, _x0);
blst::blst_fp_from_bendian(&y0, _y0);
blst::blst_fp_from_bendian(&x1, _x1);
blst::blst_fp_from_bendian(&y1, _y1);

blst::blst_p1_affine p0_affine{x0, y0};
if (!blst::blst_p1_affine_on_curve(&p0_affine))
return false;

blst::blst_p1_affine p1_affine{x1, y1};
if (!blst::blst_p1_affine_on_curve(&p1_affine))
return false;

blst::blst_p1 p0;
blst::blst_p1 p1;
blst::blst_p1_from_affine(&p0, &p0_affine);
blst::blst_p1_from_affine(&p1, &p1_affine);

blst::blst_p1 out;
blst::blst_p1_add_or_double(&out, &p0, &p1);

blst::blst_p1_affine result;
blst::blst_p1_to_affine(&result, &out);

blst::blst_bendian_from_fp(_rx, &result.x);
blst::blst_bendian_from_fp(_ry, &result.y);

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

#include <cstdint>
#include <intx/intx.hpp>

// TODO(intx): Add ""_u384.
inline constexpr auto operator""_u384(const char* s)
{
return intx::from_string<intx::uint384>(s);
}

namespace evmone::crypto::bls
{
inline constexpr auto FieldPrime =
0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab_u384;

bool g1_add(uint8_t* _rx, uint8_t* _ry, const uint8_t _x0[48], const uint8_t _y0[48],
const uint8_t _x1[48], const uint8_t _y1[48]);

} // namespace evmone::crypto::bls
54 changes: 54 additions & 0 deletions test/state/precompiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
#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>
#include <evmone_precompiles/sha256.hpp>
#include <intx/intx.hpp>
#include <algorithm>
#include <array>
#include <bit>
#include <cassert>
#include <limits>
#include <span>

#ifdef EVMONE_PRECOMPILES_SILKPRE
#include "precompiles_silkpre.hpp"
Expand Down Expand Up @@ -153,6 +156,12 @@ PrecompileAnalysis point_evaluation_analyze(bytes_view, evmc_revision) noexcept
return {POINT_EVALUATION_PRECOMPILE_GAS, 64};
}

PrecompileAnalysis bls12_g1add_analyze(bytes_view, evmc_revision) noexcept
{
static constexpr auto BLS12_G1ADD_PRECOMPILE_GAS = 500;
return {BLS12_G1ADD_PRECOMPILE_GAS, 128};
}

ExecutionResult ecrecover_execute(const uint8_t* input, size_t input_size, uint8_t* output,
[[maybe_unused]] size_t output_size) noexcept
{
Expand Down Expand Up @@ -292,6 +301,50 @@ ExecutionResult blake2bf_execute(const uint8_t* input, [[maybe_unused]] size_t i
return {EVMC_SUCCESS, sizeof(h)};
}

ExecutionResult bls12_g1add_execute(
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept
{
static_assert(std::endian::native == std::endian::little,
"bls12_g1add only works correctly on little-endian architectures");

if (input_size != 256)
return {EVMC_PRECOMPILE_FAILURE, 0};

if (output_size != 128)
return {EVMC_PRECOMPILE_FAILURE, 0};

memset(output, 0, output_size);

constexpr auto verify_element = [](const uint8_t* p) {
constexpr auto check_zero_padded = [](const uint8_t* v) {
std::span s(v, 16);
if (!std::all_of(s.begin(), s.end(), [](const auto& i) { return i == 0; }))
return false;
return true;
};
constexpr auto is_field_element = [](const uint8_t* v) {
return intx::be::unsafe::load<intx::uint384>(v) < crypto::bls::FieldPrime;
};

return check_zero_padded(p) && is_field_element(&p[16]);
};

if (!verify_element(input))
return {EVMC_PRECOMPILE_FAILURE, 0};
if (!verify_element(&input[64]))
return {EVMC_PRECOMPILE_FAILURE, 0};
if (!verify_element(&input[128]))
return {EVMC_PRECOMPILE_FAILURE, 0};
if (!verify_element(&input[192]))
return {EVMC_PRECOMPILE_FAILURE, 0};

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

return {EVMC_SUCCESS, 128};
}

namespace
{
struct PrecompileTraits
Expand All @@ -313,6 +366,7 @@ inline constexpr auto traits = []() noexcept {
{ecpairing_analyze, ecpairing_stub},
{blake2bf_analyze, blake2bf_execute},
{point_evaluation_analyze, point_evaluation_stub},
{bls12_g1add_analyze, bls12_g1add_execute},
}};
#ifdef EVMONE_PRECOMPILES_SILKPRE
// tbl[static_cast<size_t>(PrecompileId::ecrecover)].execute = silkpre_ecrecover_execute;
Expand Down
4 changes: 3 additions & 1 deletion test/state/precompiles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ enum class PrecompileId : uint8_t
ecpairing = 0x08,
blake2bf = 0x09,
point_evaluation = 0x0a,
bls12_g1add = 0x0b,

since_byzantium = expmod, ///< The first precompile introduced in Byzantium.
since_istanbul = blake2bf, ///< The first precompile introduced in Istanbul.
since_cancun = point_evaluation, ///< The first precompile introduced in Cancun.
latest = point_evaluation ///< The latest introduced precompile (highest address).
since_prague = bls12_g1add, ///< The first precompile introduced in Prague.
latest = bls12_g1add ///< The latest introduced precompile (highest address).
};

/// The total number of known precompiles ids, including 0.
Expand Down
3 changes: 3 additions & 0 deletions test/state/precompiles_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ PrecompileAnalysis ecmul_analyze(evmc::bytes_view input, evmc_revision rev) noex
PrecompileAnalysis ecpairing_analyze(evmc::bytes_view input, evmc_revision rev) noexcept;
PrecompileAnalysis blake2bf_analyze(evmc::bytes_view input, evmc_revision rev) noexcept;
PrecompileAnalysis point_evaluation_analyze(evmc::bytes_view input, evmc_revision rev) noexcept;
PrecompileAnalysis bls12_g1add_analyze(evmc::bytes_view input, evmc_revision rev) noexcept;

ExecutionResult ecrecover_execute(
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;
Expand All @@ -44,4 +45,6 @@ ExecutionResult ecmul_execute(
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;
ExecutionResult blake2bf_execute(
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;
ExecutionResult bls12_g1add_execute(
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;
} // namespace evmone::state
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
36 changes: 36 additions & 0 deletions test/unittests/precompiles_bls_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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 =
"17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"_hex;
const auto y0 =
"08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"_hex;
const auto x1 =
"112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca9426"_hex;
const auto y1 =
"186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21"_hex;

uint8_t rx[48];
uint8_t ry[48];

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

const auto expected_x =
"0a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d"_hex;
const auto expected_y =
"06d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a870025"_hex;

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

0 comments on commit 90fcdc7

Please sign in to comment.