Skip to content
5 changes: 2 additions & 3 deletions src/bls/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
#include <bls/bls.h>

#include <random.h>
#include <tinyformat.h>

#ifndef BUILD_BITCOIN_INTERNAL
#include <support/allocators/mt_pooled_secure.h>
#endif

#include <assert.h>
#include <string.h>
#include <cassert>
#include <cstring>

static std::unique_ptr<bls::CoreMPL> pSchemeLegacy(new bls::LegacySchemeMPL);
static std::unique_ptr<bls::CoreMPL> pScheme(new bls::BasicSchemeMPL);
Expand Down
22 changes: 11 additions & 11 deletions src/bls/bls_worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,13 +404,13 @@ struct ContributionVerifier {
BLSVerificationVectorPtr vvec;
CBLSSecretKey skShare;

// starts with 0 and is incremented if either vvec or skShare aggregation finishs. If it reaches 2, we know
// starts with 0 and is incremented if either vvec or skShare aggregation finishes. If it reaches 2, we know
// that aggregation for this batch is fully done. We can then start verification.
std::unique_ptr<std::atomic<int> > aggDone;

// we can't directly update a vector<bool> in parallel
// as vector<bool> is not thread safe (uses bitsets internally)
// so we must use vector<char> temporarely and concatenate/convert
// so we must use vector<char> temporarily and concatenate/convert
// each batch result into a final vector<bool>
std::vector<char> verifyResults;
};
Expand Down Expand Up @@ -575,7 +575,7 @@ struct ContributionVerifier {
}
}

