Skip to content

Commit

Permalink
Merge pull request #2373 from AntelopeIO/bls_update_60
Browse files Browse the repository at this point in the history
[5.0 -> main] Update to latest version of BLS12 submodule with clearer conversion parameters
  • Loading branch information
greg7mdp authored Apr 3, 2024
2 parents e29e3ea + 3753fc7 commit 5d56c4b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 41 deletions.
22 changes: 11 additions & 11 deletions benchmark/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ void benchmark_bls_g1_add() {
// prepare g1 operand in Jacobian LE format
g1 p = random_g1();
std::array<char, 96> op;
p.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)op.data(), 96), false);
p.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)op.data(), 96), from_mont::yes);

// prepare result operand
std::array<char, 96> result;
Expand All @@ -171,7 +171,7 @@ void benchmark_bls_g2_add() {
// prepare g2 operand in Jacobian LE format
g2 p = random_g2();
std::array<char, 192> op;
p.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)op.data(), 192), false);
p.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)op.data(), 192), from_mont::yes);

// prepare result operand
std::array<char, 192> result;
Expand All @@ -191,7 +191,7 @@ void benchmark_bls_g1_weighted_sum_impl(const std::string& test_name, uint32_t n
std::vector<char> g1_buf(96*num_points);
for (auto i=0u; i < num_points; ++i) {
g1 p = random_g1();
p.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)g1_buf.data() + i * 96, 96), false);
p.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)g1_buf.data() + i * 96, 96), from_mont::yes);
}
chain::span<const char> g1_points(g1_buf.data(), g1_buf.size());

Expand Down Expand Up @@ -236,7 +236,7 @@ void benchmark_bls_g2_weighted_sum_impl(const std::string& test_name, uint32_t n
std::vector<char> g2_buf(192*num_points);
for (auto i=0u; i < num_points; ++i) {
g2 p = random_g2();
p.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)g2_buf.data() + i * 192, 192), false);
p.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)g2_buf.data() + i * 192, 192), from_mont::yes);
}
eosio::chain::span<const char> g2_points(g2_buf.data(), g2_buf.size());

Expand Down Expand Up @@ -281,15 +281,15 @@ void benchmark_bls_pairing_impl(const std::string& test_name, uint32_t num_pairs
std::vector<char> g1_buf(96*num_pairs);
for (auto i=0u; i < num_pairs; ++i) {
g1 p = random_g1();
p.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)g1_buf.data() + i * 96, 96), false);
p.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)g1_buf.data() + i * 96, 96), from_mont::yes);
}
eosio::chain::span<const char> g1_points(g1_buf.data(), g1_buf.size());

// prepare g2 operand
std::vector<char> g2_buf(192*num_pairs);
for (auto i=0u; i < num_pairs; ++i) {
g2 p2 = random_g2();
p2.toAffineBytesLE(std::span<uint8_t, (192)>((uint8_t*)g2_buf.data() + i * 192, (192)), false);
p2.toAffineBytesLE(std::span<uint8_t, (192)>((uint8_t*)g2_buf.data() + i * 192, (192)), from_mont::yes);
}
eosio::chain::span<const char> g2_points(g2_buf.data(), g2_buf.size());

