LCOV - code coverage report
Current view: top level - src/llmq - quorums_dkgsessionmgr.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 29 133 21.8 %
Date: 2026-08-09 10:51:41 Functions: 5 15 33.3 %

          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         413 : CDKGSessionManager::CDKGSessionManager(CDBWrapper& _llmqDb, CBLSWorker& _blsWorker) : llmqDb(_llmqDb),
      23         413 :                                                                                       blsWorker(_blsWorker)
      24             : {
      25         982 :     for (const auto& qt : Params().GetConsensus().llmqs) {
      26         569 :         dkgSessionHandlers.emplace(std::piecewise_construct,
      27         569 :                 std::forward_as_tuple(qt.first),
      28         569 :                 std::forward_as_tuple(qt.second, blsWorker, *this));
      29             :     }
      30         413 : }
      31             : 
      32         285 : void CDKGSessionManager::StartThreads()
      33             : {
      34         570 :     for (auto& it : dkgSessionHandlers) {
      35         285 :         it.second.StartThread();
      36             :     }
      37         285 : }
      38             : 
      39         295 : void CDKGSessionManager::StopThreads()
      40             : {
      41         590 :     for (auto& it : dkgSessionHandlers) {
      42         295 :         it.second.StopThread();
      43             :     }
      44         295 : }
      45             : 
      46       24761 : void CDKGSessionManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitialDownload)
      47             : {
      48       24761 :     CleanupCache();
      49             : 
      50       24761 :     if (fInitialDownload)
      51       23966 :         return;
      52       24034 :     if (!deterministicMNManager->IsDIP3Enforced(pindexNew->nHeight))
      53             :         return;
      54             : 
      55        1590 :     LOCK(cs_main);
      56             : 
      57        1590 :     for (auto& qt : dkgSessionHandlers) {
      58         795 :         qt.second.UpdatedBlockTip(pindexNew);
      59             :     }
      60             : }
      61             : 
      62           0 : bool CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv)
      63             : {
      64           0 :     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           0 :     Consensus::LLMQType llmqType = (Consensus::LLMQType)*vRecv.begin();
      70           0 :     if (!dkgSessionHandlers.count(llmqType)) {
      71           0 :         return false;
      72             :     }
      73             : 
      74           0 :     dkgSessionHandlers.at(llmqType).ProcessMessage(pfrom, strCommand, vRecv);
      75             :     return true;
      76             : }
      77             : 
      78           0 : bool CDKGSessionManager::AlreadyHave(const CInv& inv) const
      79             : {
      80           0 :     for (const auto& p : dkgSessionHandlers) {
      81           0 :         auto& dkgType = p.second;
      82           0 :         if (dkgType.pendingContributions.HasSeen(inv.hash)
      83           0 :             || dkgType.pendingComplaints.HasSeen(inv.hash)
      84           0 :             || dkgType.pendingJustifications.HasSeen(inv.hash)
      85           0 :             || dkgType.pendingPrematureCommitments.HasSeen(inv.hash)) {
      86           0 :             return true;
      87             :         }
      88             :     }
      89           0 :     return false;
      90             : }
      91             : 
      92           0 : bool CDKGSessionManager::GetContribution(const uint256& hash, CDKGContribution& ret) const
      93             : {
      94           0 :     for (const auto& p : dkgSessionHandlers) {
      95           0 :         auto& dkgType = p.second;
      96           0 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
      97           0 :         if (dkgType.phase < QuorumPhase_Initialized || dkgType.phase > QuorumPhase_Contribute) {
      98           0 :             continue;
      99             :         }
     100           0 :         auto it = dkgType.curSession->contributions.find(hash);
     101           0 :         if (it != dkgType.curSession->contributions.end()) {
     102           0 :             ret = it->second;
     103           0 :             return true;
     104             :         }
     105             :     }
     106           0 :     return false;
     107             : }
     108             : 
     109           0 : bool CDKGSessionManager::GetComplaint(const uint256& hash, CDKGComplaint& ret) const
     110             : {
     111           0 :     for (const auto& p : dkgSessionHandlers) {
     112           0 :         auto& dkgType = p.second;
     113           0 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
     114           0 :         if (dkgType.phase < QuorumPhase_Contribute || dkgType.phase > QuorumPhase_Complain) {
     115           0 :             continue;
     116             :         }
     117           0 :         auto it = dkgType.curSession->complaints.find(hash);
     118           0 :         if (it != dkgType.curSession->complaints.end()) {
     119           0 :             ret = it->second;
     120           0 :             return true;
     121             :         }
     122             :     }
     123           0 :     return false;
     124             : }
     125             : 
     126           0 : bool CDKGSessionManager::GetJustification(const uint256& hash, CDKGJustification& ret) const
     127             : {
     128           0 :     for (const auto& p : dkgSessionHandlers) {
     129           0 :         auto& dkgType = p.second;
     130           0 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
     131           0 :         if (dkgType.phase < QuorumPhase_Complain || dkgType.phase > QuorumPhase_Justify) {
     132           0 :             continue;
     133             :         }
     134           0 :         auto it = dkgType.curSession->justifications.find(hash);
     135           0 :         if (it != dkgType.curSession->justifications.end()) {
     136           0 :             ret = it->second;
     137           0 :             return true;
     138             :         }
     139             :     }
     140           0 :     return false;
     141             : }
     142             : 
     143           0 : bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const
     144             : {
     145           0 :     for (const auto& p : dkgSessionHandlers) {
     146           0 :         auto& dkgType = p.second;
     147           0 :         LOCK2(dkgType.cs, dkgType.curSession->invCs);
     148           0 :         if (dkgType.phase < QuorumPhase_Justify || dkgType.phase > QuorumPhase_Commit) {
     149           0 :             continue;
     150             :         }
     151           0 :         auto it = dkgType.curSession->prematureCommitments.find(hash);
     152           0 :         if (it != dkgType.curSession->prematureCommitments.end() && dkgType.curSession->validCommitments.count(hash)) {
     153           0 :             ret = it->second;
     154           0 :             return true;
     155             :         }
     156             :     }
     157           0 :     return false;
     158             : }
     159             : 
     160           0 : void CDKGSessionManager::WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec)
     161             : {
     162           0 :     llmqDb.Write(std::make_tuple(DB_VVEC, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), *vvec);
     163           0 : }
     164             : 
     165           0 : void CDKGSessionManager::WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const CBLSSecretKey& skContribution)
     166             : {
     167           0 :     llmqDb.Write(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, pindexQuorum->GetBlockHash(), proTxHash), skContribution);
     168           0 : }
     169             : 
     170           0 : 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           0 :     auto members = deterministicMNManager->GetAllQuorumMembers(llmqType, pindexQuorum);
     173             : 
     174           0 :     memberIndexesRet.clear();
     175           0 :     vvecsRet.clear();
     176           0 :     skContributionsRet.clear();
     177           0 :     memberIndexesRet.reserve(members.size());
     178           0 :     vvecsRet.reserve(members.size());
     179           0 :     skContributionsRet.reserve(members.size());
     180           0 :     for (size_t i = 0; i < members.size(); i++) {
     181           0 :         if (validMembers[i]) {
     182           0 :             BLSVerificationVectorPtr vvec;
     183           0 :             CBLSSecretKey skContribution;
     184           0 :             if (!GetVerifiedContribution(llmqType, pindexQuorum, members[i]->proTxHash, vvec, skContribution)) {
     185           0 :                 return false;
     186             :             }
     187             : 
     188           0 :             memberIndexesRet.emplace_back(i);
     189           0 :             vvecsRet.emplace_back(vvec);
     190           0 :             skContributionsRet.emplace_back(skContribution);
     191             :         }
     192             :     }
     193           0 :     return true;
     194             : }
     195             : 
     196           0 : bool CDKGSessionManager::GetVerifiedContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, BLSVerificationVectorPtr& vvecRet, CBLSSecretKey& skContributionRet)
     197             : {
     198           0 :     const uint256& quorumHash = pindexQuorum->GetBlockHash();
     199           0 :     LOCK(contributionsCacheCs);
     200           0 :     ContributionsCacheKey cacheKey = {llmqType, quorumHash, proTxHash};
     201           0 :     auto it = contributionsCache.find(cacheKey);
     202           0 :     if (it != contributionsCache.end()) {
     203           0 :         vvecRet = it->second.vvec;
     204           0 :         skContributionRet = it->second.skContribution;
     205           0 :         return true;
     206             :     }
     207             : 
     208           0 :     BLSVerificationVector vvec;
     209           0 :     BLSVerificationVectorPtr vvecPtr;
     210           0 :     CBLSSecretKey skContribution;
     211           0 :     if (llmqDb.Read(std::make_tuple(DB_VVEC, (uint8_t)llmqType, quorumHash, proTxHash), vvec)) {
     212           0 :         vvecPtr = std::make_shared<BLSVerificationVector>(std::move(vvec));
     213             :     }
     214           0 :     llmqDb.Read(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, quorumHash, proTxHash), skContribution);
     215             : 
     216           0 :     it = contributionsCache.emplace(cacheKey, ContributionsCacheEntry{GetTimeMillis(), vvecPtr, skContribution}).first;
     217             : 
     218           0 :     vvecRet = it->second.vvec;
     219           0 :     skContributionRet = it->second.skContribution;
     220             : 
     221           0 :     return true;
     222             : }
     223             : 
     224       24761 : void CDKGSessionManager::CleanupCache()
     225             : {
     226       24761 :     LOCK(contributionsCacheCs);
     227       24761 :     auto curTime = GetTimeMillis();
     228       24761 :     for (auto it = contributionsCache.begin(); it != contributionsCache.end(); ) {
     229           0 :         if (curTime - it->second.entryTime > MAX_CONTRIBUTION_CACHE_TIME) {
     230           0 :             it = contributionsCache.erase(it);
     231             :         } else {
     232       24761 :             ++it;
     233             :         }
     234             :     }
     235       24761 : }
     236             : 
     237             : }

Generated by: LCOV version 1.14