Skip to content

Commit

Permalink
Merge branch 'hotstuff_integration' into add_finality_data_in_transit…
Browse files Browse the repository at this point in the history
…ion_block
  • Loading branch information
linh2931 authored Apr 4, 2024
2 parents 78c6de1 + f02fa48 commit a9987a2
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 178 deletions.
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
15 changes: 11 additions & 4 deletions benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ std::map<std::string, std::function<void()>> features {
{ "key", key_benchmarking },
{ "hash", hash_benchmarking },
{ "blake2", blake2_benchmarking },
{ "bls", bls_benchmarking }
{ "bls", bls_benchmarking },
{ "merkle", merkle_benchmarking }
};

// values to control cout format
Expand All @@ -34,6 +35,10 @@ void set_num_runs(uint32_t runs) {
num_runs = runs;
}

uint32_t get_num_runs() {
return num_runs;
}

void print_header() {
std::cout << std::left << std::setw(name_width) << "function"
<< std::setw(runs_width) << "runs"
Expand Down Expand Up @@ -63,12 +68,14 @@ bytes to_bytes(const std::string& source) {
return output;
};

void benchmarking(const std::string& name, const std::function<void()>& func) {
void benchmarking(const std::string& name, const std::function<void()>& func,
std::optional<size_t> opt_num_runs /* = {} */) {
uint64_t total{0};
uint64_t min{std::numeric_limits<uint64_t>::max()};
uint64_t max{0};
uint32_t runs = opt_num_runs ? *opt_num_runs : num_runs;

for (auto i = 0U; i < num_runs; ++i) {
for (auto i = 0U; i < runs; ++i) {
auto start_time = std::chrono::high_resolution_clock::now();
func();
auto end_time = std::chrono::high_resolution_clock::now();
Expand All @@ -79,7 +86,7 @@ void benchmarking(const std::string& name, const std::function<void()>& func) {
max = std::max(max, duration);
}

print_results(name, num_runs, total, min, max);
print_results(name, runs, total, min, max);
}

} // benchmark
5 changes: 4 additions & 1 deletion benchmark/benchmark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
#include <map>
#include <vector>
#include <limits>
#include <optional>

#include <fc/crypto/hex.hpp>

namespace eosio::benchmark {
using bytes = std::vector<char>;

void set_num_runs(uint32_t runs);
uint32_t get_num_runs();
std::map<std::string, std::function<void()>> get_features();
void print_header();
bytes to_bytes(const std::string& source);
Expand All @@ -21,7 +23,8 @@ void key_benchmarking();
void hash_benchmarking();
void blake2_benchmarking();
void bls_benchmarking();
void merkle_benchmarking();

void benchmarking(const std::string& name, const std::function<void()>& func);
void benchmarking(const std::string& name, const std::function<void()>& func, std::optional<size_t> num_runs = {});

} // benchmark
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
69 changes: 69 additions & 0 deletions benchmark/merkle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <benchmark.hpp>
#include <eosio/chain/incremental_merkle.hpp>
#include <eosio/chain/incremental_merkle_legacy.hpp>
#include <random>

namespace eosio::benchmark {

using namespace eosio::chain;

std::vector<digest_type> create_test_digests(size_t n) {
std::vector<digest_type> v;
v.reserve(n);
for (size_t i=0; i<n; ++i)
v.push_back(fc::sha256::hash(std::string{"Node"} + std::to_string(i)));
return v;
}

void benchmark_calc_merkle(uint32_t size_boost) {
using namespace std::string_literals;
const size_t num_digests = size_boost * 1000ull; // don't use exact powers of 2 as it is a special case

const std::vector<digest_type> digests = create_test_digests(num_digests);
const deque<digest_type> deq { digests.begin(), digests.end() };

auto num_str = std::to_string(size_boost);
while(num_str.size() < 4)
num_str.insert(0, 1, ' ');
auto msg_header = "Calc, "s + num_str + ",000 digests, "s;
uint32_t num_runs = std::min(get_num_runs(), std::max(1u, get_num_runs() / size_boost));
benchmarking(msg_header + "legacy: ", [&]() { calculate_merkle_legacy(deq); }, num_runs);
benchmarking(msg_header + "savanna:", [&]() { calculate_merkle(digests.begin(), digests.end()); }, num_runs);
}

void benchmark_incr_merkle(uint32_t size_boost) {
using namespace std::string_literals;
const size_t num_digests = size_boost * 1000ull; // don't use exact powers of 2 as it is a special case

const std::vector<digest_type> digests = create_test_digests(num_digests);

auto num_str = std::to_string(size_boost);
while(num_str.size() < 4)
num_str.insert(0, 1, ' ');
auto msg_header = "Incr, "s + num_str + ",000 digests, "s;
uint32_t num_runs = std::min(get_num_runs(), std::max(1u, get_num_runs() / size_boost));

auto incr = [&](const auto& incr_tree) {
auto work_tree = incr_tree;
for (const auto& d : digests)
work_tree.append(d);
return work_tree.get_root();
};

benchmarking(msg_header + "legacy: ", [&]() { incr(incremental_merkle_tree_legacy()); }, num_runs);
benchmarking(msg_header + "savanna:", [&]() { incr(incremental_merkle_tree()); }, num_runs);
}

// register benchmarking functions
void merkle_benchmarking() {
benchmark_calc_merkle(1000); // calculate_merkle of very large sequence (1,000,000 digests)
benchmark_calc_merkle(50); // calculate_merkle of large sequence (50,000 digests)
benchmark_calc_merkle(1); // calculate_merkle of small sequence (1000 digests)
std::cout << "\n";

benchmark_incr_merkle(100); // incremental_merkle of very large sequence (100,000 digests)
benchmark_incr_merkle(25); // incremental_merkle of large sequence (25,000 digests)
benchmark_incr_merkle(1); // incremental_merkle of small sequence (1000 digests)
}

}
Loading

0 comments on commit a9987a2

Please sign in to comment.