Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

masternode-payments.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 <consensus/validation.h>
8 #include <init.h>
11 #include <messagesigner.h>
12 #include <netfulfilledman.h>
13 #include <netmessagemaker.h>
14 #include <spork.h>
15 #include <util.h>
16 #include <validation.h>
17 
18 #include <evo/deterministicmns.h>
19 
20 #include <string>
21 
23 
24 bool IsOldBudgetBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward, std::string& strErrorRet) {
25  const Consensus::Params& consensusParams = Params().GetConsensus();
26  bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockReward);
27 
28  if (nBlockHeight < consensusParams.nBudgetPaymentsStartBlock) {
29  strErrorRet = strprintf("Incorrect block %d, old budgets are not activated yet", nBlockHeight);
30  return false;
31  }
32 
33  if (nBlockHeight >= consensusParams.nSuperblockStartBlock) {
34  strErrorRet = strprintf("Incorrect block %d, old budgets are no longer active", nBlockHeight);
35  return false;
36  }
37 
38  // we are still using budgets, but we have no data about them anymore,
39  // all we know is predefined budget cycle and window
40 
41  int nOffset = nBlockHeight % consensusParams.nBudgetPaymentsCycleBlocks;
42  if(nBlockHeight >= consensusParams.nBudgetPaymentsStartBlock &&
43  nOffset < consensusParams.nBudgetPaymentsWindowBlocks) {
44  // NOTE: old budget system is disabled since 12.1
45  if(masternodeSync.IsSynced()) {
46  // no old budget blocks should be accepted here on mainnet,
47  // testnet/devnet/regtest should produce regular blocks only
48  LogPrint(BCLog::GOBJECT, "%s -- WARNING: Client synced but old budget system is disabled, checking block value against block reward\n", __func__);
49  if(!isBlockRewardValueMet) {
50  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, old budgets are disabled",
51  nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
52  }
53  return isBlockRewardValueMet;
54  }
55  // when not synced, rely on online nodes (all networks)
56  LogPrint(BCLog::GOBJECT, "%s -- WARNING: Skipping old budget block value checks, accepting block\n", __func__);
57  return true;
58  }
59  if(!isBlockRewardValueMet) {
60  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, block is not in old budget cycle window",
61  nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
62  }
63  return isBlockRewardValueMet;
64 }
65 
77 bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward, std::string& strErrorRet)
78 {
79  const Consensus::Params& consensusParams = Params().GetConsensus();
80  bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockReward);
81 
82  strErrorRet = "";
83 
84  if (nBlockHeight < consensusParams.nBudgetPaymentsStartBlock) {
85  // old budget system is not activated yet, just make sure we do not exceed the regular block reward
86  if(!isBlockRewardValueMet) {
87  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, old budgets are not activated yet",
88  nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
89  }
90  return isBlockRewardValueMet;
91  } else if (nBlockHeight < consensusParams.nSuperblockStartBlock) {
92  // superblocks are not enabled yet, check if we can pass old budget rules
93  return IsOldBudgetBlockValueValid(block, nBlockHeight, blockReward, strErrorRet);
94  }
95 
96  LogPrint(BCLog::MNPAYMENTS, "block.vtx[0]->GetValueOut() %lld <= blockReward %lld\n", block.vtx[0]->GetValueOut(), blockReward);
97 
98  CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit(nBlockHeight);
99  bool isSuperblockMaxValueMet = (block.vtx[0]->GetValueOut() <= nSuperblockMaxValue);
100 
101  LogPrint(BCLog::GOBJECT, "block.vtx[0]->GetValueOut() %lld <= nSuperblockMaxValue %lld\n", block.vtx[0]->GetValueOut(), nSuperblockMaxValue);
102 
103  if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
104  // can't possibly be a superblock, so lets just check for block reward limits
105  if (!isBlockRewardValueMet) {
106  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",
107  nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
108  }
109  return isBlockRewardValueMet;
110  }
111 
112  // bail out in case superblock limits were exceeded
113  if (!isSuperblockMaxValueMet) {
114  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded superblock max value",
115  nBlockHeight, block.vtx[0]->GetValueOut(), nSuperblockMaxValue);
116  return false;
117  }
118 
120  LogPrint(BCLog::MNPAYMENTS, "%s -- WARNING: Not enough data, checked superblock max bounds only\n", __func__);
121  // not enough data for full checks but at least we know that the superblock limits were honored.
122  // We rely on the network to have followed the correct chain in this case
123  return true;
124  }
125 
126  // we are synced and possibly on a superblock now
127 
129  // should NOT allow superblocks at all, when superblocks are disabled
130  // revert to block reward limits in this case
131  LogPrint(BCLog::GOBJECT, "%s -- Superblocks are disabled, no superblocks allowed\n", __func__);
132  if(!isBlockRewardValueMet) {
133  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, superblocks are disabled",
134  nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
135  }
136  return isBlockRewardValueMet;
137  }
138 
139  if (!CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
140  // we are on a valid superblock height but a superblock was not triggered
141  // revert to block reward limits in this case
142  if(!isBlockRewardValueMet) {
143  strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, no triggered superblock detected",
144  nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
145  }
146  return isBlockRewardValueMet;
147  }
148 
149  // this actually also checks for correct payees and not only amount
150  if (!CSuperblockManager::IsValid(*block.vtx[0], nBlockHeight, blockReward)) {
151  // triggered but invalid? that's weird
152  LogPrintf("%s -- ERROR: Invalid superblock detected at height %d: %s", __func__, nBlockHeight, block.vtx[0]->ToString()); /* Continued */
153  // should NOT allow invalid superblocks, when superblocks are enabled
154  strErrorRet = strprintf("invalid superblock detected at height %d", nBlockHeight);
155  return false;
156  }
157 
158  // we got a valid superblock
159  return true;
160 }
161 
162 bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
163 {
164  if(fDisableGovernance) {
165  //there is no budget data to use to check anything, let's just accept the longest chain
166  LogPrint(BCLog::MNPAYMENTS, "%s -- WARNING: Not enough data, skipping block payee checks\n", __func__);
167  return true;
168  }
169 
170  // we are still using budgets, but we have no data about them anymore,
171  // we can only check masternode payments
172 
173  const Consensus::Params& consensusParams = Params().GetConsensus();
174 
175  if(nBlockHeight < consensusParams.nSuperblockStartBlock) {
176  // NOTE: old budget system is disabled since 12.1 and we should never enter this branch
177  // anymore when sync is finished (on mainnet). We have no old budget data but these blocks
178  // have tons of confirmations and can be safely accepted without payee verification
179  LogPrint(BCLog::GOBJECT, "%s -- WARNING: Client synced but old budget system is disabled, accepting any payee\n", __func__);
180  return true;
181  }
182 
183  // superblocks started
184  // SEE IF THIS IS A VALID SUPERBLOCK
185 
188  if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) {
189  LogPrint(BCLog::GOBJECT, "%s -- Valid superblock at height %d: %s", __func__, nBlockHeight, txNew.ToString());
190  // continue validation, should also pay MN
191  } else {
192  LogPrintf("%s -- ERROR: Invalid superblock detected at height %d: %s", __func__, nBlockHeight, txNew.ToString()); /* Continued */
193  // should NOT allow such superblocks, when superblocks are enabled
194  return false;
195  }
196  } else {
197  LogPrint(BCLog::GOBJECT, "%s -- No triggered superblock detected at height %d\n", __func__, nBlockHeight);
198  }
199  } else {
200  // should NOT allow superblocks at all, when superblocks are disabled
201  LogPrint(BCLog::GOBJECT, "%s -- Superblocks are disabled, no superblocks allowed\n", __func__);
202  }
203 
204  // Check for correct masternode payment
205  if(mnpayments.IsTransactionValid(txNew, nBlockHeight, blockReward)) {
206  LogPrint(BCLog::MNPAYMENTS, "%s -- Valid masternode payment at height %d: %s", __func__, nBlockHeight, txNew.ToString());
207  return true;
208  }
209 
210  LogPrintf("%s -- ERROR: Invalid masternode payment detected at height %d: %s", __func__, nBlockHeight, txNew.ToString()); /* Continued */
211  return false;
212 }
213 
214 void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet, std::vector<CTxOut>& voutSuperblockPaymentsRet)
215 {
216  // only create superblocks if spork is enabled AND if superblock is actually triggered
217  // (height should be validated inside)
220  LogPrint(BCLog::GOBJECT, "%s -- triggered superblock creation at height %d\n", __func__, nBlockHeight);
221  CSuperblockManager::GetSuperblockPayments(nBlockHeight, voutSuperblockPaymentsRet);
222  }
223 
224  if (!mnpayments.GetMasternodeTxOuts(nBlockHeight, blockReward, voutMasternodePaymentsRet)) {
225  LogPrint(BCLog::MNPAYMENTS, "%s -- no masternode to pay (MN list probably empty)\n", __func__);
226  }
227 
228  txNew.vout.insert(txNew.vout.end(), voutMasternodePaymentsRet.begin(), voutMasternodePaymentsRet.end());
229  txNew.vout.insert(txNew.vout.end(), voutSuperblockPaymentsRet.begin(), voutSuperblockPaymentsRet.end());
230 
231  std::string voutMasternodeStr;
232  for (const auto& txout : voutMasternodePaymentsRet) {
233  // subtract MN payment from miner reward
234  txNew.vout[0].nValue -= txout.nValue;
235  if (!voutMasternodeStr.empty())
236  voutMasternodeStr += ",";
237  voutMasternodeStr += txout.ToString();
238  }
239 
240  LogPrint(BCLog::MNPAYMENTS, "%s -- nBlockHeight %d blockReward %lld voutMasternodePaymentsRet \"%s\" txNew %s", __func__,
241  nBlockHeight, blockReward, voutMasternodeStr, txNew.ToString());
242 }
243 
244 std::string GetRequiredPaymentsString(int nBlockHeight, const CDeterministicMNCPtr &payee)
245 {
246  std::string strPayee = "Unknown";
247  if (payee) {
248  CTxDestination dest;
249  if (!ExtractDestination(payee->pdmnState->scriptPayout, dest))
250  assert(false);
251  strPayee = EncodeDestination(dest);
252  }
253  if (CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
254  strPayee += ", " + CSuperblockManager::GetRequiredPaymentsString(nBlockHeight);
255  }
256  return strPayee;
257 }
258 
259 std::map<int, std::string> GetRequiredPaymentsStrings(int nStartHeight, int nEndHeight)
260 {
261  std::map<int, std::string> mapPayments;
262 
263  if (nStartHeight < 1) {
264  nStartHeight = 1;
265  }
266 
267  LOCK(cs_main);
268  int nChainTipHeight = chainActive.Height();
269 
270  bool doProjection = false;
271  for(int h = nStartHeight; h < nEndHeight; h++) {
272  if (h <= nChainTipHeight) {
273  auto payee = deterministicMNManager->GetListForBlock(chainActive[h - 1]).GetMNPayee();
274  mapPayments.emplace(h, GetRequiredPaymentsString(h, payee));
275  } else {
276  doProjection = true;
277  break;
278  }
279  }
280  if (doProjection) {
281  auto projection = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(nEndHeight - nChainTipHeight);
282  for (size_t i = 0; i < projection.size(); i++) {
283  auto payee = projection[i];
284  int h = nChainTipHeight + 1 + i;
285  mapPayments.emplace(h, GetRequiredPaymentsString(h, payee));
286  }
287  }
288 
289  return mapPayments;
290 }
291 
298 bool CMasternodePayments::GetMasternodeTxOuts(int nBlockHeight, CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet) const
299 {
300  // make sure it's not filled yet
301  voutMasternodePaymentsRet.clear();
302 
303  if(!GetBlockTxOuts(nBlockHeight, blockReward, voutMasternodePaymentsRet)) {
304  LogPrintf("CMasternodePayments::%s -- no payee (deterministic masternode list empty)\n", __func__);
305  return false;
306  }
307 
308  for (const auto& txout : voutMasternodePaymentsRet) {
309  CTxDestination dest;
310  ExtractDestination(txout.scriptPubKey, dest);
311 
312  LogPrintf("CMasternodePayments::%s -- Masternode payment %lld to %s\n", __func__, txout.nValue, EncodeDestination(dest));
313  }
314 
315  return true;
316 }
317 
318 bool CMasternodePayments::GetBlockTxOuts(int nBlockHeight, CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet) const
319 {
320  voutMasternodePaymentsRet.clear();
321 
322  const CBlockIndex* pindex;
323  int nReallocActivationHeight{std::numeric_limits<int>::max()};
324 
325  {
326  LOCK(cs_main);
327  pindex = chainActive[nBlockHeight - 1];
328 
329  const Consensus::Params& consensusParams = Params().GetConsensus();
331  nReallocActivationHeight = VersionBitsStateSinceHeight(pindex, consensusParams, Consensus::DEPLOYMENT_REALLOC, versionbitscache);
332  }
333  }
334  uint256 proTxHash;
335 
336  CAmount masternodeReward = GetMasternodePayment(nBlockHeight, blockReward, nReallocActivationHeight);
337 
338  auto dmnPayee = deterministicMNManager->GetListForBlock(pindex).GetMNPayee();
339  if (!dmnPayee) {
340  return false;
341  }
342 
343  CAmount operatorReward = 0;
344  if (dmnPayee->nOperatorReward != 0 && dmnPayee->pdmnState->scriptOperatorPayout != CScript()) {
345  // This calculation might eventually turn out to result in 0 even if an operator reward percentage is given.
346  // This will however only happen in a few years when the block rewards drops very low.
347  operatorReward = (masternodeReward * dmnPayee->nOperatorReward) / 10000;
348  masternodeReward -= operatorReward;
349  }
350 
351  if (masternodeReward > 0) {
352  voutMasternodePaymentsRet.emplace_back(masternodeReward, dmnPayee->pdmnState->scriptPayout);
353  }
354  if (operatorReward > 0) {
355  voutMasternodePaymentsRet.emplace_back(operatorReward, dmnPayee->pdmnState->scriptOperatorPayout);
356  }
357 
358  return true;
359 }
360 
361 bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const
362 {
363  if (!deterministicMNManager->IsDIP3Enforced(nBlockHeight)) {
364  // can't verify historical blocks here
365  return true;
366  }
367 
368  std::vector<CTxOut> voutMasternodePayments;
369  if (!GetBlockTxOuts(nBlockHeight, blockReward, voutMasternodePayments)) {
370  LogPrintf("CMasternodePayments::%s -- ERROR failed to get payees for block at height %s\n", __func__, nBlockHeight);
371  return true;
372  }
373 
374  for (const auto& txout : voutMasternodePayments) {
375  bool found = false;
376  for (const auto& txout2 : txNew.vout) {
377  if (txout == txout2) {
378  found = true;
379  break;
380  }
381  }
382  if (!found) {
383  CTxDestination dest;
384  if (!ExtractDestination(txout.scriptPubKey, dest))
385  assert(false);
386  LogPrintf("CMasternodePayments::%s -- ERROR failed to find expected payee %s in block at height %s\n", __func__, EncodeDestination(dest), nBlockHeight);
387  return false;
388  }
389  }
390  return true;
391 }
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
CMasternodeSync masternodeSync
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
Definition: block.h:72
int nBudgetPaymentsCycleBlocks
Definition: params.h:140
#define strprintf
Definition: tinyformat.h:1066
int nBudgetPaymentsWindowBlocks
Definition: params.h:141
bool IsBlockPayeeValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
int Height() const
Return the maximal height in the chain.
Definition: chain.h:484
CCriticalSection cs_main
Definition: validation.cpp:213
static bool IsSuperblockTriggered(int nBlockHeight)
Is Superblock Triggered.
bool IsOldBudgetBlockValueValid(const CBlock &block, int nBlockHeight, CAmount blockReward, std::string &strErrorRet)
static bool IsValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward)
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
int nBudgetPaymentsStartBlock
Definition: params.h:139
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
#define LogPrintf(...)
Definition: util.h:203
int nSuperblockStartBlock
Definition: params.h:142
CMasternodePayments mnpayments
int VersionBitsStateSinceHeight(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
#define LOCK(cs)
Definition: sync.h:178
static bool IsValidBlockHeight(int nBlockHeight)
Is Valid Superblock Height.
CAmount GetMasternodePayment(int nHeight, CAmount blockValue, int nReallocActivationHeight)
const std::vector< CTxOut > vout
Definition: transaction.h:216
static std::string GetRequiredPaymentsString(int nBlockHeight)
Get Required Payment String.
std::string GetRequiredPaymentsString(int nBlockHeight, const CDeterministicMNCPtr &payee)
Parameters that influence chain consensus.
Definition: params.h:130
std::vector< CTxOut > vout
Definition: transaction.h:294
VersionBitsCache versionbitscache
CSporkManager sporkManager
Definition: spork.cpp:29
#define LogPrint(category,...)
Definition: util.h:214
bool GetBlockTxOuts(int nBlockHeight, CAmount blockReward, std::vector< CTxOut > &voutMasternodePaymentsRet) const
bool IsBlockValueValid(const CBlock &block, int nBlockHeight, CAmount blockReward, std::string &strErrorRet)
IsBlockValueValid.
256-bit opaque blob.
Definition: uint256.h:123
static bool GetSuperblockPayments(int nBlockHeight, std::vector< CTxOut > &voutSuperblockRet)
Get Superblock Payments.
std::vector< CTransactionRef > vtx
Definition: block.h:76
static CAmount GetPaymentsLimit(int nBlockHeight)
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
std::string ToString() const
Definition: transaction.cpp:71
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
const CChainParams & Params()
Return the currently selected parameters.
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:389
std::map< int, std::string > GetRequiredPaymentsStrings(int nStartHeight, int nEndHeight)
std::string ToString() const
void FillBlockPayments(CMutableTransaction &txNew, int nBlockHeight, CAmount blockReward, std::vector< CTxOut > &voutMasternodePaymentsRet, std::vector< CTxOut > &voutSuperblockPaymentsRet)
A mutable version of CTransaction.
Definition: transaction.h:291
bool GetMasternodeTxOuts(int nBlockHeight, CAmount blockReward, std::vector< CTxOut > &voutMasternodePaymentsRet) const
GetMasternodeTxOuts.
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:198
bool IsSporkActive(SporkId nSporkID)
IsSporkActive returns a bool for time-based sporks, and should be used to determine whether the spork...
Definition: spork.cpp:211
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:54
bool fDisableGovernance
Definition: util.cpp:94
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:217
ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
bool IsTransactionValid(const CTransaction &txNew, int nBlockHeight, CAmount blockReward) const
Released under the MIT license