Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

precompiles: Investigate missing BLS test cases #1015

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions lib/evmone_precompiles/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace evmone::crypto::bls
{
using namespace intx;
namespace
{
/// Offset of the beginning of field element. First 16 bytes must be zero according to spec
Expand All @@ -15,6 +16,7 @@ constexpr auto FP_BYTES_OFFSET = 64 - 48;
/// Validates that integer encoded in big endian is valid element of BLS12-381 Fp field
[[nodiscard]] std::optional<blst_fp> validate_fp(const uint8_t _p[64]) noexcept
{
// assert(intx::be::unsafe::load<intx::uint512>(_p) != BLS_FIELD_MODULUS);
if (intx::be::unsafe::load<intx::uint512>(_p) >= BLS_FIELD_MODULUS)
return std::nullopt;

Expand All @@ -29,13 +31,20 @@ constexpr auto FP_BYTES_OFFSET = 64 - 48;
const uint8_t _x[64], const uint8_t _y[64]) noexcept
{
const auto x = validate_fp(_x);
const auto y = validate_fp(_y);

// assert(x.has_value() && y.has_value());
// assert(x.has_value() && !y.has_value());
// assert(!x.has_value() && !y.has_value());
// assert(!x.has_value() && y.has_value());

if (!x.has_value())
return std::nullopt;
const auto y = validate_fp(_y);
if (!y.has_value())
return std::nullopt;

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

Expand All @@ -46,9 +55,15 @@ constexpr auto FP_BYTES_OFFSET = 64 - 48;
[[nodiscard]] std::optional<blst_fp2> validate_fp2(const uint8_t _p[128]) noexcept
{
const auto fp0 = validate_fp(_p);
const auto fp1 = validate_fp(&_p[64]);

// assert(fp0.has_value() && fp1.has_value());
// assert(fp0.has_value() && !fp1.has_value());
// assert(!fp0.has_value() && !fp1.has_value());
// assert(!fp0.has_value() && fp1.has_value());

if (!fp0.has_value())
return std::nullopt;
const auto fp1 = validate_fp(&_p[64]);
if (!fp1.has_value())
return std::nullopt;

Expand All @@ -61,14 +76,21 @@ constexpr auto FP_BYTES_OFFSET = 64 - 48;
const uint8_t _x[128], const uint8_t _y[128]) noexcept
{
const auto x = validate_fp2(_x);
const auto y = validate_fp2(_y);

// assert(x.has_value() && y.has_value());
// assert(x.has_value() && !y.has_value());
// assert(!x.has_value() && !y.has_value());
// assert(!x.has_value() && y.has_value());

if (!x.has_value())
return std::nullopt;

const auto y = validate_fp2(_y);
if (!y.has_value())
return std::nullopt;

const blst_p2_affine p_affine{*x, *y};
// assert(blst_p2_affine_on_curve(&p_affine));
if (!blst_p2_affine_on_curve(&p_affine))
return std::nullopt;

Expand Down Expand Up @@ -209,6 +231,7 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept
scalars_ptrs.reserve(npoints);

auto ptr = _xycs;
[[maybe_unused]] const auto x_org_npoints = npoints;
for (size_t i = 0; i < npoints; ++i)
{
const auto p_affine = validate_p1(ptr, &ptr[64]);
Expand All @@ -220,11 +243,18 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept

// Point at infinity must be filtered out for BLST library.
if (blst_p1_affine_is_inf(&*p_affine))
{
[[maybe_unused]] const auto xs = be::unsafe::load<uint256>(ptr + 128);
// assert(xs == 0);
// assert(xs != 0);
assert(xs != 1);
continue;
}

const auto& p = p1_affines.emplace_back(*p_affine);
p1_affine_ptrs.emplace_back(&p);

// assert((ptr[128] & 0x80) != 0);
blst_scalar scalar;
blst_scalar_from_bendian(&scalar, &ptr[128]);
const auto& s = scalars.emplace_back(scalar);
Expand All @@ -237,6 +267,8 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept

if (npoints == 0)
{
// assert(x_org_npoints == 0);
assert(x_org_npoints != 0);
memset(_rx, 0, 64);
memset(_ry, 0, 64);
return true;
Expand Down Expand Up @@ -273,6 +305,7 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept
scalars.reserve(npoints);
scalars_ptrs.reserve(npoints);

[[maybe_unused]] const auto x_org_npoints = npoints;
auto ptr = _xycs;
for (size_t i = 0; i < npoints; ++i)
{
Expand All @@ -285,11 +318,18 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept

// Point at infinity must be filtered out for BLST library.
if (blst_p2_affine_is_inf(&*p_affine))
{
[[maybe_unused]] const auto xs = be::unsafe::load<uint256>(ptr + 256);
// assert(xs == 0);
// assert(xs != 0);
assert(xs != 1);
continue;
}

const auto& p = p2_affines.emplace_back(*p_affine);
p2_affine_ptrs.emplace_back(&p);

// assert((ptr[256] & 0x80) != 0);
blst_scalar scalar;
blst_scalar_from_bendian(&scalar, &ptr[256]);
const auto& s = scalars.emplace_back(scalar);
Expand All @@ -302,6 +342,8 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept

if (npoints == 0)
{
// assert(x_org_npoints == 0);
assert(x_org_npoints != 0);
memset(_rx, 0, 128);
memset(_ry, 0, 128);
return true;
Expand Down
4 changes: 4 additions & 0 deletions test/state/precompiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ PrecompileAnalysis bls12_g1mul_analyze(bytes_view, evmc_revision) noexcept

PrecompileAnalysis bls12_g1msm_analyze(bytes_view input, evmc_revision) noexcept
{
// assert(!input.empty());
// assert(input.size() % 160 == 0);
if (input.empty() || input.size() % 160 != 0)
return {GasCostMax, 0};

Expand All @@ -209,6 +211,8 @@ PrecompileAnalysis bls12_g2mul_analyze(bytes_view, evmc_revision) noexcept

PrecompileAnalysis bls12_g2msm_analyze(bytes_view input, evmc_revision) noexcept
{
// assert(!input.empty());
// assert(input.size() % 288 == 0);
if (input.empty() || input.size() % 288 != 0)
return {GasCostMax, 0};

Expand Down