Expand Down Expand Up @@ -320,7 +320,7 @@ void benchmark_bls_g1_map() {
// prepare e operand. Must be fp LE.
std::array<char, 48> e;
fp a = random_fe();
a.toBytesLE(std::span<uint8_t, 48>((uint8_t*)e.data(), 48), false);
a.toBytesLE(std::span<uint8_t, 48>((uint8_t*)e.data(), 48), from_mont::yes);

// prepare result operand
std::array<char, 96> result;
Expand All @@ -338,7 +338,7 @@ void benchmark_bls_g1_map() {
void benchmark_bls_g2_map() {
std::array<char, 96> e;
fp2 a = random_fe2();
a.toBytesLE(std::span<uint8_t, 96>((uint8_t*)e.data(), 96), false);
a.toBytesLE(std::span<uint8_t, 96>((uint8_t*)e.data(), 96), from_mont::yes);

// prepare result operand
std::array<char, 192> result;
Expand Down Expand Up @@ -378,12 +378,12 @@ void benchmark_bls_fp_mul() {
// prepare op1
std::array<char, 48> op1;
fp a = random_fe();
a.toBytesLE(std::span<uint8_t, 48>((uint8_t*)op1.data(), 48), false);
a.toBytesLE(std::span<uint8_t, 48>((uint8_t*)op1.data(), 48), from_mont::yes);

// prepare op2
std::array<char, 48> op2;
fp b = random_fe();
b.toBytesLE(std::span<uint8_t, 48>((uint8_t*)op2.data(), 48), false);
b.toBytesLE(std::span<uint8_t, 48>((uint8_t*)op2.data(), 48), from_mont::yes);

// prepare result operand
std::array<char, 48> result;
Expand All @@ -401,7 +401,7 @@ void benchmark_bls_fp_exp() {
// prepare base
std::array<char, 48> base;
fp a = random_fe();
a.toBytesLE(std::span<uint8_t, 48>((uint8_t*)base.data(), 48), false);
a.toBytesLE(std::span<uint8_t, 48>((uint8_t*)base.data(), 48), from_mont::yes);

// prepare exp operand
std::array<char, 64> exp;
Expand Down
59 changes: 30 additions & 29 deletions libraries/chain/webassembly/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ namespace {
namespace {
using eosio::chain::span;
using eosio::chain::webassembly::return_code;
using bls12_381::from_mont;
}

namespace eosio { namespace chain { namespace webassembly {
namespace eosio::chain::webassembly {

void interface::assert_recover_key( legacy_ptr<const fc::sha256> digest,
legacy_span<const char> sig,
Expand Down Expand Up @@ -262,24 +263,24 @@ namespace eosio { namespace chain { namespace webassembly {
int32_t interface::bls_g1_add(span<const char> op1, span<const char> op2, span<char> result) const {
if(op1.size() != 96 || op2.size() != 96 || result.size() != 96)
return return_code::failure;
std::optional<bls12_381::g1> a = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)op1.data(), 96), true, false);
std::optional<bls12_381::g1> b = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)op2.data(), 96), true, false);
std::optional<bls12_381::g1> a = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)op1.data(), 96), {.check_valid = true, .to_mont = true});
std::optional<bls12_381::g1> b = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)op2.data(), 96), {.check_valid = true, .to_mont = true});
if(!a || !b)
return return_code::failure;
bls12_381::g1 c = a->add(*b);
c.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), false);
c.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), from_mont::yes);
return return_code::success;
}

int32_t interface::bls_g2_add(span<const char> op1, span<const char> op2, span<char> result) const {
if(op1.size() != 192 || op2.size() != 192 || result.size() != 192)
return return_code::failure;
std::optional<bls12_381::g2> a = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)op1.data(), 192), true, false);
std::optional<bls12_381::g2> b = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)op2.data(), 192), true, false);
std::optional<bls12_381::g2> a = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)op1.data(), 192), {.check_valid = true, .to_mont = true});
std::optional<bls12_381::g2> b = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)op2.data(), 192), {.check_valid = true, .to_mont = true});
if(!a || !b)
return return_code::failure;
bls12_381::g2 c = a->add(*b);
c.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), false);
c.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), from_mont::yes);
return return_code::success;
}

Expand All @@ -289,12 +290,12 @@ namespace eosio { namespace chain { namespace webassembly {

// Use much efficient scale for the special case of n == 1.
if (1 == n) {
std::optional<bls12_381::g1> a = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)points.data(), 96), true, false);
std::optional<bls12_381::g1> a = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)points.data(), 96), {.check_valid = true, .to_mont = true});
if(!a)
return return_code::failure;
std::array<uint64_t, 4> b = bls12_381::scalar::fromBytesLE<4>(std::span<uint8_t, 32>((uint8_t*)scalars.data(), 32));
bls12_381::g1 c = a->scale(b);
c.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), false);
c.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), from_mont::yes);
return return_code::success;
}

