Line data Source code
1 : // Copyright (c) 2018-2025 The Dash Core developers 2 : // Distributed under the MIT/X11 software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #ifndef BITCOIN_LLMQ_DKGSESSIONHANDLER_H 6 : #define BITCOIN_LLMQ_DKGSESSIONHANDLER_H 7 : 8 : #include <net.h> // for NodeId 9 : #include <sync.h> 10 : 11 : #include <list> 12 : #include <map> 13 : #include <memory> 14 : #include <optional> 15 : #include <string_view> 16 : #include <vector> 17 : 18 : class CDataStream; 19 : class CBlockIndex; 20 : class uint256; 21 : 22 : namespace Consensus { 23 : struct LLMQParams; 24 : } // namespace Consensus 25 : 26 : namespace llmq 27 : { 28 : class CDKGContribution; 29 : class CDKGComplaint; 30 : class CDKGJustification; 31 : class CDKGPrematureCommitment; 32 : class CDKGSessionManager; 33 : 34 : enum class QuorumPhase { 35 : Initialized = 1, 36 : Contribute, 37 : Complain, 38 : Justify, 39 : Commit, 40 : Finalize, 41 : Idle, 42 : }; 43 : 44 : /** 45 : * Acts as a FIFO queue for incoming DKG messages. The reason we need this is that deserialization of these messages 46 : * is too slow to be processed in the main message handler thread. So, instead of processing them directly from the 47 : * main handler thread, we push them into a CDKGPendingMessages object and later pop+deserialize them in the DKG phase 48 : * handler thread. 49 : * 50 : * Each message type has it's own instance of this class. 51 : */ 52 : class CDKGPendingMessages 53 : { 54 : public: 55 : using BinaryMessage = std::pair<NodeId, std::shared_ptr<CDataStream>>; 56 : 57 : private: 58 : const size_t maxMessagesPerNode; 59 : mutable Mutex cs_messages; 60 : std::list<BinaryMessage> pendingMessages GUARDED_BY(cs_messages); 61 : std::map<NodeId, size_t> messagesPerNode GUARDED_BY(cs_messages); 62 : Uint256HashSet seenMessages GUARDED_BY(cs_messages); 63 : 64 : public: 65 47952 : explicit CDKGPendingMessages(size_t _maxMessagesPerNode) : 66 47952 : maxMessagesPerNode(_maxMessagesPerNode) {}; 67 : 68 : /** 69 : * Enqueue a serialized DKG message under @p from with content hash @p hash. 70 : * Caller is responsible for hashing the payload and (for real peers) 71 : * routing the erase-request to PeerManager. Drops the message silently on 72 : * per-node capacity overflow or duplicate hash. 73 : */ 74 : void PushPendingMessage(NodeId from, std::shared_ptr<CDataStream> pm, const uint256& hash) 75 : EXCLUSIVE_LOCKS_REQUIRED(!cs_messages); 76 : 77 : std::list<BinaryMessage> PopPendingMessages(size_t maxCount) EXCLUSIVE_LOCKS_REQUIRED(!cs_messages); 78 : bool HasSeen(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_messages); 79 : void Clear() EXCLUSIVE_LOCKS_REQUIRED(!cs_messages); 80 : 81 : // Might return nullptr messages, which indicates that deserialization failed for some reason 82 : template <typename Message> 83 138536 : std::vector<std::pair<NodeId, std::shared_ptr<Message>>> PopAndDeserializeMessages(size_t maxCount) 84 : EXCLUSIVE_LOCKS_REQUIRED(!cs_messages) 85 : { 86 138536 : auto binaryMessages = PopPendingMessages(maxCount); 87 138536 : if (binaryMessages.empty()) { 88 124747 : return {}; 89 : } 90 : 91 13789 : std::vector<std::pair<NodeId, std::shared_ptr<Message>>> ret; 92 13789 : ret.reserve(binaryMessages.size()); 93 31739 : for (const auto& bm : binaryMessages) { 94 17961 : auto msg = std::make_shared<Message>(); 95 : try { 96 17960 : *bm.second >> *msg; 97 17960 : } catch (...) { 98 0 : msg = nullptr; 99 0 : } 100 17960 : ret.emplace_back(std::make_pair(bm.first, std::move(msg))); 101 17960 : } 102 : 103 13781 : return ret; 104 152329 : } 105 : }; 106 : 107 : /** 108 : * Handles multiple sequential sessions of one specific LLMQ type. There is one instance of this class per LLMQ type. 109 : */ 110 : class CDKGSessionHandler 111 : { 112 : public: 113 : const Consensus::LLMQParams& params; 114 : 115 : // Do not guard these, they protect their internals themselves 116 : CDKGPendingMessages pendingContributions; 117 : CDKGPendingMessages pendingComplaints; 118 : CDKGPendingMessages pendingJustifications; 119 : CDKGPendingMessages pendingPrematureCommitments; 120 : 121 : public: 122 : explicit CDKGSessionHandler(const Consensus::LLMQParams& _params); 123 : virtual ~CDKGSessionHandler(); 124 : 125 : void ClearPendingMessages(); 126 : 127 : public: 128 0 : virtual bool GetContribution(const uint256& hash, CDKGContribution& ret) const { return false; } 129 0 : virtual bool GetComplaint(const uint256& hash, CDKGComplaint& ret) const { return false; } 130 0 : virtual bool GetJustification(const uint256& hash, CDKGJustification& ret) const { return false; } 131 0 : virtual bool GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const { return false; } 132 0 : virtual QuorumPhase GetPhase() const { return QuorumPhase::Idle; } 133 36 : virtual void UpdatedBlockTip(const CBlockIndex* pindexNew) {} 134 : }; 135 : } // namespace llmq 136 : 137 : #endif // BITCOIN_LLMQ_DKGSESSIONHANDLER_H