bool Verify(const BLSVerificationVectorPtr& vvec, const CBLSSecretKey& skShare)
bool Verify(const BLSVerificationVectorPtr& vvec, const CBLSSecretKey& skShare) const
{
CBLSPublicKey pk1;
if (!pk1.PublicKeyShare(*vvec, forId)) {
Expand All @@ -590,7 +590,7 @@ struct ContributionVerifier {
void PushOrDoWork(Callable&& f)
{
if (parallel) {
workerPool.push(std::move(f));
workerPool.push(std::forward<Callable>(f));
} else {
f(0);
}
Expand Down Expand Up @@ -656,7 +656,7 @@ void CBLSWorker::AsyncAggregateSecretKeys(const BLSSecretKeyVector& secKeys,
size_t start, size_t count, bool parallel,
std::function<void(const CBLSSecretKey&)> doneCallback)
{
AsyncAggregateHelper(workerPool, secKeys, start, count, parallel, doneCallback);
AsyncAggregateHelper(workerPool, secKeys, start, count, parallel, std::move(doneCallback));
}

std::future<CBLSSecretKey> CBLSWorker::AsyncAggregateSecretKeys(const BLSSecretKeyVector& secKeys,
Expand All @@ -677,7 +677,7 @@ void CBLSWorker::AsyncAggregatePublicKeys(const BLSPublicKeyVector& pubKeys,
size_t start, size_t count, bool parallel,
std::function<void(const CBLSPublicKey&)> doneCallback)
{
AsyncAggregateHelper(workerPool, pubKeys, start, count, parallel, doneCallback);
AsyncAggregateHelper(workerPool, pubKeys, start, count, parallel, std::move(doneCallback));
}

std::future<CBLSPublicKey> CBLSWorker::AsyncAggregatePublicKeys(const BLSPublicKeyVector& pubKeys,
Expand All @@ -698,7 +698,7 @@ void CBLSWorker::AsyncAggregateSigs(const BLSSignatureVector& sigs,
size_t start, size_t count, bool parallel,
std::function<void(const CBLSSignature&)> doneCallback)
{
AsyncAggregateHelper(workerPool, sigs, start, count, parallel, doneCallback);
AsyncAggregateHelper(workerPool, sigs, start, count, parallel, std::move(doneCallback));
}

std::future<CBLSSignature> CBLSWorker::AsyncAggregateSigs(const BLSSignatureVector& sigs,
Expand Down Expand Up @@ -830,7 +830,7 @@ bool CBLSWorker::VerifySignatureVector(const BLSSignatureVector& sigs, size_t st
return VerifyVectorHelper(sigs, start, count);
}

void CBLSWorker::AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash, CBLSWorker::SignDoneCallback doneCallback)
void CBLSWorker::AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash, const CBLSWorker::SignDoneCallback& doneCallback)
{
workerPool.push([secKey, msgHash, doneCallback](int threadId) {
doneCallback(secKey.Sign(msgHash));
Expand All @@ -840,7 +840,7 @@ void CBLSWorker::AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash,
std::future<CBLSSignature> CBLSWorker::AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash)
{
auto p = BuildFutureDoneCallback<CBLSSignature>();
AsyncSign(secKey, msgHash, std::move(p.first));
AsyncSign(secKey, msgHash, p.first);
return std::move(p.second);
}

Expand Down Expand Up @@ -877,7 +877,7 @@ void CBLSWorker::AsyncVerifySig(const CBLSSignature& sig, const CBLSPublicKey& p
std::future<bool> CBLSWorker::AsyncVerifySig(const CBLSSignature& sig, const CBLSPublicKey& pubKey, const uint256& msgHash, CancelCond cancelCond)
{
auto p = BuildFutureDoneCallback2<bool>();
AsyncVerifySig(sig, pubKey, msgHash, std::move(p.first), cancelCond);
AsyncVerifySig(sig, pubKey, msgHash, std::move(p.first), std::move(cancelCond));
return std::move(p.second);
}

Expand All @@ -890,7 +890,7 @@ bool CBLSWorker::IsAsyncVerifyInProgress()
// sigVerifyMutex must be held while calling
void CBLSWorker::PushSigVerifyBatch()
{
auto f = [this](int threadId, std::shared_ptr<std::vector<SigVerifyJob> > _jobs) {
auto f = [this](int threadId, const std::shared_ptr<std::vector<SigVerifyJob> >& _jobs) {
auto& jobs = *_jobs;
if (jobs.size() == 1) {
auto& job = jobs[0];
Expand Down
24 changes: 11 additions & 13 deletions src/bls/bls_worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
#include <future>
#include <mutex>

#include <boost/lockfree/queue.hpp>

// Low level BLS/DKG stuff. All very compute intensive and optimized for parallelization
// The worker tries to parallelize as much as possible and utilizes a few properties of BLS aggregation to speed up things
// For example, public key vectors can be aggregated in parallel if they are split into batches and the batched aggregations are
Expand Down Expand Up @@ -69,7 +67,7 @@ class CBLSWorker
// The result is in the following form:
// [ a1+a2+a3+a4, b1+b2+b3+b4, c1+c2+c3+c4, d1+d2+d3+d4]
// Multiple things can be parallelized here. For example, all 4 entries in the result vector can be calculated in parallel
// Also, each individual vector can be split into multiple batches and aggregating the batches can also be paralellized.
// Also, each individual vector can be split into multiple batches and aggregating the batches can also be parallelized.
void AsyncBuildQuorumVerificationVector(const std::vector<BLSVerificationVectorPtr>& vvecs,
size_t start, size_t count, bool parallel,
std::function<void(const BLSVerificationVectorPtr&)> doneCallback);
Expand All @@ -82,7 +80,7 @@ class CBLSWorker
// Inputs are in the following form:
// [a, b, c, d],
// The result is simply a+b+c+d
// Aggregation is paralellized by splitting up the input vector into multiple batches and then aggregating the individual batch results
// Aggregation is parallelized by splitting up the input vector into multiple batches and then aggregating the individual batch results
void AsyncAggregateSecretKeys(const BLSSecretKeyVector& secKeys,
size_t start, size_t count, bool parallel,
std::function<void(const CBLSSecretKey&)> doneCallback);
Expand All @@ -106,7 +104,7 @@ class CBLSWorker


// Calculate public key share from public key vector and id. Not parallelized
CBLSPublicKey BuildPubKeyShare(const BLSVerificationVectorPtr& vvec, const CBLSId& id);
static CBLSPublicKey BuildPubKeyShare(const BLSVerificationVectorPtr& vvec, const CBLSId& id);

// The following functions verify multiple verification vectors and contributions for the same id
// This is parallelized by performing batched verification. The verification vectors and the contributions of
Expand All @@ -123,17 +121,17 @@ class CBLSWorker

std::future<bool> AsyncVerifyContributionShare(const CBLSId& forId, const BLSVerificationVectorPtr& vvec, const CBLSSecretKey& skContribution);

// Non paralellized verification of a single contribution
bool VerifyContributionShare(const CBLSId& forId, const BLSVerificationVectorPtr& vvec, const CBLSSecretKey& skContribution);
// Non parallelized verification of a single contribution
static bool VerifyContributionShare(const CBLSId& forId, const BLSVerificationVectorPtr& vvec, const CBLSSecretKey& skContribution);

// Simple verification of vectors. Checks x.IsValid() for every entry and checks for duplicate entries
bool VerifyVerificationVector(const BLSVerificationVector& vvec, size_t start = 0, size_t count = 0);
bool VerifyVerificationVectors(const std::vector<BLSVerificationVectorPtr>& vvecs, size_t start = 0, size_t count = 0);
bool VerifySecretKeyVector(const BLSSecretKeyVector& secKeys, size_t start = 0, size_t count = 0);
bool VerifySignatureVector(const BLSSignatureVector& sigs, size_t start = 0, size_t count = 0);
static bool VerifyVerificationVector(const BLSVerificationVector& vvec, size_t start = 0, size_t count = 0);
static bool VerifyVerificationVectors(const std::vector<BLSVerificationVectorPtr>& vvecs, size_t start = 0, size_t count = 0);
static bool VerifySecretKeyVector(const BLSSecretKeyVector& secKeys, size_t start = 0, size_t count = 0);
static bool VerifySignatureVector(const BLSSignatureVector& sigs, size_t start = 0, size_t count = 0);

// Internally batched signature signing and verification
void AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash, SignDoneCallback doneCallback);
void AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash, const SignDoneCallback& doneCallback);
std::future<CBLSSignature> AsyncSign(const CBLSSecretKey& secKey, const uint256& msgHash);
void AsyncVerifySig(const CBLSSignature& sig, const CBLSPublicKey& pubKey, const uint256& msgHash, SigVerifyDoneCallback doneCallback, CancelCond cancelCond = [] { return false; });
std::future<bool> AsyncVerifySig(const CBLSSignature& sig, const CBLSPublicKey& pubKey, const uint256& msgHash, CancelCond cancelCond = [] { return false; });
Expand Down Expand Up @@ -176,7 +174,7 @@ class CBLSWorkerCache
CBLSPublicKey BuildPubKeyShare(const uint256& cacheKey, const BLSVerificationVectorPtr& vvec, const CBLSId& id)
{
return GetOrBuild(cacheKey, publicKeyShareCache, [&]() {
return worker.BuildPubKeyShare(vvec, id);
return CBLSWorker::BuildPubKeyShare(vvec, id);
});
}

Expand Down