LCOV - code coverage report
Current view: top level - src/llmq - quorums_signing.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 17 17 100.0 %
Date: 2025-04-02 01:23:23 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2018-2022 The Dash Core developers
       2             : // Copyright (c) 2023 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             : #ifndef PIVX_LLMQ_QUORUMS_SIGNING_H
       7             : #define PIVX_LLMQ_QUORUMS_SIGNING_H
       8             : 
       9             : #include "llmq/quorums.h"
      10             : 
      11             : #include "chainparams.h"
      12             : #include "net.h"
      13             : #include "saltedhasher.h"
      14             : #include "sync.h"
      15             : #include "unordered_lru_cache.h"
      16             : 
      17             : #include <unordered_map>
      18             : 
      19             : namespace llmq
      20             : {
      21             : 
      22       14082 : class CRecoveredSig
      23             : {
      24             : public:
      25             :     uint8_t llmqType;
      26             :     uint256 quorumHash;
      27             :     uint256 id;
      28             :     uint256 msgHash;
      29             :     CBLSLazySignature sig;
      30             : 
      31             :     // only in-memory
      32             :     uint256 hash;
      33             : 
      34             : public:
      35       19844 :     SERIALIZE_METHODS(CRecoveredSig, obj)
      36             :     {
      37       10754 :         READWRITE(obj.llmqType);
      38       10754 :         READWRITE(obj.quorumHash);
      39       10754 :         READWRITE(obj.id);
      40       10754 :         READWRITE(obj.msgHash);
      41       10754 :         READWRITE(obj.sig);
      42       14082 :         SER_READ(obj, obj.UpdateHash());
      43       10754 :     }
      44             : 
      45        3713 :     void UpdateHash()
      46             :     {
      47        3713 :         hash = ::SerializeHash(*this);
      48         385 :     }
      49             : 
      50       16901 :     const uint256& GetHash() const
      51             :     {
      52       33802 :         assert(!hash.IsNull());
      53       16901 :         return hash;
      54             :     }
      55             : };
      56             : 
      57             : class CRecoveredSigsDb
      58             : {
      59             : private:
      60             :     CDBWrapper& db;
      61             : 
      62             :     RecursiveMutex cs;
      63             :     unordered_lru_cache<std::pair<Consensus::LLMQType, uint256>, bool, StaticSaltedHasher, 30000> hasSigForIdCache;
      64             :     unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForSessionCache;
      65             :     unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForHashCache;
      66             : 
      67             : public:
      68             :     explicit CRecoveredSigsDb(CDBWrapper& _db);
      69             : 
      70             :     void ConvertInvalidTimeKeys();
      71             :     void AddVoteTimeKeys();
      72             : 
      73             :     bool HasRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash);
      74             :     bool HasRecoveredSigForId(Consensus::LLMQType llmqType, const uint256& id);
      75             :     bool HasRecoveredSigForSession(const uint256& signHash);
      76             :     bool HasRecoveredSigForHash(const uint256& hash);
      77             :     bool GetRecoveredSigByHash(const uint256& hash, CRecoveredSig& ret);
      78             :     bool GetRecoveredSigById(Consensus::LLMQType llmqType, const uint256& id, CRecoveredSig& ret);
      79             :     void WriteRecoveredSig(const CRecoveredSig& recSig);
      80             :     void RemoveRecoveredSig(Consensus::LLMQType llmqType, const uint256& id);
      81             :     void TruncateRecoveredSig(Consensus::LLMQType llmqType, const uint256& id);
      82             : 
      83             :     void CleanupOldRecoveredSigs(int64_t maxAge);
      84             : 
      85             :     // votes are removed when the recovered sig is written to the db
      86             :     bool HasVotedOnId(Consensus::LLMQType llmqType, const uint256& id);
      87             :     bool GetVoteForId(Consensus::LLMQType llmqType, const uint256& id, uint256& msgHashRet);
      88             :     void WriteVoteForId(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash);
      89             : 
      90             :     void CleanupOldVotes(int64_t maxAge);
      91             : 
      92             : private:
      93             :     bool ReadRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, CRecoveredSig& ret);
      94             :     void RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType llmqType, const uint256& id, bool deleteHashKey, bool deleteTimeKey);
      95             : };
      96             : 
      97         950 : class CRecoveredSigsListener
      98             : {
      99             : public:
     100         950 :     virtual ~CRecoveredSigsListener() {}
     101             : 
     102             :     virtual void HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) = 0;
     103             : };
     104             : 
     105             : class CSigningManager
     106             : {
     107             :     friend class CSigSharesManager;
     108             :     static const int64_t DEFAULT_MAX_RECOVERED_SIGS_AGE = 60 * 60 * 24 * 7; // keep them for a week
     109             : 
     110             :     // when selecting a quorum for signing and verification, we use CQuorumManager::SelectQuorum with this offset as
     111             :     // starting height for scanning. This is because otherwise the resulting signatures would not be verifiable by nodes
     112             :     // which are not 100% at the chain tip.
     113             :     static const int SIGN_HEIGHT_OFFSET = 8;
     114             : 
     115             : private:
     116             :     RecursiveMutex cs;
     117             : 
     118             :     CRecoveredSigsDb db;
     119             : 
     120             :     // Incoming and not verified yet
     121             :     std::unordered_map<NodeId, std::list<CRecoveredSig>> pendingRecoveredSigs;
     122             : 
     123             :     // must be protected by cs
     124             :     FastRandomContext rnd;
     125             : 
     126             :     int64_t lastCleanupTime{0};
     127             : 
     128             :     std::vector<CRecoveredSigsListener*> recoveredSigsListeners;
     129             : 
     130             : public:
     131             :     CSigningManager(CDBWrapper& llmqDb, bool fMemory);
     132             : 
     133             :     bool AlreadyHave(const CInv& inv);
     134             :     bool GetRecoveredSigForGetData(const uint256& hash, CRecoveredSig& ret);
     135             : 
     136             :     void ProcessMessage(CNode* pnode, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
     137             : 
     138             :     // This is called when a recovered signature can be safely removed from the DB. This is only safe when some other
     139             :     // mechanism prevents possible conflicts. As an example, ChainLocks prevent conflicts in confirmed TXs InstantSend votes
     140             :     // This won't completely remove all traces of the recovered sig but instead leave the hash entry in the DB. This
     141             :     // allows AlreadyHave to keep returning true. Cleanup will later remove the remains
     142             :     void TruncateRecoveredSig(Consensus::LLMQType llmqType, const uint256& id);
     143             : 
     144             : private:
     145             :     void ProcessMessageRecoveredSig(CNode* pfrom, const CRecoveredSig& recoveredSig, CConnman& connman);
     146             :     bool PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig& recoveredSig, bool& retBan);
     147             : 
     148             :     void CollectPendingRecoveredSigsToVerify(size_t maxUniqueSessions,
     149             :         std::unordered_map<NodeId, std::list<CRecoveredSig>>& retSigShares,
     150             :         std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr, StaticSaltedHasher>& retQuorums);
     151             :     bool ProcessPendingRecoveredSigs(CConnman& connman); // called from the worker thread of CSigSharesManager
     152             :     void ProcessRecoveredSig(NodeId nodeId, const CRecoveredSig& recoveredSig, const CQuorumCPtr& quorum, CConnman& connman);
     153             :     void Cleanup(); // called from the worker thread of CSigSharesManager
     154             : 
     155             : public:
     156             :     // public interface
     157             :     void RegisterRecoveredSigsListener(CRecoveredSigsListener* l);
     158             :     void UnregisterRecoveredSigsListener(CRecoveredSigsListener* l);
     159             :     bool AsyncSignIfMember(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash, bool allowReSign = false);
     160             :     bool HasRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash);
     161             :     bool HasRecoveredSigForId(Consensus::LLMQType llmqType, const uint256& id);
     162             :     bool HasRecoveredSigForSession(const uint256& signHash);
     163             :     bool IsConflicting(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash);
     164             :     bool HasVotedOnId(Consensus::LLMQType llmqType, const uint256& id);
     165             :     bool GetVoteForId(Consensus::LLMQType llmqType, const uint256& id, uint256& msgHashRet);
     166             : 
     167             :     std::vector<CQuorumCPtr> GetActiveQuorumSet(Consensus::LLMQType llmqType, int signHeight);
     168             :     CQuorumCPtr SelectQuorumForSigning(Consensus::LLMQType llmqType, const uint256& selectionHash, int signHeight = -1 /*chain tip*/, int signOffset = SIGN_HEIGHT_OFFSET);
     169             :     // Verifies a recovered sig that was signed while the chain tip was at signedAtTip
     170             :     bool VerifyRecoveredSig(Consensus::LLMQType llmqType, int signedAtHeight, const uint256& id, const uint256& msgHash, const CBLSSignature& sig);
     171             : };
     172             : 
     173             : extern std::unique_ptr<CSigningManager> quorumSigningManager;
     174             : 
     175             : } // namespace llmq
     176             : 
     177             : #endif // PIVX_LLMQ_QUORUMS_SIGNING_H

Generated by: LCOV version 1.14