Dash Core  0.12.2.1
P2P Digital Currency
masternode-payments.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 The Dash Core developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "activemasternode.h"
6 #include "governance-classes.h"
7 #include "masternode-payments.h"
8 #include "masternode-sync.h"
9 #include "masternodeman.h"
10 #include "messagesigner.h"
11 #include "netfulfilledman.h"
12 #include "spork.h"
13 #include "util.h"
14 
15 #include <boost/lexical_cast.hpp>
16 
19 
23 
35 bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward, std::string &strErrorRet)
36 {
37  strErrorRet = "";
38 
39  bool isBlockRewardValueMet = (block.vtx[0].GetValueOut() <= blockReward);
40  if(fDebug) LogPrintf("block.vtx[0].GetValueOut() %lld <= blockReward %lld\n", block.vtx[0].GetValueOut(), blockReward);
41 
42  // we are still using budgets, but we have no data about them anymore,
43  // all we know is predefined budget cycle and window
44 
45  const Consensus::Params& consensusParams = Params().GetConsensus();
46 
47  if(nBlockHeight < consensusParams.nSuperblockStartBlock) {
48  int nOffset = nBlockHeight % consensusParams.nBudgetPaymentsCycleBlocks;
49  if(nBlockHeight >= consensusParams.nBudgetPaymentsStartBlock &&
50  nOffset < consensusParams.nBudgetPaymentsWindowBlocks) {
51  // NOTE: make sure SPORK_13_OLD_SUPERBLOCK_FLAG is disabled when 12.1 starts to go live
53  // no budget blocks should be accepted here, if SPORK_13_OLD_SUPERBLOCK_FLAG is disabled
54  LogPrint("gobject", "IsBlockValueValid -- Client synced but budget spork is disabled, checking block value against block reward\n");
55  if(!isBlockRewardValueMet) {
56  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, budgets are disabled",
57  nBlockHeight, block.vtx[0].GetValueOut(), blockReward);
58  }
59  return isBlockRewardValueMet;
60  }
61  LogPrint("gobject", "IsBlockValueValid -- WARNING: Skipping budget block value checks, accepting block\n");
62  // TODO: reprocess blocks to make sure they are legit?
63  return true;
64  }
65  // LogPrint("gobject", "IsBlockValueValid -- Block is not in budget cycle window, checking block value against block reward\n");
66  if(!isBlockRewardValueMet) {
67  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, block is not in budget cycle window",
68  nBlockHeight, block.vtx[0].GetValueOut(), blockReward);
69  }
70  return isBlockRewardValueMet;
71  }
72 
73  // superblocks started
74 
75  CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit(nBlockHeight);
76  bool isSuperblockMaxValueMet = (block.vtx[0].GetValueOut() <= nSuperblockMaxValue);
77 
78  LogPrint("gobject", "block.vtx[0].GetValueOut() %lld <= nSuperblockMaxValue %lld\n", block.vtx[0].GetValueOut(), nSuperblockMaxValue);
79 
80  if(!masternodeSync.IsSynced()) {
81  // not enough data but at least it must NOT exceed superblock max value
82  if(CSuperblock::IsValidBlockHeight(nBlockHeight)) {
83  if(fDebug) LogPrintf("IsBlockPayeeValid -- WARNING: Client not synced, checking superblock max bounds only\n");
84  if(!isSuperblockMaxValueMet) {
85  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded superblock max value",
86  nBlockHeight, block.vtx[0].GetValueOut(), nSuperblockMaxValue);
87  }
88  return isSuperblockMaxValueMet;
89  }
90  if(!isBlockRewardValueMet) {
91  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, only regular blocks are allowed at this height",
92  nBlockHeight, block.vtx[0].GetValueOut(), blockReward);
93  }
94  // it MUST be a regular block otherwise
95  return isBlockRewardValueMet;
96  }
97 
98  // we are synced, let's try to check as much data as we can
99 
102  if(CSuperblockManager::IsValid(block.vtx[0], nBlockHeight, blockReward)) {
103  LogPrint("gobject", "IsBlockValueValid -- Valid superblock at height %d: %s", nBlockHeight, block.vtx[0].ToString());
104  // all checks are done in CSuperblock::IsValid, nothing to do here
105  return true;
106  }
107 
108  // triggered but invalid? that's weird
109  LogPrintf("IsBlockValueValid -- ERROR: Invalid superblock detected at height %d: %s", nBlockHeight, block.vtx[0].ToString());
110  // should NOT allow invalid superblocks, when superblocks are enabled
111  strErrorRet = strprintf("invalid superblock detected at height %d", nBlockHeight);
112  return false;
113  }
114  LogPrint("gobject", "IsBlockValueValid -- No triggered superblock detected at height %d\n", nBlockHeight);
115  if(!isBlockRewardValueMet) {
116  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, no triggered superblock detected",
117  nBlockHeight, block.vtx[0].GetValueOut(), blockReward);
118  }
119  } else {
120  // should NOT allow superblocks at all, when superblocks are disabled
121  LogPrint("gobject", "IsBlockValueValid -- Superblocks are disabled, no superblocks allowed\n");
122  if(!isBlockRewardValueMet) {
123  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, superblocks are disabled",
124  nBlockHeight, block.vtx[0].GetValueOut(), blockReward);
125  }
126  }
127 
128  // it MUST be a regular block
129  return isBlockRewardValueMet;
130 }
131 
132 bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
133 {
134  if(!masternodeSync.IsSynced()) {
135  //there is no budget data to use to check anything, let's just accept the longest chain
136  if(fDebug) LogPrintf("IsBlockPayeeValid -- WARNING: Client not synced, skipping block payee checks\n");
137  return true;
138  }
139 
140  // we are still using budgets, but we have no data about them anymore,
141  // we can only check masternode payments
142 
143  const Consensus::Params& consensusParams = Params().GetConsensus();
144 
145  if(nBlockHeight < consensusParams.nSuperblockStartBlock) {
146  if(mnpayments.IsTransactionValid(txNew, nBlockHeight)) {
147  LogPrint("mnpayments", "IsBlockPayeeValid -- Valid masternode payment at height %d: %s", nBlockHeight, txNew.ToString());
148  return true;
149  }
150 
151  int nOffset = nBlockHeight % consensusParams.nBudgetPaymentsCycleBlocks;
152  if(nBlockHeight >= consensusParams.nBudgetPaymentsStartBlock &&
153  nOffset < consensusParams.nBudgetPaymentsWindowBlocks) {
155  // no budget blocks should be accepted here, if SPORK_13_OLD_SUPERBLOCK_FLAG is disabled
156  LogPrint("gobject", "IsBlockPayeeValid -- ERROR: Client synced but budget spork is disabled and masternode payment is invalid\n");
157  return false;
158  }
159  // NOTE: this should never happen in real, SPORK_13_OLD_SUPERBLOCK_FLAG MUST be disabled when 12.1 starts to go live
160  LogPrint("gobject", "IsBlockPayeeValid -- WARNING: Probably valid budget block, have no data, accepting\n");
161  // TODO: reprocess blocks to make sure they are legit?
162  return true;
163  }
164 
166  LogPrintf("IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s", nBlockHeight, txNew.ToString());
167  return false;
168  }
169 
170  LogPrintf("IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee\n");
171  return true;
172  }
173 
174  // superblocks started
175  // SEE IF THIS IS A VALID SUPERBLOCK
176 
179  if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) {
180  LogPrint("gobject", "IsBlockPayeeValid -- Valid superblock at height %d: %s", nBlockHeight, txNew.ToString());
181  return true;
182  }
183 
184  LogPrintf("IsBlockPayeeValid -- ERROR: Invalid superblock detected at height %d: %s", nBlockHeight, txNew.ToString());
185  // should NOT allow such superblocks, when superblocks are enabled
186  return false;
187  }
188  // continue validation, should pay MN
189  LogPrint("gobject", "IsBlockPayeeValid -- No triggered superblock detected at height %d\n", nBlockHeight);
190  } else {
191  // should NOT allow superblocks at all, when superblocks are disabled
192  LogPrint("gobject", "IsBlockPayeeValid -- Superblocks are disabled, no superblocks allowed\n");
193  }
194 
195  // IF THIS ISN'T A SUPERBLOCK OR SUPERBLOCK IS INVALID, IT SHOULD PAY A MASTERNODE DIRECTLY
196  if(mnpayments.IsTransactionValid(txNew, nBlockHeight)) {
197  LogPrint("mnpayments", "IsBlockPayeeValid -- Valid masternode payment at height %d: %s", nBlockHeight, txNew.ToString());
198  return true;
199  }
200 
202  LogPrintf("IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s", nBlockHeight, txNew.ToString());
203  return false;
204  }
205 
206  LogPrintf("IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee\n");
207  return true;
208 }
209 
210 void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet, std::vector<CTxOut>& voutSuperblockRet)
211 {
212  // only create superblocks if spork is enabled AND if superblock is actually triggered
213  // (height should be validated inside)
216  LogPrint("gobject", "FillBlockPayments -- triggered superblock creation at height %d\n", nBlockHeight);
217  CSuperblockManager::CreateSuperblock(txNew, nBlockHeight, voutSuperblockRet);
218  return;
219  }
220 
221  // FILL BLOCK PAYEE WITH MASTERNODE PAYMENT OTHERWISE
222  mnpayments.FillBlockPayee(txNew, nBlockHeight, blockReward, txoutMasternodeRet);
223  LogPrint("mnpayments", "FillBlockPayments -- nBlockHeight %d blockReward %lld txoutMasternodeRet %s txNew %s",
224  nBlockHeight, blockReward, txoutMasternodeRet.ToString(), txNew.ToString());
225 }
226 
227 std::string GetRequiredPaymentsString(int nBlockHeight)
228 {
229  // IF WE HAVE A ACTIVATED TRIGGER FOR THIS HEIGHT - IT IS A SUPERBLOCK, GET THE REQUIRED PAYEES
232  }
233 
234  // OTHERWISE, PAY MASTERNODE
235  return mnpayments.GetRequiredPaymentsString(nBlockHeight);
236 }
237 
239 {
241  mapMasternodeBlocks.clear();
243 }
244 
245 bool CMasternodePayments::CanVote(COutPoint outMasternode, int nBlockHeight)
246 {
248 
249  if (mapMasternodesLastVote.count(outMasternode) && mapMasternodesLastVote[outMasternode] == nBlockHeight) {
250  return false;
251  }
252 
253  //record this masternode voted
254  mapMasternodesLastVote[outMasternode] = nBlockHeight;
255  return true;
256 }
257 
264 void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet)
265 {
266  // make sure it's not filled yet
267  txoutMasternodeRet = CTxOut();
268 
269  CScript payee;
270 
271  if(!mnpayments.GetBlockPayee(nBlockHeight, payee)) {
272  // no masternode detected...
273  int nCount = 0;
274  masternode_info_t mnInfo;
275  if(!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
276  // ...and we can't calculate it on our own
277  LogPrintf("CMasternodePayments::FillBlockPayee -- Failed to detect masternode to pay\n");
278  return;
279  }
280  // fill payee with locally calculated winner and hope for the best
282  }
283 
284  // GET MASTERNODE PAYMENT VARIABLES SETUP
285  CAmount masternodePayment = GetMasternodePayment(nBlockHeight, blockReward);
286 
287  // split reward between miner ...
288  txNew.vout[0].nValue -= masternodePayment;
289  // ... and masternode
290  txoutMasternodeRet = CTxOut(masternodePayment, payee);
291  txNew.vout.push_back(txoutMasternodeRet);
292 
293  CTxDestination address1;
294  ExtractDestination(payee, address1);
295  CBitcoinAddress address2(address1);
296 
297  LogPrintf("CMasternodePayments::FillBlockPayee -- Masternode payment %lld to %s\n", masternodePayment, address2.ToString());
298 }
299 
304 }
305 
306 void CMasternodePayments::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv, CConnman& connman)
307 {
308  // Ignore any payments messages until masternode list is synced
310 
311  if(fLiteMode) return; // disable all Dash specific functionality
312 
313  if (strCommand == NetMsgType::MASTERNODEPAYMENTSYNC) { //Masternode Payments Request Sync
314 
315  // Ignore such requests until we are fully synced.
316  // We could start processing this after masternode list is synced
317  // but this is a heavy one so it's better to finish sync first.
318  if (!masternodeSync.IsSynced()) return;
319 
320  int nCountNeeded;
321  vRecv >> nCountNeeded;
322 
324  // Asking for the payments list multiple times in a short period of time is no good
325  LogPrintf("MASTERNODEPAYMENTSYNC -- peer already asked me for the list, peer=%d\n", pfrom->id);
326  Misbehaving(pfrom->GetId(), 20);
327  return;
328  }
330 
331  Sync(pfrom, connman);
332  LogPrintf("MASTERNODEPAYMENTSYNC -- Sent Masternode payment votes to peer %d\n", pfrom->id);
333 
334  } else if (strCommand == NetMsgType::MASTERNODEPAYMENTVOTE) { // Masternode Payments Vote for the Winner
335 
337  vRecv >> vote;
338 
339  if(pfrom->nVersion < GetMinMasternodePaymentsProto()) return;
340 
341  uint256 nHash = vote.GetHash();
342 
343  pfrom->setAskFor.erase(nHash);
344 
345  {
347  if(mapMasternodePaymentVotes.count(nHash)) {
348  LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- hash=%s, nHeight=%d seen\n", nHash.ToString(), nCachedBlockHeight);
349  return;
350  }
351 
352  // Avoid processing same vote multiple times
353  mapMasternodePaymentVotes[nHash] = vote;
354  // but first mark vote as non-verified,
355  // AddPaymentVote() below should take care of it if vote is actually ok
356  mapMasternodePaymentVotes[nHash].MarkAsNotVerified();
357  }
358 
359  int nFirstBlock = nCachedBlockHeight - GetStorageLimit();
360  if(vote.nBlockHeight < nFirstBlock || vote.nBlockHeight > nCachedBlockHeight+20) {
361  LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- vote out of range: nFirstBlock=%d, nBlockHeight=%d, nHeight=%d\n", nFirstBlock, vote.nBlockHeight, nCachedBlockHeight);
362  return;
363  }
364 
365  std::string strError = "";
366  if(!vote.IsValid(pfrom, nCachedBlockHeight, strError, connman)) {
367  LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- invalid message, error: %s\n", strError);
368  return;
369  }
370 
371  if(!CanVote(vote.vinMasternode.prevout, vote.nBlockHeight)) {
372  LogPrintf("MASTERNODEPAYMENTVOTE -- masternode already voted, masternode=%s\n", vote.vinMasternode.prevout.ToStringShort());
373  return;
374  }
375 
376  masternode_info_t mnInfo;
377  if(!mnodeman.GetMasternodeInfo(vote.vinMasternode.prevout, mnInfo)) {
378  // mn was not found, so we can't check vote, some info is probably missing
379  LogPrintf("MASTERNODEPAYMENTVOTE -- masternode is missing %s\n", vote.vinMasternode.prevout.ToStringShort());
380  mnodeman.AskForMN(pfrom, vote.vinMasternode.prevout, connman);
381  return;
382  }
383 
384  int nDos = 0;
385  if(!vote.CheckSignature(mnInfo.pubKeyMasternode, nCachedBlockHeight, nDos)) {
386  if(nDos) {
387  LogPrintf("MASTERNODEPAYMENTVOTE -- ERROR: invalid signature\n");
388  Misbehaving(pfrom->GetId(), nDos);
389  } else {
390  // only warn about anything non-critical (i.e. nDos == 0) in debug mode
391  LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- WARNING: invalid signature\n");
392  }
393  // Either our info or vote info could be outdated.
394  // In case our info is outdated, ask for an update,
395  mnodeman.AskForMN(pfrom, vote.vinMasternode.prevout, connman);
396  // but there is nothing we can do if vote info itself is outdated
397  // (i.e. it was signed by a mn which changed its key),
398  // so just quit here.
399  return;
400  }
401 
402  CTxDestination address1;
403  ExtractDestination(vote.payee, address1);
404  CBitcoinAddress address2(address1);
405 
406  LogPrint("mnpayments", "MASTERNODEPAYMENTVOTE -- vote: address=%s, nBlockHeight=%d, nHeight=%d, prevout=%s, hash=%s new\n",
407  address2.ToString(), vote.nBlockHeight, nCachedBlockHeight, vote.vinMasternode.prevout.ToStringShort(), nHash.ToString());
408 
409  if(AddPaymentVote(vote)){
410  vote.Relay(connman);
411  masternodeSync.BumpAssetLastTime("MASTERNODEPAYMENTVOTE");
412  }
413  }
414 }
415 
417 {
418  std::string strError;
419  std::string strMessage = vinMasternode.prevout.ToStringShort() +
420  boost::lexical_cast<std::string>(nBlockHeight) +
422 
424  LogPrintf("CMasternodePaymentVote::Sign -- SignMessage() failed\n");
425  return false;
426  }
427 
429  LogPrintf("CMasternodePaymentVote::Sign -- VerifyMessage() failed, error: %s\n", strError);
430  return false;
431  }
432 
433  return true;
434 }
435 
436 bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
437 {
438  if(mapMasternodeBlocks.count(nBlockHeight)){
439  return mapMasternodeBlocks[nBlockHeight].GetBestPayee(payee);
440  }
441 
442  return false;
443 }
444 
445 // Is this masternode scheduled to get paid soon?
446 // -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 blocks of votes
447 bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
448 {
450 
451  if(!masternodeSync.IsMasternodeListSynced()) return false;
452 
453  CScript mnpayee;
455 
456  CScript payee;
457  for(int64_t h = nCachedBlockHeight; h <= nCachedBlockHeight + 8; h++){
458  if(h == nNotBlockHeight) continue;
459  if(mapMasternodeBlocks.count(h) && mapMasternodeBlocks[h].GetBestPayee(payee) && mnpayee == payee) {
460  return true;
461  }
462  }
463 
464  return false;
465 }
466 
468 {
469  uint256 blockHash = uint256();
470  if(!GetBlockHash(blockHash, vote.nBlockHeight - 101)) return false;
471 
472  if(HasVerifiedPaymentVote(vote.GetHash())) return false;
473 
475 
476  mapMasternodePaymentVotes[vote.GetHash()] = vote;
477 
478  if(!mapMasternodeBlocks.count(vote.nBlockHeight)) {
479  CMasternodeBlockPayees blockPayees(vote.nBlockHeight);
480  mapMasternodeBlocks[vote.nBlockHeight] = blockPayees;
481  }
482 
483  mapMasternodeBlocks[vote.nBlockHeight].AddPayee(vote);
484 
485  return true;
486 }
487 
489 {
491  std::map<uint256, CMasternodePaymentVote>::iterator it = mapMasternodePaymentVotes.find(hashIn);
492  return it != mapMasternodePaymentVotes.end() && it->second.IsVerified();
493 }
494 
496 {
498 
499  BOOST_FOREACH(CMasternodePayee& payee, vecPayees) {
500  if (payee.GetPayee() == vote.payee) {
501  payee.AddVoteHash(vote.GetHash());
502  return;
503  }
504  }
505  CMasternodePayee payeeNew(vote.payee, vote.GetHash());
506  vecPayees.push_back(payeeNew);
507 }
508 
510 {
512 
513  if(!vecPayees.size()) {
514  LogPrint("mnpayments", "CMasternodeBlockPayees::GetBestPayee -- ERROR: couldn't find any payee\n");
515  return false;
516  }
517 
518  int nVotes = -1;
519  BOOST_FOREACH(CMasternodePayee& payee, vecPayees) {
520  if (payee.GetVoteCount() > nVotes) {
521  payeeRet = payee.GetPayee();
522  nVotes = payee.GetVoteCount();
523  }
524  }
525 
526  return (nVotes > -1);
527 }
528 
529 bool CMasternodeBlockPayees::HasPayeeWithVotes(const CScript& payeeIn, int nVotesReq)
530 {
532 
533  BOOST_FOREACH(CMasternodePayee& payee, vecPayees) {
534  if (payee.GetVoteCount() >= nVotesReq && payee.GetPayee() == payeeIn) {
535  return true;
536  }
537  }
538 
539  LogPrint("mnpayments", "CMasternodeBlockPayees::HasPayeeWithVotes -- ERROR: couldn't find any payee with %d+ votes\n", nVotesReq);
540  return false;
541 }
542 
544 {
546 
547  int nMaxSignatures = 0;
548  std::string strPayeesPossible = "";
549 
550  CAmount nMasternodePayment = GetMasternodePayment(nBlockHeight, txNew.GetValueOut());
551 
552  //require at least MNPAYMENTS_SIGNATURES_REQUIRED signatures
553 
554  BOOST_FOREACH(CMasternodePayee& payee, vecPayees) {
555  if (payee.GetVoteCount() >= nMaxSignatures) {
556  nMaxSignatures = payee.GetVoteCount();
557  }
558  }
559 
560  // if we don't have at least MNPAYMENTS_SIGNATURES_REQUIRED signatures on a payee, approve whichever is the longest chain
561  if(nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) return true;
562 
563  BOOST_FOREACH(CMasternodePayee& payee, vecPayees) {
565  BOOST_FOREACH(CTxOut txout, txNew.vout) {
566  if (payee.GetPayee() == txout.scriptPubKey && nMasternodePayment == txout.nValue) {
567  LogPrint("mnpayments", "CMasternodeBlockPayees::IsTransactionValid -- Found required payment\n");
568  return true;
569  }
570  }
571 
572  CTxDestination address1;
573  ExtractDestination(payee.GetPayee(), address1);
574  CBitcoinAddress address2(address1);
575 
576  if(strPayeesPossible == "") {
577  strPayeesPossible = address2.ToString();
578  } else {
579  strPayeesPossible += "," + address2.ToString();
580  }
581  }
582  }
583 
584  LogPrintf("CMasternodeBlockPayees::IsTransactionValid -- ERROR: Missing required payment, possible payees: '%s', amount: %f DASH\n", strPayeesPossible, (float)nMasternodePayment/COIN);
585  return false;
586 }
587 
589 {
591 
592  std::string strRequiredPayments = "Unknown";
593 
594  BOOST_FOREACH(CMasternodePayee& payee, vecPayees)
595  {
596  CTxDestination address1;
597  ExtractDestination(payee.GetPayee(), address1);
598  CBitcoinAddress address2(address1);
599 
600  if (strRequiredPayments != "Unknown") {
601  strRequiredPayments += ", " + address2.ToString() + ":" + boost::lexical_cast<std::string>(payee.GetVoteCount());
602  } else {
603  strRequiredPayments = address2.ToString() + ":" + boost::lexical_cast<std::string>(payee.GetVoteCount());
604  }
605  }
606 
607  return strRequiredPayments;
608 }
609 
611 {
613 
614  if(mapMasternodeBlocks.count(nBlockHeight)){
615  return mapMasternodeBlocks[nBlockHeight].GetRequiredPaymentsString();
616  }
617 
618  return "Unknown";
619 }
620 
621 bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight)
622 {
624 
625  if(mapMasternodeBlocks.count(nBlockHeight)){
626  return mapMasternodeBlocks[nBlockHeight].IsTransactionValid(txNew);
627  }
628 
629  return true;
630 }
631 
633 {
634  if(!masternodeSync.IsBlockchainSynced()) return;
635 
637 
638  int nLimit = GetStorageLimit();
639 
640  std::map<uint256, CMasternodePaymentVote>::iterator it = mapMasternodePaymentVotes.begin();
641  while(it != mapMasternodePaymentVotes.end()) {
642  CMasternodePaymentVote vote = (*it).second;
643 
644  if(nCachedBlockHeight - vote.nBlockHeight > nLimit) {
645  LogPrint("mnpayments", "CMasternodePayments::CheckAndRemove -- Removing old Masternode payment: nBlockHeight=%d\n", vote.nBlockHeight);
646  mapMasternodePaymentVotes.erase(it++);
647  mapMasternodeBlocks.erase(vote.nBlockHeight);
648  } else {
649  ++it;
650  }
651  }
652  LogPrintf("CMasternodePayments::CheckAndRemove -- %s\n", ToString());
653 }
654 
655 bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::string& strError, CConnman& connman)
656 {
657  masternode_info_t mnInfo;
658 
660  strError = strprintf("Unknown Masternode: prevout=%s", vinMasternode.prevout.ToStringShort());
661  // Only ask if we are already synced and still have no idea about that Masternode
663  mnodeman.AskForMN(pnode, vinMasternode.prevout, connman);
664  }
665 
666  return false;
667  }
668 
669  int nMinRequiredProtocol;
670  if(nBlockHeight >= nValidationHeight) {
671  // new votes must comply SPORK_10_MASTERNODE_PAY_UPDATED_NODES rules
672  nMinRequiredProtocol = mnpayments.GetMinMasternodePaymentsProto();
673  } else {
674  // allow non-updated masternodes for old blocks
675  nMinRequiredProtocol = MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1;
676  }
677 
678  if(mnInfo.nProtocolVersion < nMinRequiredProtocol) {
679  strError = strprintf("Masternode protocol is too old: nProtocolVersion=%d, nMinRequiredProtocol=%d", mnInfo.nProtocolVersion, nMinRequiredProtocol);
680  return false;
681  }
682 
683  // Only masternodes should try to check masternode rank for old votes - they need to pick the right winner for future blocks.
684  // Regular clients (miners included) need to verify masternode rank for future block votes only.
685  if(!fMasterNode && nBlockHeight < nValidationHeight) return true;
686 
687  int nRank;
688 
689  if(!mnodeman.GetMasternodeRank(vinMasternode.prevout, nRank, nBlockHeight - 101, nMinRequiredProtocol)) {
690  LogPrint("mnpayments", "CMasternodePaymentVote::IsValid -- Can't calculate rank for masternode %s\n",
692  return false;
693  }
694 
695  if(nRank > MNPAYMENTS_SIGNATURES_TOTAL) {
696  // It's common to have masternodes mistakenly think they are in the top 10
697  // We don't want to print all of these messages in normal mode, debug mode should print though
698  strError = strprintf("Masternode is not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL, nRank);
699  // Only ban for new mnw which is out of bounds, for old mnw MN list itself might be way too much off
700  if(nRank > MNPAYMENTS_SIGNATURES_TOTAL*2 && nBlockHeight > nValidationHeight) {
701  strError = strprintf("Masternode is not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL*2, nRank);
702  LogPrintf("CMasternodePaymentVote::IsValid -- Error: %s\n", strError);
703  // do not ban nodes before DIP0001 is locked in to avoid banning majority of (old) masternodes
704  if (fDIP0001WasLockedIn) {
705  Misbehaving(pnode->GetId(), 20);
706  }
707  }
708  // Still invalid however
709  return false;
710  }
711 
712  return true;
713 }
714 
715 bool CMasternodePayments::ProcessBlock(int nBlockHeight, CConnman& connman)
716 {
717  // DETERMINE IF WE SHOULD BE VOTING FOR THE NEXT PAYEE
718 
719  if(fLiteMode || !fMasterNode) return false;
720 
721  // We have little chances to pick the right winner if winners list is out of sync
722  // but we have no choice, so we'll try. However it doesn't make sense to even try to do so
723  // if we have not enough data about masternodes.
724  if(!masternodeSync.IsMasternodeListSynced()) return false;
725 
726  int nRank;
727 
729  LogPrint("mnpayments", "CMasternodePayments::ProcessBlock -- Unknown Masternode\n");
730  return false;
731  }
732 
733  if (nRank > MNPAYMENTS_SIGNATURES_TOTAL) {
734  LogPrint("mnpayments", "CMasternodePayments::ProcessBlock -- Masternode not in the top %d (%d)\n", MNPAYMENTS_SIGNATURES_TOTAL, nRank);
735  return false;
736  }
737 
738 
739  // LOCATE THE NEXT MASTERNODE WHICH SHOULD BE PAID
740 
741  LogPrintf("CMasternodePayments::ProcessBlock -- Start: nBlockHeight=%d, masternode=%s\n", nBlockHeight, activeMasternode.outpoint.ToStringShort());
742 
743  // pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
744  int nCount = 0;
745  masternode_info_t mnInfo;
746 
747  if (!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
748  LogPrintf("CMasternodePayments::ProcessBlock -- ERROR: Failed to find masternode to pay\n");
749  return false;
750  }
751 
752  LogPrintf("CMasternodePayments::ProcessBlock -- Masternode found by GetNextMasternodeInQueueForPayment(): %s\n", mnInfo.vin.prevout.ToStringShort());
753 
754 
756 
757  CMasternodePaymentVote voteNew(activeMasternode.outpoint, nBlockHeight, payee);
758 
759  CTxDestination address1;
760  ExtractDestination(payee, address1);
761  CBitcoinAddress address2(address1);
762 
763  LogPrintf("CMasternodePayments::ProcessBlock -- vote: payee=%s, nBlockHeight=%d\n", address2.ToString(), nBlockHeight);
764 
765  // SIGN MESSAGE TO NETWORK WITH OUR MASTERNODE KEYS
766 
767  LogPrintf("CMasternodePayments::ProcessBlock -- Signing vote\n");
768  if (voteNew.Sign()) {
769  LogPrintf("CMasternodePayments::ProcessBlock -- AddPaymentVote()\n");
770 
771  if (AddPaymentVote(voteNew)) {
772  voteNew.Relay(connman);
773  return true;
774  }
775  }
776 
777  return false;
778 }
779 
781 {
782  if (!masternodeSync.IsWinnersListSynced()) return;
783 
784  std::string debugStr;
785 
786  debugStr += strprintf("CMasternodePayments::CheckPreviousBlockVotes -- nPrevBlockHeight=%d, expected voting MNs:\n", nPrevBlockHeight);
787 
789  if (!mnodeman.GetMasternodeRanks(mns, nPrevBlockHeight - 101, GetMinMasternodePaymentsProto())) {
790  debugStr += "CMasternodePayments::CheckPreviousBlockVotes -- GetMasternodeRanks failed\n";
791  LogPrint("mnpayments", "%s", debugStr);
792  return;
793  }
794 
796 
797  for (int i = 0; i < MNPAYMENTS_SIGNATURES_TOTAL && i < (int)mns.size(); i++) {
798  auto mn = mns[i];
799  CScript payee;
800  bool found = false;
801 
802  if (mapMasternodeBlocks.count(nPrevBlockHeight)) {
803  for (auto &p : mapMasternodeBlocks[nPrevBlockHeight].vecPayees) {
804  for (auto &voteHash : p.GetVoteHashes()) {
805  if (!mapMasternodePaymentVotes.count(voteHash)) {
806  debugStr += strprintf("CMasternodePayments::CheckPreviousBlockVotes -- could not find vote %s\n",
807  voteHash.ToString());
808  continue;
809  }
810  auto vote = mapMasternodePaymentVotes[voteHash];
811  if (vote.vinMasternode.prevout == mn.second.vin.prevout) {
812  payee = vote.payee;
813  found = true;
814  break;
815  }
816  }
817  }
818  }
819 
820  if (!found) {
821  debugStr += strprintf("CMasternodePayments::CheckPreviousBlockVotes -- %s - no vote received\n",
822  mn.second.vin.prevout.ToStringShort());
823  mapMasternodesDidNotVote[mn.second.vin.prevout]++;
824  continue;
825  }
826 
827  CTxDestination address1;
828  ExtractDestination(payee, address1);
829  CBitcoinAddress address2(address1);
830 
831  debugStr += strprintf("CMasternodePayments::CheckPreviousBlockVotes -- %s - voted for %s\n",
832  mn.second.vin.prevout.ToStringShort(), address2.ToString());
833  }
834  debugStr += "CMasternodePayments::CheckPreviousBlockVotes -- Masternodes which missed a vote in the past:\n";
835  for (auto it : mapMasternodesDidNotVote) {
836  debugStr += strprintf("CMasternodePayments::CheckPreviousBlockVotes -- %s: %d\n", it.first.ToStringShort(), it.second);
837  }
838 
839  LogPrint("mnpayments", "%s", debugStr);
840 }
841 
843 {
844  // do not relay until synced
845  if (!masternodeSync.IsWinnersListSynced()) return;
847  // relay votes only strictly to new nodes until DIP0001 is locked in to avoid being banned by majority of (old) masternodes
849 }
850 
851 bool CMasternodePaymentVote::CheckSignature(const CPubKey& pubKeyMasternode, int nValidationHeight, int &nDos)
852 {
853  // do not ban by default
854  nDos = 0;
855 
856  std::string strMessage = vinMasternode.prevout.ToStringShort() +
857  boost::lexical_cast<std::string>(nBlockHeight) +
859 
860  std::string strError = "";
861  if (!CMessageSigner::VerifyMessage(pubKeyMasternode, vchSig, strMessage, strError)) {
862  // Only ban for future block vote when we are already synced.
863  // Otherwise it could be the case when MN which signed this vote is using another key now
864  // and we have no idea about the old one.
865  if(masternodeSync.IsMasternodeListSynced() && nBlockHeight > nValidationHeight) {
866  nDos = 20;
867  }
868  return error("CMasternodePaymentVote::CheckSignature -- Got bad Masternode payment signature, masternode=%s, error: %s", vinMasternode.prevout.ToStringShort().c_str(), strError);
869  }
870 
871  return true;
872 }
873 
875 {
876  std::ostringstream info;
877 
878  info << vinMasternode.prevout.ToStringShort() <<
879  ", " << nBlockHeight <<
880  ", " << ScriptToAsmStr(payee) <<
881  ", " << (int)vchSig.size();
882 
883  return info.str();
884 }
885 
886 // Send only votes for future blocks, node should request every other missing payment block individually
888 {
890 
891  if(!masternodeSync.IsWinnersListSynced()) return;
892 
893  int nInvCount = 0;
894 
895  for(int h = nCachedBlockHeight; h < nCachedBlockHeight + 20; h++) {
896  if(mapMasternodeBlocks.count(h)) {
897  BOOST_FOREACH(CMasternodePayee& payee, mapMasternodeBlocks[h].vecPayees) {
898  std::vector<uint256> vecVoteHashes = payee.GetVoteHashes();
899  BOOST_FOREACH(uint256& hash, vecVoteHashes) {
900  if(!HasVerifiedPaymentVote(hash)) continue;
902  nInvCount++;
903  }
904  }
905  }
906  }
907 
908  LogPrintf("CMasternodePayments::Sync -- Sent %d votes to peer %d\n", nInvCount, pnode->id);
909  connman.PushMessage(pnode, NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_MNW, nInvCount);
910 }
911 
912 // Request low data/unknown payment blocks in batches directly from some node instead of/after preliminary Sync.
914 {
916 
918 
919  std::vector<CInv> vToFetch;
920  int nLimit = GetStorageLimit();
921 
922  const CBlockIndex *pindex = chainActive.Tip();
923 
924  while(nCachedBlockHeight - pindex->nHeight < nLimit) {
925  if(!mapMasternodeBlocks.count(pindex->nHeight)) {
926  // We have no idea about this block height, let's ask
927  vToFetch.push_back(CInv(MSG_MASTERNODE_PAYMENT_BLOCK, pindex->GetBlockHash()));
928  // We should not violate GETDATA rules
929  if(vToFetch.size() == MAX_INV_SZ) {
930  LogPrintf("CMasternodePayments::SyncLowDataPaymentBlocks -- asking peer %d for %d blocks\n", pnode->id, MAX_INV_SZ);
931  connman.PushMessage(pnode, NetMsgType::GETDATA, vToFetch);
932  // Start filling new batch
933  vToFetch.clear();
934  }
935  }
936  if(!pindex->pprev) break;
937  pindex = pindex->pprev;
938  }
939 
940  std::map<int, CMasternodeBlockPayees>::iterator it = mapMasternodeBlocks.begin();
941 
942  while(it != mapMasternodeBlocks.end()) {
943  int nTotalVotes = 0;
944  bool fFound = false;
945  BOOST_FOREACH(CMasternodePayee& payee, it->second.vecPayees) {
947  fFound = true;
948  break;
949  }
950  nTotalVotes += payee.GetVoteCount();
951  }
952  // A clear winner (MNPAYMENTS_SIGNATURES_REQUIRED+ votes) was found
953  // or no clear winner was found but there are at least avg number of votes
954  if(fFound || nTotalVotes >= (MNPAYMENTS_SIGNATURES_TOTAL + MNPAYMENTS_SIGNATURES_REQUIRED)/2) {
955  // so just move to the next block
956  ++it;
957  continue;
958  }
959  // DEBUG
960  DBG (
961  // Let's see why this failed
962  BOOST_FOREACH(CMasternodePayee& payee, it->second.vecPayees) {
963  CTxDestination address1;
964  ExtractDestination(payee.GetPayee(), address1);
965  CBitcoinAddress address2(address1);
966  printf("payee %s votes %d\n", address2.ToString().c_str(), payee.GetVoteCount());
967  }
968  printf("block %d votes total %d\n", it->first, nTotalVotes);
969  )
970  // END DEBUG
971  // Low data block found, let's try to sync it
972  uint256 hash;
973  if(GetBlockHash(hash, it->first)) {
974  vToFetch.push_back(CInv(MSG_MASTERNODE_PAYMENT_BLOCK, hash));
975  }
976  // We should not violate GETDATA rules
977  if(vToFetch.size() == MAX_INV_SZ) {
978  LogPrintf("CMasternodePayments::SyncLowDataPaymentBlocks -- asking peer %d for %d payment blocks\n", pnode->id, MAX_INV_SZ);
979  connman.PushMessage(pnode, NetMsgType::GETDATA, vToFetch);
980  // Start filling new batch
981  vToFetch.clear();
982  }
983  ++it;
984  }
985  // Ask for the rest of it
986  if(!vToFetch.empty()) {
987  LogPrintf("CMasternodePayments::SyncLowDataPaymentBlocks -- asking peer %d for %d payment blocks\n", pnode->id, vToFetch.size());
988  connman.PushMessage(pnode, NetMsgType::GETDATA, vToFetch);
989  }
990 }
991 
992 std::string CMasternodePayments::ToString() const
993 {
994  std::ostringstream info;
995 
996  info << "Votes: " << (int)mapMasternodePaymentVotes.size() <<
997  ", Blocks: " << (int)mapMasternodeBlocks.size();
998 
999  return info.str();
1000 }
1001 
1003 {
1004  float nAverageVotes = (MNPAYMENTS_SIGNATURES_TOTAL + MNPAYMENTS_SIGNATURES_REQUIRED) / 2;
1005  int nStorageLimit = GetStorageLimit();
1006  return GetBlockCount() > nStorageLimit && GetVoteCount() > nStorageLimit * nAverageVotes;
1007 }
1008 
1010 {
1011  return std::max(int(mnodeman.size() * nStorageCoeff), nMinBlocksToStore);
1012 }
1013 
1015 {
1016  if(!pindex) return;
1017 
1018  nCachedBlockHeight = pindex->nHeight;
1019  LogPrint("mnpayments", "CMasternodePayments::UpdatedBlockTip -- nCachedBlockHeight=%d\n", nCachedBlockHeight);
1020 
1021  int nFutureBlock = nCachedBlockHeight + 10;
1022 
1023  CheckPreviousBlockVotes(nFutureBlock - 1);
1024  ProcessBlock(nFutureBlock, connman);
1025 }
bool AddPaymentVote(const CMasternodePaymentVote &vote)
bool GetBlockHash(uint256 &hashRet, int nBlockHeight)
static const int SPORK_10_MASTERNODE_PAY_UPDATED_NODES
Definition: spork.h:27
void FillBlockPayee(CMutableTransaction &txNew, int nBlockHeight, CAmount blockReward, CTxOut &txoutMasternodeRet)
CMasternodeMan mnodeman
CCriticalSection cs_vecPayees
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
Definition: standard.h:69
CMasternodeSync masternodeSync
std::set< uint256 > setAskFor
Definition: net.h:743
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: standard.cpp:164
int nSuperblockStartBlock
Definition: params.h:54
CAmount GetMasternodePayment(int nHeight, CAmount blockValue)
static std::string GetRequiredPaymentsString(int nBlockHeight)
std::string ToString() const
CActiveMasternode activeMasternode
const char * MASTERNODEPAYMENTVOTE
Definition: protocol.cpp:43
bool fDebug
Definition: util.cpp:124
void AddFulfilledRequest(CAddress addr, std::string strRequest)
#define strprintf
Definition: tinyformat.h:1011
uint64_t GetHash(const uint256 &salt) const
Definition: uint256.cpp:126
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:55
bool GetBestPayee(CScript &payeeRet)
static const CAmount COIN
Definition: amount.h:16
std::string ToString() const
#define DBG(x)
Definition: util.h:41
bool CheckSignature(const CPubKey &pubKeyMasternode, int nValidationHeight, int &nDos)
bool IsBlockPayeeValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
CCriticalSection cs_main
Definition: validation.cpp:62
CCriticalSection cs_mapMasternodePaymentVotes
CAmount nValue
Definition: transaction.h:136
int nBudgetPaymentsWindowBlocks
Definition: params.h:52
static const int SPORK_9_SUPERBLOCKS_ENABLED
Definition: spork.h:26
CAddress addr
Definition: net.h:688
Definition: net.h:108
static bool IsSuperblockTriggered(int nBlockHeight)
NodeId id
Definition: net.h:718
std::string ToString() const
Definition: transaction.cpp:76
bool GetMasternodeRanks(rank_pair_vec_t &vecMasternodeRanksRet, int nBlockHeight=-1, int nMinProtocol=0)
const char * SYNCSTATUSCOUNT
Definition: protocol.cpp:63
void ProcessMessage(CNode *pfrom, std::string &strCommand, CDataStream &vRecv, CConnman &connman)
void RelayInv(CInv &inv, const int minProtoVersion=MIN_PEER_PROTO_VERSION)
Definition: net.cpp:2528
CPubKey pubKeyMasternode
Definition: masternode.h:117
static const int MNPAYMENTS_SIGNATURES_REQUIRED
void AskForMN(CNode *pnode, const COutPoint &outpoint, CConnman &connman)
Ask (source) node for mnb.
CAmount GetValueOut() const
bool IsWinnersListSynced()
void RequestLowDataPaymentBlocks(CNode *pnode, CConnman &connman)
CCriticalSection cs_mapMasternodeBlocks
bool IsValid(CNode *pnode, int nValidationHeight, std::string &strError, CConnman &connman)
bool HasFulfilledRequest(CAddress addr, std::string strRequest)
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:144
void CheckPreviousBlockVotes(int nPrevBlockHeight)
void AddVoteHash(uint256 hashIn)
void UpdatedBlockTip(const CBlockIndex *pindex, CConnman &connman)
static const int MASTERNODE_SYNC_MNW
std::vector< CTransaction > vtx
Definition: block.h:77
std::string ToString() const
Definition: base58.cpp:193
bool fMasterNode
Definition: util.cpp:108
static bool IsValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
int64_t CAmount
Definition: amount.h:14
NodeId GetId() const
Definition: net.h:790
bool fLiteMode
Definition: util.cpp:109
#define LOCK2(cs1, cs2)
Definition: sync.h:169
std::atomic< bool > fDIP0001WasLockedIn
Definition: validation.cpp:88
void Misbehaving(NodeId pnode, int howmuch)
#define LogPrintf(...)
Definition: util.h:98
static const int MNPAYMENTS_SIGNATURES_TOTAL
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Definition: core_write.cpp:75
COutPoint prevout
Definition: transaction.h:61
std::vector< CMasternodePayee > vecPayees
std::map< COutPoint, int > mapMasternodesLastVote
Definition: net.h:661
CMasternodePayments mnpayments
std::string GetRequiredPaymentsString(int nBlockHeight)
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
static const int SPORK_13_OLD_SUPERBLOCK_FLAG
Definition: spork.h:29
#define LOCK(cs)
Definition: sync.h:168
bool GetMasternodeInfo(const COutPoint &outpoint, masternode_info_t &mnInfoRet)
std::vector< uint256 > GetVoteHashes()
static const int SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT
Definition: spork.h:25
static bool error(const char *format)
Definition: util.h:131
bool GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int &nCountRet, masternode_info_t &mnInfoRet)
Find an entry in the masternode list that is next to be paid.
bool IsScheduled(CMasternode &mn, int nNotBlockHeight)
void PushInventory(const CInv &inv)
Definition: net.h:866
const char * GETDATA
Definition: protocol.cpp:20
bool IsTransactionValid(const CTransaction &txNew)
std::vector< rank_pair_t > rank_pair_vec_t
Definition: masternodeman.h:24
static bool VerifyMessage(const CPubKey pubkey, const std::vector< unsigned char > &vchSig, const std::string strMessage, std::string &strErrorRet)
Verify the message signature, returns true if succcessful.
CChain chainActive
Definition: validation.cpp:65
bool IsTransactionValid(const CTransaction &txNew, int nBlockHeight)
std::string ToString() const
Definition: uint256.cpp:65
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:262
static CAmount GetPaymentsLimit(int nBlockHeight)
int size()
Return the number of (unique) Masternodes.
CScript scriptPubKey
Definition: transaction.h:137
std::string GetRequiredPaymentsString(int nBlockHeight)
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1
minimum peer version that can receive and send masternode payment messages,
std::vector< CTxOut > vout
Definition: transaction.h:307
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2
CSporkManager sporkManager
Definition: spork.cpp:14
bool IsBlockValueValid(const CBlock &block, int nBlockHeight, CAmount blockReward, std::string &strErrorRet)
TODO: all 4 functions do not belong here really, they should be refactored/moved somewhere (main...
int nBudgetPaymentsCycleBlocks
Definition: params.h:51
std::vector< unsigned char > vchSig
CPubKey pubKeyCollateralAddress
Definition: masternode.h:116
bool HasPayeeWithVotes(const CScript &payeeIn, int nVotesReq)
bool ProcessBlock(int nBlockHeight, CConnman &connman)
const CChainParams & Params()
std::string GetRequiredPaymentsString()
std::string ToString() const
Definition: transaction.cpp:63
bool IsBlockchainSynced()
std::string ToString() const
uint256 GetBlockHash() const
Definition: chain.h:218
CNetFulfilledRequestManager netfulfilledman
Definition: protocol.h:314
const std::vector< CTxOut > vout
Definition: transaction.h:234
CBlockIndex * Tip() const
Definition: chain.h:366
Definition: pubkey.h:37
bool GetMasternodeRank(const COutPoint &outpoint, int &nRankRet, int nBlockHeight=-1, int nMinProtocol=0)
static bool SignMessage(const std::string strMessage, std::vector< unsigned char > &vchSigRet, const CKey key)
Sign the message, returns true if successful.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:107
bool IsSporkActive(int nSporkID)
Definition: spork.cpp:120
std::map< COutPoint, int > mapMasternodesDidNotVote
const char * MASTERNODEPAYMENTSYNC
Definition: protocol.cpp:45
void BumpAssetLastTime(std::string strFuncName)
void Sync(CNode *node, CConnman &connman)
std::map< uint256, CMasternodePaymentVote > mapMasternodePaymentVotes
Definition: block.h:73
void Relay(CConnman &connman)
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:113
std::string ToStringShort() const
Definition: transaction.cpp:17
static const unsigned int MAX_INV_SZ
Definition: net.h:55
static bool IsValidBlockHeight(int nBlockHeight)
int nBudgetPaymentsStartBlock
Definition: params.h:50
bool IsMasternodeListSynced()
bool CanVote(COutPoint outMasternode, int nBlockHeight)
void FillBlockPayments(CMutableTransaction &txNew, int nBlockHeight, CAmount blockReward, CTxOut &txoutMasternodeRet, std::vector< CTxOut > &voutSuperblockRet)
static void CreateSuperblock(CMutableTransaction &txNewRet, int nBlockHeight, std::vector< CTxOut > &voutSuperblockRet)
bool GetBlockPayee(int nBlockHeight, CScript &payee)
void PushMessage(CNode *pnode, const std::string &sCommand, Args &&... args)
Definition: net.h:199
std::map< int, CMasternodeBlockPayees > mapMasternodeBlocks
std::atomic< int > nVersion
Definition: net.h:692
void AddPayee(const CMasternodePaymentVote &vote)
bool HasVerifiedPaymentVote(uint256 hashIn)