PIVX Core  5.6.99
P2P Digital Currency
masternodeman.cpp
Go to the documentation of this file.
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 "masternodeman.h"
7 
8 #include "addrman.h"
9 #include "evo/deterministicmns.h"
10 #include "fs.h"
11 #include "masternode-payments.h"
12 #include "masternode-sync.h"
13 #include "masternode.h"
14 #include "messagesigner.h"
15 #include "netbase.h"
16 #include "netmessagemaker.h"
17 #include "shutdown.h"
18 #include "spork.h"
20 #include "validation.h"
21 
22 #include <boost/thread/thread.hpp>
23 
24 #define MN_WINNER_MINIMUM_AGE 8000 // Age in seconds. This should be > MASTERNODE_REMOVAL_SECONDS to avoid misconfigured new nodes in the list.
25 
30 
32  template <typename T>
33  bool operator()(const std::pair<int64_t, T>& t1,
34  const std::pair<int64_t, T>& t2) const
35  {
36  return t1.first < t2.first;
37  }
38 };
39 
40 //
41 // CMasternodeDB
42 //
43 
44 static const int MASTERNODE_DB_VERSION_BIP155 = 2;
45 
47 {
48  pathMN = GetDataDir() / "mncache.dat";
49  strMagicMessage = "MasternodeCache";
50 }
51 
52 bool CMasternodeDB::Write(const CMasternodeMan& mnodemanToSave)
53 {
54  int64_t nStart = GetTimeMillis();
55  const auto& params = Params();
56 
57  // serialize, checksum data up to that point, then append checksum
58  // Always done in the latest format.
59  CDataStream ssMasternodes(SER_DISK, CLIENT_VERSION | ADDRV2_FORMAT);
60  ssMasternodes << MASTERNODE_DB_VERSION_BIP155;
61  ssMasternodes << strMagicMessage; // masternode cache file specific magic message
62  ssMasternodes << params.MessageStart(); // network specific magic number
63  ssMasternodes << mnodemanToSave;
64  uint256 hash = Hash(ssMasternodes.begin(), ssMasternodes.end());
65  ssMasternodes << hash;
66 
67  // open output file, and associate with CAutoFile
68  FILE* file = fsbridge::fopen(pathMN, "wb");
69  CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
70  if (fileout.IsNull())
71  return error("%s : Failed to open file %s", __func__, pathMN.string());
72 
73  // Write and commit header, data
74  try {
75  fileout << ssMasternodes;
76  } catch (const std::exception& e) {
77  return error("%s : Serialize or I/O error - %s", __func__, e.what());
78  }
79  // FileCommit(fileout);
80  fileout.fclose();
81 
82  LogPrint(BCLog::MASTERNODE,"Written info to mncache.dat %dms\n", GetTimeMillis() - nStart);
83  LogPrint(BCLog::MASTERNODE," %s\n", mnodemanToSave.ToString());
84 
85  return true;
86 }
87 
89 {
90  int64_t nStart = GetTimeMillis();
91  // open input file, and associate with CAutoFile
92  FILE* file = fsbridge::fopen(pathMN, "rb");
93  CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
94  if (filein.IsNull()) {
95  error("%s : Failed to open file %s", __func__, pathMN.string());
96  return FileError;
97  }
98 
99  // use file size to size memory buffer
100  int fileSize = fs::file_size(pathMN);
101  int dataSize = fileSize - sizeof(uint256);
102  // Don't try to resize to a negative number if file is small
103  if (dataSize < 0)
104  dataSize = 0;
105  std::vector<unsigned char> vchData;
106  vchData.resize(dataSize);
107  uint256 hashIn;
108 
109  // read data and checksum from file
110  try {
111  filein.read((char*)vchData.data(), dataSize);
112  filein >> hashIn;
113  } catch (const std::exception& e) {
114  error("%s : Deserialize or I/O error - %s", __func__, e.what());
115  return HashReadError;
116  }
117  filein.fclose();
118 
119  const auto& params = Params();
120  // serialize, checksum data up to that point, then append checksum
121  CDataStream ssMasternodes(vchData, SER_DISK, CLIENT_VERSION);
122 
123  // verify stored checksum matches input data
124  uint256 hashTmp = Hash(ssMasternodes.begin(), ssMasternodes.end());
125  if (hashIn != hashTmp) {
126  error("%s : Checksum mismatch, data corrupted", __func__);
127  return IncorrectHash;
128  }
129 
130  int version;
131  std::string strMagicMessageTmp;
132  try {
133  // de-serialize file header
134  ssMasternodes >> version;
135  ssMasternodes >> strMagicMessageTmp;
136 
137  // ... verify the message matches predefined one
138  if (strMagicMessage != strMagicMessageTmp) {
139  error("%s : Invalid masternode cache magic message", __func__);
140  return IncorrectMagicMessage;
141  }
142 
143  // de-serialize file header (network specific magic number) and ..
144  std::vector<unsigned char> pchMsgTmp(4);
145  ssMasternodes >> MakeSpan(pchMsgTmp);
146 
147  // ... verify the network matches ours
148  if (memcmp(pchMsgTmp.data(), params.MessageStart(), pchMsgTmp.size()) != 0) {
149  error("%s : Invalid network magic number", __func__);
150  return IncorrectMagicNumber;
151  }
152  // de-serialize data into CMasternodeMan object.
153  if (version == MASTERNODE_DB_VERSION_BIP155) {
154  OverrideStream<CDataStream> s(&ssMasternodes, ssMasternodes.GetType(), ssMasternodes.GetVersion() | ADDRV2_FORMAT);
155  s >> mnodemanToLoad;
156  } else {
157  // Old format
158  ssMasternodes >> mnodemanToLoad;
159  }
160  } catch (const std::exception& e) {
161  mnodemanToLoad.Clear();
162  error("%s : Deserialize or I/O error - %s", __func__, e.what());
163  return IncorrectFormat;
164  }
165 
166  LogPrint(BCLog::MASTERNODE,"Loaded info from mncache.dat (dbversion=%d) %dms\n", version, GetTimeMillis() - nStart);
167  LogPrint(BCLog::MASTERNODE," %s\n", mnodemanToLoad.ToString());
168 
169  return Ok;
170 }
171 
173 {
174  int64_t nStart = GetTimeMillis();
175 
176  CMasternodeDB mndb;
177  LogPrint(BCLog::MASTERNODE,"Writing info to mncache.dat...\n");
178  mndb.Write(mnodeman);
179 
180  LogPrint(BCLog::MASTERNODE,"Masternode dump finished %dms\n", GetTimeMillis() - nStart);
181 }
182 
184  cvLastBlockHashes(CACHED_BLOCK_HASHES, UINT256_ZERO),
185  nDsqCount(0)
186 {}
187 
189 {
190  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
191  if (deterministicMNManager->LegacyMNObsolete()) {
192  return false;
193  }
194 
195  if (deterministicMNManager->GetListAtChainTip().HasMNByCollateral(mn.vin.prevout)) {
196  LogPrint(BCLog::MASTERNODE, "ERROR: Not Adding Masternode %s as the collateral is already registered with a DMN\n",
197  mn.vin.prevout.ToString());
198  return false;
199  }
200 
201  LOCK(cs);
202 
203  if (!mn.IsAvailableState())
204  return false;
205 
206  const auto& it = mapMasternodes.find(mn.vin.prevout);
207  if (it == mapMasternodes.end()) {
208  LogPrint(BCLog::MASTERNODE, "Adding new Masternode %s\n", mn.vin.prevout.ToString());
209  mapMasternodes.emplace(mn.vin.prevout, std::make_shared<CMasternode>(mn));
210  LogPrint(BCLog::MASTERNODE, "Masternode added. New total count: %d\n", mapMasternodes.size());
211  return true;
212  }
213 
214  return false;
215 }
216 
217 void CMasternodeMan::AskForMN(CNode* pnode, const CTxIn& vin)
218 {
219  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
220  if (deterministicMNManager->LegacyMNObsolete()) {
221  return;
222  }
223 
224  std::map<COutPoint, int64_t>::iterator i = mWeAskedForMasternodeListEntry.find(vin.prevout);
225  if (i != mWeAskedForMasternodeListEntry.end()) {
226  int64_t t = (*i).second;
227  if (GetTime() < t) return; // we've asked recently
228  }
229 
230  // ask for the mnb info once from the node that sent mnp
231 
232  LogPrint(BCLog::MASTERNODE, "CMasternodeMan::AskForMN - Asking node for missing entry, vin: %s\n", vin.prevout.hash.ToString());
233  g_connman->PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::GETMNLIST, vin));
234  int64_t askAgain = GetTime() + MasternodeMinPingSeconds();
235  mWeAskedForMasternodeListEntry[vin.prevout] = askAgain;
236 }
237 
238 int CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval)
239 {
240  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
241  if (deterministicMNManager->LegacyMNObsolete()) {
242  LogPrint(BCLog::MASTERNODE, "Removing all legacy mn due to SPORK 21\n");
243  Clear();
244  return 0;
245  }
246 
247  LOCK(cs);
248 
249  //remove inactive and outdated (or replaced by DMN)
250  auto it = mapMasternodes.begin();
251  while (it != mapMasternodes.end()) {
252  MasternodeRef& mn = it->second;
253  auto activeState = mn->GetActiveState();
254  if (activeState == CMasternode::MASTERNODE_REMOVE ||
255  activeState == CMasternode::MASTERNODE_VIN_SPENT ||
256  (forceExpiredRemoval && activeState == CMasternode::MASTERNODE_EXPIRED) ||
257  mn->protocolVersion < ActiveProtocol()) {
258  LogPrint(BCLog::MASTERNODE, "Removing inactive (legacy) Masternode %s\n", it->first.ToString());
259  //erase all of the broadcasts we've seen from this vin
260  // -- if we missed a few pings and the node was removed, this will allow is to get it back without them
261  // sending a brand new mnb
262  std::map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
263  while (it3 != mapSeenMasternodeBroadcast.end()) {
264  if (it3->second.vin.prevout == it->first) {
265  g_tiertwo_sync_state.EraseSeenMNB((*it3).first);
266  it3 = mapSeenMasternodeBroadcast.erase(it3);
267  } else {
268  ++it3;
269  }
270  }
271 
272  // allow us to ask for this masternode again if we see another ping
273  std::map<COutPoint, int64_t>::iterator it2 = mWeAskedForMasternodeListEntry.begin();
274  while (it2 != mWeAskedForMasternodeListEntry.end()) {
275  if (it2->first == it->first) {
276  it2 = mWeAskedForMasternodeListEntry.erase(it2);
277  } else {
278  ++it2;
279  }
280  }
281 
282  // clean MN pings right away.
283  auto itPing = mapSeenMasternodePing.begin();
284  while (itPing != mapSeenMasternodePing.end()) {
285  if (itPing->second.GetVin().prevout == it->first) {
286  itPing = mapSeenMasternodePing.erase(itPing);
287  } else {
288  ++itPing;
289  }
290  }
291 
292  it = mapMasternodes.erase(it);
293  LogPrint(BCLog::MASTERNODE, "Masternode removed.\n");
294  } else {
295  ++it;
296  }
297  }
298  LogPrint(BCLog::MASTERNODE, "New total masternode count: %d\n", mapMasternodes.size());
299 
300  // check who's asked for the Masternode list
301  std::map<CNetAddr, int64_t>::iterator it1 = mAskedUsForMasternodeList.begin();
302  while (it1 != mAskedUsForMasternodeList.end()) {
303  if ((*it1).second < GetTime()) {
304  it1 = mAskedUsForMasternodeList.erase(it1);
305  } else {
306  ++it1;
307  }
308  }
309 
310  // check who we asked for the Masternode list
311  it1 = mWeAskedForMasternodeList.begin();
312  while (it1 != mWeAskedForMasternodeList.end()) {
313  if ((*it1).second < GetTime()) {
314  it1 = mWeAskedForMasternodeList.erase(it1);
315  } else {
316  ++it1;
317  }
318  }
319 
320  // check which Masternodes we've asked for
321  std::map<COutPoint, int64_t>::iterator it2 = mWeAskedForMasternodeListEntry.begin();
322  while (it2 != mWeAskedForMasternodeListEntry.end()) {
323  if ((*it2).second < GetTime()) {
324  it2 = mWeAskedForMasternodeListEntry.erase(it2);
325  } else {
326  ++it2;
327  }
328  }
329 
330  // remove expired mapSeenMasternodeBroadcast
331  std::map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
332  while (it3 != mapSeenMasternodeBroadcast.end()) {
333  if ((*it3).second.lastPing.sigTime < GetTime() - (MasternodeRemovalSeconds() * 2)) {
334  g_tiertwo_sync_state.EraseSeenMNB((*it3).second.GetHash());
335  it3 = mapSeenMasternodeBroadcast.erase(it3);
336  } else {
337  ++it3;
338  }
339  }
340 
341  // remove expired mapSeenMasternodePing
342  std::map<uint256, CMasternodePing>::iterator it4 = mapSeenMasternodePing.begin();
343  while (it4 != mapSeenMasternodePing.end()) {
344  if ((*it4).second.sigTime < GetTime() - (MasternodeRemovalSeconds() * 2)) {
345  it4 = mapSeenMasternodePing.erase(it4);
346  } else {
347  ++it4;
348  }
349  }
350 
351  return mapMasternodes.size();
352 }
353 
355 {
356  LOCK(cs);
357  mapMasternodes.clear();
362  mapSeenMasternodePing.clear();
363  nDsqCount = 0;
364 }
365 
366 static void CountNetwork(const CService& addr, int& ipv4, int& ipv6, int& onion)
367 {
368  std::string strHost;
369  int port;
370  SplitHostPort(addr.ToString(), port, strHost);
371  CNetAddr node;
372  LookupHost(strHost, node, false);
373  switch(node.GetNetwork()) {
374  case NET_IPV4:
375  ipv4++;
376  break;
377  case NET_IPV6:
378  ipv6++;
379  break;
380  case NET_ONION:
381  onion++;
382  break;
383  default:
384  break;
385  }
386 }
387 
389 {
390  MNsInfo info;
391  int nMinProtocol = ActiveProtocol();
393 
394  // legacy masternodes
395  {
396  LOCK(cs);
397  for (const auto& it : mapMasternodes) {
398  const MasternodeRef& mn = it.second;
399  info.total++;
400  CountNetwork(mn->addr, info.ipv4, info.ipv6, info.onion);
401  if (mn->protocolVersion < nMinProtocol || !mn->IsEnabled()) {
402  continue;
403  }
404  info.enabledSize++;
405  // Eligible for payments
406  if (spork_8_active && (GetAdjustedTime() - mn->sigTime < MN_WINNER_MINIMUM_AGE)) {
407  continue; // Skip masternodes younger than (default) 8000 sec (MUST be > MASTERNODE_REMOVAL_SECONDS)
408  }
409  info.stableSize++;
410  }
411  }
412 
413  // deterministic masternodes
414  if (deterministicMNManager->IsDIP3Enforced()) {
415  auto mnList = deterministicMNManager->GetListAtChainTip();
416  mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
417  info.total++;
418  CountNetwork(dmn->pdmnState->addr, info.ipv4, info.ipv6, info.onion);
419  if (!dmn->IsPoSeBanned()) {
420  info.enabledSize++;
421  info.stableSize++;
422  }
423  });
424  }
425 
426  return info;
427 }
428 
429 int CMasternodeMan::CountEnabled(bool only_legacy) const
430 {
431  int count_enabled = 0;
432  int protocolVersion = ActiveProtocol();
433 
434  {
435  LOCK(cs);
436  for (const auto& it : mapMasternodes) {
437  const MasternodeRef& mn = it.second;
438  if (mn->protocolVersion < protocolVersion || !mn->IsEnabled()) continue;
439  count_enabled++;
440  }
441  }
442 
443  if (!only_legacy && deterministicMNManager->IsDIP3Enforced()) {
444  count_enabled += deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
445  }
446 
447  return count_enabled;
448 }
449 
451 {
452  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
453  if (deterministicMNManager->LegacyMNObsolete()) {
454  return false;
455  }
456 
457  LOCK(cs);
458  if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
459  if (!(pnode->addr.IsRFC1918() || pnode->addr.IsLocal())) {
460  std::map<CNetAddr, int64_t>::iterator it = mWeAskedForMasternodeList.find(pnode->addr);
461  if (it != mWeAskedForMasternodeList.end()) {
462  if (GetTime() < (*it).second) {
463  LogPrint(BCLog::MASTERNODE, "dseg - we already asked peer %i for the list; skipping...\n", pnode->GetId());
464  return false;
465  }
466  }
467  }
468  }
469 
470  g_connman->PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::GETMNLIST, CTxIn()));
471  int64_t askAgain = GetTime() + MASTERNODES_REQUEST_SECONDS;
472  mWeAskedForMasternodeList[pnode->addr] = askAgain;
473  return true;
474 }
475 
477 {
478  LOCK(cs);
479  auto it = mapMasternodes.find(collateralOut);
480  return it != mapMasternodes.end() ? it->second.get() : nullptr;
481 }
482 
483 const CMasternode* CMasternodeMan::Find(const COutPoint& collateralOut) const
484 {
485  LOCK(cs);
486  auto const& it = mapMasternodes.find(collateralOut);
487  return it != mapMasternodes.end() ? it->second.get() : nullptr;
488 }
489 
490 CMasternode* CMasternodeMan::Find(const CPubKey& pubKeyMasternode)
491 {
492  LOCK(cs);
493 
494  for (auto& it : mapMasternodes) {
495  MasternodeRef& mn = it.second;
496  if (mn->pubKeyMasternode == pubKeyMasternode)
497  return mn.get();
498  }
499  return nullptr;
500 }
501 
502 void CMasternodeMan::CheckSpentCollaterals(const std::vector<CTransactionRef>& vtx)
503 {
504  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
505  if (deterministicMNManager->LegacyMNObsolete()) {
506  return;
507  }
508 
509  LOCK(cs);
510  for (const auto& tx : vtx) {
511  for (const auto& in : tx->vin) {
512  auto it = mapMasternodes.find(in.prevout);
513  if (it != mapMasternodes.end()) {
514  it->second->SetSpent();
515  }
516  }
517  }
518 }
519 
520 static bool canScheduleMN(bool fFilterSigTime, const MasternodeRef& mn, int minProtocol,
521  int nMnCount, int nBlockHeight)
522 {
523  // check protocol version
524  if (mn->protocolVersion < minProtocol) return false;
525 
526  // it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
527  if (masternodePayments.IsScheduled(*mn, nBlockHeight)) return false;
528 
529  // it's too new, wait for a cycle
530  if (fFilterSigTime && mn->sigTime + (nMnCount * 2.6 * 60) > GetAdjustedTime()) return false;
531 
532  // make sure it has as many confirmations as there are masternodes
533  if (pcoinsTip->GetCoinDepthAtHeight(mn->vin.prevout, nBlockHeight) < nMnCount) return false;
534 
535  return true;
536 }
537 
538 //
539 // Deterministically select the oldest/best masternode to pay on the network
540 //
541 MasternodeRef CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount, const CBlockIndex* pChainTip) const
542 {
543  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
544  if (deterministicMNManager->LegacyMNObsolete(nBlockHeight)) {
545  LogPrintf("%s: ERROR - called after legacy system disabled\n", __func__);
546  return nullptr;
547  }
548 
550  const CBlockIndex* BlockReading = (pChainTip == nullptr ? GetChainTip() : pChainTip);
551  if (!BlockReading) return nullptr;
552 
553  MasternodeRef pBestMasternode = nullptr;
554  std::vector<std::pair<int64_t, MasternodeRef> > vecMasternodeLastPaid;
555 
556  /*
557  Make a vector with all of the last paid times
558  */
559  int minProtocol = ActiveProtocol();
560  int count_enabled = CountEnabled();
561  {
562  LOCK(cs);
563  for (const auto& it : mapMasternodes) {
564  if (!it.second->IsEnabled()) continue;
565  if (canScheduleMN(fFilterSigTime, it.second, minProtocol, count_enabled, nBlockHeight)) {
566  vecMasternodeLastPaid.emplace_back(SecondsSincePayment(it.second, count_enabled, BlockReading), it.second);
567  }
568  }
569  }
570  // Add deterministic masternodes to the vector
571  if (deterministicMNManager->IsDIP3Enforced()) {
572  CDeterministicMNList mnList = deterministicMNManager->GetListAtChainTip();
573  mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
574  const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
575  if (canScheduleMN(fFilterSigTime, mn, minProtocol, count_enabled, nBlockHeight)) {
576  vecMasternodeLastPaid.emplace_back(SecondsSincePayment(mn, count_enabled, BlockReading), mn);
577  }
578  });
579  }
580 
581  nCount = (int)vecMasternodeLastPaid.size();
582 
583  //when the network is in the process of upgrading, don't penalize nodes that recently restarted
584  if (fFilterSigTime && nCount < count_enabled / 3) return GetNextMasternodeInQueueForPayment(nBlockHeight, false, nCount, BlockReading);
585 
586  // Sort them high to low
587  sort(vecMasternodeLastPaid.rbegin(), vecMasternodeLastPaid.rend(), CompareScoreMN());
588 
589  // Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
590  // -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
591  // -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2
592  // -- (chance per block * chances before IsScheduled will fire)
593  int nTenthNetwork = count_enabled / 10;
594  int nCountTenth = 0;
596  const uint256& hash = GetHashAtHeight(nBlockHeight - 101);
597  for (const auto& s: vecMasternodeLastPaid) {
598  const MasternodeRef pmn = s.second;
599  if (!pmn) break;
600 
601  const arith_uint256& n = pmn->CalculateScore(hash);
602  if (n > nHigh) {
603  nHigh = n;
604  pBestMasternode = pmn;
605  }
606  nCountTenth++;
607  if (nCountTenth >= nTenthNetwork) break;
608  }
609  return pBestMasternode;
610 }
611 
613 {
614  int minProtocol = ActiveProtocol();
615  int64_t score = 0;
616  MasternodeRef winner = nullptr;
617 
618  // scan for winner
619  for (const auto& it : mapMasternodes) {
620  const MasternodeRef& mn = it.second;
621  if (mn->protocolVersion < minProtocol || !mn->IsEnabled()) continue;
622  // calculate the score of the masternode
623  const int64_t n = mn->CalculateScore(hash).GetCompact(false);
624  // determine the winner
625  if (n > score) {
626  score = n;
627  winner = mn;
628  }
629  }
630 
631  // scan also dmns
632  if (deterministicMNManager->IsDIP3Enforced()) {
633  auto mnList = deterministicMNManager->GetListAtChainTip();
634  mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
635  const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
636  // calculate the score of the masternode
637  const int64_t n = mn->CalculateScore(hash).GetCompact(false);
638  // determine the winner
639  if (n > score) {
640  score = n;
641  winner = mn;
642  }
643  });
644  }
645 
646  return winner;
647 }
648 
649 std::vector<std::pair<MasternodeRef, int>> CMasternodeMan::GetMnScores(int nLast) const
650 {
651  std::vector<std::pair<MasternodeRef, int>> ret;
652  int nChainHeight = GetBestHeight();
653  if (nChainHeight < 0) return ret;
654 
655  for (int nHeight = nChainHeight - nLast; nHeight < nChainHeight + 20; nHeight++) {
656  const uint256& hash = GetHashAtHeight(nHeight - 101);
657  MasternodeRef winner = GetCurrentMasterNode(hash);
658  if (winner) {
659  ret.emplace_back(winner, nHeight);
660  }
661  }
662  return ret;
663 }
664 
665 int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight) const
666 {
667  const uint256& hash = GetHashAtHeight(nBlockHeight - 1);
668  // height outside range
669  if (hash == UINT256_ZERO) return -1;
670 
671  // scan for winner
672  int minProtocol = ActiveProtocol();
673  std::vector<std::pair<int64_t, CTxIn> > vecMasternodeScores;
674  {
675  LOCK(cs);
676  for (const auto& it : mapMasternodes) {
677  const MasternodeRef& mn = it.second;
678  if (!mn->IsEnabled()) {
679  continue; // Skip not enabled
680  }
681  if (mn->protocolVersion < minProtocol) {
682  LogPrint(BCLog::MASTERNODE,"Skipping Masternode with obsolete version %d\n", mn->protocolVersion);
683  continue; // Skip obsolete versions
684  }
686  GetAdjustedTime() - mn->sigTime < MN_WINNER_MINIMUM_AGE) {
687  continue; // Skip masternodes younger than (default) 1 hour
688  }
689  vecMasternodeScores.emplace_back(mn->CalculateScore(hash).GetCompact(false), mn->vin);
690  }
691  }
692 
693  // scan also dmns
694  if (deterministicMNManager->IsDIP3Enforced()) {
695  auto mnList = deterministicMNManager->GetListAtChainTip();
696  mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
697  const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
698  vecMasternodeScores.emplace_back(mn->CalculateScore(hash).GetCompact(false), mn->vin);
699  });
700  }
701 
702  sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
703 
704  int rank = 0;
705  for (std::pair<int64_t, CTxIn> & s : vecMasternodeScores) {
706  rank++;
707  if (s.second.prevout == vin.prevout) {
708  return rank;
709  }
710  }
711 
712  return -1;
713 }
714 
715 std::vector<std::pair<int64_t, MasternodeRef>> CMasternodeMan::GetMasternodeRanks(int nBlockHeight) const
716 {
717  std::vector<std::pair<int64_t, MasternodeRef>> vecMasternodeScores;
718  const uint256& hash = GetHashAtHeight(nBlockHeight - 1);
719  // height outside range
720  if (hash == UINT256_ZERO) return vecMasternodeScores;
721  {
722  LOCK(cs);
723  // scan for winner
724  for (const auto& it : mapMasternodes) {
725  const MasternodeRef mn = it.second;
726  const uint32_t score = mn->IsEnabled() ? mn->CalculateScore(hash).GetCompact(false) : 9999;
727 
728  vecMasternodeScores.emplace_back(score, mn);
729  }
730  }
731  // scan also dmns
732  if (deterministicMNManager->IsDIP3Enforced()) {
733  auto mnList = deterministicMNManager->GetListAtChainTip();
734  mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
735  const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
736  const uint32_t score = dmn->IsPoSeBanned() ? 9999 : mn->CalculateScore(hash).GetCompact(false);
737 
738  vecMasternodeScores.emplace_back(score, mn);
739  });
740  }
741  sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
742  return vecMasternodeScores;
743 }
744 
745 bool CMasternodeMan::CheckInputs(CMasternodeBroadcast& mnb, int nChainHeight, int& nDoS)
746 {
747  const auto& consensus = Params().GetConsensus();
748  // incorrect ping or its sigTime
749  if(mnb.lastPing.IsNull() || !mnb.lastPing.CheckAndUpdate(nDoS, false, true)) {
750  return false;
751  }
752 
753  // search existing Masternode list
754  CMasternode* pmn = Find(mnb.vin.prevout);
755  if (pmn != nullptr) {
756  // nothing to do here if we already know about this masternode and it's enabled
757  if (pmn->IsEnabled()) return true;
758  // if it's not enabled, remove old MN first and continue
759  else
760  mnodeman.Remove(pmn->vin.prevout);
761  }
762 
763  const Coin& collateralUtxo = pcoinsTip->AccessCoin(mnb.vin.prevout);
764  if (collateralUtxo.IsSpent()) {
765  LogPrint(BCLog::MASTERNODE,"mnb - vin %s spent\n", mnb.vin.prevout.ToString());
766  return false;
767  }
768 
769  // Check collateral value
770  if (collateralUtxo.out.nValue != consensus.nMNCollateralAmt) {
771  LogPrint(BCLog::MASTERNODE,"mnb - invalid amount for mnb collateral %s\n", mnb.vin.prevout.ToString());
772  nDoS = 33;
773  return false;
774  }
775 
776  // Check collateral association with mnb pubkey
778  if (collateralUtxo.out.scriptPubKey != payee) {
779  LogPrint(BCLog::MASTERNODE,"mnb - collateral %s not associated with mnb pubkey\n", mnb.vin.prevout.ToString());
780  nDoS = 33;
781  return false;
782  }
783 
784  LogPrint(BCLog::MASTERNODE, "mnb - Accepted Masternode entry\n");
785  const int utxoHeight = (int) collateralUtxo.nHeight;
786  int collateralUtxoDepth = nChainHeight - utxoHeight + 1;
787  if (collateralUtxoDepth < consensus.MasternodeCollateralMinConf()) {
788  LogPrint(BCLog::MASTERNODE,"mnb - Input must have at least %d confirmations\n", consensus.MasternodeCollateralMinConf());
789  // maybe we miss few blocks, let this mnb to be checked again later
790  mapSeenMasternodeBroadcast.erase(mnb.GetHash());
792  return false;
793  }
794 
795  // verify that sig time is legit in past
796  // should be at least not earlier than block when 1000 PIV tx got MASTERNODE_MIN_CONFIRMATIONS
797  CBlockIndex* pConfIndex = WITH_LOCK(cs_main, return chainActive[utxoHeight + consensus.MasternodeCollateralMinConf() - 1]); // block where tx got MASTERNODE_MIN_CONFIRMATIONS
798  if (pConfIndex->GetBlockTime() > mnb.sigTime) {
799  LogPrint(BCLog::MASTERNODE,"mnb - Bad sigTime %d for Masternode %s (%i conf block is at %d)\n",
800  mnb.sigTime, mnb.vin.prevout.hash.ToString(), consensus.MasternodeCollateralMinConf(), pConfIndex->GetBlockTime());
801  return false;
802  }
803 
804  // Good input
805  return true;
806 }
807 
809 {
810  const uint256& mnbHash = mnb.GetHash();
811  if (mapSeenMasternodeBroadcast.count(mnbHash)) { //seen
813  return 0;
814  }
815 
816  int chainHeight = GetBestHeight();
817  int nDoS = 0;
818  if (!mnb.CheckAndUpdate(nDoS)) {
819  return nDoS;
820  }
821 
822  // make sure it's still unspent
823  if (!CheckInputs(mnb, chainHeight, nDoS)) {
824  return nDoS; // error set internally
825  }
826 
827  // now that did the mnb checks, can add it.
828  mapSeenMasternodeBroadcast.emplace(mnbHash, mnb);
829 
830  // All checks performed, add it
831  LogPrint(BCLog::MASTERNODE,"%s - Got NEW Masternode entry - %s - %lli \n", __func__,
832  mnb.vin.prevout.hash.ToString(), mnb.sigTime);
833  CMasternode mn(mnb);
834  if (!Add(mn)) {
835  LogPrint(BCLog::MASTERNODE, "%s - Rejected Masternode entry %s\n", __func__,
836  mnb.vin.prevout.hash.ToString());
837  return 0;
838  }
839 
840  // if it matches our MN pubkey, then we've been remotely activated
841  if (mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode && mnb.protocolVersion == PROTOCOL_VERSION) {
843  }
844 
845  // Relay only if we are synchronized and if the mnb address is not local.
846  // Makes no sense to relay MNBs to the peers from where we are syncing them.
847  bool isLocal = (mnb.addr.IsRFC1918() || mnb.addr.IsLocal()) && !Params().IsRegTestNet();
848  if (!isLocal && g_tiertwo_sync_state.IsSynced()) mnb.Relay();
849 
850  // Add it as a peer
851  g_connman->AddNewAddress(CAddress(mnb.addr, NODE_NETWORK), pfrom->addr, 2 * 60 * 60);
852 
853  // Update sync status
855 
856  // All good
857  return 0;
858 }
859 
861 {
862  const uint256& mnpHash = mnp.GetHash();
863  if (mapSeenMasternodePing.count(mnpHash)) return 0; //seen
864 
865  int nDoS = 0;
866  if (mnp.CheckAndUpdate(nDoS)) return 0;
867 
868  if (nDoS > 0) {
869  // if anything significant failed, mark that node
870  return nDoS;
871  } else {
872  // if nothing significant failed, search existing Masternode list
873  CMasternode* pmn = Find(mnp.vin.prevout);
874  // if it's known, don't ask for the mnb, just return
875  if (pmn != nullptr) return 0;
876  }
877 
878  // something significant is broken or mn is unknown,
879  // we might have to ask for the mn entry (while we aren't syncing).
881  AskForMN(pfrom, mnp.vin);
882  }
883 
884  // All good
885  return 0;
886 }
887 
889 {
891  const uint256& hash = mnb.GetHash();
893 
894  // Add to mapSeenMasternodeBroadcast in case that isn't there for some reason.
895  if (!mapSeenMasternodeBroadcast.count(hash)) mapSeenMasternodeBroadcast.emplace(hash, mnb);
896 }
897 
899 {
900  // Single MN request
901  if (!vin.IsNull()) {
902  CMasternode* mn = Find(vin.prevout);
903  if (!mn || !mn->IsEnabled()) return 0; // Nothing to return.
904 
905  // Relay the MN.
906  BroadcastInvMN(mn, pfrom);
907  LogPrint(BCLog::MASTERNODE, "dseg - Sent 1 Masternode entry to peer %i\n", pfrom->GetId());
908  return 0;
909  }
910 
911  // Check if the node asked for mn list sync before.
912  bool isLocal = (pfrom->addr.IsRFC1918() || pfrom->addr.IsLocal());
913  if (!isLocal) {
914  auto itAskedUsMNList = mAskedUsForMasternodeList.find(pfrom->addr);
915  if (itAskedUsMNList != mAskedUsForMasternodeList.end()) {
916  int64_t t = (*itAskedUsMNList).second;
917  if (GetTime() < t) {
918  LogPrintf("CMasternodeMan::ProcessMessage() : dseg - peer already asked me for the list\n");
919  return 20;
920  }
921  }
922  int64_t askAgain = GetTime() + MASTERNODES_REQUEST_SECONDS;
923  mAskedUsForMasternodeList[pfrom->addr] = askAgain;
924  }
925 
926  int nInvCount = 0;
927  {
928  LOCK(cs);
929  for (auto& it : mapMasternodes) {
930  MasternodeRef& mn = it.second;
931  if (mn->addr.IsRFC1918()) continue; //local network
932  if (mn->IsEnabled()) {
933  LogPrint(BCLog::MASTERNODE, "dseg - Sending Masternode entry - %s \n", mn->vin.prevout.hash.ToString());
934  BroadcastInvMN(mn.get(), pfrom);
935  nInvCount++;
936  }
937  }
938  }
939 
941  LogPrint(BCLog::MASTERNODE, "dseg - Sent %d Masternode entries to peer %i\n", nInvCount, pfrom->GetId());
942 
943  // All good
944  return 0;
945 }
946 
947 bool CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv, int& dosScore)
948 {
949  dosScore = ProcessMessageInner(pfrom, strCommand, vRecv);
950  return dosScore == 0;
951 }
952 
953 int CMasternodeMan::ProcessMessageInner(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
954 {
955  if (!g_tiertwo_sync_state.IsBlockchainSynced()) return 0;
956 
957  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
958  if (deterministicMNManager->LegacyMNObsolete()) {
959  LogPrint(BCLog::MASTERNODE, "%s: skip obsolete message %s\n", __func__, strCommand);
960  return 0;
961  }
962 
964 
965  if (strCommand == NetMsgType::MNBROADCAST) {
967  vRecv >> mnb;
968  {
969  // Clear inv request
970  LOCK(cs_main);
971  g_connman->RemoveAskFor(mnb.GetHash(), MSG_MASTERNODE_ANNOUNCE);
972  }
973  return ProcessMNBroadcast(pfrom, mnb);
974 
975  } else if (strCommand == NetMsgType::MNBROADCAST2) {
977  OverrideStream<CDataStream> s(&vRecv, vRecv.GetType(), vRecv.GetVersion() | ADDRV2_FORMAT);
978  s >> mnb;
979  {
980  // Clear inv request
981  LOCK(cs_main);
982  g_connman->RemoveAskFor(mnb.GetHash(), MSG_MASTERNODE_ANNOUNCE);
983  }
984 
985  // For now, let's not process mnb2 with pre-BIP155 node addr format.
986  if (mnb.addr.IsAddrV1Compatible()) {
987  LogPrint(BCLog::MASTERNODE, "%s: mnb2 with pre-BIP155 node addr format rejected\n", __func__);
988  return 30;
989  }
990 
991  return ProcessMNBroadcast(pfrom, mnb);
992 
993  } else if (strCommand == NetMsgType::MNPING) {
994  //Masternode Ping
995  CMasternodePing mnp;
996  vRecv >> mnp;
997  LogPrint(BCLog::MNPING, "mnp - Masternode ping, vin: %s\n", mnp.vin.prevout.hash.ToString());
998  {
999  // Clear inv request
1000  LOCK(cs_main);
1001  g_connman->RemoveAskFor(mnp.GetHash(), MSG_MASTERNODE_PING);
1002  }
1003  return ProcessMNPing(pfrom, mnp);
1004 
1005  } else if (strCommand == NetMsgType::GETMNLIST) {
1006  //Get Masternode list or specific entry
1007  CTxIn vin;
1008  vRecv >> vin;
1009  return ProcessGetMNList(pfrom, vin);
1010  }
1011  // Nothing to report
1012  return 0;
1013 }
1014 
1015 void CMasternodeMan::Remove(const COutPoint& collateralOut)
1016 {
1017  LOCK(cs);
1018  const auto it = mapMasternodes.find(collateralOut);
1019  if (it != mapMasternodes.end()) {
1020  mapMasternodes.erase(it);
1021  }
1022 }
1023 
1025 {
1026  // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
1027  if (deterministicMNManager->LegacyMNObsolete()) {
1028  return;
1029  }
1030 
1031  mapSeenMasternodePing.emplace(mnb.lastPing.GetHash(), mnb.lastPing);
1032  mapSeenMasternodeBroadcast.emplace(mnb.GetHash(), mnb);
1034 
1035  LogPrint(BCLog::MASTERNODE,"%s -- masternode=%s\n", __func__, mnb.vin.prevout.ToString());
1036 
1037  CMasternode* pmn = Find(mnb.vin.prevout);
1038  if (pmn == nullptr) {
1039  CMasternode mn(mnb);
1040  Add(mn);
1041  } else {
1042  pmn->UpdateFromNewBroadcast(mnb);
1043  }
1044 }
1045 
1046 int64_t CMasternodeMan::SecondsSincePayment(const MasternodeRef& mn, int count_enabled, const CBlockIndex* BlockReading) const
1047 {
1048  int64_t sec = (GetAdjustedTime() - GetLastPaid(mn, count_enabled, BlockReading));
1049  int64_t month = 60 * 60 * 24 * 30;
1050  if (sec < month) return sec; //if it's less than 30 days, give seconds
1051 
1052  CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
1053  ss << mn->vin;
1054  ss << mn->sigTime;
1055  const arith_uint256& hash = UintToArith256(ss.GetHash());
1056 
1057  // return some deterministic value for unknown/unpaid but force it to be more than 30 days old
1058  return month + hash.GetCompact(false);
1059 }
1060 
1061 int64_t CMasternodeMan::GetLastPaid(const MasternodeRef& mn, int count_enabled, const CBlockIndex* BlockReading) const
1062 {
1063  if (BlockReading == nullptr) return false;
1064 
1065  const CScript& mnpayee = mn->GetPayeeScript();
1066 
1067  CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
1068  ss << mn->vin;
1069  ss << mn->sigTime;
1070  const uint256& hash = ss.GetHash();
1071 
1072  // use a deterministic offset to break a tie -- 2.5 minutes
1073  int64_t nOffset = UintToArith256(hash).GetCompact(false) % 150;
1074 
1075  int max_depth = count_enabled * 1.25;
1076  for (int n = 0; n < max_depth; n++) {
1077  const auto& it = masternodePayments.mapMasternodeBlocks.find(BlockReading->nHeight);
1078  if (it != masternodePayments.mapMasternodeBlocks.end()) {
1079  // Search for this payee, with at least 2 votes. This will aid in consensus
1080  // allowing the network to converge on the same payees quickly, then keep the same schedule.
1081  if (it->second.HasPayeeWithVotes(mnpayee, 2))
1082  return BlockReading->nTime + nOffset;
1083  }
1084  BlockReading = BlockReading->pprev;
1085 
1086  if (BlockReading == nullptr || BlockReading->nHeight <= 0) {
1087  break;
1088  }
1089  }
1090 
1091  return 0;
1092 }
1093 
1094 std::string CMasternodeMan::ToString() const
1095 {
1096  std::ostringstream info;
1097  info << "Masternodes: " << (int)mapMasternodes.size()
1098  << ", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size()
1099  << ", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size()
1100  << ", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size();
1101  return info.str();
1102 }
1103 
1105 {
1106  cvLastBlockHashes.Set(pindex->nHeight, pindex->GetBlockHash());
1107 }
1108 
1110 {
1112 }
1113 
1115 {
1116  // return zero if outside bounds
1117  if (nHeight < 0) {
1118  LogPrint(BCLog::MASTERNODE, "%s: Negative height. Returning 0\n", __func__);
1119  return UINT256_ZERO;
1120  }
1121  int nCurrentHeight = GetBestHeight();
1122  if (nHeight > nCurrentHeight) {
1123  LogPrint(BCLog::MASTERNODE, "%s: height %d over current height %d. Returning 0\n",
1124  __func__, nHeight, nCurrentHeight);
1125  return UINT256_ZERO;
1126  }
1127 
1128  if (nHeight > nCurrentHeight - (int) CACHED_BLOCK_HASHES) {
1129  // Use cached hash
1130  return cvLastBlockHashes.Get(nHeight);
1131  } else {
1132  // Use chainActive
1133  LOCK(cs_main);
1134  return chainActive[nHeight]->GetBlockHash();
1135  }
1136 }
1137 
1138 bool CMasternodeMan::IsWithinDepth(const uint256& nHash, int depth) const
1139 {
1140  // Sanity checks
1141  if (nHash.IsNull()) {
1142  return error("%s: Called with null hash\n", __func__);
1143  }
1144  if (depth < 0 || (unsigned) depth >= CACHED_BLOCK_HASHES) {
1145  return error("%s: Invalid depth %d. Cached block hashes: %d\n", __func__, depth, CACHED_BLOCK_HASHES);
1146  }
1147  // Check last depth blocks to find one with matching hash
1148  const int nCurrentHeight = GetBestHeight();
1149  int nStopHeight = std::max(0, nCurrentHeight - depth);
1150  for (int i = nCurrentHeight; i >= nStopHeight; i--) {
1151  if (GetHashAtHeight(i) == nHash)
1152  return true;
1153  }
1154  return false;
1155 }
1156 
1158 {
1159  // Make this thread recognisable as the wallet flushing thread
1160  util::ThreadRename("pivx-masternodeman");
1161  LogPrintf("Masternodes thread started\n");
1162 
1163  unsigned int c = 0;
1164 
1165  try {
1166  // first clean up stale masternode payments data
1168 
1169  // Startup-only, clean any stored seen MN broadcast with an invalid service that
1170  // could have been invalidly stored on a previous release
1171  auto itSeenMNB = mnodeman.mapSeenMasternodeBroadcast.begin();
1172  while (itSeenMNB != mnodeman.mapSeenMasternodeBroadcast.end()) {
1173  if (!itSeenMNB->second.addr.IsValid()) {
1174  itSeenMNB = mnodeman.mapSeenMasternodeBroadcast.erase(itSeenMNB);
1175  } else {
1176  itSeenMNB++;
1177  }
1178  }
1179 
1180  while (true) {
1181 
1182  if (ShutdownRequested()) {
1183  break;
1184  }
1185 
1186  MilliSleep(1000);
1187  boost::this_thread::interruption_point();
1188 
1189  // try to sync from all available nodes, one step at a time
1191 
1193  c++;
1194 
1195  // check if we should activate or ping every few minutes,
1196  // start right after sync is considered to be done
1197  if (c % (MasternodePingSeconds()/2) == 0)
1199 
1200  if (c % (MasternodePingSeconds()/5) == 0) {
1202  }
1203  }
1204  }
1205  } catch (boost::thread_interrupted&) {
1206  // nothing, thread interrupted.
1207  }
1208 }
arith_uint256 UintToArith256(const uint256 &a)
const arith_uint256 ARITH_UINT256_ZERO
const CChainParams & Params()
Return the currently selected parameters.
uint256 hash
Definition: transaction.h:35
bool EnableHotColdMasterNode(CTxIn &vin, CService &addr)
Enable cold wallet mode (run a Masternode with no funds)
void ManageStatus()
Manage status of main Masternode.
A CService with information about it as peer.
Definition: protocol.h:338
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:452
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition: streams.h:501
void fclose()
Definition: streams.h:474
void read(char *pch, size_t nSize)
Definition: streams.h:509
static const std::string MAIN
Chain name strings.
int GetType() const
Definition: streams.h:258
const_iterator end() const
Definition: streams.h:163
const_iterator begin() const
Definition: streams.h:161
int GetVersion() const
Definition: streams.h:260
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:145
uint32_t nTime
Definition: chain.h:196
uint256 GetBlockHash() const
Definition: chain.h:215
int64_t GetBlockTime() const
Definition: chain.h:216
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
bool IsRegTestNet() const
Definition: chainparams.h:98
void ForEachMN(bool onlyValid, Callback &&cb) const
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:216
uint256 GetHash()
Definition: hash.h:236
inv message data
Definition: protocol.h:466
bool CheckAndUpdate(int &nDoS)
Definition: masternode.cpp:382
uint256 GetHash() const
Definition: masternode.cpp:481
Access to the MN database (mncache.dat)
Definition: masternodeman.h:34
fs::path pathMN
Definition: masternodeman.h:36
bool Write(const CMasternodeMan &mnodemanToSave)
ReadResult Read(CMasternodeMan &mnodemanToLoad)
std::string strMagicMessage
Definition: masternodeman.h:37
CMasternodePing lastPing
Definition: masternode.h:104
CService addr
Definition: masternode.h:97
bool IsAvailableState() const
Definition: masternode.h:203
CTxIn vin
Definition: masternode.h:96
CPubKey pubKeyMasternode
Definition: masternode.h:99
int protocolVersion
Definition: masternode.h:101
int64_t sigTime
Definition: masternode.h:100
@ MASTERNODE_REMOVE
Definition: masternode.h:92
@ MASTERNODE_VIN_SPENT
Definition: masternode.h:93
@ MASTERNODE_EXPIRED
Definition: masternode.h:91
bool UpdateFromNewBroadcast(CMasternodeBroadcast &mnb)
Definition: masternode.cpp:134
bool IsEnabled() const
Definition: masternode.h:193
CPubKey pubKeyCollateralAddress
Definition: masternode.h:98
std::map< uint256, CMasternodeBroadcast > mapSeenMasternodeBroadcast
Definition: masternodeman.h:93
std::map< CNetAddr, int64_t > mAskedUsForMasternodeList
Definition: masternodeman.h:68
void UpdateMasternodeList(CMasternodeBroadcast &mnb)
Update masternode list and maps using provided CMasternodeBroadcast.
std::map< CNetAddr, int64_t > mWeAskedForMasternodeList
Definition: masternodeman.h:70
int CheckAndRemove(bool forceExpiredRemoval=false)
Check all Masternodes and remove inactive. Return the total masternode count.
int CountEnabled(bool only_legacy=false) const
bool CheckInputs(CMasternodeBroadcast &mnb, int nChainHeight, int &nDoS)
void CheckSpentCollaterals(const std::vector< CTransactionRef > &vtx)
Check all transactions in a block, for spent masternode collateral outpoints (marking them as spent)
int ProcessGetMNList(CNode *pfrom, CTxIn &vin)
RecursiveMutex cs_process_message
Definition: masternodeman.h:63
std::vector< std::pair< int64_t, MasternodeRef > > GetMasternodeRanks(int nBlockHeight) const
std::vector< std::pair< MasternodeRef, int > > GetMnScores(int nLast) const
vector of pairs <masternode winner, height>
void AskForMN(CNode *pnode, const CTxIn &vin)
Ask (source) node for mnb.
void CacheBlockHash(const CBlockIndex *pindex)
uint256 GetHashAtHeight(int nHeight) const
std::map< COutPoint, MasternodeRef > mapMasternodes
Definition: masternodeman.h:66
MasternodeRef GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int &nCount, const CBlockIndex *pChainTip=nullptr) const
Find an entry in the masternode list that is next to be paid.
bool RequestMnList(CNode *pnode)
int ProcessMNPing(CNode *pfrom, CMasternodePing &mnp)
int GetBestHeight() const
int64_t GetLastPaid(const MasternodeRef &mn, int count_enabled, const CBlockIndex *BlockReading) const
Get the time a masternode was last paid.
CMasternodeMan::MNsInfo getMNsInfo() const
std::string ToString() const
int GetMasternodeRank(const CTxIn &vin, int64_t nBlockHeight) const
bool ProcessMessage(CNode *pfrom, std::string &strCommand, CDataStream &vRecv, int &dosScore)
void Remove(const COutPoint &collateralOut)
int64_t nDsqCount
Definition: masternodeman.h:99
bool Add(CMasternode &mn)
Add an entry.
int64_t SecondsSincePayment(const MasternodeRef &mn, int count_enabled, const CBlockIndex *BlockReading) const
CyclingVector< uint256 > cvLastBlockHashes
Definition: masternodeman.h:78
RecursiveMutex cs
Definition: masternodeman.h:60
std::map< COutPoint, int64_t > mWeAskedForMasternodeListEntry
Definition: masternodeman.h:72
void Clear()
Clear Masternode vector.
int ProcessMNBroadcast(CNode *pfrom, CMasternodeBroadcast &mnb)
bool IsWithinDepth(const uint256 &nHash, int depth) const
std::map< uint256, CMasternodePing > mapSeenMasternodePing
Definition: masternodeman.h:95
CMasternode * Find(const COutPoint &collateralOut)
Find an entry.
void BroadcastInvMN(CMasternode *mn, CNode *pfrom)
MasternodeRef GetCurrentMasterNode(const uint256 &hash) const
Get the winner for this block hash.
int ProcessMessageInner(CNode *pfrom, std::string &strCommand, CDataStream &vRecv)
void UncacheBlockHash(const CBlockIndex *pindex)
void CleanPaymentList(int mnCount, int nHeight)
std::map< int, CMasternodeBlockPayees > mapMasternodeBlocks
bool IsScheduled(const CMasternode &mn, int nNotBlockHeight)
bool IsNull() const
Definition: masternode.h:59
bool CheckAndUpdate(int &nDos, bool fRequireAvailable=true, bool fCheckSigTimeOnly=false)
Definition: masternode.cpp:517
uint256 GetHash() const
Definition: masternode.cpp:503
Network address.
Definition: netaddress.h:120
bool IsRFC1918() const
Definition: netaddress.cpp:299
bool IsLocal() const
Definition: netaddress.cpp:402
enum Network GetNetwork() const
Definition: netaddress.cpp:489
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Definition: netaddress.cpp:469
CSerializedNetMsg Make(int nFlags, std::string sCommand, Args &&... args)
Information about a peer.
Definition: net.h:669
NodeId GetId() const
Definition: net.h:825
int GetSendVersion() const
Definition: net.cpp:789
const CAddress addr
Definition: net.h:698
void PushInventory(const CInv &inv)
Definition: net.h:914
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:72
std::string ToString() const
Definition: transaction.cpp:18
An encapsulated public key.
Definition: pubkey.h:44
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:381
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:484
std::string ToString() const
Definition: netaddress.cpp:954
bool IsSporkActive(SporkId nSporkID)
Definition: spork.cpp:220
An input of a transaction.
Definition: transaction.h:94
bool IsNull() const
Definition: transaction.h:111
COutPoint prevout
Definition: transaction.h:96
CScript scriptPubKey
Definition: transaction.h:140
CAmount nValue
Definition: transaction.h:139
A UTXO entry.
Definition: coins.h:32
CTxOut out
unspent transaction output
Definition: coins.h:41
bool IsSpent() const
Definition: coins.h:86
uint32_t nHeight
at which height the containing transaction was included in the active block chain
Definition: coins.h:44
T Get(int idx) const
Definition: cyclingvector.h:31
void Set(int idx, const T &value)
Definition: cyclingvector.h:32
void EraseSeenMNB(const uint256 &hash)
bool IsBlockchainSynced() const
void AddedMasternodeList(const uint256 &hash)
bool IsSynced() const
256-bit unsigned big integer.
uint32_t GetCompact(bool fNegative=false) const
std::string ToString() const
Definition: uint256.cpp:65
bool IsNull() const
Definition: uint256.h:36
256-bit opaque blob.
Definition: uint256.h:138
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
if(!read_stdin(buffer))
Definition: fuzz.cpp:72
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:173
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:90
@ LOCK
Definition: lockunlock.h:16
#define LogPrint(category,...)
Definition: logging.h:163
CMasternodePayments masternodePayments
Object for who's going to get paid on which blocks.
CMasternodeSync masternodeSync
int MasternodeMinPingSeconds()
Definition: masternode.cpp:28
int MasternodeRemovalSeconds()
Definition: masternode.cpp:48
int MasternodePingSeconds()
Definition: masternode.cpp:38
MasternodeRef MakeMasternodeRefForDMN(const CDeterministicMNCPtr &dmn)
Definition: masternode.cpp:613
std::shared_ptr< CMasternode > MasternodeRef
Definition: masternode.h:24
CMasternodeMan mnodeman
Masternode manager.
CActiveMasternode activeMasternode
Keep track of the active Masternode.
#define MN_WINNER_MINIMUM_AGE
void ThreadCheckMasternodes()
void DumpMasternodes()
#define MASTERNODES_REQUEST_SECONDS
Definition: masternodeman.h:18
@ MASTERNODE
Definition: logging.h:59
@ MNPING
Definition: logging.h:61
const char * MNBROADCAST2
The mnbroadcast2 message is used to broadcast masternode startup data to connected peers Supporting B...
Definition: protocol.cpp:45
const char * GETMNLIST
The dseg message is used to request the Masternode list or an specific entry.
Definition: protocol.cpp:55
const char * MNBROADCAST
The mnbroadcast message is used to broadcast masternode startup data to connected peers.
Definition: protocol.cpp:44
const char * MNPING
The mnping message is used to ensure a masternode is still active.
Definition: protocol.cpp:46
const char * SYNCSTATUSCOUNT
The syncstatuscount message is used to track the layer 2 syncing process.
Definition: protocol.cpp:54
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:23
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
Definition: threadnames.cpp:62
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
@ NET_ONION
TOR (v2 or v3)
Definition: netaddress.h:55
@ NET_IPV6
IPv6.
Definition: netaddress.h:52
@ NET_IPV4
IPv4.
Definition: netaddress.h:49
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Definition: netbase.cpp:71
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:149
@ MSG_MASTERNODE_ANNOUNCE
Definition: protocol.h:451
@ MSG_MASTERNODE_PING
Definition: protocol.h:452
@ NODE_NETWORK
Definition: protocol.h:318
@ SER_DISK
Definition: serialize.h:175
@ SER_GETHASH
Definition: serialize.h:176
bool ShutdownRequested()
Definition: shutdown.cpp:22
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
Definition: span.h:221
CSporkManager sporkManager
Definition: spork.cpp:29
@ SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT
Definition: sporkid.h:18
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
Definition: standard.cpp:278
bool operator()(const std::pair< int64_t, T > &t1, const std::pair< int64_t, T > &t2) const
#define AssertLockNotHeld(cs)
Definition: sync.h:76
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:724
bool error(const char *fmt, const Args &... args)
Definition: system.h:77
TierTwoSyncState g_tiertwo_sync_state
#define MASTERNODE_SYNC_LIST
int64_t GetAdjustedTime()
Definition: timedata.cpp:36
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:175
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: utiltime.cpp:61
void MilliSleep(int64_t n)
Definition: utiltime.cpp:82
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: utiltime.cpp:27
int ActiveProtocol()
See whether the protocol update is enforced for connected nodes.
std::unique_ptr< CCoinsViewCache > pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: validation.cpp:206
CBlockIndex * GetChainTip()
Return a reliable pointer (in mapBlockIndex) to the chain's tip index.
Definition: validation.cpp:194
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84