PIVX Core  5.6.99
P2P Digital Currency
budget_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2022 The PIVX 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 "test_pivx.h"
6 
7 #include "bls/bls_wrapper.h"
8 #include "budget/budgetmanager.h"
9 #include "masternode-payments.h"
10 #include "spork.h"
11 #include "test/util/blocksutil.h"
13 #include "tinyformat.h"
14 #include "utilmoneystr.h"
15 #include "validation.h"
16 
17 #include <boost/test/unit_test.hpp>
18 
19 BOOST_AUTO_TEST_SUITE(budget_tests)
20 
21 void CheckBudgetValue(int nHeight, std::string strNetwork, CAmount nExpectedValue)
22 {
23  CBudgetManager budget;
24  CAmount nBudget = g_budgetman.GetTotalBudget(nHeight);
25  std::string strError = strprintf("Budget is not as expected for %s. Result: %s, Expected: %s", strNetwork, FormatMoney(nBudget), FormatMoney(nExpectedValue));
26  BOOST_CHECK_MESSAGE(nBudget == nExpectedValue, strError);
27 }
28 
30 {
31  // force mnsync complete
33 
34  // enable SPORK_13
35  int64_t nTime = GetTime() - 10;
39 
43 }
44 
45 BOOST_AUTO_TEST_CASE(masternode_value)
46 {
49  BOOST_CHECK_EQUAL(GetMasternodePayment(nHeightTest - 1), 3 * COIN);
50  BOOST_CHECK_EQUAL(GetMasternodePayment(nHeightTest), 6 * COIN);
51 }
52 
53 BOOST_AUTO_TEST_CASE(budget_value)
54 {
57  CheckBudgetValue(nHeightTest-1, "testnet", 7200*COIN);
58  CheckBudgetValue(nHeightTest, "testnet", 144*COIN);
59 
62  CheckBudgetValue(nHeightTest, "mainnet", 43200*COIN);
63 
66  CheckBudgetValue(nHeightTest-1, "testnet", 144*COIN);
67  CheckBudgetValue(nHeightTest, "testnet", 1440*COIN);
68 
71  CheckBudgetValue(nHeightTest-1, "mainnet", 43200*COIN);
72  CheckBudgetValue(nHeightTest, "mainnet", 432000*COIN);
73 
74 }
75 
77 {
79  int nHeight = 100; std::string strError;
80  const CAmount nBlockReward = GetBlockValue(nHeight);
81  CAmount nExpectedRet = nBlockReward;
82  CAmount nBudgetAmtRet = 0;
83 
84  // regular block
85  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, 0, nBudgetAmtRet));
86  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, nBlockReward-1, nBudgetAmtRet));
87  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward);
88  BOOST_CHECK_EQUAL(nBudgetAmtRet, 0);
89  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, nBlockReward, nBudgetAmtRet));
90  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward);
91  BOOST_CHECK_EQUAL(nBudgetAmtRet, 0);
92  BOOST_CHECK(!IsBlockValueValid(nHeight, nExpectedRet, nBlockReward+1, nBudgetAmtRet));
93  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward);
94  BOOST_CHECK_EQUAL(nBudgetAmtRet, 0);
95 
96  // superblock - create the finalized budget with a proposal, and vote on it
97  nHeight = 144;
98  const CTxIn mnVin(GetRandHash(), 0);
99  const CScript payee = GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))));
100  const CAmount propAmt = 100 * COIN;
101  const uint256& propHash = GetRandHash(), finTxId = GetRandHash();
102  const CTxBudgetPayment txBudgetPayment(propHash, payee, propAmt);
103  CFinalizedBudget fin("main (test)", 144, {txBudgetPayment}, finTxId);
104  const CFinalizedBudgetVote fvote(mnVin, fin.GetHash());
105  BOOST_CHECK(fin.AddOrUpdateVote(fvote, strError));
106  g_budgetman.ForceAddFinalizedBudget(fin.GetHash(), fin.GetFeeTXHash(), fin);
107 
108  // check superblock's block-value
109  nExpectedRet = nBlockReward;
110  nBudgetAmtRet = 0;
111  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, nBlockReward, nBudgetAmtRet));
112  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward + propAmt);
113  BOOST_CHECK_EQUAL(nBudgetAmtRet, propAmt);
114  nExpectedRet = nBlockReward;
115  nBudgetAmtRet = 0;
116  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, nBlockReward+propAmt-1, nBudgetAmtRet));
117  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward + propAmt);
118  BOOST_CHECK_EQUAL(nBudgetAmtRet, propAmt);
119  nExpectedRet = nBlockReward;
120  nBudgetAmtRet = 0;
121  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, nBlockReward+propAmt, nBudgetAmtRet));
122  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward + propAmt);
123  BOOST_CHECK_EQUAL(nBudgetAmtRet, propAmt);
124  nExpectedRet = nBlockReward;
125  nBudgetAmtRet = 0;
126  BOOST_CHECK(!IsBlockValueValid(nHeight, nExpectedRet, nBlockReward+propAmt+1, nBudgetAmtRet));
127  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward + propAmt);
128  BOOST_CHECK_EQUAL(nBudgetAmtRet, propAmt);
129 
130  // disable SPORK_13
131  const CSporkMessage& spork2 = CSporkMessage(SPORK_13_ENABLE_SUPERBLOCKS, 4070908800ULL, GetTime());
134 
135  // check with spork disabled
136  nExpectedRet = nBlockReward;
137  nBudgetAmtRet = 0;
138  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, nBlockReward, nBudgetAmtRet));
139  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward);
140  BOOST_CHECK_EQUAL(nBudgetAmtRet, 0);
141  BOOST_CHECK(!IsBlockValueValid(nHeight, nExpectedRet, nBlockReward+propAmt-1, nBudgetAmtRet));
142  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward);
143  BOOST_CHECK_EQUAL(nBudgetAmtRet, 0);
144  BOOST_CHECK(!IsBlockValueValid(nHeight, nExpectedRet, nBlockReward+propAmt, nBudgetAmtRet));
145  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward);
146  BOOST_CHECK_EQUAL(nBudgetAmtRet, 0);
147  BOOST_CHECK(!IsBlockValueValid(nHeight, nExpectedRet, nBlockReward+propAmt+1, nBudgetAmtRet));
148  BOOST_CHECK_EQUAL(nExpectedRet, nBlockReward);
149  BOOST_CHECK_EQUAL(nBudgetAmtRet, 0);
150 }
151 
153 {
154  int nHeight = 100;
155  CAmount nExpectedRet = GetBlockValue(nHeight);
156  CAmount nBudgetAmtRet = 0;
157  // under-minting blocks are invalid after v5.3
158  BOOST_CHECK(IsBlockValueValid(nHeight, nExpectedRet, -1, nBudgetAmtRet));
160  BOOST_CHECK(!IsBlockValueValid(nHeight, nExpectedRet, -1, nBudgetAmtRet));
161 }
162 
168 void forceAddFakeProposals(const CTxOut& payee1, const CTxOut& payee2)
169 {
170  const CTxIn mnVin(GetRandHash(), 0);
171  const uint256& propHash = GetRandHash(), finTxId = GetRandHash();
172  const CTxBudgetPayment txBudgetPayment(propHash, payee1.scriptPubKey, payee1.nValue);
173 
174  const CTxIn mnVin2(GetRandHash(), 0);
175  const uint256& propHash2 = GetRandHash(), finTxId2 = GetRandHash();
176  const CTxBudgetPayment txBudgetPayment2(propHash2, payee2.scriptPubKey, payee2.nValue);
177 
178  // Create first finalization
179  CFinalizedBudget fin("main (test)", 144, {txBudgetPayment, txBudgetPayment2}, finTxId);
180  const CFinalizedBudgetVote fvote(mnVin, fin.GetHash());
181  const CFinalizedBudgetVote fvote1_a({GetRandHash(), 0}, fin.GetHash());
182  const CFinalizedBudgetVote fvote1_b({GetRandHash(), 0}, fin.GetHash());
183  std::string strError;
184  BOOST_CHECK(fin.AddOrUpdateVote(fvote, strError));
185  BOOST_CHECK(fin.AddOrUpdateVote(fvote1_a, strError));
186  BOOST_CHECK(fin.AddOrUpdateVote(fvote1_b, strError));
187  g_budgetman.ForceAddFinalizedBudget(fin.GetHash(), fin.GetFeeTXHash(), fin);
188 
189  // Create second finalization
190  CFinalizedBudget fin2("main2 (test)", 144, {txBudgetPayment2, txBudgetPayment}, finTxId2);
191  const CFinalizedBudgetVote fvote2(mnVin2, fin2.GetHash());
192  const CFinalizedBudgetVote fvote2_a({GetRandHash(), 0}, fin2.GetHash());
193  BOOST_CHECK(fin2.AddOrUpdateVote(fvote2, strError));
194  BOOST_CHECK(fin2.AddOrUpdateVote(fvote2_a, strError));
195  g_budgetman.ForceAddFinalizedBudget(fin2.GetHash(), fin2.GetFeeTXHash(), fin2);
196 }
197 
198 BOOST_FIXTURE_TEST_CASE(budget_blocks_payee_test, TestChain100Setup)
199 {
200  // Regtest superblock is every 144 blocks.
201  for (int i=0; i<43; i++) CreateAndProcessBlock({}, coinbaseKey);
203  g_budgetman.Clear();
205  BOOST_ASSERT(g_budgetman.GetFinalizedBudgets().size() == 0);
206 
207  // Now we are at the superblock height, let's add a proposal to pay.
208  const CScript payee1 = GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))));
209  const CAmount propAmt1 = 100 * COIN;
210  const CScript payee2 = GetScriptForDestination(CKeyID(uint160(ParseHex("8d5b4f83212214d6ef693e02e6d71969fddad976"))));
211  const CAmount propAmt2 = propAmt1;
212  forceAddFakeProposals({propAmt1, payee1}, {propAmt2, payee2});
213 
214  CBlock block = CreateBlock({}, coinbaseKey);
215  // Check payee validity:
216  CTxOut payeeOut = block.vtx[0]->vout[1];
217  BOOST_CHECK_EQUAL(payeeOut.nValue, propAmt1);
218  BOOST_CHECK(payeeOut.scriptPubKey == payee1);
219 
220  // Good tx
221  CMutableTransaction goodMtx(*block.vtx[0]);
222 
223  // Modify payee
224  CMutableTransaction mtx(*block.vtx[0]);
225  mtx.vout[1].scriptPubKey = GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))));
226  block.vtx[0] = MakeTransactionRef(mtx);
227  std::shared_ptr<CBlock> pblock = FinalizeBlock(std::make_shared<CBlock>(block));
228  BOOST_CHECK(block.vtx[0]->vout[1].scriptPubKey != payee1);
229 
230  // Verify block rejection reason.
231  ProcessBlockAndCheckRejectionReason(pblock, "bad-cb-payee", 143);
232 
233  // Try to overmint, valid payee --> bad amount.
234  mtx = goodMtx; // reset
235  mtx.vout[1].nValue *= 2; // invalid amount
236  block.vtx[0] = MakeTransactionRef(mtx);
237  pblock = FinalizeBlock(std::make_shared<CBlock>(block));
238  BOOST_CHECK(block.vtx[0]->vout[1].scriptPubKey == payee1);
239  BOOST_CHECK(block.vtx[0]->vout[1].nValue == payeeOut.nValue * 2);
240  ProcessBlockAndCheckRejectionReason(pblock, "bad-blk-amount", 143);
241 
242  // Try to send less to a valid payee --> bad amount.
243  mtx = goodMtx; // reset
244  mtx.vout[1].nValue /= 2;
245  block.vtx[0] = MakeTransactionRef(mtx);
246  pblock = FinalizeBlock(std::make_shared<CBlock>(block));
247  BOOST_CHECK(block.vtx[0]->vout[1].scriptPubKey == payee1);
248  BOOST_CHECK(block.vtx[0]->vout[1].nValue == payeeOut.nValue / 2);
249  ProcessBlockAndCheckRejectionReason(pblock, "bad-cb-payee", 143);
250 
251  // Context, this has:
252  // 1) Two proposals and two budget finalizations with a different proposal payment order (read `forceAddFakeProposals()` description):
253  // BudA pays propA and propB, BudB pays propB and propA.
254  // 2) Voted both budgets, adding more votes to budA (so it becomes the most voted one).
255  // 3) Now: in the superblock, pay to budB order (the less voted finalization) --> which will fail.
256 
257  // Try to pay proposals in different order
258  mtx = goodMtx; // reset
259  std::vector<CFinalizedBudget*> vecFin = g_budgetman.GetFinalizedBudgets();
260  CFinalizedBudget* secondFin{nullptr};
261  for (auto fin : vecFin) {
262  if (!secondFin || fin->GetVoteCount() < secondFin->GetVoteCount()) {
263  secondFin = fin;
264  }
265  }
266  secondFin->GetPayeeAndAmount(144, mtx.vout[1].scriptPubKey, mtx.vout[1].nValue);
267  BOOST_CHECK(mtx.vout[1].scriptPubKey != goodMtx.vout[1].scriptPubKey);
268  BOOST_CHECK(mtx.vout[1].nValue == goodMtx.vout[1].nValue);
269  block.vtx[0] = MakeTransactionRef(mtx);
270  pblock = FinalizeBlock(std::make_shared<CBlock>(block));
271  ProcessBlockAndCheckRejectionReason(pblock, "bad-cb-payee", 143);
272 
273  // Now create the good block
274  block.vtx[0] = MakeTransactionRef(goodMtx);
275  pblock = FinalizeBlock(std::make_shared<CBlock>(block));
276  ProcessNewBlock(pblock, nullptr);
277  BOOST_CHECK_EQUAL(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash();), pblock->GetHash());
278 }
279 
280 BOOST_FIXTURE_TEST_CASE(budget_blocks_reorg_test, TestChain100Setup)
281 {
282  // Regtest superblock is every 144 blocks.
283  for (int i=0; i<43; i++) CreateAndProcessBlock({}, coinbaseKey);
286 
287  // Now we are at the superblock height, let's add a proposal to pay.
288  const CScript payee = GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))));
289  const CAmount propAmt = 100 * COIN;
290  const CScript payee2 = GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))));
291  const CAmount propAmt2 = propAmt * 2;
292  forceAddFakeProposals({propAmt, payee}, {propAmt2, payee2});
293 
294  // This will:
295  // 1) Create a proposal to be paid at block 144 (first superblock).
296  // 1) create blocksA and blockB at block 144 (paying for the proposal).
297  // 2) Process and connect blockA.
298  // 3) Create blockC on top of BlockA and blockD on top of blockB. At height 145.
299  // 4) Process and connect blockC.
300  // 5) Now force the reorg:
301  // a) Process blockB and blockD.
302  // b) Create and process blockE on top of blockD.
303  // 6) Verify that tip is at blockE.
304 
305  CScript forkCoinbaseScript = GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))));
306  CBlock blockA = CreateBlock({}, coinbaseKey, false);
307  CBlock blockB = CreateBlock({}, forkCoinbaseScript, false);
308  BOOST_CHECK(blockA.GetHash() != blockB.GetHash());
309  // Check blocks payee validity:
310  CTxOut payeeOut = blockA.vtx[0]->vout[1];
311  BOOST_CHECK_EQUAL(payeeOut.nValue, propAmt);
312  BOOST_CHECK(payeeOut.scriptPubKey == payee);
313  payeeOut = blockB.vtx[0]->vout[1];
314  BOOST_CHECK_EQUAL(payeeOut.nValue, propAmt);
315  BOOST_CHECK(payeeOut.scriptPubKey == payee);
316 
317  // Now let's process BlockA:
318  auto pblockA = std::make_shared<const CBlock>(blockA);
319  ProcessNewBlock(pblockA, nullptr);
320  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash()) == blockA.GetHash());
321 
322  // Now let's create blockC on top of BlockA, blockD on top of blockB
323  // and process blockC to expand the chain.
324  CBlock blockC = CreateBlock({}, coinbaseKey, false);
325  BOOST_CHECK(blockC.hashPrevBlock == blockA.GetHash());
326  CBlock blockD = CreateBlock({}, forkCoinbaseScript, false);
327 
328  // Process and connect blockC
329  ProcessNewBlock(std::make_shared<const CBlock>(blockC), nullptr);
330  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash()) == blockC.GetHash());
331 
332  // Now let's process the secondary chain
333  blockD.hashPrevBlock = blockB.GetHash();
334  std::shared_ptr<CBlock> pblockD = FinalizeBlock(std::make_shared<CBlock>(blockD));
335 
336  ProcessNewBlock(std::make_shared<const CBlock>(blockB), nullptr);
337  ProcessNewBlock(pblockD, nullptr);
338  CBlock blockE = CreateBlock({}, forkCoinbaseScript, false);
339  blockE.hashPrevBlock = pblockD->GetHash();
340  std::shared_ptr<CBlock> pblockE = FinalizeBlock(std::make_shared<CBlock>(blockE));
341  ProcessNewBlock(pblockE, nullptr);
342  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash()) == pblockE->GetHash());
343 }
344 
345 static CScript GetRandomP2PKH()
346 {
347  CKey key;
348  key.MakeNewKey(false);
349  return GetScriptForDestination(key.GetPubKey().GetID());
350 }
351 
352 static CMutableTransaction NewCoinBase(int nHeight, CAmount cbaseAmt, const CScript& cbaseScript)
353 {
355  tx.vout.emplace_back(cbaseAmt, cbaseScript);
356  tx.vin.emplace_back();
357  tx.vin[0].scriptSig = CScript() << nHeight << OP_0;
358  return tx;
359 }
360 
361 BOOST_FIXTURE_TEST_CASE(IsCoinbaseValueValid_test, TestingSetup)
362 {
363  int nHeight = 100;
364  const CAmount mnAmt = GetMasternodePayment(nHeight);
365  const CScript& cbaseScript = GetRandomP2PKH();
366  CValidationState state;
367 
368  // force mnsync complete
370 
371  // -- Regular blocks
372 
373  // Exact
374  CMutableTransaction cbase = NewCoinBase(1, mnAmt, cbaseScript);
375  BOOST_CHECK(IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
376  cbase.vout[0].nValue /= 2;
377  cbase.vout.emplace_back(cbase.vout[0]);
378  BOOST_CHECK(IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
379 
380  // Underpaying with SPORK_8 disabled (good)
381  cbase.vout.clear();
382  cbase.vout.emplace_back(mnAmt - 1, cbaseScript);
383  BOOST_CHECK(IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
384  cbase.vout[0].nValue = mnAmt/2;
385  cbase.vout.emplace_back(cbase.vout[0]);
386  cbase.vout[1].nValue = mnAmt/2 - 1;
387  BOOST_CHECK(IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
388 
389  // Overpaying with SPORK_8 disabled
390  cbase.vout.clear();
391  cbase.vout.emplace_back(mnAmt + 1, cbaseScript);
392  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
393  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-cb-amt-spork8-disabled");
394  state = CValidationState();
395  cbase.vout[0].nValue = mnAmt/2;
396  cbase.vout.emplace_back(cbase.vout[0]);
397  cbase.vout[1].nValue = mnAmt/2 + 1;
398  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
399  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-cb-amt-spork8-disabled");
400  state = CValidationState();
401 
402  // enable SPORK_8
403  int64_t nTime = GetTime() - 10;
407 
408  // Underpaying with SPORK_8 enabled
409  cbase.vout.clear();
410  cbase.vout.emplace_back(mnAmt - 1, cbaseScript);
411  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
412  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-cb-amt");
413  state = CValidationState();
414  cbase.vout[0].nValue = mnAmt/2;
415  cbase.vout.emplace_back(cbase.vout[0]);
416  cbase.vout[1].nValue = mnAmt/2 - 1;
417  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
418  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-cb-amt");
419  state = CValidationState();
420 
421  // Overpaying with SPORK_8 enabled
422  cbase.vout.clear();
423  cbase.vout.emplace_back(mnAmt + 1, cbaseScript);
424  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
425  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-cb-amt");
426  state = CValidationState();
427  cbase.vout[0].nValue = mnAmt/2;
428  cbase.vout.emplace_back(cbase.vout[0]);
429  cbase.vout[1].nValue = mnAmt/2 + 1;
430  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), 0, state));
431  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-cb-amt");
432  state = CValidationState();
433 
434  const CAmount budgAmt = 200 * COIN;
435 
436  // -- Superblocks
437 
438  // Exact
439  cbase.vout.clear();
440  cbase.vout.emplace_back(budgAmt, cbaseScript);
441  BOOST_CHECK(IsCoinbaseValueValid(MakeTransactionRef(cbase), budgAmt, state));
442  cbase.vout[0].nValue /= 2;
443  cbase.vout.emplace_back(cbase.vout[0]);
444  BOOST_CHECK(IsCoinbaseValueValid(MakeTransactionRef(cbase), budgAmt, state));
445 
446  // Underpaying
447  cbase.vout.clear();
448  cbase.vout.emplace_back(budgAmt - 1, cbaseScript);
449  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), budgAmt, state));
450  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-superblock-cb-amt");
451  state = CValidationState();
452  cbase.vout[0].nValue = budgAmt/2;
453  cbase.vout.emplace_back(cbase.vout[0]);
454  cbase.vout[1].nValue = budgAmt/2 - 1;
455  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), budgAmt, state));
456  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-superblock-cb-amt");
457  state = CValidationState();
458 
459  // Overpaying
460  cbase.vout.clear();
461  cbase.vout.emplace_back(budgAmt + 1, cbaseScript);
462  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), budgAmt, state));
463  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-superblock-cb-amt");
464  state = CValidationState();
465  cbase.vout[0].nValue = budgAmt/2;
466  cbase.vout.emplace_back(cbase.vout[0]);
467  cbase.vout[1].nValue = budgAmt/2 + 1;
468  BOOST_CHECK(!IsCoinbaseValueValid(MakeTransactionRef(cbase), budgAmt, state));
469  BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-superblock-cb-amt");
470 }
471 
472 BOOST_AUTO_TEST_CASE(fbv_signverify_bls)
473 {
474  CBLSSecretKey sk1, sk2;
475  sk1.MakeNewKey();
476  sk2.MakeNewKey();
477  BOOST_ASSERT(sk1 != sk2);
478 
479  CTxIn vin(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000002"), 0));
480  CTxIn vin2(COutPoint(uint256S("000000000000000000000000000000000000000000000000000000000000003"), 0));
481  CTxIn vin3(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000002"), 1));
482 
483  uint256 budgetHash1 = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
484  uint256 budgetHash2 = uint256S("0000000000000000000000000000000000010000000000000000000000000001");
485 
486  // Create serialized finalbudgetvote for budgetHash1, signed with sk1
487  CFinalizedBudgetVote vote(vin, budgetHash1);
488  BOOST_CHECK(vote.Sign(sk1));
489  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
490  ss << vote;
491 
492  // Verify received message on pk1
493  CFinalizedBudgetVote _vote;
494  ss >> _vote;
496 
497  // Failing verification on pk2
498  BOOST_CHECK(!_vote.CheckSignature(sk2.GetPublicKey()));
499 
500  std::vector<unsigned char> sig = _vote.GetVchSig();
501 
502  // Failing with different time
503  CFinalizedBudgetVote vote1(_vote);
504  vote1.SetTime(vote1.GetTime()+1);
505  BOOST_CHECK(!vote1.CheckSignature(sk1.GetPublicKey()));
506 
507  // Failing with different budget hash
508  CFinalizedBudgetVote vote2(vin, budgetHash2);
509  vote2.SetTime(_vote.GetTime());
510  vote2.SetVchSig(sig);
511  BOOST_CHECK(!vote2.CheckSignature(sk1.GetPublicKey()));
512 
513  // Failing with different vins: different txid (vin2) or voutn (vin3)
514  CFinalizedBudgetVote vote3_1(vin, budgetHash1);
515  CFinalizedBudgetVote vote3_2(vin2, budgetHash1);
516  CFinalizedBudgetVote vote3_3(vin3, budgetHash1);
517  vote3_1.SetTime(_vote.GetTime());
518  vote3_2.SetTime(_vote.GetTime());
519  vote3_3.SetTime(_vote.GetTime());
520  vote3_1.SetVchSig(sig);
521  vote3_2.SetVchSig(sig);
522  vote3_3.SetVchSig(sig);
523  BOOST_CHECK(vote3_1.CheckSignature(sk1.GetPublicKey())); // vote3_1 == _vote
524  BOOST_CHECK(!vote3_2.CheckSignature(sk1.GetPublicKey()));
525  BOOST_CHECK(!vote3_3.CheckSignature(sk1.GetPublicKey()));
526 }
527 
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
void ProcessBlockAndCheckRejectionReason(std::shared_ptr< CBlock > &pblock, const std::string &blockRejectionReason, int expectedChainHeight)
Definition: blocksutil.cpp:13
BOOST_FIXTURE_TEST_CASE(block_value, TestnetSetup)
BOOST_AUTO_TEST_CASE(masternode_value)
void forceAddFakeProposals(const CTxOut &payee1, const CTxOut &payee2)
1) Create two proposals and two budget finalizations with a different proposal payment order: BudA pa...
void enableMnSyncAndSuperblocksPayment()
void CheckBudgetValue(int nHeight, std::string strNetwork, CAmount nExpectedValue)
CBudgetManager g_budgetman
void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight)
Allows modifying the network upgrade regtest parameters.
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given chain name.
const CChainParams & Params()
Return the currently selected parameters.
void MakeNewKey()
Definition: bls_wrapper.cpp:54
CBLSPublicKey GetPublicKey() const
Definition: bls_wrapper.cpp:99
static const std::string REGTEST
static const std::string TESTNET
static const std::string MAIN
Chain name strings.
uint256 hashPrevBlock
Definition: block.h:28
uint256 GetHash() const
Definition: block.cpp:15
Definition: block.h:80
std::vector< CTransactionRef > vtx
Definition: block.h:83
uint256 GetBlockHash() const
Definition: chain.h:215
static CAmount GetTotalBudget(int nHeight)
std::vector< CFinalizedBudget * > GetFinalizedBudgets()
void ForceAddFinalizedBudget(const uint256 &nHash, const uint256 &feeTxId, const CFinalizedBudget &finalizedBudget)
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:405
int Height() const
Return the maximal height in the chain.
Definition: chain.h:450
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
bool GetPayeeAndAmount(int64_t nBlockHeight, CScript &payee, CAmount &nAmount) const
void SetTime(const int64_t &_nTime)
An encapsulated private key.
Definition: key.h:30
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:158
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:186
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:72
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:381
bool Sign(const CKey &key, const CKeyID &keyID)
CSignedMessage Class Functions inherited by network signed-messages.
bool CheckSignature(const CKeyID &keyID) const
std::vector< unsigned char > GetVchSig() const
Definition: messagesigner.h:88
void SetVchSig(const std::vector< unsigned char > &vchSigIn)
Definition: messagesigner.h:87
bool IsSporkActive(SporkId nSporkID)
Definition: spork.cpp:220
void AddOrUpdateSporkMessage(const CSporkMessage &spork, bool flush=false)
Definition: spork.cpp:206
An input of a transaction.
Definition: transaction.h:94
An output of a transaction.
Definition: transaction.h:137
CScript scriptPubKey
Definition: transaction.h:140
CAmount nValue
Definition: transaction.h:139
Capture information about block/transaction validation.
Definition: validation.h:24
std::string GetRejectReason() const
Definition: validation.h:94
void SetCurrentSyncPhase(int sync_phase)
160-bit opaque blob.
Definition: uint256.h:127
256-bit opaque blob.
Definition: uint256.h:138
BOOST_AUTO_TEST_SUITE(cuckoocache_tests)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
bool IsBlockValueValid(int nHeight, CAmount &nExpectedValue, CAmount nMinted, CAmount &nBudgetAmt)
bool IsCoinbaseValueValid(const CTransactionRef &tx, CAmount nBudgetAmt, CValidationState &_state)
Check coinbase output value for blocks after v6.0 enforcement.
UniValue spork(const JSONRPCRequest &request)
Definition: misc.cpp:286
@ UPGRADE_V5_3
Definition: params.h:38
@ UPGRADE_V5_5
Definition: params.h:39
@ UPGRADE_ZC_V2
Definition: params.h:31
Definition: uint256.h:212
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
uint256 GetRandHash() noexcept
Definition: random.cpp:596
@ OP_0
Definition: script.h:52
@ SER_NETWORK
Definition: serialize.h:174
CSporkManager sporkManager
Definition: spork.cpp:29
@ SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT
Definition: sporkid.h:19
@ SPORK_13_ENABLE_SUPERBLOCKS
Definition: sporkid.h:20
@ SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT
Definition: sporkid.h:18
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
Definition: standard.cpp:278
A mutable version of CTransaction.
Definition: transaction.h:409
std::vector< CTxOut > vout
Definition: transaction.h:411
std::vector< CTxIn > vin
Definition: transaction.h:410
static constexpr int ALWAYS_ACTIVE
Special value for nActivationHeight indicating that the upgrade is always active.
Definition: params.h:67
int nActivationHeight
Height of the first block for which the new consensus rules will be active.
Definition: params.h:56
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]
Definition: params.h:213
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
std::shared_ptr< CBlock > FinalizeBlock(std::shared_ptr< CBlock > pblock)
Definition: test_pivx.cpp:239
TierTwoSyncState g_tiertwo_sync_state
#define MASTERNODE_SYNC_FINISHED
#define strprintf
Definition: tinyformat.h:1056
uint256 uint256S(const char *str)
Definition: uint256.h:157
std::string FormatMoney(const CAmount &n, bool fPlus)
Money parsing/formatting utilities.
std::vector< unsigned char > ParseHex(const char *psz)
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: utiltime.cpp:27
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &pblock, const FlatFilePos *dbp)
Process an incoming block.
int64_t GetMasternodePayment(int nHeight)
Definition: validation.cpp:852
CAmount GetBlockValue(int nHeight)
Definition: validation.cpp:816
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84