LCOV - code coverage report
Current view: top level - src/masternode - meta.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 15 170 8.8 %
Date: 2026-06-25 07:23:51 Functions: 7 37 18.9 %

          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         146 : 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         146 : static const CMasternodeMetaInfo default_meta_info{};
      18             : } // anonymous namespace
      19             : 
      20        1254 : CMasternodeMetaMan::CMasternodeMetaMan() :
      21         627 :     m_db{std::make_unique<db_type>("mncache.dat", "magicMasternodeCache")}
      22         627 : {
      23         627 : }
      24             : 
      25        1252 : CMasternodeMetaMan::~CMasternodeMetaMan()
      26         626 : {
      27         626 :     if (!is_valid) return;
      28           0 :     m_db->Store(*this);
      29        1252 : }
      30             : 
      31           0 : bool CMasternodeMetaMan::LoadCache(bool load_cache)
      32             : {
      33           0 :     assert(m_db != nullptr);
      34           0 :     is_valid = load_cache ? m_db->Load(*this) : m_db->Store(*this);
      35           0 :     return is_valid;
      36             : }
      37             : 
      38           0 : UniValue CMasternodeMetaInfo::ToJson() const
      39             : {
      40           0 :     int64_t now = GetTime<std::chrono::seconds>().count();
      41             : 
      42           0 :     UniValue ret(UniValue::VOBJ);
      43           0 :     ret.pushKV("lastDSQ", m_last_dsq);
      44           0 :     ret.pushKV("mixingTxCount", m_mixing_tx_count);
      45           0 :     ret.pushKV("outboundAttemptCount", outboundAttemptCount);
      46           0 :     ret.pushKV("lastOutboundAttempt", lastOutboundAttempt);
      47           0 :     ret.pushKV("lastOutboundAttemptElapsed", now - lastOutboundAttempt);
      48           0 :     ret.pushKV("lastOutboundSuccess", lastOutboundSuccess);
      49           0 :     ret.pushKV("lastOutboundSuccessElapsed", now - lastOutboundSuccess);
      50           0 :     ret.pushKV("is_platform_banned", m_platform_ban);
      51           0 :     ret.pushKV("platform_ban_height_updated", m_platform_ban_updated);
      52             : 
      53           0 :     return ret;
      54           0 : }
      55             : 
      56           0 : 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           0 :     const auto& pair = mapGovernanceObjectsVotedOn.emplace(nGovernanceObjectHash, 0);
      61           0 :     pair.first->second++;
      62           0 : }
      63             : 
      64           0 : void CMasternodeMetaInfo::RemoveGovernanceObject(const uint256& nGovernanceObjectHash)
      65             : {
      66             :     // Whether or not the govobj hash exists in the map first is irrelevant.
      67           0 :     mapGovernanceObjectsVotedOn.erase(nGovernanceObjectHash);
      68           0 : }
      69             : 
      70           0 : const CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfoOrDefault(const uint256& protx_hash) const
      71             : {
      72           0 :     const auto it = metaInfos.find(protx_hash);
      73           0 :     if (it == metaInfos.end()) return default_meta_info;
      74           0 :     return it->second;
      75           0 : }
      76             : 
      77           0 : CMasternodeMetaInfo CMasternodeMetaMan::GetInfo(const uint256& proTxHash) const
      78             : {
      79           0 :     LOCK(cs);
      80           0 :     return GetMetaInfoOrDefault(proTxHash);
      81           0 : }
      82             : 
      83           0 : CMasternodeMetaInfo& CMasternodeMetaMan::GetMetaInfo(const uint256& proTxHash)
      84             : {
      85           0 :     auto it = metaInfos.find(proTxHash);
      86           0 :     if (it != metaInfos.end()) {
      87           0 :         return it->second;
      88             :     }
      89           0 :     it = metaInfos.emplace(proTxHash, CMasternodeMetaInfo{proTxHash}).first;
      90           0 :     return it->second;
      91           0 : }
      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           0 : void CMasternodeMetaMan::AddGovernanceVote(const uint256& proTxHash, const uint256& nGovernanceObjectHash)
     131             : {
     132           0 :     LOCK(cs);
     133           0 :     GetMetaInfo(proTxHash).AddGovernanceVote(nGovernanceObjectHash);
     134           0 : }
     135             : 
     136           0 : void CMasternodeMetaMan::RemoveGovernanceObject(const uint256& nGovernanceObjectHash)
     137             : {
     138           0 :     LOCK(cs);
     139           0 :     for (auto& [_, meta_info] : metaInfos) {
     140           0 :         meta_info.RemoveGovernanceObject(nGovernanceObjectHash);
     141             :     }
     142           0 : }
     143             : 
     144           0 : std::vector<uint256> CMasternodeMetaMan::GetAndClearDirtyGovernanceObjectHashes()
     145             : {
     146           0 :     std::vector<uint256> vecTmp;
     147           0 :     WITH_LOCK(cs, vecTmp.swap(vecDirtyGovernanceObjectHashes));
     148           0 :     return vecTmp;
     149           0 : }
     150             : 
     151           0 : void CMasternodeMetaMan::SetLastOutboundAttempt(const uint256& protx_hash, int64_t t)
     152             : {
     153           0 :     LOCK(cs);
     154           0 :     GetMetaInfo(protx_hash).SetLastOutboundAttempt(t);
     155           0 : }
     156             : 
     157           0 : void CMasternodeMetaMan::SetLastOutboundSuccess(const uint256& protx_hash, int64_t t)
     158             : {
     159           0 :     LOCK(cs);
     160           0 :     GetMetaInfo(protx_hash).SetLastOutboundSuccess(t);
     161           0 : }
     162             : 
     163           0 : int64_t CMasternodeMetaMan::GetLastOutboundAttempt(const uint256& protx_hash) const
     164             : {
     165           0 :     LOCK(cs);
     166           0 :     return GetMetaInfoOrDefault(protx_hash).lastOutboundAttempt;
     167           0 : }
     168             : 
     169           0 : int64_t CMasternodeMetaMan::GetLastOutboundSuccess(const uint256& protx_hash) const
     170             : {
     171           0 :     LOCK(cs);
     172           0 :     return GetMetaInfoOrDefault(protx_hash).lastOutboundSuccess;
     173           0 : }
     174             : 
     175           0 : bool CMasternodeMetaMan::OutboundFailedTooManyTimes(const uint256& protx_hash) const
     176             : {
     177           0 :     LOCK(cs);
     178           0 :     return GetMetaInfoOrDefault(protx_hash).outboundAttemptCount > MASTERNODE_MAX_FAILED_OUTBOUND_ATTEMPTS;
     179           0 : }
     180             : 
     181           0 : bool CMasternodeMetaMan::IsPlatformBanned(const uint256& protx_hash) const
     182             : {
     183           0 :     LOCK(cs);
     184           0 :     return GetMetaInfoOrDefault(protx_hash).m_platform_ban;
     185           0 : }
     186             : 
     187           4 : bool CMasternodeMetaMan::ResetPlatformBan(const uint256& protx_hash, int height)
     188             : {
     189           4 :     LOCK(cs);
     190             : 
     191           4 :     auto it = metaInfos.find(protx_hash);
     192           4 :     if (it == metaInfos.end()) return false;
     193             : 
     194           0 :     return it->second.SetPlatformBan(false, height);
     195           4 : }
     196             : 
     197           0 : bool CMasternodeMetaMan::SetPlatformBan(const uint256& inv_hash, PlatformBanMessage&& ban_msg)
     198             : {
     199           0 :     LOCK(cs);
     200             : 
     201           0 :     const uint256& protx_hash = ban_msg.m_protx_hash;
     202             : 
     203           0 :     bool ret = GetMetaInfo(protx_hash).SetPlatformBan(true, ban_msg.m_requested_height);
     204           0 :     if (ret) {
     205           0 :         m_seen_platform_bans.emplace(inv_hash, std::move(ban_msg));
     206           0 :     }
     207           0 :     return ret;
     208           0 : }
     209             : 
     210           0 : bool CMasternodeMetaMan::AlreadyHavePlatformBan(const uint256& inv_hash) const
     211             : {
     212           0 :     LOCK(cs);
     213           0 :     return m_seen_platform_bans.exists(inv_hash);
     214           0 : }
     215             : 
     216           0 : std::optional<PlatformBanMessage> CMasternodeMetaMan::GetPlatformBan(const uint256& inv_hash) const
     217             : {
     218           0 :     LOCK(cs);
     219           0 :     PlatformBanMessage ret;
     220           0 :     if (!m_seen_platform_bans.get(inv_hash, ret)) {
     221           0 :         return std::nullopt;
     222             :     }
     223             : 
     224           0 :     return ret;
     225           0 : }
     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           0 : std::string MasternodeMetaStore::ToString() const
     261             : {
     262           0 :     LOCK(cs);
     263           0 :     return strprintf("Masternodes: meta infos object count: %d, nDsqCount: %d, used masternodes count: %d",
     264           0 :                      metaInfos.size(), nDsqCount, m_used_masternodes.size());
     265           0 : }
     266             : 
     267           0 : uint256 PlatformBanMessage::GetHash() const { return ::SerializeHash(*this); }

Generated by: LCOV version 1.16