From f1f1d6392b397b46e7fd9352cae406e258f9e5c8 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Wed, 26 Apr 2023 15:33:26 +0000 Subject: [PATCH 01/10] net: pass PeerLogicValidation to LLMQ objects --- src/init.cpp | 2 +- src/llmq/blockprocessor.cpp | 4 ++-- src/llmq/blockprocessor.h | 5 ++++- src/llmq/chainlocks.cpp | 6 +++++- src/llmq/chainlocks.h | 13 ++++++++++--- src/llmq/context.cpp | 24 +++++++++++++----------- src/llmq/context.h | 7 +++++-- src/llmq/dkgsessionhandler.cpp | 14 ++++++++------ src/llmq/dkgsessionhandler.h | 6 +++++- src/llmq/dkgsessionmgr.cpp | 15 +++++++++++---- src/llmq/dkgsessionmgr.h | 10 ++++++++-- src/llmq/instantsend.h | 10 +++++++--- src/llmq/quorums.cpp | 6 ++++-- src/llmq/quorums.h | 13 ++++++++----- src/llmq/signing.cpp | 6 ++++-- src/llmq/signing.h | 9 +++++++-- src/llmq/signing_shares.h | 9 +++++++-- src/test/util/setup_common.cpp | 2 +- 18 files changed, 110 insertions(+), 51 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 09d8e3d96787..b6418b319179 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2028,7 +2028,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc llmq::quorumSnapshotManager.reset(); llmq::quorumSnapshotManager.reset(new llmq::CQuorumSnapshotManager(*node.evodb)); node.llmq_ctx.reset(); - node.llmq_ctx.reset(new LLMQContext(*node.evodb, *node.mempool, *node.connman, *::sporkManager, false, fReset || fReindexChainState)); + node.llmq_ctx.reset(new LLMQContext(*node.evodb, *node.mempool, *node.connman, *::sporkManager, node.peer_logic, false, fReset || fReindexChainState)); if (fReset) { pblocktree->WriteReindexing(true); diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index 606ae15cf5c5..69c934ea0896 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -36,8 +36,8 @@ static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT_Q_INDEXED = "q_m static const std::string DB_BEST_BLOCK_UPGRADE = "q_bbu2"; -CQuorumBlockProcessor::CQuorumBlockProcessor(CEvoDB& evoDb, CConnman& _connman) : - m_evoDb(evoDb), connman(_connman) +CQuorumBlockProcessor::CQuorumBlockProcessor(CEvoDB& evoDb, CConnman& _connman, const std::unique_ptr& peer_logic) : + m_evoDb(evoDb), connman(_connman), m_peer_logic(peer_logic) { utils::InitQuorumsCache(mapHasMinedCommitmentCache); } diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index a5a28fc535a7..427f6a1bdae8 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -20,6 +20,7 @@ class BlockValidationState; class CNode; class CConnman; class CEvoDB; +class PeerLogicValidation; extern CCriticalSection cs_main; @@ -35,6 +36,8 @@ class CQuorumBlockProcessor CEvoDB& m_evoDb; CConnman& connman; + const std::unique_ptr& m_peer_logic; + // TODO cleanup mutable CCriticalSection minableCommitmentsCs; std::map, uint256> minableCommitmentsByQuorum GUARDED_BY(minableCommitmentsCs); @@ -43,7 +46,7 @@ class CQuorumBlockProcessor mutable std::map> mapHasMinedCommitmentCache GUARDED_BY(minableCommitmentsCs); public: - explicit CQuorumBlockProcessor(CEvoDB& _evoDb, CConnman& _connman); + explicit CQuorumBlockProcessor(CEvoDB& _evoDb, CConnman& _connman, const std::unique_ptr& peer_logic); bool UpgradeDB(); diff --git a/src/llmq/chainlocks.cpp b/src/llmq/chainlocks.cpp index 370a1ffb36bf..105925384107 100644 --- a/src/llmq/chainlocks.cpp +++ b/src/llmq/chainlocks.cpp @@ -24,7 +24,10 @@ namespace llmq { std::unique_ptr chainLocksHandler; -CChainLocksHandler::CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, CSigningManager& _sigman, CSigSharesManager& _shareman, CQuorumManager& _qman, const std::unique_ptr& mn_sync) : +CChainLocksHandler::CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, + CSigningManager& _sigman, CSigSharesManager& _shareman, CQuorumManager& _qman, + const std::unique_ptr& mn_sync, + const std::unique_ptr& peer_logic) : connman(_connman), mempool(_mempool), spork_manager(sporkManager), @@ -32,6 +35,7 @@ CChainLocksHandler::CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, shareman(_shareman), qman(_qman), m_mn_sync(mn_sync), + m_peer_logic(peer_logic), scheduler(std::make_unique()), scheduler_thread(std::make_unique([&] { TraceThread("cl-schdlr", [&] { scheduler->serviceQueue(); }); })) { diff --git a/src/llmq/chainlocks.h b/src/llmq/chainlocks.h index 27687da2f51e..88ebf963e4cb 100644 --- a/src/llmq/chainlocks.h +++ b/src/llmq/chainlocks.h @@ -21,10 +21,11 @@ class CConnman; class CBlockIndex; +class CMasternodeSync; class CScheduler; -class CTxMemPool; class CSporkManager; -class CMasternodeSync; +class CTxMemPool; +class PeerLogicValidation; namespace llmq { @@ -47,7 +48,10 @@ class CChainLocksHandler : public CRecoveredSigsListener CSigningManager& sigman; CSigSharesManager& shareman; CQuorumManager& qman; + const std::unique_ptr& m_mn_sync; + const std::unique_ptr& m_peer_logic; + std::unique_ptr scheduler; std::unique_ptr scheduler_thread; mutable Mutex cs; @@ -80,7 +84,10 @@ class CChainLocksHandler : public CRecoveredSigsListener int64_t lastCleanupTime GUARDED_BY(cs) {0}; public: - explicit CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, CSigningManager& _sigman, CSigSharesManager& _shareman, CQuorumManager& _qman, const std::unique_ptr& mn_sync); + explicit CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, + CSigningManager& _sigman, CSigSharesManager& _shareman, CQuorumManager& _qman, + const std::unique_ptr& mn_sync, + const std::unique_ptr& peer_logic); ~CChainLocksHandler(); void Start(); diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index b188aac29470..d52d3834f6f1 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -19,8 +19,9 @@ #include #include -LLMQContext::LLMQContext(CEvoDB& evoDb, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkManager, bool unitTests, bool fWipe) { - Create(evoDb, mempool, connman, sporkManager, unitTests, fWipe); +LLMQContext::LLMQContext(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, + const std::unique_ptr& peer_logic, bool unit_tests, bool wipe) { + Create(evo_db, mempool, connman, sporkman, peer_logic, unit_tests, wipe); /* Context aliases to globals used by the LLMQ system */ quorum_block_processor = llmq::quorumBlockProcessor.get(); @@ -38,21 +39,22 @@ LLMQContext::~LLMQContext() { Destroy(); } -void LLMQContext::Create(CEvoDB& evoDb, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkManager, bool unitTests, bool fWipe) { +void LLMQContext::Create(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, + const std::unique_ptr& peer_logic, bool unit_tests, bool wipe) { bls_worker = std::make_shared(); dkg_debugman = std::make_unique(); - llmq::quorumBlockProcessor = std::make_unique(evoDb, connman); - qdkgsman = std::make_unique(connman, *bls_worker, *dkg_debugman, *llmq::quorumBlockProcessor, sporkManager, unitTests, fWipe); - llmq::quorumManager = std::make_unique(evoDb, connman, *bls_worker, *llmq::quorumBlockProcessor, *qdkgsman, ::masternodeSync); - sigman = std::make_unique(connman, *llmq::quorumManager, unitTests, fWipe); - shareman = std::make_unique(connman, *llmq::quorumManager, *sigman); - llmq::chainLocksHandler = std::make_unique(mempool, connman, sporkManager, *sigman, *shareman, *llmq::quorumManager, ::masternodeSync); - llmq::quorumInstantSendManager = std::make_unique(mempool, connman, sporkManager, *llmq::quorumManager, *sigman, *shareman, *llmq::chainLocksHandler, ::masternodeSync, unitTests, fWipe); + llmq::quorumBlockProcessor = std::make_unique(evo_db, connman, peer_logic); + qdkgsman = std::make_unique(connman, *bls_worker, *dkg_debugman, *llmq::quorumBlockProcessor, sporkman, peer_logic, unit_tests, wipe); + llmq::quorumManager = std::make_unique(evo_db, connman, *bls_worker, *llmq::quorumBlockProcessor, *qdkgsman, ::masternodeSync, peer_logic); + sigman = std::make_unique(connman, *llmq::quorumManager, peer_logic, unit_tests, wipe); + shareman = std::make_unique(connman, *llmq::quorumManager, *sigman, peer_logic); + llmq::chainLocksHandler = std::make_unique(mempool, connman, sporkman, *sigman, *shareman, *llmq::quorumManager, ::masternodeSync, peer_logic); + llmq::quorumInstantSendManager = std::make_unique(mempool, connman, sporkman, *llmq::quorumManager, *sigman, *shareman, *llmq::chainLocksHandler, ::masternodeSync, peer_logic, unit_tests, wipe); // NOTE: we use this only to wipe the old db, do NOT use it for anything else // TODO: remove it in some future version - auto llmqDbTmp = std::make_unique(unitTests ? "" : (GetDataDir() / "llmq"), 1 << 20, unitTests, true); + auto llmqDbTmp = std::make_unique(unit_tests ? "" : (GetDataDir() / "llmq"), 1 << 20, unit_tests, true); } void LLMQContext::Destroy() { diff --git a/src/llmq/context.h b/src/llmq/context.h index 3f48f25991b3..19042dc7b72d 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -13,6 +13,7 @@ class CDBWrapper; class CEvoDB; class CTxMemPool; class CSporkManager; +class PeerLogicValidation; namespace llmq { class CDKGDebugManager; @@ -26,10 +27,12 @@ class CInstantSendManager; } struct LLMQContext { - LLMQContext(CEvoDB& evoDb, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkManager, bool unitTests, bool fWipe); + LLMQContext(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, + const std::unique_ptr& peer_logic, bool unit_tests, bool wipe); ~LLMQContext(); - void Create(CEvoDB& evoDb, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkManager, bool unitTests, bool fWipe); + void Create(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, + const std::unique_ptr& peer_logic, bool unit_tests, bool wipe); void Destroy(); void Interrupt(); void Start(); diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index e29b88c44ec3..5abd29874239 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -22,7 +22,8 @@ namespace llmq { CDKGSessionHandler::CDKGSessionHandler(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDKGSessionManager& _dkgManager, - CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, CConnman& _connman, int _quorumIndex) : + CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, + CConnman& _connman, const std::unique_ptr& peer_logic, int _quorumIndex) : params(_params), connman(_connman), quorumIndex(_quorumIndex), @@ -30,6 +31,7 @@ CDKGSessionHandler::CDKGSessionHandler(const Consensus::LLMQParams& _params, CBL dkgManager(_dkgManager), dkgDebugManager(_dkgDebugManager), quorumBlockProcessor(_quorumBlockProcessor), + m_peer_logic(peer_logic), curSession(std::make_unique(_params, _blsWorker, _dkgManager, _dkgDebugManager, _connman)), 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), @@ -414,7 +416,7 @@ std::set BatchVerifyMessageSigs(CDKGSession& session, const std::vector< } template -bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendingMessages, size_t maxCount) +bool ProcessPendingMessageBatch(CDKGSession& session, PeerLogicValidation& peer_logic, CDKGPendingMessages& pendingMessages, size_t maxCount) { auto msgs = pendingMessages.PopAndDeserializeMessages(maxCount); if (msgs.empty()) { @@ -517,7 +519,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->Contribute(pendingContributions); }; auto fContributeWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingContributions, 8); + return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingContributions, 8); }; HandlePhase(QuorumPhase::Contribute, QuorumPhase::Complain, curQuorumHash, 0.05, fContributeStart, fContributeWait); @@ -526,7 +528,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndComplain(pendingComplaints); }; auto fComplainWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingComplaints, 8); + return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingComplaints, 8); }; HandlePhase(QuorumPhase::Complain, QuorumPhase::Justify, curQuorumHash, 0.05, fComplainStart, fComplainWait); @@ -535,7 +537,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndJustify(pendingJustifications); }; auto fJustifyWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingJustifications, 8); + return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingJustifications, 8); }; HandlePhase(QuorumPhase::Justify, QuorumPhase::Commit, curQuorumHash, 0.05, fJustifyStart, fJustifyWait); @@ -544,7 +546,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndCommit(pendingPrematureCommitments); }; auto fCommitWait = [this] { - return ProcessPendingMessageBatch(*curSession, pendingPrematureCommitments, 8); + return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingPrematureCommitments, 8); }; HandlePhase(QuorumPhase::Commit, QuorumPhase::Finalize, curQuorumHash, 0.1, fCommitStart, fCommitWait); diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index e099e969ede8..598c6df7d14a 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -13,6 +13,7 @@ class CBLSWorker; class CBlockIndex; +class PeerLogicValidation; namespace llmq { @@ -117,6 +118,8 @@ class CDKGSessionHandler CDKGDebugManager& dkgDebugManager; CQuorumBlockProcessor& quorumBlockProcessor; + const std::unique_ptr& m_peer_logic; + QuorumPhase phase GUARDED_BY(cs) {QuorumPhase::Idle}; int currentHeight GUARDED_BY(cs) {-1}; uint256 quorumHash GUARDED_BY(cs); @@ -132,7 +135,8 @@ class CDKGSessionHandler public: CDKGSessionHandler(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDKGSessionManager& _dkgManager, - CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, CConnman& _connman, int _quorumIndex); + CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, + CConnman& _connman, const std::unique_ptr& peer_logic, int _quorumIndex); ~CDKGSessionHandler() = default; void UpdatedBlockTip(const CBlockIndex *pindexNew); diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index 8cea880fa0b2..f280c284a267 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -22,9 +22,16 @@ static const std::string DB_VVEC = "qdkg_V"; static const std::string DB_SKCONTRIB = "qdkg_S"; static const std::string DB_ENC_CONTRIB = "qdkg_E"; -CDKGSessionManager::CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorker, CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, CSporkManager& sporkManager, bool unitTests, bool fWipe) : - db(std::make_unique(unitTests ? "" : (GetDataDir() / "llmq/dkgdb"), 1 << 20, unitTests, fWipe)), - blsWorker(_blsWorker), connman(_connman), spork_manager(sporkManager), dkgDebugManager(_dkgDebugManager), quorumBlockProcessor(_quorumBlockProcessor) +CDKGSessionManager::CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorker, CDKGDebugManager& _dkgDebugManager, + CQuorumBlockProcessor& _quorumBlockProcessor, CSporkManager& sporkManager, + const std::unique_ptr& peer_logic, bool unitTests, bool fWipe) : + db(std::make_unique(unitTests ? "" : (GetDataDir() / "llmq/dkgdb"), 1 << 20, unitTests, fWipe)), + blsWorker(_blsWorker), + connman(_connman), + spork_manager(sporkManager), + dkgDebugManager(_dkgDebugManager), + quorumBlockProcessor(_quorumBlockProcessor), + m_peer_logic(peer_logic) { if (!fMasternodeMode && !utils::IsWatchQuorumsEnabled()) { // Regular nodes do not care about any DKG internals, bail out @@ -39,7 +46,7 @@ CDKGSessionManager::CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorke for (const auto i : irange::range(session_count)) { dkgSessionHandlers.emplace(std::piecewise_construct, std::forward_as_tuple(params.type, i), - std::forward_as_tuple(params, blsWorker, *this, dkgDebugManager, quorumBlockProcessor, connman, i)); + std::forward_as_tuple(params, blsWorker, *this, dkgDebugManager, quorumBlockProcessor, connman, peer_logic, i)); } } } diff --git a/src/llmq/dkgsessionmgr.h b/src/llmq/dkgsessionmgr.h index c239c62049b6..c18caf54cafe 100644 --- a/src/llmq/dkgsessionmgr.h +++ b/src/llmq/dkgsessionmgr.h @@ -10,10 +10,12 @@ #include #include -class UniValue; class CBlockIndex; class CDKGDebugManager; class CSporkManager; +class PeerLogicValidation; + +class UniValue; namespace llmq { @@ -31,6 +33,8 @@ class CDKGSessionManager CDKGDebugManager& dkgDebugManager; CQuorumBlockProcessor& quorumBlockProcessor; + const std::unique_ptr& m_peer_logic; + //TODO name struct instead of std::pair std::map, CDKGSessionHandler> dkgSessionHandlers; @@ -54,7 +58,9 @@ class CDKGSessionManager mutable std::map contributionsCache GUARDED_BY(contributionsCacheCs); public: - CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorker, CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, CSporkManager& sporkManager, bool unitTests, bool fWipe); + CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorker, CDKGDebugManager& _dkgDebugManager, + CQuorumBlockProcessor& _quorumBlockProcessor, CSporkManager& sporkManager, + const std::unique_ptr& peer_logic, bool unitTests, bool fWipe); ~CDKGSessionManager() = default; void StartThreads(); diff --git a/src/llmq/instantsend.h b/src/llmq/instantsend.h index 386544a9608f..0732e236e52b 100644 --- a/src/llmq/instantsend.h +++ b/src/llmq/instantsend.h @@ -18,8 +18,9 @@ #include #include -class CSporkManager; class CMasternodeSync; +class CSporkManager; +class PeerLogicValidation; namespace llmq { @@ -209,7 +210,9 @@ class CInstantSendManager : public CRecoveredSigsListener CSigningManager& sigman; CSigSharesManager& shareman; CChainLocksHandler& clhandler; + const std::unique_ptr& m_mn_sync; + const std::unique_ptr& m_peer_logic; std::atomic fUpgradedDB{false}; @@ -259,9 +262,10 @@ class CInstantSendManager : public CRecoveredSigsListener public: explicit CInstantSendManager(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, CQuorumManager& _qman, CSigningManager& _sigman, CSigSharesManager& _shareman, - CChainLocksHandler& _clhandler, const std::unique_ptr& mn_sync, bool unitTests, bool fWipe) : + CChainLocksHandler& _clhandler, const std::unique_ptr& mn_sync, + const std::unique_ptr& peer_logic, bool unitTests, bool fWipe) : db(unitTests, fWipe), connman(_connman), mempool(_mempool), spork_manager(sporkManager), qman(_qman), sigman(_sigman), shareman(_shareman), - clhandler(_clhandler), m_mn_sync(mn_sync) + clhandler(_clhandler), m_mn_sync(mn_sync), m_peer_logic(peer_logic) { workInterrupt.reset(); } diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 37de78c4c66e..5a5de34fbf3b 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -188,13 +188,15 @@ bool CQuorum::ReadContributions(CEvoDB& evoDb) } CQuorumManager::CQuorumManager(CEvoDB& _evoDb, CConnman& _connman, CBLSWorker& _blsWorker, CQuorumBlockProcessor& _quorumBlockProcessor, - CDKGSessionManager& _dkgManager, const std::unique_ptr& mn_sync) : + CDKGSessionManager& _dkgManager, const std::unique_ptr& mn_sync, + const std::unique_ptr& peer_logic) : m_evoDb(_evoDb), connman(_connman), blsWorker(_blsWorker), dkgManager(_dkgManager), quorumBlockProcessor(_quorumBlockProcessor), - m_mn_sync(mn_sync) + m_mn_sync(mn_sync), + m_peer_logic(peer_logic) { utils::InitQuorumsCache(mapQuorumsCache); utils::InitQuorumsCache(scanQuorumsCache); diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index c254393322a9..652c2bca9d69 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -16,14 +16,14 @@ #include -class CNode; - class CConnman; class CBlockIndex; - class CDeterministicMN; -using CDeterministicMNCPtr = std::shared_ptr; class CMasternodeSync; +class CNode; +class PeerLogicValidation; + +using CDeterministicMNCPtr = std::shared_ptr; namespace llmq { @@ -217,7 +217,9 @@ class CQuorumManager CBLSWorker& blsWorker; CDKGSessionManager& dkgManager; CQuorumBlockProcessor& quorumBlockProcessor; + const std::unique_ptr& m_mn_sync; + const std::unique_ptr& m_peer_logic; mutable CCriticalSection cs_map_quorums; mutable std::map> mapQuorumsCache GUARDED_BY(cs_map_quorums); @@ -229,7 +231,8 @@ class CQuorumManager public: CQuorumManager(CEvoDB& _evoDb, CConnman& _connman, CBLSWorker& _blsWorker, CQuorumBlockProcessor& _quorumBlockProcessor, - CDKGSessionManager& _dkgManager, const std::unique_ptr& mnSync); + CDKGSessionManager& _dkgManager, const std::unique_ptr& mnSync, + const std::unique_ptr& peer_logic); ~CQuorumManager() { Stop(); }; void Start(); diff --git a/src/llmq/signing.cpp b/src/llmq/signing.cpp index 7c5dc5ea23a8..960c214df056 100644 --- a/src/llmq/signing.cpp +++ b/src/llmq/signing.cpp @@ -526,8 +526,10 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge) ////////////////// -CSigningManager::CSigningManager(CConnman& _connman, const CQuorumManager& _qman, bool fMemory, bool fWipe) : - db(fMemory, fWipe), connman(_connman), qman(_qman) +CSigningManager::CSigningManager(CConnman& _connman, const CQuorumManager& _qman, + const std::unique_ptr& peer_logic, + bool fMemory, bool fWipe) : + db(fMemory, fWipe), connman(_connman), qman(_qman), m_peer_logic(peer_logic) { } diff --git a/src/llmq/signing.h b/src/llmq/signing.h index 1d4391669114..3fd16ee93f37 100644 --- a/src/llmq/signing.h +++ b/src/llmq/signing.h @@ -17,10 +17,12 @@ #include -using NodeId = int64_t; class CConnman; class CInv; class CNode; +class PeerLogicValidation; + +using NodeId = int64_t; namespace llmq { @@ -168,6 +170,8 @@ class CSigningManager CConnman& connman; const CQuorumManager& qman; + const std::unique_ptr& m_peer_logic; + // Incoming and not verified yet std::unordered_map>> pendingRecoveredSigs GUARDED_BY(cs); std::unordered_map, StaticSaltedHasher> pendingReconstructedRecoveredSigs GUARDED_BY(cs); @@ -179,7 +183,8 @@ class CSigningManager std::vector recoveredSigsListeners GUARDED_BY(cs); public: - CSigningManager(CConnman& _connman, const CQuorumManager& _qman, bool fMemory, bool fWipe); + CSigningManager(CConnman& _connman, const CQuorumManager& _qman, + const std::unique_ptr& peer_logic, bool fMemory, bool fWipe); bool AlreadyHave(const CInv& inv) const; bool GetRecoveredSigForGetData(const uint256& hash, CRecoveredSig& ret) const; diff --git a/src/llmq/signing_shares.h b/src/llmq/signing_shares.h index 4b3b39213bc1..b498b65c0385 100644 --- a/src/llmq/signing_shares.h +++ b/src/llmq/signing_shares.h @@ -19,11 +19,12 @@ #include #include +class CDeterministicMN; class CEvoDB; class CScheduler; class CSporkManager; +class PeerLogicValidation; -class CDeterministicMN; using CDeterministicMNCPtr = std::shared_ptr; namespace llmq @@ -399,11 +400,15 @@ class CSigSharesManager : public CRecoveredSigsListener CConnman& connman; const CQuorumManager& qman; CSigningManager& sigman; + + const std::unique_ptr& m_peer_logic; + int64_t lastCleanupTime{0}; std::atomic recoveredSigsCounter{0}; public: - explicit CSigSharesManager(CConnman& _connman, CQuorumManager& _qman, CSigningManager& _sigman) : connman(_connman), qman(_qman), sigman(_sigman) + explicit CSigSharesManager(CConnman& _connman, CQuorumManager& _qman, CSigningManager& _sigman, const std::unique_ptr& peer_logic) : + connman(_connman), qman(_qman), sigman(_sigman), m_peer_logic(peer_logic) { workInterrupt.reset(); }; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index ecda0359c0e4..d3007fd1a906 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -188,7 +188,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve #endif // ENABLE_WALLET deterministicMNManager.reset(new CDeterministicMNManager(*m_node.evodb, *m_node.connman)); - m_node.llmq_ctx = std::make_unique(*m_node.evodb, *m_node.mempool, *m_node.connman, *sporkManager, true, false); + m_node.llmq_ctx = std::make_unique(*m_node.evodb, *m_node.mempool, *m_node.connman, *sporkManager, m_node.peer_logic, true, false); // Start script-checking threads. Set g_parallel_script_checks to true so they are used. constexpr int script_check_threads = 2; From d9d98505e457b852fd977f2c442fec217053ddd5 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Wed, 26 Apr 2023 15:44:43 +0000 Subject: [PATCH 02/10] net: pass PeerLogicValidation to remaining ProcessMessages --- src/coinjoin/client.cpp | 12 ++++++------ src/coinjoin/client.h | 9 +++++---- src/coinjoin/server.cpp | 6 +++--- src/coinjoin/server.h | 6 ++++-- src/evo/mnauth.cpp | 2 +- src/evo/mnauth.h | 6 ++++-- src/governance/governance.cpp | 6 +++--- src/governance/governance.h | 5 +++-- src/net_processing.cpp | 12 ++++++------ src/spork.cpp | 6 +++--- src/spork.h | 5 +++-- 11 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 9c5fb026b855..9a3b1b5be665 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -31,7 +31,7 @@ std::map> coinJoinCli std::unique_ptr coinJoinClientQueueManager; -void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv) { if (fMasternodeMode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; @@ -43,11 +43,11 @@ void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, std::string_ } if (msg_type == NetMsgType::DSQUEUE) { - CCoinJoinClientQueueManager::ProcessDSQueue(peer, vRecv); + CCoinJoinClientQueueManager::ProcessDSQueue(peer, peer_logic, vRecv); } } -void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataStream& vRecv) +void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv) { CCoinJoinQueue dsq; vRecv >> dsq; @@ -130,7 +130,7 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataStream& } } -void CCoinJoinClientManager::ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) { if (fMasternodeMode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; @@ -149,12 +149,12 @@ void CCoinJoinClientManager::ProcessMessage(CNode& peer, CConnman& connman, cons AssertLockNotHeld(cs_deqsessions); LOCK(cs_deqsessions); for (auto& session : deqSessions) { - session.ProcessMessage(peer, connman, mempool, msg_type, vRecv); + session.ProcessMessage(peer, peer_logic, connman, mempool, msg_type, vRecv); } } } -void CCoinJoinClientSession::ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientSession::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) { if (fMasternodeMode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; diff --git a/src/coinjoin/client.h b/src/coinjoin/client.h index 2ec7406201b4..cc531d5c3ee8 100644 --- a/src/coinjoin/client.h +++ b/src/coinjoin/client.h @@ -22,6 +22,7 @@ class CBlockPolicyEstimator; class CConnman; class CNode; class CTxMemPool; +class PeerLogicValidation; class UniValue; class CMasternodeSync; @@ -128,7 +129,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession { } - void ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); void UnlockCoins(); @@ -163,8 +164,8 @@ class CCoinJoinClientQueueManager : public CCoinJoinBaseManager explicit CCoinJoinClientQueueManager(CConnman& _connman, const std::unique_ptr& mn_sync) : connman(_connman), m_mn_sync(mn_sync) {}; - void ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); - void ProcessDSQueue(const CNode& peer, CDataStream& vRecv); + void ProcessMessage(const CNode& peer, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); + void ProcessDSQueue(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv); void DoMaintenance(); }; @@ -209,7 +210,7 @@ class CCoinJoinClientManager explicit CCoinJoinClientManager(CWallet& wallet, const std::unique_ptr& mn_sync) : m_mn_sync(mn_sync), mixingWallet(wallet) {} - void ProcessMessage(CNode& peer, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_deqsessions); + void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_deqsessions); bool StartMixing(); void StopMixing(); diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index fac306d9594e..b970e080c6a5 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -26,7 +26,7 @@ std::unique_ptr coinJoinServer; constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10}; -void CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinServer::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv) { if (!fMasternodeMode) return; if (!m_mn_sync->IsBlockchainSynced()) return; @@ -34,7 +34,7 @@ void CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_type, CDa if (msg_type == NetMsgType::DSACCEPT) { ProcessDSACCEPT(peer, vRecv); } else if (msg_type == NetMsgType::DSQUEUE) { - ProcessDSQUEUE(peer, vRecv); + ProcessDSQUEUE(peer, peer_logic, vRecv); } else if (msg_type == NetMsgType::DSVIN) { ProcessDSVIN(peer, vRecv); } else if (msg_type == NetMsgType::DSSIGNFINALTX) { @@ -107,7 +107,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) } } -void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv) +void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv) { CCoinJoinQueue dsq; vRecv >> dsq; diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index 21a8ff290633..604450ba56b5 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -10,6 +10,8 @@ class CCoinJoinServer; class CTxMemPool; +class PeerLogicValidation; + class UniValue; // The main object for accessing mixing @@ -70,7 +72,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager void RelayCompletedTransaction(PoolMessage nMessageID) LOCKS_EXCLUDED(cs_coinjoin); void ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); - void ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); + void ProcessDSQUEUE(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); void ProcessDSVIN(CNode& peer, CDataStream& vRecv) LOCKS_EXCLUDED(cs_coinjoin); void ProcessDSSIGNFINALTX(CDataStream& vRecv) LOCKS_EXCLUDED(cs_coinjoin); @@ -85,7 +87,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager fUnitTest(false) {} - void ProcessMessage(CNode& pfrom, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& pfrom, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv); bool HasTimedOut() const; void CheckTimeout(); diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 1968f875da50..7eeebddca6cc 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -58,7 +58,7 @@ void CMNAuth::PushMNAUTH(CNode& peer, CConnman& connman, const CBlockIndex* tip) connman.PushMessage(&peer, CNetMsgMaker(peer.GetSendVersion()).Make(NetMsgType::MNAUTH, mnauth)); } -void CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) +void CMNAuth::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) { if (msg_type != NetMsgType::MNAUTH || !::masternodeSync->IsBlockchainSynced()) { // we can't verify MNAUTH messages when we don't have the latest MN list diff --git a/src/evo/mnauth.h b/src/evo/mnauth.h index 00543cbfec71..9e2079f8879d 100644 --- a/src/evo/mnauth.h +++ b/src/evo/mnauth.h @@ -8,14 +8,16 @@ #include #include +class CBlockIndex; class CConnman; class CDataStream; class CDeterministicMN; class CDeterministicMNList; class CDeterministicMNListDiff; class CNode; +class PeerLogicValidation; + class UniValue; -class CBlockIndex; /** * This class handles the p2p message MNAUTH. MNAUTH is sent directly after VERACK and authenticates the sender as a @@ -46,7 +48,7 @@ class CMNAuth } static void PushMNAUTH(CNode& peer, CConnman& connman, const CBlockIndex* tip); - static void ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); + static void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); static void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman); }; diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index f5a719c968e1..7236514fd19f 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -87,7 +87,7 @@ bool CGovernanceManager::SerializeVoteForHash(const uint256& nHash, CDataStream& return cmapVoteToObject.Get(nHash, pGovobj) && pGovobj->GetVoteFile().SerializeVoteToStream(nHash, ss); } -void CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) +void CGovernanceManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) { if (fDisableGovernance) return; if (::masternodeSync == nullptr || !::masternodeSync->IsBlockchainSynced()) return; @@ -107,7 +107,7 @@ void CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, std::str vRecv >> filter; if (nProp == uint256()) { - SyncObjects(peer, connman); + SyncObjects(peer, peer_logic, connman); } else { SyncSingleObjVotes(peer, nProp, filter, connman); } @@ -617,7 +617,7 @@ void CGovernanceManager::SyncSingleObjVotes(CNode& peer, const uint256& nProp, c LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- sent %d votes to peer=%d\n", __func__, nVoteCount, peer.GetId()); } -void CGovernanceManager::SyncObjects(CNode& peer, CConnman& connman) const +void CGovernanceManager::SyncObjects(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman) const { // do not provide any data until our node is synced if (!::masternodeSync->IsSynced()) return; diff --git a/src/governance/governance.h b/src/governance/governance.h index 1c8e203a78da..b6594748da0b 100644 --- a/src/governance/governance.h +++ b/src/governance/governance.h @@ -18,6 +18,7 @@ class CGovernanceTriggerManager; class CGovernanceObject; class CGovernanceVote; class CSporkManager; +class PeerLogicValidation; extern std::unique_ptr governance; @@ -231,9 +232,9 @@ class CGovernanceManager bool ConfirmInventoryRequest(const CInv& inv); void SyncSingleObjVotes(CNode& peer, const uint256& nProp, const CBloomFilter& filter, CConnman& connman); - void SyncObjects(CNode& peer, CConnman& connman) const; + void SyncObjects(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman) const; - void ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); void DoMaintenance(CConnman& connman); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 091510ea62a2..a65087a7c39a 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -4147,16 +4147,16 @@ void PeerLogicValidation::ProcessMessage( { //probably one the extensions #ifdef ENABLE_WALLET - coinJoinClientQueueManager->ProcessMessage(pfrom, msg_type, vRecv); + coinJoinClientQueueManager->ProcessMessage(pfrom, *this, msg_type, vRecv); for (auto& pair : coinJoinClientManagers) { - pair.second->ProcessMessage(pfrom, m_connman, m_mempool, msg_type, vRecv); + pair.second->ProcessMessage(pfrom, *this, m_connman, m_mempool, msg_type, vRecv); } #endif // ENABLE_WALLET - coinJoinServer->ProcessMessage(pfrom, msg_type, vRecv); - sporkManager->ProcessMessage(pfrom, m_connman, msg_type, vRecv); + coinJoinServer->ProcessMessage(pfrom, *this, msg_type, vRecv); + sporkManager->ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv); ::masternodeSync->ProcessMessage(pfrom, msg_type, vRecv); - governance->ProcessMessage(pfrom, m_connman, msg_type, vRecv); - CMNAuth::ProcessMessage(pfrom, m_connman, msg_type, vRecv); + governance->ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv); + CMNAuth::ProcessMessage(pfrom, *this, m_connman, msg_type, vRecv); m_llmq_ctx->quorum_block_processor->ProcessMessage(pfrom, msg_type, vRecv); m_llmq_ctx->qdkgsman->ProcessMessage(pfrom, *m_llmq_ctx->qman, msg_type, vRecv); m_llmq_ctx->qman->ProcessMessage(pfrom, msg_type, vRecv); diff --git a/src/spork.cpp b/src/spork.cpp index 2daae12a01fb..cf2a9c774fc0 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -105,16 +105,16 @@ void CSporkManager::CheckAndRemove() } } -void CSporkManager::ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) +void CSporkManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) { if (msg_type == NetMsgType::SPORK) { - ProcessSpork(peer, connman, vRecv); + ProcessSpork(peer, peer_logic, connman, vRecv); } else if (msg_type == NetMsgType::GETSPORKS) { ProcessGetSporks(peer, connman); } } -void CSporkManager::ProcessSpork(const CNode& peer, CConnman& connman, CDataStream& vRecv) +void CSporkManager::ProcessSpork(const CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, CDataStream& vRecv) { CSporkMessage spork; vRecv >> spork; diff --git a/src/spork.h b/src/spork.h index d390131abdbf..522b6250482a 100644 --- a/src/spork.h +++ b/src/spork.h @@ -22,6 +22,7 @@ class CConnman; class CNode; class CDataStream; +class PeerLogicValidation; class CSporkMessage; class CSporkManager; @@ -233,7 +234,7 @@ class CSporkManager /** * ProcessMessage is used to call ProcessSpork and ProcessGetSporks. See below */ - void ProcessMessage(CNode& peer, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); /** * ProcessSpork is used to handle the 'spork' p2p message. @@ -241,7 +242,7 @@ class CSporkManager * For 'spork', it validates the spork and adds it to the internal spork storage and * performs any necessary processing. */ - void ProcessSpork(const CNode& peer, CConnman& connman, CDataStream& vRecv) LOCKS_EXCLUDED(cs); + void ProcessSpork(const CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, CDataStream& vRecv) LOCKS_EXCLUDED(cs); /** From f2384ffa90da0b702b317447043b983b27c2e269 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Fri, 28 Apr 2023 05:17:42 +0000 Subject: [PATCH 03/10] merge bitcoin#19791: Move Misbehaving() to PeerManager --- src/coinjoin/client.cpp | 18 ++-- src/coinjoin/client.h | 10 +- src/coinjoin/server.cpp | 12 +-- src/coinjoin/server.h | 6 +- src/evo/mnauth.cpp | 14 +-- src/evo/mnauth.h | 4 +- src/governance/governance.cpp | 12 +-- src/governance/governance.h | 6 +- src/init.cpp | 14 +-- src/llmq/blockprocessor.cpp | 14 +-- src/llmq/blockprocessor.h | 6 +- src/llmq/chainlocks.cpp | 6 +- src/llmq/chainlocks.h | 6 +- src/llmq/context.cpp | 20 ++-- src/llmq/context.h | 6 +- src/llmq/dkgsessionhandler.cpp | 22 ++--- src/llmq/dkgsessionhandler.h | 6 +- src/llmq/dkgsessionmgr.cpp | 18 ++-- src/llmq/dkgsessionmgr.h | 6 +- src/llmq/instantsend.cpp | 8 +- src/llmq/instantsend.h | 8 +- src/llmq/quorums.cpp | 6 +- src/llmq/quorums.h | 6 +- src/llmq/signing.cpp | 8 +- src/llmq/signing.h | 6 +- src/llmq/signing_shares.cpp | 2 +- src/llmq/signing_shares.h | 8 +- src/net_processing.cpp | 146 ++++++++++++----------------- src/net_processing.h | 77 +++++++++++---- src/node/context.h | 4 +- src/spork.cpp | 10 +- src/spork.h | 6 +- src/test/denialofservice_tests.cpp | 43 +++++---- src/test/fuzz/process_message.cpp | 6 +- src/test/fuzz/process_messages.cpp | 4 +- src/test/util/setup_common.cpp | 8 +- 36 files changed, 289 insertions(+), 273 deletions(-) diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 9a3b1b5be665..890dbdef269e 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -31,7 +31,7 @@ std::map> coinJoinCli std::unique_ptr coinJoinClientQueueManager; -void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv) { if (fMasternodeMode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; @@ -43,17 +43,17 @@ void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, PeerLogicVal } if (msg_type == NetMsgType::DSQUEUE) { - CCoinJoinClientQueueManager::ProcessDSQueue(peer, peer_logic, vRecv); + CCoinJoinClientQueueManager::ProcessDSQueue(peer, peerman, vRecv); } } -void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv) +void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerManager& peerman, CDataStream& vRecv) { CCoinJoinQueue dsq; vRecv >> dsq; if (dsq.masternodeOutpoint.IsNull() && dsq.m_protxHash.IsNull()) { - Misbehaving(peer.GetId(), 100); + peerman.Misbehaving(peer.GetId(), 100); return; } @@ -62,7 +62,7 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerLogicVal if (auto dmn = mnList.GetValidMN(dsq.m_protxHash)) { dsq.masternodeOutpoint = dmn->collateralOutpoint; } else { - Misbehaving(peer.GetId(), 10); + peerman.Misbehaving(peer.GetId(), 10); return; } } @@ -97,7 +97,7 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerLogicVal } if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { - Misbehaving(peer.GetId(), 10); + peerman.Misbehaving(peer.GetId(), 10); return; } @@ -130,7 +130,7 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, PeerLogicVal } } -void CCoinJoinClientManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientManager::ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) { if (fMasternodeMode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; @@ -149,12 +149,12 @@ void CCoinJoinClientManager::ProcessMessage(CNode& peer, PeerLogicValidation& pe AssertLockNotHeld(cs_deqsessions); LOCK(cs_deqsessions); for (auto& session : deqSessions) { - session.ProcessMessage(peer, peer_logic, connman, mempool, msg_type, vRecv); + session.ProcessMessage(peer, peerman, connman, mempool, msg_type, vRecv); } } } -void CCoinJoinClientSession::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinClientSession::ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) { if (fMasternodeMode) return; if (!CCoinJoinClientOptions::IsEnabled()) return; diff --git a/src/coinjoin/client.h b/src/coinjoin/client.h index cc531d5c3ee8..455e1a4aca8f 100644 --- a/src/coinjoin/client.h +++ b/src/coinjoin/client.h @@ -22,7 +22,7 @@ class CBlockPolicyEstimator; class CConnman; class CNode; class CTxMemPool; -class PeerLogicValidation; +class PeerManager; class UniValue; class CMasternodeSync; @@ -129,7 +129,7 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession { } - void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv); void UnlockCoins(); @@ -164,8 +164,8 @@ class CCoinJoinClientQueueManager : public CCoinJoinBaseManager explicit CCoinJoinClientQueueManager(CConnman& _connman, const std::unique_ptr& mn_sync) : connman(_connman), m_mn_sync(mn_sync) {}; - void ProcessMessage(const CNode& peer, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); - void ProcessDSQueue(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv); + void ProcessMessage(const CNode& peer, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); + void ProcessDSQueue(const CNode& peer, PeerManager& peerman, CDataStream& vRecv); void DoMaintenance(); }; @@ -210,7 +210,7 @@ class CCoinJoinClientManager explicit CCoinJoinClientManager(CWallet& wallet, const std::unique_ptr& mn_sync) : m_mn_sync(mn_sync), mixingWallet(wallet) {} - void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_deqsessions); + void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) LOCKS_EXCLUDED(cs_deqsessions); bool StartMixing(); void StopMixing(); diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index b970e080c6a5..bbd97bb91f93 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -26,7 +26,7 @@ std::unique_ptr coinJoinServer; constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10}; -void CCoinJoinServer::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv) +void CCoinJoinServer::ProcessMessage(CNode& peer, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv) { if (!fMasternodeMode) return; if (!m_mn_sync->IsBlockchainSynced()) return; @@ -34,7 +34,7 @@ void CCoinJoinServer::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logi if (msg_type == NetMsgType::DSACCEPT) { ProcessDSACCEPT(peer, vRecv); } else if (msg_type == NetMsgType::DSQUEUE) { - ProcessDSQUEUE(peer, peer_logic, vRecv); + ProcessDSQUEUE(peer, peerman, vRecv); } else if (msg_type == NetMsgType::DSVIN) { ProcessDSVIN(peer, vRecv); } else if (msg_type == NetMsgType::DSSIGNFINALTX) { @@ -107,13 +107,13 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) } } -void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv) +void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, PeerManager& peerman, CDataStream& vRecv) { CCoinJoinQueue dsq; vRecv >> dsq; if (dsq.masternodeOutpoint.IsNull() && dsq.m_protxHash.IsNull()) { - Misbehaving(peer.GetId(), 100); + peerman.Misbehaving(peer.GetId(), 100); return; } @@ -122,7 +122,7 @@ void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, PeerLogicValidation& pee if (auto dmn = mnList.GetValidMN(dsq.m_protxHash)) { dsq.masternodeOutpoint = dmn->collateralOutpoint; } else { - Misbehaving(peer.GetId(), 10); + peerman.Misbehaving(peer.GetId(), 10); return; } } @@ -157,7 +157,7 @@ void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, PeerLogicValidation& pee } if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { - Misbehaving(peer.GetId(), 10); + peerman.Misbehaving(peer.GetId(), 10); return; } diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index 604450ba56b5..6d05a95e7b53 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -10,7 +10,7 @@ class CCoinJoinServer; class CTxMemPool; -class PeerLogicValidation; +class PeerManager; class UniValue; @@ -72,7 +72,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager void RelayCompletedTransaction(PoolMessage nMessageID) LOCKS_EXCLUDED(cs_coinjoin); void ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); - void ProcessDSQUEUE(const CNode& peer, PeerLogicValidation& peer_logic, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); + void ProcessDSQUEUE(const CNode& peer, PeerManager& peerman, CDataStream& vRecv) LOCKS_EXCLUDED(cs_vecqueue); void ProcessDSVIN(CNode& peer, CDataStream& vRecv) LOCKS_EXCLUDED(cs_coinjoin); void ProcessDSSIGNFINALTX(CDataStream& vRecv) LOCKS_EXCLUDED(cs_coinjoin); @@ -87,7 +87,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager fUnitTest(false) {} - void ProcessMessage(CNode& pfrom, PeerLogicValidation& peer_logic, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& pfrom, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv); bool HasTimedOut() const; void CheckTimeout(); diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 7eeebddca6cc..70cccc47f9f1 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -58,7 +58,7 @@ void CMNAuth::PushMNAUTH(CNode& peer, CConnman& connman, const CBlockIndex* tip) connman.PushMessage(&peer, CNetMsgMaker(peer.GetSendVersion()).Make(NetMsgType::MNAUTH, mnauth)); } -void CMNAuth::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) +void CMNAuth::ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) { if (msg_type != NetMsgType::MNAUTH || !::masternodeSync->IsBlockchainSynced()) { // we can't verify MNAUTH messages when we don't have the latest MN list @@ -70,23 +70,23 @@ void CMNAuth::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConn // only one MNAUTH allowed if (!peer.GetVerifiedProRegTxHash().IsNull()) { - Misbehaving(peer.GetId(), 100, "duplicate mnauth"); + peerman.Misbehaving(peer.GetId(), 100, "duplicate mnauth"); return; } if ((~peer.nServices) & (NODE_NETWORK | NODE_BLOOM)) { // either NODE_NETWORK or NODE_BLOOM bit is missing in node's services - Misbehaving(peer.GetId(), 100, "mnauth from a node with invalid services"); + peerman.Misbehaving(peer.GetId(), 100, "mnauth from a node with invalid services"); return; } if (mnauth.proRegTxHash.IsNull()) { - Misbehaving(peer.GetId(), 100, "empty mnauth proRegTxHash"); + peerman.Misbehaving(peer.GetId(), 100, "empty mnauth proRegTxHash"); return; } if (!mnauth.sig.IsValid()) { - Misbehaving(peer.GetId(), 100, "invalid mnauth signature"); + peerman.Misbehaving(peer.GetId(), 100, "invalid mnauth signature"); LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- invalid mnauth for protx=%s with sig=%s\n", mnauth.proRegTxHash.ToString(), mnauth.sig.ToString()); return; } @@ -97,7 +97,7 @@ void CMNAuth::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConn // in case node was unlucky and not up to date, just let it be connected as a regular node, which gives it // a chance to get up-to-date and thus realize that it's not a MN anymore. We still give it a // low DoS score. - Misbehaving(peer.GetId(), 10, "missing mnauth masternode"); + peerman.Misbehaving(peer.GetId(), 10, "missing mnauth masternode"); return; } @@ -120,7 +120,7 @@ void CMNAuth::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConn if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), signHash)) { // Same as above, MN seems to not know its fate yet, so give it a chance to update. If this is a // malicious node (DoSing us), it'll get banned soon. - Misbehaving(peer.GetId(), 10, "mnauth signature verification failed"); + peerman.Misbehaving(peer.GetId(), 10, "mnauth signature verification failed"); return; } diff --git a/src/evo/mnauth.h b/src/evo/mnauth.h index 9e2079f8879d..629eaeb5d28c 100644 --- a/src/evo/mnauth.h +++ b/src/evo/mnauth.h @@ -15,7 +15,7 @@ class CDeterministicMN; class CDeterministicMNList; class CDeterministicMNListDiff; class CNode; -class PeerLogicValidation; +class PeerManager; class UniValue; @@ -48,7 +48,7 @@ class CMNAuth } static void PushMNAUTH(CNode& peer, CConnman& connman, const CBlockIndex* tip); - static void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); + static void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); static void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman); }; diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index 7236514fd19f..1980e4ee898a 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -87,7 +87,7 @@ bool CGovernanceManager::SerializeVoteForHash(const uint256& nHash, CDataStream& return cmapVoteToObject.Get(nHash, pGovobj) && pGovobj->GetVoteFile().SerializeVoteToStream(nHash, ss); } -void CGovernanceManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) +void CGovernanceManager::ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) { if (fDisableGovernance) return; if (::masternodeSync == nullptr || !::masternodeSync->IsBlockchainSynced()) return; @@ -107,7 +107,7 @@ void CGovernanceManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_l vRecv >> filter; if (nProp == uint256()) { - SyncObjects(peer, peer_logic, connman); + SyncObjects(peer, peerman, connman); } else { SyncSingleObjVotes(peer, nProp, filter, connman); } @@ -174,7 +174,7 @@ void CGovernanceManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_l } else { LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Governance object is invalid - %s\n", strError); // apply node's ban score - Misbehaving(peer.GetId(), 20); + peerman.Misbehaving(peer.GetId(), 20); } return; @@ -219,7 +219,7 @@ void CGovernanceManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_l } else { LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- Rejected vote, error = %s\n", exception.what()); if ((exception.GetNodePenalty() != 0) && ::masternodeSync->IsSynced()) { - Misbehaving(peer.GetId(), exception.GetNodePenalty()); + peerman.Misbehaving(peer.GetId(), exception.GetNodePenalty()); } return; } @@ -617,7 +617,7 @@ void CGovernanceManager::SyncSingleObjVotes(CNode& peer, const uint256& nProp, c LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- sent %d votes to peer=%d\n", __func__, nVoteCount, peer.GetId()); } -void CGovernanceManager::SyncObjects(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman) const +void CGovernanceManager::SyncObjects(CNode& peer, PeerManager& peerman, CConnman& connman) const { // do not provide any data until our node is synced if (!::masternodeSync->IsSynced()) return; @@ -625,7 +625,7 @@ void CGovernanceManager::SyncObjects(CNode& peer, PeerLogicValidation& peer_logi if (netfulfilledman.HasFulfilledRequest(peer.addr, NetMsgType::MNGOVERNANCESYNC)) { // Asking for the whole list multiple times in a short period of time is no good LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- peer already asked me for the list\n", __func__); - Misbehaving(peer.GetId(), 20); + peerman.Misbehaving(peer.GetId(), 20); return; } netfulfilledman.AddFulfilledRequest(peer.addr, NetMsgType::MNGOVERNANCESYNC); diff --git a/src/governance/governance.h b/src/governance/governance.h index b6594748da0b..194d4b19599f 100644 --- a/src/governance/governance.h +++ b/src/governance/governance.h @@ -18,7 +18,7 @@ class CGovernanceTriggerManager; class CGovernanceObject; class CGovernanceVote; class CSporkManager; -class PeerLogicValidation; +class PeerManager; extern std::unique_ptr governance; @@ -232,9 +232,9 @@ class CGovernanceManager bool ConfirmInventoryRequest(const CInv& inv); void SyncSingleObjVotes(CNode& peer, const uint256& nProp, const CBloomFilter& filter, CConnman& connman); - void SyncObjects(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman) const; + void SyncObjects(CNode& peer, PeerManager& peerman, CConnman& connman) const; - void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); void DoMaintenance(CConnman& connman); diff --git a/src/init.cpp b/src/init.cpp index b6418b319179..eeddeaaae61a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -244,7 +244,7 @@ void PrepareShutdown(NodeContext& node) // Because these depend on each-other, we make sure that neither can be // using the other before destroying them. - if (node.peer_logic) UnregisterValidationInterface(node.peer_logic.get()); + if (node.peerman) UnregisterValidationInterface(node.peerman.get()); if (node.connman) node.connman->Stop(); StopTorControl(); @@ -275,7 +275,7 @@ void PrepareShutdown(NodeContext& node) // After the threads that potentially access these pointers have been stopped, // destruct and reset all to nullptr. - node.peer_logic.reset(); + node.peerman.reset(); node.connman.reset(); node.banman.reset(); node.addrman.reset(); @@ -1781,10 +1781,10 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc node.chainman = &g_chainman; ChainstateManager& chainman = *Assert(node.chainman); - node.peer_logic.reset(new PeerLogicValidation( - *node.connman, *node.addrman, node.banman.get(), *node.scheduler, chainman, *node.mempool, node.llmq_ctx + node.peerman.reset(new PeerManager( + chainparams, *node.connman, *node.addrman, node.banman.get(), *node.scheduler, chainman, *node.mempool, node.llmq_ctx )); - RegisterValidationInterface(node.peer_logic.get()); + RegisterValidationInterface(node.peerman.get()); ::governance = std::make_unique(); assert(!::sporkManager); @@ -2028,7 +2028,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc llmq::quorumSnapshotManager.reset(); llmq::quorumSnapshotManager.reset(new llmq::CQuorumSnapshotManager(*node.evodb)); node.llmq_ctx.reset(); - node.llmq_ctx.reset(new LLMQContext(*node.evodb, *node.mempool, *node.connman, *::sporkManager, node.peer_logic, false, fReset || fReindexChainState)); + node.llmq_ctx.reset(new LLMQContext(*node.evodb, *node.mempool, *node.connman, *::sporkManager, node.peerman, false, fReset || fReindexChainState)); if (fReset) { pblocktree->WriteReindexing(true); @@ -2496,7 +2496,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc connOptions.nBestHeight = chain_active_height; connOptions.uiInterface = &uiInterface; connOptions.m_banman = node.banman.get(); - connOptions.m_msgproc = node.peer_logic.get(); + connOptions.m_msgproc = node.peerman.get(); connOptions.nSendBufferMaxSize = 1000 * args.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); connOptions.nReceiveFloodSize = 1000 * args.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); connOptions.m_added_nodes = args.GetArgs("-addnode"); diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index 69c934ea0896..bfb1e721e5a1 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -36,8 +36,8 @@ static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT_Q_INDEXED = "q_m static const std::string DB_BEST_BLOCK_UPGRADE = "q_bbu2"; -CQuorumBlockProcessor::CQuorumBlockProcessor(CEvoDB& evoDb, CConnman& _connman, const std::unique_ptr& peer_logic) : - m_evoDb(evoDb), connman(_connman), m_peer_logic(peer_logic) +CQuorumBlockProcessor::CQuorumBlockProcessor(CEvoDB& evoDb, CConnman& _connman, const std::unique_ptr& peerman) : + m_evoDb(evoDb), connman(_connman), m_peerman(peerman) { utils::InitQuorumsCache(mapHasMinedCommitmentCache); } @@ -55,7 +55,7 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m if (qc.IsNull()) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- null commitment from peer=%d\n", __func__, peer.GetId()); - Misbehaving(peer.GetId(), 100); + m_peerman->Misbehaving(peer.GetId(), 100); return; } @@ -63,7 +63,7 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m if (!llmq_params_opt.has_value()) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- invalid commitment type %d from peer=%d\n", __func__, ToUnderlying(qc.llmqType), peer.GetId()); - Misbehaving(peer.GetId(), 100); + m_peerman->Misbehaving(peer.GetId(), 100); return; } auto type = qc.llmqType; @@ -90,14 +90,14 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m if (quorumHeight != pQuorumBaseBlockIndex->nHeight) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s is not the first block in the DKG interval, peer=%d\n", __func__, qc.quorumHash.ToString(), peer.GetId()); - Misbehaving(peer.GetId(), 100); + m_peerman->Misbehaving(peer.GetId(), 100); return; } if (pQuorumBaseBlockIndex->nHeight < (::ChainActive().Height() - llmq_params_opt->dkgInterval)) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s is too old, peer=%d\n", __func__, qc.quorumHash.ToString(), peer.GetId()); // TODO: enable punishment in some future version when all/most nodes are running with this fix - // Misbehaving(peer.GetId(), 100); + // m_peerman->Misbehaving(peer.GetId(), 100); return; } if (HasMinedCommitment(type, qc.quorumHash)) { @@ -126,7 +126,7 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- commitment for quorum %s:%d is not valid quorumIndex[%d] nversion[%d], peer=%d\n", __func__, qc.quorumHash.ToString(), ToUnderlying(qc.llmqType), qc.quorumIndex, qc.nVersion, peer.GetId()); - Misbehaving(peer.GetId(), 100); + m_peerman->Misbehaving(peer.GetId(), 100); return; } diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index 427f6a1bdae8..25b9764d62e9 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -20,7 +20,7 @@ class BlockValidationState; class CNode; class CConnman; class CEvoDB; -class PeerLogicValidation; +class PeerManager; extern CCriticalSection cs_main; @@ -36,7 +36,7 @@ class CQuorumBlockProcessor CEvoDB& m_evoDb; CConnman& connman; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; // TODO cleanup mutable CCriticalSection minableCommitmentsCs; @@ -46,7 +46,7 @@ class CQuorumBlockProcessor mutable std::map> mapHasMinedCommitmentCache GUARDED_BY(minableCommitmentsCs); public: - explicit CQuorumBlockProcessor(CEvoDB& _evoDb, CConnman& _connman, const std::unique_ptr& peer_logic); + explicit CQuorumBlockProcessor(CEvoDB& _evoDb, CConnman& _connman, const std::unique_ptr& peerman); bool UpgradeDB(); diff --git a/src/llmq/chainlocks.cpp b/src/llmq/chainlocks.cpp index 105925384107..f4022be19ae4 100644 --- a/src/llmq/chainlocks.cpp +++ b/src/llmq/chainlocks.cpp @@ -27,7 +27,7 @@ std::unique_ptr chainLocksHandler; CChainLocksHandler::CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, CSigningManager& _sigman, CSigSharesManager& _shareman, CQuorumManager& _qman, const std::unique_ptr& mn_sync, - const std::unique_ptr& peer_logic) : + const std::unique_ptr& peerman) : connman(_connman), mempool(_mempool), spork_manager(sporkManager), @@ -35,7 +35,7 @@ CChainLocksHandler::CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, shareman(_shareman), qman(_qman), m_mn_sync(mn_sync), - m_peer_logic(peer_logic), + m_peerman(peerman), scheduler(std::make_unique()), scheduler_thread(std::make_unique([&] { TraceThread("cl-schdlr", [&] { scheduler->serviceQueue(); }); })) { @@ -129,7 +129,7 @@ void CChainLocksHandler::ProcessNewChainLock(const NodeId from, const llmq::CCha if (!VerifyChainLock(clsig)) { LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- invalid CLSIG (%s), peer=%d\n", __func__, clsig.ToString(), from); if (from != -1) { - Misbehaving(from, 10); + m_peerman->Misbehaving(from, 10); } return; } diff --git a/src/llmq/chainlocks.h b/src/llmq/chainlocks.h index 88ebf963e4cb..e7bf421e9eca 100644 --- a/src/llmq/chainlocks.h +++ b/src/llmq/chainlocks.h @@ -25,7 +25,7 @@ class CMasternodeSync; class CScheduler; class CSporkManager; class CTxMemPool; -class PeerLogicValidation; +class PeerManager; namespace llmq { @@ -50,7 +50,7 @@ class CChainLocksHandler : public CRecoveredSigsListener CQuorumManager& qman; const std::unique_ptr& m_mn_sync; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; std::unique_ptr scheduler; std::unique_ptr scheduler_thread; @@ -87,7 +87,7 @@ class CChainLocksHandler : public CRecoveredSigsListener explicit CChainLocksHandler(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, CSigningManager& _sigman, CSigSharesManager& _shareman, CQuorumManager& _qman, const std::unique_ptr& mn_sync, - const std::unique_ptr& peer_logic); + const std::unique_ptr& peerman); ~CChainLocksHandler(); void Start(); diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index d52d3834f6f1..f2fc033f7907 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -20,8 +20,8 @@ #include LLMQContext::LLMQContext(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, - const std::unique_ptr& peer_logic, bool unit_tests, bool wipe) { - Create(evo_db, mempool, connman, sporkman, peer_logic, unit_tests, wipe); + const std::unique_ptr& peerman, bool unit_tests, bool wipe) { + Create(evo_db, mempool, connman, sporkman, peerman, unit_tests, wipe); /* Context aliases to globals used by the LLMQ system */ quorum_block_processor = llmq::quorumBlockProcessor.get(); @@ -40,17 +40,17 @@ LLMQContext::~LLMQContext() { } void LLMQContext::Create(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, - const std::unique_ptr& peer_logic, bool unit_tests, bool wipe) { + const std::unique_ptr& peerman, bool unit_tests, bool wipe) { bls_worker = std::make_shared(); dkg_debugman = std::make_unique(); - llmq::quorumBlockProcessor = std::make_unique(evo_db, connman, peer_logic); - qdkgsman = std::make_unique(connman, *bls_worker, *dkg_debugman, *llmq::quorumBlockProcessor, sporkman, peer_logic, unit_tests, wipe); - llmq::quorumManager = std::make_unique(evo_db, connman, *bls_worker, *llmq::quorumBlockProcessor, *qdkgsman, ::masternodeSync, peer_logic); - sigman = std::make_unique(connman, *llmq::quorumManager, peer_logic, unit_tests, wipe); - shareman = std::make_unique(connman, *llmq::quorumManager, *sigman, peer_logic); - llmq::chainLocksHandler = std::make_unique(mempool, connman, sporkman, *sigman, *shareman, *llmq::quorumManager, ::masternodeSync, peer_logic); - llmq::quorumInstantSendManager = std::make_unique(mempool, connman, sporkman, *llmq::quorumManager, *sigman, *shareman, *llmq::chainLocksHandler, ::masternodeSync, peer_logic, unit_tests, wipe); + llmq::quorumBlockProcessor = std::make_unique(evo_db, connman, peerman); + qdkgsman = std::make_unique(connman, *bls_worker, *dkg_debugman, *llmq::quorumBlockProcessor, sporkman, peerman, unit_tests, wipe); + llmq::quorumManager = std::make_unique(evo_db, connman, *bls_worker, *llmq::quorumBlockProcessor, *qdkgsman, ::masternodeSync, peerman); + sigman = std::make_unique(connman, *llmq::quorumManager, peerman, unit_tests, wipe); + shareman = std::make_unique(connman, *llmq::quorumManager, *sigman, peerman); + llmq::chainLocksHandler = std::make_unique(mempool, connman, sporkman, *sigman, *shareman, *llmq::quorumManager, ::masternodeSync, peerman); + llmq::quorumInstantSendManager = std::make_unique(mempool, connman, sporkman, *llmq::quorumManager, *sigman, *shareman, *llmq::chainLocksHandler, ::masternodeSync, peerman, unit_tests, wipe); // NOTE: we use this only to wipe the old db, do NOT use it for anything else // TODO: remove it in some future version diff --git a/src/llmq/context.h b/src/llmq/context.h index 19042dc7b72d..08e256a95e3a 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -13,7 +13,7 @@ class CDBWrapper; class CEvoDB; class CTxMemPool; class CSporkManager; -class PeerLogicValidation; +class PeerManager; namespace llmq { class CDKGDebugManager; @@ -28,11 +28,11 @@ class CInstantSendManager; struct LLMQContext { LLMQContext(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, - const std::unique_ptr& peer_logic, bool unit_tests, bool wipe); + const std::unique_ptr& peerman, bool unit_tests, bool wipe); ~LLMQContext(); void Create(CEvoDB& evo_db, CTxMemPool& mempool, CConnman& connman, CSporkManager& sporkman, - const std::unique_ptr& peer_logic, bool unit_tests, bool wipe); + const std::unique_ptr& peerman, bool unit_tests, bool wipe); void Destroy(); void Interrupt(); void Start(); diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index 5abd29874239..2329021474dd 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -23,7 +23,7 @@ namespace llmq CDKGSessionHandler::CDKGSessionHandler(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, - CConnman& _connman, const std::unique_ptr& peer_logic, int _quorumIndex) : + CConnman& _connman, const std::unique_ptr& peerman, int _quorumIndex) : params(_params), connman(_connman), quorumIndex(_quorumIndex), @@ -31,7 +31,7 @@ CDKGSessionHandler::CDKGSessionHandler(const Consensus::LLMQParams& _params, CBL dkgManager(_dkgManager), dkgDebugManager(_dkgDebugManager), quorumBlockProcessor(_quorumBlockProcessor), - m_peer_logic(peer_logic), + m_peerman(peerman), curSession(std::make_unique(_params, _blsWorker, _dkgManager, _dkgDebugManager, _connman)), 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), @@ -416,7 +416,7 @@ std::set BatchVerifyMessageSigs(CDKGSession& session, const std::vector< } template -bool ProcessPendingMessageBatch(CDKGSession& session, PeerLogicValidation& peer_logic, CDKGPendingMessages& pendingMessages, size_t maxCount) +bool ProcessPendingMessageBatch(CDKGSession& session, PeerManager& peerman, CDKGPendingMessages& pendingMessages, size_t maxCount) { auto msgs = pendingMessages.PopAndDeserializeMessages(maxCount); if (msgs.empty()) { @@ -431,7 +431,7 @@ bool ProcessPendingMessageBatch(CDKGSession& session, PeerLogicValidation& peer_ if (!p.second) { LogPrint(BCLog::LLMQ_DKG, "%s -- failed to deserialize message, peer=%d\n", __func__, nodeId); { - Misbehaving(nodeId, 100); + peerman.Misbehaving(nodeId, 100); } continue; } @@ -440,7 +440,7 @@ bool ProcessPendingMessageBatch(CDKGSession& session, PeerLogicValidation& peer_ if (ban) { LogPrint(BCLog::LLMQ_DKG, "%s -- banning node due to failed preverification, peer=%d\n", __func__, nodeId); { - Misbehaving(nodeId, 100); + peerman.Misbehaving(nodeId, 100); } } LogPrint(BCLog::LLMQ_DKG, "%s -- skipping message due to failed preverification, peer=%d\n", __func__, nodeId); @@ -457,7 +457,7 @@ bool ProcessPendingMessageBatch(CDKGSession& session, PeerLogicValidation& peer_ LOCK(cs_main); for (auto nodeId : badNodes) { LogPrint(BCLog::LLMQ_DKG, "%s -- failed to verify signature, peer=%d\n", __func__, nodeId); - Misbehaving(nodeId, 100); + peerman.Misbehaving(nodeId, 100); } } @@ -470,7 +470,7 @@ bool ProcessPendingMessageBatch(CDKGSession& session, PeerLogicValidation& peer_ session.ReceiveMessage(*p.second, ban); if (ban) { LogPrint(BCLog::LLMQ_DKG, "%s -- banning node after ReceiveMessage failed, peer=%d\n", __func__, nodeId); - Misbehaving(nodeId, 100); + peerman.Misbehaving(nodeId, 100); badNodes.emplace(nodeId); } } @@ -519,7 +519,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->Contribute(pendingContributions); }; auto fContributeWait = [this] { - return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingContributions, 8); + return ProcessPendingMessageBatch(*curSession, *m_peerman, pendingContributions, 8); }; HandlePhase(QuorumPhase::Contribute, QuorumPhase::Complain, curQuorumHash, 0.05, fContributeStart, fContributeWait); @@ -528,7 +528,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndComplain(pendingComplaints); }; auto fComplainWait = [this] { - return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingComplaints, 8); + return ProcessPendingMessageBatch(*curSession, *m_peerman, pendingComplaints, 8); }; HandlePhase(QuorumPhase::Complain, QuorumPhase::Justify, curQuorumHash, 0.05, fComplainStart, fComplainWait); @@ -537,7 +537,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndJustify(pendingJustifications); }; auto fJustifyWait = [this] { - return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingJustifications, 8); + return ProcessPendingMessageBatch(*curSession, *m_peerman, pendingJustifications, 8); }; HandlePhase(QuorumPhase::Justify, QuorumPhase::Commit, curQuorumHash, 0.05, fJustifyStart, fJustifyWait); @@ -546,7 +546,7 @@ void CDKGSessionHandler::HandleDKGRound() curSession->VerifyAndCommit(pendingPrematureCommitments); }; auto fCommitWait = [this] { - return ProcessPendingMessageBatch(*curSession, *m_peer_logic, pendingPrematureCommitments, 8); + return ProcessPendingMessageBatch(*curSession, *m_peerman, pendingPrematureCommitments, 8); }; HandlePhase(QuorumPhase::Commit, QuorumPhase::Finalize, curQuorumHash, 0.1, fCommitStart, fCommitWait); diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index 598c6df7d14a..508dc6bf8e7a 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -13,7 +13,7 @@ class CBLSWorker; class CBlockIndex; -class PeerLogicValidation; +class PeerManager; namespace llmq { @@ -118,7 +118,7 @@ class CDKGSessionHandler CDKGDebugManager& dkgDebugManager; CQuorumBlockProcessor& quorumBlockProcessor; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; QuorumPhase phase GUARDED_BY(cs) {QuorumPhase::Idle}; int currentHeight GUARDED_BY(cs) {-1}; @@ -136,7 +136,7 @@ class CDKGSessionHandler public: CDKGSessionHandler(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, - CConnman& _connman, const std::unique_ptr& peer_logic, int _quorumIndex); + CConnman& _connman, const std::unique_ptr& peerman, int _quorumIndex); ~CDKGSessionHandler() = default; void UpdatedBlockTip(const CBlockIndex *pindexNew); diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index f280c284a267..83a24f8655c4 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -24,14 +24,14 @@ static const std::string DB_ENC_CONTRIB = "qdkg_E"; CDKGSessionManager::CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorker, CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, CSporkManager& sporkManager, - const std::unique_ptr& peer_logic, bool unitTests, bool fWipe) : + const std::unique_ptr& peerman, bool unitTests, bool fWipe) : db(std::make_unique(unitTests ? "" : (GetDataDir() / "llmq/dkgdb"), 1 << 20, unitTests, fWipe)), blsWorker(_blsWorker), connman(_connman), spork_manager(sporkManager), dkgDebugManager(_dkgDebugManager), quorumBlockProcessor(_quorumBlockProcessor), - m_peer_logic(peer_logic) + m_peerman(peerman) { if (!fMasternodeMode && !utils::IsWatchQuorumsEnabled()) { // Regular nodes do not care about any DKG internals, bail out @@ -46,7 +46,7 @@ CDKGSessionManager::CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorke for (const auto i : irange::range(session_count)) { dkgSessionHandlers.emplace(std::piecewise_construct, std::forward_as_tuple(params.type, i), - std::forward_as_tuple(params, blsWorker, *this, dkgDebugManager, quorumBlockProcessor, connman, peer_logic, i)); + std::forward_as_tuple(params, blsWorker, *this, dkgDebugManager, quorumBlockProcessor, connman, peerman, i)); } } } @@ -192,7 +192,7 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor } if (vRecv.empty()) { - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); return; } @@ -206,7 +206,7 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor const auto& llmq_params_opt = GetLLMQParams(llmqType); if (!llmq_params_opt.has_value()) { LogPrintf("CDKGSessionManager -- invalid llmqType [%d]\n", ToUnderlying(llmqType)); - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); return; } const auto& llmq_params = llmq_params_opt.value(); @@ -228,13 +228,13 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor if (pQuorumBaseBlockIndex == nullptr) { LogPrintf("CDKGSessionManager -- unknown quorumHash %s\n", quorumHash.ToString()); // NOTE: do not insta-ban for this, we might be lagging behind - Misbehaving(pfrom.GetId(), 10); + m_peerman->Misbehaving(pfrom.GetId(), 10); return; } if (!utils::IsQuorumTypeEnabled(llmqType, quorum_manager, pQuorumBaseBlockIndex->pprev)) { LogPrintf("CDKGSessionManager -- llmqType [%d] quorums aren't active\n", ToUnderlying(llmqType)); - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); return; } @@ -244,13 +244,13 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor if (quorumIndex > quorumIndexMax) { LogPrintf("CDKGSessionManager -- invalid quorumHash %s\n", quorumHash.ToString()); - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); return; } if (!dkgSessionHandlers.count(std::make_pair(llmqType, quorumIndex))) { LogPrintf("CDKGSessionManager -- no session handlers for quorumIndex [%d]\n", quorumIndex); - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); return; } } diff --git a/src/llmq/dkgsessionmgr.h b/src/llmq/dkgsessionmgr.h index c18caf54cafe..1c0b41683f36 100644 --- a/src/llmq/dkgsessionmgr.h +++ b/src/llmq/dkgsessionmgr.h @@ -13,7 +13,7 @@ class CBlockIndex; class CDKGDebugManager; class CSporkManager; -class PeerLogicValidation; +class PeerManager; class UniValue; @@ -33,7 +33,7 @@ class CDKGSessionManager CDKGDebugManager& dkgDebugManager; CQuorumBlockProcessor& quorumBlockProcessor; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; //TODO name struct instead of std::pair std::map, CDKGSessionHandler> dkgSessionHandlers; @@ -60,7 +60,7 @@ class CDKGSessionManager public: CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorker, CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, CSporkManager& sporkManager, - const std::unique_ptr& peer_logic, bool unitTests, bool fWipe); + const std::unique_ptr& peerman, bool unitTests, bool fWipe); ~CDKGSessionManager() = default; void StartThreads(); diff --git a/src/llmq/instantsend.cpp b/src/llmq/instantsend.cpp index 44716d36e20e..aa1ec46f302a 100644 --- a/src/llmq/instantsend.cpp +++ b/src/llmq/instantsend.cpp @@ -790,7 +790,7 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons } if (!islock->TriviallyValid()) { - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); return; } @@ -799,7 +799,7 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons const auto blockIndex = WITH_LOCK(cs_main, return g_chainman.m_blockman.LookupBlockIndex(islock->cycleHash)); if (blockIndex == nullptr) { // Maybe we don't have the block yet or maybe some peer spams invalid values for cycleHash - Misbehaving(pfrom.GetId(), 1); + m_peerman->Misbehaving(pfrom.GetId(), 1); return; } @@ -808,7 +808,7 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons const auto& llmq_params_opt = GetLLMQParams(llmqType); assert(llmq_params_opt); if (blockIndex->nHeight % llmq_params_opt->dkgInterval != 0) { - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); return; } } @@ -1010,7 +1010,7 @@ std::unordered_set CInstantSendManager::ProcessPend for (const auto& nodeId : batchVerifier.badSources) { // Let's not be too harsh, as the peer might simply be unlucky and might have sent us an old lock which // does not validate anymore due to changed quorums - Misbehaving(nodeId, 20); + m_peerman->Misbehaving(nodeId, 20); } } for (const auto& p : pend) { diff --git a/src/llmq/instantsend.h b/src/llmq/instantsend.h index 0732e236e52b..dda6e535c4c8 100644 --- a/src/llmq/instantsend.h +++ b/src/llmq/instantsend.h @@ -20,7 +20,7 @@ class CMasternodeSync; class CSporkManager; -class PeerLogicValidation; +class PeerManager; namespace llmq { @@ -212,7 +212,7 @@ class CInstantSendManager : public CRecoveredSigsListener CChainLocksHandler& clhandler; const std::unique_ptr& m_mn_sync; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; std::atomic fUpgradedDB{false}; @@ -263,9 +263,9 @@ class CInstantSendManager : public CRecoveredSigsListener explicit CInstantSendManager(CTxMemPool& _mempool, CConnman& _connman, CSporkManager& sporkManager, CQuorumManager& _qman, CSigningManager& _sigman, CSigSharesManager& _shareman, CChainLocksHandler& _clhandler, const std::unique_ptr& mn_sync, - const std::unique_ptr& peer_logic, bool unitTests, bool fWipe) : + const std::unique_ptr& peerman, bool unitTests, bool fWipe) : db(unitTests, fWipe), connman(_connman), mempool(_mempool), spork_manager(sporkManager), qman(_qman), sigman(_sigman), shareman(_shareman), - clhandler(_clhandler), m_mn_sync(mn_sync), m_peer_logic(peer_logic) + clhandler(_clhandler), m_mn_sync(mn_sync), m_peerman(peerman) { workInterrupt.reset(); } diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 5a5de34fbf3b..a617037236f2 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -189,14 +189,14 @@ bool CQuorum::ReadContributions(CEvoDB& evoDb) CQuorumManager::CQuorumManager(CEvoDB& _evoDb, CConnman& _connman, CBLSWorker& _blsWorker, CQuorumBlockProcessor& _quorumBlockProcessor, CDKGSessionManager& _dkgManager, const std::unique_ptr& mn_sync, - const std::unique_ptr& peer_logic) : + const std::unique_ptr& peerman) : m_evoDb(_evoDb), connman(_connman), blsWorker(_blsWorker), dkgManager(_dkgManager), quorumBlockProcessor(_quorumBlockProcessor), m_mn_sync(mn_sync), - m_peer_logic(peer_logic) + m_peerman(peerman) { utils::InitQuorumsCache(mapQuorumsCache); utils::InitQuorumsCache(scanQuorumsCache); @@ -620,7 +620,7 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C auto errorHandler = [&](const std::string& strError, int nScore = 10) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- %s: %s, from peer=%d\n", strFunc, msg_type, strError, pfrom.GetId()); if (nScore > 0) { - Misbehaving(pfrom.GetId(), nScore); + m_peerman->Misbehaving(pfrom.GetId(), nScore); } }; diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 652c2bca9d69..444b52d28d9d 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -21,7 +21,7 @@ class CBlockIndex; class CDeterministicMN; class CMasternodeSync; class CNode; -class PeerLogicValidation; +class PeerManager; using CDeterministicMNCPtr = std::shared_ptr; @@ -219,7 +219,7 @@ class CQuorumManager CQuorumBlockProcessor& quorumBlockProcessor; const std::unique_ptr& m_mn_sync; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; mutable CCriticalSection cs_map_quorums; mutable std::map> mapQuorumsCache GUARDED_BY(cs_map_quorums); @@ -232,7 +232,7 @@ class CQuorumManager public: CQuorumManager(CEvoDB& _evoDb, CConnman& _connman, CBLSWorker& _blsWorker, CQuorumBlockProcessor& _quorumBlockProcessor, CDKGSessionManager& _dkgManager, const std::unique_ptr& mnSync, - const std::unique_ptr& peer_logic); + const std::unique_ptr& peerman); ~CQuorumManager() { Stop(); }; void Start(); diff --git a/src/llmq/signing.cpp b/src/llmq/signing.cpp index 960c214df056..2cc53600cde8 100644 --- a/src/llmq/signing.cpp +++ b/src/llmq/signing.cpp @@ -527,9 +527,9 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge) ////////////////// CSigningManager::CSigningManager(CConnman& _connman, const CQuorumManager& _qman, - const std::unique_ptr& peer_logic, + const std::unique_ptr& peerman, bool fMemory, bool fWipe) : - db(fMemory, fWipe), connman(_connman), qman(_qman), m_peer_logic(peer_logic) + db(fMemory, fWipe), connman(_connman), qman(_qman), m_peerman(peerman) { } @@ -579,7 +579,7 @@ void CSigningManager::ProcessMessageRecoveredSig(const CNode& pfrom, const std:: bool ban = false; if (!PreVerifyRecoveredSig(qman, *recoveredSig, ban)) { if (ban) { - Misbehaving(pfrom.GetId(), 100); + m_peerman->Misbehaving(pfrom.GetId(), 100); } return; } @@ -753,7 +753,7 @@ bool CSigningManager::ProcessPendingRecoveredSigs() if (batchVerifier.badSources.count(nodeId)) { LogPrint(BCLog::LLMQ, "CSigningManager::%s -- invalid recSig from other node, banning peer=%d\n", __func__, nodeId); - Misbehaving(nodeId, 100); + m_peerman->Misbehaving(nodeId, 100); continue; } diff --git a/src/llmq/signing.h b/src/llmq/signing.h index 3fd16ee93f37..b06469aefa05 100644 --- a/src/llmq/signing.h +++ b/src/llmq/signing.h @@ -20,7 +20,7 @@ class CConnman; class CInv; class CNode; -class PeerLogicValidation; +class PeerManager; using NodeId = int64_t; @@ -170,7 +170,7 @@ class CSigningManager CConnman& connman; const CQuorumManager& qman; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; // Incoming and not verified yet std::unordered_map>> pendingRecoveredSigs GUARDED_BY(cs); @@ -184,7 +184,7 @@ class CSigningManager public: CSigningManager(CConnman& _connman, const CQuorumManager& _qman, - const std::unique_ptr& peer_logic, bool fMemory, bool fWipe); + const std::unique_ptr& peerman, bool fMemory, bool fWipe); bool AlreadyHave(const CInv& inv) const; bool GetRecoveredSigForGetData(const uint256& hash, CRecoveredSig& ret) const; diff --git a/src/llmq/signing_shares.cpp b/src/llmq/signing_shares.cpp index ed7b5adf1932..c407be20db74 100644 --- a/src/llmq/signing_shares.cpp +++ b/src/llmq/signing_shares.cpp @@ -1409,7 +1409,7 @@ void CSigSharesManager::BanNode(NodeId nodeId) } { - Misbehaving(nodeId, 100); + m_peerman->Misbehaving(nodeId, 100); } LOCK(cs); diff --git a/src/llmq/signing_shares.h b/src/llmq/signing_shares.h index b498b65c0385..b595be906e4f 100644 --- a/src/llmq/signing_shares.h +++ b/src/llmq/signing_shares.h @@ -23,7 +23,7 @@ class CDeterministicMN; class CEvoDB; class CScheduler; class CSporkManager; -class PeerLogicValidation; +class PeerManager; using CDeterministicMNCPtr = std::shared_ptr; @@ -401,14 +401,14 @@ class CSigSharesManager : public CRecoveredSigsListener const CQuorumManager& qman; CSigningManager& sigman; - const std::unique_ptr& m_peer_logic; + const std::unique_ptr& m_peerman; int64_t lastCleanupTime{0}; std::atomic recoveredSigsCounter{0}; public: - explicit CSigSharesManager(CConnman& _connman, CQuorumManager& _qman, CSigningManager& _sigman, const std::unique_ptr& peer_logic) : - connman(_connman), qman(_qman), sigman(_sigman), m_peer_logic(peer_logic) + explicit CSigSharesManager(CConnman& _connman, CQuorumManager& _qman, CSigningManager& _sigman, const std::unique_ptr& peerman) : + connman(_connman), qman(_qman), sigman(_sigman), m_peerman(peerman) { workInterrupt.reset(); }; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index a65087a7c39a..434d65f8433c 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -937,7 +937,7 @@ static bool IsOutboundDisconnectionCandidate(const CNode& node) return !(node.fInbound || node.m_manual_connection || node.fFeeler || node.fOneShot); } -void PeerLogicValidation::InitializeNode(CNode *pnode) { +void PeerManager::InitializeNode(CNode *pnode) { CAddress addr = pnode->addr; NodeId nodeid = pnode->GetId(); { @@ -953,7 +953,7 @@ void PeerLogicValidation::InitializeNode(CNode *pnode) { PushNodeVersion(*pnode, m_connman, GetTime()); } -void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const +void PeerManager::ReattemptInitialBroadcast(CScheduler& scheduler) const { std::set unbroadcast_txids = m_mempool.GetUnbroadcastTxs(); @@ -972,7 +972,7 @@ void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta); } -void PeerLogicValidation::FinalizeNode(const CNode& node) { +void PeerManager::FinalizeNode(const CNode& node) { NodeId nodeid = node.GetId(); int misbehavior{0}; LOCK(cs_main); @@ -1183,12 +1183,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphansSize) return nEvicted; } -void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans); - -/** - * Increment peer's misbehavior score. If the new value surpasses banscore (specified on startup or by default), mark node to be discouraged, meaning the peer might be disconnected & added to the discouragement filter. - */ -void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) +void PeerManager::Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) { assert(howmuch > 0); @@ -1222,17 +1217,8 @@ bool IsBanned(NodeId pnode) return false; } -/** - * Potentially mark a node discouraged based on the contents of a BlockValidationState object - * - * @param[in] via_compact_block this bool is passed in because net_processing should - * punish peers differently depending on whether the data was provided in a compact - * block message or not. If the compact block had a valid header, but contained invalid - * txs, the peer should not be punished. See BIP 152. - * - * @return Returns true if the peer was punished (probably disconnected) - */ -static bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, bool via_compact_block, const std::string& message = "") +bool PeerManager::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, + bool via_compact_block, const std::string& message) { switch (state.GetResult()) { case BlockValidationResult::BLOCK_RESULT_UNSET: @@ -1281,14 +1267,7 @@ static bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& s return false; } -/** - * Potentially ban a node based on the contents of a TxValidationState object - * - * @return Returns true if the peer was punished (probably disconnected) - * - * Changes here may need to be reflected in TxRelayMayResultInDisconnect(). - */ -static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "") { +bool PeerManager::MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message) { switch (state.GetResult()) { case TxValidationResult::TX_RESULT_UNSET: break; @@ -1335,9 +1314,10 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT); } -PeerLogicValidation::PeerLogicValidation(CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, - std::unique_ptr& llmq_ctx) - : m_connman(connman), +PeerManager::PeerManager(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, + std::unique_ptr& llmq_ctx) + : m_chainparams(chainparams), + m_connman(connman), m_addrman(addrman), m_banman(banman), m_chainman(chainman), @@ -1375,7 +1355,7 @@ PeerLogicValidation::PeerLogicValidation(CConnman& connman, CAddrMan& addrman, B * Evict orphan txn pool entries (EraseOrphanTx) based on a newly connected * block. Also save the time of the last tip update. */ -void PeerLogicValidation::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) +void PeerManager::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) { { LOCK2(cs_main, g_cs_orphans); @@ -1418,7 +1398,7 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr& pb while (!orphanWorkSet.empty()) { LogPrint(BCLog::MEMPOOL, "Trying to process %d orphans\n", orphanWorkSet.size()); - ProcessOrphanTx(m_connman, m_mempool, orphanWorkSet); + ProcessOrphanTx(orphanWorkSet); } g_last_tip_update = GetTime(); @@ -1431,7 +1411,7 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr& pb } } -void PeerLogicValidation::BlockDisconnected(const std::shared_ptr &block, const CBlockIndex* pindex) +void PeerManager::BlockDisconnected(const std::shared_ptr &block, const CBlockIndex* pindex) { // To avoid relay problems with transactions that were previously // confirmed, clear our filter of recently confirmed transactions whenever @@ -1455,7 +1435,7 @@ static uint256 most_recent_block_hash GUARDED_BY(cs_most_recent_block); * Maintain state about the best-seen block and fast-announce a compact block * to compatible peers. */ -void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) { +void PeerManager::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) { std::shared_ptr pcmpctblock = std::make_shared (*pblock); const CNetMsgMaker msgMaker(PROTOCOL_VERSION); @@ -1487,7 +1467,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std: if (state.fPreferHeaderAndIDs && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->pprev)) { - LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", "PeerLogicValidation::NewPoWValidBlock", + LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", "PeerManager::NewPoWValidBlock", hashBlock.ToString(), pnode->GetId()); m_connman.PushMessage(pnode, msgMaker.Make(NetMsgType::CMPCTBLOCK, *pcmpctblock)); state.pindexBestHeaderSent = pindex; @@ -1499,7 +1479,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std: * Update our best height and announce any block hashes which weren't previously * in ::ChainActive() to our peers. */ -void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { +void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { const int nNewHeight = pindexNew->nHeight; m_connman.SetBestHeight(nNewHeight); @@ -1536,7 +1516,7 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB * Handle invalid block rejection and consequent peer discouragement, maintain which * peers announce compact blocks. */ -void PeerLogicValidation::BlockChecked(const CBlock& block, const BlockValidationState& state) { +void PeerManager::BlockChecked(const CBlock& block, const BlockValidationState& state) { LOCK(cs_main); const uint256 hash(block.GetHash()); @@ -2081,7 +2061,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm } } -inline void static SendBlockTransactions(const CBlock& block, const BlockTransactionsRequest& req, CNode& pfrom, CConnman& connman) { +void PeerManager::SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req) { BlockTransactions resp(req); for (size_t i = 0; i < req.indexes.size(); i++) { if (req.indexes[i] >= block.vtx.size()) { @@ -2092,10 +2072,10 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac } LOCK(cs_main); CNetMsgMaker msgMaker(pfrom.GetSendVersion()); - connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCKTXN, resp)); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCKTXN, resp)); } -static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateManager& chainman, CTxMemPool& mempool, const std::vector& headers, const CChainParams& chainparams, bool via_compact_block) +void PeerManager::ProcessHeadersMessage(CNode& pfrom, const std::vector& headers, bool via_compact_block) { const CNetMsgMaker msgMaker(pfrom.GetSendVersion()); size_t nCount = headers.size(); @@ -2122,7 +2102,7 @@ static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateMan if (!g_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) { nodestate->nUnconnectingHeaders++; std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS; - connman.PushMessage(&pfrom, msgMaker.Make(msg_type, ::ChainActive().GetLocator(pindexBestHeader), uint256())); + m_connman.PushMessage(&pfrom, msgMaker.Make(msg_type, ::ChainActive().GetLocator(pindexBestHeader), uint256())); LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending %s (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n", headers[0].GetHash().ToString(), headers[0].hashPrevBlock.ToString(), @@ -2157,7 +2137,7 @@ static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateMan } BlockValidationState state; - if (!chainman.ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast)) { + if (!m_chainman.ProcessNewBlockHeaders(headers, state, m_chainparams, &pindexLast)) { if (state.IsInvalid()) { MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received"); return; @@ -2189,10 +2169,10 @@ static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateMan // from there instead. std::string msg_type = (pfrom.nServices & NODE_HEADERS_COMPRESSED) ? NetMsgType::GETHEADERS2 : NetMsgType::GETHEADERS; LogPrint(BCLog::NET, "more %s (%d) to end to peer=%d (startheight:%d)\n", msg_type, pindexLast->nHeight, pfrom.GetId(), pfrom.nStartingHeight); - connman.PushMessage(&pfrom, msgMaker.Make(msg_type, ::ChainActive().GetLocator(pindexLast), uint256())); + m_connman.PushMessage(&pfrom, msgMaker.Make(msg_type, ::ChainActive().GetLocator(pindexLast), uint256())); } - bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus()); + bool fCanDirectFetch = CanDirectFetch(m_chainparams.GetConsensus()); // If this set of headers is valid and ends in a block with at least as // much work as our tip, download as much as possible. if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && ::ChainActive().Tip()->nChainWork <= pindexLast->nChainWork) { @@ -2224,7 +2204,7 @@ static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateMan break; } vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); - MarkBlockAsInFlight(mempool, pfrom.GetId(), pindex->GetBlockHash(), pindex); + MarkBlockAsInFlight(m_mempool, pfrom.GetId(), pindex->GetBlockHash(), pindex); LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", pindex->GetBlockHash().ToString(), pfrom.GetId()); } @@ -2237,7 +2217,7 @@ static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateMan // In any case, we want to download using a compact block, not a regular one vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash); } - connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData)); + m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData)); } } } @@ -2278,7 +2258,7 @@ static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateMan return; } -void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans) +void PeerManager::ProcessOrphanTx(std::set& orphan_work_set) { AssertLockHeld(cs_main); AssertLockHeld(g_cs_orphans); @@ -2300,10 +2280,10 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set static ValidateDSTX(CTxMemPool& memp return {true, false}; } -void PeerLogicValidation::ProcessMessage( +void PeerManager::ProcessMessage( CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, - const CChainParams& chainparams, const std::atomic& interruptMsgProc) { LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom.GetId()); @@ -3067,7 +3046,7 @@ void PeerLogicValidation::ProcessMessage( if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) { // Make sure to mark this peer as the one we are currently syncing with etc. state->fSyncStarted = true; - state->nHeadersSyncTimeout = GetTimeMicros() + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(chainparams.GetConsensus().nPowTargetSpacing); + state->nHeadersSyncTimeout = GetTimeMicros() + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(m_chainparams.GetConsensus().nPowTargetSpacing); nSyncStarted++; // We used to request the full block here, but since headers-announcements are now the // primary method of announcement on the network, and since, in the case that a node @@ -3128,7 +3107,7 @@ void PeerLogicValidation::ProcessMessage( } pfrom.vRecvGetData.insert(pfrom.vRecvGetData.end(), vInv.begin(), vInv.end()); - ProcessGetData(pfrom, chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); + ProcessGetData(pfrom, m_chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); return; } @@ -3181,7 +3160,7 @@ void PeerLogicValidation::ProcessMessage( } // If pruning, don't inv blocks unless we have on disk and are likely to still have // for some reasonable time window (1 hour) that block relay might require. - const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus().nPowTargetSpacing; + const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / m_chainparams.GetConsensus().nPowTargetSpacing; if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= ::ChainActive().Tip()->nHeight - nPrunedBlocksLikelyToHave)) { LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); @@ -3214,7 +3193,7 @@ void PeerLogicValidation::ProcessMessage( // Unlock cs_most_recent_block to avoid cs_main lock inversion } if (recent_block) { - SendBlockTransactions(*recent_block, req, pfrom, m_connman); + SendBlockTransactions(pfrom, *recent_block, req); return; } @@ -3244,10 +3223,10 @@ void PeerLogicValidation::ProcessMessage( } CBlock block; - bool ret = ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()); + bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus()); assert(ret); - SendBlockTransactions(block, req, pfrom, m_connman); + SendBlockTransactions(pfrom, block, req); return; } @@ -3278,7 +3257,7 @@ void PeerLogicValidation::ProcessMessage( return; } - if (!BlockRequestAllowed(pindex, chainparams.GetConsensus())) { + if (!BlockRequestAllowed(pindex, m_chainparams.GetConsensus())) { LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.GetId()); return; } @@ -3403,7 +3382,7 @@ void PeerLogicValidation::ProcessMessage( m_mempool.size(), m_mempool.DynamicMemoryUsage() / 1000); // Recursively process any orphan transactions that depended on this one - ProcessOrphanTx(m_connman, m_mempool, pfrom.orphan_work_set); + ProcessOrphanTx(pfrom.orphan_work_set); } else if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) { @@ -3520,7 +3499,7 @@ void PeerLogicValidation::ProcessMessage( const CBlockIndex *pindex = nullptr; BlockValidationState state; - if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) { + if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, m_chainparams, &pindex)) { if (state.IsInvalid()) { MaybePunishNodeForBlock(pfrom.GetId(), state, /*via_compact_block*/ true, "invalid header via cmpctblock"); return; @@ -3576,7 +3555,7 @@ void PeerLogicValidation::ProcessMessage( } // If we're not close to tip yet, give up and let parallel block fetch work its magic - if (!fAlreadyInFlight && !CanDirectFetch(chainparams.GetConsensus())) + if (!fAlreadyInFlight && !CanDirectFetch(m_chainparams.GetConsensus())) return; // We want to be a bit conservative just to be extra careful about DoS @@ -3658,7 +3637,7 @@ void PeerLogicValidation::ProcessMessage( } // cs_main if (fProcessBLOCKTXN) - return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, interruptMsgProc); + return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, interruptMsgProc); if (fRevertToHeaderProcessing) { // Headers received from HB compact block peers are permitted to be @@ -3666,7 +3645,7 @@ void PeerLogicValidation::ProcessMessage( // the peer if the header turns out to be for an invalid block. // Note that if a peer tries to build on an invalid chain, that // will be detected and the peer will be disconnected/discouraged. - return ProcessHeadersMessage(pfrom, m_connman, m_chainman, m_mempool, {cmpctblock.header}, chainparams, /*punish_duplicate_invalid=*/true); + return ProcessHeadersMessage(pfrom, {cmpctblock.header}, /*punish_duplicate_invalid=*/true); } if (fBlockReconstructed) { @@ -3686,7 +3665,7 @@ void PeerLogicValidation::ProcessMessage( // we have a chain with at least nMinimumChainWork), and we ignore // compact blocks with less work than our tip, it is safe to treat // reconstructed compact blocks as having been requested. - m_chainman.ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); + m_chainman.ProcessNewBlock(m_chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); if (fNewBlock) { pfrom.nLastBlockTime = GetTime(); } else { @@ -3776,7 +3755,7 @@ void PeerLogicValidation::ProcessMessage( // disk-space attacks), but this should be safe due to the // protections in the compact block handler -- see related comment // in compact block optimistic reconstruction handling. - m_chainman.ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); + m_chainman.ProcessNewBlock(m_chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); if (fNewBlock) { pfrom.nLastBlockTime = GetTime(); } else { @@ -3819,7 +3798,7 @@ void PeerLogicValidation::ProcessMessage( } } - return ProcessHeadersMessage(pfrom, m_connman, m_chainman, m_mempool, headers, chainparams, /*via_compact_block=*/false); + return ProcessHeadersMessage(pfrom, headers, /*via_compact_block=*/false); } if (msg_type == NetMsgType::BLOCK) @@ -3848,7 +3827,7 @@ void PeerLogicValidation::ProcessMessage( mapBlockSource.emplace(hash, std::make_pair(pfrom.GetId(), true)); } bool fNewBlock = false; - m_chainman.ProcessNewBlock(chainparams, pblock, forceProcessing, &fNewBlock); + m_chainman.ProcessNewBlock(m_chainparams, pblock, forceProcessing, &fNewBlock); if (fNewBlock) { pfrom.nLastBlockTime = GetTime(); } else { @@ -4065,17 +4044,17 @@ void PeerLogicValidation::ProcessMessage( } if (msg_type == NetMsgType::GETCFILTERS) { - ProcessGetCFilters(pfrom, vRecv, chainparams, m_connman); + ProcessGetCFilters(pfrom, vRecv, m_chainparams, m_connman); return; } if (msg_type == NetMsgType::GETCFHEADERS) { - ProcessGetCFHeaders(pfrom, vRecv, chainparams, m_connman); + ProcessGetCFHeaders(pfrom, vRecv, m_chainparams, m_connman); return; } if (msg_type == NetMsgType::GETCFCHECKPT) { - ProcessGetCFCheckPt(pfrom, vRecv, chainparams, m_connman); + ProcessGetCFCheckPt(pfrom, vRecv, m_chainparams, m_connman); return; } @@ -4173,12 +4152,7 @@ void PeerLogicValidation::ProcessMessage( return; } -/** Maybe disconnect a peer and discourage future connections from its address. - * - * @param[in] pnode The node to check. - * @return True if the peer was marked for disconnection in this function - */ -bool PeerLogicValidation::MaybeDiscourageAndDisconnect(CNode& pnode) +bool PeerManager::MaybeDiscourageAndDisconnect(CNode& pnode) { const NodeId peer_id{pnode.GetId()}; PeerRef peer = GetPeerRef(peer_id); @@ -4222,17 +4196,17 @@ bool PeerLogicValidation::MaybeDiscourageAndDisconnect(CNode& pnode) return true; } -bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgProc) +bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgProc) { const CChainParams& chainparams = Params(); bool fMoreWork = false; if (!pfrom->vRecvGetData.empty()) - ProcessGetData(*pfrom, chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); + ProcessGetData(*pfrom, m_chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); if (!pfrom->orphan_work_set.empty()) { LOCK2(cs_main, g_cs_orphans); - ProcessOrphanTx(m_connman, m_mempool, pfrom->orphan_work_set); + ProcessOrphanTx(pfrom->orphan_work_set); } if (pfrom->fDisconnect) @@ -4267,7 +4241,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic& inter unsigned int nMessageSize = msg.m_message_size; try { - ProcessMessage(*pfrom, msg_type, msg.m_recv, msg.m_time, chainparams, interruptMsgProc); + ProcessMessage(*pfrom, msg_type, msg.m_recv, msg.m_time, interruptMsgProc); if (interruptMsgProc) return false; if (!pfrom->vRecvGetData.empty()) @@ -4281,7 +4255,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic& inter return fMoreWork; } -void PeerLogicValidation::ConsiderEviction(CNode& pto, int64_t time_in_seconds) +void PeerManager::ConsiderEviction(CNode& pto, int64_t time_in_seconds) { AssertLockHeld(cs_main); @@ -4339,7 +4313,7 @@ void PeerLogicValidation::ConsiderEviction(CNode& pto, int64_t time_in_seconds) } } -void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds) +void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds) { // Check whether we have too many outbound peers int extra_peers = m_connman.GetExtraOutboundCount(); @@ -4400,7 +4374,7 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds) } } -void PeerLogicValidation::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) +void PeerManager::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) { LOCK(cs_main); @@ -4440,7 +4414,7 @@ class CompareInvMempoolOrder }; } -bool PeerLogicValidation::SendMessages(CNode* pto) +bool PeerManager::SendMessages(CNode* pto) { assert(m_llmq_ctx); diff --git a/src/net_processing.h b/src/net_processing.h index 4932f9267dea..f6e8e18a34d6 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -11,9 +11,13 @@ #include #include +class BlockTransactionsRequest; +class BlockValidationState; class CAddrMan; +class CBlockHeader; class CTxMemPool; class ChainstateManager; +class TxValidationState; struct LLMQContext; extern CCriticalSection cs_main; @@ -25,20 +29,10 @@ static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100; static const bool DEFAULT_PEERBLOOMFILTERS = true; static const bool DEFAULT_PEERBLOCKFILTERS = false; -class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface { -private: - CConnman& m_connman; - BanMan* const m_banman; - CAddrMan& m_addrman; - ChainstateManager& m_chainman; - CTxMemPool& m_mempool; - std::unique_ptr& m_llmq_ctx; - - bool MaybeDiscourageAndDisconnect(CNode& pnode); - +class PeerManager final : public CValidationInterface, public NetEventsInterface { public: - PeerLogicValidation(CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, - std::unique_ptr& llmq_ctx); + PeerManager(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, + ChainstateManager& chainman, CTxMemPool& pool, std::unique_ptr& llmq_ctx); /** * Overridden from CValidationInterface. @@ -86,9 +80,59 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI /** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */ void ReattemptInitialBroadcast(CScheduler& scheduler) const; /** Process a single message from a peer. Public for fuzz testing */ - void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, const std::atomic& interruptMsgProc); + void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const std::atomic& interruptMsgProc); + + /** + * Increment peer's misbehavior score. If the new value surpasses banscore (specified on startup or by default), mark node to be discouraged, meaning the peer might be disconnected & added to the discouragement filter. + */ + void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message = ""); private: + /** + * Potentially mark a node discouraged based on the contents of a BlockValidationState object + * + * @param[in] via_compact_block this bool is passed in because net_processing should + * punish peers differently depending on whether the data was provided in a compact + * block message or not. If the compact block had a valid header, but contained invalid + * txs, the peer should not be punished. See BIP 152. + * + * @return Returns true if the peer was punished (probably disconnected) + */ + bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, + bool via_compact_block, const std::string& message = ""); + + /** + * Potentially ban a node based on the contents of a TxValidationState object + * + * @return Returns true if the peer was punished (probably disconnected) + * + * Changes here may need to be reflected in TxRelayMayResultInDisconnect(). + */ + bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = ""); + + /** Maybe disconnect a peer and discourage future connections from its address. + * + * @param[in] pnode The node to check. + * @return True if the peer was marked for disconnection in this function + */ + bool MaybeDiscourageAndDisconnect(CNode& pnode); + + void ProcessOrphanTx(std::set& orphan_work_set) + EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans); + /** Process a single headers message from a peer. */ + void ProcessHeadersMessage(CNode& pfrom, const std::vector& headers, bool via_compact_block); + + void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req); + + const CChainParams& m_chainparams; + CConnman& m_connman; + /** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */ + BanMan* const m_banman; + CAddrMan& m_addrman; + ChainstateManager& m_chainman; + CTxMemPool& m_mempool; + std::unique_ptr& m_llmq_ctx; + int64_t m_stale_tip_check_time; //!< Next time to check for stale tip }; @@ -103,11 +147,6 @@ struct CNodeStateStats { bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); bool IsBanned(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main); -// Upstream moved this into net_processing.cpp (13417), however since we use Misbehaving in a number of dash specific -// files such as mnauth.cpp and governance.cpp it makes sense to keep it in the header -/** Increase a node's misbehavior score. */ -void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message=""); - void EraseObjectRequest(NodeId nodeId, const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main); void RequestObject(NodeId nodeId, const CInv& inv, std::chrono::microseconds current_time, bool fForce=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); size_t GetRequestedObjectCount(NodeId nodeId) EXCLUSIVE_LOCKS_REQUIRED(cs_main); diff --git a/src/node/context.h b/src/node/context.h index 86d3dbc087b3..dcdee0f96a68 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -19,7 +19,7 @@ class CScheduler; class CTxMemPool; class ChainstateManager; struct LLMQContext; -class PeerLogicValidation; +class PeerManager; class CEvoDB; namespace interfaces { class Chain; @@ -42,7 +42,7 @@ struct NodeContext { std::unique_ptr connman; std::unique_ptr mempool; std::unique_ptr fee_estimator; - std::unique_ptr peer_logic; + std::unique_ptr peerman; ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct std::unique_ptr banman; ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct diff --git a/src/spork.cpp b/src/spork.cpp index cf2a9c774fc0..7dc55bd29787 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -105,16 +105,16 @@ void CSporkManager::CheckAndRemove() } } -void CSporkManager::ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) +void CSporkManager::ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, std::string_view msg_type, CDataStream& vRecv) { if (msg_type == NetMsgType::SPORK) { - ProcessSpork(peer, peer_logic, connman, vRecv); + ProcessSpork(peer, peerman, connman, vRecv); } else if (msg_type == NetMsgType::GETSPORKS) { ProcessGetSporks(peer, connman); } } -void CSporkManager::ProcessSpork(const CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, CDataStream& vRecv) +void CSporkManager::ProcessSpork(const CNode& peer, PeerManager& peerman, CConnman& connman, CDataStream& vRecv) { CSporkMessage spork; vRecv >> spork; @@ -131,7 +131,7 @@ void CSporkManager::ProcessSpork(const CNode& peer, PeerLogicValidation& peer_lo if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) { LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: too far into the future\n"); - Misbehaving(peer.GetId(), 100); + peerman.Misbehaving(peer.GetId(), 100); return; } @@ -139,7 +139,7 @@ void CSporkManager::ProcessSpork(const CNode& peer, PeerLogicValidation& peer_lo if (opt_keyIDSigner == std::nullopt || WITH_LOCK(cs, return !setSporkPubKeyIDs.count(*opt_keyIDSigner))) { LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: invalid signature\n"); - Misbehaving(peer.GetId(), 100); + peerman.Misbehaving(peer.GetId(), 100); return; } diff --git a/src/spork.h b/src/spork.h index 522b6250482a..75df30805667 100644 --- a/src/spork.h +++ b/src/spork.h @@ -22,7 +22,7 @@ class CConnman; class CNode; class CDataStream; -class PeerLogicValidation; +class PeerManager; class CSporkMessage; class CSporkManager; @@ -234,7 +234,7 @@ class CSporkManager /** * ProcessMessage is used to call ProcessSpork and ProcessGetSporks. See below */ - void ProcessMessage(CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); + void ProcessMessage(CNode& peer, PeerManager& peerman, CConnman& connman, std::string_view msg_type, CDataStream& vRecv); /** * ProcessSpork is used to handle the 'spork' p2p message. @@ -242,7 +242,7 @@ class CSporkManager * For 'spork', it validates the spork and adds it to the internal spork storage and * performs any necessary processing. */ - void ProcessSpork(const CNode& peer, PeerLogicValidation& peer_logic, CConnman& connman, CDataStream& vRecv) LOCKS_EXCLUDED(cs); + void ProcessSpork(const CNode& peer, PeerManager& peerman, CConnman& connman, CDataStream& vRecv) LOCKS_EXCLUDED(cs); /** diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 464070949ceb..ef9a7fcd9e1e 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -46,8 +46,6 @@ struct CConnmanTest : public CConnman { extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer); extern void EraseOrphansFor(NodeId peer); extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); -// We don't need this, since we kept declaration in net_processing.h when backporting (#13417) -// extern void Misbehaving(NodeId nodeid, int howmuch, const std::string& message=""); struct COrphanTx { CTransactionRef tx; @@ -80,9 +78,10 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup) // work. BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) { + const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - *connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx + auto peerLogic = std::make_unique( + chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx ); // Mock an outbound peer @@ -136,7 +135,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) peerLogic->FinalizeNode(dummyNode1); } -static void AddRandomOutboundPeer(std::vector &vNodes, PeerLogicValidation &peerLogic, CConnmanTest* connman) +static void AddRandomOutboundPeer(std::vector &vNodes, PeerManager &peerLogic, CConnmanTest* connman) { CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE); vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false)); @@ -152,9 +151,10 @@ static void AddRandomOutboundPeer(std::vector &vNodes, PeerLogicValidat BOOST_AUTO_TEST_CASE(stale_tip_peer_management) { + const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - *connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx + auto peerLogic = std::make_unique( + chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx ); const Consensus::Params& consensusParams = Params().GetConsensus(); @@ -225,10 +225,11 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) BOOST_AUTO_TEST_CASE(DoS_banning) { + const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx + auto peerLogic = std::make_unique( + chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx ); banman->ClearBanned(); @@ -238,7 +239,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) peerLogic->InitializeNode(&dummyNode1); dummyNode1.nVersion = 1; dummyNode1.fSuccessfullyConnected = true; - Misbehaving(dummyNode1.GetId(), 100); // Should get banned + peerLogic->Misbehaving(dummyNode1.GetId(), 100); // Should get banned { LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); @@ -252,14 +253,14 @@ BOOST_AUTO_TEST_CASE(DoS_banning) peerLogic->InitializeNode(&dummyNode2); dummyNode2.nVersion = 1; dummyNode2.fSuccessfullyConnected = true; - Misbehaving(dummyNode2.GetId(), 50); + peerLogic->Misbehaving(dummyNode2.GetId(), 50); { LOCK(dummyNode2.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode2)); } BOOST_CHECK(!banman->IsDiscouraged(addr2)); // 2 not banned yet... BOOST_CHECK(banman->IsDiscouraged(addr1)); // ... but 1 still should be - Misbehaving(dummyNode2.GetId(), 50); + peerLogic->Misbehaving(dummyNode2.GetId(), 50); { LOCK(dummyNode2.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode2)); @@ -272,10 +273,11 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_AUTO_TEST_CASE(DoS_banscore) { + const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx + auto peerLogic = std::make_unique( + chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx ); banman->ClearBanned(); @@ -287,7 +289,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) dummyNode1.nVersion = 1; dummyNode1.fSuccessfullyConnected = true; { - Misbehaving(dummyNode1.GetId(), 100); + peerLogic->Misbehaving(dummyNode1.GetId(), 100); } { LOCK(dummyNode1.cs_sendProcessing); @@ -295,7 +297,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) } BOOST_CHECK(!banman->IsDiscouraged(addr1)); { - Misbehaving(dummyNode1.GetId(), 10); + peerLogic->Misbehaving(dummyNode1.GetId(), 10); } { LOCK(dummyNode1.cs_sendProcessing); @@ -303,7 +305,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) } BOOST_CHECK(!banman->IsDiscouraged(addr1)); { - Misbehaving(dummyNode1.GetId(), 1); + peerLogic->Misbehaving(dummyNode1.GetId(), 1); } { LOCK(dummyNode1.cs_sendProcessing); @@ -317,10 +319,11 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) BOOST_AUTO_TEST_CASE(DoS_bantime) { + const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx + auto peerLogic = std::make_unique( + chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx ); banman->ClearBanned(); @@ -334,7 +337,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) dummyNode.nVersion = 1; dummyNode.fSuccessfullyConnected = true; - Misbehaving(dummyNode.GetId(), 100); + peerLogic->Misbehaving(dummyNode.GetId(), 100); { LOCK(dummyNode.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode)); diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index b4b6def383ef..eec3b8fb0b5b 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -68,14 +68,14 @@ void fuzz_target(const std::vector& buffer, const std::string& LIMIT_TO p2p_node.fSuccessfullyConnected = true; p2p_node.nVersion = PROTOCOL_VERSION; p2p_node.SetSendVersion(PROTOCOL_VERSION); - g_setup->m_node.peer_logic->InitializeNode(&p2p_node); + g_setup->m_node.peerman->InitializeNode(&p2p_node); try { - g_setup->m_node.peer_logic->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream, GetTimeMillis(), Params(), std::atomic{false}); + g_setup->m_node.peerman->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream, GetTimeMillis(), std::atomic{false}); } catch (const std::ios_base::failure& e) { } { LOCK(p2p_node.cs_sendProcessing); - g_setup->m_node.peer_logic->SendMessages(&p2p_node); + g_setup->m_node.peerman->SendMessages(&p2p_node); } SyncWithValidationInterfaceQueue(); } diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index d7c9ed959b83..654504d96f9e 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -51,7 +51,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) p2p_node.fPauseSend = false; p2p_node.nVersion = PROTOCOL_VERSION; p2p_node.SetSendVersion(PROTOCOL_VERSION); - g_setup->m_node.peer_logic->InitializeNode(&p2p_node); + g_setup->m_node.peerman->InitializeNode(&p2p_node); connman.AddTestNode(p2p_node); } @@ -74,7 +74,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) } { LOCK(random_node.cs_sendProcessing); - g_setup->m_node.peer_logic->SendMessages(&random_node); + g_setup->m_node.peerman->SendMessages(&random_node); } } connman.ClearTestNodes(); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index d3007fd1a906..0f625cc15b42 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -188,7 +188,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve #endif // ENABLE_WALLET deterministicMNManager.reset(new CDeterministicMNManager(*m_node.evodb, *m_node.connman)); - m_node.llmq_ctx = std::make_unique(*m_node.evodb, *m_node.mempool, *m_node.connman, *sporkManager, m_node.peer_logic, true, false); + m_node.llmq_ctx = std::make_unique(*m_node.evodb, *m_node.mempool, *m_node.connman, *sporkManager, m_node.peerman, true, false); // Start script-checking threads. Set g_parallel_script_checks to true so they are used. constexpr int script_check_threads = 2; @@ -244,12 +244,12 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); - m_node.peer_logic = std::make_unique( - *m_node.connman, *m_node.addrman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx + m_node.peerman = std::make_unique( + chainparams, *m_node.connman, *m_node.addrman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx ); { CConnman::Options options; - options.m_msgproc = m_node.peer_logic.get(); + options.m_msgproc = m_node.peerman.get(); m_node.connman->Init(options); } From 60d589014c1904101527faeaf4181674914e8096 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Thu, 11 May 2023 08:57:00 +0000 Subject: [PATCH 04/10] merge bitcoin#19911: guard vRecvGetData with cs_vRecv and orphan_work_set with g_cs_orphans --- src/net.h | 3 - src/net_processing.cpp | 129 ++++++++++++++++++++++++++--------------- 2 files changed, 81 insertions(+), 51 deletions(-) diff --git a/src/net.h b/src/net.h index 9f3ab2a2736e..2e4ba3cc751f 100644 --- a/src/net.h +++ b/src/net.h @@ -958,7 +958,6 @@ class CNode CCriticalSection cs_sendProcessing; - std::deque vRecvGetData; uint64_t nRecvBytes GUARDED_BY(cs_vRecv){0}; std::atomic nRecvVersion{INIT_PROTO_VERSION}; @@ -1134,8 +1133,6 @@ class CNode // If true, we will send him all quorum related messages, even if he is not a member of our quorums std::atomic qwatch{false}; - std::set orphan_work_set; - CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false, bool block_relay_only = false, bool inbound_onion = false); ~CNode(); CNode(const CNode&) = delete; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 434d65f8433c..23957eaf5e6c 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -463,7 +463,15 @@ struct Peer { /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */ bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false}; - Peer(NodeId id) : m_id(id) {} + /** Set of txids to reconsider once their parent transactions have been accepted **/ + std::set m_orphan_work_set GUARDED_BY(g_cs_orphans); + + /** Protects m_getdata_requests **/ + Mutex m_getdata_requests_mutex; + /** Work queue of items requested by this peer **/ + std::deque m_getdata_requests GUARDED_BY(m_getdata_requests_mutex); + + explicit Peer(NodeId id) : m_id(id) {} }; using PeerRef = std::shared_ptr; @@ -1836,12 +1844,12 @@ void static ProcessGetBlockData(CNode& pfrom, const CChainParams& chainparams, c } } -void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, - LLMQContext& llmq_ctx, const std::atomic& interruptMsgProc) LOCKS_EXCLUDED(cs_main) +void static ProcessGetData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, + LLMQContext& llmq_ctx, const std::atomic& interruptMsgProc) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(peer.m_getdata_requests_mutex) { AssertLockNotHeld(cs_main); - std::deque::iterator it = pfrom.vRecvGetData.begin(); + std::deque::iterator it = peer.m_getdata_requests.begin(); std::vector vNotFound; const CNetMsgMaker msgMaker(pfrom.GetSendVersion()); @@ -1857,7 +1865,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm // Process as many TX items from the front of the getdata queue as // possible, since they're common and it's efficient to batch process // them. - while (it != pfrom.vRecvGetData.end() && it->IsKnownType()) { + while (it != peer.m_getdata_requests.end() && it->IsKnownType()) { if (interruptMsgProc) return; // The send buffer provides backpressure. If there's no space in @@ -2031,7 +2039,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm // Only process one BLOCK item per call, since they're uncommon and can be // expensive to process. - if (it != pfrom.vRecvGetData.end() && !pfrom.fPauseSend) { + if (it != peer.m_getdata_requests.end() && !pfrom.fPauseSend) { const CInv &inv = *it++; if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) { ProcessGetBlockData(pfrom, chainparams, inv, connman, *llmq_ctx.isman); @@ -2040,7 +2048,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm // and continue processing the queue on the next call. } - pfrom.vRecvGetData.erase(pfrom.vRecvGetData.begin(), it); + peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it); if (!vNotFound.empty()) { // Let the peer know that we didn't find what it asked for, so it doesn't @@ -2609,6 +2617,9 @@ void PeerManager::ProcessMessage( return; } + PeerRef peer = GetPeerRef(pfrom.GetId()); + if (peer == nullptr) return; + if (!(pfrom.GetLocalServices() & NODE_BLOOM) && (msg_type == NetMsgType::FILTERLOAD || msg_type == NetMsgType::FILTERADD)) @@ -3106,8 +3117,11 @@ void PeerManager::ProcessMessage( LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom.GetId()); } - pfrom.vRecvGetData.insert(pfrom.vRecvGetData.end(), vInv.begin(), vInv.end()); - ProcessGetData(pfrom, m_chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); + { + LOCK(peer->m_getdata_requests_mutex); + peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end()); + ProcessGetData(pfrom, *peer, m_chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); + } return; } @@ -3197,36 +3211,38 @@ void PeerManager::ProcessMessage( return; } - LOCK(cs_main); + { + LOCK(cs_main); - const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(req.blockhash); - if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) { - LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom.GetId()); - return; - } + const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(req.blockhash); + if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) { + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom.GetId()); + return; + } - if (pindex->nHeight < ::ChainActive().Height() - MAX_BLOCKTXN_DEPTH) { - // If an older block is requested (should never happen in practice, - // but can happen in tests) send a block response instead of a - // blocktxn response. Sending a full block response instead of a - // small blocktxn response is preferable in the case where a peer - // might maliciously send lots of getblocktxn requests to trigger - // expensive disk reads, because it will require the peer to - // actually receive all the data read from disk over the network. - LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH); - CInv inv; - inv.type = MSG_BLOCK; - inv.hash = req.blockhash; - pfrom.vRecvGetData.push_back(inv); - // The message processing loop will go around again (without pausing) and we'll respond then (without cs_main) - return; - } + if (pindex->nHeight >= ::ChainActive().Height() - MAX_BLOCKTXN_DEPTH) { + CBlock block; + bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus()); + assert(ret); - CBlock block; - bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus()); - assert(ret); + SendBlockTransactions(pfrom, block, req); + return; + } + } - SendBlockTransactions(pfrom, block, req); + // If an older block is requested (should never happen in practice, + // but can happen in tests) send a block response instead of a + // blocktxn response. Sending a full block response instead of a + // small blocktxn response is preferable in the case where a peer + // might maliciously send lots of getblocktxn requests to trigger + // expensive disk reads, because it will require the peer to + // actually receive all the data read from disk over the network. + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH); + CInv inv; + WITH_LOCK(cs_main, inv.type = MSG_BLOCK); + inv.hash = req.blockhash; + WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv)); + // The message processing loop will go around again (without pausing) and we'll respond then (without cs_main) return; } @@ -3369,7 +3385,7 @@ void PeerManager::ProcessMessage( auto it_by_prev = mapOrphanTransactionsByPrev.find(COutPoint(inv.hash, i)); if (it_by_prev != mapOrphanTransactionsByPrev.end()) { for (const auto& elem : it_by_prev->second) { - pfrom.orphan_work_set.insert(elem->first); + peer->m_orphan_work_set.insert(elem->first); } } } @@ -3382,7 +3398,7 @@ void PeerManager::ProcessMessage( m_mempool.size(), m_mempool.DynamicMemoryUsage() / 1000); // Recursively process any orphan transactions that depended on this one - ProcessOrphanTx(pfrom.orphan_work_set); + ProcessOrphanTx(peer->m_orphan_work_set); } else if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) { @@ -4201,21 +4217,37 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgP const CChainParams& chainparams = Params(); bool fMoreWork = false; - if (!pfrom->vRecvGetData.empty()) - ProcessGetData(*pfrom, m_chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); + PeerRef peer = GetPeerRef(pfrom->GetId()); + if (peer == nullptr) return false; + + { + LOCK(peer->m_getdata_requests_mutex); + if (!peer->m_getdata_requests.empty()) { + ProcessGetData(*pfrom, *peer, m_chainparams, m_connman, m_mempool, *m_llmq_ctx, interruptMsgProc); + } + } - if (!pfrom->orphan_work_set.empty()) { + { LOCK2(cs_main, g_cs_orphans); - ProcessOrphanTx(pfrom->orphan_work_set); + if (!peer->m_orphan_work_set.empty()) { + ProcessOrphanTx(peer->m_orphan_work_set); + } } if (pfrom->fDisconnect) return false; // this maintains the order of responses - // and prevents vRecvGetData to grow unbounded - if (!pfrom->vRecvGetData.empty()) return true; - if (!pfrom->orphan_work_set.empty()) return true; + // and prevents m_getdata_requests to grow unbounded + { + LOCK(peer->m_getdata_requests_mutex); + if (!peer->m_getdata_requests.empty()) return true; + } + + { + LOCK(g_cs_orphans); + if (!peer->m_orphan_work_set.empty()) return true; + } // Don't bother if send buffer is too full to respond anyway if (pfrom->fPauseSend) @@ -4242,10 +4274,11 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgP try { ProcessMessage(*pfrom, msg_type, msg.m_recv, msg.m_time, interruptMsgProc); - if (interruptMsgProc) - return false; - if (!pfrom->vRecvGetData.empty()) - fMoreWork = true; + if (interruptMsgProc) return false; + { + LOCK(peer->m_getdata_requests_mutex); + if (!peer->m_getdata_requests.empty()) fMoreWork = true; + } } catch (const std::exception& e) { LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' (%s) caught\n", __func__, SanitizeString(msg_type), nMessageSize, e.what(), typeid(e).name()); } catch (...) { From d0a35831db3a32ba24e4292a6945484431b70f29 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Wed, 26 Apr 2023 16:27:32 +0000 Subject: [PATCH 05/10] net: rename misbehavior members using scripted-diff implements 8e35bf59062b3a823182588e0bf809b3367c2be0 from https://github.com/bitcoin/bitcoin/pull/19607 --- src/net_processing.cpp | 14 +++++++------- src/net_processing.h | 2 +- src/qt/rpcconsole.cpp | 2 +- src/rpc/net.cpp | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 23957eaf5e6c..550e66de4780 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -459,7 +459,7 @@ struct Peer { /** Protects misbehavior data members */ Mutex m_misbehavior_mutex; /** Accumulated misbehavior score for this peer */ - int nMisbehavior GUARDED_BY(m_misbehavior_mutex){0}; + int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0}; /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */ bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false}; @@ -988,7 +988,7 @@ void PeerManager::FinalizeNode(const CNode& node) { { PeerRef peer = GetPeerRef(nodeid); assert(peer != nullptr); - misbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->nMisbehavior); + misbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_misbehavior_score); LOCK(g_peer_mutex); g_peer_map.erase(nodeid); } @@ -1045,7 +1045,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { PeerRef peer = GetPeerRef(nodeid); if (peer == nullptr) return false; - stats.nMisbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->nMisbehavior); + stats.m_misbehavior_score = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_misbehavior_score); return true; } @@ -1199,16 +1199,16 @@ void PeerManager::Misbehaving(const NodeId pnode, const int howmuch, const std:: if (peer == nullptr) return; LOCK(peer->m_misbehavior_mutex); - peer->nMisbehavior += howmuch; + peer->m_misbehavior_score += howmuch; const int banscore = gArgs.GetArg("-banscore", DEFAULT_BANSCORE_THRESHOLD); const std::string message_prefixed = message.empty() ? "" : (": " + message); - if (peer->nMisbehavior >= banscore && peer->nMisbehavior - howmuch < banscore) + if (peer->m_misbehavior_score >= banscore && peer->m_misbehavior_score - howmuch < banscore) { - LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d) DISCOURAGE THRESHOLD EXCEEDED%s\n", pnode, peer->nMisbehavior - howmuch, peer->nMisbehavior, message_prefixed); + LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d) DISCOURAGE THRESHOLD EXCEEDED%s\n", pnode, peer->m_misbehavior_score - howmuch, peer->m_misbehavior_score, message_prefixed); peer->m_should_discourage = true; statsClient.inc("misbehavior.banned", 1.0f); } else { - LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s\n", pnode, peer->nMisbehavior - howmuch, peer->nMisbehavior, message_prefixed); + LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s\n", pnode, peer->m_misbehavior_score - howmuch, peer->m_misbehavior_score, message_prefixed); statsClient.count("misbehavior.amount", howmuch, 1.0); } } diff --git a/src/net_processing.h b/src/net_processing.h index f6e8e18a34d6..53d259c6015f 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -137,7 +137,7 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface }; struct CNodeStateStats { - int nMisbehavior = 0; + int m_misbehavior_score = 0; int nSyncHeight = -1; int nCommonHeight = -1; std::vector vHeightInFlight; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 6afafb84768a..81184910147d 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1264,7 +1264,7 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) // nodeStateStats couldn't be fetched. if (stats->fNodeStateStatsAvailable) { // Ban score is init to 0 - ui->peerBanScore->setText(QString("%1").arg(stats->nodeStateStats.nMisbehavior)); + ui->peerBanScore->setText(QString("%1").arg(stats->nodeStateStats.m_misbehavior_score)); // Sync height is init to -1 if (stats->nodeStateStats.nSyncHeight > -1) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index c9e8ecafbb9f..55665cce7947 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -206,7 +206,7 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) obj.pushKV("masternode", stats.m_masternode_connection); obj.pushKV("startingheight", stats.nStartingHeight); if (fStateStats) { - obj.pushKV("banscore", statestats.nMisbehavior); + obj.pushKV("banscore", statestats.m_misbehavior_score); obj.pushKV("synced_headers", statestats.nSyncHeight); obj.pushKV("synced_blocks", statestats.nCommonHeight); UniValue heights(UniValue::VARR); From 296e0dd28ea6de3f3e5f982d4cadec83d51a4729 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Thu, 27 Apr 2023 07:46:47 +0000 Subject: [PATCH 06/10] merge bitcoin#19910: Move peer_map to PeerManager --- src/llmq/signing_shares.cpp | 2 +- src/net_processing.cpp | 83 +++++++++++-------------------------- src/net_processing.h | 73 +++++++++++++++++++++++++++----- src/node/interfaces.cpp | 12 +++--- src/rpc/net.cpp | 5 ++- 5 files changed, 98 insertions(+), 77 deletions(-) diff --git a/src/llmq/signing_shares.cpp b/src/llmq/signing_shares.cpp index c407be20db74..08bef971a088 100644 --- a/src/llmq/signing_shares.cpp +++ b/src/llmq/signing_shares.cpp @@ -1389,7 +1389,7 @@ void CSigSharesManager::RemoveBannedNodeStates() LOCK2(cs_main, cs); for (auto it = nodeStates.begin(); it != nodeStates.end();) { - if (IsBanned(it->first)) { + if (m_peerman->IsBanned(it->first)) { // re-request sigshares from other nodes it->second.requestedSigShares.ForEach([this](const SigShareKey& k, int64_t) { AssertLockHeld(cs); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 550e66de4780..f336494a18dd 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -442,58 +442,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return &it->second; } -/** - * Data structure for an individual peer. This struct is not protected by - * cs_main since it does not contain validation-critical data. - * - * Memory is owned by shared pointers and this object is destructed when - * the refcount drops to zero. - * - * TODO: move most members from CNodeState to this structure. - * TODO: move remaining application-layer data members from CNode to this structure. - */ -struct Peer { - /** Same id as the CNode object for this peer */ - const NodeId m_id{0}; - - /** Protects misbehavior data members */ - Mutex m_misbehavior_mutex; - /** Accumulated misbehavior score for this peer */ - int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0}; - /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */ - bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false}; - - /** Set of txids to reconsider once their parent transactions have been accepted **/ - std::set m_orphan_work_set GUARDED_BY(g_cs_orphans); - - /** Protects m_getdata_requests **/ - Mutex m_getdata_requests_mutex; - /** Work queue of items requested by this peer **/ - std::deque m_getdata_requests GUARDED_BY(m_getdata_requests_mutex); - - explicit Peer(NodeId id) : m_id(id) {} -}; - -using PeerRef = std::shared_ptr; - -/** - * Map of all Peer objects, keyed by peer id. This map is protected - * by the global g_peer_mutex. Once a shared pointer reference is - * taken, the lock may be released. Individual fields are protected by - * their own locks. - */ -Mutex g_peer_mutex; -static std::map g_peer_map GUARDED_BY(g_peer_mutex); - -/** Get a shared pointer to the Peer object. - * May return nullptr if the Peer object can't be found. */ -static PeerRef GetPeerRef(NodeId id) -{ - LOCK(g_peer_mutex); - auto it = g_peer_map.find(id); - return it != g_peer_map.end() ? it->second : nullptr; -} - static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { nPreferredDownload -= state->fPreferredDownload; @@ -954,8 +902,8 @@ void PeerManager::InitializeNode(CNode *pnode) { } { PeerRef peer = std::make_shared(nodeid); - LOCK(g_peer_mutex); - g_peer_map.emplace_hint(g_peer_map.end(), nodeid, std::move(peer)); + LOCK(m_peer_mutex); + m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer)); } if (!pnode->fInbound) PushNodeVersion(*pnode, m_connman, GetTime()); @@ -986,11 +934,9 @@ void PeerManager::FinalizeNode(const CNode& node) { LOCK(cs_main); { { - PeerRef peer = GetPeerRef(nodeid); + PeerRef peer = RemovePeer(nodeid); assert(peer != nullptr); misbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_misbehavior_score); - LOCK(g_peer_mutex); - g_peer_map.erase(nodeid); } CNodeState *state = State(nodeid); assert(state != nullptr); @@ -1029,7 +975,26 @@ void PeerManager::FinalizeNode(const CNode& node) { LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid); } -bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { +PeerRef PeerManager::GetPeerRef(NodeId id) const +{ + LOCK(m_peer_mutex); + auto it = m_peer_map.find(id); + return it != m_peer_map.end() ? it->second : nullptr; +} + +PeerRef PeerManager::RemovePeer(NodeId id) +{ + PeerRef ret; + LOCK(m_peer_mutex); + auto it = m_peer_map.find(id); + if (it != m_peer_map.end()) { + ret = std::move(it->second); + m_peer_map.erase(it); + } + return ret; +} + +bool PeerManager::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { { LOCK(cs_main); CNodeState* state = State(nodeid); @@ -1213,7 +1178,7 @@ void PeerManager::Misbehaving(const NodeId pnode, const int howmuch, const std:: } } -bool IsBanned(NodeId pnode) +bool PeerManager::IsBanned(NodeId pnode) { PeerRef peer = GetPeerRef(pnode); if (peer == nullptr) diff --git a/src/net_processing.h b/src/net_processing.h index 53d259c6015f..247fbf071adc 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -29,6 +29,47 @@ static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100; static const bool DEFAULT_PEERBLOOMFILTERS = true; static const bool DEFAULT_PEERBLOCKFILTERS = false; +struct CNodeStateStats { + int m_misbehavior_score = 0; + int nSyncHeight = -1; + int nCommonHeight = -1; + std::vector vHeightInFlight; +}; + +/** + * Data structure for an individual peer. This struct is not protected by + * cs_main since it does not contain validation-critical data. + * + * Memory is owned by shared pointers and this object is destructed when + * the refcount drops to zero. + * + * TODO: move most members from CNodeState to this structure. + * TODO: move remaining application-layer data members from CNode to this structure. + */ +struct Peer { + /** Same id as the CNode object for this peer */ + const NodeId m_id{0}; + + /** Protects misbehavior data members */ + Mutex m_misbehavior_mutex; + /** Accumulated misbehavior score for this peer */ + int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0}; + /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */ + bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false}; + + /** Set of txids to reconsider once their parent transactions have been accepted **/ + std::set m_orphan_work_set GUARDED_BY(g_cs_orphans); + + /** Protects m_getdata_requests **/ + Mutex m_getdata_requests_mutex; + /** Work queue of items requested by this peer **/ + std::deque m_getdata_requests GUARDED_BY(m_getdata_requests_mutex); + + explicit Peer(NodeId id) : m_id(id) {} +}; + +using PeerRef = std::shared_ptr; + class PeerManager final : public CValidationInterface, public NetEventsInterface { public: PeerManager(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, @@ -87,7 +128,20 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface */ void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message = ""); + /** Get statistics from node state */ + bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats); + + bool IsBanned(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + private: + /** Get a shared pointer to the Peer object. + * May return an empty shared_ptr if the Peer object can't be found. */ + PeerRef GetPeerRef(NodeId id) const; + + /** Get a shared pointer to the Peer object and remove it from m_peer_map. + * May return an empty shared_ptr if the Peer object can't be found. */ + PeerRef RemovePeer(NodeId id); + /** * Potentially mark a node discouraged based on the contents of a BlockValidationState object * @@ -134,19 +188,18 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface std::unique_ptr& m_llmq_ctx; int64_t m_stale_tip_check_time; //!< Next time to check for stale tip -}; -struct CNodeStateStats { - int m_misbehavior_score = 0; - int nSyncHeight = -1; - int nCommonHeight = -1; - std::vector vHeightInFlight; + /** Protects m_peer_map */ + mutable Mutex m_peer_mutex; + /** + * Map of all Peer objects, keyed by peer id. This map is protected + * by the m_peer_mutex. Once a shared pointer reference is + * taken, the lock may be released. Individual fields are protected by + * their own locks. + */ + std::map m_peer_map GUARDED_BY(m_peer_mutex); }; -/** Get statistics from node state */ -bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); -bool IsBanned(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - void EraseObjectRequest(NodeId nodeId, const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main); void RequestObject(NodeId nodeId, const CInv& inv, std::chrono::microseconds current_time, bool fForce=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); size_t GetRequestedObjectCount(NodeId nodeId) EXCLUSIVE_LOCKS_REQUIRED(cs_main); diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 27e86c6d6860..963d08a50f45 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -253,11 +253,13 @@ class NodeImpl : public Node } // Try to retrieve the CNodeStateStats for each node. - TRY_LOCK(::cs_main, lockMain); - if (lockMain) { - for (auto& node_stats : stats) { - std::get<1>(node_stats) = - GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats)); + if (m_context->peerman) { + TRY_LOCK(::cs_main, lockMain); + if (lockMain) { + for (auto& node_stats : stats) { + std::get<1>(node_stats) = + m_context->peerman->GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats)); + } } } return true; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 55665cce7947..058fe265e5aa 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -148,8 +148,9 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) }.Check(request); NodeContext& node = EnsureNodeContext(request.context); - if(!node.connman) + if(!node.connman || !node.peerman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + } std::vector vstats; node.connman->GetNodeStats(vstats); @@ -159,7 +160,7 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) for (const CNodeStats& stats : vstats) { UniValue obj(UniValue::VOBJ); CNodeStateStats statestats; - bool fStateStats = GetNodeStateStats(stats.nodeid, statestats); + bool fStateStats = node.peerman->GetNodeStateStats(stats.nodeid, statestats); obj.pushKV("id", stats.nodeid); obj.pushKV("addr", stats.addrName); if (stats.addrBind.IsValid()) { From 2c3feb8e4b4908447f61447850c68682d0183fb6 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Thu, 27 Apr 2023 07:21:41 +0000 Subject: [PATCH 07/10] merge bitcoin#20217: Remove g_relay_txes --- src/init.cpp | 15 +++--- src/net.cpp | 9 +++- src/net.h | 9 +--- src/net_processing.cpp | 83 +++++++++++++++--------------- src/net_processing.h | 11 +++- src/rpc/net.cpp | 4 +- src/test/denialofservice_tests.cpp | 25 ++++----- src/test/util/setup_common.cpp | 6 +-- 8 files changed, 84 insertions(+), 78 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index eeddeaaae61a..72313840b624 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1756,10 +1756,9 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc // is not yet setup and may end up being set up twice if we // need to reindex later. - // see Step 2: parameter interactions for more information about these fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN); fDiscover = args.GetBoolArg("-discover", true); - g_relay_txes = !args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); + const bool ignores_incoming_txs{args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)}; assert(!node.addrman); node.addrman = std::make_unique(); @@ -1771,7 +1770,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc assert(!node.fee_estimator); // Don't initialize fee estimation with old data if we don't relay transactions, // as they would never get updated. - if (g_relay_txes) node.fee_estimator = std::make_unique(); + if (!ignores_incoming_txs) node.fee_estimator = std::make_unique(); assert(!node.mempool); int check_ratio = std::min(std::max(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); @@ -1781,9 +1780,9 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc node.chainman = &g_chainman; ChainstateManager& chainman = *Assert(node.chainman); - node.peerman.reset(new PeerManager( - chainparams, *node.connman, *node.addrman, node.banman.get(), *node.scheduler, chainman, *node.mempool, node.llmq_ctx - )); + assert(!node.peerman); + node.peerman = std::make_unique(chainparams, *node.connman, *node.addrman, node.banman.get(), + *node.scheduler, chainman, *node.mempool, node.llmq_ctx, ignores_incoming_txs); RegisterValidationInterface(node.peerman.get()); ::governance = std::make_unique(); @@ -2310,7 +2309,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc ::coinJoinServer = std::make_unique(*node.mempool, *node.connman, ::masternodeSync); #ifdef ENABLE_WALLET - if (g_relay_txes) { + if (!ignores_incoming_txs) { ::coinJoinClientQueueManager = std::make_unique(*node.connman, ::masternodeSync); } #endif // ENABLE_WALLET @@ -2383,7 +2382,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*::coinJoinServer)), std::chrono::seconds{1}); node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1}); #ifdef ENABLE_WALLET - } else if (g_relay_txes && CCoinJoinClientOptions::IsEnabled()) { + } else if (!ignores_incoming_txs && CCoinJoinClientOptions::IsEnabled()) { node.scheduler->scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*node.connman), std::ref(*node.fee_estimator), std::ref(*node.mempool)), std::chrono::seconds{1}); #endif // ENABLE_WALLET } diff --git a/src/net.cpp b/src/net.cpp index 453e75ee3d21..7e169da5fd1c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -130,7 +130,6 @@ static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // S // bool fDiscover = true; bool fListen = true; -bool g_relay_txes = !DEFAULT_BLOCKSONLY; CCriticalSection cs_mapLocalHost; std::map mapLocalHost GUARDED_BY(cs_mapLocalHost); static bool vfLimited[NET_MAX] GUARDED_BY(cs_mapLocalHost) = {}; @@ -555,6 +554,14 @@ void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNet } } +bool CNode::IsBlockRelayOnly() const { + bool ignores_incoming_txs{gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)}; + // Stop processing non-block data early if + // 1) We are in blocks only mode and peer has no relay permission + // 2) This peer is a block-relay-only peer + return (ignores_incoming_txs && !HasPermission(PF_RELAY)) || !IsAddrRelayPeer(); +} + std::string CNode::GetAddrName() const { LOCK(cs_addrName); return addrName; diff --git a/src/net.h b/src/net.h index 2e4ba3cc751f..5f630cbd4e8f 100644 --- a/src/net.h +++ b/src/net.h @@ -762,7 +762,6 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices) extern bool fDiscover; extern bool fListen; -extern bool g_relay_txes; /** Subversion as sent to the P2P network in `version` messages */ extern std::string strSubVersion; @@ -1055,13 +1054,7 @@ class CNode // traffic). bool IsAddrRelayPeer() const { return m_addr_known != nullptr; } - bool IsBlockRelayOnly() const - { - // Stop processing non-block data early if - // 1) We are in blocks only mode and peer has no relay permission - // 2) This peer is a block-relay-only peer - return (!g_relay_txes && !HasPermission(PF_RELAY)) || !IsAddrRelayPeer(); - } + bool IsBlockRelayOnly() const; // List of block ids we still have announce. // There is no final sorting before sending, as they are always sent immediately diff --git a/src/net_processing.cpp b/src/net_processing.cpp index f336494a18dd..57235fc97e39 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -452,43 +452,6 @@ static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUS nPreferredDownload += state->fPreferredDownload; } -static void PushNodeVersion(CNode& pnode, CConnman& connman, int64_t nTime) -{ - const auto& params = Params(); - - // Note that pnode->GetLocalServices() is a reflection of the local - // services we were offering when the CNode object was created for this - // peer. - ServiceFlags nLocalNodeServices = pnode.GetLocalServices(); - uint64_t nonce = pnode.GetLocalNonce(); - int nNodeStartingHeight = pnode.GetMyStartingHeight(); - NodeId nodeid = pnode.GetId(); - CAddress addr = pnode.addr; - - CAddress addrYou = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ? - addr : - CAddress(CService(), addr.nServices); - CAddress addrMe = CAddress(CService(), nLocalNodeServices); - - uint256 mnauthChallenge; - GetRandBytes(mnauthChallenge.begin(), mnauthChallenge.size()); - pnode.SetSentMNAuthChallenge(mnauthChallenge); - - int nProtocolVersion = PROTOCOL_VERSION; - if (params.NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) { - nProtocolVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION); - } - - connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, nProtocolVersion, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe, - nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes && pnode.IsAddrRelayPeer(), mnauthChallenge, pnode.m_masternode_connection.load())); - - if (fLogIPs) { - LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid); - } else { - LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addrMe.ToString(), nodeid); - } -} - // Returns a bool indicating whether we requested this block. // Also used if a block was /not/ received and timed out or started with another peer static bool MarkBlockAsReceived(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { @@ -735,6 +698,43 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec } } // namespace +void PeerManager::PushNodeVersion(CNode& pnode, int64_t nTime) +{ + const auto& params = Params(); + + // Note that pnode->GetLocalServices() is a reflection of the local + // services we were offering when the CNode object was created for this + // peer. + ServiceFlags nLocalNodeServices = pnode.GetLocalServices(); + uint64_t nonce = pnode.GetLocalNonce(); + int nNodeStartingHeight = pnode.GetMyStartingHeight(); + NodeId nodeid = pnode.GetId(); + CAddress addr = pnode.addr; + + CAddress addrYou = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ? + addr : + CAddress(CService(), addr.nServices); + CAddress addrMe = CAddress(CService(), nLocalNodeServices); + + uint256 mnauthChallenge; + GetRandBytes(mnauthChallenge.begin(), mnauthChallenge.size()); + pnode.SetSentMNAuthChallenge(mnauthChallenge); + + int nProtocolVersion = PROTOCOL_VERSION; + if (params.NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) { + nProtocolVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION); + } + + m_connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, nProtocolVersion, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe, + nonce, strSubVersion, nNodeStartingHeight, !m_ignore_incoming_txs && pnode.IsAddrRelayPeer(), mnauthChallenge, pnode.m_masternode_connection.load())); + + if (fLogIPs) { + LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid); + } else { + LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addrMe.ToString(), nodeid); + } +} + void EraseObjectRequest(CNodeState* nodestate, const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); @@ -906,7 +906,7 @@ void PeerManager::InitializeNode(CNode *pnode) { m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer)); } if (!pnode->fInbound) - PushNodeVersion(*pnode, m_connman, GetTime()); + PushNodeVersion(*pnode, GetTime()); } void PeerManager::ReattemptInitialBroadcast(CScheduler& scheduler) const @@ -1288,7 +1288,7 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para } PeerManager::PeerManager(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, - std::unique_ptr& llmq_ctx) + std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) : m_chainparams(chainparams), m_connman(connman), m_addrman(addrman), @@ -1296,7 +1296,8 @@ PeerManager::PeerManager(const CChainParams& chainparams, CConnman& connman, CAd m_chainman(chainman), m_mempool(pool), m_llmq_ctx(llmq_ctx), - m_stale_tip_check_time(0) + m_stale_tip_check_time(0), + m_ignore_incoming_txs(ignore_incoming_txs) { // Initialize global variables that cannot be constructed at startup. recentRejects.reset(new CRollingBloomFilter(120000, 0.000001)); @@ -2681,7 +2682,7 @@ void PeerManager::ProcessMessage( // Be shy and don't send version until we hear if (pfrom.fInbound) - PushNodeVersion(pfrom, m_connman, GetAdjustedTime()); + PushNodeVersion(pfrom, GetAdjustedTime()); if (Params().NetworkIDString() == CBaseChainParams::DEVNET) { if (cleanSubVer.find(strprintf("devnet.%s", gArgs.GetDevNetName())) == std::string::npos) { diff --git a/src/net_processing.h b/src/net_processing.h index 247fbf071adc..086e7b4a4082 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -73,7 +73,7 @@ using PeerRef = std::shared_ptr; class PeerManager final : public CValidationInterface, public NetEventsInterface { public: PeerManager(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, - ChainstateManager& chainman, CTxMemPool& pool, std::unique_ptr& llmq_ctx); + ChainstateManager& chainman, CTxMemPool& pool, std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); /** * Overridden from CValidationInterface. @@ -131,6 +131,9 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface /** Get statistics from node state */ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats); + /** Whether this node ignores txs received over p2p. */ + bool IgnoresIncomingTxs() { return m_ignore_incoming_txs; }; + bool IsBanned(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main); private: @@ -178,6 +181,9 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req); + /** Send a version message to a peer */ + void PushNodeVersion(CNode& pnode, int64_t nTime); + const CChainParams& m_chainparams; CConnman& m_connman; /** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */ @@ -189,6 +195,9 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface int64_t m_stale_tip_check_time; //!< Next time to check for stale tip + //* Whether this node is running in blocks only mode */ + const bool m_ignore_incoming_txs; + /** Protects m_peer_map */ mutable Mutex m_peer_mutex; /** diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 058fe265e5aa..748d0c1f7759 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -547,7 +547,9 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) obj.pushKV("localservices", strprintf("%016x", services)); obj.pushKV("localservicesnames", GetServicesNames(services)); } - obj.pushKV("localrelay", g_relay_txes); + if (node.peerman) { + obj.pushKV("localrelay", !node.peerman->IgnoresIncomingTxs()); + } obj.pushKV("timeoffset", GetTimeOffset()); if (node.connman) { obj.pushKV("networkactive", node.connman->GetNetworkActive()); diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index ef9a7fcd9e1e..3c670b855e98 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -80,9 +80,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) { const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx - ); + auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -153,9 +152,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) { const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx - ); + auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); const Consensus::Params& consensusParams = Params().GetConsensus(); constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS; @@ -228,9 +226,8 @@ BOOST_AUTO_TEST_CASE(DoS_banning) const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx - ); + auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -276,9 +273,8 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx - ); + auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); banman->ClearBanned(); gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number @@ -322,9 +318,8 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique( - chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx - ); + auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); banman->ClearBanned(); int64_t nStartTime = GetTime(); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 0f625cc15b42..a8506e0d1d22 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -244,9 +244,9 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); - m_node.peerman = std::make_unique( - chainparams, *m_node.connman, *m_node.addrman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx - ); + m_node.peerman = std::make_unique(chainparams, *m_node.connman, *m_node.addrman, m_node.banman.get(), + *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, + false); { CConnman::Options options; options.m_msgproc = m_node.peerman.get(); From 6f3060b763e62f6b83446c19b2c7172cd79f25b2 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Fri, 28 Apr 2023 06:36:19 +0000 Subject: [PATCH 08/10] merge bitcoin#20649: Remove nMyStartingHeight from CNode/Connman --- src/init.cpp | 2 +- src/net.cpp | 17 +++-------------- src/net.h | 13 +------------ src/net_processing.cpp | 11 +++++------ src/net_processing.h | 8 +++++++- src/test/denialofservice_tests.cpp | 12 ++++++------ src/test/fuzz/connman.cpp | 4 ---- src/test/fuzz/net.cpp | 2 -- src/test/fuzz/process_message.cpp | 2 +- src/test/fuzz/process_messages.cpp | 2 +- src/test/fuzz/util.h | 3 +-- src/test/net_tests.cpp | 7 +++---- 12 files changed, 29 insertions(+), 54 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 72313840b624..cf5cd86cdc88 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2479,6 +2479,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc } } LogPrintf("::ChainActive().Height() = %d\n", chain_active_height); + if (node.peerman) node.peerman->SetBestHeight(chain_active_height); Discover(); @@ -2492,7 +2493,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc connOptions.m_max_outbound_block_relay = std::min(MAX_BLOCK_RELAY_ONLY_CONNECTIONS, connOptions.nMaxConnections-connOptions.m_max_outbound_full_relay); connOptions.nMaxAddnode = MAX_ADDNODE_CONNECTIONS; connOptions.nMaxFeeler = MAX_FEELER_CONNECTIONS; - connOptions.nBestHeight = chain_active_height; connOptions.uiInterface = &uiInterface; connOptions.m_banman = node.banman.get(); connOptions.m_msgproc = node.peerman.get(); diff --git a/src/net.cpp b/src/net.cpp index 7e169da5fd1c..766ba32ccbf2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -507,7 +507,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo NodeId id = GetNewNodeId(); uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); CAddress addr_bind = GetBindAddress(sock->Get()); - CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), sock->Release(), addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false, block_relay_only); + CNode* pnode = new CNode(id, nLocalServices, sock->Release(), addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false, block_relay_only); pnode->AddRef(); statsClient.inc("peers.connect", 1.0f); @@ -1220,7 +1220,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end(); - CNode* pnode = new CNode(id, nodeServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true, inbound_onion); + CNode* pnode = new CNode(id, nodeServices, hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true, inbound_onion); pnode->AddRef(); pnode->m_permissionFlags = permissionFlags; // If this flag is present, the user probably expect that RPC and QT report it as whitelisted (backward compatibility) @@ -3759,19 +3759,9 @@ ServiceFlags CConnman::GetLocalServices() const return nLocalServices; } -void CConnman::SetBestHeight(int height) -{ - nBestHeight.store(height, std::memory_order_release); -} - -int CConnman::GetBestHeight() const -{ - return nBestHeight.load(std::memory_order_acquire); -} - unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } -CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, bool fInboundIn, bool block_relay_only, bool inbound_onion) +CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, bool fInboundIn, bool block_relay_only, bool inbound_onion) : nTimeConnected(GetSystemTimeInSeconds()), addr(addrIn), addrBind(addrBindIn), @@ -3781,7 +3771,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn id(idIn), nLocalHostNonce(nLocalHostNonceIn), nLocalServices(nLocalServicesIn), - nMyStartingHeight(nMyStartingHeightIn), m_inbound_onion(inbound_onion) { hSocket = hSocketIn; diff --git a/src/net.h b/src/net.h index 5f630cbd4e8f..a28f04199375 100644 --- a/src/net.h +++ b/src/net.h @@ -166,7 +166,6 @@ friend class CNode; int m_max_outbound_block_relay = 0; int nMaxAddnode = 0; int nMaxFeeler = 0; - int nBestHeight = 0; CClientUIInterface* uiInterface = nullptr; NetEventsInterface* m_msgproc = nullptr; BanMan* m_banman = nullptr; @@ -195,7 +194,6 @@ friend class CNode; nMaxAddnode = connOptions.nMaxAddnode; nMaxFeeler = connOptions.nMaxFeeler; m_max_outbound = m_max_outbound_full_relay + m_max_outbound_block_relay + nMaxFeeler; - nBestHeight = connOptions.nBestHeight; clientInterface = connOptions.uiInterface; m_banman = connOptions.m_banman; m_msgproc = connOptions.m_msgproc; @@ -467,9 +465,6 @@ friend class CNode; uint64_t GetTotalBytesRecv(); uint64_t GetTotalBytesSent(); - void SetBestHeight(int height); - int GetBestHeight() const; - /** Get a unique deterministic randomizer. */ CSipHasher GetDeterministicRandomizer(uint64_t id) const; @@ -629,7 +624,6 @@ friend class CNode; int nMaxFeeler; int m_max_outbound; bool m_use_addrman_outgoing; - std::atomic nBestHeight; CClientUIInterface* clientInterface; NetEventsInterface* m_msgproc; BanMan* m_banman; @@ -1126,7 +1120,7 @@ class CNode // If true, we will send him all quorum related messages, even if he is not a member of our quorums std::atomic qwatch{false}; - CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false, bool block_relay_only = false, bool inbound_onion = false); + CNode(NodeId id, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false, bool block_relay_only = false, bool inbound_onion = false); ~CNode(); CNode(const CNode&) = delete; CNode& operator=(const CNode&) = delete; @@ -1152,7 +1146,6 @@ class CNode //! service advertisements. const ServiceFlags nLocalServices; - const int nMyStartingHeight; int nSendVersion {0}; NetPermissionFlags m_permissionFlags{ PF_NONE }; std::list vRecvMsg; // Used only by SocketHandler thread @@ -1184,10 +1177,6 @@ class CNode return nLocalHostNonce; } - int GetMyStartingHeight() const { - return nMyStartingHeight; - } - int GetRefCount() const { assert(nRefCount >= 0); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 57235fc97e39..1ec9d9ee4d46 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -707,7 +707,7 @@ void PeerManager::PushNodeVersion(CNode& pnode, int64_t nTime) // peer. ServiceFlags nLocalNodeServices = pnode.GetLocalServices(); uint64_t nonce = pnode.GetLocalNonce(); - int nNodeStartingHeight = pnode.GetMyStartingHeight(); + const int nNodeStartingHeight{m_best_height}; NodeId nodeid = pnode.GetId(); CAddress addr = pnode.addr; @@ -1453,9 +1453,8 @@ void PeerManager::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ * Update our best height and announce any block hashes which weren't previously * in ::ChainActive() to our peers. */ -void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { - const int nNewHeight = pindexNew->nHeight; - m_connman.SetBestHeight(nNewHeight); +void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload){ + m_best_height = pindexNew->nHeight; SetServiceFlagsIBDCache(!fInitialDownload); if (!fInitialDownload) { @@ -1472,11 +1471,11 @@ void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockInde } } // Relay inventory, but don't relay old inventory during initial block download. - m_connman.ForEachNode([nNewHeight, &vHashes](CNode* pnode) { + m_connman.ForEachNode([this, &vHashes](CNode* pnode) { if (!pnode->CanRelay()) { return; } - if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { + if (m_best_height > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { for (const uint256& hash : reverse_iterate(vHashes)) { pnode->PushBlockHash(hash); } diff --git a/src/net_processing.h b/src/net_processing.h index 086e7b4a4082..b0ca5d69f5ac 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -131,6 +131,9 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface /** Get statistics from node state */ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats); + /** Set the best height */ + void SetBestHeight(int height) { m_best_height = height; }; + /** Whether this node ignores txs received over p2p. */ bool IgnoresIncomingTxs() { return m_ignore_incoming_txs; }; @@ -193,9 +196,12 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface CTxMemPool& m_mempool; std::unique_ptr& m_llmq_ctx; + /** The height of the best chain */ + std::atomic m_best_height{-1}; + int64_t m_stale_tip_check_time; //!< Next time to check for stale tip - //* Whether this node is running in blocks only mode */ + /** Whether this node is running in blocks only mode */ const bool m_ignore_incoming_txs; /** Protects m_peer_map */ diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 3c670b855e98..7253c2946343 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", /*fInboundIn=*/ false); + CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK), INVALID_SOCKET, addr1, 0, 0, CAddress(), "", /*fInboundIn=*/ false); dummyNode1.SetSendVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(&dummyNode1); @@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) static void AddRandomOutboundPeer(std::vector &vNodes, PeerManager &peerLogic, CConnmanTest* connman) { CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE); - vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false)); + vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK), INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false)); CNode &node = *vNodes.back(); node.SetSendVersion(PROTOCOL_VERSION); @@ -231,7 +231,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true); + CNode dummyNode1(id++, NODE_NETWORK, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(&dummyNode1); dummyNode1.nVersion = 1; @@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(!banman->IsDiscouraged(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); - CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true); + CNode dummyNode2(id++, NODE_NETWORK, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true); dummyNode2.SetSendVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(&dummyNode2); dummyNode2.nVersion = 1; @@ -279,7 +279,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) banman->ClearBanned(); gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true); + CNode dummyNode1(id++, NODE_NETWORK, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(&dummyNode1); dummyNode1.nVersion = 1; @@ -326,7 +326,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true); + CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true); dummyNode.SetSendVersion(PROTOCOL_VERSION); peerLogic->InitializeNode(&dummyNode); dummyNode.nVersion = 1; diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index 13de7604bd37..9c21e7ce7d8a 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -102,9 +102,6 @@ FUZZ_TARGET_INIT(connman, initialize_connman) connman.SetAsmap(asmap); } }, - [&] { - connman.SetBestHeight(fuzzed_data_provider.ConsumeIntegral()); - }, [&] { connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool()); }, @@ -113,7 +110,6 @@ FUZZ_TARGET_INIT(connman, initialize_connman) }); } (void)connman.GetAddedNodeInfo(); - (void)connman.GetBestHeight(); (void)connman.GetExtraOutboundCount(); (void)connman.GetLocalServices(); (void)connman.GetMaxOutboundTarget(); diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index a302b0aa75c8..9252c0b2ab43 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -39,7 +39,6 @@ FUZZ_TARGET_INIT(net, initialize_net) CNode node{fuzzed_data_provider.ConsumeIntegral(), static_cast(fuzzed_data_provider.ConsumeIntegral()), - fuzzed_data_provider.ConsumeIntegral(), INVALID_SOCKET, *address, fuzzed_data_provider.ConsumeIntegral(), @@ -138,7 +137,6 @@ FUZZ_TARGET_INIT(net, initialize_net) (void)node.GetId(); (void)node.GetLocalNonce(); (void)node.GetLocalServices(); - (void)node.GetMyStartingHeight(); (void)node.GetRecvVersion(); const int ref_count = node.GetRefCount(); assert(ref_count >= 0); diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index eec3b8fb0b5b..f377fcc36063 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -64,7 +64,7 @@ void fuzz_target(const std::vector& buffer, const std::string& LIMIT_TO return; } CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes(), SER_NETWORK, PROTOCOL_VERSION}; - CNode p2p_node{0, ServiceFlags(NODE_NETWORK | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, false}; + CNode p2p_node{0, ServiceFlags(NODE_NETWORK | NODE_BLOOM), INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, false}; p2p_node.fSuccessfullyConnected = true; p2p_node.nVersion = PROTOCOL_VERSION; p2p_node.SetSendVersion(PROTOCOL_VERSION); diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index 654504d96f9e..8d43502be677 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -44,7 +44,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) for (int i = 0; i < num_peers_to_add; ++i) { const ServiceFlags service_flags = ServiceFlags(fuzzed_data_provider.ConsumeIntegral()); const bool inbound{fuzzed_data_provider.ConsumeBool()}; - peers.push_back(std::make_unique(i, service_flags, 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, inbound).release()); + peers.push_back(std::make_unique(i, service_flags, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, inbound).release()); CNode& p2p_node = *peers.back(); p2p_node.fSuccessfullyConnected = true; diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index b4b9eb45b5e7..ef6851e5bc84 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -292,7 +292,6 @@ inline CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept { const NodeId node_id = fuzzed_data_provider.ConsumeIntegral(); const ServiceFlags local_services = static_cast(fuzzed_data_provider.ConsumeIntegral()); - const int my_starting_height = fuzzed_data_provider.ConsumeIntegral(); const SOCKET socket = INVALID_SOCKET; const CAddress address = ConsumeAddress(fuzzed_data_provider); const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral(); @@ -301,7 +300,7 @@ inline CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64); const bool inbound = fuzzed_data_provider.ConsumeBool(); const bool block_relay_only = fuzzed_data_provider.ConsumeBool(); - return {node_id, local_services, my_starting_height, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, inbound, block_relay_only}; + return {node_id, local_services, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, inbound, block_relay_only}; } inline void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST) diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 024fff406fdf..96b930bf1674 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -178,7 +178,6 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) { SOCKET hSocket = INVALID_SOCKET; NodeId id = 0; - int height = 0; in_addr ipv4Addr; ipv4Addr.s_addr = 0xa0b0c001; @@ -188,12 +187,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) bool fInboundIn = false; // Test that fFeeler is false by default. - std::unique_ptr pnode1 = std::make_unique(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn); + std::unique_ptr pnode1 = std::make_unique(id++, NODE_NETWORK, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - std::unique_ptr pnode2 = std::make_unique(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn); + std::unique_ptr pnode2 = std::make_unique(id++, NODE_NETWORK, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } @@ -624,7 +623,7 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test) in_addr ipv4AddrPeer; ipv4AddrPeer.s_addr = 0xa0b0c001; CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK); - std::unique_ptr pnode = std::make_unique(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, false); + std::unique_ptr pnode = std::make_unique(0, NODE_NETWORK, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, false); pnode->fSuccessfullyConnected.store(true); // the peer claims to be reaching us via IPv6 From 3a4c4633a47a1cd06c61d1551c7d76501b50c1bb Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Thu, 27 Apr 2023 08:48:14 +0000 Subject: [PATCH 09/10] merge bitcoin#18458: Add missing cs_vNodes lock --- src/init.cpp | 15 ++++++++++++++- src/net.cpp | 12 +++++++----- src/net.h | 17 +++++++---------- src/net_processing.h | 1 + src/test/denialofservice_tests.cpp | 1 - 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index cf5cd86cdc88..8c3587ff6a43 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -245,7 +245,20 @@ void PrepareShutdown(NodeContext& node) // Because these depend on each-other, we make sure that neither can be // using the other before destroying them. if (node.peerman) UnregisterValidationInterface(node.peerman.get()); - if (node.connman) node.connman->Stop(); + // Follow the lock order requirements: + // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount + // which locks cs_vNodes. + // * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which + // locks cs_vNodes. + // * CConnman::Stop calls DeleteNode, which calls FinalizeNode, which locks cs_main and calls + // EraseOrphansFor, which locks g_cs_orphans. + // + // Thus the implicit locking order requirement is: (1) cs_main, (2) g_cs_orphans, (3) cs_vNodes. + if (node.connman) { + node.connman->StopThreads(); + LOCK2(::cs_main, ::g_cs_orphans); + node.connman->StopNodes(); + } StopTorControl(); diff --git a/src/net.cpp b/src/net.cpp index 766ba32ccbf2..fd2566feb50c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3238,7 +3238,7 @@ void CConnman::Interrupt() } } -void CConnman::Stop() +void CConnman::StopThreads() { if (threadMessageHandler.joinable()) threadMessageHandler.join(); @@ -3252,9 +3252,11 @@ void CConnman::Stop() threadDNSAddressSeed.join(); if (threadSocketHandler.joinable()) threadSocketHandler.join(); +} - if (fAddressesInitialized) - { +void CConnman::StopNodes() +{ + if (fAddressesInitialized) { DumpAddresses(); fAddressesInitialized = false; } @@ -3287,10 +3289,10 @@ void CConnman::Stop() // clean up some globals (to help leak detection) std::vector nodes; WITH_LOCK(cs_vNodes, nodes.swap(vNodes)); - for (CNode *pnode : nodes) { + for (CNode* pnode : nodes) { DeleteNode(pnode); } - for (CNode *pnode : vNodesDisconnected) { + for (CNode* pnode : vNodesDisconnected) { DeleteNode(pnode); } mapSocketToNode.clear(); diff --git a/src/net.h b/src/net.h index a28f04199375..29ff443303d9 100644 --- a/src/net.h +++ b/src/net.h @@ -217,16 +217,13 @@ friend class CNode; ~CConnman(); bool Start(CScheduler& scheduler, const Options& options); - // TODO: Remove NO_THREAD_SAFETY_ANALYSIS. Lock cs_vNodes before reading the variable vNodes. - // - // When removing NO_THREAD_SAFETY_ANALYSIS be aware of the following lock order requirements: - // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount - // which locks cs_vNodes. - // * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which - // locks cs_vNodes. - // - // Thus the implicit locking order requirement is: (1) cs_main, (2) g_cs_orphans, (3) cs_vNodes. - void Stop() NO_THREAD_SAFETY_ANALYSIS; + void StopThreads(); + void StopNodes(); + void Stop() + { + StopThreads(); + StopNodes(); + }; void Interrupt(); bool GetNetworkActive() const { return fNetworkActive; }; diff --git a/src/net_processing.h b/src/net_processing.h index b0ca5d69f5ac..876cc6c33264 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -21,6 +21,7 @@ class TxValidationState; struct LLMQContext; extern CCriticalSection cs_main; +extern CCriticalSection g_cs_orphans; /** Default for -maxorphantxsize, maximum size in megabytes the orphan map can grow before entries are removed */ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE = 10; // this allows around 100 TXs of max size (and many more of normal size) diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 7253c2946343..a9325c66ba6d 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -52,7 +52,6 @@ struct COrphanTx { NodeId fromPeer; int64_t nTimeExpire; }; -extern CCriticalSection g_cs_orphans; extern std::map mapOrphanTransactions GUARDED_BY(g_cs_orphans); static CService ip(uint32_t i) From d663d47be91796d1d0bc4d67a05d946689acf771 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Fri, 28 Apr 2023 05:23:04 +0000 Subject: [PATCH 10/10] merge bitcoin#20811: move net_processing implementation details out of header --- src/init.cpp | 4 +- src/net.h | 23 ++- src/net_processing.cpp | 220 +++++++++++++++++++++++++---- src/net_processing.h | 187 +++--------------------- src/test/denialofservice_tests.cpp | 20 +-- src/test/util/setup_common.cpp | 6 +- 6 files changed, 245 insertions(+), 215 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8c3587ff6a43..6e64d286d51d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1794,8 +1794,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc ChainstateManager& chainman = *Assert(node.chainman); assert(!node.peerman); - node.peerman = std::make_unique(chainparams, *node.connman, *node.addrman, node.banman.get(), - *node.scheduler, chainman, *node.mempool, node.llmq_ctx, ignores_incoming_txs); + node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), + *node.scheduler, chainman, *node.mempool, node.llmq_ctx, ignores_incoming_txs); RegisterValidationInterface(node.peerman.get()); ::governance = std::make_unique(); diff --git a/src/net.h b/src/net.h index 29ff443303d9..c15110a30b00 100644 --- a/src/net.h +++ b/src/net.h @@ -705,11 +705,30 @@ struct CombinerAll class NetEventsInterface { public: - virtual bool ProcessMessages(CNode* pnode, std::atomic& interrupt) = 0; - virtual bool SendMessages(CNode* pnode) = 0; + /** Initialize a peer (setup state, queue any initial messages) */ virtual void InitializeNode(CNode* pnode) = 0; + + /** Handle removal of a peer (clear state) */ virtual void FinalizeNode(const CNode& node) = 0; + /** + * Process protocol messages received from a given node + * + * @param[in] pnode The node which we have received messages from. + * @param[in] interrupt Interrupt condition for processing threads + * @return True if there is more work to be done + */ + virtual bool ProcessMessages(CNode* pnode, std::atomic& interrupt) = 0; + + /** + * Send queued protocol messages to a given node. + * + * @param[in] pnode The node which we are sending messages to. + * @return True if there is more work to be done + */ + virtual bool SendMessages(CNode* pnode) = 0; + + protected: /** * Protected destructor so that instances can only be deleted by derived classes. diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 1ec9d9ee4d46..b9de0cd85f9f 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -169,6 +169,157 @@ size_t nMapOrphanTransactionsSize = 0; void EraseOrphansFor(NodeId peer); // Internal stuff +namespace { +/** + * Data structure for an individual peer. This struct is not protected by + * cs_main since it does not contain validation-critical data. + * + * Memory is owned by shared pointers and this object is destructed when + * the refcount drops to zero. + * + * TODO: move most members from CNodeState to this structure. + * TODO: move remaining application-layer data members from CNode to this structure. + */ +struct Peer { + /** Same id as the CNode object for this peer */ + const NodeId m_id{0}; + + /** Protects misbehavior data members */ + Mutex m_misbehavior_mutex; + /** Accumulated misbehavior score for this peer */ + int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0}; + /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */ + bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false}; + + /** Set of txids to reconsider once their parent transactions have been accepted **/ + std::set m_orphan_work_set GUARDED_BY(g_cs_orphans); + + /** Protects m_getdata_requests **/ + Mutex m_getdata_requests_mutex; + /** Work queue of items requested by this peer **/ + std::deque m_getdata_requests GUARDED_BY(m_getdata_requests_mutex); + + explicit Peer(NodeId id) : m_id(id) {} +}; + +using PeerRef = std::shared_ptr; + +class PeerManagerImpl final : public PeerManager +{ +public: + PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, + BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, + CTxMemPool& pool, std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); + + /** Overridden from CValidationInterface. */ + void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected) override; + void BlockDisconnected(const std::shared_ptr &block, const CBlockIndex* pindex) override; + void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; + void BlockChecked(const CBlock& block, const BlockValidationState& state) override; + void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) override; + + /** Implement NetEventsInterface */ + void InitializeNode(CNode* pnode) override; + void FinalizeNode(const CNode& node) override; + bool ProcessMessages(CNode* pfrom, std::atomic& interrupt) override; + bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing); + + /** Implement PeerManager */ + void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) override; + bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) override; + bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; } + void SetBestHeight(int height) override { m_best_height = height; }; + void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message = "") override; + void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, + int64_t nTimeReceived, const std::atomic& interruptMsgProc) override; + bool IsBanned(NodeId pnode) override EXCLUSIVE_LOCKS_REQUIRED(cs_main); + +private: + /** Consider evicting an outbound peer based on the amount of time they've been behind our tip */ + void ConsiderEviction(CNode& pto, int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + /** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */ + void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + /** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */ + void ReattemptInitialBroadcast(CScheduler& scheduler) const; + + /** Get a shared pointer to the Peer object. + * May return an empty shared_ptr if the Peer object can't be found. */ + PeerRef GetPeerRef(NodeId id) const; + + /** Get a shared pointer to the Peer object and remove it from m_peer_map. + * May return an empty shared_ptr if the Peer object can't be found. */ + PeerRef RemovePeer(NodeId id); + + /** + * Potentially mark a node discouraged based on the contents of a BlockValidationState object + * + * @param[in] via_compact_block this bool is passed in because net_processing should + * punish peers differently depending on whether the data was provided in a compact + * block message or not. If the compact block had a valid header, but contained invalid + * txs, the peer should not be punished. See BIP 152. + * + * @return Returns true if the peer was punished (probably disconnected) + */ + bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, + bool via_compact_block, const std::string& message = ""); + + /** + * Potentially ban a node based on the contents of a TxValidationState object + * + * @return Returns true if the peer was punished (probably disconnected) + * + * Changes here may need to be reflected in TxRelayMayResultInDisconnect(). + */ + bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = ""); + + /** Maybe disconnect a peer and discourage future connections from its address. + * + * @param[in] pnode The node to check. + * @return True if the peer was marked for disconnection in this function + */ + bool MaybeDiscourageAndDisconnect(CNode& pnode); + + void ProcessOrphanTx(std::set& orphan_work_set) + EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans); + /** Process a single headers message from a peer. */ + void ProcessHeadersMessage(CNode& pfrom, const std::vector& headers, bool via_compact_block); + + void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req); + + /** Send a version message to a peer */ + void PushNodeVersion(CNode& pnode, int64_t nTime); + + const CChainParams& m_chainparams; + CConnman& m_connman; + /** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */ + BanMan* const m_banman; + CAddrMan& m_addrman; + ChainstateManager& m_chainman; + CTxMemPool& m_mempool; + std::unique_ptr& m_llmq_ctx; + + /** The height of the best chain */ + std::atomic m_best_height{-1}; + + int64_t m_stale_tip_check_time; //!< Next time to check for stale tip + + /** Whether this node is running in blocks only mode */ + const bool m_ignore_incoming_txs; + + /** Protects m_peer_map */ + mutable Mutex m_peer_mutex; + /** + * Map of all Peer objects, keyed by peer id. This map is protected + * by the m_peer_mutex. Once a shared pointer reference is + * taken, the lock may be released. Individual fields are protected by + * their own locks. + */ + std::map m_peer_map GUARDED_BY(m_peer_mutex); +}; +} // namespace + namespace { /** Number of nodes with fSyncStarted. */ int nSyncStarted GUARDED_BY(cs_main) = 0; @@ -698,7 +849,7 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec } } // namespace -void PeerManager::PushNodeVersion(CNode& pnode, int64_t nTime) +void PeerManagerImpl::PushNodeVersion(CNode& pnode, int64_t nTime) { const auto& params = Params(); @@ -893,7 +1044,7 @@ static bool IsOutboundDisconnectionCandidate(const CNode& node) return !(node.fInbound || node.m_manual_connection || node.fFeeler || node.fOneShot); } -void PeerManager::InitializeNode(CNode *pnode) { +void PeerManagerImpl::InitializeNode(CNode *pnode) { CAddress addr = pnode->addr; NodeId nodeid = pnode->GetId(); { @@ -909,7 +1060,7 @@ void PeerManager::InitializeNode(CNode *pnode) { PushNodeVersion(*pnode, GetTime()); } -void PeerManager::ReattemptInitialBroadcast(CScheduler& scheduler) const +void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler) const { std::set unbroadcast_txids = m_mempool.GetUnbroadcastTxs(); @@ -928,7 +1079,7 @@ void PeerManager::ReattemptInitialBroadcast(CScheduler& scheduler) const scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta); } -void PeerManager::FinalizeNode(const CNode& node) { +void PeerManagerImpl::FinalizeNode(const CNode& node) { NodeId nodeid = node.GetId(); int misbehavior{0}; LOCK(cs_main); @@ -975,14 +1126,14 @@ void PeerManager::FinalizeNode(const CNode& node) { LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid); } -PeerRef PeerManager::GetPeerRef(NodeId id) const +PeerRef PeerManagerImpl::GetPeerRef(NodeId id) const { LOCK(m_peer_mutex); auto it = m_peer_map.find(id); return it != m_peer_map.end() ? it->second : nullptr; } -PeerRef PeerManager::RemovePeer(NodeId id) +PeerRef PeerManagerImpl::RemovePeer(NodeId id) { PeerRef ret; LOCK(m_peer_mutex); @@ -994,7 +1145,8 @@ PeerRef PeerManager::RemovePeer(NodeId id) return ret; } -bool PeerManager::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { +bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) +{ { LOCK(cs_main); CNodeState* state = State(nodeid); @@ -1156,7 +1308,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphansSize) return nEvicted; } -void PeerManager::Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) +void PeerManagerImpl::Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) { assert(howmuch > 0); @@ -1178,7 +1330,7 @@ void PeerManager::Misbehaving(const NodeId pnode, const int howmuch, const std:: } } -bool PeerManager::IsBanned(NodeId pnode) +bool PeerManagerImpl::IsBanned(NodeId pnode) { PeerRef peer = GetPeerRef(pnode); if (peer == nullptr) @@ -1190,8 +1342,8 @@ bool PeerManager::IsBanned(NodeId pnode) return false; } -bool PeerManager::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, - bool via_compact_block, const std::string& message) +bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, + bool via_compact_block, const std::string& message) { switch (state.GetResult()) { case BlockValidationResult::BLOCK_RESULT_UNSET: @@ -1240,7 +1392,7 @@ bool PeerManager::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationSt return false; } -bool PeerManager::MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message) { +bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message) { switch (state.GetResult()) { case TxValidationResult::TX_RESULT_UNSET: break; @@ -1287,8 +1439,16 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT); } -PeerManager::PeerManager(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, - std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) +std::unique_ptr PeerManager::make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, + CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, + std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) +{ + return std::make_unique(chainparams, connman, addrman, banman, scheduler, chainman, pool, llmq_ctx, ignore_incoming_txs); +} + +PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, + CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, + std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) : m_chainparams(chainparams), m_connman(connman), m_addrman(addrman), @@ -1329,7 +1489,7 @@ PeerManager::PeerManager(const CChainParams& chainparams, CConnman& connman, CAd * Evict orphan txn pool entries (EraseOrphanTx) based on a newly connected * block. Also save the time of the last tip update. */ -void PeerManager::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) +void PeerManagerImpl::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) { { LOCK2(cs_main, g_cs_orphans); @@ -1385,7 +1545,7 @@ void PeerManager::BlockConnected(const std::shared_ptr& pblock, co } } -void PeerManager::BlockDisconnected(const std::shared_ptr &block, const CBlockIndex* pindex) +void PeerManagerImpl::BlockDisconnected(const std::shared_ptr &block, const CBlockIndex* pindex) { // To avoid relay problems with transactions that were previously // confirmed, clear our filter of recently confirmed transactions whenever @@ -1409,7 +1569,7 @@ static uint256 most_recent_block_hash GUARDED_BY(cs_most_recent_block); * Maintain state about the best-seen block and fast-announce a compact block * to compatible peers. */ -void PeerManager::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) { +void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) { std::shared_ptr pcmpctblock = std::make_shared (*pblock); const CNetMsgMaker msgMaker(PROTOCOL_VERSION); @@ -1453,7 +1613,7 @@ void PeerManager::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ * Update our best height and announce any block hashes which weren't previously * in ::ChainActive() to our peers. */ -void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload){ +void PeerManagerImpl::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload){ m_best_height = pindexNew->nHeight; SetServiceFlagsIBDCache(!fInitialDownload); @@ -1489,7 +1649,8 @@ void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockInde * Handle invalid block rejection and consequent peer discouragement, maintain which * peers announce compact blocks. */ -void PeerManager::BlockChecked(const CBlock& block, const BlockValidationState& state) { +void PeerManagerImpl::BlockChecked(const CBlock& block, const BlockValidationState& state) +{ LOCK(cs_main); const uint256 hash(block.GetHash()); @@ -2034,7 +2195,7 @@ void static ProcessGetData(CNode& pfrom, Peer& peer, const CChainParams& chainpa } } -void PeerManager::SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req) { +void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req) { BlockTransactions resp(req); for (size_t i = 0; i < req.indexes.size(); i++) { if (req.indexes[i] >= block.vtx.size()) { @@ -2048,7 +2209,7 @@ void PeerManager::SendBlockTransactions(CNode& pfrom, const CBlock& block, const m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCKTXN, resp)); } -void PeerManager::ProcessHeadersMessage(CNode& pfrom, const std::vector& headers, bool via_compact_block) +void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const std::vector& headers, bool via_compact_block) { const CNetMsgMaker msgMaker(pfrom.GetSendVersion()); size_t nCount = headers.size(); @@ -2231,7 +2392,7 @@ void PeerManager::ProcessHeadersMessage(CNode& pfrom, const std::vector& orphan_work_set) +void PeerManagerImpl::ProcessOrphanTx(std::set& orphan_work_set) { AssertLockHeld(cs_main); AssertLockHeld(g_cs_orphans); @@ -2566,7 +2727,7 @@ std::pair static ValidateDSTX(CTxMemPool& memp return {true, false}; } -void PeerManager::ProcessMessage( +void PeerManagerImpl::ProcessMessage( CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, @@ -4133,7 +4294,7 @@ void PeerManager::ProcessMessage( return; } -bool PeerManager::MaybeDiscourageAndDisconnect(CNode& pnode) +bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode& pnode) { const NodeId peer_id{pnode.GetId()}; PeerRef peer = GetPeerRef(peer_id); @@ -4177,9 +4338,8 @@ bool PeerManager::MaybeDiscourageAndDisconnect(CNode& pnode) return true; } -bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgProc) +bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgProc) { - const CChainParams& chainparams = Params(); bool fMoreWork = false; PeerRef peer = GetPeerRef(pfrom->GetId()); @@ -4253,7 +4413,7 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgP return fMoreWork; } -void PeerManager::ConsiderEviction(CNode& pto, int64_t time_in_seconds) +void PeerManagerImpl::ConsiderEviction(CNode& pto, int64_t time_in_seconds) { AssertLockHeld(cs_main); @@ -4311,7 +4471,7 @@ void PeerManager::ConsiderEviction(CNode& pto, int64_t time_in_seconds) } } -void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds) +void PeerManagerImpl::EvictExtraOutboundPeers(int64_t time_in_seconds) { // Check whether we have too many outbound peers int extra_peers = m_connman.GetExtraOutboundCount(); @@ -4372,7 +4532,7 @@ void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds) } } -void PeerManager::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) +void PeerManagerImpl::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) { LOCK(cs_main); @@ -4412,7 +4572,7 @@ class CompareInvMempoolOrder }; } -bool PeerManager::SendMessages(CNode* pto) +bool PeerManagerImpl::SendMessages(CNode* pto) { assert(m_llmq_ctx); diff --git a/src/net_processing.h b/src/net_processing.h index 876cc6c33264..fefabdb4b495 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -6,18 +6,13 @@ #ifndef BITCOIN_NET_PROCESSING_H #define BITCOIN_NET_PROCESSING_H -#include #include #include #include -class BlockTransactionsRequest; -class BlockValidationState; class CAddrMan; -class CBlockHeader; class CTxMemPool; class ChainstateManager; -class TxValidationState; struct LLMQContext; extern CCriticalSection cs_main; @@ -37,183 +32,39 @@ struct CNodeStateStats { std::vector vHeightInFlight; }; -/** - * Data structure for an individual peer. This struct is not protected by - * cs_main since it does not contain validation-critical data. - * - * Memory is owned by shared pointers and this object is destructed when - * the refcount drops to zero. - * - * TODO: move most members from CNodeState to this structure. - * TODO: move remaining application-layer data members from CNode to this structure. - */ -struct Peer { - /** Same id as the CNode object for this peer */ - const NodeId m_id{0}; - - /** Protects misbehavior data members */ - Mutex m_misbehavior_mutex; - /** Accumulated misbehavior score for this peer */ - int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0}; - /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */ - bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false}; - - /** Set of txids to reconsider once their parent transactions have been accepted **/ - std::set m_orphan_work_set GUARDED_BY(g_cs_orphans); - - /** Protects m_getdata_requests **/ - Mutex m_getdata_requests_mutex; - /** Work queue of items requested by this peer **/ - std::deque m_getdata_requests GUARDED_BY(m_getdata_requests_mutex); - - explicit Peer(NodeId id) : m_id(id) {} -}; - -using PeerRef = std::shared_ptr; - -class PeerManager final : public CValidationInterface, public NetEventsInterface { +class PeerManager : public CValidationInterface, public NetEventsInterface +{ public: - PeerManager(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, - ChainstateManager& chainman, CTxMemPool& pool, std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); - - /** - * Overridden from CValidationInterface. - */ - void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected) override; - void BlockDisconnected(const std::shared_ptr &block, const CBlockIndex* pindex) override; - /** - * Overridden from CValidationInterface. - */ - void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; - /** - * Overridden from CValidationInterface. - */ - void BlockChecked(const CBlock& block, const BlockValidationState& state) override; - /** - * Overridden from CValidationInterface. - */ - void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) override; - - /** Initialize a peer by adding it to mapNodeState and pushing a message requesting its version */ - void InitializeNode(CNode* pnode) override; - /** Handle removal of a peer by updating various state and removing it from mapNodeState */ - void FinalizeNode(const CNode& node) override; - /** - * Process protocol messages received from a given node - * - * @param[in] pfrom The node which we have received messages from. - * @param[in] interrupt Interrupt condition for processing threads - */ - bool ProcessMessages(CNode* pfrom, std::atomic& interrupt) override; - /** - * Send queued protocol messages to be sent to a give node. - * - * @param[in] pto The node which we are sending messages to. - * @return True if there is more work to be done - */ - bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing); - - /** Consider evicting an outbound peer based on the amount of time they've been behind our tip */ - void ConsiderEviction(CNode& pto, int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - /** Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound */ - void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams); - /** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */ - void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - /** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */ - void ReattemptInitialBroadcast(CScheduler& scheduler) const; - /** Process a single message from a peer. Public for fuzz testing */ - void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const std::atomic& interruptMsgProc); - - /** - * Increment peer's misbehavior score. If the new value surpasses banscore (specified on startup or by default), mark node to be discouraged, meaning the peer might be disconnected & added to the discouragement filter. - */ - void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message = ""); + static std::unique_ptr make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman, + BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, + CTxMemPool& pool, std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); + virtual ~PeerManager() { } /** Get statistics from node state */ - bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats); - - /** Set the best height */ - void SetBestHeight(int height) { m_best_height = height; }; + virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) = 0; /** Whether this node ignores txs received over p2p. */ - bool IgnoresIncomingTxs() { return m_ignore_incoming_txs; }; - - bool IsBanned(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - -private: - /** Get a shared pointer to the Peer object. - * May return an empty shared_ptr if the Peer object can't be found. */ - PeerRef GetPeerRef(NodeId id) const; + virtual bool IgnoresIncomingTxs() = 0; - /** Get a shared pointer to the Peer object and remove it from m_peer_map. - * May return an empty shared_ptr if the Peer object can't be found. */ - PeerRef RemovePeer(NodeId id); + /** Set the best height */ + virtual void SetBestHeight(int height) = 0; /** - * Potentially mark a node discouraged based on the contents of a BlockValidationState object - * - * @param[in] via_compact_block this bool is passed in because net_processing should - * punish peers differently depending on whether the data was provided in a compact - * block message or not. If the compact block had a valid header, but contained invalid - * txs, the peer should not be punished. See BIP 152. - * - * @return Returns true if the peer was punished (probably disconnected) + * Increment peer's misbehavior score. If the new value surpasses banscore (specified on startup or by default), mark node to be discouraged, meaning the peer might be disconnected & added to the discouragement filter. */ - bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, - bool via_compact_block, const std::string& message = ""); + virtual void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message = "") = 0; /** - * Potentially ban a node based on the contents of a TxValidationState object - * - * @return Returns true if the peer was punished (probably disconnected) - * - * Changes here may need to be reflected in TxRelayMayResultInDisconnect(). - */ - bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = ""); - - /** Maybe disconnect a peer and discourage future connections from its address. - * - * @param[in] pnode The node to check. - * @return True if the peer was marked for disconnection in this function + * Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound. + * Public for unit testing. */ - bool MaybeDiscourageAndDisconnect(CNode& pnode); + virtual void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) = 0; - void ProcessOrphanTx(std::set& orphan_work_set) - EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans); - /** Process a single headers message from a peer. */ - void ProcessHeadersMessage(CNode& pfrom, const std::vector& headers, bool via_compact_block); - - void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req); - - /** Send a version message to a peer */ - void PushNodeVersion(CNode& pnode, int64_t nTime); - - const CChainParams& m_chainparams; - CConnman& m_connman; - /** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */ - BanMan* const m_banman; - CAddrMan& m_addrman; - ChainstateManager& m_chainman; - CTxMemPool& m_mempool; - std::unique_ptr& m_llmq_ctx; - - /** The height of the best chain */ - std::atomic m_best_height{-1}; - - int64_t m_stale_tip_check_time; //!< Next time to check for stale tip - - /** Whether this node is running in blocks only mode */ - const bool m_ignore_incoming_txs; + /** Process a single message from a peer. Public for fuzz testing */ + virtual void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, + int64_t nTimeReceived, const std::atomic& interruptMsgProc) = 0; - /** Protects m_peer_map */ - mutable Mutex m_peer_mutex; - /** - * Map of all Peer objects, keyed by peer id. This map is protected - * by the m_peer_mutex. Once a shared pointer reference is - * taken, the lock may be released. Individual fields are protected by - * their own locks. - */ - std::map m_peer_map GUARDED_BY(m_peer_mutex); + virtual bool IsBanned(NodeId pnode) = 0; }; void EraseObjectRequest(NodeId nodeId, const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main); diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index a9325c66ba6d..f80908d83b77 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -79,8 +79,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) { const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -151,8 +151,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) { const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); const Consensus::Params& consensusParams = Params().GetConsensus(); constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS; @@ -225,8 +225,8 @@ BOOST_AUTO_TEST_CASE(DoS_banning) const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -272,8 +272,8 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); banman->ClearBanned(); gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number @@ -317,8 +317,8 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) const CChainParams& chainparams = Params(); auto banman = std::make_unique(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman); - auto peerLogic = std::make_unique(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.scheduler, + *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, false); banman->ClearBanned(); int64_t nStartTime = GetTime(); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index a8506e0d1d22..83496dc8e02e 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -244,9 +244,9 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); - m_node.peerman = std::make_unique(chainparams, *m_node.connman, *m_node.addrman, m_node.banman.get(), - *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, - false); + m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman, m_node.banman.get(), + *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx, + false); { CConnman::Options options; options.m_msgproc = m_node.peerman.get();