Expand All @@ -304,7 +305,7 @@ namespace eosio { namespace chain { namespace webassembly {
sv.reserve(n);
for(uint32_t i = 0; i < n; i++)
{
std::optional<bls12_381::g1> p = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)points.data() + i*96, 96), true, false);
std::optional<bls12_381::g1> p = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)points.data() + i*96, 96), {.check_valid = true, .to_mont = true});
if(!p.has_value())
return return_code::failure;
std::array<uint64_t, 4> s = bls12_381::scalar::fromBytesLE<4>(std::span<const uint8_t, 32>((const uint8_t*)scalars.data() + i*32, 32));
Expand All @@ -314,7 +315,7 @@ namespace eosio { namespace chain { namespace webassembly {
context.trx_context.checktime();
}
bls12_381::g1 r = bls12_381::g1::weightedSum(pv, sv, [this](){ context.trx_context.checktime();}); // accessing value is safe
r.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), false);
r.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), from_mont::yes);
return return_code::success;
}

Expand All @@ -324,12 +325,12 @@ namespace eosio { namespace chain { namespace webassembly {

// Use much efficient scale for the special case of n == 1.
if (1 == n) {
std::optional<bls12_381::g2> a = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)points.data(), 192), true, false);
std::optional<bls12_381::g2> a = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)points.data(), 192), {.check_valid = true, .to_mont = true});
if(!a)
return return_code::failure;
std::array<uint64_t, 4> b = bls12_381::scalar::fromBytesLE<4>(std::span<uint8_t, 32>((uint8_t*)scalars.data(), 32));
bls12_381::g2 c = a->scale(b);
c.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), false);
c.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), from_mont::yes);
return return_code::success;
}

Expand All @@ -339,7 +340,7 @@ namespace eosio { namespace chain { namespace webassembly {
sv.reserve(n);
for(uint32_t i = 0; i < n; i++)
{
std::optional<bls12_381::g2> p = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)points.data() + i*192, 192), true, false);
std::optional<bls12_381::g2> p = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)points.data() + i*192, 192), {.check_valid = true, .to_mont = true});
if(!p)
return return_code::failure;
std::array<uint64_t, 4> s = bls12_381::scalar::fromBytesLE<4>(std::span<const uint8_t, 32>((const uint8_t*)scalars.data() + i*32, 32));
Expand All @@ -349,7 +350,7 @@ namespace eosio { namespace chain { namespace webassembly {
context.trx_context.checktime();
}
bls12_381::g2 r = bls12_381::g2::weightedSum(pv, sv, [this](){ context.trx_context.checktime();}); // accessing value is safe
r.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), false);
r.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), from_mont::yes);
return return_code::success;
}

Expand All @@ -360,38 +361,38 @@ namespace eosio { namespace chain { namespace webassembly {
v.reserve(n);
for(uint32_t i = 0; i < n; i++)
{
std::optional<bls12_381::g1> p_g1 = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)g1_points.data() + i*96, 96), true, false);
std::optional<bls12_381::g2> p_g2 = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)g2_points.data() + i*192, 192), true, false);
std::optional<bls12_381::g1> p_g1 = bls12_381::g1::fromAffineBytesLE(std::span<const uint8_t, 96>((const uint8_t*)g1_points.data() + i*96, 96), {.check_valid = true, .to_mont = true});
std::optional<bls12_381::g2> p_g2 = bls12_381::g2::fromAffineBytesLE(std::span<const uint8_t, 192>((const uint8_t*)g2_points.data() + i*192, 192), {.check_valid = true, .to_mont = true});
if(!p_g1 || !p_g2)
return return_code::failure;
bls12_381::pairing::add_pair(v, *p_g1, *p_g2);
if(i%4 == 0)
context.trx_context.checktime();
}
bls12_381::fp12 r = bls12_381::pairing::calculate(v, [this](){ context.trx_context.checktime();});
r.toBytesLE(std::span<uint8_t, 576>((uint8_t*)result.data(), 576), false);
r.toBytesLE(std::span<uint8_t, 576>((uint8_t*)result.data(), 576), from_mont::yes);
return return_code::success;
}

