From 6cb2344a0090ce805777f5a72817bab0be79e9e6 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 14:17:13 +0700 Subject: [PATCH 01/15] refactor: replace direct call of MetaInfo from rpc/evo code to helper --- src/masternode/meta.cpp | 8 ++++++++ src/masternode/meta.h | 1 + src/rpc/evo.cpp | 3 +-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index dee9c08397dc7..bced7fcfae04a 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -66,6 +66,14 @@ void CMasternodeMetaInfo::RemoveGovernanceObject(const uint256& nGovernanceObjec mapGovernanceObjectsVotedOn.erase(nGovernanceObjectHash); } +CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) +{ + const auto info = GetMetaInfo(proTxHash, false); + if (info == nullptr) return CMasternodeMetaInfo{}; + + return *info; +} + CMasternodeMetaInfoPtr CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash, bool fCreate) { LOCK(cs); diff --git a/src/masternode/meta.h b/src/masternode/meta.h index c74b9afe04c55..59f84ee20e1b3 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -259,6 +259,7 @@ class CMasternodeMetaMan : public MasternodeMetaStore bool IsValid() const { return is_valid; } + CMasternodeMetaInfo GetInfo(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); CMasternodeMetaInfoPtr GetMetaInfo(const uint256& proTxHash, bool fCreate = true) EXCLUSIVE_LOCKS_REQUIRED(!cs); int64_t GetDsqCount() const { return nDsqCount; } diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index 1ddd1cfd9980a..c4afbce2db756 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -1379,8 +1379,7 @@ static UniValue BuildDMNListEntry(const CWallet* const pwallet, const CDetermini } #endif - const auto metaInfo = mn_metaman.GetMetaInfo(dmn.proTxHash); - o.pushKV("metaInfo", metaInfo->ToJson()); + o.pushKV("metaInfo", mn_metaman.GetInfo(dmn.proTxHash).ToJson()); return o; } From 16abbedce82d084a6d53790ced2ab4d2987ed166 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 22:08:31 +0700 Subject: [PATCH 02/15] refactor: replace direct usages of GetMetaInfo while calculating dsq threshold --- src/coinjoin/client.cpp | 17 ++++------------- src/coinjoin/server.cpp | 9 ++------- src/masternode/meta.cpp | 25 ++++++++++++++----------- src/masternode/meta.h | 7 +++++-- 4 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 0af6a36643b9a..b79671e654398 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -124,17 +124,11 @@ MessageProcessingResult CCoinJoinClientQueueManager::ProcessMessage(NodeId from, LogPrint(BCLog::COINJOIN, "DSQUEUE -- CoinJoin queue is ready, masternode=%s, queue=%s\n", dmn->proTxHash.ToString(), dsq.ToString()); return ret; } else { - int64_t nLastDsq = m_mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq(); - int64_t nDsqThreshold = m_mn_metaman.GetDsqThreshold(dmn->proTxHash, tip_mn_list.GetValidMNsCount()); - LogPrint(BCLog::COINJOIN, "DSQUEUE -- nLastDsq: %d nDsqThreshold: %d nDsqCount: %d\n", nLastDsq, - nDsqThreshold, m_mn_metaman.GetDsqCount()); - // don't allow a few nodes to dominate the queuing process - if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) { + if (m_mn_metaman.IsDsqOver(dmn->proTxHash, tip_mn_list.GetValidMNsCount())) { LogPrint(BCLog::COINJOIN, "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString()); return ret; } - m_mn_metaman.AllowMixing(dmn->proTxHash); LogPrint(BCLog::COINJOIN, "DSQUEUE -- new CoinJoin queue, masternode=%s, queue=%s\n", dmn->proTxHash.ToString(), dsq.ToString()); @@ -1180,13 +1174,10 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon continue; } - int64_t nLastDsq = m_mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq(); - int64_t nDsqThreshold = m_mn_metaman.GetDsqThreshold(dmn->proTxHash, nMnCount); - if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) { + if (m_mn_metaman.IsDsqOver(dmn->proTxHash, nMnCount)) { WalletCJLogPrint(m_wallet, /* Continued */ - "CCoinJoinClientSession::StartNewQueue -- too early to mix with node," /* Continued */ - " masternode=%s, nLastDsq=%d, nDsqThreshold=%d, nDsqCount=%d\n", - dmn->proTxHash.ToString(), nLastDsq, nDsqThreshold, m_mn_metaman.GetDsqCount()); + "CCoinJoinClientSession::StartNewQueue -- too early to mix with node masternode=%s\n", + dmn->proTxHash.ToString()); nTries++; continue; } diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index 3beb5641677ab..c666e1df5e22b 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -99,9 +99,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) } } - int64_t nLastDsq = m_mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq(); - int64_t nDsqThreshold = m_mn_metaman.GetDsqThreshold(dmn->proTxHash, mnList.GetValidMNsCount()); - if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) { + if (m_mn_metaman.IsDsqOver(dmn->proTxHash, mnList.GetValidMNsCount())) { if (fLogIPs) { LogPrint(BCLog::COINJOIN, "DSACCEPT -- last dsq too recent, must wait: peer=%d, addr=%s\n", peer.GetId(), peer.addr.ToStringAddrPort()); @@ -194,11 +192,8 @@ MessageProcessingResult CCoinJoinServer::ProcessDSQUEUE(NodeId from, CDataStream } if (!dsq.fReady) { - int64_t nLastDsq = m_mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq(); - int64_t nDsqThreshold = m_mn_metaman.GetDsqThreshold(dmn->proTxHash, tip_mn_list.GetValidMNsCount()); - LogPrint(BCLog::COINJOIN, "DSQUEUE -- nLastDsq: %d nDsqThreshold: %d nDsqCount: %d\n", nLastDsq, nDsqThreshold, m_mn_metaman.GetDsqCount()); //don't allow a few nodes to dominate the queuing process - if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) { + if (m_mn_metaman.IsDsqOver(dmn->proTxHash, tip_mn_list.GetValidMNsCount())) { LogPrint(BCLog::COINJOIN, "DSQUEUE -- node sending too many dsq messages, masternode=%s\n", dmn->proTxHash.ToString()); return ret; } diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index bced7fcfae04a..cde099d475128 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -88,18 +88,21 @@ CMasternodeMetaInfoPtr CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash, return it->second; } -// We keep track of dsq (mixing queues) count to avoid using same masternodes for mixing too often. -// This threshold is calculated as the last dsq count this specific masternode was used in a mixing -// session plus a margin of 20% of masternode count. In other words we expect at least 20% of unique -// masternodes before we ever see a masternode that we know already mixed someone's funds earlier. -int64_t CMasternodeMetaMan::GetDsqThreshold(const uint256& proTxHash, int nMnCount) -{ - auto metaInfo = GetMetaInfo(proTxHash); - if (metaInfo == nullptr) { - // return a threshold which is slightly above nDsqCount i.e. a no-go - return nDsqCount + 1; +bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) const +{ + LOCK(cs); + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) { + LogPrint(BCLog::COINJOIN, "DSQUEUE -- node %s is logged\n", protx_hash.ToString()); + return false; } - return metaInfo->GetLastDsq() + nMnCount / 5; + const auto& meta_info = *it->second; + int64_t last_dsq = meta_info.GetLastDsq(); + int64_t threshold = last_dsq + mn_count / 5; + + LogPrint(BCLog::COINJOIN, "DSQUEUE -- mn: %s last_dsq: %d dsq_threshold: %d nDsqCount: %d\n", + protx_hash.ToString(), last_dsq, threshold, nDsqCount); + return last_dsq != 0 && threshold > nDsqCount; } void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash) diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 59f84ee20e1b3..2ad873e8ef2fe 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -262,8 +262,11 @@ class CMasternodeMetaMan : public MasternodeMetaStore CMasternodeMetaInfo GetInfo(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); CMasternodeMetaInfoPtr GetMetaInfo(const uint256& proTxHash, bool fCreate = true) EXCLUSIVE_LOCKS_REQUIRED(!cs); - int64_t GetDsqCount() const { return nDsqCount; } - int64_t GetDsqThreshold(const uint256& proTxHash, int nMnCount); + // We keep track of dsq (mixing queues) count to avoid using same masternodes for mixing too often. + // MN's threshold is calculated as the last dsq count this specific masternode was used in a mixing + // session plus a margin of 20% of masternode count. In other words we expect at least 20% of unique + // masternodes before we ever see a masternode that we know already mixed someone's funds earlier. + bool IsDsqOver(const uint256& protx_hash, int mn_count) const EXCLUSIVE_LOCKS_REQUIRED(!cs); void AllowMixing(const uint256& proTxHash); void DisallowMixing(const uint256& proTxHash); From 7ec239bf3326bd53d2e1f9d5f8b3d4f1edcdd600 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 22:19:05 +0700 Subject: [PATCH 03/15] refactor: replace direct usages of GetMetaInfo when platform unban node in mn-list --- src/evo/deterministicmns.cpp | 3 +-- src/masternode/meta.cpp | 10 ++++++++++ src/masternode/meta.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index d8140aa0db900..75678cb6c709c 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -676,8 +676,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null(tx); if (!opt_proTx) continue; // should not happen but does not matter - if (auto meta_info = m_mn_metaman.GetMetaInfo(opt_proTx->proTxHash, false); - !meta_info || !meta_info->SetPlatformBan(false, nHeight)) { + if (m_mn_metaman.ResetPlatformBan(opt_proTx->proTxHash, nHeight)) { LogPrint(BCLog::LLMQ, "%s -- MN %s is failed to Platform revived at height %d\n", __func__, opt_proTx->proTxHash.ToString(), nHeight); } diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index cde099d475128..f5aedf3447a1a 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -141,6 +141,16 @@ std::vector CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes( return vecTmp; } +bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height) +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) return false; + + return it->second->SetPlatformBan(false, height); +} + bool CMasternodeMetaMan::AlreadyHavePlatformBan(const uint256& inv_hash) const { LOCK(cs); diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 2ad873e8ef2fe..2f422a2f0b27b 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -276,6 +276,7 @@ class CMasternodeMetaMan : public MasternodeMetaStore std::vector GetAndClearDirtyGovernanceObjectHashes() EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool ResetPlatformBan(const uint256& protx_hash, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs); bool AlreadyHavePlatformBan(const uint256& inv_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); std::optional GetPlatformBan(const uint256& inv_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); void RememberPlatformBan(const uint256& inv_hash, PlatformBanMessage&& msg) EXCLUSIVE_LOCKS_REQUIRED(!cs); From 7ba51ec19f6813c1466edfb92346758ee02cdea0 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 22:26:46 +0700 Subject: [PATCH 04/15] refactor: remove direct usages of GetMetaInfo for dkgsession --- src/llmq/dkgsession.cpp | 5 ++--- src/masternode/meta.cpp | 20 ++++++++++++++++++++ src/masternode/meta.h | 2 ++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/llmq/dkgsession.cpp b/src/llmq/dkgsession.cpp index 062040a819a50..f7c6c4491771d 100644 --- a/src/llmq/dkgsession.cpp +++ b/src/llmq/dkgsession.cpp @@ -492,12 +492,11 @@ void CDKGSession::VerifyConnectionAndMinProtoVersions(CConnman& connman) const m->badConnection = true; logger.Batch("%s does not have min proto version %d (has %d)", m->dmn->proTxHash.ToString(), MIN_MASTERNODE_PROTO_VERSION, it->second); } - const auto meta_info = m_mn_metaman.GetMetaInfo(m->dmn->proTxHash); - if (meta_info->OutboundFailedTooManyTimes()) { + if (m_mn_metaman.OutboundFailedTooManyTimes(m->dmn->proTxHash)) { m->badConnection = true; logger.Batch("%s failed to connect to it too many times", m->dmn->proTxHash.ToString()); } - if (meta_info->IsPlatformBanned()) { + if (m_mn_metaman.IsPlatformBanned(m->dmn->proTxHash)) { m->badConnection = true; logger.Batch("%s is Platform PoSe banned", m->dmn->proTxHash.ToString()); } diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index f5aedf3447a1a..f1149fa3f26e9 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -141,6 +141,26 @@ std::vector CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes( return vecTmp; } +bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) return false; + + return it->second->OutboundFailedTooManyTimes(); +} + +bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) return false; + + return it->second->IsPlatformBanned(); +} + bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height) { LOCK(cs); diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 2f422a2f0b27b..1a4c41f56db0d 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -276,6 +276,8 @@ class CMasternodeMetaMan : public MasternodeMetaStore std::vector GetAndClearDirtyGovernanceObjectHashes() EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool OutboundFailedTooManyTimes(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool IsPlatformBanned(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool ResetPlatformBan(const uint256& protx_hash, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs); bool AlreadyHavePlatformBan(const uint256& inv_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); std::optional GetPlatformBan(const uint256& inv_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); From a40c418ee7afd8ccde5a0628b5c513647ba1d4c6 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 22:32:09 +0700 Subject: [PATCH 05/15] refactor: hide direct calls of GetMetaInfo from llmq/utils --- src/llmq/utils.cpp | 2 +- src/masternode/meta.cpp | 10 ++++++++++ src/masternode/meta.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index 09d2d4fddc7b9..099f5f74c9b98 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -912,7 +912,7 @@ void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman if (dmn->proTxHash == myProTxHash) { continue; } - auto lastOutbound = mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastOutboundSuccess(); + auto lastOutbound = mn_metaman.GetLastOutboundSuccess(dmn->proTxHash); if (curTime - lastOutbound < 10 * 60) { // avoid re-probing nodes too often continue; diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index f1149fa3f26e9..7f687370291d7 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -141,6 +141,16 @@ std::vector CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes( return vecTmp; } +int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) return 0; + + return it->second->GetLastOutboundSuccess(); +} + bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const { LOCK(cs); diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 1a4c41f56db0d..451ec871ba139 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -276,6 +276,7 @@ class CMasternodeMetaMan : public MasternodeMetaStore std::vector GetAndClearDirtyGovernanceObjectHashes() EXCLUSIVE_LOCKS_REQUIRED(!cs); + int64_t GetLastOutboundSuccess(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool OutboundFailedTooManyTimes(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool IsPlatformBanned(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool ResetPlatformBan(const uint256& protx_hash, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs); From b1a03e6a471d341fb52002625e37c60502f58577 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 22:44:45 +0700 Subject: [PATCH 06/15] refactor: hide direct usages of GetMetaInfo from net module --- src/evo/mnauth.cpp | 2 +- src/masternode/meta.cpp | 34 ++++++++++++++++++++++++++++++++++ src/masternode/meta.h | 4 ++++ src/net.cpp | 10 +++++----- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 376c96ecfaf40..4d813ebbbf00f 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -103,7 +103,7 @@ MessageProcessingResult CMNAuth::ProcessMessage(CNode& peer, ServiceFlags node_s } if (!peer.IsInboundConn()) { - mn_metaman.GetMetaInfo(mnauth.proRegTxHash)->SetLastOutboundSuccess(GetTime().count()); + mn_metaman.SetLastOutboundSuccess(mnauth.proRegTxHash, GetTime().count()); if (peer.m_masternode_probe_connection) { LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- Masternode probe successful for %s, disconnecting. peer=%d\n", mnauth.proRegTxHash.ToString(), peer.GetId()); diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 7f687370291d7..fb2dcd437425c 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -141,6 +141,40 @@ std::vector CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes( return vecTmp; } +void CMasternodeMetaMan::SetLastOutboundAttempt(const uint256& protx_hash, int64_t t) +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) { + it = metaInfos.emplace(protx_hash, std::make_shared(protx_hash)).first; + } + + return it->second->SetLastOutboundAttempt(t); +} + +void CMasternodeMetaMan::SetLastOutboundSuccess(const uint256& protx_hash, int64_t t) +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) { + it = metaInfos.emplace(protx_hash, std::make_shared(protx_hash)).first; + } + + return it->second->SetLastOutboundSuccess(t); +} + +int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) const +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) return 0; + + return it->second->GetLastOutboundAttempt(); +} + int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const { LOCK(cs); diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 451ec871ba139..8eef35a85ddeb 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -276,8 +276,12 @@ class CMasternodeMetaMan : public MasternodeMetaStore std::vector GetAndClearDirtyGovernanceObjectHashes() EXCLUSIVE_LOCKS_REQUIRED(!cs); + void SetLastOutboundAttempt(const uint256& protx_hash, int64_t t) EXCLUSIVE_LOCKS_REQUIRED(!cs); + void SetLastOutboundSuccess(const uint256& protx_hash, int64_t t) EXCLUSIVE_LOCKS_REQUIRED(!cs); + int64_t GetLastOutboundAttempt(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); int64_t GetLastOutboundSuccess(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool OutboundFailedTooManyTimes(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool IsPlatformBanned(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool ResetPlatformBan(const uint256& protx_hash, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs); bool AlreadyHavePlatformBan(const uint256& inv_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); diff --git a/src/net.cpp b/src/net.cpp index 7c120ff66833b..f138362cc51f3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3403,7 +3403,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, continue; } // back off connecting to an address if we already tried recently - int64_t last_attempt = mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastOutboundAttempt(); + int64_t last_attempt = mn_metaman.GetLastOutboundAttempt(dmn->proTxHash); if (nANow - last_attempt < chainParams.LLMQConnectionRetryTimeout()) { continue; } @@ -3426,14 +3426,14 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, bool connectedAndOutbound = connectedProRegTxHashes.count(dmn->proTxHash) && !connectedProRegTxHashes[dmn->proTxHash]; if (connectedAndOutbound) { // we already have an outbound connection to this MN so there is no theed to probe it again - mn_metaman.GetMetaInfo(dmn->proTxHash)->SetLastOutboundSuccess(nANow); + mn_metaman.SetLastOutboundSuccess(dmn->proTxHash, nANow); it = masternodePendingProbes.erase(it); continue; } ++it; - int64_t lastAttempt = mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastOutboundAttempt(); + int64_t lastAttempt = mn_metaman.GetLastOutboundAttempt(dmn->proTxHash); // back off trying connecting to an address if we already tried recently if (nANow - lastAttempt < chainParams.LLMQConnectionRetryTimeout()) { continue; @@ -3493,7 +3493,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, didConnect = true; - mn_metaman.GetMetaInfo(connectToDmn->proTxHash)->SetLastOutboundAttempt(nANow); + mn_metaman.SetLastOutboundAttempt(connectToDmn->proTxHash, nANow); OpenMasternodeConnection(CAddress(connectToDmn->pdmnState->netInfo->GetPrimary(), NODE_NETWORK), /*use_v2transport=*/GetLocalServices() & NODE_P2P_V2, isProbe); // should be in the list now if connection was opened @@ -3506,7 +3506,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, if (!connected) { LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->netInfo->GetPrimary().ToStringAddrPort()); // Will take a few consequent failed attempts to PoSe-punish a MN. - if (mn_metaman.GetMetaInfo(connectToDmn->proTxHash)->OutboundFailedTooManyTimes()) { + if (mn_metaman.OutboundFailedTooManyTimes(connectToDmn->proTxHash)) { LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- failed to connect to masternode %s too many times\n", __func__, connectToDmn->proTxHash.ToString()); } } From c0e146f74735bb767f1641622fcda9e7cb15525c Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 23:05:55 +0700 Subject: [PATCH 07/15] refactor: hide direct usages of GetMetaInfo for net_processing --- src/masternode/meta.cpp | 34 ++++++++++++++++++++++++++++------ src/masternode/meta.h | 3 ++- src/net_processing.cpp | 8 +++----- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index fb2dcd437425c..452f79b21c227 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -119,6 +119,16 @@ void CMasternodeMetaMan::DisallowMixing(const uint256& proTxHash) mm->nMixingTxCount++; } +bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const +{ + LOCK(cs); + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) return true; + + return it->second->IsValidForMixingTxes(); +} + bool CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash) { auto mm = GetMetaInfo(proTxHash); @@ -215,6 +225,24 @@ bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height) return it->second->SetPlatformBan(false, height); } +bool CMasternodeMetaMan::SetPlatformBan(const uint256& inv_hash, PlatformBanMessage&& ban_msg) +{ + LOCK(cs); + + const uint256& protx_hash = ban_msg.m_protx_hash; + + auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) { + it = metaInfos.emplace(protx_hash, std::make_shared(protx_hash)).first; + } + + bool ret = it->second->SetPlatformBan(true, ban_msg.m_requested_height); + if (ret) { + m_seen_platform_bans.insert(inv_hash, std::move(ban_msg)); + } + return ret; +} + bool CMasternodeMetaMan::AlreadyHavePlatformBan(const uint256& inv_hash) const { LOCK(cs); @@ -232,12 +260,6 @@ std::optional CMasternodeMetaMan::GetPlatformBan(const uint2 return ret; } -void CMasternodeMetaMan::RememberPlatformBan(const uint256& inv_hash, PlatformBanMessage&& msg) -{ - LOCK(cs); - m_seen_platform_bans.insert(inv_hash, std::move(msg)); -} - void CMasternodeMetaMan::AddUsedMasternode(const uint256& proTxHash) { LOCK(cs); diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 8eef35a85ddeb..64a2f0166680f 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -270,6 +270,7 @@ class CMasternodeMetaMan : public MasternodeMetaStore void AllowMixing(const uint256& proTxHash); void DisallowMixing(const uint256& proTxHash); + bool IsValidForMixingTxes(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash); void RemoveGovernanceObject(const uint256& nGovernanceObjectHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); @@ -284,9 +285,9 @@ class CMasternodeMetaMan : public MasternodeMetaStore bool IsPlatformBanned(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); bool ResetPlatformBan(const uint256& protx_hash, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool SetPlatformBan(const uint256& inv_hash, PlatformBanMessage&& msg) EXCLUSIVE_LOCKS_REQUIRED(!cs); bool AlreadyHavePlatformBan(const uint256& inv_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); std::optional GetPlatformBan(const uint256& inv_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); - void RememberPlatformBan(const uint256& inv_hash, PlatformBanMessage&& msg) EXCLUSIVE_LOCKS_REQUIRED(!cs); // CoinJoin masternode tracking void AddUsedMasternode(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index cc5b427d5ce82..38a45d18478fd 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3471,7 +3471,7 @@ std::pair static ValidateDSTX(CDeterministicMN return {false, true}; } - if (!mn_metaman.GetMetaInfo(dmn->proTxHash)->IsValidForMixingTxes()) { + if (!mn_metaman.IsValidForMixingTxes(dmn->proTxHash)) { LogPrint(BCLog::COINJOIN, "DSTX -- Masternode %s is sending too many transactions %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString()); return {true, true}; // TODO: Not an error? Could it be that someone is relaying old DSTXes @@ -3602,10 +3602,8 @@ MessageProcessingResult PeerManagerImpl::ProcessPlatformBanMessage(NodeId node, } // At this point, the outgoing message serialization version can't change. - const auto meta_info = m_mn_metaman.GetMetaInfo(ban_msg.m_protx_hash); - if (meta_info->SetPlatformBan(true, ban_msg.m_requested_height)) { - LogPrintf("PLATFORMBAN -- forward message to other nodes\n"); - m_mn_metaman.RememberPlatformBan(hash, std::move(ban_msg)); + if (m_mn_metaman.SetPlatformBan(hash, std::move(ban_msg))) { + LogPrintf("PLATFORMBAN -- hash: %s forward message to other nodes\n", hash.ToString()); ret.m_inventory.emplace_back(MSG_PLATFORM_BAN, hash); } return ret; From d5e693fc7af0aa5aa16b140ae7c30612d9d5864e Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 23:14:44 +0700 Subject: [PATCH 08/15] refactor: drop shared_ptr from CMasternodeMetaMan and make GetMetaInfo a private member --- src/masternode/meta.cpp | 62 ++++++++++++++++++++--------------------- src/masternode/meta.h | 17 +++++------ 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 452f79b21c227..9c0f4fb7751ac 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -68,23 +68,20 @@ void CMasternodeMetaInfo::RemoveGovernanceObject(const uint256& nGovernanceObjec CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) { - const auto info = GetMetaInfo(proTxHash, false); - if (info == nullptr) return CMasternodeMetaInfo{}; + LOCK(cs); + auto it = metaInfos.find(proTxHash); + if (it == metaInfos.end()) return CMasternodeMetaInfo{}; - return *info; + return it->second; } -CMasternodeMetaInfoPtr CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash, bool fCreate) +CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash) { - LOCK(cs); auto it = metaInfos.find(proTxHash); if (it != metaInfos.end()) { return it->second; } - if (!fCreate) { - return nullptr; - } - it = metaInfos.emplace(proTxHash, std::make_shared(proTxHash)).first; + it = metaInfos.emplace(proTxHash, CMasternodeMetaInfo{proTxHash}).first; return it->second; } @@ -96,7 +93,7 @@ bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) cons LogPrint(BCLog::COINJOIN, "DSQUEUE -- node %s is logged\n", protx_hash.ToString()); return false; } - const auto& meta_info = *it->second; + const auto& meta_info = it->second; int64_t last_dsq = meta_info.GetLastDsq(); int64_t threshold = last_dsq + mn_count / 5; @@ -107,16 +104,18 @@ bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) cons void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash) { - auto mm = GetMetaInfo(proTxHash); + LOCK(cs); + auto& mm = GetMetaInfo(proTxHash); nDsqCount++; - mm->nLastDsq = nDsqCount.load(); - mm->nMixingTxCount = 0; + mm.nLastDsq = nDsqCount.load(); + mm.nMixingTxCount = 0; } void CMasternodeMetaMan::DisallowMixing(const uint256& proTxHash) { - auto mm = GetMetaInfo(proTxHash); - mm->nMixingTxCount++; + LOCK(cs); + auto& mm = GetMetaInfo(proTxHash); + mm.nMixingTxCount++; } bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const @@ -126,21 +125,22 @@ bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return true; - return it->second->IsValidForMixingTxes(); + return it->second.IsValidForMixingTxes(); } bool CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash) { - auto mm = GetMetaInfo(proTxHash); - mm->AddGovernanceVote(nGovernanceObjectHash); + LOCK(cs); + auto& mm = GetMetaInfo(proTxHash); + mm.AddGovernanceVote(nGovernanceObjectHash); return true; } void CMasternodeMetaMan::RemoveGovernanceObject(const uint256& nGovernanceObjectHash) { LOCK(cs); - for(const auto& p : metaInfos) { - p.second->RemoveGovernanceObject(nGovernanceObjectHash); + for (auto& p : metaInfos) { + p.second.RemoveGovernanceObject(nGovernanceObjectHash); } } @@ -157,10 +157,10 @@ void CMasternodeMetaMan::SetLastOutboundAttempt(const uint256& protx_hash, int64 auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) { - it = metaInfos.emplace(protx_hash, std::make_shared(protx_hash)).first; + it = metaInfos.emplace(protx_hash, CMasternodeMetaInfo{protx_hash}).first; } - return it->second->SetLastOutboundAttempt(t); + return it->second.SetLastOutboundAttempt(t); } void CMasternodeMetaMan::SetLastOutboundSuccess(const uint256& protx_hash, int64_t t) @@ -169,10 +169,10 @@ void CMasternodeMetaMan::SetLastOutboundSuccess(const uint256& protx_hash, int64 auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) { - it = metaInfos.emplace(protx_hash, std::make_shared(protx_hash)).first; + it = metaInfos.emplace(protx_hash, CMasternodeMetaInfo{protx_hash}).first; } - return it->second->SetLastOutboundSuccess(t); + return it->second.SetLastOutboundSuccess(t); } int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) const @@ -182,7 +182,7 @@ int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) co auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return 0; - return it->second->GetLastOutboundAttempt(); + return it->second.GetLastOutboundAttempt(); } int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const @@ -192,7 +192,7 @@ int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) co auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return 0; - return it->second->GetLastOutboundSuccess(); + return it->second.GetLastOutboundSuccess(); } bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const @@ -202,7 +202,7 @@ bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) c auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return false; - return it->second->OutboundFailedTooManyTimes(); + return it->second.OutboundFailedTooManyTimes(); } bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const @@ -212,7 +212,7 @@ bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return false; - return it->second->IsPlatformBanned(); + return it->second.IsPlatformBanned(); } bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height) @@ -222,7 +222,7 @@ bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height) auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return false; - return it->second->SetPlatformBan(false, height); + return it->second.SetPlatformBan(false, height); } bool CMasternodeMetaMan::SetPlatformBan(const uint256& inv_hash, PlatformBanMessage&& ban_msg) @@ -233,10 +233,10 @@ bool CMasternodeMetaMan::SetPlatformBan(const uint256& inv_hash, PlatformBanMess auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) { - it = metaInfos.emplace(protx_hash, std::make_shared(protx_hash)).first; + it = metaInfos.emplace(protx_hash, CMasternodeMetaInfo{protx_hash}).first; } - bool ret = it->second->SetPlatformBan(true, ban_msg.m_requested_height); + bool ret = it->second.SetPlatformBan(true, ban_msg.m_requested_height); if (ret) { m_seen_platform_bans.insert(inv_hash, std::move(ban_msg)); } diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 64a2f0166680f..a0d3fd03e27c0 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -129,7 +128,6 @@ class CMasternodeMetaInfo return m_platform_ban; } }; -using CMasternodeMetaInfoPtr = std::shared_ptr; class MasternodeMetaStore { @@ -137,7 +135,7 @@ class MasternodeMetaStore static const std::string SERIALIZATION_VERSION_STRING; mutable Mutex cs; - std::map metaInfos GUARDED_BY(cs); + std::map metaInfos GUARDED_BY(cs); // keep track of dsq count to prevent masternodes from gaming coinjoin queue std::atomic nDsqCount{0}; // keep track of the used Masternodes for CoinJoin across all wallets @@ -152,7 +150,7 @@ class MasternodeMetaStore LOCK(cs); std::vector tmpMetaInfo; for (const auto& p : metaInfos) { - tmpMetaInfo.emplace_back(*p.second); + tmpMetaInfo.emplace_back(p.second); } // Convert deque to vector for serialization - unordered_set will be rebuilt on deserialization std::vector tmpUsedMasternodes(m_used_masternodes.begin(), m_used_masternodes.end()); @@ -162,9 +160,9 @@ class MasternodeMetaStore template void Unserialize(Stream &s) EXCLUSIVE_LOCKS_REQUIRED(!cs) { - Clear(); - LOCK(cs); + + metaInfos.clear(); std::string strVersion; s >> strVersion; if (strVersion != SERIALIZATION_VERSION_STRING) { @@ -173,10 +171,8 @@ class MasternodeMetaStore std::vector tmpMetaInfo; std::vector tmpUsedMasternodes; s >> tmpMetaInfo >> nDsqCount >> tmpUsedMasternodes; - - metaInfos.clear(); for (auto& mm : tmpMetaInfo) { - metaInfos.emplace(mm.GetProTxHash(), std::make_shared(std::move(mm))); + metaInfos.emplace(mm.GetProTxHash(), CMasternodeMetaInfo{std::move(mm)}); } // Convert vector to deque and build unordered_set for O(1) lookups @@ -249,6 +245,8 @@ class CMasternodeMetaMan : public MasternodeMetaStore mutable unordered_lru_cache m_seen_platform_bans GUARDED_BY(cs){ SeenBanInventorySize}; + CMasternodeMetaInfo& GetMetaInfo(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(cs); + public: CMasternodeMetaMan(const CMasternodeMetaMan&) = delete; CMasternodeMetaMan& operator=(const CMasternodeMetaMan&) = delete; @@ -260,7 +258,6 @@ class CMasternodeMetaMan : public MasternodeMetaStore bool IsValid() const { return is_valid; } CMasternodeMetaInfo GetInfo(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); - CMasternodeMetaInfoPtr GetMetaInfo(const uint256& proTxHash, bool fCreate = true) EXCLUSIVE_LOCKS_REQUIRED(!cs); // We keep track of dsq (mixing queues) count to avoid using same masternodes for mixing too often. // MN's threshold is calculated as the last dsq count this specific masternode was used in a mixing From 1bfd6ffc11deb636a64eb638130e3b5bb1bfc062 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 23:28:47 +0700 Subject: [PATCH 09/15] refactor: drop mutex and atomics from CMasternodeMetaInfo It is already guarded by CMasternodeMetaMan::cs --- src/masternode/meta.cpp | 27 ++++++++------------ src/masternode/meta.h | 56 +++++++++++------------------------------ 2 files changed, 25 insertions(+), 58 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 9c0f4fb7751ac..2e32d79a47d14 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -30,29 +30,24 @@ bool CMasternodeMetaMan::LoadCache(bool load_cache) UniValue CMasternodeMetaInfo::ToJson() const { - UniValue ret(UniValue::VOBJ); - int64_t now = GetTime().count(); - ret.pushKV("lastDSQ", nLastDsq.load()); - ret.pushKV("mixingTxCount", nMixingTxCount.load()); - ret.pushKV("outboundAttemptCount", outboundAttemptCount.load()); - ret.pushKV("lastOutboundAttempt", lastOutboundAttempt.load()); - ret.pushKV("lastOutboundAttemptElapsed", now - lastOutboundAttempt.load()); - ret.pushKV("lastOutboundSuccess", lastOutboundSuccess.load()); - ret.pushKV("lastOutboundSuccessElapsed", now - lastOutboundSuccess.load()); - { - LOCK(cs); - ret.pushKV("is_platform_banned", m_platform_ban); - ret.pushKV("platform_ban_height_updated", m_platform_ban_updated); - } + UniValue ret(UniValue::VOBJ); + ret.pushKV("lastDSQ", nLastDsq); + ret.pushKV("mixingTxCount", nMixingTxCount); + ret.pushKV("outboundAttemptCount", outboundAttemptCount); + ret.pushKV("lastOutboundAttempt", lastOutboundAttempt); + ret.pushKV("lastOutboundAttemptElapsed", now - lastOutboundAttempt); + ret.pushKV("lastOutboundSuccess", lastOutboundSuccess); + ret.pushKV("lastOutboundSuccessElapsed", now - lastOutboundSuccess); + ret.pushKV("is_platform_banned", m_platform_ban); + ret.pushKV("platform_ban_height_updated", m_platform_ban_updated); return ret; } void CMasternodeMetaInfo::AddGovernanceVote(const uint256& nGovernanceObjectHash) { - LOCK(cs); // Insert a zero value, or not. Then increment the value regardless. This // ensures the value is in the map. const auto& pair = mapGovernanceObjectsVotedOn.emplace(nGovernanceObjectHash, 0); @@ -61,14 +56,12 @@ void CMasternodeMetaInfo::AddGovernanceVote(const uint256& nGovernanceObjectHash void CMasternodeMetaInfo::RemoveGovernanceObject(const uint256& nGovernanceObjectHash) { - LOCK(cs); // Whether or not the govobj hash exists in the map first is irrelevant. mapGovernanceObjectsVotedOn.erase(nGovernanceObjectHash); } CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) { - LOCK(cs); auto it = metaInfos.find(proTxHash); if (it == metaInfos.end()) return CMasternodeMetaInfo{}; diff --git a/src/masternode/meta.h b/src/masternode/meta.h index a0d3fd03e27c0..81662b1d1e5bd 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -32,58 +32,35 @@ static constexpr int MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS{5}; // This is mostly local information, e.g. about mixing and governance class CMasternodeMetaInfo { - friend class CMasternodeMetaMan; - -private: - mutable Mutex cs; - - uint256 proTxHash GUARDED_BY(cs); +public: + uint256 proTxHash; //the dsq count from the last dsq broadcast of this node - std::atomic nLastDsq{0}; - std::atomic nMixingTxCount{0}; + int64_t nLastDsq{0}; + int nMixingTxCount{0}; // KEEP TRACK OF GOVERNANCE ITEMS EACH MASTERNODE HAS VOTE UPON FOR RECALCULATION - std::map mapGovernanceObjectsVotedOn GUARDED_BY(cs); + std::map mapGovernanceObjectsVotedOn; - std::atomic outboundAttemptCount{0}; - std::atomic lastOutboundAttempt{0}; - std::atomic lastOutboundSuccess{0}; + int outboundAttemptCount{0}; + int64_t lastOutboundAttempt{0}; + int64_t lastOutboundSuccess{0}; //! bool flag is node currently under platform ban by p2p message - bool m_platform_ban GUARDED_BY(cs){false}; + bool m_platform_ban{false}; //! height at which platform ban has been applied or removed - int m_platform_ban_updated GUARDED_BY(cs){0}; + int m_platform_ban_updated{0}; public: CMasternodeMetaInfo() = default; explicit CMasternodeMetaInfo(const uint256& _proTxHash) : proTxHash(_proTxHash) {} - CMasternodeMetaInfo(const CMasternodeMetaInfo& ref) : - proTxHash(ref.proTxHash), - nLastDsq(ref.nLastDsq.load()), - nMixingTxCount(ref.nMixingTxCount.load()), - mapGovernanceObjectsVotedOn(ref.mapGovernanceObjectsVotedOn), - lastOutboundAttempt(ref.lastOutboundAttempt.load()), - lastOutboundSuccess(ref.lastOutboundSuccess.load()), - m_platform_ban(ref.m_platform_ban), - m_platform_ban_updated(ref.m_platform_ban_updated) - { - } + CMasternodeMetaInfo(const CMasternodeMetaInfo& ref) = default; - template - void Serialize(Stream& s) const EXCLUSIVE_LOCKS_REQUIRED(!cs) + SERIALIZE_METHODS(CMasternodeMetaInfo, obj) { - LOCK(cs); - s << proTxHash << nLastDsq << nMixingTxCount << mapGovernanceObjectsVotedOn << outboundAttemptCount - << lastOutboundAttempt << lastOutboundSuccess << m_platform_ban << m_platform_ban_updated; - } - - template - void Unserialize(Stream& s) EXCLUSIVE_LOCKS_REQUIRED(!cs) - { - LOCK(cs); - s >> proTxHash >> nLastDsq >> nMixingTxCount >> mapGovernanceObjectsVotedOn >> outboundAttemptCount >> - lastOutboundAttempt >> lastOutboundSuccess >> m_platform_ban >> m_platform_ban_updated; + READWRITE(obj.proTxHash, obj.nLastDsq, obj.nMixingTxCount, obj.mapGovernanceObjectsVotedOn, + obj.outboundAttemptCount, obj.lastOutboundAttempt, obj.lastOutboundSuccess, obj.m_platform_ban, + obj.m_platform_ban_updated); } UniValue ToJson() const EXCLUSIVE_LOCKS_REQUIRED(!cs); @@ -91,7 +68,6 @@ class CMasternodeMetaInfo public: const uint256 GetProTxHash() const EXCLUSIVE_LOCKS_REQUIRED(!cs) { - LOCK(cs); return proTxHash; } int64_t GetLastDsq() const { return nLastDsq; } @@ -111,7 +87,6 @@ class CMasternodeMetaInfo int64_t GetLastOutboundSuccess() const { return lastOutboundSuccess; } bool SetPlatformBan(bool is_banned, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs) { - LOCK(cs); if (height < m_platform_ban_updated) { return false; } @@ -124,7 +99,6 @@ class CMasternodeMetaInfo } bool IsPlatformBanned() const EXCLUSIVE_LOCKS_REQUIRED(!cs) { - LOCK(cs); return m_platform_ban; } }; From 69ed5f5293dd16df5a255d02e189d5c35f0cd0c0 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 11 Oct 2025 23:50:36 +0700 Subject: [PATCH 10/15] refactor: remove useless helpers of CMasternodeMetaInfo --- src/masternode/meta.cpp | 25 ++++++++++++++----------- src/masternode/meta.h | 34 +++++++++------------------------- 2 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 2e32d79a47d14..c7d802a0851ac 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -10,6 +10,9 @@ const std::string MasternodeMetaStore::SERIALIZATION_VERSION_STRING = "CMasternodeMetaMan-Version-5"; +static constexpr int MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS{5}; +static constexpr int MASTERNODE_MAX_MIXING_TXES{5}; + CMasternodeMetaMan::CMasternodeMetaMan() : m_db{std::make_unique("mncache.dat", "magicMasternodeCache")} { @@ -33,8 +36,8 @@ UniValue CMasternodeMetaInfo::ToJson() const int64_t now = GetTime().count(); UniValue ret(UniValue::VOBJ); - ret.pushKV("lastDSQ", nLastDsq); - ret.pushKV("mixingTxCount", nMixingTxCount); + ret.pushKV("lastDSQ", m_last_dsq); + ret.pushKV("mixingTxCount", m_mixing_tx_count); ret.pushKV("outboundAttemptCount", outboundAttemptCount); ret.pushKV("lastOutboundAttempt", lastOutboundAttempt); ret.pushKV("lastOutboundAttemptElapsed", now - lastOutboundAttempt); @@ -87,7 +90,7 @@ bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) cons return false; } const auto& meta_info = it->second; - int64_t last_dsq = meta_info.GetLastDsq(); + int64_t last_dsq = meta_info.m_last_dsq; int64_t threshold = last_dsq + mn_count / 5; LogPrint(BCLog::COINJOIN, "DSQUEUE -- mn: %s last_dsq: %d dsq_threshold: %d nDsqCount: %d\n", @@ -100,15 +103,15 @@ void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash) LOCK(cs); auto& mm = GetMetaInfo(proTxHash); nDsqCount++; - mm.nLastDsq = nDsqCount.load(); - mm.nMixingTxCount = 0; + mm.m_last_dsq = nDsqCount.load(); + mm.m_mixing_tx_count = 0; } void CMasternodeMetaMan::DisallowMixing(const uint256& proTxHash) { LOCK(cs); auto& mm = GetMetaInfo(proTxHash); - mm.nMixingTxCount++; + mm.m_mixing_tx_count++; } bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const @@ -118,7 +121,7 @@ bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return true; - return it->second.IsValidForMixingTxes(); + return it->second.m_mixing_tx_count <= MASTERNODE_MAX_MIXING_TXES; } bool CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash) @@ -175,7 +178,7 @@ int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) co auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return 0; - return it->second.GetLastOutboundAttempt(); + return it->second.lastOutboundAttempt; } int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const @@ -185,7 +188,7 @@ int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) co auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return 0; - return it->second.GetLastOutboundSuccess(); + return it->second.lastOutboundSuccess; } bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const @@ -195,7 +198,7 @@ bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) c auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return false; - return it->second.OutboundFailedTooManyTimes(); + return it->second.outboundAttemptCount > MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS; } bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const @@ -205,7 +208,7 @@ bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const auto it = metaInfos.find(protx_hash); if (it == metaInfos.end()) return false; - return it->second.IsPlatformBanned(); + return it->second.m_platform_ban; } bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height) diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 81662b1d1e5bd..838e6cd218e36 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -25,19 +25,16 @@ class UniValue; template class CFlatDB; -static constexpr int MASTERNODE_MAX_MIXING_TXES{5}; -static constexpr int MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS{5}; - // Holds extra (non-deterministic) information about masternodes // This is mostly local information, e.g. about mixing and governance class CMasternodeMetaInfo { public: - uint256 proTxHash; + uint256 m_protx_hash; //the dsq count from the last dsq broadcast of this node - int64_t nLastDsq{0}; - int nMixingTxCount{0}; + int64_t m_last_dsq{0}; + int m_mixing_tx_count{0}; // KEEP TRACK OF GOVERNANCE ITEMS EACH MASTERNODE HAS VOTE UPON FOR RECALCULATION std::map mapGovernanceObjectsVotedOn; @@ -53,12 +50,15 @@ class CMasternodeMetaInfo public: CMasternodeMetaInfo() = default; - explicit CMasternodeMetaInfo(const uint256& _proTxHash) : proTxHash(_proTxHash) {} + explicit CMasternodeMetaInfo(const uint256& protx_hash) : + m_protx_hash(protx_hash) + { + } CMasternodeMetaInfo(const CMasternodeMetaInfo& ref) = default; SERIALIZE_METHODS(CMasternodeMetaInfo, obj) { - READWRITE(obj.proTxHash, obj.nLastDsq, obj.nMixingTxCount, obj.mapGovernanceObjectsVotedOn, + READWRITE(obj.m_protx_hash, obj.m_last_dsq, obj.m_mixing_tx_count, obj.mapGovernanceObjectsVotedOn, obj.outboundAttemptCount, obj.lastOutboundAttempt, obj.lastOutboundSuccess, obj.m_platform_ban, obj.m_platform_ban_updated); } @@ -66,25 +66,13 @@ class CMasternodeMetaInfo UniValue ToJson() const EXCLUSIVE_LOCKS_REQUIRED(!cs); public: - const uint256 GetProTxHash() const EXCLUSIVE_LOCKS_REQUIRED(!cs) - { - return proTxHash; - } - int64_t GetLastDsq() const { return nLastDsq; } - int GetMixingTxCount() const { return nMixingTxCount; } - - bool IsValidForMixingTxes() const { return GetMixingTxCount() <= MASTERNODE_MAX_MIXING_TXES; } - // KEEP TRACK OF EACH GOVERNANCE ITEM IN CASE THIS NODE GOES OFFLINE, SO WE CAN RECALCULATE THEIR STATUS void AddGovernanceVote(const uint256& nGovernanceObjectHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); void RemoveGovernanceObject(const uint256& nGovernanceObjectHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); - bool OutboundFailedTooManyTimes() const { return outboundAttemptCount > MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS; } void SetLastOutboundAttempt(int64_t t) { lastOutboundAttempt = t; ++outboundAttemptCount; } - int64_t GetLastOutboundAttempt() const { return lastOutboundAttempt; } void SetLastOutboundSuccess(int64_t t) { lastOutboundSuccess = t; outboundAttemptCount = 0; } - int64_t GetLastOutboundSuccess() const { return lastOutboundSuccess; } bool SetPlatformBan(bool is_banned, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs) { if (height < m_platform_ban_updated) { @@ -97,10 +85,6 @@ class CMasternodeMetaInfo m_platform_ban_updated = height; return true; } - bool IsPlatformBanned() const EXCLUSIVE_LOCKS_REQUIRED(!cs) - { - return m_platform_ban; - } }; class MasternodeMetaStore @@ -146,7 +130,7 @@ class MasternodeMetaStore std::vector tmpUsedMasternodes; s >> tmpMetaInfo >> nDsqCount >> tmpUsedMasternodes; for (auto& mm : tmpMetaInfo) { - metaInfos.emplace(mm.GetProTxHash(), CMasternodeMetaInfo{std::move(mm)}); + metaInfos.emplace(mm.m_protx_hash, CMasternodeMetaInfo{std::move(mm)}); } // Convert vector to deque and build unordered_set for O(1) lookups From b79dd900a9f739ef13eb16ccc0afb8d90945f7fd Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 12 Oct 2025 00:00:32 +0700 Subject: [PATCH 11/15] refactor: use a helper GetMetaInfo and GetMetaInfoOrDefault internally --- src/masternode/meta.cpp | 34 ++++++++++++---------------------- src/masternode/meta.h | 1 + 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index c7d802a0851ac..c6dcc9b42de94 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -13,6 +13,10 @@ const std::string MasternodeMetaStore::SERIALIZATION_VERSION_STRING = "CMasterno static constexpr int MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS{5}; static constexpr int MASTERNODE_MAX_MIXING_TXES{5}; +namespace { +static const CMasternodeMetaInfo default_meta_info_meta_info{}; +} // anonymous namespace + CMasternodeMetaMan::CMasternodeMetaMan() : m_db{std::make_unique("mncache.dat", "magicMasternodeCache")} { @@ -63,14 +67,15 @@ void CMasternodeMetaInfo::RemoveGovernanceObject(const uint256& nGovernanceObjec mapGovernanceObjectsVotedOn.erase(nGovernanceObjectHash); } -CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) +const CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfoOrDefault(const uint256& protx_hash) const { - auto it = metaInfos.find(proTxHash); - if (it == metaInfos.end()) return CMasternodeMetaInfo{}; - + const auto it = metaInfos.find(protx_hash); + if (it == metaInfos.end()) return default_meta_info_meta_info; return it->second; } +CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) { return GetMetaInfoOrDefault(proTxHash); } + CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash) { auto it = metaInfos.find(proTxHash); @@ -151,24 +156,14 @@ void CMasternodeMetaMan::SetLastOutboundAttempt(const uint256& protx_hash, int64 { LOCK(cs); - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) { - it = metaInfos.emplace(protx_hash, CMasternodeMetaInfo{protx_hash}).first; - } - - return it->second.SetLastOutboundAttempt(t); + GetMetaInfo(protx_hash).SetLastOutboundAttempt(t); } void CMasternodeMetaMan::SetLastOutboundSuccess(const uint256& protx_hash, int64_t t) { LOCK(cs); - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) { - it = metaInfos.emplace(protx_hash, CMasternodeMetaInfo{protx_hash}).first; - } - - return it->second.SetLastOutboundSuccess(t); + GetMetaInfo(protx_hash).SetLastOutboundSuccess(t); } int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) const @@ -227,12 +222,7 @@ bool CMasternodeMetaMan::SetPlatformBan(const uint256& inv_hash, PlatformBanMess const uint256& protx_hash = ban_msg.m_protx_hash; - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) { - it = metaInfos.emplace(protx_hash, CMasternodeMetaInfo{protx_hash}).first; - } - - bool ret = it->second.SetPlatformBan(true, ban_msg.m_requested_height); + bool ret = GetMetaInfo(protx_hash).SetPlatformBan(true, ban_msg.m_requested_height); if (ret) { m_seen_platform_bans.insert(inv_hash, std::move(ban_msg)); } diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 838e6cd218e36..82d318d11b27b 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -204,6 +204,7 @@ class CMasternodeMetaMan : public MasternodeMetaStore SeenBanInventorySize}; CMasternodeMetaInfo& GetMetaInfo(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(cs); + const CMasternodeMetaInfo& GetMetaInfoOrDefault(const uint256& proTxHash) const EXCLUSIVE_LOCKS_REQUIRED(cs); public: CMasternodeMetaMan(const CMasternodeMetaMan&) = delete; From ed27d90f61bb9bd93f0913227858908f6385abd9 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 12 Oct 2025 00:06:03 +0700 Subject: [PATCH 12/15] refactor: use GetMetaInfoOrDefault widely, final --- src/masternode/meta.cpp | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index c6dcc9b42de94..3b478327a1cca 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -105,9 +105,10 @@ bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) cons void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash) { + nDsqCount++; + LOCK(cs); auto& mm = GetMetaInfo(proTxHash); - nDsqCount++; mm.m_last_dsq = nDsqCount.load(); mm.m_mixing_tx_count = 0; } @@ -115,25 +116,19 @@ void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash) void CMasternodeMetaMan::DisallowMixing(const uint256& proTxHash) { LOCK(cs); - auto& mm = GetMetaInfo(proTxHash); - mm.m_mixing_tx_count++; + GetMetaInfo(proTxHash).m_mixing_tx_count++; } bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const { LOCK(cs); - - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) return true; - - return it->second.m_mixing_tx_count <= MASTERNODE_MAX_MIXING_TXES; + return GetMetaInfoOrDefault(protx_hash).m_mixing_tx_count <= MASTERNODE_MAX_MIXING_TXES; } bool CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash) { LOCK(cs); - auto& mm = GetMetaInfo(proTxHash); - mm.AddGovernanceVote(nGovernanceObjectHash); + GetMetaInfo(proTxHash).AddGovernanceVote(nGovernanceObjectHash); return true; } @@ -155,55 +150,37 @@ std::vector CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes( void CMasternodeMetaMan::SetLastOutboundAttempt(const uint256& protx_hash, int64_t t) { LOCK(cs); - GetMetaInfo(protx_hash).SetLastOutboundAttempt(t); } void CMasternodeMetaMan::SetLastOutboundSuccess(const uint256& protx_hash, int64_t t) { LOCK(cs); - GetMetaInfo(protx_hash).SetLastOutboundSuccess(t); } int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) const { LOCK(cs); - - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) return 0; - - return it->second.lastOutboundAttempt; + return GetMetaInfoOrDefault(protx_hash).lastOutboundAttempt; } int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const { LOCK(cs); - - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) return 0; - - return it->second.lastOutboundSuccess; + return GetMetaInfoOrDefault(protx_hash).lastOutboundSuccess; } bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const { LOCK(cs); - - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) return false; - - return it->second.outboundAttemptCount > MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS; + return GetMetaInfoOrDefault(protx_hash).outboundAttemptCount > MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS; } bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const { LOCK(cs); - - auto it = metaInfos.find(protx_hash); - if (it == metaInfos.end()) return false; - - return it->second.m_platform_ban; + return GetMetaInfoOrDefault(protx_hash).m_platform_ban; } bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height) From 04ab976f70c74908ed5e0db1c2b5e3d21634f673 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 12 Oct 2025 00:11:16 +0700 Subject: [PATCH 13/15] refactor: remove unused CConnMan from meta.h --- src/masternode/meta.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 82d318d11b27b..788b310af2fee 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -19,7 +19,6 @@ #include #include -class CConnman; class UniValue; template From 969b84131dffc041381d2ebf6575395620851235 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 12 Oct 2025 00:17:55 +0700 Subject: [PATCH 14/15] refactor: drop return bool from AddGovernanceVote which is always true --- src/governance/object.cpp | 9 +-------- src/masternode/meta.cpp | 3 +-- src/masternode/meta.h | 2 +- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/governance/object.cpp b/src/governance/object.cpp index cc961d4d4d816..01b9135d34c6a 100644 --- a/src/governance/object.cpp +++ b/src/governance/object.cpp @@ -147,14 +147,7 @@ bool CGovernanceObject::ProcessVote(CMasternodeMetaMan& mn_metaman, CGovernanceM return false; } - if (!mn_metaman.AddGovernanceVote(dmn->proTxHash, vote.GetParentHash())) { - std::string msg{strprintf("CGovernanceObject::%s -- Unable to add governance vote, MN outpoint = %s, " - "governance object hash = %s", - __func__, vote.GetMasternodeOutpoint().ToStringShort(), GetHash().ToString())}; - LogPrint(BCLog::GOBJECT, "%s\n", msg); - exception = CGovernanceException(msg, GOVERNANCE_EXCEPTION_PERMANENT_ERROR); - return false; - } + mn_metaman.AddGovernanceVote(dmn->proTxHash, vote.GetParentHash()); voteInstanceRef = vote_instance_t(vote.GetOutcome(), nVoteTimeUpdate, vote.GetTimestamp()); fileVotes.AddVote(vote); diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 3b478327a1cca..954e45ea397ca 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -125,11 +125,10 @@ bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const return GetMetaInfoOrDefault(protx_hash).m_mixing_tx_count <= MASTERNODE_MAX_MIXING_TXES; } -bool CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash) +void CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash) { LOCK(cs); GetMetaInfo(proTxHash).AddGovernanceVote(nGovernanceObjectHash); - return true; } void CMasternodeMetaMan::RemoveGovernanceObject(const uint256& nGovernanceObjectHash) diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 788b310af2fee..22bceec51bba5 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -227,7 +227,7 @@ class CMasternodeMetaMan : public MasternodeMetaStore void DisallowMixing(const uint256& proTxHash); bool IsValidForMixingTxes(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); - bool AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash); + void AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash); void RemoveGovernanceObject(const uint256& nGovernanceObjectHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); std::vector GetAndClearDirtyGovernanceObjectHashes() EXCLUSIVE_LOCKS_REQUIRED(!cs); From fe3966d7edaf039a990ad35ca95b76c501bbc1de Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 16 Oct 2025 01:42:23 +0700 Subject: [PATCH 15/15] fix: removed leftover annotation, as follow-up conflict resolving with #6880 --- src/masternode/meta.cpp | 6 +++++- src/masternode/meta.h | 19 +++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 954e45ea397ca..fa69d53eebd4d 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -74,7 +74,11 @@ const CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfoOrDefault(const uint25 return it->second; } -CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) { return GetMetaInfoOrDefault(proTxHash); } +CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) const +{ + LOCK(cs); + return GetMetaInfoOrDefault(proTxHash); +} CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash) { diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 22bceec51bba5..ac031da492514 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -31,7 +31,7 @@ class CMasternodeMetaInfo public: uint256 m_protx_hash; - //the dsq count from the last dsq broadcast of this node + //! the dsq count from the last dsq broadcast of this node int64_t m_last_dsq{0}; int m_mixing_tx_count{0}; @@ -62,17 +62,16 @@ class CMasternodeMetaInfo obj.m_platform_ban_updated); } - UniValue ToJson() const EXCLUSIVE_LOCKS_REQUIRED(!cs); + UniValue ToJson() const; -public: // KEEP TRACK OF EACH GOVERNANCE ITEM IN CASE THIS NODE GOES OFFLINE, SO WE CAN RECALCULATE THEIR STATUS - void AddGovernanceVote(const uint256& nGovernanceObjectHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); - - void RemoveGovernanceObject(const uint256& nGovernanceObjectHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); + void AddGovernanceVote(const uint256& nGovernanceObjectHash); + void RemoveGovernanceObject(const uint256& nGovernanceObjectHash); void SetLastOutboundAttempt(int64_t t) { lastOutboundAttempt = t; ++outboundAttemptCount; } void SetLastOutboundSuccess(int64_t t) { lastOutboundSuccess = t; outboundAttemptCount = 0; } - bool SetPlatformBan(bool is_banned, int height) EXCLUSIVE_LOCKS_REQUIRED(!cs) + + bool SetPlatformBan(bool is_banned, int height) { if (height < m_platform_ban_updated) { return false; @@ -215,7 +214,7 @@ class CMasternodeMetaMan : public MasternodeMetaStore bool IsValid() const { return is_valid; } - CMasternodeMetaInfo GetInfo(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); + CMasternodeMetaInfo GetInfo(const uint256& proTxHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); // We keep track of dsq (mixing queues) count to avoid using same masternodes for mixing too often. // MN's threshold is calculated as the last dsq count this specific masternode was used in a mixing @@ -223,8 +222,8 @@ class CMasternodeMetaMan : public MasternodeMetaStore // masternodes before we ever see a masternode that we know already mixed someone's funds earlier. bool IsDsqOver(const uint256& protx_hash, int mn_count) const EXCLUSIVE_LOCKS_REQUIRED(!cs); - void AllowMixing(const uint256& proTxHash); - void DisallowMixing(const uint256& proTxHash); + void AllowMixing(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); + void DisallowMixing(const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(!cs); bool IsValidForMixingTxes(const uint256& protx_hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs); void AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash);