LCOV - code coverage report
Current view: top level - src - masternode.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 246 328 75.0 %
Date: 2025-02-23 09:33:43 Functions: 32 34 94.1 %

          Line data    Source code
       1             : // Copyright (c) 2014-2015 The Dash developers
       2             : // Copyright (c) 2015-2022 The PIVX Core developers
       3             : // Distributed under the MIT/X11 software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "masternode.h"
       7             : 
       8             : #include "addrman.h"
       9             : #include "masternodeman.h"
      10             : #include "netbase.h"
      11             : #include "sync.h"
      12             : #include "tiertwo/tiertwo_sync_state.h"
      13             : #include "wallet/wallet.h"
      14             : 
      15             : #define MASTERNODE_MIN_MNP_SECONDS_REGTEST 90
      16             : #define MASTERNODE_MIN_MNB_SECONDS_REGTEST 25
      17             : #define MASTERNODE_PING_SECONDS_REGTEST 25
      18             : #define MASTERNODE_EXPIRATION_SECONDS_REGTEST 12 * 60
      19             : #define MASTERNODE_REMOVAL_SECONDS_REGTEST 13 * 60
      20             : 
      21             : #define MASTERNODE_MIN_MNP_SECONDS (10 * 60)
      22             : #define MASTERNODE_MIN_MNB_SECONDS (5 * 60)
      23             : #define MASTERNODE_PING_SECONDS (5 * 60)
      24             : #define MASTERNODE_EXPIRATION_SECONDS (120 * 60)
      25             : #define MASTERNODE_REMOVAL_SECONDS (130 * 60)
      26             : #define MASTERNODE_CHECK_SECONDS 5
      27             : 
      28      122294 : int MasternodeMinPingSeconds()
      29             : {
      30      122294 :     return Params().IsRegTestNet() ? MASTERNODE_MIN_MNP_SECONDS_REGTEST : MASTERNODE_MIN_MNP_SECONDS;
      31             : }
      32             : 
      33          10 : int MasternodeBroadcastSeconds()
      34             : {
      35          10 :     return Params().IsRegTestNet() ? MASTERNODE_MIN_MNB_SECONDS_REGTEST : MASTERNODE_MIN_MNB_SECONDS;
      36             : }
      37             : 
      38       34121 : int MasternodePingSeconds()
      39             : {
      40       34121 :     return Params().IsRegTestNet() ? MASTERNODE_PING_SECONDS_REGTEST : MASTERNODE_PING_SECONDS;
      41             : }
      42             : 
      43      120245 : int MasternodeExpirationSeconds()
      44             : {
      45      120245 :     return Params().IsRegTestNet() ? MASTERNODE_EXPIRATION_SECONDS_REGTEST : MASTERNODE_EXPIRATION_SECONDS;
      46             : }
      47             : 
      48      140066 : int MasternodeRemovalSeconds()
      49             : {
      50      140066 :     return Params().IsRegTestNet() ? MASTERNODE_REMOVAL_SECONDS_REGTEST : MASTERNODE_REMOVAL_SECONDS;
      51             : }
      52             : 
      53             : // Used for sigTime < maxTimeWindow
      54       52337 : int64_t GetMaxTimeWindow()
      55             : {
      56       52337 :     return GetAdjustedTime() + 60 * 2;
      57             : }
      58             : 
      59             : 
      60         136 : CMasternode::CMasternode() :
      61         136 :         CSignedMessage()
      62             : {
      63         136 :     LOCK(cs);
      64         136 :     vin = CTxIn();
      65         136 :     addr = CService();
      66         136 :     pubKeyCollateralAddress = CPubKey();
      67         136 :     pubKeyMasternode = CPubKey();
      68         136 :     sigTime = 0;
      69         136 :     lastPing = CMasternodePing();
      70         136 :     protocolVersion = PROTOCOL_VERSION;
      71         136 :     nScanningErrorCount = 0;
      72         136 :     nLastScanningErrorBlockHeight = 0;
      73         136 :     mnPayeeScript.clear();
      74         136 : }
      75             : 
      76        7725 : CMasternode::CMasternode(const CMasternode& other) :
      77        7725 :         CSignedMessage(other)
      78             : {
      79        7725 :     LOCK(cs);
      80        7725 :     vin = other.vin;
      81        7725 :     addr = other.addr;
      82        7725 :     pubKeyCollateralAddress = other.pubKeyCollateralAddress;
      83        7725 :     pubKeyMasternode = other.pubKeyMasternode;
      84        7725 :     sigTime = other.sigTime;
      85        7725 :     lastPing = other.lastPing;
      86        7725 :     protocolVersion = other.protocolVersion;
      87        7725 :     nScanningErrorCount = other.nScanningErrorCount;
      88        7725 :     nLastScanningErrorBlockHeight = other.nLastScanningErrorBlockHeight;
      89        7725 :     mnPayeeScript = other.mnPayeeScript;
      90        7725 : }
      91             : 
      92        3830 : CMasternode::CMasternode(const CDeterministicMNCPtr& dmn, int64_t registeredTime, const uint256& registeredHash) :
      93        3830 :         CSignedMessage()
      94             : {
      95        3830 :     LOCK(cs);
      96        3830 :     vin = CTxIn(dmn->collateralOutpoint);
      97        3830 :     addr = dmn->pdmnState->addr;
      98        3830 :     pubKeyCollateralAddress = CPubKey();
      99        3830 :     pubKeyMasternode = CPubKey();
     100        3830 :     sigTime = registeredTime;
     101        3830 :     lastPing = CMasternodePing(vin, registeredHash, registeredTime);
     102        3830 :     protocolVersion = PROTOCOL_VERSION;
     103        3830 :     nScanningErrorCount = 0;
     104        3830 :     nLastScanningErrorBlockHeight = 0;
     105        3830 :     mnPayeeScript = dmn->pdmnState->scriptPayout;
     106        3830 : }
     107             : 
     108          82 : uint256 CMasternode::GetSignatureHash() const
     109             : {
     110          82 :     int version = !addr.IsAddrV1Compatible() ? PROTOCOL_VERSION | ADDRV2_FORMAT : PROTOCOL_VERSION;
     111          82 :     CHashWriter ss(SER_GETHASH, version);
     112          82 :     ss << nMessVersion;
     113          82 :     ss << addr;
     114          82 :     ss << sigTime;
     115          82 :     ss << pubKeyCollateralAddress;
     116          82 :     ss << pubKeyMasternode;
     117          82 :     ss << protocolVersion;
     118          82 :     return ss.GetHash();
     119             : }
     120             : 
     121           0 : std::string CMasternode::GetStrMessage() const
     122             : {
     123           0 :     return (addr.ToString() +
     124           0 :             std::to_string(sigTime) +
     125           0 :             pubKeyCollateralAddress.GetID().ToString() +
     126           0 :             pubKeyMasternode.GetID().ToString() +
     127           0 :             std::to_string(protocolVersion)
     128           0 :     );
     129             : }
     130             : 
     131             : //
     132             : // When a new masternode broadcast is sent, update our information
     133             : //
     134          12 : bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
     135             : {
     136          12 :     if (mnb.sigTime > sigTime) {
     137             :         // TODO: lock cs. Need to be careful as mnb.lastPing.CheckAndUpdate locks cs_main internally.
     138          12 :         nMessVersion = mnb.nMessVersion;
     139          12 :         pubKeyMasternode = mnb.pubKeyMasternode;
     140          12 :         pubKeyCollateralAddress = mnb.pubKeyCollateralAddress;
     141          12 :         sigTime = mnb.sigTime;
     142          12 :         vchSig = mnb.vchSig;
     143          12 :         protocolVersion = mnb.protocolVersion;
     144          12 :         addr = mnb.addr;
     145          12 :         int nDoS = 0;
     146          12 :         if (mnb.lastPing.IsNull() || (!mnb.lastPing.IsNull() && mnb.lastPing.CheckAndUpdate(nDoS, false))) {
     147           0 :             lastPing = mnb.lastPing;
     148           0 :             mnodeman.mapSeenMasternodePing.emplace(lastPing.GetHash(), lastPing);
     149             :         }
     150          12 :         return true;
     151             :     }
     152             :     return false;
     153             : }
     154             : 
     155             : //
     156             : // Deterministically calculate a given "score" for a Masternode depending on how close it's hash is to
     157             : // the proof of work for that block. The further away they are the better, the furthest will win the election
     158             : // and get paid this block
     159             : //
     160       43641 : arith_uint256 CMasternode::CalculateScore(const uint256& hash) const
     161             : {
     162       43641 :     CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
     163       43641 :     ss << hash;
     164       87282 :     const arith_uint256& hash2 = UintToArith256(ss.GetHash());
     165             : 
     166       43641 :     CHashWriter ss2(SER_GETHASH, PROTOCOL_VERSION);
     167       43641 :     ss2 << hash;
     168      130923 :     const arith_uint256& aux = UintToArith256(vin.prevout.hash) + vin.prevout.n;
     169       43641 :     ss2 << aux;
     170       87282 :     const arith_uint256& hash3 = UintToArith256(ss2.GetHash());
     171             : 
     172       43641 :     return (hash3 > hash2 ? hash3 - hash2 : hash2 - hash3);
     173             : }
     174             : 
     175      122938 : CMasternode::state CMasternode::GetActiveState() const
     176             : {
     177      245876 :     LOCK(cs);
     178      122938 :     if (fCollateralSpent) {
     179             :         return MASTERNODE_VIN_SPENT;
     180             :     }
     181      120334 :     if (!IsPingedWithin(MasternodeRemovalSeconds())) {
     182             :         return MASTERNODE_REMOVE;
     183             :     }
     184      120245 :     if (!IsPingedWithin(MasternodeExpirationSeconds())) {
     185             :         return MASTERNODE_EXPIRED;
     186             :     }
     187      120165 :     if(lastPing.sigTime - sigTime < MasternodeMinPingSeconds()){
     188        3891 :         return MASTERNODE_PRE_ENABLED;
     189             :     }
     190             :     return MASTERNODE_ENABLED;
     191             : }
     192             : 
     193          14 : bool CMasternode::IsValidNetAddr() const
     194             : {
     195             :     // TODO: regtest is fine with any addresses for now,
     196             :     // should probably be a bit smarter if one day we start to implement tests for this
     197          14 :     return Params().IsRegTestNet() ||
     198           0 :            (IsReachable(addr) && addr.IsRoutable());
     199             : }
     200             : 
     201          82 : CMasternodeBroadcast::CMasternodeBroadcast() :
     202          82 :         CMasternode()
     203          82 : { }
     204             : 
     205          14 : CMasternodeBroadcast::CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int protocolVersionIn, const CMasternodePing& _lastPing) :
     206          14 :         CMasternode()
     207             : {
     208          14 :     vin = newVin;
     209          14 :     addr = newAddr;
     210          14 :     pubKeyCollateralAddress = pubKeyCollateralAddressNew;
     211          14 :     pubKeyMasternode = pubKeyMasternodeNew;
     212          14 :     protocolVersion = protocolVersionIn;
     213          14 :     lastPing = _lastPing;
     214          14 :     sigTime = lastPing.sigTime;
     215          14 : }
     216             : 
     217        2617 : CMasternodeBroadcast::CMasternodeBroadcast(const CMasternode& mn) :
     218        2617 :         CMasternode(mn)
     219        2617 : { }
     220             : 
     221          14 : bool CMasternodeBroadcast::Create(const std::string& strService,
     222             :                                   const std::string& strKeyMasternode,
     223             :                                   const std::string& strTxHash,
     224             :                                   const std::string& strOutputIndex,
     225             :                                   std::string& strErrorRet,
     226             :                                   CMasternodeBroadcast& mnbRet,
     227             :                                   bool fOffline,
     228             :                                   int chainHeight)
     229             : {
     230          14 :     CPubKey pubKeyCollateralAddressNew;
     231          28 :     CKey keyCollateralAddressNew;
     232          14 :     CPubKey pubKeyMasternodeNew;
     233          28 :     CKey keyMasternodeNew;
     234             : 
     235             :     //need correct blocks to send ping
     236          14 :     if (!fOffline && !g_tiertwo_sync_state.IsBlockchainSynced()) {
     237           0 :         strErrorRet = "Sync in progress. Must wait until sync is complete to start Masternode";
     238           0 :         LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
     239           0 :         return false;
     240             :     }
     241             : 
     242          28 :     std::string strError;
     243          14 :     if (strTxHash.empty() || strOutputIndex.empty()) {
     244           0 :         strError = "Invalid masternode collateral hash or output index";
     245           0 :         return error("%s: %s", __func__, strError);
     246             :     }
     247             : 
     248          14 :     const uint256 collateralHash = uint256S(strTxHash);
     249          14 :     int collateralOutputIndex;
     250          14 :     try {
     251          28 :         collateralOutputIndex = std::stoi(strOutputIndex.c_str());
     252           0 :     } catch (const std::exception& e) {
     253           0 :         strError = "Invalid masternode output index";
     254           0 :         return error("%s: %s on strOutputIndex", __func__, e.what());
     255             :     }
     256             : 
     257          14 :     if (!CMessageSigner::GetKeysFromSecret(strKeyMasternode, keyMasternodeNew, pubKeyMasternodeNew)) {
     258           0 :         strErrorRet = strprintf("Invalid masternode key %s", strKeyMasternode);
     259           0 :         LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
     260           0 :         return false;
     261             :     }
     262             : 
     263             :     // Use wallet-0 here. Legacy mnb creation can be removed after transition to DMN
     264          14 :     COutPoint collateralOut(collateralHash, collateralOutputIndex);
     265          14 :     if (vpwallets.empty() || !vpwallets[0]->GetMasternodeVinAndKeys(pubKeyCollateralAddressNew,
     266             :                                                                     keyCollateralAddressNew,
     267             :                                                                     collateralOut,
     268             :                                                                     true, // fValidateCollateral
     269             :                                                                     strError)) {
     270           0 :         strErrorRet = strError; // GetMasternodeVinAndKeys logs this error. Only returned for GUI error notification.
     271           0 :         LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strprintf("Could not allocate txin %s:%s for masternode %s", strTxHash, strOutputIndex, strService));
     272           0 :         return false;
     273             :     }
     274             : 
     275          14 :     int nPort = 0;
     276          14 :     int nDefaultPort = Params().GetDefaultPort();
     277          28 :     std::string strHost;
     278          28 :     SplitHostPort(strService, nPort, strHost);
     279          14 :     if (nPort == 0) nPort = nDefaultPort;
     280          28 :     CService _service(LookupNumeric(strHost.c_str(), nPort));
     281             : 
     282             :     // The service needs the correct default port to work properly
     283          42 :     if (!CheckDefaultPort(_service, strErrorRet, "CMasternodeBroadcast::Create"))
     284             :         return false;
     285             : 
     286          28 :     CTxIn txin(collateralOut.hash, collateralOut.n);
     287          14 :     return Create(txin, _service, keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, mnbRet);
     288             : }
     289             : 
     290          14 : bool CMasternodeBroadcast::Create(const CTxIn& txin,
     291             :                                   const CService& service,
     292             :                                   const CKey& keyCollateralAddressNew,
     293             :                                   const CPubKey& pubKeyCollateralAddressNew,
     294             :                                   const CKey& keyMasternodeNew,
     295             :                                   const CPubKey& pubKeyMasternodeNew,
     296             :                                   std::string& strErrorRet,
     297             :                                   CMasternodeBroadcast& mnbRet)
     298             : {
     299             :     // wait for reindex and/or import to finish
     300          14 :     if (fImporting || fReindex) return false;
     301             : 
     302          42 :     LogPrint(BCLog::MASTERNODE, "CMasternodeBroadcast::Create -- pubKeyCollateralAddressNew = %s, pubKeyMasternodeNew.GetID() = %s\n",
     303             :              EncodeDestination(pubKeyCollateralAddressNew.GetID()),
     304             :         pubKeyMasternodeNew.GetID().ToString());
     305             : 
     306             :     // Get block hash to ping (TODO: move outside of this function)
     307          14 :     const uint256& nBlockHashToPing = mnodeman.GetBlockHashToPing();
     308          28 :     CMasternodePing mnp(txin, nBlockHashToPing, GetAdjustedTime());
     309          14 :     if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew.GetID())) {
     310           0 :         strErrorRet = strprintf("Failed to sign ping, masternode=%s", txin.prevout.hash.ToString());
     311           0 :         LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
     312           0 :         mnbRet = CMasternodeBroadcast();
     313           0 :         return false;
     314             :     }
     315             : 
     316          28 :     mnbRet = CMasternodeBroadcast(service, txin, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION, mnp);
     317             : 
     318          14 :     if (!mnbRet.IsValidNetAddr()) {
     319           0 :         strErrorRet = strprintf("Invalid IP address %s, masternode=%s", mnbRet.addr.ToStringIP (), txin.prevout.hash.ToString());
     320           0 :         LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
     321           0 :         mnbRet = CMasternodeBroadcast();
     322           0 :         return false;
     323             :     }
     324             : 
     325          14 :     if (!mnbRet.Sign(keyCollateralAddressNew, pubKeyCollateralAddressNew)) {
     326           0 :         strErrorRet = strprintf("Failed to sign broadcast, masternode=%s", txin.prevout.hash.ToString());
     327           0 :         LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
     328           0 :         mnbRet = CMasternodeBroadcast();
     329           0 :         return false;
     330             :     }
     331             : 
     332             :     return true;
     333             : }
     334             : 
     335          14 : bool CMasternodeBroadcast::Sign(const CKey& key, const CPubKey& pubKey)
     336             : {
     337          28 :     std::string strError = "";
     338          14 :     nMessVersion = MessageVersion::MESS_VER_HASH;
     339          28 :     const std::string strMessage = GetSignatureHash().GetHex();
     340             : 
     341          14 :     if (!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
     342           0 :         return error("%s : SignMessage() (nMessVersion=%d) failed", __func__, nMessVersion);
     343             :     }
     344             : 
     345          14 :     if (!CMessageSigner::VerifyMessage(pubKey, vchSig, strMessage, strError)) {
     346           0 :         return error("%s : VerifyMessage() (nMessVersion=%d) failed, error: %s\n",
     347           0 :                 __func__, nMessVersion, strError);
     348             :     }
     349             : 
     350             :     return true;
     351             : }
     352             : 
     353          68 : bool CMasternodeBroadcast::CheckSignature() const
     354             : {
     355         136 :     std::string strError = "";
     356          68 :     std::string strMessage = (
     357          68 :                             nMessVersion == MessageVersion::MESS_VER_HASH ?
     358          68 :                             GetSignatureHash().GetHex() :
     359           0 :                             GetStrMessage()
     360         204 :                             );
     361             : 
     362          68 :     if(!CMessageSigner::VerifyMessage(pubKeyCollateralAddress, vchSig, strMessage, strError))
     363           0 :         return error("%s : VerifyMessage (nMessVersion=%d) failed: %s", __func__, nMessVersion, strError);
     364             : 
     365             :     return true;
     366             : }
     367             : 
     368          14 : bool CMasternodeBroadcast::CheckDefaultPort(CService service, std::string& strErrorRet, const std::string& strContext)
     369             : {
     370          14 :     int nDefaultPort = Params().GetDefaultPort();
     371             : 
     372          14 :     if (service.GetPort() != nDefaultPort && !Params().IsRegTestNet()) {
     373           0 :         strErrorRet = strprintf("Invalid port %u for masternode %s, only %d is supported on %s-net.",
     374           0 :             service.GetPort(), service.ToString(), nDefaultPort, Params().NetworkIDString());
     375           0 :         LogPrintf("%s - %s\n", strContext, strErrorRet);
     376           0 :         return false;
     377             :     }
     378             : 
     379             :     return true;
     380             : }
     381             : 
     382          68 : bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
     383             : {
     384             :     // make sure signature isn't in the future (past is OK)
     385          68 :     if (sigTime > GetMaxTimeWindow()) {
     386           0 :         LogPrint(BCLog::MASTERNODE,"mnb - Signature rejected, too far into the future %s\n", vin.prevout.hash.ToString());
     387           0 :         nDos = 1;
     388           0 :         return false;
     389             :     }
     390             : 
     391             :     // reject old signature version
     392          68 :     if (nMessVersion != MessageVersion::MESS_VER_HASH) {
     393           0 :         LogPrint(BCLog::MASTERNODE, "mnb - rejecting old message version for mn %s\n", vin.prevout.hash.ToString());
     394           0 :         nDos = 30;
     395           0 :         return false;
     396             :     }
     397             : 
     398          68 :     if (protocolVersion < ActiveProtocol()) {
     399           0 :         LogPrint(BCLog::MASTERNODE,"mnb - ignoring outdated Masternode %s protocol version %d\n", vin.prevout.hash.ToString(), protocolVersion);
     400           0 :         return false;
     401             :     }
     402             : 
     403         136 :     CScript pubkeyScript;
     404          68 :     pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID());
     405             : 
     406          68 :     if (pubkeyScript.size() != 25) {
     407           0 :         LogPrint(BCLog::MASTERNODE,"mnb - pubkey the wrong size\n");
     408           0 :         nDos = 100;
     409           0 :         return false;
     410             :     }
     411             : 
     412         136 :     CScript pubkeyScript2;
     413          68 :     pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID());
     414             : 
     415          68 :     if (pubkeyScript2.size() != 25) {
     416           0 :         LogPrint(BCLog::MASTERNODE,"mnb - pubkey2 the wrong size\n");
     417           0 :         nDos = 100;
     418           0 :         return false;
     419             :     }
     420             : 
     421          68 :     if (!vin.scriptSig.empty()) {
     422           0 :         LogPrint(BCLog::MASTERNODE,"mnb - Ignore Not Empty ScriptSig %s\n", vin.prevout.hash.ToString());
     423           0 :         return false;
     424             :     }
     425             : 
     426         136 :     std::string strError = "";
     427          68 :     if (!CheckSignature()) {
     428             :         // For now (till v6.0), let's be "naive" and not fully ban nodes when the node is syncing
     429             :         // This could be a bad parsed BIP155 address that got stored on db on an old software version.
     430           0 :         nDos = g_tiertwo_sync_state.IsSynced() ? 100 : 5;
     431           0 :         return error("%s : Got bad Masternode address signature", __func__);
     432             :     }
     433             : 
     434         136 :     if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
     435           0 :         if (addr.GetPort() != 51472) return false;
     436          68 :     } else if (addr.GetPort() == 51472)
     437             :         return false;
     438             : 
     439             :     // incorrect ping or its sigTime
     440          68 :     if(lastPing.IsNull() || !lastPing.CheckAndUpdate(nDos, false, true)) {
     441           0 :         return false;
     442             :     }
     443             : 
     444             :     //search existing Masternode list, this is where we update existing Masternodes with new mnb broadcasts
     445          68 :     CMasternode* pmn = mnodeman.Find(vin.prevout);
     446             : 
     447             :     // no such masternode, nothing to update
     448          68 :     if (pmn == nullptr) return true;
     449             : 
     450             :     // this broadcast is older or equal than the one that we already have - it's bad and should never happen
     451             :     // unless someone is doing something fishy
     452             :     // (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates)
     453          10 :     if(pmn->sigTime >= sigTime) {
     454           0 :         return error("%s : Bad sigTime %d for Masternode %20s %105s (existing broadcast is at %d)",
     455           0 :                       __func__, sigTime, addr.ToString(), vin.ToString(), pmn->sigTime);
     456             :     }
     457             : 
     458             :     // masternode is not enabled yet/already, nothing to update
     459          10 :     if (!pmn->IsEnabled()) return true;
     460             : 
     461             :     // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
     462             :     //   after that they just need to match
     463          10 :     if (pmn->pubKeyCollateralAddress == pubKeyCollateralAddress && !pmn->IsBroadcastedWithin(MasternodeBroadcastSeconds())) {
     464             :         //take the newest entry
     465          20 :         LogPrint(BCLog::MASTERNODE,"mnb - Got updated entry for %s\n", vin.prevout.hash.ToString());
     466          10 :         if (pmn->UpdateFromNewBroadcast((*this))) {
     467          10 :             if (pmn->IsEnabled()) Relay();
     468             :         }
     469          10 :         g_tiertwo_sync_state.AddedMasternodeList(GetHash());
     470             :     }
     471             : 
     472             :     return true;
     473             : }
     474             : 
     475          78 : void CMasternodeBroadcast::Relay()
     476             : {
     477          78 :     CInv inv(MSG_MASTERNODE_ANNOUNCE, GetHash());
     478          78 :     g_connman->RelayInv(inv);
     479          78 : }
     480             : 
     481        2872 : uint256 CMasternodeBroadcast::GetHash() const
     482             : {
     483        2872 :     CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
     484        2872 :     ss << sigTime;
     485        2872 :     ss << pubKeyCollateralAddress;
     486        2872 :     return ss.GetHash();
     487             : }
     488             : 
     489       63948 : CMasternodePing::CMasternodePing() :
     490             :         CSignedMessage(),
     491             :         vin(),
     492             :         blockHash(),
     493       63948 :         sigTime(0)
     494       63948 : { }
     495             : 
     496        4455 : CMasternodePing::CMasternodePing(const CTxIn& newVin, const uint256& nBlockHash, uint64_t _sigTime) :
     497             :         CSignedMessage(),
     498             :         vin(newVin),
     499             :         blockHash(nBlockHash),
     500        4455 :         sigTime(_sigTime)
     501        4455 : { }
     502             : 
     503      164288 : uint256 CMasternodePing::GetHash() const
     504             : {
     505      164288 :     CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
     506      164288 :     ss << vin;
     507      164288 :     if (nMessVersion == MessageVersion::MESS_VER_HASH) ss << blockHash;
     508      164288 :     ss << sigTime;
     509      164288 :     return ss.GetHash();
     510             : }
     511             : 
     512           0 : std::string CMasternodePing::GetStrMessage() const
     513             : {
     514           0 :     return vin.ToString() + blockHash.ToString() + std::to_string(sigTime);
     515             : }
     516             : 
     517       52269 : bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireAvailable, bool fCheckSigTimeOnly)
     518             : {
     519       52269 :     if (sigTime > GetMaxTimeWindow()) {
     520           0 :         LogPrint(BCLog::MNPING,"%s: Signature rejected, too far into the future %s\n", __func__, vin.prevout.hash.ToString());
     521           0 :         nDos = 30;
     522           0 :         return false;
     523             :     }
     524             : 
     525       52269 :     if (sigTime <= GetAdjustedTime() - 60 * 60) {
     526           0 :         LogPrint(BCLog::MNPING,"%s: Signature rejected, too far into the past %s - %d %d \n", __func__, vin.prevout.hash.ToString(), sigTime, GetAdjustedTime());
     527           0 :         nDos = 30;
     528           0 :         return false;
     529             :     }
     530             : 
     531             :     // reject old signature version
     532       52269 :     if (nMessVersion != MessageVersion::MESS_VER_HASH) {
     533           0 :         LogPrint(BCLog::MNPING, "mnp - rejecting old message version for mn %s\n", vin.prevout.hash.ToString());
     534           0 :         nDos = 30;
     535           0 :         return false;
     536             :     }
     537             : 
     538             :     // Check if the ping block hash exists and it's within 24 blocks from the tip
     539       52269 :     if (!mnodeman.IsWithinDepth(blockHash, 2 * MNPING_DEPTH)) {
     540           3 :         LogPrint(BCLog::MNPING,"%s: Masternode %s block hash %s is too old or has an invalid block hash\n",
     541             :                                         __func__, vin.prevout.hash.ToString(), blockHash.ToString());
     542             :         // don't ban peers relaying stale data before the active protocol enforcement
     543           1 :         nDos = 33;
     544           1 :         return false;
     545             :     }
     546             : 
     547             :     // see if we have this Masternode
     548       52268 :     CMasternode* pmn = mnodeman.Find(vin.prevout);
     549       52268 :     const bool isMasternodeFound = (pmn != nullptr);
     550       52268 :     const bool isSignatureValid = (isMasternodeFound && CheckSignature(pmn->pubKeyMasternode.GetID()));
     551             : 
     552       52268 :     if(fCheckSigTimeOnly) {
     553         136 :         if (isMasternodeFound && !isSignatureValid) {
     554           0 :             nDos = 33;
     555           0 :             return false;
     556             :         }
     557             :         return true;
     558             :     }
     559             : 
     560      156396 :     LogPrint(BCLog::MNPING, "%s: New Ping - %s - %s - %lli\n", __func__, GetHash().ToString(), blockHash.ToString(), sigTime);
     561             : 
     562       52132 :     if (isMasternodeFound && pmn->protocolVersion >= ActiveProtocol()) {
     563             : 
     564             :         // Update ping only if the masternode is in available state (pre-enabled or enabled)
     565        4252 :         if (fRequireAvailable && !pmn->IsAvailableState()) {
     566           5 :             nDos = 20;
     567           5 :             return false;
     568             :         }
     569             : 
     570             :         // update only if there is no known ping for this masternode or
     571             :         // last ping was more then MASTERNODE_MIN_MNP_SECONDS-60 ago comparing to this one
     572        2127 :         if (!pmn->IsPingedWithin(MasternodeMinPingSeconds() - 60, sigTime)) {
     573        2115 :             if (!isSignatureValid) {
     574           0 :                 nDos = 33;
     575           0 :                 return false;
     576             :             }
     577             : 
     578             :             // ping have passed the basic checks, can be updated now
     579        2115 :             mnodeman.mapSeenMasternodePing.emplace(GetHash(), *this);
     580             : 
     581             :             // SetLastPing locks masternode cs. Be careful with the lock ordering.
     582        2115 :             pmn->SetLastPing(*this);
     583             : 
     584             :             //mnodeman.mapSeenMasternodeBroadcast.lastPing is probably outdated, so we'll update it
     585        4230 :             CMasternodeBroadcast mnb(*pmn);
     586        2115 :             const uint256& hash = mnb.GetHash();
     587        2115 :             if (mnodeman.mapSeenMasternodeBroadcast.count(hash)) {
     588        2115 :                 mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = *this;
     589             :             }
     590             : 
     591        2115 :             if (!pmn->IsEnabled()) return false;
     592             : 
     593        4168 :             LogPrint(BCLog::MNPING, "%s: Masternode ping accepted, vin: %s\n", __func__, vin.prevout.hash.ToString());
     594             : 
     595        2084 :             Relay();
     596             :             return true;
     597             :         }
     598          24 :         LogPrint(BCLog::MNPING, "%s: Masternode ping arrived too early, vin: %s\n", __func__, vin.prevout.hash.ToString());
     599             :         //nDos = 1; //disable, this is happening frequently and causing banned peers
     600          12 :         return false;
     601             :     }
     602      100000 :     LogPrint(BCLog::MNPING, "%s: Couldn't find compatible Masternode entry, vin: %s\n", __func__, vin.prevout.hash.ToString());
     603             : 
     604             :     return false;
     605             : }
     606             : 
     607        2566 : void CMasternodePing::Relay()
     608             : {
     609        2566 :     CInv inv(MSG_MASTERNODE_PING, GetHash());
     610        2566 :     g_connman->RelayInv(inv);
     611        2566 : }
     612             : 
     613        3830 : MasternodeRef MakeMasternodeRefForDMN(const CDeterministicMNCPtr& dmn)
     614             : {
     615             :     // create legacy masternode for DMN
     616        3830 :     int refHeight = std::max(dmn->pdmnState->nRegisteredHeight, dmn->pdmnState->nPoSeRevivedHeight);
     617       15320 :     const CBlockIndex* pindex = WITH_LOCK(cs_main, return mapBlockIndex.at(chainActive[refHeight]->GetBlockHash()); );
     618        3830 :     return std::make_shared<CMasternode>(CMasternode(dmn, pindex->GetBlockTime(), pindex->GetBlockHash()));
     619             : }

Generated by: LCOV version 1.14