Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions src/coinjoin/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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;
}
Expand Down
9 changes: 2 additions & 7 deletions src/coinjoin/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 1 addition & 2 deletions src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null<co
const auto opt_proTx = GetTxPayload<CProUpServTx>(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);
}
Comment on lines +671 to 674
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify the log message for platform ban revival.

The log message "is failed to Platform revived" is grammatically incorrect and confusing. Since this block now executes when the revival succeeds (not when it fails, as in the previous implementation), consider revising the message to something clearer like:

LogPrint(BCLog::LLMQ, "%s -- MN %s platform ban revived at height %d\n", __func__,
         opt_proTx->proTxHash.ToString(), nHeight);
🤖 Prompt for AI Agents
In src/evo/deterministicmns.cpp around lines 671-674, the LogPrint message is
grammatically incorrect and misleading ("is failed to Platform revived") and
should reflect that ResetPlatformBan succeeded; update the log string to a
clear, concise message such as "MN %s platform ban revived at height %d"
(preserve __func__ and the proTxHash.ToString() and nHeight parameters) so the
log accurately represents a successful revival.

Expand Down
2 changes: 1 addition & 1 deletion src/evo/mnauth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ MessageProcessingResult CMNAuth::ProcessMessage(CNode& peer, ServiceFlags node_s
}

if (!peer.IsInboundConn()) {
mn_metaman.GetMetaInfo(mnauth.proRegTxHash)->SetLastOutboundSuccess(GetTime<std::chrono::seconds>().count());
mn_metaman.SetLastOutboundSuccess(mnauth.proRegTxHash, GetTime<std::chrono::seconds>().count());
if (peer.m_masternode_probe_connection) {
LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- Masternode probe successful for %s, disconnecting. peer=%d\n",
Comment on lines 105 to 108
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard SetLastOutboundSuccess with mn meta lock

SetLastOutboundSuccess requires the manager mutex to be held (the old code locked via GetMetaInfo). We’re now calling it bare, which violates the contract and will assert. Wrap the call in the manager’s lock (e.g. WITH_LOCK(mn_metaman.GetCs(), mn_metaman.SetLastOutboundSuccess(...));).

🤖 Prompt for AI Agents
In src/evo/mnauth.cpp around lines 105 to 108, SetLastOutboundSuccess is called
without holding mn_metaman's mutex which violates the manager's locking contract
and will assert; wrap the call with the manager lock, e.g. use
WITH_LOCK(mn_metaman.GetCs(),
mn_metaman.SetLastOutboundSuccess(mnauth.proRegTxHash,
GetTime<std::chrono::seconds>().count())); and keep the rest of the logic
unchanged so the call is protected by the manager's mutex.

mnauth.proRegTxHash.ToString(), peer.GetId());
Expand Down
9 changes: 1 addition & 8 deletions src/governance/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions src/llmq/dkgsession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
2 changes: 1 addition & 1 deletion src/llmq/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
171 changes: 122 additions & 49 deletions src/masternode/meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@

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};

namespace {
static const CMasternodeMetaInfo default_meta_info_meta_info{};
} // anonymous namespace

CMasternodeMetaMan::CMasternodeMetaMan() :
m_db{std::make_unique<db_type>("mncache.dat", "magicMasternodeCache")}
{
Expand All @@ -30,29 +37,24 @@ CMasternodeMetaMan::~CMasternodeMetaMan()

UniValue CMasternodeMetaInfo::ToJson() const
{
UniValue ret(UniValue::VOBJ);

int64_t now = GetTime<std::chrono::seconds>().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", m_last_dsq);
ret.pushKV("mixingTxCount", m_mixing_tx_count);
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);
Expand All @@ -61,65 +63,83 @@ 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);
}

CMasternodeMetaInfoPtr CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash, bool fCreate)
const CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfoOrDefault(const uint256& protx_hash) const
{
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) const
{
LOCK (cs);
return GetMetaInfoOrDefault(proTxHash);
}

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<CMasternodeMetaInfo>(proTxHash)).first;
it = metaInfos.emplace(proTxHash, CMasternodeMetaInfo{proTxHash}).first;
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)
bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) const
{
auto metaInfo = GetMetaInfo(proTxHash);
if (metaInfo == nullptr) {
// return a threshold which is slightly above nDsqCount i.e. a no-go
return nDsqCount + 1;
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.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",
protx_hash.ToString(), last_dsq, threshold, nDsqCount);
return last_dsq != 0 && threshold > nDsqCount;
}
Comment on lines +93 to 108
Copy link

