diff --git a/src/active/dkgsessionhandler.cpp b/src/active/dkgsessionhandler.cpp index cea8553d48f5..c11fcd3d18cd 100644 --- a/src/active/dkgsessionhandler.cpp +++ b/src/active/dkgsessionhandler.cpp @@ -87,16 +87,23 @@ bool ActiveDKGSessionHandler::InitNewQuorum(gsl::not_null pQ return false; } - curSession = std::make_unique(m_bls_worker, m_dmnman, m_dkgdbgman, m_qdkgsman, m_mn_metaman, - m_qsnapman, m_mn_activeman, m_chainman, m_sporkman, - pQuorumBaseBlockIndex, params); + auto next_session = std::make_shared(m_bls_worker, m_dmnman, m_dkgdbgman, m_qdkgsman, + m_mn_metaman, m_qsnapman, m_mn_activeman, m_chainman, + m_sporkman, pQuorumBaseBlockIndex, params); - if (!curSession->Init(m_mn_activeman.GetProTxHash(), quorumIndex)) { + { + std::shared_ptr previous_session; + WITH_LOCK(cs_session, previous_session.swap(curSession)); + } + + if (!next_session->Init(m_mn_activeman.GetProTxHash(), quorumIndex)) { LogPrintf("ActiveDKGSessionHandler::%s -- height[%d] quorum initialization failed for %s qi[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, params.name, quorumIndex); return false; } + WITH_LOCK(cs_session, curSession = std::move(next_session)); + LogPrintf("ActiveDKGSessionHandler::%s -- height[%d] quorum initialization OK for %s qi[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, params.name, quorumIndex); return true; } @@ -166,7 +173,8 @@ void ActiveDKGSessionHandler::WaitForNewQuorum(const uint256& oldQuorumHash) con void ActiveDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase, const uint256& expectedQuorumHash, double randomSleepFactor, const WhileWaitFunc& runWhileWaiting) const { - if (!curSession->AreWeMember()) { + const auto session = GetCurSession(); + if (!session || !session->AreWeMember()) { // Non-members do not participate and do not create any network load, no need to sleep. return; } @@ -187,7 +195,7 @@ void ActiveDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase, const uint2 // Don't expect perfect block times and thus reduce the phase time to be on the secure side (caller chooses factor) double adjustedPhaseSleepTimePerMember = phaseSleepTimePerMember * randomSleepFactor; - int64_t sleepTime = static_cast(adjustedPhaseSleepTimePerMember * curSession->GetMyMemberIndex().value_or(0)); + int64_t sleepTime = static_cast(adjustedPhaseSleepTimePerMember * session->GetMyMemberIndex().value_or(0)); const auto endTime = SteadyClock::now() + std::chrono::milliseconds{sleepTime}; int heightTmp{currentHeight.load()}; int heightStart{heightTmp}; @@ -248,22 +256,31 @@ void ActiveDKGSessionHandler::HandlePhase(QuorumPhase curPhase, QuorumPhase next bool ActiveDKGSessionHandler::GetContribution(const uint256& hash, CDKGContribution& ret) const { - return curSession && curSession->GetContribution(hash, ret); + const auto session = GetCurSession(); + return session && session->GetContribution(hash, ret); } bool ActiveDKGSessionHandler::GetComplaint(const uint256& hash, CDKGComplaint& ret) const { - return curSession && curSession->GetComplaint(hash, ret); + const auto session = GetCurSession(); + return session && session->GetComplaint(hash, ret); } bool ActiveDKGSessionHandler::GetJustification(const uint256& hash, CDKGJustification& ret) const { - return curSession && curSession->GetJustification(hash, ret); + const auto session = GetCurSession(); + return session && session->GetJustification(hash, ret); } bool ActiveDKGSessionHandler::GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const { - return curSession && curSession->GetPrematureCommitment(hash, ret); + const auto session = GetCurSession(); + return session && session->GetPrematureCommitment(hash, ret); +} + +std::shared_ptr ActiveDKGSessionHandler::GetCurSession() const +{ + return WITH_LOCK(cs_session, return curSession); } QuorumPhase ActiveDKGSessionHandler::GetPhase() const diff --git a/src/active/dkgsessionhandler.h b/src/active/dkgsessionhandler.h index d6684c74c6ba..11764fe17bd1 100644 --- a/src/active/dkgsessionhandler.h +++ b/src/active/dkgsessionhandler.h @@ -61,7 +61,8 @@ class ActiveDKGSessionHandler final : public llmq::CDKGSessionHandler private: std::atomic stopRequested{false}; std::atomic currentHeight{-1}; - std::unique_ptr curSession{nullptr}; + mutable Mutex cs_session; + std::shared_ptr curSession GUARDED_BY(cs_session); mutable Mutex cs_phase_qhash; QuorumPhase phase GUARDED_BY(cs_phase_qhash){QuorumPhase::Idle}; @@ -81,10 +82,12 @@ class ActiveDKGSessionHandler final : public llmq::CDKGSessionHandler public: //! CDKGSessionHandler - bool GetContribution(const uint256& hash, CDKGContribution& ret) const override; - bool GetComplaint(const uint256& hash, CDKGComplaint& ret) const override; - bool GetJustification(const uint256& hash, CDKGJustification& ret) const override; - bool GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const override; + bool GetContribution(const uint256& hash, CDKGContribution& ret) const override EXCLUSIVE_LOCKS_REQUIRED(!cs_session); + bool GetComplaint(const uint256& hash, CDKGComplaint& ret) const override EXCLUSIVE_LOCKS_REQUIRED(!cs_session); + bool GetJustification(const uint256& hash, CDKGJustification& ret) const override + EXCLUSIVE_LOCKS_REQUIRED(!cs_session); + bool GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const override + EXCLUSIVE_LOCKS_REQUIRED(!cs_session); QuorumPhase GetPhase() const override EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); void UpdatedBlockTip(const CBlockIndex* pindexNew) override EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); @@ -96,12 +99,12 @@ class ActiveDKGSessionHandler final : public llmq::CDKGSessionHandler int QuorumIndex() const { return quorumIndex; } bool QuorumsWatch() const { return m_quorums_watch; } uint256 GetCurrentQuorumHash() const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); - CDKGSession* GetCurSession() { return curSession.get(); } + std::shared_ptr GetCurSession() const EXCLUSIVE_LOCKS_REQUIRED(!cs_session); void RequestStop() { stopRequested = true; } bool IsStopRequested() const { return stopRequested; } - bool InitNewQuorum(gsl::not_null pQuorumBaseBlockIndex); + bool InitNewQuorum(gsl::not_null pQuorumBaseBlockIndex) EXCLUSIVE_LOCKS_REQUIRED(!cs_session); /** * @param curPhase current QuorumPhase @@ -114,10 +117,11 @@ class ActiveDKGSessionHandler final : public llmq::CDKGSessionHandler const WhileWaitFunc& shouldNotWait = [] { return false; }) const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); void WaitForNewQuorum(const uint256& oldQuorumHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); void SleepBeforePhase(QuorumPhase curPhase, const uint256& expectedQuorumHash, double randomSleepFactor, - const WhileWaitFunc& runWhileWaiting) const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); + const WhileWaitFunc& runWhileWaiting) const + EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash, !cs_session); void HandlePhase(QuorumPhase curPhase, QuorumPhase nextPhase, const uint256& expectedQuorumHash, double randomSleepFactor, const StartPhaseFunc& startPhaseFunc, - const WhileWaitFunc& runWhileWaiting) EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); + const WhileWaitFunc& runWhileWaiting) EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash, !cs_session); private: std::pair GetPhaseAndQuorumHash() const EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); diff --git a/src/llmq/net_dkg.cpp b/src/llmq/net_dkg.cpp index a0c82915d96b..da1f2481a0b4 100644 --- a/src/llmq/net_dkg.cpp +++ b/src/llmq/net_dkg.cpp @@ -851,7 +851,7 @@ void NetDKG::HandleDKGRound(ActiveDKGSessionHandler& handler) active.dkgdbgman.MarkPhaseAdvanced(handler.params.type, handler.QuorumIndex(), QuorumPhase::Initialized); - auto* curSession = handler.GetCurSession(); + const auto curSession = handler.GetCurSession(); if (handler.params.is_single_member()) { auto finalCommitment = curSession->FinalizeSingleCommitment(); if (!finalCommitment.IsNull()) { // it can be null only if we are not member