LCOV - code coverage report
Current view: top level - src/masternode - meta.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 121 170 71.2 %
Date: 2026-06-25 07:23:43 Functions: 29 37 78.4 %

          Line data    Source code
       1             : // Copyright (c) 2014-2025 The Dash Core developers
       2             : // Distributed under the MIT/X11 software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <masternode/meta.h>
       6             : 
       7             : #include <flat-database.h>
       8             : #include <univalue.h>
       9             : #include <util/time.h>
      10             : 
      11        3308 : const std::string MasternodeMetaStore::SERIALIZATION_VERSION_STRING = "CMasternodeMetaMan-Version-5";
      12             : 
      13             : static constexpr int MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS{5};
      14             : static constexpr int MASTERNODE_MAX_MIXING_TXES{5};
      15             : 
      16             : namespace {
      17        3308 : static const CMasternodeMetaInfo default_meta_info{};
      18             : } // anonymous namespace
      19             : 
      20        7124 : CMasternodeMetaMan::CMasternodeMetaMan() :
      21        3562 :     m_db{std::make_unique<db_type>("mncache.dat", "magicMasternodeCache")}
      22        3562 : {
      23        3562 : }
      24             : 
      25        7122 : CMasternodeMetaMan::~CMasternodeMetaMan()
      26        3561 : {
      27        3561 :     if (!is_valid) return;
      28        2857 :     m_db->Store(*this);
      29        7122 : }
      30             : 
      31        2857 : bool CMasternodeMetaMan::LoadCache(bool load_cache)
      32             : {
      33        2857 :     assert(m_db != nullptr);
      34        2857 :     is_valid = load_cache ? m_db->Load(*this) : m_db->Store(*this);
      35        2857 :     return is_valid;
      36             : }
      37             : 
      38        3758 : UniValue CMasternodeMetaInfo::ToJson() const
      39             : {
      40        3758 :     int64_t now = GetTime<std::chrono::seconds>().count();
      41             : 
      42        3758 :     UniValue ret(UniValue::VOBJ);
      43        3758 :     ret.pushKV("lastDSQ", m_last_dsq);
      44        3758 :     ret.pushKV("mixingTxCount", m_mixing_tx_count);
      45        3758 :     ret.pushKV("outboundAttemptCount", outboundAttemptCount);
      46        3758 :     ret.pushKV("lastOutboundAttempt", lastOutboundAttempt);
      47        3758 :     ret.pushKV("lastOutboundAttemptElapsed", now - lastOutboundAttempt);
      48        3758 :     ret.pushKV("lastOutboundSuccess", lastOutboundSuccess);
      49        3758 :     ret.pushKV("lastOutboundSuccessElapsed", now - lastOutboundSuccess);
      50        3758 :     ret.pushKV("is_platform_banned", m_platform_ban);
      51        3758 :     ret.pushKV("platform_ban_height_updated", m_platform_ban_updated);
      52             : 
      53        3758 :     return ret;
      54        3758 : }
      55             : 
      56        1480 : void CMasternodeMetaInfo::AddGovernanceVote(const uint256& nGovernanceObjectHash)
      57             : {
      58             :     // Insert a zero value, or not. Then increment the value regardless. This
      59             :     // ensures the value is in the map.
      60        1480 :     const auto& pair = mapGovernanceObjectsVotedOn.emplace(nGovernanceObjectHash, 0);
      61        1480 :     pair.first->second++;
      62        1480 : }
      63             : 
      64         300 : void CMasternodeMetaInfo::RemoveGovernanceObject(const uint256& nGovernanceObjectHash)
      65             : {
      66             :     // Whether or not the govobj hash exists in the map first is irrelevant.
      67         300 :     mapGovernanceObjectsVotedOn.erase(nGovernanceObjectHash);
      68         300 : }
      69             : 
      70       22676 : const CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfoOrDefault(const uint256& protx_hash) const
      71             : {
      72       22676 :     const auto it = metaInfos.find(protx_hash);
      73       22676 :     if (it == metaInfos.end()) return default_meta_info;
      74       17407 :     return it->second;
      75       22676 : }
      76             : 
      77        3758 : CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) const
      78             : {
      79        3758 :     LOCK(cs);
      80        3758 :     return GetMetaInfoOrDefault(proTxHash);
      81        3758 : }
      82             : 
      83        7301 : CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash)
      84             : {
      85        7301 :     auto it = metaInfos.find(proTxHash);
      86        7301 :     if (it != metaInfos.end()) {
      87        6010 :         return it->second;
      88             :     }
      89        1291 :     it = metaInfos.emplace(proTxHash, CMasternodeMetaInfo{proTxHash}).first;
      90        1291 :     return it->second;
      91        7301 : }
      92             : 
      93           0 : bool CMasternodeMetaMan::IsMixingThresholdExceeded(const uint256& protx_hash, int mn_count) const
      94             : {
      95           0 :     LOCK(cs);
      96           0 :     auto it = metaInfos.find(protx_hash);
      97           0 :     if (it == metaInfos.end()) {
      98           0 :         LogPrint(BCLog::COINJOIN, "DSQUEUE -- node %s is logged\n", protx_hash.ToString());
      99           0 :         return false;
     100             :     }
     101           0 :     const auto& meta_info = it->second;
     102           0 :     int64_t last_dsq = meta_info.m_last_dsq;
     103           0 :     int64_t threshold = last_dsq + mn_count / 5;
     104             : 
     105           0 :     LogPrint(BCLog::COINJOIN, "DSQUEUE -- mn: %s last_dsq: %d  dsq_threshold: %d  nDsqCount: %d\n",
     106             :              protx_hash.ToString(), last_dsq, threshold, nDsqCount);
     107           0 :     return last_dsq != 0 && threshold > nDsqCount;
     108           0 : }
     109             : 
     110           0 : void CMasternodeMetaMan::AllowMixing(const uint256& proTxHash)
     111             : {
     112           0 :     LOCK(cs);
     113           0 :     auto& mm = GetMetaInfo(proTxHash);
     114           0 :     mm.m_last_dsq = ++nDsqCount;
     115           0 :     mm.m_mixing_tx_count = 0;
     116           0 : }
     117             : 
     118           0 : void CMasternodeMetaMan::DisallowMixing(const uint256& proTxHash)
     119             : {
     120           0 :     LOCK(cs);
     121           0 :     GetMetaInfo(proTxHash).m_mixing_tx_count++;
     122           0 : }
     123             : 
     124           0 : bool CMasternodeMetaMan::IsValidForMixingTxes(const uint256& protx_hash) const
     125             : {
     126           0 :     LOCK(cs);
     127           0 :     return GetMetaInfoOrDefault(protx_hash).m_mixing_tx_count <= MASTERNODE_MAX_MIXING_TXES;
     128           0 : }
     129             : 
     130        1480 : void CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash)
     131             : {
     132        1480 :     LOCK(cs);
     133        1480 :     GetMetaInfo(proTxHash).AddGovernanceVote(nGovernanceObjectHash);
     134        1480 : }
     135             : 
     136          60 : void CMasternodeMetaMan::RemoveGovernanceObject(const uint256& nGovernanceObjectHash)
     137             : {
     138          60 :     LOCK(cs);
     139         360 :     for (auto& [_, meta_info] : metaInfos) {
     140         300 :         meta_info.RemoveGovernanceObject(nGovernanceObjectHash);
     141             :     }
     142          60 : }
     143             : 
     144       99040 : std::vector<uint256> CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes()
     145             : {
     146       99040 :     std::vector<uint256> vecTmp;
     147      198080 :     WITH_LOCK(cs, vecTmp.swap(vecDirtyGovernanceObjectHashes));
     148       99040 :     return vecTmp;
     149       99040 : }
     150             : 
     151        3545 : void CMasternodeMetaMan::SetLastOutboundAttempt(const uint256& protx_hash, int64_t t)
     152             : {
     153        3545 :     LOCK(cs);
     154        3545 :     GetMetaInfo(protx_hash).SetLastOutboundAttempt(t);
     155        3545 : }
     156             : 
     157        2266 : void CMasternodeMetaMan::SetLastOutboundSuccess(const uint256& protx_hash, int64_t t)
     158             : {
     159        2266 :     LOCK(cs);
     160        2266 :     GetMetaInfo(protx_hash).SetLastOutboundSuccess(t);
     161        2266 : }
     162             : 
     163       14229 : int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) const
     164             : {
     165       14229 :     LOCK(cs);
     166       14229 :     return GetMetaInfoOrDefault(protx_hash).lastOutboundAttempt;
     167       14229 : }
     168             : 
     169        1266 : int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const
     170             : {
     171        1266 :     LOCK(cs);
     172        1266 :     return GetMetaInfoOrDefault(protx_hash).lastOutboundSuccess;
     173        1266 : }
     174             : 
     175        2166 : bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const
     176             : {
     177        2166 :     LOCK(cs);
     178        2166 :     return GetMetaInfoOrDefault(protx_hash).outboundAttemptCount > MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS;
     179        2166 : }
     180             : 
     181        1257 : bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const
     182             : {
     183        1257 :     LOCK(cs);
     184        1257 :     return GetMetaInfoOrDefault(protx_hash).m_platform_ban;
     185        1257 : }
     186             : 
     187        2163 : bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height)
     188             : {
     189        2163 :     LOCK(cs);
     190             : 
     191        2163 :     auto it = metaInfos.find(protx_hash);
     192        2163 :     if (it == metaInfos.end()) return false;
     193             : 
     194          51 :     return it->second.SetPlatformBan(false, height);
     195        2163 : }
     196             : 
     197          10 : bool CMasternodeMetaMan::SetPlatformBan(const uint256& inv_hash, PlatformBanMessage&& ban_msg)
     198             : {
     199          10 :     LOCK(cs);
     200             : 
     201          10 :     const uint256& protx_hash = ban_msg.m_protx_hash;
     202             : 
     203          10 :     bool ret = GetMetaInfo(protx_hash).SetPlatformBan(true, ban_msg.m_requested_height);
     204          10 :     if (ret) {
     205          10 :         m_seen_platform_bans.emplace(inv_hash, std::move(ban_msg));
     206          10 :     }
     207          10 :     return ret;
     208          10 : }
     209             : 
     210          19 : bool CMasternodeMetaMan::AlreadyHavePlatformBan(const uint256& inv_hash) const
     211             : {
     212          19 :     LOCK(cs);
     213          19 :     return m_seen_platform_bans.exists(inv_hash);
     214          19 : }
     215             : 
     216          10 : std::optional<PlatformBanMessage> CMasternodeMetaMan::GetPlatformBan(const uint256& inv_hash) const
     217             : {
     218          10 :     LOCK(cs);
     219          10 :     PlatformBanMessage ret;
     220          10 :     if (!m_seen_platform_bans.get(inv_hash, ret)) {
     221           0 :         return std::nullopt;
     222             :     }
     223             : 
     224          10 :     return ret;
     225          10 : }
     226             : 
     227           0 : void CMasternodeMetaMan::AddUsedMasternode(const uint256& proTxHash)
     228             : {
     229           0 :     LOCK(cs);
     230             :     // Only add if not already present (prevents duplicates)
     231           0 :     if (m_used_masternodes_set.insert(proTxHash).second) {
     232           0 :         m_used_masternodes.push_back(proTxHash);
     233           0 :     }
     234           0 : }
     235             : 
     236           0 : void CMasternodeMetaMan::RemoveUsedMasternodes(size_t count)
     237             : {
     238           0 :     LOCK(cs);
     239           0 :     size_t removed = 0;
     240           0 :     while (removed < count && !m_used_masternodes.empty()) {
     241             :         // Remove from both the set and the deque
     242           0 :         m_used_masternodes_set.erase(m_used_masternodes.front());
     243           0 :         m_used_masternodes.pop_front();
     244           0 :         ++removed;
     245             :     }
     246           0 : }
     247             : 
     248           0 : size_t CMasternodeMetaMan::GetUsedMasternodesCount() const
     249             : {
     250           0 :     LOCK(cs);
     251           0 :     return m_used_masternodes.size();
     252           0 : }
     253             : 
     254           0 : bool CMasternodeMetaMan::IsUsedMasternode(const uint256& proTxHash) const
     255             : {
     256           0 :     LOCK(cs);
     257           0 :     return m_used_masternodes_set.find(proTxHash) != m_used_masternodes_set.end();
     258           0 : }
     259             : 
     260        7204 : std::string MasternodeMetaStore::ToString() const
     261             : {
     262        7204 :     LOCK(cs);
     263        7204 :     return strprintf("Masternodes: meta infos object count: %d, nDsqCount: %d, used masternodes count: %d",
     264        7204 :                      metaInfos.size(), nDsqCount, m_used_masternodes.size());
     265        7204 : }
     266             : 
     267          10 : uint256 PlatformBanMessage::GetHash() const { return ::SerializeHash(*this); }

Generated by: LCOV version 1.16