PIVX Core  5.6.99
P2P Digital Currency
pos_validations_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020-2022 The PIVX Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or https://www.opensource.org/licenses/mit-license.php.
4 
6 
7 #include "blockassembler.h"
8 #include "coincontrol.h"
10 #include "blocksignature.h"
11 #include "consensus/merkle.h"
12 #include "primitives/block.h"
13 #include "script/sign.h"
14 #include "test/util/blocksutil.h"
15 #include "wallet/wallet.h"
16 
17 #include <boost/test/unit_test.hpp>
18 
19 BOOST_AUTO_TEST_SUITE(pos_validations_tests)
20 
22  const std::vector<CTxOut>& txPrevOutputs,
23  CWallet* wallet)
24 {
25  CTransaction txNewConst(mtx);
26  for (int index=0; index < (int) txPrevOutputs.size(); index++) {
27  const CTxOut& prevOut = txPrevOutputs.at(index);
28  SignatureData sigdata;
29  BOOST_ASSERT(ProduceSignature(
30  TransactionSignatureCreator(wallet, &txNewConst, index, prevOut.nValue, SIGHASH_ALL),
31  prevOut.scriptPubKey,
32  sigdata,
33  txNewConst.GetRequiredSigVersion(),
34  true));
35  UpdateTransaction(mtx, index, sigdata);
36  }
37 }
38 
40 {
41  // Verify that we are at block 251
44 
45  // Let's create the block
46  std::vector<CStakeableOutput> availableCoins;
47  BOOST_CHECK(pwalletMain->StakeableCoins(&availableCoins));
48  std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
49  Params(), false).CreateNewBlock(CScript(),
50  pwalletMain.get(),
51  true,
52  &availableCoins,
53  true);
54  std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
55  BOOST_CHECK(pblock->IsProofOfStake());
56 
57  // Add a second input to a coinstake
58  CMutableTransaction mtx(*pblock->vtx[1]);
59  const CStakeableOutput& in2 = availableCoins.back();
60  availableCoins.pop_back();
61  CTxIn vin2(in2.tx->GetHash(), in2.i);
62  mtx.vin.emplace_back(vin2);
63 
64  CTxOut prevOutput1 = pwalletMain->GetWalletTx(mtx.vin[0].prevout.hash)->tx->vout[mtx.vin[0].prevout.n];
65  std::vector<CTxOut> txPrevOutputs{prevOutput1, in2.tx->tx->vout[in2.i]};
66 
67  reSignTx(mtx, txPrevOutputs, pwalletMain.get());
68  pblock->vtx[1] = MakeTransactionRef(mtx);
69  pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
70  BOOST_CHECK(SignBlock(*pblock, *pwalletMain));
71  ProcessBlockAndCheckRejectionReason(pblock, "bad-cs-multi-inputs", 250);
72 
73  // Check multi-empty-outputs now
74  pblock = std::make_shared<CBlock>(pblocktemplate->block);
75  mtx = CMutableTransaction(*pblock->vtx[1]);
76  for (int i = 0; i < 999; ++i) {
77  mtx.vout.emplace_back();
78  mtx.vout.back().SetEmpty();
79  }
80  reSignTx(mtx, {prevOutput1}, pwalletMain.get());
81  pblock->vtx[1] = MakeTransactionRef(mtx);
82  pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
83  BOOST_CHECK(SignBlock(*pblock, *pwalletMain));
84  ProcessBlockAndCheckRejectionReason(pblock, "bad-txns-vout-empty", 250);
85 
86  // Now connect the proper block
87  pblock = std::make_shared<CBlock>(pblocktemplate->block);
88  ProcessNewBlock(pblock, nullptr);
89  BOOST_CHECK_EQUAL(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash()), pblock->GetHash());
90 }
91 
92 CTransaction CreateAndCommitTx(CWallet* pwalletMain, const CTxDestination& dest, CAmount destValue, CCoinControl* coinControl = nullptr)
93 {
94  CTransactionRef txNew;
95  CReserveKey reservekey(pwalletMain);
96  CAmount nFeeRet = 0;
97  std::string strFailReason;
98  // The minimum depth (100) required to spend coinbase outputs is calculated from the current chain tip.
99  // Since this transaction could be included in a fork block, at a lower height, this may result in
100  // selecting non-yet-available inputs, and thus creating non-connectable blocks due to premature-cb-spend.
101  // So, to be sure, only select inputs which are more than 120-blocks deep in the chain.
102  BOOST_ASSERT(pwalletMain->CreateTransaction(GetScriptForDestination(dest),
103  destValue,
104  txNew,
105  reservekey,
106  nFeeRet,
107  strFailReason,
108  coinControl,
109  true, /* sign*/
110  false, /*fIncludeDelegated*/
111  nullptr, /*fStakeDelegationVoided*/
112  0, /*nExtraSize*/
113  120 /*nMinDepth*/));
114  pwalletMain->CommitTransaction(txNew, reservekey, nullptr);
115  return *txNew;
116 }
117 
119 {
120  for (size_t i = 0; i < tx.vout.size(); i++) {
121  if (tx.vout[i].nValue == outpointValue) {
122  return COutPoint(tx.GetHash(), i);
123  }
124  }
125  BOOST_ASSERT_MSG(false, "error in test, no output in tx for value");
126  return {};
127 }
128 
129 static bool IsSpentOnFork(const COutput& coin, std::initializer_list<std::shared_ptr<CBlock>> forkchain = {})
130 {
131  for (const auto& block : forkchain) {
132  const auto& usedOutput = block->vtx[1]->vin.at(0).prevout;
133  if (coin.tx->GetHash() == usedOutput.hash && coin.i == (int)usedOutput.n) {
134  // spent on fork
135  return true;
136  }
137  }
138  return false;
139 }
140 
141 std::shared_ptr<CBlock> CreateBlockInternal(CWallet* pwalletMain, const std::vector<CMutableTransaction>& txns = {},
142  CBlockIndex* customPrevBlock = nullptr,
143  std::initializer_list<std::shared_ptr<CBlock>> forkchain = {})
144 {
145  std::vector<CStakeableOutput> availableCoins;
146  BOOST_CHECK(pwalletMain->StakeableCoins(&availableCoins));
147 
148  // Remove any utxo which is not deeper than 120 blocks (for the same reasoning
149  // used when selecting tx inputs in CreateAndCommitTx)
150  // Also, as the wallet is not prepared to follow several chains at the same time,
151  // need to manually remove from the stakeable utxo set every already used
152  // coinstake inputs on the previous blocks of the parallel chain so they
153  // are not used again.
154  for (auto it = availableCoins.begin(); it != availableCoins.end() ;) {
155  if (it->nDepth <= 120 || IsSpentOnFork(*it, forkchain)) {
156  it = availableCoins.erase(it);
157  } else {
158  it++;
159  }
160  }
161 
162  std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
163  Params(), false).CreateNewBlock(CScript(),
164  pwalletMain,
165  true,
166  &availableCoins,
167  true,
168  false,
169  customPrevBlock,
170  false);
171  BOOST_ASSERT(pblocktemplate);
172  auto pblock = std::make_shared<CBlock>(pblocktemplate->block);
173  if (!txns.empty()) {
174  for (const auto& tx : txns) {
175  pblock->vtx.emplace_back(MakeTransactionRef(tx));
176  }
177  pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
178  assert(SignBlock(*pblock, *pwalletMain));
179  }
180  return pblock;
181 }
182 
183 static COutput GetUnspentCoin(CWallet* pwallet, std::initializer_list<std::shared_ptr<CBlock>> forkchain = {})
184 {
185  std::vector<COutput> availableCoins;
186  CWallet::AvailableCoinsFilter coinsFilter;
187  coinsFilter.minDepth = 120;
188  BOOST_CHECK(pwallet->AvailableCoins(&availableCoins, nullptr, coinsFilter));
189  for (const auto& coin : availableCoins) {
190  if (!IsSpentOnFork(coin, forkchain)) {
191  return coin;
192  }
193  }
194  throw std::runtime_error("Unspent coin not found");
195 }
196 
198 {
199  // Let's create few more PoS blocks
200  for (int i=0; i<30; i++) {
201  std::shared_ptr<CBlock> pblock = CreateBlockInternal(pwalletMain.get());
202  BOOST_CHECK(ProcessNewBlock(pblock, nullptr));
203  }
204 
205  /*
206  Chains diagram:
207  A -- B -- C -- D -- E -- F -- G -- H -- I
208  \
209  -- D1 -- E1 -- F1
210  \
211  -- E2 -- F2
212  \
213  -- D3 -- E3 -- F3
214  \
215  -- F3_1 -- G3 -- H3 -- I3
216  */
217 
218  // Tests:
219  // 1) coins created in D1 and spent in E1. --> should pass
220  // 2) coins created in E, being spent in D4 --> should fail.
221  // 3) coins created and spent in E2, being double spent in F2. --> should fail
222  // 4) coins created in D and spent in E3. --> should fail
223  // 5) coins create in D, spent in F and then double spent in F3. --> should fail
224  // 6) coins created in G and G3, being spent in H and H3 --> should pass.
225  // 7) use coinstake on different chains --> should pass.
226 
227  // Let's create block C with a valid cTx
228  auto cTx = CreateAndCommitTx(pwalletMain.get(), *pwalletMain->getNewAddress("").getObjResult(), 249 * COIN);
229  const auto& cTx_out = GetOutpointWithAmount(cTx, 249 * COIN);
230  WITH_LOCK(pwalletMain->cs_wallet, pwalletMain->LockCoin(cTx_out));
231  std::shared_ptr<CBlock> pblockC = CreateBlockInternal(pwalletMain.get(), {cTx});
232  BOOST_CHECK(ProcessNewBlock(pblockC, nullptr));
233 
234  // Create block D with a valid dTx
235  auto dTx = CreateAndCommitTx(pwalletMain.get(), *pwalletMain->getNewAddress("").getObjResult(), 249 * COIN);
236  auto dTxOutPoint = GetOutpointWithAmount(dTx, 249 * COIN);
237  WITH_LOCK(pwalletMain->cs_wallet, pwalletMain->LockCoin(dTxOutPoint));
238  std::shared_ptr<CBlock> pblockD = CreateBlockInternal(pwalletMain.get(), {dTx});
239 
240  // Create D1 forked block that connects a new tx
241  auto dest = pwalletMain->getNewAddress("").getObjResult();
242  auto d1Tx = CreateAndCommitTx(pwalletMain.get(), *dest, 200 * COIN);
243  std::shared_ptr<CBlock> pblockD1 = CreateBlockInternal(pwalletMain.get(), {d1Tx});
244 
245  // Process blocks
246  ProcessNewBlock(pblockD, nullptr);
247  ProcessNewBlock(pblockD1, nullptr);
248  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash() == pblockD->GetHash()));
249 
250  // Ensure that the coin does not exist in the main chain
251  const Coin& utxo = pcoinsTip->AccessCoin(COutPoint(d1Tx.GetHash(), 0));
252  BOOST_CHECK(utxo.out.IsNull());
253 
254  // Create valid block E
255  auto eTx = CreateAndCommitTx(pwalletMain.get(), *dest, 200 * COIN);
256  std::shared_ptr<CBlock> pblockE = CreateBlockInternal(pwalletMain.get(), {eTx});
257  BOOST_CHECK(ProcessNewBlock(pblockE, nullptr));
258 
259  // #################################################
260  // ### 1) -> coins created in D' and spent in E' ###
261  // #################################################
262 
263  // Create tx spending the previously created tx on the forked chain
264  CCoinControl coinControl;
265  coinControl.fAllowOtherInputs = false;
266  coinControl.Select(COutPoint(d1Tx.GetHash(), 0), d1Tx.vout[0].nValue);
267  auto e1Tx = CreateAndCommitTx(pwalletMain.get(), *dest, d1Tx.vout[0].nValue - 0.1 * COIN, &coinControl);
268 
269  CBlockIndex* pindexPrev = mapBlockIndex.at(pblockD1->GetHash());
270  std::shared_ptr<CBlock> pblockE1 = CreateBlockInternal(pwalletMain.get(), {e1Tx}, pindexPrev, {pblockD1});
271  BOOST_CHECK(ProcessNewBlock(pblockE1, nullptr));
272 
273  // #################################################################
274  // ### 2) coins created in E, being spent in D4 --> should fail. ###
275  // #################################################################
276 
277  coinControl.UnSelectAll();
278  coinControl.Select(GetOutpointWithAmount(eTx, 200 * COIN), 200 * COIN);
279  coinControl.fAllowOtherInputs = false;
280  auto D4_tx1 = CreateAndCommitTx(pwalletMain.get(), *dest, 199 * COIN, &coinControl);
281  std::shared_ptr<CBlock> pblockD4 = CreateBlockInternal(pwalletMain.get(), {D4_tx1}, mapBlockIndex.at(pblockC->GetHash()));
282  BOOST_CHECK(!ProcessNewBlock(pblockD4, nullptr));
283 
284  // #####################################################################
285  // ### 3) -> coins created and spent in E2, being double spent in F2 ###
286  // #####################################################################
287 
288  // Create block E2 with E2_tx1 and E2_tx2. Where E2_tx2 is spending the outputs of E2_tx1
289  CCoinControl coinControlE2;
290  coinControlE2.Select(cTx_out, 249 * COIN);
291  auto E2_tx1 = CreateAndCommitTx(pwalletMain.get(), *dest, 200 * COIN, &coinControlE2);
292 
293  coinControl.UnSelectAll();
294  coinControl.Select(GetOutpointWithAmount(E2_tx1, 200 * COIN), 200 * COIN);
295  coinControl.fAllowOtherInputs = false;
296  auto E2_tx2 = CreateAndCommitTx(pwalletMain.get(), *dest, 199 * COIN, &coinControl);
297 
298  std::shared_ptr<CBlock> pblockE2 = CreateBlockInternal(pwalletMain.get(), {E2_tx1, E2_tx2},
299  pindexPrev, {pblockD1});
300  BOOST_CHECK(ProcessNewBlock(pblockE2, nullptr));
301 
302  // Create block with F2_tx1 spending E2_tx1 again.
303  auto F2_tx1 = CreateAndCommitTx(pwalletMain.get(), *dest, 199 * COIN, &coinControl);
304 
305  pindexPrev = mapBlockIndex.at(pblockE2->GetHash());
306  std::shared_ptr<CBlock> pblock5Forked = CreateBlockInternal(pwalletMain.get(), {F2_tx1},
307  pindexPrev, {pblockD1, pblockE2});
308  BlockStateCatcherWrapper stateCatcher(pblock5Forked->GetHash());
309  stateCatcher.registerEvent();
310  BOOST_CHECK(!ProcessNewBlock(pblock5Forked, nullptr));
311  BOOST_CHECK(stateCatcher.get().found);
312  BOOST_CHECK(!stateCatcher.get().state.IsValid());
313  BOOST_CHECK_EQUAL(stateCatcher.get().state.GetRejectReason(), "bad-txns-inputs-spent-fork-post-split");
314 
315  // #############################################
316  // ### 4) coins created in D and spent in E3 ###
317  // #############################################
318 
319  // First create D3
320  pindexPrev = mapBlockIndex.at(pblockC->GetHash());
321  std::shared_ptr<CBlock> pblockD3 = CreateBlockInternal(pwalletMain.get(), {}, pindexPrev);
322  BOOST_CHECK(ProcessNewBlock(pblockD3, nullptr));
323 
324  // Now let's try to spend the coins created in D in E3
325  coinControl.UnSelectAll();
326  coinControl.Select(dTxOutPoint, 249 * COIN);
327  coinControl.fAllowOtherInputs = false;
328  auto E3_tx1 = CreateAndCommitTx(pwalletMain.get(), *dest, 200 * COIN, &coinControl);
329 
330  pindexPrev = mapBlockIndex.at(pblockD3->GetHash());
331  std::shared_ptr<CBlock> pblockE3 = CreateBlockInternal(pwalletMain.get(), {E3_tx1}, pindexPrev, {pblockD3});
332  stateCatcher.get().clear();
333  stateCatcher.get().setBlockHash(pblockE3->GetHash());
334  BOOST_CHECK(!ProcessNewBlock(pblockE3, nullptr));
335  BOOST_CHECK(stateCatcher.get().found);
336  BOOST_CHECK(!stateCatcher.get().state.IsValid());
337  BOOST_CHECK_EQUAL(stateCatcher.get().state.GetRejectReason(), "bad-txns-inputs-created-post-split");
338 
339  // ####################################################################
340  // ### 5) coins create in D, spent in F and then double spent in F3 ###
341  // ####################################################################
342 
343  // Create valid block F spending the coins created in D
344  const auto& F_tx1 = E3_tx1;
345  std::shared_ptr<CBlock> pblockF = CreateBlockInternal(pwalletMain.get(), {F_tx1});
346  BOOST_CHECK(ProcessNewBlock(pblockF, nullptr));
347  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash() == pblockF->GetHash()));
348 
349  // Create valid block E3
350  pindexPrev = mapBlockIndex.at(pblockD3->GetHash());
351  pblockE3 = CreateBlockInternal(pwalletMain.get(), {}, pindexPrev, {pblockD3});
352  BOOST_CHECK(ProcessNewBlock(pblockE3, nullptr));
353 
354  // Now double spend F_tx1 in F3
355  pindexPrev = mapBlockIndex.at(pblockE3->GetHash());
356  std::shared_ptr<CBlock> pblockF3 = CreateBlockInternal(pwalletMain.get(), {F_tx1}, pindexPrev, {pblockD3, pblockE3});
357  // Accepted on disk but not connected.
358  BOOST_CHECK(ProcessNewBlock(pblockF3, nullptr));
359  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash();) != pblockF3->GetHash());
360 
361  {
362  // Trigger a rescan so the wallet cleans up its internal state.
363  WalletRescanReserver reserver(pwalletMain.get());
364  BOOST_CHECK(reserver.reserve());
365  pwalletMain->RescanFromTime(0, reserver, true /* update */);
366  }
367 
368  // ##############################################################################
369  // ### 6) coins created in G and G3, being spent in H and H3 --> should pass. ###
370  // ##############################################################################
371 
372  // First create new coins in G
373  // select an input that is not already spent in D3 or E3 (since we want to spend it also in G3)
374  const COutput& input = GetUnspentCoin(pwalletMain.get(), {pblockD3, pblockE3});
375 
376  coinControl.UnSelectAll();
377  coinControl.Select(COutPoint(input.tx->GetHash(), input.i), input.Value());
378  coinControl.fAllowOtherInputs = false;
379 
380  dest = pwalletMain->getNewAddress("").getObjResult();
381  auto gTx = CreateAndCommitTx(pwalletMain.get(), *dest, 200 * COIN, &coinControl);
382  auto gOut = GetOutpointWithAmount(gTx, 200 * COIN);
383  std::shared_ptr<CBlock> pblockG = CreateBlockInternal(pwalletMain.get(), {gTx});
384  BOOST_CHECK(ProcessNewBlock(pblockG, nullptr));
385 
386  // Now create the same coin in G3
387  pblockF3 = CreateBlockInternal(pwalletMain.get(), {}, mapBlockIndex.at(pblockE3->GetHash()), {pblockD3, pblockE3});
388  BOOST_CHECK(ProcessNewBlock(pblockF3, nullptr));
389  auto pblockG3 = CreateBlockInternal(pwalletMain.get(), {gTx}, mapBlockIndex.at(pblockF3->GetHash()), {pblockD3, pblockE3, pblockF3});
390  BOOST_CHECK(ProcessNewBlock(pblockG3, nullptr));
392 
393  // Now spend the coin in both, H and H3
394  coinControl.UnSelectAll();
395  coinControl.Select(gOut, 200 * COIN);
396  coinControl.fAllowOtherInputs = false;
397  auto hTx = CreateAndCommitTx(pwalletMain.get(), *dest, 199 * COIN, &coinControl);
398  std::shared_ptr<CBlock> pblockH = CreateBlockInternal(pwalletMain.get(), {hTx});
399  BOOST_CHECK(ProcessNewBlock(pblockH, nullptr));
400  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash() == pblockH->GetHash()));
402 
403  // H3 now..
404  std::shared_ptr<CBlock> pblockH3 = CreateBlockInternal(pwalletMain.get(),
405  {hTx},
406  mapBlockIndex.at(pblockG3->GetHash()),
407  {pblockD3, pblockE3, pblockF3, pblockG3});
408  BOOST_CHECK(ProcessNewBlock(pblockH3, nullptr));
409 
410  // Try to read the forking point manually
411  CBlock bl;
412  BOOST_CHECK(ReadBlockFromDisk(bl, mapBlockIndex.at(pblockC->GetHash())));
413 
414  // Make I3 the tip now.
415  std::shared_ptr<CBlock> pblockI3 = CreateBlockInternal(pwalletMain.get(),
416  {},
417  mapBlockIndex.at(pblockH3->GetHash()),
418  {pblockD3, pblockE3, pblockF3, pblockG3, pblockH3});
419  BOOST_CHECK(ProcessNewBlock(pblockI3, nullptr));
420  BOOST_CHECK(WITH_LOCK(cs_main, return chainActive.Tip()->GetBlockHash() == pblockI3->GetHash()));
421 
422  // And rescan the wallet on top of the new chain
423  WalletRescanReserver reserver(pwalletMain.get());
424  BOOST_CHECK(reserver.reserve());
425  pwalletMain->RescanFromTime(0, reserver, true /* update */);
426 
427  // #################################################################################
428  // ### 7) Now try to use the same coinstake on different chains --> should pass. ###
429  // #################################################################################
430 
431  // Take I3 coinstake and use it for block I, changing its hash adding a new tx
432  std::shared_ptr<CBlock> pblockI = std::make_shared<CBlock>(*pblockI3);
433  auto iTx = CreateAndCommitTx(pwalletMain.get(), *dest, 1 * COIN);
434  pblockI->vtx.emplace_back(MakeTransactionRef(iTx));
435  pblockI->hashMerkleRoot = BlockMerkleRoot(*pblockI);
436  assert(SignBlock(*pblockI, *pwalletMain));
437  BOOST_CHECK(pblockI3->GetHash() != pblockI->GetHash());
438  BOOST_CHECK(ProcessNewBlock(pblockI, nullptr));
439 }
440 
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
bool SignBlock(CBlock &block, const CKeyStore &keystore)
void ProcessBlockAndCheckRejectionReason(std::shared_ptr< CBlock > &pblock, const std::string &blockRejectionReason, int expectedChainHeight)
Definition: blocksutil.cpp:13
const CChainParams & Params()
Return the currently selected parameters.
Generate a new block.
std::unique_ptr< CBlockTemplate > CreateNewBlock(const CScript &scriptPubKeyIn, CWallet *pwallet=nullptr, bool fProofOfStake=false, std::vector< CStakeableOutput > *availableCoins=nullptr, bool fNoMempoolTx=false, bool fTestValidity=true, CBlockIndex *prevBlock=nullptr, bool stopPoSOnNewBlock=true, bool fIncludeQfc=true)
Construct a new block template with coinbase to scriptPubKeyIn.
void setBlockHash(const uint256 &_hash)
CValidationState state
BlockStateCatcher & get() const
Definition: block.h:80
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
uint256 GetBlockHash() const
Definition: chain.h:215
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:405
Coin Control Features.
Definition: coincontrol.h:34
void Select(const BaseOutPoint &output, CAmount value=0, bool isP2CS=false)
Definition: coincontrol.h:76
void UnSelectAll()
Definition: coincontrol.h:86
bool fAllowOtherInputs
If false, allows unselected inputs, but requires all selected inputs be used.
Definition: coincontrol.h:40
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:72
CAmount Value() const
Definition: wallet.h:1308
const CWalletTx * tx
Definition: wallet.h:1287
int i
Definition: wallet.h:1288
A key allocated from the key pool.
Definition: wallet.h:1256
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:381
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:244
SigVersion GetRequiredSigVersion() const
Definition: transaction.h:347
const uint256 & GetHash() const
Definition: transaction.h:301
std::vector< CTxOut > vout
Definition: transaction.h:271
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
bool IsNull() const
Definition: transaction.h:159
bool IsValid() const
Definition: validation.h:69
std::string GetRejectReason() const
Definition: validation.h:94
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
RecursiveMutex cs_wallet
Definition: wallet.h:720
CTransactionRef tx
Definition: wallet.h:364
const uint256 & GetHash() const
Definition: wallet.h:561
A UTXO entry.
Definition: coins.h:32
CTxOut out
unspent transaction output
Definition: coins.h:41
A signature creator for transactions.
Definition: sign.h:73
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1324
BOOST_AUTO_TEST_SUITE(cuckoocache_tests)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
CWallet::CommitResult CommitTransaction(CTransactionRef tx, CReserveKey &opReservekey, CConnman *connman)
Definition: wallet.cpp:3510
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CTransactionRef &txRet, CReserveKey &reservekey, CAmount &nFeeRet, int &nChangePosInOut, std::string &strFailReason, const CCoinControl *coinControl=nullptr, bool sign=true, CAmount nFeePay=0, bool fIncludeDelegated=false, bool *fStakeDelegationVoided=nullptr, int nExtraSize=0, int nMinDepth=0)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: wallet.cpp:3040
bool AvailableCoins(std::vector< COutput > *pCoins, const CCoinControl *coinControl=nullptr, AvailableCoinsFilter coinsFilter=AvailableCoinsFilter()) const
populate vCoins with vector of available COutputs.
Definition: wallet.cpp:2555
void LockCoin(const COutPoint &output)
Definition: wallet.cpp:3948
bool StakeableCoins(std::vector< CStakeableOutput > *pCoins=nullptr)
Available coins (staking)
Definition: wallet.cpp:2709
CallResult< CTxDestination > getNewAddress(const std::string &addressLabel, const std::string purpose, const CChainParams::Base58Type addrType=CChainParams::PUBKEY_ADDRESS)
Definition: wallet.cpp:196
const CWalletTx * GetWalletTx(const uint256 &hash) const
Definition: wallet.cpp:166
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Definition: wallet.cpp:1859
@ SIGHASH_ALL
Definition: interpreter.h:24
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:154
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
CTransaction CreateAndCommitTx(CWallet *pwalletMain, const CTxDestination &dest, CAmount destValue, CCoinControl *coinControl=nullptr)
void reSignTx(CMutableTransaction &mtx, const std::vector< CTxOut > &txPrevOutputs, CWallet *wallet)
COutPoint GetOutpointWithAmount(const CTransaction &tx, CAmount outpointValue)
BOOST_FIXTURE_TEST_CASE(coinstake_tests, TestPoSChainSetup)
std::shared_ptr< CBlock > CreateBlockInternal(CWallet *pwalletMain, const std::vector< CMutableTransaction > &txns={}, CBlockIndex *customPrevBlock=nullptr, std::initializer_list< std::shared_ptr< CBlock >> forkchain={})
void UpdateTransaction(CMutableTransaction &tx, unsigned int nIn, const SignatureData &data)
Definition: sign.cpp:186
bool ProduceSignature(const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata, SigVersion sigversion, bool fColdStake, ScriptError *serror)
Produce a script signature using a generic signature creator.
Definition: sign.cpp:153
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
Definition: standard.cpp:278
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
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
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:456
void FlushStateToDisk()
Flush all state, indexes and buffers to disk.
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &pblock, const FlatFilePos *dbp)
Process an incoming block.
std::unique_ptr< CCoinsViewCache > pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: validation.cpp:206
BlockMap mapBlockIndex
Definition: validation.cpp:82
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos)
Definition: validation.cpp:758
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...