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

IF: Catchup from main, includes bls12 submodule API change. #2374

Merged
merged 15 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
37 changes: 37 additions & 0 deletions .cicd/platforms/asan.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# syntax=docker/dockerfile:1
FROM ubuntu:jammy
ENV TZ="America/New_York"
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get upgrade -y && \
apt-get install -y build-essential \
cmake \
git \
jq \
libcurl4-openssl-dev \
libgmp-dev \
llvm-11-dev \
lsb-release \
ninja-build \
python3-numpy \
software-properties-common \
file \
wget \
zlib1g-dev \
zstd

RUN yes | bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" llvm.sh 18

#make sure no confusion on what llvm library leap's cmake should pick up on
RUN rm -rf /usr/lib/llvm-18/lib/cmake

ENV LEAP_PLATFORM_HAS_EXTRAS_CMAKE=1
COPY <<-EOF /extras.cmake
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)

set(CMAKE_C_COMPILER "clang-18" CACHE STRING "")
set(CMAKE_CXX_COMPILER "clang++-18" CACHE STRING "")
set(CMAKE_C_FLAGS "-fsanitize=address -fno-omit-frame-pointer" CACHE STRING "")
set(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer" CACHE STRING "")
EOF

ENV ASAN_OPTIONS=detect_leaks=0
1 change: 1 addition & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ jobs:
- cfg: {name: 'ubuntu22', base: 'ubuntu22', builddir: 'ubuntu22'}
- cfg: {name: 'asserton', base: 'asserton', builddir: 'asserton'}
- cfg: {name: 'ubsan', base: 'ubsan', builddir: 'ubsan'}
- cfg: {name: 'asan', base: 'asan', builddir: 'asan'}
- cfg: {name: 'ubuntu20repro', base: 'ubuntu20', builddir: 'reproducible'}
- cfg: {name: 'ubuntu22repro', base: 'ubuntu22', builddir: 'reproducible'}
runs-on: ["self-hosted", "enf-x86-hightier"]
Expand Down
22 changes: 11 additions & 11 deletions benchmark/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,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 @@ -172,7 +172,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 @@ -192,7 +192,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 @@ -237,7 +237,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 @@ -282,15 +282,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 @@ -321,7 +321,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 @@ -339,7 +339,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 @@ -379,12 +379,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 @@ -402,7 +402,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/chainbase
Loading
Loading