diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 29a9999965..a5f8d6b1cd 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -2,16 +2,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include #include +#include +#include #include #include #include #include +#include #include -#include -#include -#include #include #include diff --git a/src/evo/creditpool.cpp b/src/evo/creditpool.cpp index 876b9bfb3a..374f45792c 100644 --- a/src/evo/creditpool.cpp +++ b/src/evo/creditpool.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include diff --git a/src/evo/creditpool.h b/src/evo/creditpool.h index 479cc77879..9f3034cbcf 100644 --- a/src/evo/creditpool.h +++ b/src/evo/creditpool.h @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -23,6 +22,7 @@ class BlockManager; class CBlockIndex; class BlockValidationState; +class CEvoDB; class TxValidationState; namespace Consensus { struct Params; diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 158de1ad78..ac167a298b 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 7d035fc2eb..3dcbdd33a4 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -8,15 +8,15 @@ #include #include +#include #include #include #include -#include #include +#include #include #include #include -#include #include @@ -30,6 +30,7 @@ class CBlock; class CBlockIndex; class CChainState; class CConnman; +class CEvoDB; class TxValidationState; extern RecursiveMutex cs_main; diff --git a/src/evo/mnhftx.cpp b/src/evo/mnhftx.cpp index 22b95062b1..a7a953db58 100644 --- a/src/evo/mnhftx.cpp +++ b/src/evo/mnhftx.cpp @@ -4,11 +4,12 @@ #include #include +#include #include #include #include -#include #include +#include #include #include diff --git a/src/init.cpp b/src/init.cpp index 81f05e48fd..fe971a52cc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -90,6 +90,7 @@ #include #include +#include #include #include #include diff --git a/src/llmq/chainlocks.h b/src/llmq/chainlocks.h index f229f5b608..79f96ccb68 100644 --- a/src/llmq/chainlocks.h +++ b/src/llmq/chainlocks.h @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -36,6 +35,7 @@ namespace llmq { class CSigningManager; class CSigSharesManager; +enum class VerifyRecSigStatus; class CChainLocksHandler : public CRecoveredSigsListener { diff --git a/src/llmq/dkgsession.cpp b/src/llmq/dkgsession.cpp index b5f393d4d2..d59e7defee 100644 --- a/src/llmq/dkgsession.cpp +++ b/src/llmq/dkgsession.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -33,14 +32,13 @@ namespace llmq { -class CDKGLogger : public CBatchedLogger +CDKGLogger::CDKGLogger(const CDKGSession& _quorumDkg, std::string_view _func, int source_line) : + CBatchedLogger(BCLog::LLMQ_DKG, + strprintf("QuorumDKG(type=%s, qIndex=%d, h=%d, member=%d)", _quorumDkg.params.name, _quorumDkg.quorumIndex, + _quorumDkg.m_quorum_base_block_index->nHeight, _quorumDkg.AreWeMember()), + __FILE__, source_line) { -public: - CDKGLogger(const CDKGSession& _quorumDkg, std::string_view _func, int source_line) : - CDKGLogger(_quorumDkg.params.name, _quorumDkg.quorumIndex, _quorumDkg.m_quorum_base_block_index->GetBlockHash(), _quorumDkg.m_quorum_base_block_index->nHeight, _quorumDkg.AreWeMember(), _func, source_line){}; - CDKGLogger(std::string_view _llmqTypeName, int _quorumIndex, const uint256& _quorumHash, int _height, bool _areWeMember, std::string_view _func, int source_line) : - CBatchedLogger(BCLog::LLMQ_DKG, strprintf("QuorumDKG(type=%s, qIndex=%d, h=%d, member=%d)", _llmqTypeName, _quorumIndex, _height, _areWeMember), __FILE__, source_line){}; -}; +} static std::array, ToUnderlying(DKGError::type::_COUNT)> simDkgErrorMap{}; @@ -73,9 +71,28 @@ CDKGMember::CDKGMember(const CDeterministicMNCPtr& _dmn, size_t _idx) : } -bool CDKGSession::Init(gsl::not_null _pQuorumBaseBlockIndex, Span mns, const uint256& _myProTxHash, int _quorumIndex) +CDKGSession::CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params, + CBLSWorker& _blsWorker, CConnman& _connman, CDeterministicMNManager& dmnman, + CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, + CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman, + const CSporkManager& sporkman) : + params(_params), + blsWorker(_blsWorker), + cache(_blsWorker), + connman(_connman), + m_dmnman(dmnman), + dkgManager(_dkgManager), + dkgDebugManager(_dkgDebugManager), + m_mn_metaman(mn_metaman), + m_mn_activeman(mn_activeman), + m_sporkman(sporkman), + m_quorum_base_block_index{pQuorumBaseBlockIndex} { - m_quorum_base_block_index = _pQuorumBaseBlockIndex; +} + +bool CDKGSession::Init(const uint256& _myProTxHash, int _quorumIndex) +{ + const auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, m_quorum_base_block_index); quorumIndex = _quorumIndex; members.resize(mns.size()); memberIds.resize(members.size()); @@ -259,12 +276,10 @@ bool CDKGSession::PreVerifyMessage(const CDKGContribution& qc, bool& retBan) con return true; } -void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) +std::optional CDKGSession::ReceiveMessage(const CDKGContribution& qc) { CDKGLogger logger(*this, __func__, __LINE__); - retBan = false; - auto* member = GetMember(qc.proTxHash); cxxtimer::Timer t1(true); @@ -275,7 +290,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) if (member->contributions.size() >= 2) { // only relay up to 2 contributions, that's enough to let the other members know about his bad behavior - return; + return std::nullopt; } const uint256 hash = ::SerializeHash(qc); @@ -283,7 +298,6 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) member->contributions.emplace(hash); CInv inv(MSG_QUORUM_CONTRIB, hash); - RelayInvToParticipants(inv); dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) { status.statusBits.receivedContribution = true; @@ -295,7 +309,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) // so others know about his bad behavior MarkBadMember(member->idx); logger.Batch("%s did send multiple contributions", member->dmn->proTxHash.ToString()); - return; + return inv; } receivedVvecs[member->idx] = qc.vvec; @@ -308,7 +322,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) if (!AreWeMember()) { // can't further validate - return; + return inv; } dkgManager.WriteVerifiedVvecContribution(params.type, m_quorum_base_block_index, qc.proTxHash, qc.vvec); @@ -329,7 +343,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) status.statusBits.weComplain = true; return true; }); - return; + return inv; } logger.Batch("decrypted our contribution share. time=%d", t2.count()); @@ -341,6 +355,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) if (pendingContributionVerifications.size() >= 32) { VerifyPendingContributions(); } + return inv; } // Verifies all pending secret key contributions in one batch @@ -569,19 +584,17 @@ bool CDKGSession::PreVerifyMessage(const CDKGComplaint& qc, bool& retBan) const return true; } -void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan) +std::optional CDKGSession::ReceiveMessage(const CDKGComplaint& qc) { CDKGLogger logger(*this, __func__, __LINE__); - retBan = false; - logger.Batch("received complaint from %s", qc.proTxHash.ToString()); auto* member = GetMember(qc.proTxHash); if (member->complaints.size() >= 2) { // only relay up to 2 complaints, that's enough to let the other members know about his bad behavior - return; + return std::nullopt; } const uint256 hash = ::SerializeHash(qc); @@ -589,7 +602,6 @@ void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan) member->complaints.emplace(hash); CInv inv(MSG_QUORUM_COMPLAINT, hash); - RelayInvToParticipants(inv); dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) { status.statusBits.receivedComplaint = true; @@ -601,7 +613,7 @@ void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan) // so others know about his bad behavior MarkBadMember(member->idx); logger.Batch("%s did send multiple complaints", member->dmn->proTxHash.ToString()); - return; + return inv; } int receivedCount = 0; @@ -630,6 +642,7 @@ void CDKGSession::ReceiveMessage(const CDKGComplaint& qc, bool& retBan) } logger.Batch("received and relayed complaint. received=%d", receivedCount); + return inv; } void CDKGSession::VerifyAndJustify(CDKGPendingMessages& pendingMessages) @@ -780,19 +793,17 @@ bool CDKGSession::PreVerifyMessage(const CDKGJustification& qj, bool& retBan) co return true; } -void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan) +std::optional CDKGSession::ReceiveMessage(const CDKGJustification& qj) { CDKGLogger logger(*this, __func__, __LINE__); - retBan = false; - logger.Batch("received justification from %s", qj.proTxHash.ToString()); auto* member = GetMember(qj.proTxHash); if (member->justifications.size() >= 2) { // only relay up to 2 justifications, that's enough to let the other members know about his bad behavior - return; + return std::nullopt; } const uint256 hash = ::SerializeHash(qj); @@ -801,7 +812,6 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan) // we always relay, even if further verification fails CInv inv(MSG_QUORUM_JUSTIFICATION, hash); - RelayInvToParticipants(inv); dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) { status.statusBits.receivedJustification = true; @@ -813,13 +823,13 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan) // so others know about his bad behavior logger.Batch("%s did send multiple justifications", member->dmn->proTxHash.ToString()); MarkBadMember(member->idx); - return; + return inv; } if (member->bad) { // we locally determined him to be bad (sent none or more then one contributions) // don't give him a second chance (but we relay the justification in case other members disagree) - return; + return inv; } for (const auto& p : qj.contributions) { @@ -832,7 +842,7 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan) } } if (member->bad) { - return; + return inv; } cxxtimer::Timer t1(true); @@ -872,6 +882,7 @@ void CDKGSession::ReceiveMessage(const CDKGJustification& qj, bool& retBan) }); logger.Batch("verified justification: received=%d/%d time=%d", receivedCount, expectedCount, t1.count()); + return inv; } void CDKGSession::VerifyAndCommit(CDKGPendingMessages& pendingMessages) @@ -1095,12 +1106,10 @@ bool CDKGSession::PreVerifyMessage(const CDKGPrematureCommitment& qc, bool& retB return true; } -void CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan) +std::optional CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc) { CDKGLogger logger(*this, __func__, __LINE__); - retBan = false; - cxxtimer::Timer t1(true); logger.Batch("received premature commitment from %s. validMembers=%d", qc.proTxHash.ToString(), qc.CountValidMembers()); @@ -1137,30 +1146,29 @@ void CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan if ((*quorumVvec)[0] != qc.quorumPublicKey) { logger.Batch("calculated quorum public key does not match"); - return; + return std::nullopt; } uint256 vvecHash = ::SerializeHash(*quorumVvec); if (qc.quorumVvecHash != vvecHash) { logger.Batch("calculated quorum vvec hash does not match"); - return; + return std::nullopt; } CBLSPublicKey pubKeyShare = cache.BuildPubKeyShare(::SerializeHash(std::make_pair(memberIndexes, member->id)), quorumVvec, member->id); if (!pubKeyShare.IsValid()) { logger.Batch("failed to calculate public key share"); - return; + return std::nullopt; } if (!qc.quorumSig.VerifyInsecure(pubKeyShare, qc.GetSignHash())) { logger.Batch("failed to verify quorumSig"); - return; + return std::nullopt; } } WITH_LOCK(invCs, validCommitments.emplace(hash)); CInv inv(MSG_QUORUM_PREMATURE_COMMITMENT, hash); - RelayInvToParticipants(inv); dkgDebugManager.UpdateLocalMemberStatus(params.type, quorumIndex, member->idx, [&](CDKGDebugMemberStatus& status) { status.statusBits.receivedPrematureCommitment = true; @@ -1172,6 +1180,7 @@ void CDKGSession::ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan t1.stop(); logger.Batch("verified premature commitment. received=%d/%d, time=%d", receivedCount, members.size(), t1.count()); + return inv; } std::vector CDKGSession::FinalizeCommitments() @@ -1304,41 +1313,5 @@ void CDKGSession::MarkBadMember(size_t idx) member->bad = true; } -void CDKGSession::RelayInvToParticipants(const CInv& inv) const -{ - CDKGLogger logger(*this, __func__, __LINE__); - std::stringstream ss; - for (const auto& r : relayMembers) { - ss << r.ToString().substr(0, 4) << " | "; - } - logger.Batch("RelayInvToParticipants inv[%s] relayMembers[%d] GetNodeCount[%d] GetNetworkActive[%d] HasMasternodeQuorumNodes[%d] for quorumHash[%s] forMember[%s] relayMembers[%s]", - inv.ToString(), - relayMembers.size(), - connman.GetNodeCount(ConnectionDirection::Both), - connman.GetNetworkActive(), - connman.HasMasternodeQuorumNodes(params.type, m_quorum_base_block_index->GetBlockHash()), - m_quorum_base_block_index->GetBlockHash().ToString(), - myProTxHash.ToString().substr(0, 4), ss.str()); - - std::stringstream ss2; - connman.ForEachNode([&](const CNode* pnode) { - if (pnode->qwatch || - (!pnode->GetVerifiedProRegTxHash().IsNull() && (relayMembers.count(pnode->GetVerifiedProRegTxHash()) != 0))) { - Assert(m_peerman)->PushInventory(pnode->GetId(), inv); - } - - if (pnode->GetVerifiedProRegTxHash().IsNull()) { - logger.Batch("node[%d:%s] not mn", - pnode->GetId(), - pnode->m_addr_name); - } else if (relayMembers.count(pnode->GetVerifiedProRegTxHash()) == 0) { - ss2 << pnode->GetVerifiedProRegTxHash().ToString().substr(0, 4) << " | "; - } - }); - logger.Batch("forMember[%s] NOTrelayMembers[%s]", - myProTxHash.ToString().substr(0, 4), - ss2.str()); - logger.Flush(); -} } // namespace llmq diff --git a/src/llmq/dkgsession.h b/src/llmq/dkgsession.h index c16a741874..72cf7f714b 100644 --- a/src/llmq/dkgsession.h +++ b/src/llmq/dkgsession.h @@ -5,13 +5,14 @@ #ifndef BITCOIN_LLMQ_DKGSESSION_H #define BITCOIN_LLMQ_DKGSESSION_H +#include + +#include #include #include #include - -#include -#include #include +#include #include @@ -22,7 +23,6 @@ class CDeterministicMN; class CMasternodeMetaMan; class CSporkManager; class UniValue; -class PeerManager; using CDeterministicMNCPtr = std::shared_ptr; @@ -249,6 +249,12 @@ public: } }; +class CDKGLogger : public CBatchedLogger +{ +public: + CDKGLogger(const CDKGSession& _quorumDkg, std::string_view _func, int source_line); +}; + /** * The DKG session is a single instance of the DKG process. It is owned and called by CDKGSessionHandler, which passes * received DKG messages to the session. The session is not persistent and will loose it's state (the whole object is @@ -281,9 +287,8 @@ private: CMasternodeMetaMan& m_mn_metaman; const CActiveMasternodeManager* const m_mn_activeman; const CSporkManager& m_sporkman; - const std::unique_ptr& m_peerman; - const CBlockIndex* m_quorum_base_block_index{nullptr}; + const CBlockIndex* const m_quorum_base_block_index; int quorumIndex{0}; private: @@ -321,15 +326,13 @@ private: std::set validCommitments GUARDED_BY(invCs); public: - CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CConnman& _connman, - CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, - CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman, - const CSporkManager& sporkman, const std::unique_ptr& peerman) : - params(_params), blsWorker(_blsWorker), cache(_blsWorker), connman(_connman), m_dmnman(dmnman), dkgManager(_dkgManager), - dkgDebugManager(_dkgDebugManager), m_mn_metaman(mn_metaman), m_mn_activeman(mn_activeman), m_sporkman(sporkman), - m_peerman(peerman) {} + CDKGSession(const CBlockIndex* pQuorumBaseBlockIndex, const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, + CConnman& _connman, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, + CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, + const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman); - bool Init(gsl::not_null pQuorumBaseBlockIndex, Span mns, const uint256& _myProTxHash, int _quorumIndex); + // TODO: remove Init completely + bool Init(const uint256& _myProTxHash, int _quorumIndex); [[nodiscard]] std::optional GetMyMemberIndex() const { return myIdx; } @@ -350,7 +353,7 @@ public: void Contribute(CDKGPendingMessages& pendingMessages); void SendContributions(CDKGPendingMessages& pendingMessages); bool PreVerifyMessage(const CDKGContribution& qc, bool& retBan) const; - void ReceiveMessage(const CDKGContribution& qc, bool& retBan); + std::optional ReceiveMessage(const CDKGContribution& qc); void VerifyPendingContributions() EXCLUSIVE_LOCKS_REQUIRED(cs_pending); // Phase 2: complaint @@ -358,19 +361,19 @@ public: void VerifyConnectionAndMinProtoVersions() const; void SendComplaint(CDKGPendingMessages& pendingMessages); bool PreVerifyMessage(const CDKGComplaint& qc, bool& retBan) const; - void ReceiveMessage(const CDKGComplaint& qc, bool& retBan); + std::optional ReceiveMessage(const CDKGComplaint& qc); // Phase 3: justification void VerifyAndJustify(CDKGPendingMessages& pendingMessages); void SendJustification(CDKGPendingMessages& pendingMessages, const std::set& forMembers); bool PreVerifyMessage(const CDKGJustification& qj, bool& retBan) const; - void ReceiveMessage(const CDKGJustification& qj, bool& retBan); + std::optional ReceiveMessage(const CDKGJustification& qj); // Phase 4: commit void VerifyAndCommit(CDKGPendingMessages& pendingMessages); void SendCommitment(CDKGPendingMessages& pendingMessages); bool PreVerifyMessage(const CDKGPrematureCommitment& qc, bool& retBan) const; - void ReceiveMessage(const CDKGPrematureCommitment& qc, bool& retBan); + std::optional ReceiveMessage(const CDKGPrematureCommitment& qc); // Phase 5: aggregate/finalize std::vector FinalizeCommitments(); @@ -378,10 +381,12 @@ public: [[nodiscard]] bool AreWeMember() const { return !myProTxHash.IsNull(); } void MarkBadMember(size_t idx); - void RelayInvToParticipants(const CInv& inv) const; - public: [[nodiscard]] CDKGMember* GetMember(const uint256& proTxHash) const; + [[nodiscard]] const std::set& RelayMembers() const { return relayMembers; } + [[nodiscard]] const CBlockIndex* BlockIndex() const { return m_quorum_base_block_index; } + [[nodiscard]] const uint256& ProTx() const { return myProTxHash; } + [[nodiscard]] const Consensus::LLMQParams GetParams() const { return params; } private: [[nodiscard]] bool ShouldSimulateError(DKGError::type type) const; diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index 7b4b8c4ab2..661cafdcad 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -24,34 +24,42 @@ namespace llmq { -CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, - CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, - CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, - const CSporkManager& sporkman, const std::unique_ptr& peerman, const Consensus::LLMQParams& _params, int _quorumIndex) : - blsWorker(_blsWorker), - m_chainstate(chainstate), - connman(_connman), - m_dmnman(dmnman), - dkgDebugManager(_dkgDebugManager), - dkgManager(_dkgManager), - m_mn_metaman(mn_metaman), - quorumBlockProcessor(_quorumBlockProcessor), - m_mn_activeman(mn_activeman), - m_sporkman(sporkman), - m_peerman(peerman), - params(_params), - quorumIndex(_quorumIndex), - curSession(std::make_unique(_params, _blsWorker, _connman, dmnman, _dkgManager, _dkgDebugManager, m_mn_metaman, m_mn_activeman, sporkman, peerman)), - pendingContributions((size_t)_params.size * 2, MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages) - pendingComplaints((size_t)_params.size * 2, MSG_QUORUM_COMPLAINT), - pendingJustifications((size_t)_params.size * 2, MSG_QUORUM_JUSTIFICATION), - pendingPrematureCommitments((size_t)_params.size * 2, MSG_QUORUM_PREMATURE_COMMITMENT) +CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, + CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, + CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, + CQuorumBlockProcessor& _quorumBlockProcessor, + const CActiveMasternodeManager* const mn_activeman, + const CSporkManager& sporkman, const std::unique_ptr& peerman, + const Consensus::LLMQParams& _params, int _quorumIndex) : + blsWorker(_blsWorker), + m_chainstate(chainstate), + connman(_connman), + m_dmnman(dmnman), + dkgDebugManager(_dkgDebugManager), + dkgManager(_dkgManager), + m_mn_metaman(mn_metaman), + quorumBlockProcessor(_quorumBlockProcessor), + m_mn_activeman(mn_activeman), + m_sporkman(sporkman), + m_peerman(peerman), + params(_params), + quorumIndex(_quorumIndex), + curSession(std::make_unique(nullptr, _params, _blsWorker, _connman, dmnman, _dkgManager, + _dkgDebugManager, m_mn_metaman, m_mn_activeman, sporkman)), + pendingContributions( + (size_t)_params.size * 2, + MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages) + pendingComplaints((size_t)_params.size * 2, MSG_QUORUM_COMPLAINT), + pendingJustifications((size_t)_params.size * 2, MSG_QUORUM_JUSTIFICATION), + pendingPrematureCommitments((size_t)_params.size * 2, MSG_QUORUM_PREMATURE_COMMITMENT) { if (params.type == Consensus::LLMQType::LLMQ_NONE) { throw std::runtime_error("Can't initialize CDKGSessionHandler with LLMQ_NONE type."); } } +CDKGSessionHandler::~CDKGSessionHandler() = default; + void CDKGPendingMessages::PushPendingMessage(NodeId from, PeerManager* peerman, CDataStream& vRecv) { // if peer is not -1 we should always pass valid peerman @@ -188,15 +196,16 @@ void CDKGSessionHandler::StopThread() bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex) { - curSession = std::make_unique(params, blsWorker, connman, m_dmnman, dkgManager, dkgDebugManager, m_mn_metaman, m_mn_activeman, m_sporkman, m_peerman); - if (!DeploymentDIP0003Enforced(pQuorumBaseBlockIndex->nHeight, Params().GetConsensus())) { return false; } - auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, pQuorumBaseBlockIndex); - if (!curSession->Init(pQuorumBaseBlockIndex, mns, m_mn_activeman->GetProTxHash(), quorumIndex)) { - LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d] mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex, mns.size()); + curSession = std::make_unique(pQuorumBaseBlockIndex, params, blsWorker, connman, m_dmnman, dkgManager, + dkgDebugManager, m_mn_metaman, m_mn_activeman, m_sporkman); + + if (!curSession->Init(m_mn_activeman->GetProTxHash(), quorumIndex)) { + LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d]\n", __func__, + pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex); return false; } @@ -436,8 +445,40 @@ std::set BatchVerifyMessageSigs(CDKGSession& session, const std::vector< return ret; } -template -bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendingMessages, size_t maxCount) +static void RelayInvToParticipants(const CDKGSession& session, CConnman& connman, PeerManager& peerman, const CInv& inv) +{ + CDKGLogger logger(session, __func__, __LINE__); + std::stringstream ss; + const auto& relayMembers = session.RelayMembers(); + for (const auto& r : relayMembers) { + ss << r.ToString().substr(0, 4) << " | "; + } + logger.Batch("RelayInvToParticipants inv[%s] relayMembers[%d] GetNodeCount[%d] GetNetworkActive[%d] " + "HasMasternodeQuorumNodes[%d] for quorumHash[%s] forMember[%s] relayMembers[%s]", + inv.ToString(), relayMembers.size(), connman.GetNodeCount(ConnectionDirection::Both), + connman.GetNetworkActive(), + connman.HasMasternodeQuorumNodes(session.GetParams().type, session.BlockIndex()->GetBlockHash()), + session.BlockIndex()->GetBlockHash().ToString(), session.ProTx().ToString().substr(0, 4), ss.str()); + + std::stringstream ss2; + connman.ForEachNode([&](const CNode* pnode) { + if (pnode->qwatch || + (!pnode->GetVerifiedProRegTxHash().IsNull() && (relayMembers.count(pnode->GetVerifiedProRegTxHash()) != 0))) { + peerman.PushInventory(pnode->GetId(), inv); + } + + if (pnode->GetVerifiedProRegTxHash().IsNull()) { + logger.Batch("node[%d:%s] not mn", pnode->GetId(), pnode->m_addr_name); + } else if (relayMembers.count(pnode->GetVerifiedProRegTxHash()) == 0) { + ss2 << pnode->GetVerifiedProRegTxHash().ToString().substr(0, 4) << " | "; + } + }); + logger.Batch("forMember[%s] NOTrelayMembers[%s]", session.ProTx().ToString().substr(0, 4), ss2.str()); + logger.Flush(); +} +template +bool ProcessPendingMessageBatch(CConnman& connman, PeerManager* peerman, CDKGSession& session, + CDKGPendingMessages& pendingMessages, size_t maxCount) { auto msgs = pendingMessages.PopAndDeserializeMessages(maxCount); if (msgs.empty()) { @@ -487,12 +528,9 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi if (badNodes.count(nodeId)) { continue; } - bool ban = false; - session.ReceiveMessage(*p.second, ban); - if (ban) { - LogPrint(BCLog::LLMQ_DKG, "%s -- banning node after ReceiveMessage failed, peer=%d\n", __func__, nodeId); - pendingMessages.Misbehaving(nodeId, 100); - badNodes.emplace(nodeId); + const std::optional inv = session.ReceiveMessage(*p.second); + if (inv && peerman) { + RelayInvToParticipants(session, connman, *peerman, *inv); } } @@ -536,7 +574,8 @@ void CDKGSessionHandler::HandleDKGRound() curSession->Contribute(pendingContributions); }; auto fContributeWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingContributions, 8); + return ProcessPendingMessageBatch(connman, m_peerman.get(), *curSession, + pendingContributions, 8); }; HandlePhase(QuorumPhase::Contribute, QuorumPhase::Complain, curQuorumHash, 0.05, fContributeStart, fContributeWait); @@ -545,7 +584,8 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndComplain(pendingComplaints); }; auto fComplainWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingComplaints, 8); + return ProcessPendingMessageBatch(connman, m_peerman.get(), *curSession, + pendingComplaints, 8); }; HandlePhase(QuorumPhase::Complain, QuorumPhase::Justify, curQuorumHash, 0.05, fComplainStart, fComplainWait); @@ -554,7 +594,9 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndJustify(pendingJustifications); }; auto fJustifyWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingJustifications, 8); + return ProcessPendingMessageBatch(connman, m_peerman.get(), + *curSession, + pendingJustifications, 8); }; HandlePhase(QuorumPhase::Justify, QuorumPhase::Commit, curQuorumHash, 0.05, fJustifyStart, fJustifyWait); @@ -563,7 +605,8 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndCommit(pendingPrematureCommitments); }; auto fCommitWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingPrematureCommitments, 8); + return ProcessPendingMessageBatch( + connman, m_peerman.get(), *curSession, pendingPrematureCommitments, 8); }; HandlePhase(QuorumPhase::Commit, QuorumPhase::Finalize, curQuorumHash, 0.1, fCommitStart, fCommitWait); @@ -589,4 +632,48 @@ void CDKGSessionHandler::PhaseHandlerThread() } } +bool CDKGSessionHandler::GetContribution(const uint256& hash, CDKGContribution& ret) const +{ + LOCK(curSession->invCs); + auto it = curSession->contributions.find(hash); + if (it != curSession->contributions.end()) { + ret = it->second; + return true; + } + return false; +} + +bool CDKGSessionHandler::GetComplaint(const uint256& hash, CDKGComplaint& ret) const +{ + LOCK(curSession->invCs); + auto it = curSession->complaints.find(hash); + if (it != curSession->complaints.end()) { + ret = it->second; + return true; + } + return false; +} + +bool CDKGSessionHandler::GetJustification(const uint256& hash, CDKGJustification& ret) const +{ + LOCK(curSession->invCs); + auto it = curSession->justifications.find(hash); + if (it != curSession->justifications.end()) { + ret = it->second; + return true; + } + return false; +} + +bool CDKGSessionHandler::GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const +{ + LOCK(curSession->invCs); + auto it = curSession->prematureCommitments.find(hash); + if (it != curSession->prematureCommitments.end() && curSession->validCommitments.count(hash)) { + ret = it->second; + return true; + } + return false; +} + } // namespace llmq diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index 3ffedf0d6f..9abd982efe 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -25,6 +25,10 @@ class PeerManager; namespace llmq { +class CDKGContribution; +class CDKGComplaint; +class CDKGJustification; +class CDKGPrematureCommitment; class CDKGDebugManager; class CDKGSession; class CDKGSessionManager; @@ -153,7 +157,7 @@ public: CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, const std::unique_ptr& peerman, const Consensus::LLMQParams& _params, int _quorumIndex); - ~CDKGSessionHandler() = default; + ~CDKGSessionHandler(); void UpdatedBlockTip(const CBlockIndex *pindexNew); void ProcessMessage(const CNode& pfrom, gsl::not_null peerman, const std::string& msg_type, CDataStream& vRecv); @@ -161,6 +165,11 @@ public: void StartThread(); void StopThread(); + bool GetContribution(const uint256& hash, CDKGContribution& ret) const; + bool GetComplaint(const uint256& hash, CDKGComplaint& ret) const; + bool GetJustification(const uint256& hash, CDKGJustification& ret) const; + bool GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const; + private: bool InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex); diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index eefaeaef18..1743f0376c 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -56,6 +56,8 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai } } +CDKGSessionManager::~CDKGSessionManager() = default; + void CDKGSessionManager::MigrateDKG() { if (!db->IsEmpty()) return; @@ -297,10 +299,7 @@ bool CDKGSessionManager::GetContribution(const uint256& hash, CDKGContribution& if (dkgType.phase < QuorumPhase::Initialized || dkgType.phase > QuorumPhase::Contribute) { continue; } - LOCK(dkgType.curSession->invCs); - auto it = dkgType.curSession->contributions.find(hash); - if (it != dkgType.curSession->contributions.end()) { - ret = it->second; + if (dkgType.GetContribution(hash, ret)) { return true; } } @@ -318,10 +317,7 @@ bool CDKGSessionManager::GetComplaint(const uint256& hash, CDKGComplaint& ret) c if (dkgType.phase < QuorumPhase::Contribute || dkgType.phase > QuorumPhase::Complain) { continue; } - LOCK(dkgType.curSession->invCs); - auto it = dkgType.curSession->complaints.find(hash); - if (it != dkgType.curSession->complaints.end()) { - ret = it->second; + if (dkgType.GetComplaint(hash, ret)) { return true; } } @@ -339,10 +335,7 @@ bool CDKGSessionManager::GetJustification(const uint256& hash, CDKGJustification if (dkgType.phase < QuorumPhase::Complain || dkgType.phase > QuorumPhase::Justify) { continue; } - LOCK(dkgType.curSession->invCs); - auto it = dkgType.curSession->justifications.find(hash); - if (it != dkgType.curSession->justifications.end()) { - ret = it->second; + if (dkgType.GetJustification(hash, ret)) { return true; } } @@ -360,10 +353,7 @@ bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematu if (dkgType.phase < QuorumPhase::Justify || dkgType.phase > QuorumPhase::Commit) { continue; } - LOCK(dkgType.curSession->invCs); - auto it = dkgType.curSession->prematureCommitments.find(hash); - if (it != dkgType.curSession->prematureCommitments.end() && dkgType.curSession->validCommitments.count(hash)) { - ret = it->second; + if (dkgType.GetPrematureCommitment(hash, ret)) { return true; } } diff --git a/src/llmq/dkgsessionmgr.h b/src/llmq/dkgsessionmgr.h index 92094063a8..8c1ddea339 100644 --- a/src/llmq/dkgsessionmgr.h +++ b/src/llmq/dkgsessionmgr.h @@ -5,10 +5,10 @@ #ifndef BITCOIN_LLMQ_DKGSESSIONMGR_H #define BITCOIN_LLMQ_DKGSESSIONMGR_H -#include -#include #include +#include #include +#include #include #include @@ -23,6 +23,10 @@ class CDKGDebugManager; class CMasternodeMetaMan; class CSporkManager; class PeerManager; +class CDKGContribution; +class CDKGComplaint; +class CDKGJustification; +class CDKGPrematureCommitment; class UniValue; @@ -71,7 +75,7 @@ public: CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, const CSporkManager& sporkman, const std::unique_ptr& peerman, bool unitTests, bool fWipe); - ~CDKGSessionManager() = default; + ~CDKGSessionManager(); void StartThreads(); void StopThreads(); diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 6fc79b82a1..ada778def1 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -11,10 +11,12 @@ #include #include -#include #include +#include +#include #include +#include #include #include #include @@ -230,6 +232,8 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, MigrateOldQuorumDB(_evoDb); } +CQuorumManager::~CQuorumManager() { Stop(); } + void CQuorumManager::Start() { int workerCount = std::thread::hardware_concurrency() / 2; diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index be377e357f..4756011e14 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -26,8 +25,11 @@ class CActiveMasternodeManager; class CBlockIndex; class CChainState; class CConnman; +class CDataStream; class CDeterministicMN; class CDeterministicMNManager; +class CDBWrapper; +class CEvoDB; class CMasternodeSync; class CNode; class CSporkManager; @@ -258,7 +260,7 @@ public: CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, const CSporkManager& sporkman, bool unit_tests, bool wipe); - ~CQuorumManager() { Stop(); }; + ~CQuorumManager(); void Start(); void Stop(); diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index 1224eae2d7..7b349fb31d 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -4,6 +4,7 @@ #include +#include #include #include diff --git a/src/llmq/snapshot.h b/src/llmq/snapshot.h index b108e3f8ff..4113e255cc 100644 --- a/src/llmq/snapshot.h +++ b/src/llmq/snapshot.h @@ -5,7 +5,6 @@ #ifndef BITCOIN_LLMQ_SNAPSHOT_H #define BITCOIN_LLMQ_SNAPSHOT_H -#include #include #include #include @@ -20,6 +19,7 @@ class CBlockIndex; class CDeterministicMN; class CDeterministicMNList; +class CEvoDb; namespace llmq { class CQuorumBlockProcessor; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 4ea95ac0ca..1c9df71e79 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index 603f79baf9..90417d9138 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -62,7 +62,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "banman -> bloom -> evo/assetlocktx -> llmq/quorums -> net -> banman" "banman -> bloom -> evo/assetlocktx -> llmq/signing -> net_processing -> banman" - "llmq/dkgsession -> llmq/dkgsessionmgr -> llmq/dkgsession" "llmq/chainlocks -> validation -> llmq/chainlocks" "coinjoin/coinjoin -> llmq/chainlocks -> net -> coinjoin/coinjoin" "evo/deterministicmns -> llmq/utils -> llmq/snapshot -> evo/simplifiedmns -> evo/deterministicmns" @@ -94,7 +93,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "llmq/context -> llmq/ehf_signals -> net_processing -> llmq/context" "llmq/blockprocessor -> net_processing -> llmq/blockprocessor" "llmq/chainlocks -> net_processing -> llmq/chainlocks" - "llmq/dkgsession -> net_processing -> llmq/quorums -> llmq/dkgsession" "net_processing -> spork -> net_processing" "evo/simplifiedmns -> llmq/blockprocessor -> net_processing -> evo/simplifiedmns" "governance/governance -> net_processing -> governance/governance"