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 "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"
19 : #include "tiertwo/tiertwo_sync_state.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 :
26 : /** Masternode manager */
27 : CMasternodeMan mnodeman;
28 : /** Keep track of the active Masternode */
29 : CActiveMasternode activeMasternode;
30 :
31 : struct CompareScoreMN {
32 : template <typename T>
33 251954 : bool operator()(const std::pair<int64_t, T>& t1,
34 : const std::pair<int64_t, T>& t2) const
35 : {
36 247016 : return t1.first < t2.first;
37 : }
38 : };
39 :
40 : //
41 : // CMasternodeDB
42 : //
43 :
44 : static const int MASTERNODE_DB_VERSION_BIP155 = 2;
45 :
46 733 : CMasternodeDB::CMasternodeDB()
47 : {
48 733 : pathMN = GetDataDir() / "mncache.dat";
49 733 : strMagicMessage = "MasternodeCache";
50 733 : }
51 :
52 378 : bool CMasternodeDB::Write(const CMasternodeMan& mnodemanToSave)
53 : {
54 378 : int64_t nStart = GetTimeMillis();
55 378 : const auto& params = Params();
56 :
57 : // serialize, checksum data up to that point, then append checksum
58 : // Always done in the latest format.
59 756 : CDataStream ssMasternodes(SER_DISK, CLIENT_VERSION | ADDRV2_FORMAT);
60 378 : ssMasternodes << MASTERNODE_DB_VERSION_BIP155;
61 378 : ssMasternodes << strMagicMessage; // masternode cache file specific magic message
62 378 : ssMasternodes << params.MessageStart(); // network specific magic number
63 378 : ssMasternodes << mnodemanToSave;
64 378 : uint256 hash = Hash(ssMasternodes.begin(), ssMasternodes.end());
65 378 : ssMasternodes << hash;
66 :
67 : // open output file, and associate with CAutoFile
68 378 : FILE* file = fsbridge::fopen(pathMN, "wb");
69 756 : CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
70 378 : if (fileout.IsNull())
71 0 : return error("%s : Failed to open file %s", __func__, pathMN.string());
72 :
73 : // Write and commit header, data
74 378 : try {
75 378 : fileout << ssMasternodes;
76 0 : } catch (const std::exception& e) {
77 0 : return error("%s : Serialize or I/O error - %s", __func__, e.what());
78 : }
79 : // FileCommit(fileout);
80 378 : fileout.fclose();
81 :
82 378 : LogPrint(BCLog::MASTERNODE,"Written info to mncache.dat %dms\n", GetTimeMillis() - nStart);
83 752 : LogPrint(BCLog::MASTERNODE," %s\n", mnodemanToSave.ToString());
84 :
85 : return true;
86 : }
87 :
88 355 : CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad)
89 : {
90 355 : int64_t nStart = GetTimeMillis();
91 : // open input file, and associate with CAutoFile
92 355 : FILE* file = fsbridge::fopen(pathMN, "rb");
93 710 : CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
94 355 : if (filein.IsNull()) {
95 273 : error("%s : Failed to open file %s", __func__, pathMN.string());
96 : return FileError;
97 : }
98 :
99 : // use file size to size memory buffer
100 82 : int fileSize = fs::file_size(pathMN);
101 82 : int dataSize = fileSize - sizeof(uint256);
102 : // Don't try to resize to a negative number if file is small
103 82 : if (dataSize < 0)
104 0 : dataSize = 0;
105 437 : std::vector<unsigned char> vchData;
106 82 : vchData.resize(dataSize);
107 82 : uint256 hashIn;
108 :
109 : // read data and checksum from file
110 82 : try {
111 82 : filein.read((char*)vchData.data(), dataSize);
112 82 : filein >> hashIn;
113 0 : } catch (const std::exception& e) {
114 0 : error("%s : Deserialize or I/O error - %s", __func__, e.what());
115 0 : return HashReadError;
116 : }
117 82 : filein.fclose();
118 :
119 82 : const auto& params = Params();
120 : // serialize, checksum data up to that point, then append checksum
121 164 : CDataStream ssMasternodes(vchData, SER_DISK, CLIENT_VERSION);
122 :
123 : // verify stored checksum matches input data
124 82 : uint256 hashTmp = Hash(ssMasternodes.begin(), ssMasternodes.end());
125 82 : if (hashIn != hashTmp) {
126 0 : error("%s : Checksum mismatch, data corrupted", __func__);
127 : return IncorrectHash;
128 : }
129 :
130 82 : int version;
131 164 : std::string strMagicMessageTmp;
132 82 : try {
133 : // de-serialize file header
134 82 : ssMasternodes >> version;
135 82 : ssMasternodes >> strMagicMessageTmp;
136 :
137 : // ... verify the message matches predefined one
138 82 : if (strMagicMessage != strMagicMessageTmp) {
139 0 : error("%s : Invalid masternode cache magic message", __func__);
140 0 : return IncorrectMagicMessage;
141 : }
142 :
143 : // de-serialize file header (network specific magic number) and ..
144 82 : std::vector<unsigned char> pchMsgTmp(4);
145 82 : ssMasternodes >> MakeSpan(pchMsgTmp);
146 :
147 : // ... verify the network matches ours
148 82 : if (memcmp(pchMsgTmp.data(), params.MessageStart(), pchMsgTmp.size()) != 0) {
149 0 : error("%s : Invalid network magic number", __func__);
150 0 : return IncorrectMagicNumber;
151 : }
152 : // de-serialize data into CMasternodeMan object.
153 82 : if (version == MASTERNODE_DB_VERSION_BIP155) {
154 82 : OverrideStream<CDataStream> s(&ssMasternodes, ssMasternodes.GetType(), ssMasternodes.GetVersion() | ADDRV2_FORMAT);
155 82 : s >> mnodemanToLoad;
156 : } else {
157 : // Old format
158 82 : ssMasternodes >> mnodemanToLoad;
159 : }
160 0 : } catch (const std::exception& e) {
161 0 : mnodemanToLoad.Clear();
162 0 : error("%s : Deserialize or I/O error - %s", __func__, e.what());
163 0 : return IncorrectFormat;
164 : }
165 :
166 82 : LogPrint(BCLog::MASTERNODE,"Loaded info from mncache.dat (dbversion=%d) %dms\n", version, GetTimeMillis() - nStart);
167 164 : LogPrint(BCLog::MASTERNODE," %s\n", mnodemanToLoad.ToString());
168 :
169 : return Ok;
170 : }
171 :
172 378 : void DumpMasternodes()
173 : {
174 378 : int64_t nStart = GetTimeMillis();
175 :
176 756 : CMasternodeDB mndb;
177 378 : LogPrint(BCLog::MASTERNODE,"Writing info to mncache.dat...\n");
178 378 : mndb.Write(mnodeman);
179 :
180 378 : LogPrint(BCLog::MASTERNODE,"Masternode dump finished %dms\n", GetTimeMillis() - nStart);
181 378 : }
182 :
183 479 : CMasternodeMan::CMasternodeMan():
184 : cvLastBlockHashes(CACHED_BLOCK_HASHES, UINT256_ZERO),
185 479 : nDsqCount(0)
186 479 : {}
187 :
188 120 : bool CMasternodeMan::Add(CMasternode& mn)
189 : {
190 : // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
191 120 : if (deterministicMNManager->LegacyMNObsolete()) {
192 : return false;
193 : }
194 :
195 120 : if (deterministicMNManager->GetListAtChainTip().HasMNByCollateral(mn.vin.prevout)) {
196 6 : LogPrint(BCLog::MASTERNODE, "ERROR: Not Adding Masternode %s as the collateral is already registered with a DMN\n",
197 : mn.vin.prevout.ToString());
198 3 : return false;
199 : }
200 :
201 237 : LOCK(cs);
202 :
203 117 : if (!mn.IsAvailableState())
204 : return false;
205 :
206 117 : const auto& it = mapMasternodes.find(mn.vin.prevout);
207 117 : if (it == mapMasternodes.end()) {
208 194 : LogPrint(BCLog::MASTERNODE, "Adding new Masternode %s\n", mn.vin.prevout.ToString());
209 117 : mapMasternodes.emplace(mn.vin.prevout, std::make_shared<CMasternode>(mn));
210 117 : LogPrint(BCLog::MASTERNODE, "Masternode added. New total count: %d\n", mapMasternodes.size());
211 117 : return true;
212 : }
213 :
214 : return false;
215 : }
216 :
217 4 : void CMasternodeMan::AskForMN(CNode* pnode, const CTxIn& vin)
218 : {
219 : // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
220 4 : if (deterministicMNManager->LegacyMNObsolete()) {
221 2 : return;
222 : }
223 :
224 4 : std::map<COutPoint, int64_t>::iterator i = mWeAskedForMasternodeListEntry.find(vin.prevout);
225 4 : if (i != mWeAskedForMasternodeListEntry.end()) {
226 2 : int64_t t = (*i).second;
227 2 : 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 4 : LogPrint(BCLog::MASTERNODE, "CMasternodeMan::AskForMN - Asking node for missing entry, vin: %s\n", vin.prevout.hash.ToString());
233 2 : g_connman->PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::GETMNLIST, vin));
234 2 : int64_t askAgain = GetTime() + MasternodeMinPingSeconds();
235 2 : mWeAskedForMasternodeListEntry[vin.prevout] = askAgain;
236 : }
237 :
238 3627 : int CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval)
239 : {
240 : // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
241 3627 : if (deterministicMNManager->LegacyMNObsolete()) {
242 948 : LogPrint(BCLog::MASTERNODE, "Removing all legacy mn due to SPORK 21\n");
243 948 : Clear();
244 948 : return 0;
245 : }
246 :
247 6306 : LOCK(cs);
248 :
249 : //remove inactive and outdated (or replaced by DMN)
250 2679 : auto it = mapMasternodes.begin();
251 3817 : while (it != mapMasternodes.end()) {
252 1138 : MasternodeRef& mn = it->second;
253 1138 : auto activeState = mn->GetActiveState();
254 1138 : if (activeState == CMasternode::MASTERNODE_REMOVE ||
255 1105 : activeState == CMasternode::MASTERNODE_VIN_SPENT ||
256 2243 : (forceExpiredRemoval && activeState == CMasternode::MASTERNODE_EXPIRED) ||
257 1105 : mn->protocolVersion < ActiveProtocol()) {
258 66 : 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 33 : std::map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
263 107 : while (it3 != mapSeenMasternodeBroadcast.end()) {
264 74 : if (it3->second.vin.prevout == it->first) {
265 39 : g_tiertwo_sync_state.EraseSeenMNB((*it3).first);
266 39 : it3 = mapSeenMasternodeBroadcast.erase(it3);
267 : } else {
268 142 : ++it3;
269 : }
270 : }
271 :
272 : // allow us to ask for this masternode again if we see another ping
273 33 : std::map<COutPoint, int64_t>::iterator it2 = mWeAskedForMasternodeListEntry.begin();
274 33 : while (it2 != mWeAskedForMasternodeListEntry.end()) {
275 0 : if (it2->first == it->first) {
276 0 : it2 = mWeAskedForMasternodeListEntry.erase(it2);
277 : } else {
278 33 : ++it2;
279 : }
280 : }
281 :
282 : // clean MN pings right away.
283 33 : auto itPing = mapSeenMasternodePing.begin();
284 719 : while (itPing != mapSeenMasternodePing.end()) {
285 1372 : if (itPing->second.GetVin().prevout == it->first) {
286 322 : itPing = mapSeenMasternodePing.erase(itPing);
287 : } else {
288 1083 : ++itPing;
289 : }
290 : }
291 :
292 33 : it = mapMasternodes.erase(it);
293 33 : LogPrint(BCLog::MASTERNODE, "Masternode removed.\n");
294 : } else {
295 4922 : ++it;
296 : }
297 : }
298 2679 : LogPrint(BCLog::MASTERNODE, "New total masternode count: %d\n", mapMasternodes.size());
299 :
300 : // check who's asked for the Masternode list
301 2679 : std::map<CNetAddr, int64_t>::iterator it1 = mAskedUsForMasternodeList.begin();
302 2679 : while (it1 != mAskedUsForMasternodeList.end()) {
303 0 : if ((*it1).second < GetTime()) {
304 0 : it1 = mAskedUsForMasternodeList.erase(it1);
305 : } else {
306 2679 : ++it1;
307 : }
308 : }
309 :
310 : // check who we asked for the Masternode list
311 2679 : it1 = mWeAskedForMasternodeList.begin();
312 2679 : while (it1 != mWeAskedForMasternodeList.end()) {
313 0 : if ((*it1).second < GetTime()) {
314 0 : it1 = mWeAskedForMasternodeList.erase(it1);
315 : } else {
316 2679 : ++it1;
317 : }
318 : }
319 :
320 : // check which Masternodes we've asked for
321 2679 : std::map<COutPoint, int64_t>::iterator it2 = mWeAskedForMasternodeListEntry.begin();
322 2689 : while (it2 != mWeAskedForMasternodeListEntry.end()) {
323 10 : if ((*it2).second < GetTime()) {
324 2 : it2 = mWeAskedForMasternodeListEntry.erase(it2);
325 : } else {
326 2697 : ++it2;
327 : }
328 : }
329 :
330 : // remove expired mapSeenMasternodeBroadcast
331 2679 : std::map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
332 3861 : while (it3 != mapSeenMasternodeBroadcast.end()) {
333 1182 : if ((*it3).second.lastPing.sigTime < GetTime() - (MasternodeRemovalSeconds() * 2)) {
334 3 : g_tiertwo_sync_state.EraseSeenMNB((*it3).second.GetHash());
335 3 : it3 = mapSeenMasternodeBroadcast.erase(it3);
336 : } else {
337 5040 : ++it3;
338 : }
339 : }
340 :
341 : // remove expired mapSeenMasternodePing
342 2679 : std::map<uint256, CMasternodePing>::iterator it4 = mapSeenMasternodePing.begin();
343 21229 : while (it4 != mapSeenMasternodePing.end()) {
344 18550 : if ((*it4).second.sigTime < GetTime() - (MasternodeRemovalSeconds() * 2)) {
345 1590 : it4 = mapSeenMasternodePing.erase(it4);
346 : } else {
347 38189 : ++it4;
348 : }
349 : }
350 :
351 2679 : return mapMasternodes.size();
352 : }
353 :
354 948 : void CMasternodeMan::Clear()
355 : {
356 948 : LOCK(cs);
357 948 : mapMasternodes.clear();
358 948 : mAskedUsForMasternodeList.clear();
359 948 : mWeAskedForMasternodeList.clear();
360 948 : mWeAskedForMasternodeListEntry.clear();
361 948 : mapSeenMasternodeBroadcast.clear();
362 948 : mapSeenMasternodePing.clear();
363 948 : nDsqCount = 0;
364 948 : }
365 :
366 881 : static void CountNetwork(const CService& addr, int& ipv4, int& ipv6, int& onion)
367 : {
368 881 : std::string strHost;
369 881 : int port;
370 881 : SplitHostPort(addr.ToString(), port, strHost);
371 1762 : CNetAddr node;
372 881 : LookupHost(strHost, node, false);
373 881 : switch(node.GetNetwork()) {
374 0 : case NET_IPV4:
375 0 : ipv4++;
376 0 : break;
377 0 : case NET_IPV6:
378 0 : ipv6++;
379 0 : break;
380 0 : case NET_ONION:
381 0 : onion++;
382 0 : break;
383 : default:
384 : break;
385 : }
386 881 : }
387 :
388 212 : CMasternodeMan::MNsInfo CMasternodeMan::getMNsInfo() const
389 : {
390 212 : MNsInfo info;
391 212 : int nMinProtocol = ActiveProtocol();
392 212 : bool spork_8_active = sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT);
393 :
394 : // legacy masternodes
395 212 : {
396 212 : LOCK(cs);
397 254 : for (const auto& it : mapMasternodes) {
398 42 : const MasternodeRef& mn = it.second;
399 42 : info.total++;
400 42 : CountNetwork(mn->addr, info.ipv4, info.ipv6, info.onion);
401 42 : if (mn->protocolVersion < nMinProtocol || !mn->IsEnabled()) {
402 0 : continue;
403 : }
404 42 : info.enabledSize++;
405 : // Eligible for payments
406 42 : if (spork_8_active && (GetAdjustedTime() - mn->sigTime < MN_WINNER_MINIMUM_AGE)) {
407 0 : continue; // Skip masternodes younger than (default) 8000 sec (MUST be > MASTERNODE_REMOVAL_SECONDS)
408 : }
409 42 : info.stableSize++;
410 : }
411 : }
412 :
413 : // deterministic masternodes
414 212 : if (deterministicMNManager->IsDIP3Enforced()) {
415 212 : auto mnList = deterministicMNManager->GetListAtChainTip();
416 212 : mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
417 1590 : info.total++;
418 839 : CountNetwork(dmn->pdmnState->addr, info.ipv4, info.ipv6, info.onion);
419 839 : if (!dmn->IsPoSeBanned()) {
420 751 : info.enabledSize++;
421 751 : info.stableSize++;
422 : }
423 839 : });
424 : }
425 :
426 212 : return info;
427 : }
428 :
429 11926 : int CMasternodeMan::CountEnabled(bool only_legacy) const
430 : {
431 11926 : int count_enabled = 0;
432 11926 : int protocolVersion = ActiveProtocol();
433 :
434 11926 : {
435 11926 : LOCK(cs);
436 83617 : for (const auto& it : mapMasternodes) {
437 71691 : const MasternodeRef& mn = it.second;
438 71691 : if (mn->protocolVersion < protocolVersion || !mn->IsEnabled()) continue;
439 68200 : count_enabled++;
440 : }
441 : }
442 :
443 11926 : if (!only_legacy && deterministicMNManager->IsDIP3Enforced()) {
444 6876 : count_enabled += deterministicMNManager->GetListAtChainTip().GetValidMNsCount();
445 : }
446 :
447 11926 : return count_enabled;
448 : }
449 :
450 0 : bool CMasternodeMan::RequestMnList(CNode* pnode)
451 : {
452 : // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
453 0 : if (deterministicMNManager->LegacyMNObsolete()) {
454 : return false;
455 : }
456 :
457 0 : LOCK(cs);
458 0 : if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
459 0 : if (!(pnode->addr.IsRFC1918() || pnode->addr.IsLocal())) {
460 0 : std::map<CNetAddr, int64_t>::iterator it = mWeAskedForMasternodeList.find(pnode->addr);
461 0 : if (it != mWeAskedForMasternodeList.end()) {
462 0 : if (GetTime() < (*it).second) {
463 0 : LogPrint(BCLog::MASTERNODE, "dseg - we already asked peer %i for the list; skipping...\n", pnode->GetId());
464 0 : return false;
465 : }
466 : }
467 : }
468 : }
469 :
470 0 : g_connman->PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::GETMNLIST, CTxIn()));
471 0 : int64_t askAgain = GetTime() + MASTERNODES_REQUEST_SECONDS;
472 0 : mWeAskedForMasternodeList[pnode->addr] = askAgain;
473 0 : return true;
474 : }
475 :
476 106245 : CMasternode* CMasternodeMan::Find(const COutPoint& collateralOut)
477 : {
478 106245 : LOCK(cs);
479 106245 : auto it = mapMasternodes.find(collateralOut);
480 106245 : return it != mapMasternodes.end() ? it->second.get() : nullptr;
481 : }
482 :
483 0 : const CMasternode* CMasternodeMan::Find(const COutPoint& collateralOut) const
484 : {
485 0 : LOCK(cs);
486 0 : auto const& it = mapMasternodes.find(collateralOut);
487 0 : return it != mapMasternodes.end() ? it->second.get() : nullptr;
488 : }
489 :
490 130 : CMasternode* CMasternodeMan::Find(const CPubKey& pubKeyMasternode)
491 : {
492 130 : LOCK(cs);
493 :
494 183 : for (auto& it : mapMasternodes) {
495 150 : MasternodeRef& mn = it.second;
496 150 : if (mn->pubKeyMasternode == pubKeyMasternode)
497 97 : return mn.get();
498 : }
499 33 : return nullptr;
500 : }
501 :
502 41568 : void CMasternodeMan::CheckSpentCollaterals(const std::vector<CTransactionRef>& vtx)
503 : {
504 : // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
505 41568 : if (deterministicMNManager->LegacyMNObsolete()) {
506 6271 : return;
507 : }
508 :
509 70594 : LOCK(cs);
510 325307 : for (const auto& tx : vtx) {
511 789451 : for (const auto& in : tx->vin) {
512 499441 : auto it = mapMasternodes.find(in.prevout);
513 499441 : if (it != mapMasternodes.end()) {
514 12 : it->second->SetSpent();
515 : }
516 : }
517 : }
518 : }
519 :
520 1549 : static bool canScheduleMN(bool fFilterSigTime, const MasternodeRef& mn, int minProtocol,
521 : int nMnCount, int nBlockHeight)
522 : {
523 : // check protocol version
524 1549 : 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 1549 : if (masternodePayments.IsScheduled(*mn, nBlockHeight)) return false;
528 :
529 : // it's too new, wait for a cycle
530 446 : 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 284 : 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 698 : 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 698 : if (deterministicMNManager->LegacyMNObsolete(nBlockHeight)) {
545 136 : LogPrintf("%s: ERROR - called after legacy system disabled\n", __func__);
546 136 : return nullptr;
547 : }
548 :
549 562 : AssertLockNotHeld(cs_main);
550 562 : const CBlockIndex* BlockReading = (pChainTip == nullptr ? GetChainTip() : pChainTip);
551 562 : if (!BlockReading) return nullptr;
552 :
553 1260 : MasternodeRef pBestMasternode = nullptr;
554 1124 : std::vector<std::pair<int64_t, MasternodeRef> > vecMasternodeLastPaid;
555 :
556 : /*
557 : Make a vector with all of the last paid times
558 : */
559 562 : int minProtocol = ActiveProtocol();
560 562 : int count_enabled = CountEnabled();
561 562 : {
562 562 : LOCK(cs);
563 1246 : for (const auto& it : mapMasternodes) {
564 684 : if (!it.second->IsEnabled()) continue;
565 669 : if (canScheduleMN(fFilterSigTime, it.second, minProtocol, count_enabled, nBlockHeight)) {
566 143 : vecMasternodeLastPaid.emplace_back(SecondsSincePayment(it.second, count_enabled, BlockReading), it.second);
567 : }
568 : }
569 : }
570 : // Add deterministic masternodes to the vector
571 562 : if (deterministicMNManager->IsDIP3Enforced()) {
572 558 : CDeterministicMNList mnList = deterministicMNManager->GetListAtChainTip();
573 558 : mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
574 880 : const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
575 880 : if (canScheduleMN(fFilterSigTime, mn, minProtocol, count_enabled, nBlockHeight)) {
576 134 : vecMasternodeLastPaid.emplace_back(SecondsSincePayment(mn, count_enabled, BlockReading), mn);
577 : }
578 880 : });
579 : }
580 :
581 562 : nCount = (int)vecMasternodeLastPaid.size();
582 :
583 : //when the network is in the process of upgrading, don't penalize nodes that recently restarted
584 562 : if (fFilterSigTime && nCount < count_enabled / 3) return GetNextMasternodeInQueueForPayment(nBlockHeight, false, nCount, BlockReading);
585 :
586 : // Sort them high to low
587 422 : 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 422 : int nTenthNetwork = count_enabled / 10;
594 422 : int nCountTenth = 0;
595 422 : arith_uint256 nHigh = ARITH_UINT256_ZERO;
596 422 : const uint256& hash = GetHashAtHeight(nBlockHeight - 101);
597 422 : for (const auto& s: vecMasternodeLastPaid) {
598 198 : const MasternodeRef pmn = s.second;
599 198 : if (!pmn) break;
600 :
601 198 : const arith_uint256& n = pmn->CalculateScore(hash);
602 198 : if (n > nHigh) {
603 1782 : nHigh = n;
604 198 : pBestMasternode = pmn;
605 : }
606 198 : nCountTenth++;
607 198 : if (nCountTenth >= nTenthNetwork) break;
608 : }
609 562 : return pBestMasternode;
610 : }
611 :
612 14122 : MasternodeRef CMasternodeMan::GetCurrentMasterNode(const uint256& hash) const
613 : {
614 14122 : int minProtocol = ActiveProtocol();
615 14122 : int64_t score = 0;
616 14122 : MasternodeRef winner = nullptr;
617 :
618 : // scan for winner
619 14473 : for (const auto& it : mapMasternodes) {
620 351 : const MasternodeRef& mn = it.second;
621 351 : if (mn->protocolVersion < minProtocol || !mn->IsEnabled()) continue;
622 : // calculate the score of the masternode
623 334 : const int64_t n = mn->CalculateScore(hash).GetCompact(false);
624 : // determine the winner
625 334 : if (n > score) {
626 280 : score = n;
627 631 : winner = mn;
628 : }
629 : }
630 :
631 : // scan also dmns
632 14122 : if (deterministicMNManager->IsDIP3Enforced()) {
633 303 : auto mnList = deterministicMNManager->GetListAtChainTip();
634 303 : mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
635 133 : const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
636 : // calculate the score of the masternode
637 133 : const int64_t n = mn->CalculateScore(hash).GetCompact(false);
638 : // determine the winner
639 133 : if (n > score) {
640 73 : score = n;
641 206 : winner = mn;
642 : }
643 133 : });
644 : }
645 :
646 14122 : return winner;
647 : }
648 :
649 0 : std::vector<std::pair<MasternodeRef, int>> CMasternodeMan::GetMnScores(int nLast) const
650 : {
651 0 : std::vector<std::pair<MasternodeRef, int>> ret;
652 0 : int nChainHeight = GetBestHeight();
653 0 : if (nChainHeight < 0) return ret;
654 :
655 0 : for (int nHeight = nChainHeight - nLast; nHeight < nChainHeight + 20; nHeight++) {
656 0 : const uint256& hash = GetHashAtHeight(nHeight - 101);
657 0 : MasternodeRef winner = GetCurrentMasterNode(hash);
658 0 : if (winner) {
659 0 : ret.emplace_back(winner, nHeight);
660 : }
661 : }
662 0 : return ret;
663 : }
664 :
665 2495 : int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight) const
666 : {
667 2495 : const uint256& hash = GetHashAtHeight(nBlockHeight - 1);
668 : // height outside range
669 2495 : if (hash == UINT256_ZERO) return -1;
670 :
671 : // scan for winner
672 2495 : int minProtocol = ActiveProtocol();
673 4990 : std::vector<std::pair<int64_t, CTxIn> > vecMasternodeScores;
674 2495 : {
675 2495 : LOCK(cs);
676 40621 : for (const auto& it : mapMasternodes) {
677 38126 : const MasternodeRef& mn = it.second;
678 38126 : if (!mn->IsEnabled()) {
679 1876 : continue; // Skip not enabled
680 : }
681 36250 : if (mn->protocolVersion < minProtocol) {
682 0 : LogPrint(BCLog::MASTERNODE,"Skipping Masternode with obsolete version %d\n", mn->protocolVersion);
683 0 : continue; // Skip obsolete versions
684 : }
685 71686 : if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) &&
686 35436 : GetAdjustedTime() - mn->sigTime < MN_WINNER_MINIMUM_AGE) {
687 1137 : continue; // Skip masternodes younger than (default) 1 hour
688 : }
689 35113 : vecMasternodeScores.emplace_back(mn->CalculateScore(hash).GetCompact(false), mn->vin);
690 : }
691 : }
692 :
693 : // scan also dmns
694 2495 : if (deterministicMNManager->IsDIP3Enforced()) {
695 1483 : auto mnList = deterministicMNManager->GetListAtChainTip();
696 1483 : mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
697 2638 : const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
698 2638 : vecMasternodeScores.emplace_back(mn->CalculateScore(hash).GetCompact(false), mn->vin);
699 2638 : });
700 : }
701 :
702 2495 : sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
703 :
704 2495 : int rank = 0;
705 6538 : for (std::pair<int64_t, CTxIn> & s : vecMasternodeScores) {
706 6210 : rank++;
707 6210 : if (s.second.prevout == vin.prevout) {
708 2167 : return rank;
709 : }
710 : }
711 :
712 328 : return -1;
713 : }
714 :
715 468 : std::vector<std::pair<int64_t, MasternodeRef>> CMasternodeMan::GetMasternodeRanks(int nBlockHeight) const
716 : {
717 468 : std::vector<std::pair<int64_t, MasternodeRef>> vecMasternodeScores;
718 468 : const uint256& hash = GetHashAtHeight(nBlockHeight - 1);
719 : // height outside range
720 468 : if (hash == UINT256_ZERO) return vecMasternodeScores;
721 468 : {
722 468 : LOCK(cs);
723 : // scan for winner
724 6061 : for (const auto& it : mapMasternodes) {
725 11186 : const MasternodeRef mn = it.second;
726 5593 : const uint32_t score = mn->IsEnabled() ? mn->CalculateScore(hash).GetCompact(false) : 9999;
727 :
728 5593 : vecMasternodeScores.emplace_back(score, mn);
729 : }
730 : }
731 : // scan also dmns
732 468 : if (deterministicMNManager->IsDIP3Enforced()) {
733 156 : auto mnList = deterministicMNManager->GetListAtChainTip();
734 156 : mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
735 179 : const MasternodeRef mn = MakeMasternodeRefForDMN(dmn);
736 179 : const uint32_t score = dmn->IsPoSeBanned() ? 9999 : mn->CalculateScore(hash).GetCompact(false);
737 :
738 179 : vecMasternodeScores.emplace_back(score, mn);
739 179 : });
740 : }
741 468 : sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
742 468 : return vecMasternodeScores;
743 : }
744 :
745 68 : bool CMasternodeMan::CheckInputs(CMasternodeBroadcast& mnb, int nChainHeight, int& nDoS)
746 : {
747 68 : const auto& consensus = Params().GetConsensus();
748 : // incorrect ping or its sigTime
749 68 : if(mnb.lastPing.IsNull() || !mnb.lastPing.CheckAndUpdate(nDoS, false, true)) {
750 0 : return false;
751 : }
752 :
753 : // search existing Masternode list
754 68 : CMasternode* pmn = Find(mnb.vin.prevout);
755 68 : if (pmn != nullptr) {
756 : // nothing to do here if we already know about this masternode and it's enabled
757 10 : if (pmn->IsEnabled()) return true;
758 : // if it's not enabled, remove old MN first and continue
759 : else
760 10 : mnodeman.Remove(pmn->vin.prevout);
761 : }
762 :
763 68 : const Coin& collateralUtxo = pcoinsTip->AccessCoin(mnb.vin.prevout);
764 68 : if (collateralUtxo.IsSpent()) {
765 0 : LogPrint(BCLog::MASTERNODE,"mnb - vin %s spent\n", mnb.vin.prevout.ToString());
766 0 : return false;
767 : }
768 :
769 : // Check collateral value
770 68 : if (collateralUtxo.out.nValue != consensus.nMNCollateralAmt) {
771 0 : LogPrint(BCLog::MASTERNODE,"mnb - invalid amount for mnb collateral %s\n", mnb.vin.prevout.ToString());
772 0 : nDoS = 33;
773 0 : return false;
774 : }
775 :
776 : // Check collateral association with mnb pubkey
777 136 : CScript payee = GetScriptForDestination(mnb.pubKeyCollateralAddress.GetID());
778 68 : if (collateralUtxo.out.scriptPubKey != payee) {
779 0 : LogPrint(BCLog::MASTERNODE,"mnb - collateral %s not associated with mnb pubkey\n", mnb.vin.prevout.ToString());
780 0 : nDoS = 33;
781 0 : return false;
782 : }
783 :
784 68 : LogPrint(BCLog::MASTERNODE, "mnb - Accepted Masternode entry\n");
785 68 : const int utxoHeight = (int) collateralUtxo.nHeight;
786 68 : int collateralUtxoDepth = nChainHeight - utxoHeight + 1;
787 68 : if (collateralUtxoDepth < consensus.MasternodeCollateralMinConf()) {
788 0 : 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 0 : mapSeenMasternodeBroadcast.erase(mnb.GetHash());
791 0 : g_tiertwo_sync_state.EraseSeenMNB(mnb.GetHash());
792 0 : 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 204 : CBlockIndex* pConfIndex = WITH_LOCK(cs_main, return chainActive[utxoHeight + consensus.MasternodeCollateralMinConf() - 1]); // block where tx got MASTERNODE_MIN_CONFIRMATIONS
798 68 : if (pConfIndex->GetBlockTime() > mnb.sigTime) {
799 0 : 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 0 : return false;
802 : }
803 :
804 : // Good input
805 : return true;
806 : }
807 :
808 68 : int CMasternodeMan::ProcessMNBroadcast(CNode* pfrom, CMasternodeBroadcast& mnb)
809 : {
810 68 : const uint256& mnbHash = mnb.GetHash();
811 68 : if (mapSeenMasternodeBroadcast.count(mnbHash)) { //seen
812 0 : g_tiertwo_sync_state.AddedMasternodeList(mnbHash);
813 0 : return 0;
814 : }
815 :
816 68 : int chainHeight = GetBestHeight();
817 68 : int nDoS = 0;
818 68 : if (!mnb.CheckAndUpdate(nDoS)) {
819 0 : return nDoS;
820 : }
821 :
822 : // make sure it's still unspent
823 68 : if (!CheckInputs(mnb, chainHeight, nDoS)) {
824 0 : return nDoS; // error set internally
825 : }
826 :
827 : // now that did the mnb checks, can add it.
828 68 : mapSeenMasternodeBroadcast.emplace(mnbHash, mnb);
829 :
830 : // All checks performed, add it
831 136 : LogPrint(BCLog::MASTERNODE,"%s - Got NEW Masternode entry - %s - %lli \n", __func__,
832 : mnb.vin.prevout.hash.ToString(), mnb.sigTime);
833 136 : CMasternode mn(mnb);
834 68 : if (!Add(mn)) {
835 4 : LogPrint(BCLog::MASTERNODE, "%s - Rejected Masternode entry %s\n", __func__,
836 : mnb.vin.prevout.hash.ToString());
837 2 : return 0;
838 : }
839 :
840 : // if it matches our MN pubkey, then we've been remotely activated
841 66 : if (mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode && mnb.protocolVersion == PROTOCOL_VERSION) {
842 13 : activeMasternode.EnableHotColdMasterNode(mnb.vin, mnb.addr);
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 66 : bool isLocal = (mnb.addr.IsRFC1918() || mnb.addr.IsLocal()) && !Params().IsRegTestNet();
848 66 : if (!isLocal && g_tiertwo_sync_state.IsSynced()) mnb.Relay();
849 :
850 : // Add it as a peer
851 132 : g_connman->AddNewAddress(CAddress(mnb.addr, NODE_NETWORK), pfrom->addr, 2 * 60 * 60);
852 :
853 : // Update sync status
854 66 : g_tiertwo_sync_state.AddedMasternodeList(mnbHash);
855 :
856 : // All good
857 : return 0;
858 : }
859 :
860 52121 : int CMasternodeMan::ProcessMNPing(CNode* pfrom, CMasternodePing& mnp)
861 : {
862 52121 : const uint256& mnpHash = mnp.GetHash();
863 52121 : if (mapSeenMasternodePing.count(mnpHash)) return 0; //seen
864 :
865 52121 : int nDoS = 0;
866 52121 : if (mnp.CheckAndUpdate(nDoS)) return 0;
867 :
868 50037 : 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 50031 : CMasternode* pmn = Find(mnp.vin.prevout);
874 : // if it's known, don't ask for the mnb, just return
875 50031 : 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).
880 50000 : if (g_tiertwo_sync_state.IsSynced()) {
881 0 : AskForMN(pfrom, mnp.vin);
882 : }
883 :
884 : // All good
885 : return 0;
886 : }
887 :
888 20 : void CMasternodeMan::BroadcastInvMN(CMasternode* mn, CNode* pfrom)
889 : {
890 20 : CMasternodeBroadcast mnb = CMasternodeBroadcast(*mn);
891 20 : const uint256& hash = mnb.GetHash();
892 20 : pfrom->PushInventory(CInv(MSG_MASTERNODE_ANNOUNCE, hash));
893 :
894 : // Add to mapSeenMasternodeBroadcast in case that isn't there for some reason.
895 40 : if (!mapSeenMasternodeBroadcast.count(hash)) mapSeenMasternodeBroadcast.emplace(hash, mnb);
896 20 : }
897 :
898 845 : int CMasternodeMan::ProcessGetMNList(CNode* pfrom, CTxIn& vin)
899 : {
900 : // Single MN request
901 845 : if (!vin.IsNull()) {
902 2 : CMasternode* mn = Find(vin.prevout);
903 4 : if (!mn || !mn->IsEnabled()) return 0; // Nothing to return.
904 :
905 : // Relay the MN.
906 2 : BroadcastInvMN(mn, pfrom);
907 2 : LogPrint(BCLog::MASTERNODE, "dseg - Sent 1 Masternode entry to peer %i\n", pfrom->GetId());
908 2 : return 0;
909 : }
910 :
911 : // Check if the node asked for mn list sync before.
912 843 : bool isLocal = (pfrom->addr.IsRFC1918() || pfrom->addr.IsLocal());
913 0 : if (!isLocal) {
914 0 : auto itAskedUsMNList = mAskedUsForMasternodeList.find(pfrom->addr);
915 0 : if (itAskedUsMNList != mAskedUsForMasternodeList.end()) {
916 0 : int64_t t = (*itAskedUsMNList).second;
917 0 : if (GetTime() < t) {
918 0 : LogPrintf("CMasternodeMan::ProcessMessage() : dseg - peer already asked me for the list\n");
919 0 : return 20;
920 : }
921 : }
922 0 : int64_t askAgain = GetTime() + MASTERNODES_REQUEST_SECONDS;
923 0 : mAskedUsForMasternodeList[pfrom->addr] = askAgain;
924 : }
925 :
926 843 : int nInvCount = 0;
927 843 : {
928 843 : LOCK(cs);
929 861 : for (auto& it : mapMasternodes) {
930 18 : MasternodeRef& mn = it.second;
931 18 : if (mn->addr.IsRFC1918()) continue; //local network
932 18 : if (mn->IsEnabled()) {
933 36 : LogPrint(BCLog::MASTERNODE, "dseg - Sending Masternode entry - %s \n", mn->vin.prevout.hash.ToString());
934 18 : BroadcastInvMN(mn.get(), pfrom);
935 18 : nInvCount++;
936 : }
937 : }
938 : }
939 :
940 843 : g_connman->PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_LIST, nInvCount));
941 843 : 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 55750 : bool CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv, int& dosScore)
948 : {
949 55750 : dosScore = ProcessMessageInner(pfrom, strCommand, vRecv);
950 55750 : return dosScore == 0;
951 : }
952 :
953 55750 : int CMasternodeMan::ProcessMessageInner(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
954 : {
955 55750 : if (!g_tiertwo_sync_state.IsBlockchainSynced()) return 0;
956 :
957 : // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
958 55740 : if (deterministicMNManager->LegacyMNObsolete()) {
959 878 : LogPrint(BCLog::MASTERNODE, "%s: skip obsolete message %s\n", __func__, strCommand);
960 878 : return 0;
961 : }
962 :
963 110612 : LOCK(cs_process_message);
964 :
965 54862 : if (strCommand == NetMsgType::MNBROADCAST) {
966 136 : CMasternodeBroadcast mnb;
967 68 : vRecv >> mnb;
968 68 : {
969 : // Clear inv request
970 68 : LOCK(cs_main);
971 68 : g_connman->RemoveAskFor(mnb.GetHash(), MSG_MASTERNODE_ANNOUNCE);
972 : }
973 68 : return ProcessMNBroadcast(pfrom, mnb);
974 :
975 54794 : } else if (strCommand == NetMsgType::MNBROADCAST2) {
976 0 : CMasternodeBroadcast mnb;
977 0 : OverrideStream<CDataStream> s(&vRecv, vRecv.GetType(), vRecv.GetVersion() | ADDRV2_FORMAT);
978 0 : s >> mnb;
979 0 : {
980 : // Clear inv request
981 0 : LOCK(cs_main);
982 0 : 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 0 : if (mnb.addr.IsAddrV1Compatible()) {
987 0 : LogPrint(BCLog::MASTERNODE, "%s: mnb2 with pre-BIP155 node addr format rejected\n", __func__);
988 0 : return 30;
989 : }
990 :
991 0 : return ProcessMNBroadcast(pfrom, mnb);
992 :
993 54794 : } else if (strCommand == NetMsgType::MNPING) {
994 : //Masternode Ping
995 104242 : CMasternodePing mnp;
996 52121 : vRecv >> mnp;
997 104242 : LogPrint(BCLog::MNPING, "mnp - Masternode ping, vin: %s\n", mnp.vin.prevout.hash.ToString());
998 52121 : {
999 : // Clear inv request
1000 52121 : LOCK(cs_main);
1001 52121 : g_connman->RemoveAskFor(mnp.GetHash(), MSG_MASTERNODE_PING);
1002 : }
1003 52121 : return ProcessMNPing(pfrom, mnp);
1004 :
1005 2673 : } else if (strCommand == NetMsgType::GETMNLIST) {
1006 : //Get Masternode list or specific entry
1007 0 : CTxIn vin;
1008 0 : vRecv >> vin;
1009 0 : return ProcessGetMNList(pfrom, vin);
1010 : }
1011 : // Nothing to report
1012 : return 0;
1013 : }
1014 :
1015 11 : void CMasternodeMan::Remove(const COutPoint& collateralOut)
1016 : {
1017 11 : LOCK(cs);
1018 11 : const auto it = mapMasternodes.find(collateralOut);
1019 11 : if (it != mapMasternodes.end()) {
1020 11 : mapMasternodes.erase(it);
1021 : }
1022 11 : }
1023 :
1024 14 : void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast& mnb)
1025 : {
1026 : // Skip after legacy obsolete. !TODO: remove when transition to DMN is complete
1027 14 : if (deterministicMNManager->LegacyMNObsolete()) {
1028 : return;
1029 : }
1030 :
1031 14 : mapSeenMasternodePing.emplace(mnb.lastPing.GetHash(), mnb.lastPing);
1032 14 : mapSeenMasternodeBroadcast.emplace(mnb.GetHash(), mnb);
1033 14 : g_tiertwo_sync_state.AddedMasternodeList(mnb.GetHash());
1034 :
1035 28 : LogPrint(BCLog::MASTERNODE,"%s -- masternode=%s\n", __func__, mnb.vin.prevout.ToString());
1036 :
1037 14 : CMasternode* pmn = Find(mnb.vin.prevout);
1038 14 : if (pmn == nullptr) {
1039 24 : CMasternode mn(mnb);
1040 12 : Add(mn);
1041 : } else {
1042 2 : pmn->UpdateFromNewBroadcast(mnb);
1043 : }
1044 : }
1045 :
1046 277 : int64_t CMasternodeMan::SecondsSincePayment(const MasternodeRef& mn, int count_enabled, const CBlockIndex* BlockReading) const
1047 : {
1048 277 : int64_t sec = (GetAdjustedTime() - GetLastPaid(mn, count_enabled, BlockReading));
1049 277 : int64_t month = 60 * 60 * 24 * 30;
1050 277 : if (sec < month) return sec; //if it's less than 30 days, give seconds
1051 :
1052 217 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
1053 217 : ss << mn->vin;
1054 217 : ss << mn->sigTime;
1055 434 : 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 217 : return month + hash.GetCompact(false);
1059 : }
1060 :
1061 591 : int64_t CMasternodeMan::GetLastPaid(const MasternodeRef& mn, int count_enabled, const CBlockIndex* BlockReading) const
1062 : {
1063 591 : if (BlockReading == nullptr) return false;
1064 :
1065 1182 : const CScript& mnpayee = mn->GetPayeeScript();
1066 :
1067 591 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
1068 591 : ss << mn->vin;
1069 591 : ss << mn->sigTime;
1070 591 : const uint256& hash = ss.GetHash();
1071 :
1072 : // use a deterministic offset to break a tie -- 2.5 minutes
1073 591 : int64_t nOffset = UintToArith256(hash).GetCompact(false) % 150;
1074 :
1075 591 : int max_depth = count_enabled * 1.25;
1076 1840 : for (int n = 0; n < max_depth; n++) {
1077 1309 : const auto& it = masternodePayments.mapMasternodeBlocks.find(BlockReading->nHeight);
1078 1309 : 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 230 : if (it->second.HasPayeeWithVotes(mnpayee, 2))
1082 60 : return BlockReading->nTime + nOffset;
1083 : }
1084 1249 : BlockReading = BlockReading->pprev;
1085 :
1086 1249 : if (BlockReading == nullptr || BlockReading->nHeight <= 0) {
1087 : break;
1088 : }
1089 : }
1090 :
1091 : return 0;
1092 : }
1093 :
1094 456 : std::string CMasternodeMan::ToString() const
1095 : {
1096 456 : std::ostringstream info;
1097 456 : info << "Masternodes: " << (int)mapMasternodes.size()
1098 456 : << ", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size()
1099 456 : << ", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size()
1100 456 : << ", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size();
1101 456 : return info.str();
1102 : }
1103 :
1104 66091 : void CMasternodeMan::CacheBlockHash(const CBlockIndex* pindex)
1105 : {
1106 66091 : cvLastBlockHashes.Set(pindex->nHeight, pindex->GetBlockHash());
1107 66091 : }
1108 :
1109 166 : void CMasternodeMan::UncacheBlockHash(const CBlockIndex* pindex)
1110 : {
1111 166 : cvLastBlockHashes.Set(pindex->nHeight, UINT256_ZERO);
1112 166 : }
1113 :
1114 98420 : uint256 CMasternodeMan::GetHashAtHeight(int nHeight) const
1115 : {
1116 : // return zero if outside bounds
1117 98420 : if (nHeight < 0) {
1118 0 : LogPrint(BCLog::MASTERNODE, "%s: Negative height. Returning 0\n", __func__);
1119 0 : return UINT256_ZERO;
1120 : }
1121 98420 : int nCurrentHeight = GetBestHeight();
1122 98420 : if (nHeight > nCurrentHeight) {
1123 1 : LogPrint(BCLog::MASTERNODE, "%s: height %d over current height %d. Returning 0\n",
1124 : __func__, nHeight, nCurrentHeight);
1125 1 : return UINT256_ZERO;
1126 : }
1127 :
1128 98419 : if (nHeight > nCurrentHeight - (int) CACHED_BLOCK_HASHES) {
1129 : // Use cached hash
1130 98419 : return cvLastBlockHashes.Get(nHeight);
1131 : } else {
1132 : // Use chainActive
1133 0 : LOCK(cs_main);
1134 0 : return chainActive[nHeight]->GetBlockHash();
1135 : }
1136 : }
1137 :
1138 52269 : bool CMasternodeMan::IsWithinDepth(const uint256& nHash, int depth) const
1139 : {
1140 : // Sanity checks
1141 104538 : if (nHash.IsNull()) {
1142 0 : return error("%s: Called with null hash\n", __func__);
1143 : }
1144 52269 : if (depth < 0 || (unsigned) depth >= CACHED_BLOCK_HASHES) {
1145 0 : 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 52269 : const int nCurrentHeight = GetBestHeight();
1149 52269 : int nStopHeight = std::max(0, nCurrentHeight - depth);
1150 80329 : for (int i = nCurrentHeight; i >= nStopHeight; i--) {
1151 80328 : if (GetHashAtHeight(i) == nHash)
1152 : return true;
1153 : }
1154 : return false;
1155 : }
1156 :
1157 355 : void ThreadCheckMasternodes()
1158 : {
1159 : // Make this thread recognisable as the wallet flushing thread
1160 355 : util::ThreadRename("pivx-masternodeman");
1161 355 : LogPrintf("Masternodes thread started\n");
1162 :
1163 355 : unsigned int c = 0;
1164 :
1165 355 : try {
1166 : // first clean up stale masternode payments data
1167 355 : masternodePayments.CleanPaymentList(mnodeman.CheckAndRemove(), mnodeman.GetBestHeight());
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 355 : auto itSeenMNB = mnodeman.mapSeenMasternodeBroadcast.begin();
1172 355 : while (itSeenMNB != mnodeman.mapSeenMasternodeBroadcast.end()) {
1173 0 : if (!itSeenMNB->second.addr.IsValid()) {
1174 0 : itSeenMNB = mnodeman.mapSeenMasternodeBroadcast.erase(itSeenMNB);
1175 : } else {
1176 355 : itSeenMNB++;
1177 : }
1178 : }
1179 :
1180 19407 : while (true) {
1181 :
1182 19407 : if (ShutdownRequested()) {
1183 : break;
1184 : }
1185 :
1186 19217 : MilliSleep(1000);
1187 19052 : boost::this_thread::interruption_point();
1188 :
1189 : // try to sync from all available nodes, one step at a time
1190 19052 : masternodeSync.Process();
1191 :
1192 19052 : if (g_tiertwo_sync_state.IsBlockchainSynced()) {
1193 16776 : c++;
1194 :
1195 : // check if we should activate or ping every few minutes,
1196 : // start right after sync is considered to be done
1197 16776 : if (c % (MasternodePingSeconds()/2) == 0)
1198 1287 : activeMasternode.ManageStatus();
1199 :
1200 16776 : if (c % (MasternodePingSeconds()/5) == 0) {
1201 3265 : masternodePayments.CleanPaymentList(mnodeman.CheckAndRemove(), mnodeman.GetBestHeight());
1202 : }
1203 : }
1204 : }
1205 165 : } catch (boost::thread_interrupted&) {
1206 : // nothing, thread interrupted.
1207 : }
1208 355 : }
|