int32_t interface::bls_g1_map(span<const char> e, span<char> result) const {
if(e.size() != 48 || result.size() != 96)
return return_code::failure;
std::optional<bls12_381::fp> a = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)e.data(), 48), true, false);
std::optional<bls12_381::fp> a = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)e.data(), 48), {.check_valid = true, .to_mont = true});
if(!a)
return return_code::failure;
bls12_381::g1 c = bls12_381::g1::mapToCurve(*a);
c.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), false);
c.toAffineBytesLE(std::span<uint8_t, 96>((uint8_t*)result.data(), 96), from_mont::yes);
return return_code::success;
}

int32_t interface::bls_g2_map(span<const char> e, span<char> result) const {
if(e.size() != 96 || result.size() != 192)
return return_code::failure;
std::optional<bls12_381::fp2> a = bls12_381::fp2::fromBytesLE(std::span<const uint8_t, 96>((const uint8_t*)e.data(), 96), true, false);
std::optional<bls12_381::fp2> a = bls12_381::fp2::fromBytesLE(std::span<const uint8_t, 96>((const uint8_t*)e.data(), 96), {.check_valid = true, .to_mont = true});
if(!a)
return return_code::failure;
bls12_381::g2 c = bls12_381::g2::mapToCurve(*a);
c.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), false);
c.toAffineBytesLE(std::span<uint8_t, 192>((uint8_t*)result.data(), 192), from_mont::yes);
return return_code::success;
}

Expand All @@ -401,33 +402,33 @@ namespace eosio { namespace chain { namespace webassembly {
return return_code::failure;
std::array<uint64_t, 8> k = bls12_381::scalar::fromBytesLE<8>(std::span<const uint8_t, 64>((const uint8_t*)s.data(), 64));
bls12_381::fp e = bls12_381::fp::modPrime<8>(k);
e.toBytesLE(std::span<uint8_t, 48>((uint8_t*)result.data(), 48), false);
e.toBytesLE(std::span<uint8_t, 48>((uint8_t*)result.data(), 48), from_mont::yes);
return return_code::success;
}

int32_t interface::bls_fp_mul(span<const char> op1, span<const char> op2, span<char> result) const {
if(op1.size() != 48 || op2.size() != 48 || result.size() != 48)
return return_code::failure;
std::optional<bls12_381::fp> a = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)op1.data(), 48), true, false);
std::optional<bls12_381::fp> b = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)op2.data(), 48), true, false);
std::optional<bls12_381::fp> a = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)op1.data(), 48), {.check_valid = true, .to_mont = true});
std::optional<bls12_381::fp> b = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)op2.data(), 48), {.check_valid = true, .to_mont = true});
if(!a || !b)
return return_code::failure;
bls12_381::fp c = a->multiply(*b);
c.toBytesLE(std::span<uint8_t, 48>((uint8_t*)result.data(), 48), false);
c.toBytesLE(std::span<uint8_t, 48>((uint8_t*)result.data(), 48), from_mont::yes);
return return_code::success;
}

int32_t interface::bls_fp_exp(span<const char> base, span<const char> exp, span<char> result) const {
// exp is scalar.
if(base.size() != 48 || exp.size() != 64 || result.size() != 48)
return return_code::failure;
std::optional<bls12_381::fp> a = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)base.data(), 48), true, false);
std::optional<bls12_381::fp> a = bls12_381::fp::fromBytesLE(std::span<const uint8_t, 48>((const uint8_t*)base.data(), 48), {.check_valid = true, .to_mont = true});
if(!a)
return return_code::failure;
std::array<uint64_t, 8> b = bls12_381::scalar::fromBytesLE<8>(std::span<const uint8_t, 64>((const uint8_t*)exp.data(), 64));
bls12_381::fp c = a->exp<8>(b);
c.toBytesLE(std::span<uint8_t, 48>((uint8_t*)result.data(), 48), false);
c.toBytesLE(std::span<uint8_t, 48>((uint8_t*)result.data(), 48), from_mont::yes);
return return_code::success;
}

}}} // ns eosio::chain::webassembly
} // ns eosio::chain::webassembly
2 changes: 1 addition & 1 deletion libraries/libfc/libraries/bls12-381

0 comments on commit 5d56c4b

Please sign in to comment.