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

[5.0 -> main] Update to latest version of BLS12 submodule with clearer conversion parameters #2373

Merged
merged 4 commits into from
Apr 3, 2024
Merged
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
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
Loading