Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

governance-classes.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2019 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 
6 #include <core_io.h>
7 #include <init.h>
8 #include <utilstrencodings.h>
9 #include <validation.h>
10 
11 #include <boost/algorithm/string.hpp>
12 
13 #include <univalue.h>
14 
15 // DECLARE GLOBAL VARIABLES FOR GOVERNANCE CLASSES
17 
18 // SPLIT UP STRING BY DELIMITER
19 // http://www.boost.org/doc/libs/1_58_0/doc/html/boost/algorithm/split_idp202406848.html
20 std::vector<std::string> SplitBy(const std::string& strCommand, const std::string& strDelimit)
21 {
22  std::vector<std::string> vParts;
23  boost::split(vParts, strCommand, boost::is_any_of(strDelimit));
24 
25  for (int q = 0; q < (int)vParts.size(); q++) {
26  if (strDelimit.find(vParts[q]) != std::string::npos) {
27  vParts.erase(vParts.begin() + q);
28  --q;
29  }
30  }
31 
32  return vParts;
33 }
34 
35 CAmount ParsePaymentAmount(const std::string& strAmount)
36 {
37  CAmount nAmount = 0;
38  if (strAmount.empty()) {
39  std::ostringstream ostr;
40  ostr << "ParsePaymentAmount: Amount is empty";
41  throw std::runtime_error(ostr.str());
42  }
43  if (strAmount.size() > 20) {
44  // String is much too long, the functions below impose stricter
45  // requirements
46  std::ostringstream ostr;
47  ostr << "ParsePaymentAmount: Amount string too long";
48  throw std::runtime_error(ostr.str());
49  }
50  // Make sure the string makes sense as an amount
51  // Note: No spaces allowed
52  // Also note: No scientific notation
53  size_t pos = strAmount.find_first_not_of("0123456789.");
54  if (pos != std::string::npos) {
55  std::ostringstream ostr;
56  ostr << "ParsePaymentAmount: Amount string contains invalid character";
57  throw std::runtime_error(ostr.str());
58  }
59 
60  pos = strAmount.find(".");
61  if (pos == 0) {
62  // JSON doesn't allow values to start with a decimal point
63  std::ostringstream ostr;
64  ostr << "ParsePaymentAmount: Invalid amount string, leading decimal point not allowed";
65  throw std::runtime_error(ostr.str());
66  }
67 
68  // Make sure there's no more than 1 decimal point
69  if ((pos != std::string::npos) && (strAmount.find(".", pos + 1) != std::string::npos)) {
70  std::ostringstream ostr;
71  ostr << "ParsePaymentAmount: Invalid amount string, too many decimal points";
72  throw std::runtime_error(ostr.str());
73  }
74 
75  // Note this code is taken from AmountFromValue in rpcserver.cpp
76  // which is used for parsing the amounts in createrawtransaction.
77  if (!ParseFixedPoint(strAmount, 8, &nAmount)) {
78  nAmount = 0;
79  std::ostringstream ostr;
80  ostr << "ParsePaymentAmount: ParseFixedPoint failed for string: " << strAmount;
81  throw std::runtime_error(ostr.str());
82  }
83  if (!MoneyRange(nAmount)) {
84  nAmount = 0;
85  std::ostringstream ostr;
86  ostr << "ParsePaymentAmount: Invalid amount string, value outside of valid money range";
87  throw std::runtime_error(ostr.str());
88  }
89 
90  return nAmount;
91 }
92 
98 {
100 
101  // IF WE ALREADY HAVE THIS HASH, RETURN
102  if (mapTrigger.count(nHash)) {
103  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::AddNewTrigger -- Already have hash, nHash = %s, count = %d, size = %s\n",
104  nHash.GetHex(), mapTrigger.count(nHash), mapTrigger.size());
105  return false;
106  }
107 
108  CSuperblock_sptr pSuperblock;
109  try {
110  CSuperblock_sptr pSuperblockTmp(new CSuperblock(nHash));
111  pSuperblock = pSuperblockTmp;
112  } catch (std::exception& e) {
113  LogPrintf("CGovernanceTriggerManager::AddNewTrigger -- Error creating superblock: %s\n", e.what());
114  return false;
115  } catch (...) {
116  LogPrintf("CGovernanceTriggerManager::AddNewTrigger: Unknown Error creating superblock\n");
117  return false;
118  }
119 
120  pSuperblock->SetStatus(SEEN_OBJECT_IS_VALID);
121 
122  mapTrigger.insert(std::make_pair(nHash, pSuperblock));
123 
124  return true;
125 }
126 
134 {
136 
137  // Remove triggers that are invalid or expired
138  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- mapTrigger.size() = %d\n", mapTrigger.size());
139 
140  trigger_m_it it = mapTrigger.begin();
141  while (it != mapTrigger.end()) {
142  bool remove = false;
143  CGovernanceObject* pObj = nullptr;
144  CSuperblock_sptr& pSuperblock = it->second;
145  if (!pSuperblock) {
146  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- nullptr superblock\n");
147  remove = true;
148  } else {
149  pObj = governance.FindGovernanceObject(it->first);
150  if (!pObj || pObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) {
151  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- Unknown or non-trigger superblock\n");
152  pSuperblock->SetStatus(SEEN_OBJECT_ERROR_INVALID);
153  }
154 
155  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- superblock status = %d\n", pSuperblock->GetStatus());
156  switch (pSuperblock->GetStatus()) {
158  case SEEN_OBJECT_UNKNOWN:
159  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- Unknown or invalid trigger found\n");
160  remove = true;
161  break;
163  case SEEN_OBJECT_EXECUTED: {
164  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- Valid trigger found\n");
165  if (pSuperblock->IsExpired()) {
166  // update corresponding object
167  pObj->SetExpired();
168  remove = true;
169  }
170  break;
171  }
172  default:
173  break;
174  }
175  }
176  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- %smarked for removal\n", remove ? "" : "NOT ");
177 
178  if (remove) {
179  std::string strDataAsPlainString = "nullptr";
180  if (pObj) {
181  strDataAsPlainString = pObj->GetDataAsPlainString();
182  // mark corresponding object for deletion
184  }
185  LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- Removing trigger object %s\n", strDataAsPlainString);
186  // delete the trigger
187  mapTrigger.erase(it++);
188  } else {
189  ++it;
190  }
191  }
192 }
193 
201 std::vector<CSuperblock_sptr> CGovernanceTriggerManager::GetActiveTriggers()
202 {
204  std::vector<CSuperblock_sptr> vecResults;
205 
206  // LOOK AT THESE OBJECTS AND COMPILE A VALID LIST OF TRIGGERS
207  for (const auto& pair : mapTrigger) {
209  if (pObj) {
210  vecResults.push_back(pair.second);
211  }
212  }
213 
214  return vecResults;
215 }
216 
224 {
225  LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- Start nBlockHeight = %d\n", nBlockHeight);
226  if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
227  return false;
228  }
229 
230  LOCK(governance.cs);
231  // GET ALL ACTIVE TRIGGERS
232  std::vector<CSuperblock_sptr> vecTriggers = triggerman.GetActiveTriggers();
233 
234  LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- vecTriggers.size() = %d\n", vecTriggers.size());
235 
236  for (const auto& pSuperblock : vecTriggers) {
237  if (!pSuperblock) {
238  LogPrintf("CSuperblockManager::IsSuperblockTriggered -- Non-superblock found, continuing\n");
239  continue;
240  }
241 
242  CGovernanceObject* pObj = pSuperblock->GetGovernanceObject();
243 
244  if (!pObj) {
245  LogPrintf("CSuperblockManager::IsSuperblockTriggered -- pObj == nullptr, continuing\n");
246  continue;
247  }
248 
249  LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- data = %s\n", pObj->GetDataAsPlainString());
250 
251  // note : 12.1 - is epoch calculation correct?
252 
253  if (nBlockHeight != pSuperblock->GetBlockHeight()) {
254  LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- block height doesn't match nBlockHeight = %d, blockStart = %d, continuing\n",
255  nBlockHeight,
256  pSuperblock->GetBlockHeight());
257  continue;
258  }
259 
260  // MAKE SURE THIS TRIGGER IS ACTIVE VIA FUNDING CACHE FLAG
261 
262  pObj->UpdateSentinelVariables();
263 
264  if (pObj->IsSetCachedFunding()) {
265  LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = true, returning true\n");
266  return true;
267  } else {
268  LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = false, continuing\n");
269  }
270  }
271 
272  return false;
273 }
274 
275 
276 bool CSuperblockManager::GetBestSuperblock(CSuperblock_sptr& pSuperblockRet, int nBlockHeight)
277 {
278  if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
279  return false;
280  }
281 
283  std::vector<CSuperblock_sptr> vecTriggers = triggerman.GetActiveTriggers();
284  int nYesCount = 0;
285 
286  for (const auto& pSuperblock : vecTriggers) {
287  if (!pSuperblock || nBlockHeight != pSuperblock->GetBlockHeight()) {
288  continue;
289  }
290 
291  CGovernanceObject* pObj = pSuperblock->GetGovernanceObject();
292 
293  if (!pObj) {
294  continue;
295  }
296 
297  // DO WE HAVE A NEW WINNER?
298 
299  int nTempYesCount = pObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING);
300  if (nTempYesCount > nYesCount) {
301  nYesCount = nTempYesCount;
302  pSuperblockRet = pSuperblock;
303  }
304  }
305 
306  return nYesCount > 0;
307 }
308 
315 bool CSuperblockManager::GetSuperblockPayments(int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet)
316 {
317  LOCK(governance.cs);
318 
319  // GET THE BEST SUPERBLOCK FOR THIS BLOCK HEIGHT
320 
321  CSuperblock_sptr pSuperblock;
322  if (!CSuperblockManager::GetBestSuperblock(pSuperblock, nBlockHeight)) {
323  LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetSuperblockPayments -- Can't find superblock for height %d\n", nBlockHeight);
324  return false;
325  }
326 
327  // make sure it's empty, just in case
328  voutSuperblockRet.clear();
329 
330  // GET SUPERBLOCK OUTPUTS
331 
332  // Superblock payments will be appended to the end of the coinbase vout vector
333 
334  // TODO: How many payments can we add before things blow up?
335  // Consider at least following limits:
336  // - max coinbase tx size
337  // - max "budget" available
338  for (int i = 0; i < pSuperblock->CountPayments(); i++) {
339  CGovernancePayment payment;
340  if (pSuperblock->GetPayment(i, payment)) {
341  // SET COINBASE OUTPUT TO SUPERBLOCK SETTING
342 
343  CTxOut txout = CTxOut(payment.nAmount, payment.script);
344  voutSuperblockRet.push_back(txout);
345 
346  // PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
347 
348  CTxDestination dest;
349  ExtractDestination(payment.script, dest);
350 
351  // TODO: PRINT NICE N.N DASH OUTPUT
352 
353  LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetSuperblockPayments -- NEW Superblock: output %d (addr %s, amount %lld)\n",
354  i, EncodeDestination(dest), payment.nAmount);
355  } else {
356  LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetSuperblockPayments -- Payment not found\n");
357  }
358  }
359 
360  return true;
361 }
362 
363 bool CSuperblockManager::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
364 {
365  // GET BEST SUPERBLOCK, SHOULD MATCH
366  LOCK(governance.cs);
367 
368  CSuperblock_sptr pSuperblock;
369  if (CSuperblockManager::GetBestSuperblock(pSuperblock, nBlockHeight)) {
370  return pSuperblock->IsValid(txNew, nBlockHeight, blockReward);
371  }
372 
373  return false;
374 }
375 
377 {
378  LOCK(governance.cs);
379 
380  CSuperblock_sptr pSuperblock;
381  if (GetBestSuperblock(pSuperblock, nBlockHeight)) {
382  // All checks are done in CSuperblock::IsValid via IsBlockValueValid and IsBlockPayeeValid,
383  // tip wouldn't be updated if anything was wrong. Mark this trigger as executed.
384  pSuperblock->SetExecuted();
385  }
386 }
387 
390  nGovObjHash(),
391  nBlockHeight(0),
392  nStatus(SEEN_OBJECT_UNKNOWN),
393  vecPayments()
394 {
395 }
396 
399  nGovObjHash(nHash),
400  nBlockHeight(0),
401  nStatus(SEEN_OBJECT_UNKNOWN),
402  vecPayments()
403 {
405 
406  if (!pGovObj) {
407  throw std::runtime_error("CSuperblock: Failed to find Governance Object");
408  }
409 
410  LogPrint(BCLog::GOBJECT, "CSuperblock -- Constructor pGovObj: %s, nObjectType = %d\n",
411  pGovObj->GetDataAsPlainString(), pGovObj->GetObjectType());
412 
413  if (pGovObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) {
414  throw std::runtime_error("CSuperblock: Governance Object not a trigger");
415  }
416 
417  UniValue obj = pGovObj->GetJSONObject();
418 
419  // FIRST WE GET THE START HEIGHT, THE BLOCK HEIGHT AT WHICH THE PAYMENT SHALL OCCUR
420  nBlockHeight = obj["event_block_height"].get_int();
421 
422  // NEXT WE GET THE PAYMENT INFORMATION AND RECONSTRUCT THE PAYMENT VECTOR
423  std::string strAddresses = obj["payment_addresses"].get_str();
424  std::string strAmounts = obj["payment_amounts"].get_str();
425  ParsePaymentSchedule(strAddresses, strAmounts);
426 
427  LogPrint(BCLog::GOBJECT, "CSuperblock -- nBlockHeight = %d, strAddresses = %s, strAmounts = %s, vecPayments.size() = %d\n",
428  nBlockHeight, strAddresses, strAmounts, vecPayments.size());
429 }
430 
437 bool CSuperblock::IsValidBlockHeight(int nBlockHeight)
438 {
439  // SUPERBLOCKS CAN HAPPEN ONLY after hardfork and only ONCE PER CYCLE
442 }
443 
444 void CSuperblock::GetNearestSuperblocksHeights(int nBlockHeight, int& nLastSuperblockRet, int& nNextSuperblockRet)
445 {
446  const Consensus::Params& consensusParams = Params().GetConsensus();
447  int nSuperblockStartBlock = consensusParams.nSuperblockStartBlock;
448  int nSuperblockCycle = consensusParams.nSuperblockCycle;
449 
450  // Get first superblock
451  int nFirstSuperblockOffset = (nSuperblockCycle - nSuperblockStartBlock % nSuperblockCycle) % nSuperblockCycle;
452  int nFirstSuperblock = nSuperblockStartBlock + nFirstSuperblockOffset;
453 
454  if (nBlockHeight < nFirstSuperblock) {
455  nLastSuperblockRet = 0;
456  nNextSuperblockRet = nFirstSuperblock;
457  } else {
458  nLastSuperblockRet = nBlockHeight - nBlockHeight % nSuperblockCycle;
459  nNextSuperblockRet = nLastSuperblockRet + nSuperblockCycle;
460  }
461 }
462 
464 {
465  const Consensus::Params& consensusParams = Params().GetConsensus();
466 
468  return 0;
469  }
470 
471  // min subsidy for high diff networks and vice versa
472  int nBits = consensusParams.fPowAllowMinDifficultyBlocks ? UintToArith256(consensusParams.powLimit).GetCompact() : 1;
473  // some part of all blocks issued during the cycle goes to superblock, see GetBlockSubsidy
474  CAmount nSuperblockPartOfSubsidy = GetBlockSubsidy(nBits, nBlockHeight - 1, consensusParams, true);
475  CAmount nPaymentsLimit = nSuperblockPartOfSubsidy * consensusParams.nSuperblockCycle;
476  LogPrint(BCLog::GOBJECT, "CSuperblock::GetPaymentsLimit -- Valid superblock height %d, payments max %lld\n", nBlockHeight, nPaymentsLimit);
477 
478  return nPaymentsLimit;
479 }
480 
481 void CSuperblock::ParsePaymentSchedule(const std::string& strPaymentAddresses, const std::string& strPaymentAmounts)
482 {
483  // SPLIT UP ADDR/AMOUNT STRINGS AND PUT IN VECTORS
484 
485  std::vector<std::string> vecParsed1;
486  std::vector<std::string> vecParsed2;
487  vecParsed1 = SplitBy(strPaymentAddresses, "|");
488  vecParsed2 = SplitBy(strPaymentAmounts, "|");
489 
490  // IF THESE DONT MATCH, SOMETHING IS WRONG
491 
492  if (vecParsed1.size() != vecParsed2.size()) {
493  std::ostringstream ostr;
494  ostr << "CSuperblock::ParsePaymentSchedule -- Mismatched payments and amounts";
495  LogPrintf("%s\n", ostr.str());
496  throw std::runtime_error(ostr.str());
497  }
498 
499  if (vecParsed1.size() == 0) {
500  std::ostringstream ostr;
501  ostr << "CSuperblock::ParsePaymentSchedule -- Error no payments";
502  LogPrintf("%s\n", ostr.str());
503  throw std::runtime_error(ostr.str());
504  }
505 
506  // LOOP THROUGH THE ADDRESSES/AMOUNTS AND CREATE PAYMENTS
507  /*
508  ADDRESSES = [ADDR1|2|3|4|5|6]
509  AMOUNTS = [AMOUNT1|2|3|4|5|6]
510  */
511 
512  for (int i = 0; i < (int)vecParsed1.size(); i++) {
513  CTxDestination dest = DecodeDestination(vecParsed1[i]);
514  if (!IsValidDestination(dest)) {
515  std::ostringstream ostr;
516  ostr << "CSuperblock::ParsePaymentSchedule -- Invalid Dash Address : " << vecParsed1[i];
517  LogPrintf("%s\n", ostr.str());
518  throw std::runtime_error(ostr.str());
519  }
520  /*
521  TODO
522 
523  - There might be an issue with multisig in the coinbase on mainnet, we will add support for it in a future release.
524  - Post 12.3+ (test multisig coinbase transaction)
525  */
526  const CScriptID *scriptID = boost::get<CScriptID>(&dest);
527  if (scriptID) {
528  std::ostringstream ostr;
529  ostr << "CSuperblock::ParsePaymentSchedule -- Script addresses are not supported yet : " << vecParsed1[i];
530  LogPrintf("%s\n", ostr.str());
531  throw std::runtime_error(ostr.str());
532  }
533 
534  CAmount nAmount = ParsePaymentAmount(vecParsed2[i]);
535 
536  LogPrint(BCLog::GOBJECT, "CSuperblock::ParsePaymentSchedule -- i = %d, amount string = %s, nAmount = %lld\n", i, vecParsed2[i], nAmount);
537 
538  CGovernancePayment payment(dest, nAmount);
539  if (payment.IsValid()) {
540  vecPayments.push_back(payment);
541  } else {
542  vecPayments.clear();
543  std::ostringstream ostr;
544  ostr << "CSuperblock::ParsePaymentSchedule -- Invalid payment found: address = " << EncodeDestination(dest)
545  << ", amount = " << nAmount;
546  LogPrintf("%s\n", ostr.str());
547  throw std::runtime_error(ostr.str());
548  }
549  }
550 }
551 
552 bool CSuperblock::GetPayment(int nPaymentIndex, CGovernancePayment& paymentRet)
553 {
554  if ((nPaymentIndex < 0) || (nPaymentIndex >= (int)vecPayments.size())) {
555  return false;
556  }
557 
558  paymentRet = vecPayments[nPaymentIndex];
559  return true;
560 }
561 
563 {
564  CAmount nPaymentsTotalAmount = 0;
565  int nPayments = CountPayments();
566 
567  for (int i = 0; i < nPayments; i++) {
568  nPaymentsTotalAmount += vecPayments[i].nAmount;
569  }
570 
571  return nPaymentsTotalAmount;
572 }
573 
580 bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
581 {
582  // TODO : LOCK(cs);
583  // No reason for a lock here now since this method only accesses data
584  // internal to *this and since CSuperblock's are accessed only through
585  // shared pointers there's no way our object can get deleted while this
586  // code is running.
588  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, incorrect block height\n");
589  return false;
590  }
591 
592  std::string strPayeesPossible = "";
593 
594  // CONFIGURE SUPERBLOCK OUTPUTS
595 
596  int nOutputs = txNew.vout.size();
597  int nPayments = CountPayments();
598  int nMinerAndMasternodePayments = nOutputs - nPayments;
599 
600  LogPrint(BCLog::GOBJECT, "CSuperblock::IsValid -- nOutputs = %d, nPayments = %d, GetDataAsHexString = %s\n",
601  nOutputs, nPayments, GetGovernanceObject()->GetDataAsHexString());
602 
603  // We require an exact match (including order) between the expected
604  // superblock payments and the payments actually in the block.
605 
606  if (nMinerAndMasternodePayments < 0) {
607  // This means the block cannot have all the superblock payments
608  // so it is not valid.
609  // TODO: could that be that we just hit coinbase size limit?
610  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, too few superblock payments\n");
611  return false;
612  }
613 
614  // payments should not exceed limit
615  CAmount nPaymentsTotalAmount = GetPaymentsTotalAmount();
616  CAmount nPaymentsLimit = GetPaymentsLimit(nBlockHeight);
617  if (nPaymentsTotalAmount > nPaymentsLimit) {
618  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, payments limit exceeded: payments %lld, limit %lld\n", nPaymentsTotalAmount, nPaymentsLimit);
619  return false;
620  }
621 
622  // miner and masternodes should not get more than they would usually get
623  CAmount nBlockValue = txNew.GetValueOut();
624  if (nBlockValue > blockReward + nPaymentsTotalAmount) {
625  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, block value limit exceeded: block %lld, limit %lld\n", nBlockValue, blockReward + nPaymentsTotalAmount);
626  return false;
627  }
628 
629  int nVoutIndex = 0;
630  for (int i = 0; i < nPayments; i++) {
631  CGovernancePayment payment;
632  if (!GetPayment(i, payment)) {
633  // This shouldn't happen so log a warning
634  LogPrintf("CSuperblock::IsValid -- WARNING: Failed to find payment: %d of %d total payments\n", i, nPayments);
635  continue;
636  }
637 
638  bool fPaymentMatch = false;
639 
640  for (int j = nVoutIndex; j < nOutputs; j++) {
641  // Find superblock payment
642  fPaymentMatch = ((payment.script == txNew.vout[j].scriptPubKey) &&
643  (payment.nAmount == txNew.vout[j].nValue));
644 
645  if (fPaymentMatch) {
646  nVoutIndex = j;
647  break;
648  }
649  }
650 
651  if (!fPaymentMatch) {
652  // Superblock payment not found!
653 
654  CTxDestination dest;
655  ExtractDestination(payment.script, dest);
656  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid: %d payment %d to %s not found\n", i, payment.nAmount, EncodeDestination(dest));
657 
658  return false;
659  }
660  }
661 
662  return true;
663 }
664 
666 {
667  int nExpirationBlocks{0};
668  // Executed triggers are kept for another superblock cycle (approximately 1 month),
669  // other valid triggers are kept for ~1 day only, everything else is pruned after ~1h.
670  switch (nStatus) {
672  nExpirationBlocks = Params().GetConsensus().nSuperblockCycle;
673  break;
675  nExpirationBlocks = 576;
676  break;
677  default:
678  nExpirationBlocks = 24;
679  break;
680  }
681 
682  int nExpirationBlock = nBlockHeight + nExpirationBlocks;
683 
684  LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- nBlockHeight = %d, nExpirationBlock = %d\n", nBlockHeight, nExpirationBlock);
685 
686  if (governance.GetCachedBlockHeight() > nExpirationBlock) {
687  LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- Outdated trigger found\n");
688  return true;
689  }
690 
691  return false;
692 }
693 
701 {
702  LOCK(governance.cs);
703  std::string ret = "Unknown";
704 
705  // GET BEST SUPERBLOCK
706 
707  CSuperblock_sptr pSuperblock;
708  if (!GetBestSuperblock(pSuperblock, nBlockHeight)) {
709  LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetRequiredPaymentsString -- Can't find superblock for height %d\n", nBlockHeight);
710  return "error";
711  }
712 
713  // LOOP THROUGH SUPERBLOCK PAYMENTS, CONFIGURE OUTPUT STRING
714 
715  for (int i = 0; i < pSuperblock->CountPayments(); i++) {
716  CGovernancePayment payment;
717  if (pSuperblock->GetPayment(i, payment)) {
718  // PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
719 
720  CTxDestination dest;
721  ExtractDestination(payment.script, dest);
722 
723  // RETURN NICE OUTPUT FOR CONSOLE
724 
725  if (ret != "Unknown") {
726  ret += ", " + EncodeDestination(dest);
727  } else {
728  ret = EncodeDestination(dest);
729  }
730  }
731  }
732 
733  return ret;
734 }
std::vector< CSuperblock_sptr > GetActiveTriggers()
Get Active Triggers.
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
std::string GetDataAsHexString() const
GetData - As
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
CAmount ParsePaymentAmount(const std::string &strAmount)
Governance Object.
static void GetNearestSuperblocksHeights(int nBlockHeight, int &nLastSuperblockRet, int &nNextSuperblockRet)
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:27
static bool IsSuperblockTriggered(int nBlockHeight)
Is Superblock Triggered.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:281
Trigger : Superblock.
CTxDestination DecodeDestination(const std::string &str)
Definition: base58.cpp:336
CGovernanceObject * GetGovernanceObject()
bool fPowAllowMinDifficultyBlocks
Definition: params.h:174
std::vector< std::string > SplitBy(const std::string &strCommand, const std::string &strDelimit)
const std::string & get_str() const
static bool IsValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
void PrepareDeletion(int64_t nDeletionTime_)
bool IsSetCachedFunding() const
int nSuperblockCycle
Definition: params.h:144
static const int SEEN_OBJECT_ERROR_INVALID
trigger_m_t::iterator trigger_m_it
uint32_t GetCompact(bool fNegative=false) const
CGovernanceObject * FindGovernanceObject(const uint256 &nHash)
Definition: governance.cpp:463
CAmount GetValueOut() const
Definition: transaction.cpp:99
arith_uint256 UintToArith256(const uint256 &a)
bool AddNewTrigger(uint256 nHash)
Add Governance Object.
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
UniValue GetJSONObject()
Return the actual object from the vchData JSON structure.
CGovernanceManager governance
Definition: governance.cpp:23
uint256 powLimit
Proof of work parameters.
Definition: params.h:173
CGovernanceTriggerManager triggerman
std::shared_ptr< CSuperblock > CSuperblock_sptr
int GetCachedBlockHeight() const
Definition: governance.h:356
#define LogPrintf(...)
Definition: util.h:203
int GetObjectType() const
int nSuperblockStartBlock
Definition: params.h:142
#define LOCK(cs)
Definition: sync.h:178
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
static bool IsValidBlockHeight(int nBlockHeight)
Is Valid Superblock Height.
void CleanAndRemove()
Clean And Remove.
const std::vector< CTxOut > vout
Definition: transaction.h:216
static std::string GetRequiredPaymentsString(int nBlockHeight)
Get Required Payment String.
static const int GOVERNANCE_OBJECT_TRIGGER
static const int SEEN_OBJECT_IS_VALID
An output of a transaction.
Definition: transaction.h:144
int get_int() const
Parameters that influence chain consensus.
Definition: params.h:130
static const int SEEN_OBJECT_EXECUTED
static const int SEEN_OBJECT_UNKNOWN
#define LogPrint(category,...)
Definition: util.h:214
256-bit opaque blob.
Definition: uint256.h:123
static bool GetSuperblockPayments(int nBlockHeight, std::vector< CTxOut > &voutSuperblockRet)
Get Superblock Payments.
Governance Object Payment.
std::string GetDataAsPlainString() const
static CAmount GetPaymentsLimit(int nBlockHeight)
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
const CChainParams & Params()
Return the currently selected parameters.
int GetAbsoluteYesCount(vote_signal_enum_t eVoteSignalIn) const
Get specific vote counts for each outcome (funding, validity, etc)
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
static bool GetBestSuperblock(CSuperblock_sptr &pSuperblockRet, int nBlockHeight)
std::string GetHex() const
Definition: uint256.cpp:21
CAmount GetPaymentsTotalAmount()
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:22
CCriticalSection cs
Definition: governance.h:278
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:198
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:54
void ParsePaymentSchedule(const std::string &strPaymentAddresses, const std::string &strPaymentAmounts)
CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params &consensusParams, bool fSuperblockPartOnly)
AssertLockHeld(g_cs_orphans)
static void ExecuteBestSuperblock(int nBlockHeight)
std::vector< CGovernancePayment > vecPayments
bool IsValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
Is Transaction Valid.
bool GetPayment(int nPaymentIndex, CGovernancePayment &paymentRet)
bool IsExpired() const
Released under the MIT license