LCOV - code coverage report
Current view: top level - src/llmq - quorums_dkgsessionmgr.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 127 133 95.5 %
Date: 2025-02-23 09:33:43 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2018-2021 The Dash Core developers
       2             : // Copyright (c) 2022 The PIVX Core developers
       3             : // Distributed under the MIT/X11 software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "llmq/quorums_dkgsessionmgr.h"
       7             : 
       8             : #include "chainparams.h"
       9             : #include "llmq/quorums_blockprocessor.h"
      10             : #include "llmq/quorums_utils.h"
      11             : #include "spork.h"
      12             : #include "validation.h"
      13             : 
      14             : namespace llmq
      15             : {
      16             : 
      17             : std::unique_ptr<CDKGSessionManager> quorumDKGSessionManager{nullptr};
      18             : 
      19             : static const std::string DB_VVEC = "qdkg_V";
      20             : static const std::string DB_SKCONTRIB = "qdkg_S";
      21             : 
      22         475 : CDKGSessionManager::CDKGSessionManager(CDBWrapper& _llmqDb, CBLSWorker& _blsWorker) : llmqDb(_llmqDb),
      23         475 :                                                                                       blsWorker(_blsWorker)
      24             : {
      25        1106 :     for (const auto& qt : Params().GetConsensus().llmqs) {
      26         631 :         dkgSessionHandlers.emplace(std::piecewise_construct,
      27         631 :                 std::forward_as_tuple(qt.first),
      28         631 :                 std::forward_as_tuple(qt.second, blsWorker, *this));
      29             :     }
      30         475 : }
      31             : 
      32         347 : void CDKGSessionManager::StartThreads()
      33             : {
      34         694 :     for (auto& it : dkgSessionHandlers) {
      35         347 :         it.second.StartThread();
      36             :     }
      37         347 : }
      38             : 
      39         357 : void CDKGSessionManager::StopThreads()
      40             : {
      41         714 :     for (auto& it : dkgSessionHandlers) {
      42         357 :         it.second.StopThread();
      43             :     }
      44         357 : }
      45             : 
      46       41471 : void CDKGSessionManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitialDownload)
      47             : {
      48       41471 :     CleanupCache();
      49             : 
      50       41471 :     if (fInitialDownload)
      51       32848 :         return;
      52       40689 :     if (!deterministicMNManager->IsDIP3Enforced(pindexNew->nHeight))
      53             :         return;
      54             : 
      55       17246 :     LOCK(cs_main);
      56             : 
      57       17246 :     for (auto& qt : dkgSessionHandlers) {
      58        8623 :         qt.second.UpdatedBlockTip(pindexNew);
      59             :     }
      60             : }
      61             : 
      62         259 : bool CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv)
      63             : {
      64         259 :     if (vRecv.empty()) {
      65             :         return false;
      66             :     }
      67             : 
      68             :     // peek into the message and see which LLMQType it is. First byte of all messages is always the LLMQType
      69         259 :     Consensus::LLMQType llmqType = (Consensus::LLMQType)*vRecv.begin();
      70         259 :     if (!dkgSessionHandlers.count(llmqType)) {
      71           0 :         return false;
      72             :     }
      73             : 
      74         259 :     dkgSessionHandlers.at(llmqType).ProcessMessage(pfrom, strCommand, vRecv);
      75             :     return true;
      76             : }
      77             : 
      78        1038 : bool CDKGSessionManager::AlreadyHave(const CInv& inv) const
      79             : {
      80        1586 :     for (const auto& p : dkgSessionHandlers) {
      81        1038 :         auto& dkgType = p.second;
      82        1038 :         if (dkgType.pendingContributions.HasSeen(inv.hash)
      83         809 :             || dkgType.pendingComplaints.HasSeen(inv.hash)
      84         764 :             || dkgType.pendingJustifications.HasSeen(inv.hash)
      85        1786 :             || dkgType.pendingPrematureCommitments.HasSeen(inv.hash)) {
      86         490 :             return true;
      87             :         }
      88             :     }
      89         548 :     return false;
      90             : }
      91             : 
      92         126 : bool CDKGSessionManager::GetContribution(const uint256& hash, CDKGContribution& ret) const
      93             : {
      94         131 :     for (const auto& p : dkgSessionHandlers) {
      95         126 :         auto& dkgType = p.second;
      96         126 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
      97         126 :         if (dkgType.phase < QuorumPhase_Initialized || dkgType.phase > QuorumPhase_Contribute) {
      98          10 :             continue;
      99             :         }
     100         121 :         auto it = dkgType.curSession->contributions.find(hash);
     101         121 :         if (it != dkgType.curSession->contributions.end()) {
     102         121 :             ret = it->second;
     103         242 :             return true;
     104             :         }
     105             :     }
     106           5 :     return false;
     107             : }
     108             : 
     109          33 : bool CDKGSessionManager::GetComplaint(const uint256& hash, CDKGComplaint& ret) const
     110             : {
     111          40 :     for (const auto& p : dkgSessionHandlers) {
     112          33 :         auto& dkgType = p.second;
     113          33 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
     114          33 :         if (dkgType.phase < QuorumPhase_Contribute || dkgType.phase > QuorumPhase_Complain) {
     115          14 :             continue;
     116             :         }
     117          26 :         auto it = dkgType.curSession->complaints.find(hash);
     118          26 :         if (it != dkgType.curSession->complaints.end()) {
     119          26 :             ret = it->second;
     120          52 :             return true;
     121             :         }
     122             :     }
     123           7 :     return false;
     124             : }
     125             : 
     126           8 : bool CDKGSessionManager::GetJustification(const uint256& hash, CDKGJustification& ret) const
     127             : {
     128           8 :     for (const auto& p : dkgSessionHandlers) {
     129           8 :         auto& dkgType = p.second;
     130           8 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
     131           8 :         if (dkgType.phase < QuorumPhase_Complain || dkgType.phase > QuorumPhase_Justify) {
     132           0 :             continue;
     133             :         }
     134           8 :         auto it = dkgType.curSession->justifications.find(hash);
     135           8 :         if (it != dkgType.curSession->justifications.end()) {
     136           8 :             ret = it->second;
     137          16 :             return true;
     138             :         }
     139             :     }
     140           0 :     return false;
     141             : }
     142             : 
     143         104 : bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const
     144             : {
     145         104 :     for (const auto& p : dkgSessionHandlers) {
     146         104 :         auto& dkgType = p.second;
     147         104 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
     148         104 :         if (dkgType.phase < QuorumPhase_Justify || dkgType.phase > QuorumPhase_Commit) {
     149           0 :             continue;
     150             :         }
     151         104 :         auto it = dkgType.curSession->prematureCommitments.find(hash);
     152         104 :         if (it != dkgType.curSession->prematureCommitments.end() && dkgType.curSession->validCommitments.count(hash)) {
     153         104 :             ret = it->second;
     154         208 :             return true;
     155             :         }
     156             :     }
     157           0 :     return false;
     158             : }
     159             : 
     160         186 : void CDKGSessionManager::WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec)
     161             : {
     162         372 :     llmqDb.Write(std::make_tuple(DB_VVEC, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), *vvec);
     163         186 : }
     164             : 
     165         165 : void CDKGSessionManager::WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const CBLSSecretKey& skContribution)
     166             : {
     167         330 :     llmqDb.Write(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), skContribution);
     168         165 : }
     169             : 
     170         357 : bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const std::vector<bool>& validMembers, std::vector<uint16_t>& memberIndexesRet, std::vector<BLSVerificationVectorPtr>& vvecsRet, BLSSecretKeyVector& skContributionsRet)
     171             : {
     172         714 :     auto members = deterministicMNManager->GetAllQuorumMembers(llmqType, pindexQuorum);
     173             : 
     174         357 :     memberIndexesRet.clear();
     175         357 :     vvecsRet.clear();
     176         357 :     skContributionsRet.clear();
     177         357 :     memberIndexesRet.reserve(members.size());
     178         357 :     vvecsRet.reserve(members.size());
     179         357 :     skContributionsRet.reserve(members.size());
     180        1428 :     for (size_t i = 0; i < members.size(); i++) {
     181        1071 :         if (validMembers[i]) {
     182         970 :             BLSVerificationVectorPtr vvec;
     183        1940 :             CBLSSecretKey skContribution;
     184         970 :             if (!GetVerifiedContribution(llmqType, pindexQuorum, members[i]->proTxHash, vvec, skContribution)) {
     185           0 :                 return false;
     186             :             }
     187             : 
     188         970 :             memberIndexesRet.emplace_back(i);
     189         970 :             vvecsRet.emplace_back(vvec);
     190         970 :             skContributionsRet.emplace_back(skContribution);
     191             :         }
     192             :     }
     193         357 :     return true;
     194             : }
     195             : 
     196         970 : bool CDKGSessionManager::GetVerifiedContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, BLSVerificationVectorPtr& vvecRet, CBLSSecretKey& skContributionRet)
     197             : {
     198         970 :     const uint256& quorumHash = pindexQuorum->GetBlockHash();
     199        1940 :     LOCK(contributionsCacheCs);
     200         970 :     ContributionsCacheKey cacheKey = {llmqType, quorumHash, proTxHash};
     201         970 :     auto it = contributionsCache.find(cacheKey);
     202         970 :     if (it != contributionsCache.end()) {
     203         596 :         vvecRet = it->second.vvec;
     204         596 :         skContributionRet = it->second.skContribution;
     205         596 :         return true;
     206             :     }
     207             : 
     208        1344 :     BLSVerificationVector vvec;
     209         374 :     BLSVerificationVectorPtr vvecPtr;
     210         748 :     CBLSSecretKey skContribution;
     211         748 :     if (llmqDb.Read(std::make_tuple(DB_VVEC, (uint8_t)llmqType, quorumHash, proTxHash), vvec)) {
     212         312 :         vvecPtr = std::make_shared<BLSVerificationVector>(std::move(vvec));
     213             :     }
     214         748 :     llmqDb.Read(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, quorumHash, proTxHash), skContribution);
     215             : 
     216         374 :     it = contributionsCache.emplace(cacheKey, ContributionsCacheEntry{GetTimeMillis(), vvecPtr, skContribution}).first;
     217             : 
     218         374 :     vvecRet = it->second.vvec;
     219         374 :     skContributionRet = it->second.skContribution;
     220             : 
     221         374 :     return true;
     222             : }
     223             : 
     224       41471 : void CDKGSessionManager::CleanupCache()
     225             : {
     226       41471 :     LOCK(contributionsCacheCs);
     227       41471 :     auto curTime = GetTimeMillis();
     228       41471 :     for (auto it = contributionsCache.begin(); it != contributionsCache.end(); ) {
     229       26947 :         if (curTime - it->second.entryTime > MAX_CONTRIBUTION_CACHE_TIME) {
     230         110 :             it = contributionsCache.erase(it);
     231             :         } else {
     232       95255 :             ++it;
     233             :         }
     234             :     }
     235       41471 : }
     236             : 
     237             : }

Generated by: LCOV version 1.14