Line data Source code
1 : // Copyright (c) 2018 The Dash Core developers 2 : // Copyright (c) 2023 The PIVX 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_H 7 : #define PIVX_LLMQ_QUORUMS_H 8 : 9 : #include "bls/bls_worker.h" 10 : #include "bls/bls_wrapper.h" 11 : #include "consensus/params.h" 12 : #include "evo/deterministicmns.h" 13 : #include "evo/evodb.h" 14 : #include "saltedhasher.h" 15 : #include "unordered_lru_cache.h" 16 : #include "validationinterface.h" 17 : 18 : namespace llmq 19 : { 20 : 21 : class CDKGSessionManager; 22 : 23 : /** 24 : * An object of this class represents a quorum which was mined on-chain (through a quorum commitment) 25 : * It at least contains information about the members and the quorum public key which is needed to verify recovered 26 : * signatures from this quorum. 27 : * 28 : * In case the local node is a member of the same quorum and successfully participated in the DKG, the quorum object 29 : * will also contain the secret key share and the quorum verification vector. The quorum vvec is then used to recover 30 : * the public key shares of individual members, which are needed to verify signature shares of these members. 31 : */ 32 : class CQuorum 33 : { 34 : friend class CQuorumManager; 35 : 36 : public: 37 : const Consensus::LLMQParams& params; 38 : CFinalCommitment qc; 39 : const CBlockIndex* pindexQuorum; 40 : uint256 minedBlockHash; 41 : std::vector<CDeterministicMNCPtr> members; 42 : 43 : // These are only valid when we either participated in the DKG or fully watched it 44 : BLSVerificationVectorPtr quorumVvec; 45 : CBLSSecretKey skShare; 46 : 47 : private: 48 : // Recovery of public key shares is very slow, so we start a background thread that pre-populates a cache so that 49 : // the public key shares are ready when needed later 50 : mutable CBLSWorkerCache blsCache; 51 : std::atomic<bool> stopCachePopulatorThread; 52 : std::thread cachePopulatorThread; 53 : 54 : public: 55 432 : CQuorum(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker) : params(_params), blsCache(_blsWorker), stopCachePopulatorThread(false) {} 56 : ~CQuorum(); 57 : void Init(const CFinalCommitment& _qc, const CBlockIndex* _pindexQuorum, const uint256& _minedBlockHash, const std::vector<CDeterministicMNCPtr>& _members); 58 : 59 : bool IsMember(const uint256& proTxHash) const; 60 : bool IsValidMember(const uint256& proTxHash) const; 61 : int GetMemberIndex(const uint256& proTxHash) const; 62 : 63 : CBLSPublicKey GetPubKeyShare(size_t memberIdx) const; 64 : CBLSSecretKey GetSkShare() const; 65 : 66 : private: 67 : void WriteContributions(CEvoDB& evoDb); 68 : bool ReadContributions(CEvoDB& evoDb); 69 : static void StartCachePopulatorThread(std::shared_ptr<CQuorum> _this); 70 : }; 71 : typedef std::shared_ptr<CQuorum> CQuorumPtr; 72 : typedef std::shared_ptr<const CQuorum> CQuorumCPtr; 73 : 74 : /** 75 : * The quorum manager maintains quorums which were mined on chain. When a quorum is requested from the manager, 76 : * it will lookup the commitment (through CQuorumBlockProcessor) and build a CQuorum object from it. 77 : * 78 : * It is also responsible for initialization of the intra-quorum connections for new quorums. 79 : */ 80 : class CQuorumManager 81 : { 82 : private: 83 : CEvoDB& evoDb; 84 : CBLSWorker& blsWorker; 85 : CDKGSessionManager& dkgManager; 86 : 87 : RecursiveMutex quorumsCacheCs; 88 : mutable std::map<Consensus::LLMQType, unordered_lru_cache<uint256, CQuorumCPtr, StaticSaltedHasher>> mapQuorumsCache; 89 : mutable std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::vector<CQuorumCPtr>, StaticSaltedHasher>> scanQuorumsCache; 90 : 91 : public: 92 : CQuorumManager(CEvoDB& _evoDb, CBLSWorker& _blsWorker, CDKGSessionManager& _dkgManager); 93 : 94 : void UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitialDownload); 95 : 96 : public: 97 : bool HasQuorum(Consensus::LLMQType llmqType, const uint256& quorumHash); 98 : 99 : // all these methods will lock cs_main 100 : CQuorumCPtr GetQuorum(Consensus::LLMQType llmqType, const uint256& quorumHash); 101 : 102 : std::vector<CQuorumCPtr> ScanQuorums(Consensus::LLMQType llmqType, size_t maxCount); 103 : 104 : // this method will not lock cs_main 105 : std::vector<CQuorumCPtr> ScanQuorums(Consensus::LLMQType llmqType, const CBlockIndex* pindexStart, size_t maxCount); 106 : 107 : private: 108 : // all these methods will not lock cs_main 109 : void EnsureQuorumConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexNew); 110 : 111 : bool BuildQuorumFromCommitment(const CFinalCommitment& qc, const CBlockIndex* pindexQuorum, const uint256& minedBlockHash, std::shared_ptr<CQuorum>& quorum) const; 112 : bool BuildQuorumContributions(const CFinalCommitment& fqc, std::shared_ptr<CQuorum>& quorum) const; 113 : 114 : CQuorumCPtr GetQuorum(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum); 115 : }; 116 : 117 : extern std::unique_ptr<CQuorumManager> quorumManager; 118 : } // namespace llmq 119 : 120 : #endif // PIVX_LLMQ_QUORUMS_H