@coderabbitai coderabbitai bot Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the inverted logic in IsDsqOver.

There is a critical logic error in this method. Line 93 checks if (it != metaInfos.end()) and returns false when the entry is found. However, line 97 then attempts to access it->second, which would be invalid if the iterator points to end() (i.e., when the entry is not found).

The condition on line 93 should be inverted to check for the "not found" case:

Apply this diff to fix the logic error:

 bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) const
 {
     LOCK(cs);
     auto it = metaInfos.find(protx_hash);
-    if (it != metaInfos.end()) {
+    if (it == metaInfos.end()) {
         LogPrint(BCLog::COINJOIN, "DSQUEUE -- node %s is logged\n", protx_hash.ToString());
         return false;
     }
     const auto& meta_info = it->second;
     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",
              protx_hash.ToString(), last_dsq, threshold, nDsqCount);
     return last_dsq != 0 && threshold > nDsqCount;
 }

Additionally, the log message on line 94 appears incorrect. It says "node %s is logged" when the node is not found. Consider updating it to: "DSQUEUE -- node %s not found in metaInfos\n".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bool CMasternodeMetaMan::IsDsqOver(const uint256& protx_hash, int mn_count) const
{
auto metaInfo = GetMetaInfo(proTxHash);
if (metaInfo == nullptr) {
// return a threshold which is slightly above nDsqCount i.e. a no-go
return nDsqCount + 1;
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.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",
protx_hash.ToString(), last_dsq, threshold, nDsqCount);
return last_dsq != 0 && threshold > nDsqCount;
}
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;
}
const auto& meta_info = it->second;
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",
protx_hash.ToString(), last_dsq, threshold, nDsqCount);
return last_dsq != 0 && threshold > nDsqCount;
}
🤖 Prompt for AI Agents
In src/masternode/meta.cpp around lines 89 to 104, the iterator check is
inverted and leads to invalid access: change the if condition to check for "not
found" (it == metaInfos.end()), log "DSQUEUE -- node %s not found in
metaInfos\n" in that branch and return false there, and otherwise proceed to use
it->second; ensure the rest of the function uses the found meta_info to compute
last_dsq, threshold, and return the correct boolean expression.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@UdjinM6 Thank you for confirming! The fix will prevent the potential crash from dereferencing an invalid iterator. 🎉


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!


void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash)
{
auto mm = GetMetaInfo(proTxHash);
nDsqCount++;
mm->nLastDsq = nDsqCount.load();
mm->nMixingTxCount = 0;

LOCK(cs);
auto& mm = GetMetaInfo(proTxHash);
mm.m_last_dsq = nDsqCount.load();
mm.m_mixing_tx_count = 0;
}

void CMasternodeMetaMan::DisallowMixing(const uint256& proTxHash)
{
auto mm = GetMetaInfo(proTxHash);
mm->nMixingTxCount++;
LOCK(cs);
GetMetaInfo(proTxHash).m_mixing_tx_count++;
}

bool CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash)
bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const
{
auto mm = GetMetaInfo(proTxHash);
mm->AddGovernanceVote(nGovernanceObjectHash);
return true;
LOCK(cs);
return GetMetaInfoOrDefault(protx_hash).m_mixing_tx_count <= MASTERNODE_MAX_MIXING_TXES;
}

void CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash)
{
LOCK(cs);
GetMetaInfo(proTxHash).AddGovernanceVote(nGovernanceObjectHash);
}

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);
}
}

Expand All @@ -130,6 +150,65 @@ std::vector<uint256> CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes(
return vecTmp;
}

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);
return GetMetaInfoOrDefault(protx_hash).lastOutboundAttempt;
}

int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const
{
LOCK(cs);
return GetMetaInfoOrDefault(protx_hash).lastOutboundSuccess;
}

bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const
{
LOCK(cs);
return GetMetaInfoOrDefault(protx_hash).outboundAttemptCount > MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS;
}

bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const
{
LOCK(cs);
return GetMetaInfoOrDefault(protx_hash).m_platform_ban;
}

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::SetPlatformBan(const uint256& inv_hash, PlatformBanMessage&& ban_msg)
{
LOCK(cs);

const uint256& protx_hash = ban_msg.m_protx_hash;

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));
}
return ret;
}

bool CMasternodeMetaMan::AlreadyHavePlatformBan(const uint256& inv_hash) const
{
LOCK(cs);
Expand All @@ -147,12 +226,6 @@ std::optional<PlatformBanMessage> 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);
Expand Down
Loading
Loading