Skip to content

Commit

Permalink
precompiles: Investigate missing BLS test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Sep 23, 2024
1 parent 7961b60 commit 7d24f37
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
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

0 comments on commit 7d24f37

Please sign in to comment.