Add BLS and DKG benchmarks

This commit is contained in:
Alexander Block 2018-05-24 13:56:49 +02:00
parent 3ee27c1681
commit 78675d9bb0
4 changed files with 554 additions and 0 deletions

View File

@ -15,6 +15,8 @@ bench_bench_dash_SOURCES = \
bench/bench_dash.cpp \
bench/bench.cpp \
bench/bench.h \
bench/bls.cpp \
bench/bls_dkg.cpp \
bench/checkblock.cpp \
bench/checkqueue.cpp \
bench/Examples.cpp \

View File

@ -8,14 +8,24 @@
#include "validation.h"
#include "util.h"
#include "crypto/bls.h"
void CleanupBLSTests();
void CleanupBLSDkgTests();
int
main(int argc, char** argv)
{
ECC_Start();
BLSInit();
SetupEnvironment();
fPrintToDebugLog = false; // don't want to write to debug.log file
benchmark::BenchRunner::RunAll();
// need to be called before global destructors kick in (PoolAllocator is needed due to many BLSSecretKeys)
CleanupBLSDkgTests();
CleanupBLSTests();
ECC_Stop();
}

361
src/bench/bls.cpp Normal file
View File

@ -0,0 +1,361 @@
// Copyright (c) 2018 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "bench.h"
#include "random.h"
#include "crypto/bls_worker.h"
#include "utiltime.h"
#include <iostream>
CBLSWorker blsWorker;
void CleanupBLSTests()
{
blsWorker.Stop();
}
static void BuildTestVectors(size_t count, size_t invalidCount,
BLSPublicKeyVector& pubKeys, BLSSecretKeyVector& secKeys, BLSSignatureVector& sigs,
std::vector<uint256>& msgHashes,
std::vector<bool>& invalid)
{
secKeys.resize(count);
pubKeys.resize(count);
sigs.resize(count);
msgHashes.resize(count);
invalid.resize(count);
for (size_t i = 0; i < invalidCount; i++) {
invalid[i] = true;
}
std::random_shuffle(invalid.begin(), invalid.end());
for (size_t i = 0; i < count; i++) {
secKeys[i].MakeNewKey();
pubKeys[i] = secKeys[i].GetPublicKey();
msgHashes[i] = GetRandHash();
sigs[i] = secKeys[i].Sign(msgHashes[i]);
if (invalid[i]) {
CBLSSecretKey s;
s.MakeNewKey();
sigs[i] = s.Sign(msgHashes[i]);
}
}
}
static void BLSPubKeyAggregate_Normal(benchmark::State& state)
{
CBLSSecretKey secKey1, secKey2;
secKey1.MakeNewKey();
secKey2.MakeNewKey();
CBLSPublicKey pubKey1 = secKey1.GetPublicKey();
CBLSPublicKey pubKey2 = secKey2.GetPublicKey();
// Benchmark.
while (state.KeepRunning()) {
CBLSPublicKey k(pubKey1);
k.AggregateInsecure(pubKey2);
}
}
static void BLSSecKeyAggregate_Normal(benchmark::State& state)
{
CBLSSecretKey secKey1, secKey2;
secKey1.MakeNewKey();
secKey2.MakeNewKey();
CBLSPublicKey pubKey1 = secKey1.GetPublicKey();
CBLSPublicKey pubKey2 = secKey2.GetPublicKey();
// Benchmark.
while (state.KeepRunning()) {
CBLSSecretKey k(secKey1);
k.AggregateInsecure(secKey2);
}
}
static void BLSSign_Normal(benchmark::State& state)
{
CBLSSecretKey secKey;
secKey.MakeNewKey();
CBLSPublicKey pubKey = secKey.GetPublicKey();
// Benchmark.
while (state.KeepRunning()) {
uint256 hash = GetRandHash();
secKey.Sign(hash);
}
}
static void BLSVerify_Normal(benchmark::State& state)
{
BLSPublicKeyVector pubKeys;
BLSSecretKeyVector secKeys;
BLSSignatureVector sigs;
std::vector<uint256> msgHashes;
std::vector<bool> invalid;
BuildTestVectors(1000, 10, pubKeys, secKeys, sigs, msgHashes, invalid);
// Benchmark.
size_t i = 0;
while (state.KeepRunning()) {
bool valid = sigs[i].VerifyInsecure(pubKeys[i], msgHashes[i]);
if (valid && invalid[i]) {
std::cout << "expected invalid but it is valid" << std::endl;
assert(false);
} else if (!valid && !invalid[i]) {
std::cout << "expected valid but it is invalid" << std::endl;
assert(false);
}
i = (i + 1) % pubKeys.size();
}
}
static void BLSVerify_LargeBlock(size_t txCount, benchmark::State& state)
{
BLSPublicKeyVector pubKeys;
BLSSecretKeyVector secKeys;
BLSSignatureVector sigs;
std::vector<uint256> msgHashes;
std::vector<bool> invalid;
BuildTestVectors(txCount, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
// Benchmark.
while (state.KeepRunning()) {
for (size_t i = 0; i < pubKeys.size(); i++) {
sigs[i].VerifyInsecure(pubKeys[i], msgHashes[i]);
}
}
}
static void BLSVerify_LargeBlock1000(benchmark::State& state)
{
BLSVerify_LargeBlock(1000, state);
}
static void BLSVerify_LargeBlock10000(benchmark::State& state)
{
BLSVerify_LargeBlock(10000, state);
}
static void BLSVerify_LargeBlockSelfAggregated(size_t txCount, benchmark::State& state)
{
BLSPublicKeyVector pubKeys;
BLSSecretKeyVector secKeys;
BLSSignatureVector sigs;
std::vector<uint256> msgHashes;
std::vector<bool> invalid;
BuildTestVectors(txCount, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
// Benchmark.
while (state.KeepRunning()) {
CBLSSignature aggSig = CBLSSignature::AggregateInsecure(sigs);
aggSig.VerifyInsecureAggregated(pubKeys, msgHashes);
}
}
static void BLSVerify_LargeBlockSelfAggregated1000(benchmark::State& state)
{
BLSVerify_LargeBlockSelfAggregated(1000, state);
}
static void BLSVerify_LargeBlockSelfAggregated10000(benchmark::State& state)
{
BLSVerify_LargeBlockSelfAggregated(10000, state);
}
static void BLSVerify_LargeAggregatedBlock(size_t txCount, benchmark::State& state)
{
BLSPublicKeyVector pubKeys;
BLSSecretKeyVector secKeys;
BLSSignatureVector sigs;
std::vector<uint256> msgHashes;
std::vector<bool> invalid;
BuildTestVectors(txCount, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
CBLSSignature aggSig = CBLSSignature::AggregateInsecure(sigs);
// Benchmark.
size_t i = 0;
while (state.KeepRunning()) {
aggSig.VerifyInsecureAggregated(pubKeys, msgHashes);
i = (i + 1) % pubKeys.size();
}
}
static void BLSVerify_LargeAggregatedBlock1000(benchmark::State& state)
{
BLSVerify_LargeAggregatedBlock(1000, state);
}
static void BLSVerify_LargeAggregatedBlock10000(benchmark::State& state)
{
BLSVerify_LargeAggregatedBlock(10000, state);
}
static void BLSVerify_LargeAggregatedBlock1000PreVerified(benchmark::State& state)
{
BLSPublicKeyVector pubKeys;
BLSSecretKeyVector secKeys;
BLSSignatureVector sigs;
std::vector<uint256> msgHashes;
std::vector<bool> invalid;
BuildTestVectors(1000, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
CBLSSignature aggSig = CBLSSignature::AggregateInsecure(sigs);
std::set<size_t> prevalidated;
while (prevalidated.size() < 900) {
int idx = GetRandInt((int)pubKeys.size());
if (prevalidated.count((size_t)idx)) {
continue;
}
prevalidated.emplace((size_t)idx);
}
// Benchmark.
size_t i = 0;
while (state.KeepRunning()) {
BLSPublicKeyVector nonvalidatedPubKeys;
std::vector<uint256> nonvalidatedHashes;
nonvalidatedPubKeys.reserve(pubKeys.size());
nonvalidatedHashes.reserve(msgHashes.size());
for (size_t i = 0; i < sigs.size(); i++) {
if (prevalidated.count(i)) {
continue;
}
nonvalidatedPubKeys.emplace_back(pubKeys[i]);
nonvalidatedHashes.emplace_back(msgHashes[i]);
}
CBLSSignature aggSigCopy = aggSig;
for (auto idx : prevalidated) {
aggSigCopy.SubInsecure(sigs[idx]);
}
bool valid = aggSigCopy.VerifyInsecureAggregated(nonvalidatedPubKeys, nonvalidatedHashes);
assert(valid);
i = (i + 1) % pubKeys.size();
}
}
static void BLSVerify_Batched(benchmark::State& state)
{
BLSPublicKeyVector pubKeys;
BLSSecretKeyVector secKeys;
BLSSignatureVector sigs;
std::vector<uint256> msgHashes;
std::vector<bool> invalid;
BuildTestVectors(1000, 10, pubKeys, secKeys, sigs, msgHashes, invalid);
// Benchmark.
size_t i = 0;
size_t j = 0;
size_t batchSize = 16;
while (state.KeepRunning()) {
j++;
if ((j % batchSize) != 0) {
continue;
}
BLSPublicKeyVector testPubKeys;
BLSSignatureVector testSigs;
std::vector<uint256> testMsgHashes;
testPubKeys.reserve(batchSize);
testSigs.reserve(batchSize);
testMsgHashes.reserve(batchSize);
size_t startI = i;
for (size_t k = 0; k < batchSize; k++) {
testPubKeys.emplace_back(pubKeys[i]);
testSigs.emplace_back(sigs[i]);
testMsgHashes.emplace_back(msgHashes[i]);
i = (i + 1) % pubKeys.size();
}
CBLSSignature batchSig = CBLSSignature::AggregateInsecure(testSigs);
bool batchValid = batchSig.VerifyInsecureAggregated(testPubKeys, testMsgHashes);
std::vector<bool> valid;
if (batchValid) {
valid.assign(batchSize, true);
} else {
for (size_t k = 0; k < batchSize; k++) {
bool valid1 = testSigs[k].VerifyInsecure(testPubKeys[k], testMsgHashes[k]);
valid.emplace_back(valid1);
}
}
for (size_t k = 0; k < batchSize; k++) {
if (valid[k] && invalid[(startI + k) % pubKeys.size()]) {
std::cout << "expected invalid but it is valid" << std::endl;
assert(false);
} else if (!valid[k] && !invalid[(startI + k) % pubKeys.size()]) {
std::cout << "expected valid but it is invalid" << std::endl;
assert(false);
}
}
}
}
static void BLSVerify_BatchedParallel(benchmark::State& state)
{
BLSPublicKeyVector pubKeys;
BLSSecretKeyVector secKeys;
BLSSignatureVector sigs;
std::vector<uint256> msgHashes;
std::vector<bool> invalid;
BuildTestVectors(1000, 10, pubKeys, secKeys, sigs, msgHashes, invalid);
std::list<std::pair<size_t, std::future<bool>>> futures;
volatile bool cancel = false;
auto cancelCond = [&]() {
return cancel;
};
// Benchmark.
size_t i = 0;
while (state.KeepRunning()) {
if (futures.size() < 100) {
while (futures.size() < 10000) {
auto f = blsWorker.AsyncVerifySig(sigs[i], pubKeys[i], msgHashes[i], cancelCond);
futures.emplace_back(std::make_pair(i, std::move(f)));
i = (i + 1) % pubKeys.size();
}
}
auto fp = std::move(futures.front());
futures.pop_front();
size_t j = fp.first;
bool valid = fp.second.get();
if (valid && invalid[j]) {
std::cout << "expected invalid but it is valid" << std::endl;
assert(false);
} else if (!valid && !invalid[j]) {
std::cout << "expected valid but it is invalid" << std::endl;
assert(false);
}
}
cancel = true;
while (blsWorker.IsAsyncVerifyInProgress()) {
MilliSleep(100);
}
}
BENCHMARK(BLSPubKeyAggregate_Normal)
BENCHMARK(BLSSecKeyAggregate_Normal)
BENCHMARK(BLSSign_Normal)
BENCHMARK(BLSVerify_Normal)
BENCHMARK(BLSVerify_LargeBlock1000)
BENCHMARK(BLSVerify_LargeBlockSelfAggregated1000)
BENCHMARK(BLSVerify_LargeBlockSelfAggregated10000)
BENCHMARK(BLSVerify_LargeAggregatedBlock1000)
BENCHMARK(BLSVerify_LargeAggregatedBlock10000)
BENCHMARK(BLSVerify_LargeAggregatedBlock1000PreVerified)
BENCHMARK(BLSVerify_Batched)
BENCHMARK(BLSVerify_BatchedParallel)

181
src/bench/bls_dkg.cpp Normal file
View File

@ -0,0 +1,181 @@
// Copyright (c) 2018 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "bench.h"
#include "random.h"
#include "crypto/bls_worker.h"
extern CBLSWorker blsWorker;
struct Member {
CBLSId id;
BLSVerificationVectorPtr vvec;
BLSSecretKeyVector skShares;
};
struct DKG
{
std::vector<Member> members;
std::vector<CBLSId> ids;
std::vector<BLSVerificationVectorPtr> receivedVvecs;
BLSSecretKeyVector receivedSkShares;
BLSVerificationVectorPtr quorumVvec;
DKG(int quorumSize)
{
members.resize(quorumSize);
ids.resize(quorumSize);
for (int i = 0; i < quorumSize; i++) {
members[i].id.SetInt(i + 1);
ids[i] = members[i].id;
}
for (int i = 0; i < quorumSize; i++) {
blsWorker.GenerateContributions(quorumSize / 2 + 1, ids, members[i].vvec, members[i].skShares);
}
//printf("initialized quorum %d\n", quorumSize);
}
void ReceiveVvecs()
{
receivedVvecs.clear();
for (size_t i = 0; i < members.size(); i++) {
receivedVvecs.emplace_back(members[i].vvec);
}
quorumVvec = blsWorker.BuildQuorumVerificationVector(receivedVvecs);
}
void ReceiveShares(size_t whoAmI)
{
receivedSkShares.clear();
for (size_t i = 0; i < members.size(); i++) {
receivedSkShares.emplace_back(members[i].skShares[whoAmI]);
}
}
void BuildQuorumVerificationVector(bool parallel)
{
quorumVvec = blsWorker.BuildQuorumVerificationVector(receivedVvecs, 0, 0, parallel);
//assert(worker.VerifyVerificationVector(*members[memberIdx].quorumVvec));
}
void Bench_BuildQuorumVerificationVectors(benchmark::State& state, bool parallel)
{
ReceiveVvecs();
while (state.KeepRunning()) {
BuildQuorumVerificationVector(parallel);
}
}
void VerifyContributionShares(size_t whoAmI, const std::set<size_t>& invalidIndexes, bool parallel, bool aggregated)
{
auto result = blsWorker.VerifyContributionShares(members[whoAmI].id, receivedVvecs, receivedSkShares, parallel, aggregated);
for (size_t i = 0; i < receivedVvecs.size(); i++) {
if (invalidIndexes.count(i)) {
assert(!result[i]);
} else {
assert(result[i]);
}
}
}
void Bench_VerifyContributionShares(benchmark::State& state, int invalidCount, bool parallel, bool aggregated)
{
ReceiveVvecs();
// Benchmark.
size_t memberIdx = 0;
while (state.KeepRunning()) {
auto& m = members[memberIdx];
ReceiveShares(memberIdx);
std::set<size_t> invalidIndexes;
for (int i = 0; i < invalidCount; i++) {
int shareIdx = GetRandInt(receivedSkShares.size());
receivedSkShares[shareIdx].MakeNewKey();
invalidIndexes.emplace(shareIdx);
}
VerifyContributionShares(memberIdx, invalidIndexes, parallel, aggregated);
memberIdx = (memberIdx + 1) % members.size();
}
}
};
std::shared_ptr<DKG> dkg10;
std::shared_ptr<DKG> dkg100;
std::shared_ptr<DKG> dkg400;
void InitIfNeeded()
{
if (dkg10 == nullptr) {
dkg10 = std::make_shared<DKG>(10);
}
if (dkg100 == nullptr) {
dkg100 = std::make_shared<DKG>(100);
}
if (dkg400 == nullptr) {
dkg400 = std::make_shared<DKG>(400);
}
}
void CleanupBLSDkgTests()
{
dkg10.reset();
dkg100.reset();
dkg400.reset();
}
#define BENCH_BuildQuorumVerificationVectors(name, quorumSize, parallel) \
static void BLSDKG_BuildQuorumVerificationVectors_##name##_##quorumSize(benchmark::State& state) \
{ \
InitIfNeeded(); \
dkg##quorumSize->Bench_BuildQuorumVerificationVectors(state, parallel); \
} \
BENCHMARK(BLSDKG_BuildQuorumVerificationVectors_##name##_##quorumSize)
BENCH_BuildQuorumVerificationVectors(simple, 10, false)
BENCH_BuildQuorumVerificationVectors(simple, 100, false)
BENCH_BuildQuorumVerificationVectors(simple, 400, false)
BENCH_BuildQuorumVerificationVectors(parallel, 10, true)
BENCH_BuildQuorumVerificationVectors(parallel, 100, true)
BENCH_BuildQuorumVerificationVectors(parallel, 400, true)
///////////////////////////////
#define BENCH_VerifyContributionShares(name, quorumSize, invalidCount, parallel, aggregated) \
static void BLSDKG_VerifyContributionShares_##name##_##quorumSize(benchmark::State& state) \
{ \
InitIfNeeded(); \
dkg##quorumSize->Bench_VerifyContributionShares(state, invalidCount, parallel, aggregated); \
} \
BENCHMARK(BLSDKG_VerifyContributionShares_##name##_##quorumSize)
BENCH_VerifyContributionShares(simple, 10, 5, false, false)
BENCH_VerifyContributionShares(simple, 100, 5, false, false)
BENCH_VerifyContributionShares(simple, 400, 5, false, false)
BENCH_VerifyContributionShares(aggregated, 10, 5, false, true)
BENCH_VerifyContributionShares(aggregated, 100, 5, false, true)
BENCH_VerifyContributionShares(aggregated, 400, 5, false, true)
BENCH_VerifyContributionShares(parallel, 10, 5, true, false)
BENCH_VerifyContributionShares(parallel, 100, 5, true, false)
BENCH_VerifyContributionShares(parallel, 400, 5, true, false)
BENCH_VerifyContributionShares(parallel_aggregated, 10, 5, true, true)
BENCH_VerifyContributionShares(parallel_aggregated, 100, 5, true, true)
BENCH_VerifyContributionShares(parallel_aggregated, 400, 5, true, true)