Dash Core  0.12.2.1
P2P Digital Currency
governance-classes.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 //#define ENABLE_DASH_DEBUG
6 
7 #include "core_io.h"
8 #include "governance-classes.h"
9 #include "init.h"
10 #include "validation.h"
11 #include "utilstrencodings.h"
12 
13 #include <boost/algorithm/string.hpp>
14 #include <boost/foreach.hpp>
15 
16 #include <univalue.h>
17 
18 // DECLARE GLOBAL VARIABLES FOR GOVERNANCE CLASSES
20 
21 // SPLIT UP STRING BY DELIMITER
22 // http://www.boost.org/doc/libs/1_58_0/doc/html/boost/algorithm/split_idp202406848.html
23 std::vector<std::string> SplitBy(std::string strCommand, std::string strDelimit)
24 {
25  std::vector<std::string> vParts;
26  boost::split(vParts, strCommand, boost::is_any_of(strDelimit));
27 
28  for(int q=0; q<(int)vParts.size(); q++) {
29  if(strDelimit.find(vParts[q]) != std::string::npos) {
30  vParts.erase(vParts.begin()+q);
31  --q;
32  }
33  }
34 
35  return vParts;
36 }
37 
38 CAmount ParsePaymentAmount(const std::string& strAmount)
39 {
40  DBG( cout << "ParsePaymentAmount Start: strAmount = " << strAmount << endl; );
41 
42  CAmount nAmount = 0;
43  if (strAmount.empty()) {
44  std::ostringstream ostr;
45  ostr << "ParsePaymentAmount: Amount is empty";
46  throw std::runtime_error(ostr.str());
47  }
48  if(strAmount.size() > 20) {
49  // String is much too long, the functions below impose stricter
50  // requirements
51  std::ostringstream ostr;
52  ostr << "ParsePaymentAmount: Amount string too long";
53  throw std::runtime_error(ostr.str());
54  }
55  // Make sure the string makes sense as an amount
56  // Note: No spaces allowed
57  // Also note: No scientific notation
58  size_t pos = strAmount.find_first_not_of("0123456789.");
59  if (pos != std::string::npos) {
60  std::ostringstream ostr;
61  ostr << "ParsePaymentAmount: Amount string contains invalid character";
62  throw std::runtime_error(ostr.str());
63  }
64 
65  pos = strAmount.find(".");
66  if (pos == 0) {
67  // JSON doesn't allow values to start with a decimal point
68  std::ostringstream ostr;
69  ostr << "ParsePaymentAmount: Invalid amount string, leading decimal point not allowed";
70  throw std::runtime_error(ostr.str());
71  }
72 
73  // Make sure there's no more than 1 decimal point
74  if ((pos != std::string::npos) && (strAmount.find(".", pos+1) != std::string::npos)) {
75  std::ostringstream ostr;
76  ostr << "ParsePaymentAmount: Invalid amount string, too many decimal points";
77  throw std::runtime_error(ostr.str());
78  }
79 
80  // Note this code is taken from AmountFromValue in rpcserver.cpp
81  // which is used for parsing the amounts in createrawtransaction.
82  if (!ParseFixedPoint(strAmount, 8, &nAmount)) {
83  nAmount = 0;
84  std::ostringstream ostr;
85  ostr << "ParsePaymentAmount: ParseFixedPoint failed for string: " << strAmount;
86  throw std::runtime_error(ostr.str());
87  }
88  if (!MoneyRange(nAmount)) {
89  nAmount = 0;
90  std::ostringstream ostr;
91  ostr << "ParsePaymentAmount: Invalid amount string, value outside of valid money range";
92  throw std::runtime_error(ostr.str());
93  }
94 
95  DBG( cout << "ParsePaymentAmount Returning true nAmount = " << nAmount << endl; );
96 
97  return nAmount;
98 }
99 
105 {
106  DBG( cout << "CGovernanceTriggerManager::AddNewTrigger: Start" << endl; );
108 
109  // IF WE ALREADY HAVE THIS HASH, RETURN
110  if(mapTrigger.count(nHash)) {
111  DBG(
112  cout << "CGovernanceTriggerManager::AddNewTrigger: Already have hash"
113  << ", nHash = " << nHash.GetHex()
114  << ", count = " << mapTrigger.count(nHash)
115  << ", mapTrigger.size() = " << mapTrigger.size()
116  << endl; );
117  return false;
118  }
119 
120  CSuperblock_sptr pSuperblock;
121  try {
122  CSuperblock_sptr pSuperblockTmp(new CSuperblock(nHash));
123  pSuperblock = pSuperblockTmp;
124  }
125  catch(std::exception& e) {
126  DBG( cout << "CGovernanceTriggerManager::AddNewTrigger Error creating superblock"
127  << ", e.what() = " << e.what()
128  << endl; );
129  LogPrintf("CGovernanceTriggerManager::AddNewTrigger -- Error creating superblock: %s\n", e.what());
130  return false;
131  }
132  catch(...) {
133  LogPrintf("CGovernanceTriggerManager::AddNewTrigger: Unknown Error creating superblock\n");
134  DBG( cout << "CGovernanceTriggerManager::AddNewTrigger Error creating superblock catchall" << endl; );
135  return false;
136  }
137 
138  pSuperblock->SetStatus(SEEN_OBJECT_IS_VALID);
139 
140  DBG( cout << "CGovernanceTriggerManager::AddNewTrigger: Inserting trigger" << endl; );
141  mapTrigger.insert(std::make_pair(nHash, pSuperblock));
142 
143  DBG( cout << "CGovernanceTriggerManager::AddNewTrigger: End" << endl; );
144 
145  return true;
146 }
147 
155 {
156  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Start\n");
157  DBG( cout << "CGovernanceTriggerManager::CleanAndRemove: Start" << endl; );
159 
160  // LOOK AT THESE OBJECTS AND COMPILE A VALID LIST OF TRIGGERS
161  for(trigger_m_it it = mapTrigger.begin(); it != mapTrigger.end(); ++it) {
162  //int nNewStatus = -1;
164  if(!pObj) {
165  continue;
166  }
167  CSuperblock_sptr& pSuperblock = it->second;
168  if(!pSuperblock) {
169  continue;
170  }
171  // IF THIS ISN'T A TRIGGER, WHY ARE WE HERE?
173  pSuperblock->SetStatus(SEEN_OBJECT_ERROR_INVALID);
174  }
175  }
176 
177  // Remove triggers that are invalid or already executed
178  DBG( cout << "CGovernanceTriggerManager::CleanAndRemove: mapTrigger.size() = " << mapTrigger.size() << endl; );
179  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- mapTrigger.size() = %d\n", mapTrigger.size());
180  trigger_m_it it = mapTrigger.begin();
181  while(it != mapTrigger.end()) {
182  bool remove = false;
183  CSuperblock_sptr& pSuperblock = it->second;
184  if(!pSuperblock) {
185  DBG( cout << "CGovernanceTriggerManager::CleanAndRemove: NULL superblock marked for removal " << endl; );
186  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- NULL superblock marked for removal\n");
187  remove = true;
188  } else {
189  DBG( cout << "CGovernanceTriggerManager::CleanAndRemove: superblock status = " << pSuperblock->GetStatus() << endl; );
190  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- superblock status = %d\n", pSuperblock->GetStatus());
191  switch(pSuperblock->GetStatus()) {
193  case SEEN_OBJECT_UNKNOWN:
194  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Unknown or invalid trigger found\n");
195  remove = true;
196  break;
199  {
200  int nTriggerBlock = pSuperblock->GetBlockStart();
201  // Rough approximation: a cycle of superblock ++
202  int nExpirationBlock = nTriggerBlock + GOVERNANCE_TRIGGER_EXPIRATION_BLOCKS;
203  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- nTriggerBlock = %d, nExpirationBlock = %d\n", nTriggerBlock, nExpirationBlock);
204  if(governance.GetCachedBlockHeight() > nExpirationBlock) {
205  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Outdated trigger found\n");
206  remove = true;
207  CGovernanceObject* pgovobj = pSuperblock->GetGovernanceObject();
208  if(pgovobj) {
209  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Expiring outdated object: %s\n", pgovobj->GetHash().ToString());
210  pgovobj->fExpired = true;
211  pgovobj->nDeletionTime = GetAdjustedTime();
212  }
213  }
214  }
215  break;
216  default:
217  break;
218  }
219  }
220 
221  if(remove) {
222  DBG(
223  string strdata = "NULL";
224  CGovernanceObject* pgovobj = pSuperblock->GetGovernanceObject();
225  if(pgovobj) {
226  strdata = pgovobj->GetDataAsString();
227  }
228  cout << "CGovernanceTriggerManager::CleanAndRemove: Removing object: "
229  << strdata
230  << endl;
231  );
232  LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Removing trigger object\n");
233  mapTrigger.erase(it++);
234  }
235  else {
236  ++it;
237  }
238  }
239 
240  DBG( cout << "CGovernanceTriggerManager::CleanAndRemove: End" << endl; );
241 }
242 
250 std::vector<CSuperblock_sptr> CGovernanceTriggerManager::GetActiveTriggers()
251 {
253  std::vector<CSuperblock_sptr> vecResults;
254 
255  DBG( cout << "GetActiveTriggers: mapTrigger.size() = " << mapTrigger.size() << endl; );
256 
257  // LOOK AT THESE OBJECTS AND COMPILE A VALID LIST OF TRIGGERS
258  trigger_m_it it = mapTrigger.begin();
259  while(it != mapTrigger.end()) {
260 
262 
263  if(pObj) {
264  DBG( cout << "GetActiveTriggers: pObj->GetDataAsString() = " << pObj->GetDataAsString() << endl; );
265  vecResults.push_back(it->second);
266  }
267  ++it;
268  }
269 
270  DBG( cout << "GetActiveTriggers: vecResults.size() = " << vecResults.size() << endl; );
271 
272  return vecResults;
273 }
274 
282 {
283  LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- Start nBlockHeight = %d\n", nBlockHeight);
284  if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
285  return false;
286  }
287 
288  LOCK(governance.cs);
289  // GET ALL ACTIVE TRIGGERS
290  std::vector<CSuperblock_sptr> vecTriggers = triggerman.GetActiveTriggers();
291 
292  LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- vecTriggers.size() = %d\n", vecTriggers.size());
293 
294  DBG( cout << "IsSuperblockTriggered Number triggers = " << vecTriggers.size() << endl; );
295 
296  BOOST_FOREACH(CSuperblock_sptr pSuperblock, vecTriggers)
297  {
298  if(!pSuperblock) {
299  LogPrintf("CSuperblockManager::IsSuperblockTriggered -- Non-superblock found, continuing\n");
300  DBG( cout << "IsSuperblockTriggered Not a superblock, continuing " << endl; );
301  continue;
302  }
303 
304  CGovernanceObject* pObj = pSuperblock->GetGovernanceObject();
305 
306  if(!pObj) {
307  LogPrintf("CSuperblockManager::IsSuperblockTriggered -- pObj == NULL, continuing\n");
308  DBG( cout << "IsSuperblockTriggered pObj is NULL, continuing" << endl; );
309  continue;
310  }
311 
312  LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- data = %s\n", pObj->GetDataAsString());
313 
314  // note : 12.1 - is epoch calculation correct?
315 
316  if(nBlockHeight != pSuperblock->GetBlockStart()) {
317  LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- block height doesn't match nBlockHeight = %d, blockStart = %d, continuing\n",
318  nBlockHeight,
319  pSuperblock->GetBlockStart());
320  DBG( cout << "IsSuperblockTriggered Not the target block, continuing"
321  << ", nBlockHeight = " << nBlockHeight
322  << ", superblock->GetBlockStart() = " << pSuperblock->GetBlockStart()
323  << endl; );
324  continue;
325  }
326 
327  // MAKE SURE THIS TRIGGER IS ACTIVE VIA FUNDING CACHE FLAG
328 
329  pObj->UpdateSentinelVariables();
330 
331  if(pObj->IsSetCachedFunding()) {
332  LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = true, returning true\n");
333  DBG( cout << "IsSuperblockTriggered returning true" << endl; );
334  return true;
335  }
336  else {
337  LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = false, continuing\n");
338  DBG( cout << "IsSuperblockTriggered No fCachedFunding, continuing" << endl; );
339  }
340  }
341 
342  return false;
343 }
344 
345 
346 bool CSuperblockManager::GetBestSuperblock(CSuperblock_sptr& pSuperblockRet, int nBlockHeight)
347 {
348  if(!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
349  return false;
350  }
351 
353  std::vector<CSuperblock_sptr> vecTriggers = triggerman.GetActiveTriggers();
354  int nYesCount = 0;
355 
356  BOOST_FOREACH(CSuperblock_sptr pSuperblock, vecTriggers) {
357  if(!pSuperblock) {
358  DBG( cout << "GetBestSuperblock Not a superblock, continuing" << endl; );
359  continue;
360  }
361 
362  CGovernanceObject* pObj = pSuperblock->GetGovernanceObject();
363 
364  if(!pObj) {
365  DBG( cout << "GetBestSuperblock pObj is NULL, continuing" << endl; );
366  continue;
367  }
368 
369  if(nBlockHeight != pSuperblock->GetBlockStart()) {
370  DBG( cout << "GetBestSuperblock Not the target block, continuing" << endl; );
371  continue;
372  }
373 
374  // DO WE HAVE A NEW WINNER?
375 
376  int nTempYesCount = pObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING);
377  DBG( cout << "GetBestSuperblock nTempYesCount = " << nTempYesCount << endl; );
378  if(nTempYesCount > nYesCount) {
379  nYesCount = nTempYesCount;
380  pSuperblockRet = pSuperblock;
381  DBG( cout << "GetBestSuperblock Valid superblock found, pSuperblock set" << endl; );
382  }
383  }
384 
385  return nYesCount > 0;
386 }
387 
394 void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNewRet, int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet)
395 {
396  DBG( cout << "CSuperblockManager::CreateSuperblock Start" << endl; );
397 
398  LOCK(governance.cs);
399 
400  // GET THE BEST SUPERBLOCK FOR THIS BLOCK HEIGHT
401 
402  CSuperblock_sptr pSuperblock;
403  if(!CSuperblockManager::GetBestSuperblock(pSuperblock, nBlockHeight)) {
404  LogPrint("gobject", "CSuperblockManager::CreateSuperblock -- Can't find superblock for height %d\n", nBlockHeight);
405  DBG( cout << "CSuperblockManager::CreateSuperblock Failed to get superblock for height, returning" << endl; );
406  return;
407  }
408 
409  // make sure it's empty, just in case
410  voutSuperblockRet.clear();
411 
412  // CONFIGURE SUPERBLOCK OUTPUTS
413 
414  // Superblock payments are appended to the end of the coinbase vout vector
415  DBG( cout << "CSuperblockManager::CreateSuperblock Number payments: " << pSuperblock->CountPayments() << endl; );
416 
417  // TODO: How many payments can we add before things blow up?
418  // Consider at least following limits:
419  // - max coinbase tx size
420  // - max "budget" available
421  for(int i = 0; i < pSuperblock->CountPayments(); i++) {
422  CGovernancePayment payment;
423  DBG( cout << "CSuperblockManager::CreateSuperblock i = " << i << endl; );
424  if(pSuperblock->GetPayment(i, payment)) {
425  DBG( cout << "CSuperblockManager::CreateSuperblock Payment found " << endl; );
426  // SET COINBASE OUTPUT TO SUPERBLOCK SETTING
427 
428  CTxOut txout = CTxOut(payment.nAmount, payment.script);
429  txNewRet.vout.push_back(txout);
430  voutSuperblockRet.push_back(txout);
431 
432  // PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
433 
434  CTxDestination address1;
435  ExtractDestination(payment.script, address1);
436  CBitcoinAddress address2(address1);
437 
438  // TODO: PRINT NICE N.N DASH OUTPUT
439 
440  DBG( cout << "CSuperblockManager::CreateSuperblock Before LogPrintf call, nAmount = " << payment.nAmount << endl; );
441  LogPrintf("NEW Superblock : output %d (addr %s, amount %d)\n", i, address2.ToString(), payment.nAmount);
442  DBG( cout << "CSuperblockManager::CreateSuperblock After LogPrintf call " << endl; );
443  } else {
444  DBG( cout << "CSuperblockManager::CreateSuperblock Payment not found " << endl; );
445  }
446  }
447 
448  DBG( cout << "CSuperblockManager::CreateSuperblock End" << endl; );
449 }
450 
451 bool CSuperblockManager::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
452 {
453  // GET BEST SUPERBLOCK, SHOULD MATCH
454  LOCK(governance.cs);
455 
456  CSuperblock_sptr pSuperblock;
457  if(CSuperblockManager::GetBestSuperblock(pSuperblock, nBlockHeight)) {
458  return pSuperblock->IsValid(txNew, nBlockHeight, blockReward);
459  }
460 
461  return false;
462 }
463 
466  : nGovObjHash(),
467  nEpochStart(0),
468  nStatus(SEEN_OBJECT_UNKNOWN),
469  vecPayments()
470 {}
471 
474  : nGovObjHash(nHash),
475  nEpochStart(0),
476  nStatus(SEEN_OBJECT_UNKNOWN),
477  vecPayments()
478 {
479  DBG( cout << "CSuperblock Constructor Start" << endl; );
480 
482 
483  if(!pGovObj) {
484  DBG( cout << "CSuperblock Constructor pGovObjIn is NULL, returning" << endl; );
485  throw std::runtime_error("CSuperblock: Failed to find Governance Object");
486  }
487 
488  DBG( cout << "CSuperblock Constructor pGovObj : "
489  << pGovObj->GetDataAsString()
490  << ", nObjectType = " << pGovObj->GetObjectType()
491  << endl; );
492 
493  if (pGovObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) {
494  DBG( cout << "CSuperblock Constructor pHoObj not a trigger, returning" << endl; );
495  throw std::runtime_error("CSuperblock: Governance Object not a trigger");
496  }
497 
498  UniValue obj = pGovObj->GetJSONObject();
499 
500  // FIRST WE GET THE START EPOCH, THE DATE WHICH THE PAYMENT SHALL OCCUR
501  nEpochStart = obj["event_block_height"].get_int();
502 
503  // NEXT WE GET THE PAYMENT INFORMATION AND RECONSTRUCT THE PAYMENT VECTOR
504  std::string strAddresses = obj["payment_addresses"].get_str();
505  std::string strAmounts = obj["payment_amounts"].get_str();
506  ParsePaymentSchedule(strAddresses, strAmounts);
507 
508  LogPrint("gobject", "CSuperblock -- nEpochStart = %d, strAddresses = %s, strAmounts = %s, vecPayments.size() = %d\n",
509  nEpochStart, strAddresses, strAmounts, vecPayments.size());
510 
511  DBG( cout << "CSuperblock Constructor End" << endl; );
512 }
513 
520 bool CSuperblock::IsValidBlockHeight(int nBlockHeight)
521 {
522  // SUPERBLOCKS CAN HAPPEN ONLY after hardfork and only ONCE PER CYCLE
523  return nBlockHeight >= Params().GetConsensus().nSuperblockStartBlock &&
524  ((nBlockHeight % Params().GetConsensus().nSuperblockCycle) == 0);
525 }
526 
528 {
529  const Consensus::Params& consensusParams = Params().GetConsensus();
530 
531  if(!IsValidBlockHeight(nBlockHeight)) {
532  return 0;
533  }
534 
535  // min subsidy for high diff networks and vice versa
536  int nBits = consensusParams.fPowAllowMinDifficultyBlocks ? UintToArith256(consensusParams.powLimit).GetCompact() : 1;
537  // some part of all blocks issued during the cycle goes to superblock, see GetBlockSubsidy
538  CAmount nSuperblockPartOfSubsidy = GetBlockSubsidy(nBits, nBlockHeight - 1, consensusParams, true);
539  CAmount nPaymentsLimit = nSuperblockPartOfSubsidy * consensusParams.nSuperblockCycle;
540  LogPrint("gobject", "CSuperblock::GetPaymentsLimit -- Valid superblock height %d, payments max %lld\n", nBlockHeight, nPaymentsLimit);
541 
542  return nPaymentsLimit;
543 }
544 
545 void CSuperblock::ParsePaymentSchedule(std::string& strPaymentAddresses, std::string& strPaymentAmounts)
546 {
547  // SPLIT UP ADDR/AMOUNT STRINGS AND PUT IN VECTORS
548 
549  std::vector<std::string> vecParsed1;
550  std::vector<std::string> vecParsed2;
551  vecParsed1 = SplitBy(strPaymentAddresses, "|");
552  vecParsed2 = SplitBy(strPaymentAmounts, "|");
553 
554  // IF THESE DONT MATCH, SOMETHING IS WRONG
555 
556  if (vecParsed1.size() != vecParsed2.size()) {
557  std::ostringstream ostr;
558  ostr << "CSuperblock::ParsePaymentSchedule -- Mismatched payments and amounts";
559  LogPrintf("%s\n", ostr.str());
560  throw std::runtime_error(ostr.str());
561  }
562 
563  if (vecParsed1.size() == 0) {
564  std::ostringstream ostr;
565  ostr << "CSuperblock::ParsePaymentSchedule -- Error no payments";
566  LogPrintf("%s\n", ostr.str());
567  throw std::runtime_error(ostr.str());
568  }
569 
570  // LOOP THROUGH THE ADDRESSES/AMOUNTS AND CREATE PAYMENTS
571  /*
572  ADDRESSES = [ADDR1|2|3|4|5|6]
573  AMOUNTS = [AMOUNT1|2|3|4|5|6]
574  */
575 
576  DBG( cout << "CSuperblock::ParsePaymentSchedule vecParsed1.size() = " << vecParsed1.size() << endl; );
577 
578  for (int i = 0; i < (int)vecParsed1.size(); i++) {
579  CBitcoinAddress address(vecParsed1[i]);
580  if (!address.IsValid()) {
581  std::ostringstream ostr;
582  ostr << "CSuperblock::ParsePaymentSchedule -- Invalid Dash Address : " << vecParsed1[i];
583  LogPrintf("%s\n", ostr.str());
584  throw std::runtime_error(ostr.str());
585  }
586 
587  DBG( cout << "CSuperblock::ParsePaymentSchedule i = " << i
588  << ", vecParsed2[i] = " << vecParsed2[i]
589  << endl; );
590 
591  CAmount nAmount = ParsePaymentAmount(vecParsed2[i]);
592 
593  DBG( cout << "CSuperblock::ParsePaymentSchedule: "
594  << "amount string = " << vecParsed2[i]
595  << ", nAmount = " << nAmount
596  << endl; );
597 
598  CGovernancePayment payment(address, nAmount);
599  if(payment.IsValid()) {
600  vecPayments.push_back(payment);
601  }
602  else {
603  vecPayments.clear();
604  std::ostringstream ostr;
605  ostr << "CSuperblock::ParsePaymentSchedule -- Invalid payment found: address = " << address.ToString()
606  << ", amount = " << nAmount;
607  LogPrintf("%s\n", ostr.str());
608  throw std::runtime_error(ostr.str());
609  }
610  }
611 }
612 
613 bool CSuperblock::GetPayment(int nPaymentIndex, CGovernancePayment& paymentRet)
614 {
615  if((nPaymentIndex<0) || (nPaymentIndex >= (int)vecPayments.size())) {
616  return false;
617  }
618 
619  paymentRet = vecPayments[nPaymentIndex];
620  return true;
621 }
622 
624 {
625  CAmount nPaymentsTotalAmount = 0;
626  int nPayments = CountPayments();
627 
628  for(int i = 0; i < nPayments; i++) {
629  nPaymentsTotalAmount += vecPayments[i].nAmount;
630  }
631 
632  return nPaymentsTotalAmount;
633 }
634 
641 bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
642 {
643  // TODO : LOCK(cs);
644  // No reason for a lock here now since this method only accesses data
645  // internal to *this and since CSuperblock's are accessed only through
646  // shared pointers there's no way our object can get deleted while this
647  // code is running.
648  if(!IsValidBlockHeight(nBlockHeight)) {
649  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, incorrect block height\n");
650  return false;
651  }
652 
653  std::string strPayeesPossible = "";
654 
655  // CONFIGURE SUPERBLOCK OUTPUTS
656 
657  int nOutputs = txNew.vout.size();
658  int nPayments = CountPayments();
659  int nMinerPayments = nOutputs - nPayments;
660 
661  LogPrint("gobject", "CSuperblock::IsValid nOutputs = %d, nPayments = %d, strData = %s\n",
662  nOutputs, nPayments, GetGovernanceObject()->GetDataAsHex());
663 
664  // We require an exact match (including order) between the expected
665  // superblock payments and the payments actually in the block.
666 
667  if(nMinerPayments < 0) {
668  // This means the block cannot have all the superblock payments
669  // so it is not valid.
670  // TODO: could that be that we just hit coinbase size limit?
671  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, too few superblock payments\n");
672  return false;
673  }
674 
675  // payments should not exceed limit
676  CAmount nPaymentsTotalAmount = GetPaymentsTotalAmount();
677  CAmount nPaymentsLimit = GetPaymentsLimit(nBlockHeight);
678  if(nPaymentsTotalAmount > nPaymentsLimit) {
679  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, payments limit exceeded: payments %lld, limit %lld\n", nPaymentsTotalAmount, nPaymentsLimit);
680  return false;
681  }
682 
683  // miner should not get more than he would usually get
684  CAmount nBlockValue = txNew.GetValueOut();
685  if(nBlockValue > blockReward + nPaymentsTotalAmount) {
686  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, block value limit exceeded: block %lld, limit %lld\n", nBlockValue, blockReward + nPaymentsTotalAmount);
687  return false;
688  }
689 
690  int nVoutIndex = 0;
691  for(int i = 0; i < nPayments; i++) {
692  CGovernancePayment payment;
693  if(!GetPayment(i, payment)) {
694  // This shouldn't happen so log a warning
695  LogPrintf("CSuperblock::IsValid -- WARNING: Failed to find payment: %d of %d total payments\n", i, nPayments);
696  continue;
697  }
698 
699  bool fPaymentMatch = false;
700 
701  for (int j = nVoutIndex; j < nOutputs; j++) {
702  // Find superblock payment
703  fPaymentMatch = ((payment.script == txNew.vout[j].scriptPubKey) &&
704  (payment.nAmount == txNew.vout[j].nValue));
705 
706  if (fPaymentMatch) {
707  nVoutIndex = j;
708  break;
709  }
710  }
711 
712  if(!fPaymentMatch) {
713  // Superblock payment not found!
714 
715  CTxDestination address1;
716  ExtractDestination(payment.script, address1);
717  CBitcoinAddress address2(address1);
718  LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid: %d payment %d to %s not found\n", i, payment.nAmount, address2.ToString());
719 
720  return false;
721  }
722  }
723 
724  return true;
725 }
726 
734 {
735  LOCK(governance.cs);
736  std::string ret = "Unknown";
737 
738  // GET BEST SUPERBLOCK
739 
740  CSuperblock_sptr pSuperblock;
741  if(!GetBestSuperblock(pSuperblock, nBlockHeight)) {
742  LogPrint("gobject", "CSuperblockManager::GetRequiredPaymentsString -- Can't find superblock for height %d\n", nBlockHeight);
743  return "error";
744  }
745 
746  // LOOP THROUGH SUPERBLOCK PAYMENTS, CONFIGURE OUTPUT STRING
747 
748  for(int i = 0; i < pSuperblock->CountPayments(); i++) {
749  CGovernancePayment payment;
750  if(pSuperblock->GetPayment(i, payment)) {
751  // PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
752 
753  CTxDestination address1;
754  ExtractDestination(payment.script, address1);
755  CBitcoinAddress address2(address1);
756 
757  // RETURN NICE OUTPUT FOR CONSOLE
758 
759  if(ret != "Unknown") {
760  ret += ", " + address2.ToString();
761  }
762  else {
763  ret = address2.ToString();
764  }
765  }
766  }
767 
768  return ret;
769 }
int nSuperblockCycle
Definition: params.h:55
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
Definition: standard.h:69
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: standard.cpp:164
int nSuperblockStartBlock
Definition: params.h:54
CAmount ParsePaymentAmount(const std::string &strAmount)
static std::string GetRequiredPaymentsString(int nBlockHeight)
static const int GOVERNANCE_TRIGGER_EXPIRATION_BLOCKS
bool IsValid() const
Definition: base58.cpp:247
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:55
bool fPowAllowMinDifficultyBlocks
Definition: params.h:78
#define DBG(x)
Definition: util.h:41
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:31
CGovernanceObject * FindGovernanceObject(const uint256 &nHash)
Definition: governance.cpp:559
CGovernanceObject * GetGovernanceObject()
static bool IsSuperblockTriggered(int nBlockHeight)
static const int SEEN_OBJECT_ERROR_INVALID
CAmount GetValueOut() const
bool IsValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
bool fExpired
Object is no longer of interest.
CAmount GetPaymentsTotalAmount()
uint32_t GetCompact(bool fNegative=false) const
std::vector< CSuperblock_sptr > GetActiveTriggers()
bool GetPayment(int nPaymentIndex, CGovernancePayment &paymentRet)
arith_uint256 UintToArith256(const uint256 &a)
std::string ToString() const
Definition: base58.cpp:193
static bool IsValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
int64_t CAmount
Definition: amount.h:14
#define AssertLockHeld(cs)
Definition: sync.h:96
CGovernanceTriggerManager triggerman
#define LogPrintf(...)
Definition: util.h:98
static bool GetBestSuperblock(CSuperblock_sptr &pSuperblockRet, int nBlockHeight)
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
#define LOCK(cs)
Definition: sync.h:168
int64_t nDeletionTime
time this object was marked for deletion
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
std::string GetDataAsHex()
static const int GOVERNANCE_OBJECT_TRIGGER
std::string GetDataAsString()
static const int SEEN_OBJECT_IS_VALID
std::string ToString() const
Definition: uint256.cpp:65
static CAmount GetPaymentsLimit(int nBlockHeight)
static const int SEEN_OBJECT_EXECUTED
static const int SEEN_OBJECT_UNKNOWN
std::vector< CTxOut > vout
Definition: transaction.h:307
void ParsePaymentSchedule(std::string &strPaymentAddresses, std::string &strPaymentAmounts)
bool AddNewTrigger(uint256 nHash)
bool IsSetCachedFunding() const
const CChainParams & Params()
int GetAbsoluteYesCount(vote_signal_enum_t eVoteSignalIn) const
int64_t GetAdjustedTime()
Definition: timedata.cpp:33
int GetCachedBlockHeight()
Definition: governance.h:373
std::string GetHex() const
Definition: uint256.cpp:21
const std::vector< CTxOut > vout
Definition: transaction.h:234
uint256 powLimit
Definition: params.h:77
int get_int() const
Definition: univalue.cpp:317
virtual uint256 GetHash()=0
CGovernanceManager governance
Definition: governance.cpp:17
std::vector< CGovernancePayment > vecPayments
CAmount GetBlockSubsidy(int nPrevBits, int nPrevHeight, const Consensus::Params &consensusParams, bool fSuperblockPartOnly)
boost::shared_ptr< CSuperblock > CSuperblock_sptr
static bool IsValidBlockHeight(int nBlockHeight)
std::vector< std::string > SplitBy(std::string strCommand, std::string strDelimit)
trigger_m_t::iterator trigger_m_it
CCriticalSection cs
Definition: governance.h:289
static void CreateSuperblock(CMutableTransaction &txNewRet, int nBlockHeight, std::vector< CTxOut > &voutSuperblockRet)
int GetObjectType() const
std::string get_str() const
Definition: univalue.cpp:310