LCOV - code coverage report
Current view: top level - src/test - miner_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 227 227 100.0 %
Date: 2025-02-23 09:33:43 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2014 The Bitcoin Core developers
       2             : // Copyright (c) 2016-2021 The PIVX Core developers
       3             : // Distributed under the MIT/X11 software license, see the accompanying
       4             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "wallet/test/wallet_test_fixture.h"
       7             : 
       8             : #include "blockassembler.h"
       9             : #include "checkpoints.h"
      10             : #include "consensus/merkle.h"
      11             : #include "miner.h"
      12             : #include "pubkey.h"
      13             : #include "uint256.h"
      14             : #include "util/blockstatecatcher.h"
      15             : #include "util/system.h"
      16             : #include "validation.h"
      17             : #include "wallet/wallet.h"
      18             : 
      19             : #include <boost/test/unit_test.hpp>
      20             : 
      21             : 
      22             : // future: this should be MAINNET.
      23             : BOOST_FIXTURE_TEST_SUITE(miner_tests, WalletRegTestingSetup)
      24             : 
      25             : static
      26             : struct {
      27             :     unsigned char extranonce;
      28             :     unsigned int nonce;
      29             : } blockinfo[] = {
      30             :     {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5},
      31             :     {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84},
      32             :     {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4},
      33             :     {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa},
      34             :     {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb},
      35             :     {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406},
      36             :     {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38},
      37             :     {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9},
      38             :     {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7},
      39             :     {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34},
      40             :     {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c},
      41             :     {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f},
      42             :     {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81},
      43             :     {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78},
      44             :     {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c},
      45             :     {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049},
      46             :     {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169},
      47             :     {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10},
      48             :     {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d},
      49             :     {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323},
      50             :     {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6},
      51             :     {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408},
      52             :     {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602},
      53             :     {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459},
      54             :     {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668},
      55             :     {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce},
      56             :     {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e},
      57             :     {2, 0xbbbeb305}, {2, 0xfe1c810a},
      58             : };
      59             : 
      60             : // Test suite for ancestor feerate transaction selection.
      61             : // Implemented as an additional function, rather than a separate test case,
      62             : // to allow reusing the blockchain created in CreateNewBlock_validity.
      63           1 : void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransactionRef>& txFirst)
      64             : {
      65             :     // Test the ancestor feerate transaction selection.
      66           1 :     TestMemPoolEntryHelper entry;
      67             : 
      68             :     // Test that a medium fee transaction will be selected after a higher fee
      69             :     // rate package with a low fee rate parent.
      70           2 :     CMutableTransaction tx;
      71           1 :     tx.vin.resize(1);
      72           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
      73           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
      74           1 :     tx.vin[0].prevout.n = 0;
      75           1 :     tx.vout.resize(1);
      76           1 :     tx.vout[0].nValue = 5000000000LL - 1000;
      77             :     // This tx has a low fee: 1000 satoshis
      78           1 :     uint256 hashParentTx = tx.GetHash(); // save this txid for later use
      79           1 :     mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
      80             : 
      81             :     // This tx has a medium fee: 10000 satoshis
      82           1 :     tx.vin[0].prevout.hash = txFirst[1]->GetHash();
      83           1 :     tx.vout[0].nValue = 5000000000LL - 10000;
      84           1 :     uint256 hashMediumFeeTx = tx.GetHash();
      85           1 :     mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
      86             : 
      87             :     // This tx has a high fee, but depends on the first transaction
      88           1 :     tx.vin[0].prevout.hash = hashParentTx;
      89           1 :     tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
      90           1 :     uint256 hashHighFeeTx = tx.GetHash();
      91           1 :     mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbaseOrCoinstake(false).FromTx(tx));
      92             : 
      93           2 :     std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams, DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey);
      94             : 
      95           2 :     BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
      96           2 :     BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
      97           2 :     BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
      98             : 
      99             :     // Test that a package below the min relay fee doesn't get included
     100           1 :     tx.vin[0].prevout.hash = hashHighFeeTx;
     101           1 :     tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
     102           1 :     uint256 hashFreeTx = tx.GetHash();
     103           1 :     mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx));
     104           1 :     size_t freeTxSize = ::GetSerializeSize(tx, PROTOCOL_VERSION);
     105             : 
     106             :     // Calculate a fee on child transaction that will put the package just
     107             :     // below the min relay fee (assuming 1 child tx of the same size).
     108           1 :     CAmount feeToUse = minRelayTxFee.GetFee(2*freeTxSize) - 1;
     109             : 
     110           1 :     tx.vin[0].prevout.hash = hashFreeTx;
     111           1 :     tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
     112           1 :     uint256 hashLowFeeTx = tx.GetHash();
     113           1 :     mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx));
     114           2 :     pblocktemplate = BlockAssembler(chainparams, DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey);
     115             :     // Verify that the free tx and the low fee tx didn't get selected
     116           5 :     for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
     117           8 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
     118           8 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx);
     119             :     }
     120             : 
     121             :     // Test that packages above the min relay fee do get included, even if one
     122             :     // of the transactions is below the min relay fee
     123             :     // Remove the low fee transaction and replace with a higher fee transaction
     124           1 :     mempool.removeRecursive(tx);
     125           1 :     tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
     126           1 :     hashLowFeeTx = tx.GetHash();
     127           1 :     mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx));
     128           2 :     pblocktemplate = BlockAssembler(chainparams, DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey);
     129           2 :     BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
     130           2 :     BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
     131             : 
     132             :     // Test that transaction selection properly updates ancestor fee
     133             :     // calculations as ancestor transactions get included in a block.
     134             :     // Add a 0-fee transaction that has 2 outputs.
     135           1 :     tx.vin[0].prevout.hash = txFirst[2]->GetHash();
     136           1 :     tx.vout.resize(2);
     137           1 :     tx.vout[0].nValue = 5000000000LL - 100000000;
     138           1 :     tx.vout[1].nValue = 100000000; // 1BTC output
     139           1 :     uint256 hashFreeTx2 = tx.GetHash();
     140           1 :     mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
     141             : 
     142             :     // This tx can't be mined by itself
     143           1 :     tx.vin[0].prevout.hash = hashFreeTx2;
     144           1 :     tx.vout.resize(1);
     145           1 :     feeToUse = minRelayTxFee.GetFee(freeTxSize);
     146           1 :     tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
     147           1 :     uint256 hashLowFeeTx2 = tx.GetHash();
     148           1 :     mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbaseOrCoinstake(false).FromTx(tx));
     149           2 :     pblocktemplate = BlockAssembler(chainparams, DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey);
     150             : 
     151             :     // Verify that this tx isn't selected.
     152           7 :     for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
     153          12 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx2);
     154          12 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx2);
     155             :     }
     156             : 
     157             :     // This tx will be mineable, and should cause hashLowFeeTx2 to be selected
     158             :     // as well.
     159           1 :     tx.vin[0].prevout.n = 1;
     160           1 :     tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
     161           1 :     mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx));
     162           2 :     pblocktemplate = BlockAssembler(chainparams, DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey);
     163           2 :     BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
     164           1 : }
     165             : 
     166             : // NOTE: These tests rely on CreateNewBlock doing its own self-validation!
     167           2 : BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
     168             : {
     169             :     // Note that by default, these tests run with size accounting enabled.
     170           1 :     const CChainParams& chainparams = Params();
     171           2 :     CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ParseHex("8d5b4f83212214d6ef693e02e6d71969fddad976") << OP_EQUALVERIFY << OP_CHECKSIG;
     172             : 
     173           1 :     std::unique_ptr<CBlockTemplate> pblocktemplate;
     174           2 :     CMutableTransaction tx,tx2;
     175           2 :     CScript script;
     176           1 :     uint256 hash;
     177           1 :     TestMemPoolEntryHelper entry;
     178           1 :     entry.nFee = 11;
     179           1 :     entry.nHeight = 11;
     180             : 
     181           1 :     Checkpoints::fEnabled = false;
     182             : 
     183             :     // Simple block creation, nothing special yet:
     184           4 :     BOOST_CHECK(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false));
     185             :     // Set genesis block
     186           1 :     pblocktemplate->block.hashPrevBlock = chainparams.GetConsensus().hashGenesisBlock;
     187             : 
     188             :     // We can't make transactions until we have inputs
     189             :     // Therefore, load 100 blocks :)
     190           2 :     std::vector<CTransactionRef>txFirst;
     191           2 :     std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block); // pointer for convenience
     192         111 :     for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) {
     193         330 :         CBlockIndex* pindexPrev = WITH_LOCK(cs_main, return chainActive.Tip());
     194         110 :         assert(pindexPrev);
     195         110 :         pblock->nTime = pindexPrev->GetMedianTimePast() + 60;
     196         110 :         pblock->vtx.clear(); // Update coinbase input height manually
     197         110 :         CreateCoinbaseTx(pblock.get(), CScript(), pindexPrev);
     198         110 :         if (txFirst.size() < 4)
     199           4 :             txFirst.emplace_back(pblock->vtx[0]);
     200         110 :         pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
     201         110 :         pblock->nNonce = blockinfo[i].nonce;
     202         220 :         BlockStateCatcherWrapper stateCatcher(pblock->GetHash());
     203         110 :         stateCatcher.registerEvent();
     204         330 :         BOOST_CHECK(ProcessNewBlock(pblock, nullptr));
     205         110 :         SyncWithValidationInterfaceQueue();
     206         220 :         BOOST_CHECK(stateCatcher.get().found && stateCatcher.get().state.IsValid());
     207         110 :         pblock->hashPrevBlock = pblock->GetHash();
     208             :     }
     209             : 
     210             :     // Just to make sure we can still make simple blocks
     211           4 :     BOOST_CHECK(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false));
     212             : 
     213             :     // block sigops > limit: 2000 CHECKMULTISIG + 1
     214           1 :     tx.vin.resize(1);
     215             :     // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
     216           1 :     tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1;
     217           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     218           1 :     tx.vin[0].prevout.n = 0;
     219           1 :     tx.vout.resize(1);
     220           1 :     tx.vout[0].nValue = 5000000000LL;
     221        2002 :     for (unsigned int i = 0; i < 2001; ++i) {
     222        2001 :         tx.vout[0].nValue -= 1000000;
     223        2001 :         hash = tx.GetHash();
     224        2001 :         bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase
     225             :         // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
     226        2001 :         mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbaseOrCoinstake(spendsCoinbase).FromTx(tx));
     227        2001 :         tx.vin[0].prevout.hash = hash;
     228             :     }
     229           4 :     BOOST_CHECK_EXCEPTION(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false), std::runtime_error, HasReason("bad-blk-sigops"));
     230           1 :     mempool.clear();
     231             : 
     232           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     233           1 :     tx.vout[0].nValue = 5000000000LL;
     234        1002 :     for (unsigned int i = 0; i < 1001; ++i) {
     235        1001 :         tx.vout[0].nValue -= 1000000;
     236        1001 :         hash = tx.GetHash();
     237        1001 :         bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase
     238             :         // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
     239        1001 :         mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbaseOrCoinstake(spendsCoinbase).SigOps(20).FromTx(tx));
     240        1001 :         tx.vin[0].prevout.hash = hash;
     241             :     }
     242           4 :     BOOST_CHECK(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false));
     243           1 :     mempool.clear();
     244             : 
     245             :     // block size > limit
     246           1 :     tx.vin[0].scriptSig = CScript();
     247             :     // 18 * (520char + DROP) + OP_1 = 9433 bytes
     248           2 :     std::vector<unsigned char> vchData(520);
     249          19 :     for (unsigned int i = 0; i < 18; ++i)
     250          18 :         tx.vin[0].scriptSig << vchData << OP_DROP;
     251           1 :     tx.vin[0].scriptSig << OP_1;
     252           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     253           1 :     tx.vin[0].prevout.n = 0;
     254           1 :     tx.vout[0].nValue = 5000000000LL;
     255         216 :     for (unsigned int i = 0; i < 215; ++i) {
     256         215 :         tx.vout[0].nValue -= 10000000;
     257         215 :         hash = tx.GetHash();
     258         215 :         bool spendsCoinbase = i == 0; // only first tx spends coinbase
     259         215 :         mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbaseOrCoinstake(spendsCoinbase).FromTx(tx));
     260         215 :         tx.vin[0].prevout.hash = hash;
     261             :     }
     262           4 :     BOOST_CHECK(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false));
     263           1 :     mempool.clear();
     264             : 
     265             :     // orphan in mempool, template creation fails
     266           1 :     hash = tx.GetHash();
     267           1 :     mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).FromTx(tx));
     268           6 :     BOOST_CHECK_EXCEPTION(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
     269           1 :     mempool.clear();
     270             : 
     271             :     // child with higher feerate than parent
     272           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     273           1 :     tx.vin[0].prevout.hash = txFirst[1]->GetHash();
     274           1 :     tx.vout[0].nValue = 4900000000LL;
     275           1 :     hash = tx.GetHash();
     276           1 :     mempool.addUnchecked(hash, entry.Fee(100000000LL).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
     277           1 :     tx.vin[0].prevout.hash = hash;
     278           1 :     tx.vin.resize(2);
     279           1 :     tx.vin[1].scriptSig = CScript() << OP_1;
     280           1 :     tx.vin[1].prevout.hash = txFirst[0]->GetHash();
     281           1 :     tx.vin[1].prevout.n = 0;
     282           1 :     tx.vout[0].nValue = 5900000000LL;
     283           1 :     hash = tx.GetHash();
     284           1 :     mempool.addUnchecked(hash, entry.Fee(400000000LL).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
     285           4 :     BOOST_CHECK(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false));
     286           1 :     mempool.clear();
     287             : 
     288             :     // coinbase in mempool, template creation fails
     289           1 :     tx.vin.resize(1);
     290           1 :     tx.vin[0].prevout.SetNull();
     291           1 :     tx.vin[0].scriptSig = CScript() << OP_0 << OP_1;
     292           1 :     tx.vout[0].nValue = 0;
     293           1 :     hash = tx.GetHash();
     294             :     // give it a fee so it'll get mined
     295           1 :     mempool.addUnchecked(hash, entry.Fee(100000).Time(GetTime()).SpendsCoinbaseOrCoinstake(false).FromTx(tx));
     296           4 :     BOOST_CHECK_EXCEPTION(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false), std::runtime_error, HasReason("bad-cb-multiple"));
     297           1 :     mempool.clear();
     298             : 
     299             :     // invalid (pre-p2sh) txn in mempool, template creation fails
     300           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     301           1 :     tx.vin[0].prevout.n = 0;
     302           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     303           1 :     tx.vout[0].nValue = 4900000000LL;
     304           1 :     script = CScript() << OP_0;
     305           1 :     tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script));
     306           1 :     hash = tx.GetHash();
     307           1 :     mempool.addUnchecked(hash, entry.Fee(10000000L).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
     308           1 :     tx.vin[0].prevout.hash = hash;
     309           3 :     tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
     310           1 :     tx.vout[0].nValue -= 1000000;
     311           1 :     hash = tx.GetHash();
     312           1 :     mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbaseOrCoinstake(false).FromTx(tx));
     313             :      // Should throw block-validation-failed
     314           6 :     BOOST_CHECK_EXCEPTION(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false), std::runtime_error, HasReason("block-validation-failed"));
     315           1 :     mempool.clear();
     316             : 
     317             :     // double spend txn pair in mempool, template creation fails
     318           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     319           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     320           1 :     tx.vout[0].nValue = 4900000000LL;
     321           1 :     tx.vout[0].scriptPubKey = CScript() << OP_1;
     322           1 :     hash = tx.GetHash();
     323           1 :     mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
     324           1 :     tx.vout[0].scriptPubKey = CScript() << OP_2;
     325           1 :     hash = tx.GetHash();
     326           1 :     mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
     327           6 :     BOOST_CHECK_EXCEPTION(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
     328           1 :     mempool.clear();
     329             : 
     330             :     // non-final txs in mempool
     331           4 :     SetMockTime(WITH_LOCK(cs_main, return chainActive.Tip()->GetMedianTimePast()+1));
     332             : 
     333             :     // height locked
     334           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     335           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     336           1 :     tx.vin[0].nSequence = 0;
     337           1 :     tx.vout[0].nValue = 4900000000LL;
     338           1 :     tx.vout[0].scriptPubKey = CScript() << OP_1;
     339           3 :     tx.nLockTime = WITH_LOCK(cs_main, return chainActive.Tip()->nHeight+1);
     340           1 :     hash = tx.GetHash();
     341           1 :     mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx));
     342           3 :     { LOCK(cs_main); BOOST_CHECK(!CheckFinalTx(MakeTransactionRef(tx), LOCKTIME_MEDIAN_TIME_PAST)); }
     343             : 
     344             :     // time locked
     345           1 :     tx2.vin.resize(1);
     346           1 :     tx2.vin[0].prevout.hash = txFirst[1]->GetHash();
     347           1 :     tx2.vin[0].prevout.n = 0;
     348           1 :     tx2.vin[0].scriptSig = CScript() << OP_1;
     349           1 :     tx2.vin[0].nSequence = 0;
     350           1 :     tx2.vout.resize(1);
     351           1 :     tx2.vout[0].nValue = 4900000000LL;
     352           1 :     tx2.vout[0].scriptPubKey = CScript() << OP_1;
     353           4 :     tx2.nLockTime = WITH_LOCK(cs_main, return chainActive.Tip()->GetMedianTimePast()+1);
     354           1 :     hash = tx2.GetHash();
     355           1 :     mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbaseOrCoinstake(true).FromTx(tx2));
     356           3 :     { LOCK(cs_main); BOOST_CHECK(!CheckFinalTx(MakeTransactionRef(tx2), LOCKTIME_MEDIAN_TIME_PAST)); }
     357             : 
     358           4 :     BOOST_CHECK(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false));
     359             : 
     360             :     // Neither tx should have make it into the template.
     361           1 :     BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1);
     362             : 
     363           1 :     {
     364           1 :         LOCK(cs_main);
     365             :         // However if we advance height and time by one, both will.
     366           1 :         chainActive.Tip()->nHeight++;
     367           2 :         SetMockTime(chainActive.Tip()->GetMedianTimePast() + 2);
     368             :     }
     369             : 
     370             :     // FIXME: we should *actually* create a new block so the following test
     371             :     //        works; CheckFinalTx() isn't fooled by monkey-patching nHeight.
     372             :     //BOOST_CHECK(CheckFinalTx(tx));
     373             :     //BOOST_CHECK(CheckFinalTx(tx2));
     374             : 
     375           4 :     BOOST_CHECK(pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey, &m_wallet, false));
     376           1 :     BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3);
     377             : 
     378           3 :     WITH_LOCK(cs_main, chainActive.Tip()->nHeight--);
     379           1 :     SetMockTime(0);
     380           1 :     mempool.clear();
     381             : 
     382           1 :     TestPackageSelection(chainparams, scriptPubKey, txFirst);
     383             : 
     384           1 :     Checkpoints::fEnabled = true;
     385           1 : }
     386             : 
     387             : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.14