From 17e0ffa8cabf05d5971d205aa091febd3d9b031e 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 adb2aaa302593..3000b73d81b7c 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 217b9d800287d..5b76d5163039d 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -241,6 +241,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 3e0dcc6416368..e5e921d70c85c 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 47044edd968e1ee5c6e731df213923ec985e71f8 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 c08a647cac7ee..23c1789d80ba9 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -116,17 +116,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()); @@ -1169,13 +1163,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 70c5b4772109f..87cb7a46b06ed 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -78,9 +78,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()); @@ -173,11 +171,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 3000b73d81b7c..f258e9c7229f2 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 5b76d5163039d..4d75f9c50cff0 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -244,8 +244,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 80e47c2db65c62620518b0a8bc5209f98e59512a 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 edd30d189b285..54b531dfb10ad 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -668,8 +668,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 f258e9c7229f2..349981bd30724 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 4d75f9c50cff0..ad83ca78cc89e 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -258,6 +258,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 97adcccf39850fee860f4accb6b9edd6f97b0532 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 349981bd30724..9cb0bd57e5343 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 ad83ca78cc89e..dcd4ef650be32 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -258,6 +258,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 39ac748156c6d205fe16f69e965435a196ebac56 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 9cb0bd57e5343..5c3bb5ba3d82c 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 dcd4ef650be32..a30c37de4049a 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -258,6 +258,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 280b5438d55f3a835336c58a9715047fe74363b7 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 5c3bb5ba3d82c..5a17077a84a35 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 a30c37de4049a..1ef1d3816ab76 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -258,8 +258,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 ea96b1162a403..4f51ec2cada14 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3442,7 +3442,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, continue; } if (!connectedNodes.count(addr2) && !IsMasternodeOrDisconnectRequested(addr2) && !connectedProRegTxHashes.count(proRegTxHash)) { - 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; @@ -3466,14 +3466,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; @@ -3524,7 +3524,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 @@ -3537,7 +3537,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 2251670f5fa25ff19a2957dae394507c9f59262e 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 5a17077a84a35..8c73512a8c8be 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)); -} - std::string MasternodeMetaStore::ToString() const { LOCK(cs); diff --git a/src/masternode/meta.h b/src/masternode/meta.h index 1ef1d3816ab76..a888b42f3bcd1 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -252,6 +252,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); @@ -266,9 +267,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); }; #endif // BITCOIN_MASTERNODE_META_H diff --git a/src/net_processing.cpp b/src/net_processing.cpp index bee912118e31a..3d49a5c463a46 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3477,7 +3477,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 @@ -3605,10 +3605,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 6ec1e3c0fa1ac3c8dfa81ad33a72e5ea5d51738e 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 | 16 +++++------ 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 8c73512a8c8be..80d06930a78b2 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 a888b42f3bcd1..22475e93656c3 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -15,7 +15,6 @@ #include #include -#include #include #include @@ -128,7 +127,6 @@ class CMasternodeMetaInfo return m_platform_ban; } }; -using CMasternodeMetaInfoPtr = std::shared_ptr; class MasternodeMetaStore { @@ -136,7 +134,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}; @@ -147,7 +145,7 @@ class MasternodeMetaStore LOCK(cs); std::vector tmpMetaInfo; for (const auto& p : metaInfos) { - tmpMetaInfo.emplace_back(*p.second); + tmpMetaInfo.emplace_back(p.second); } s << SERIALIZATION_VERSION_STRING << tmpMetaInfo << nDsqCount; } @@ -155,9 +153,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) { @@ -165,9 +163,8 @@ class MasternodeMetaStore } std::vector tmpMetaInfo; s >> tmpMetaInfo >> nDsqCount; - metaInfos.clear(); for (auto& mm : tmpMetaInfo) { - metaInfos.emplace(mm.GetProTxHash(), std::make_shared(std::move(mm))); + metaInfos.emplace(mm.GetProTxHash(), CMasternodeMetaInfo{std::move(mm)}); } } @@ -233,6 +230,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: explicit CMasternodeMetaMan(); ~CMasternodeMetaMan(); @@ -242,7 +241,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 249c1a296049382b40a59278272e56ac00a5a936 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 | 57 +++++++++++------------------------------ 2 files changed, 25 insertions(+), 59 deletions(-) diff --git a/src/masternode/meta.cpp b/src/masternode/meta.cpp index 80d06930a78b2..288ebcb7bf900 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -30,29 +30,24 @@ CMasternodeMetaMan::~CMasternodeMetaMan() 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 22475e93656c3..55a4dd02a7fc8 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -31,58 +30,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); @@ -90,7 +66,6 @@ class CMasternodeMetaInfo public: const uint256 GetProTxHash() const EXCLUSIVE_LOCKS_REQUIRED(!cs) { - LOCK(cs); return proTxHash; } int64_t GetLastDsq() const { return nLastDsq; } @@ -110,7 +85,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; } @@ -123,7 +97,6 @@ class CMasternodeMetaInfo } bool IsPlatformBanned() const EXCLUSIVE_LOCKS_REQUIRED(!cs) { - LOCK(cs); return m_platform_ban; } }; From d1b4654720dd577e7754ed0bb7fb3ed3596cdb84 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 288ebcb7bf900..0b69085ddac3b 100644 --- a/src/masternode/meta.cpp +++ b/src/masternode/meta.cpp @@ -10,6 +10,9 @@ const std::string MasternodeMetaStore::SERIALIZATION_VERSION_STRING = "CMasternodeMetaMan-Version-4"; +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 55a4dd02a7fc8..b334dec44d1ad 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -23,19 +23,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; @@ -51,12 +48,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); } @@ -64,25 +64,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) { @@ -95,10 +83,6 @@ class CMasternodeMetaInfo m_platform_ban_updated = height; return true; } - bool IsPlatformBanned() const EXCLUSIVE_LOCKS_REQUIRED(!cs) - { - return m_platform_ban; - } }; class MasternodeMetaStore @@ -137,7 +121,7 @@ class MasternodeMetaStore std::vector tmpMetaInfo; s >> tmpMetaInfo >> nDsqCount; for (auto& mm : tmpMetaInfo) { - metaInfos.emplace(mm.GetProTxHash(), CMasternodeMetaInfo{std::move(mm)}); + metaInfos.emplace(mm.m_protx_hash, CMasternodeMetaInfo{std::move(mm)}); } } From 85b49675d48b8124a2adcba59889001274f9c341 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 0b69085ddac3b..33661d92e0eba 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 b334dec44d1ad..68ba54e4a1c3d 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -188,6 +188,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: explicit CMasternodeMetaMan(); From 29379192bc603b8038e875ba29d9b8b8b6fd51e2 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 33661d92e0eba..0b71d8eb7e9d7 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 18b7929f136a4dc162f75bf96a300b3432217e06 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 68ba54e4a1c3d..8d5996d9429f0 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -17,7 +17,6 @@ #include #include -class CConnman; class UniValue; template From b57740d8b6f0ab400718466299d01c6a7ac2c461 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 8945ec62f7fae..359d1170c4bf9 100644 --- a/src/governance/object.cpp +++ b/src/governance/object.cpp @@ -148,14 +148,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 0b71d8eb7e9d7..b9d8f85f157ed 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 8d5996d9429f0..bb08aa236443a 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -209,7 +209,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 cdc9825409b6ead65d398d3ed04a18a5329394b2 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 b9d8f85f157ed..cfb1bc54c446f 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 bb08aa236443a..13cb0bddfded1 100644 --- a/src/masternode/meta.h +++ b/src/masternode/meta.h @@ -29,7 +29,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}; @@ -60,17 +60,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; @@ -197,7 +196,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 @@ -205,8 +204,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);