20 #include "validation.h"
28 static const std::string DB_QUORUM_SK_SHARE =
"q_Qsk";
29 static const std::string DB_QUORUM_QUORUM_VVEC =
"q_Qqvvec";
33 static uint256 MakeQuorumKey(
const CQuorum& q)
36 hw << (uint8_t)q.params.type;
37 hw << q.qc.quorumHash;
38 for (
const auto& dmn : q.members) {
75 for (
size_t i = 0; i <
members.size(); i++) {
99 for (
size_t i = 0; i <
members.size(); i++) {
109 uint256 dbKey = MakeQuorumKey(*
this);
112 evoDb.GetRawDB().Write(std::make_pair(DB_QUORUM_QUORUM_VVEC, dbKey), *
quorumVvec);
115 evoDb.GetRawDB().Write(std::make_pair(DB_QUORUM_SK_SHARE, dbKey),
skShare);
121 uint256 dbKey = MakeQuorumKey(*
this);
124 if (
evoDb.Read(std::make_pair(DB_QUORUM_QUORUM_VVEC, dbKey), qv)) {
125 quorumVvec = std::make_shared<BLSVerificationVector>(std::move(qv));
132 evoDb.Read(std::make_pair(DB_QUORUM_SK_SHARE, dbKey),
skShare);
139 if (_this->quorumVvec ==
nullptr) {
148 _this->cachePopulatorThread = std::thread(&
TraceThread<std::function<
void()> >,
"quorum-cachepop", [_this, t] {
149 for (
size_t i = 0; i < _this->members.size() && !_this->stopCachePopulatorThread && !
ShutdownRequested(); i++) {
150 if (_this->qc.validMembers[i]) {
151 _this->GetPubKeyShare(i);
160 dkgManager(_dkgManager)
172 for (
auto& p :
Params().GetConsensus().llmqs) {
175 auto lastQuorums =
ScanQuorums(p.first, pindexNew, (
size_t)params.keepOldConnections);
184 assert(pindexQuorum);
188 quorum->Init(qc, pindexQuorum, minedBlockHash, members);
190 bool hasValidVvec =
false;
191 if (quorum->ReadContributions(
evoDb)) {
195 quorum->WriteContributions(
evoDb);
214 std::vector<uint16_t> memberIndexes;
215 std::vector<BLSVerificationVectorPtr> vvecs;
226 if (quorumVvec ==
nullptr) {
242 quorum->quorumVvec = quorumVvec;
243 quorum->skShare = skShare;
261 if (pindexStart ==
nullptr || maxCount == 0) {
265 bool fCacheExists{
false};
266 void* pIndexScanCommitments{(
void*)pindexStart};
267 size_t nScanCommitments{maxCount};
268 std::vector<CQuorumCPtr> vecResultQuorums;
273 fCacheExists = cache.get(pindexStart->
GetBlockHash(), vecResultQuorums);
276 if (vecResultQuorums.size() == maxCount) {
277 return vecResultQuorums;
280 if (vecResultQuorums.size() > maxCount) {
281 return {vecResultQuorums.begin(), vecResultQuorums.begin() + maxCount};
285 if (vecResultQuorums.size() > 0) {
286 nScanCommitments -= vecResultQuorums.size();
287 pIndexScanCommitments = (
void*)vecResultQuorums.back()->pindexQuorum->pprev;
291 nScanCommitments = std::max(maxCount, cache.max_size());
296 vecResultQuorums.reserve(vecResultQuorums.size() + quorumIndexes.size());
298 for (
auto& quorumIndex : quorumIndexes) {
300 auto quorum =
GetQuorum(llmqType, quorumIndex);
301 assert(quorum !=
nullptr);
302 vecResultQuorums.emplace_back(quorum);
305 size_t nCountResult{vecResultQuorums.size()};
306 if (nCountResult > 0 && !fCacheExists) {
310 size_t nCacheEndIndex = std::min(nCountResult, cache.max_size());
311 cache.emplace(pindexStart->
GetBlockHash(), {vecResultQuorums.begin(), vecResultQuorums.begin() + nCacheEndIndex});
314 size_t nResultEndIndex = std::min(nCountResult, maxCount);
315 return {vecResultQuorums.begin(), vecResultQuorums.begin() + nResultEndIndex};
330 return GetQuorum(llmqType, pindexQuorum);
335 assert(pindexQuorum);
358 auto quorum = std::make_shared<CQuorum>(params,
blsWorker);
CActiveDeterministicMasternodeManager * activeMasternodeManager
std::vector< CBLSPublicKey > BLSVerificationVector
std::shared_ptr< BLSVerificationVector > BLSVerificationVectorPtr
std::vector< CBLSSecretKey > BLSSecretKeyVector
const CChainParams & Params()
Return the currently selected parameters.
const uint256 GetProTx() const
CBLSPublicKey BuildPubKeyShare(const uint256 &cacheKey, const BLSVerificationVectorPtr &vvec, const CBLSId &id)
CBLSSecretKey AggregateSecretKeys(const BLSSecretKeyVector &secKeys, size_t start=0, size_t count=0, bool parallel=true)
BLSVerificationVectorPtr BuildQuorumVerificationVector(const std::vector< BLSVerificationVectorPtr > &vvecs, size_t start=0, size_t count=0, bool parallel=true)
The block chain is a tree shaped structure starting with the genesis block at the root,...
uint256 GetBlockHash() const
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
const Consensus::Params & GetConsensus() const
A writer stream (for serialization) that computes a 256-bit hash.
bool IsBlockchainSynced() const
std::string ToString() const
This class works as a stopwatch.
void stop()
Stop/pause the timer.
duration_t::rep count() const
Return the elapsed time.
bool GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex *pindexQuorum, const std::vector< bool > &validMembers, std::vector< uint16_t > &memberIndexesRet, std::vector< BLSVerificationVectorPtr > &vvecsRet, BLSSecretKeyVector &skContributionsRet)
std::vector< bool > validMembers
std::thread cachePopulatorThread
void WriteContributions(CEvoDB &evoDb)
CBLSPublicKey GetPubKeyShare(size_t memberIdx) const
const CBlockIndex * pindexQuorum
bool ReadContributions(CEvoDB &evoDb)
BLSVerificationVectorPtr quorumVvec
std::vector< CDeterministicMNCPtr > members
int GetMemberIndex(const uint256 &proTxHash) const
bool IsValidMember(const uint256 &proTxHash) const
std::atomic< bool > stopCachePopulatorThread
void Init(const CFinalCommitment &_qc, const CBlockIndex *_pindexQuorum, const uint256 &_minedBlockHash, const std::vector< CDeterministicMNCPtr > &_members)
CBLSSecretKey GetSkShare() const
bool IsMember(const uint256 &proTxHash) const
static void StartCachePopulatorThread(std::shared_ptr< CQuorum > _this)
std::vector< CQuorumCPtr > ScanQuorums(Consensus::LLMQType llmqType, size_t maxCount)
std::map< Consensus::LLMQType, unordered_lru_cache< uint256, CQuorumCPtr, StaticSaltedHasher > > mapQuorumsCache
CDKGSessionManager & dkgManager
CQuorumManager(CEvoDB &_evoDb, CBLSWorker &_blsWorker, CDKGSessionManager &_dkgManager)
RecursiveMutex quorumsCacheCs
bool BuildQuorumContributions(const CFinalCommitment &fqc, std::shared_ptr< CQuorum > &quorum) const
std::map< Consensus::LLMQType, unordered_lru_cache< uint256, std::vector< CQuorumCPtr >, StaticSaltedHasher > > scanQuorumsCache
CQuorumCPtr GetQuorum(Consensus::LLMQType llmqType, const uint256 &quorumHash)
bool BuildQuorumFromCommitment(const CFinalCommitment &qc, const CBlockIndex *pindexQuorum, const uint256 &minedBlockHash, std::shared_ptr< CQuorum > &quorum) const
bool HasQuorum(Consensus::LLMQType llmqType, const uint256 &quorumHash)
void UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload)
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
std::unique_ptr< CEvoDB > evoDb
#define LogPrint(category,...)
void InitQuorumsCache(CacheType &cache)
std::shared_ptr< const CQuorum > CQuorumCPtr
std::unique_ptr< CQuorumBlockProcessor > quorumBlockProcessor
void EnsureLatestQuorumConnections(Consensus::LLMQType llmqType, const CBlockIndex *pindexNew, const uint256 &myProTxHash, std::vector< CQuorumCPtr > &lastQuorums)
std::unique_ptr< CQuorumManager > quorumManager
RecursiveMutex cs_main
Global state.
std::map< LLMQType, LLMQParams > llmqs
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void TraceThread(const std::string name, Callable func)
TierTwoSyncState g_tiertwo_sync_state
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)