Line data Source code
1 : // Copyright (c) 2018-2025 The Dash Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #ifndef BITCOIN_ACTIVE_DKGSESSIONHANDLER_H 6 : #define BITCOIN_ACTIVE_DKGSESSIONHANDLER_H 7 : 8 : #include <llmq/dkgsessionhandler.h> 9 : 10 : #include <gsl/pointers.h> 11 : 12 : #include <atomic> 13 : #include <exception> 14 : #include <functional> 15 : #include <memory> 16 : #include <optional> 17 : 18 : class CActiveMasternodeManager; 19 : class CBLSWorker; 20 : class CBlockIndex; 21 : class ChainstateManager; 22 : class CDeterministicMNManager; 23 : class CMasternodeMetaMan; 24 : class CSporkManager; 25 : namespace Consensus { 26 : struct LLMQParams; 27 : } // namespace Consensus 28 : namespace llmq { 29 : class CDKGSession; 30 : class CDKGDebugManager; 31 : class CDKGSessionManager; 32 : class CQuorumBlockProcessor; 33 : class CQuorumSnapshotManager; 34 : } // namespace llmq 35 : 36 : namespace llmq { 37 : //! Thrown by Wait*, Sleep* and HandlePhase to bail out of the current DKG round. 38 : class AbortPhaseException : public std::exception 39 : { 40 : }; 41 : 42 : class ActiveDKGSessionHandler final : public llmq::CDKGSessionHandler 43 : { 44 : using StartPhaseFunc = std::function<void()>; 45 : using WhileWaitFunc = std::function<bool()>; 46 : 47 : private: 48 : CBLSWorker& m_bls_worker; 49 : CDeterministicMNManager& m_dmnman; 50 : CMasternodeMetaMan& m_mn_metaman; 51 : llmq::CDKGDebugManager& m_dkgdbgman; 52 : llmq::CDKGSessionManager& m_qdkgsman; 53 : llmq::CQuorumBlockProcessor& m_qblockman; 54 : llmq::CQuorumSnapshotManager& m_qsnapman; 55 : const CActiveMasternodeManager& m_mn_activeman; 56 : const ChainstateManager& m_chainman; 57 : const CSporkManager& m_sporkman; 58 : const bool m_quorums_watch{false}; 59 : const int quorumIndex; 60 : 61 : private: 62 : std::atomic<bool> stopRequested{false}; 63 : std::atomic<int> currentHeight{-1}; 64 : std::unique_ptr<CDKGSession> curSession{nullptr}; 65 : 66 : mutable Mutex cs_phase_qhash; 67 : QuorumPhase phase GUARDED_BY(cs_phase_qhash){QuorumPhase::Idle}; 68 : uint256 quorumHash GUARDED_BY(cs_phase_qhash); 69 : 70 : public: 71 : ActiveDKGSessionHandler() = delete; 72 : ActiveDKGSessionHandler(const ActiveDKGSessionHandler&) = delete; 73 : ActiveDKGSessionHandler& operator=(const ActiveDKGSessionHandler&) = delete; 74 : ActiveDKGSessionHandler(CBLSWorker& bls_worker, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, 75 : llmq::CDKGDebugManager& dkgdbgman, llmq::CDKGSessionManager& qdkgsman, 76 : llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, 77 : const CActiveMasternodeManager& mn_activeman, const ChainstateManager& chainman, 78 : const CSporkManager& sporkman, const Consensus::LLMQParams& llmq_params, bool quorums_watch, 79 : int quorums_idx); 80 : ~ActiveDKGSessionHandler(); 81 : 82 : public: 83 : //! CDKGSessionHandler 84 : bool GetContribution(const uint256& hash, CDKGContribution& ret) const override; 85 : bool GetComplaint(const uint256& hash, CDKGComplaint& ret) const override; 86 : bool GetJustification(const uint256& hash, CDKGJustification& ret) const override; 87 : bool GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const override; 88 : QuorumPhase GetPhase() const override EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 89 : void UpdatedBlockTip(const CBlockIndex* pindexNew) override EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 90 : 91 : /* 92 : * Phase-thread interface, called by NetDKG. Wait/Sleep/HandlePhase throw 93 : * AbortPhaseException when stopRequested is set or when an unexpected 94 : * phase change is observed. 95 : */ 96 42237 : int QuorumIndex() const { return quorumIndex; } 97 4809 : bool QuorumsWatch() const { return m_quorums_watch; } 98 : uint256 GetCurrentQuorumHash() const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 99 4873 : CDKGSession* GetCurSession() { return curSession.get(); } 100 : 101 19800 : void RequestStop() { stopRequested = true; } 102 17597 : bool IsStopRequested() const { return stopRequested; } 103 : 104 : bool InitNewQuorum(gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex); 105 : 106 : /** 107 : * @param curPhase current QuorumPhase 108 : * @param nextPhase next QuorumPhase 109 : * @param expectedQuorumHash expected QuorumHash, defaults to null 110 : * @param shouldNotWait function that returns bool, defaults to function that returns false. If the function returns false, we will wait in the loop, if true, we don't wait 111 : */ 112 : void WaitForNextPhase( 113 : std::optional<QuorumPhase> curPhase, QuorumPhase nextPhase, const uint256& expectedQuorumHash = uint256(), 114 720056 : const WhileWaitFunc& shouldNotWait = [] { return false; }) const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 115 : void WaitForNewQuorum(const uint256& oldQuorumHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 116 : void SleepBeforePhase(QuorumPhase curPhase, const uint256& expectedQuorumHash, double randomSleepFactor, 117 : const WhileWaitFunc& runWhileWaiting) const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 118 : void HandlePhase(QuorumPhase curPhase, QuorumPhase nextPhase, const uint256& expectedQuorumHash, 119 : double randomSleepFactor, const StartPhaseFunc& startPhaseFunc, 120 : const WhileWaitFunc& runWhileWaiting) EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 121 : 122 : private: 123 : std::pair<QuorumPhase, uint256> GetPhaseAndQuorumHash() const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); 124 : }; 125 : 126 : } // namespace llmq 127 : 128 : #endif // BITCOIN_ACTIVE_DKGSESSIONHANDLER_H