LCOV - code coverage report
Current view: top level - src/test - miner_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 322 328 98.2 %
Date: 2020-09-26 01:30:44 Functions: 22 22 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2019 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <chainparams.h>
       6             : #include <coins.h>
       7             : #include <consensus/consensus.h>
       8             : #include <consensus/merkle.h>
       9             : #include <consensus/tx_verify.h>
      10             : #include <miner.h>
      11             : #include <policy/policy.h>
      12             : #include <script/standard.h>
      13             : #include <txmempool.h>
      14             : #include <uint256.h>
      15             : #include <util/strencodings.h>
      16             : #include <util/system.h>
      17             : #include <util/time.h>
      18             : #include <validation.h>
      19             : 
      20             : #include <test/util/setup_common.h>
      21             : 
      22             : #include <memory>
      23             : 
      24             : #include <boost/test/unit_test.hpp>
      25             : 
      26             : namespace miner_tests {
      27           2 : struct MinerTestingSetup : public TestingSetup {
      28             :     void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
      29           8 :     bool TestSequenceLocks(const CTransaction& tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs)
      30             :     {
      31           8 :         return CheckSequenceLocks(*m_node.mempool, tx, flags);
      32             :     }
      33             :     BlockAssembler AssemblerForTest(const CChainParams& params);
      34             : };
      35             : } // namespace miner_tests
      36             : 
      37          89 : BOOST_FIXTURE_TEST_SUITE(miner_tests, MinerTestingSetup)
      38             : 
      39             : // BOOST_CHECK_EXCEPTION predicates to check the specific validation error
      40          10 : class HasReason {
      41             : public:
      42          10 :     explicit HasReason(const std::string& reason) : m_reason(reason) {}
      43           5 :     bool operator() (const std::runtime_error& e) const {
      44           5 :         return std::string(e.what()).find(m_reason) != std::string::npos;
      45             :     };
      46             : private:
      47             :     const std::string m_reason;
      48             : };
      49             : 
      50          89 : static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
      51             : 
      52          19 : BlockAssembler MinerTestingSetup::AssemblerForTest(const CChainParams& params)
      53             : {
      54          19 :     BlockAssembler::Options options;
      55             : 
      56          19 :     options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
      57          19 :     options.blockMinFeeRate = blockMinFeeRate;
      58          19 :     return BlockAssembler(*m_node.mempool, params, options);
      59          19 : }
      60             : 
      61             : constexpr static struct {
      62             :     unsigned char extranonce;
      63             :     unsigned int nonce;
      64             : } blockinfo[] = {
      65             :     {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5},
      66             :     {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84},
      67             :     {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4},
      68             :     {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa},
      69             :     {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb},
      70             :     {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406},
      71             :     {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38},
      72             :     {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9},
      73             :     {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7},
      74             :     {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34},
      75             :     {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c},
      76             :     {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f},
      77             :     {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81},
      78             :     {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78},
      79             :     {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c},
      80             :     {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049},
      81             :     {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169},
      82             :     {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10},
      83             :     {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d},
      84             :     {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323},
      85             :     {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6},
      86             :     {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408},
      87             :     {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602},
      88             :     {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459},
      89             :     {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668},
      90             :     {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce},
      91             :     {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e},
      92             :     {2, 0xbbbeb305}, {2, 0xfe1c810a},
      93             : };
      94             : 
      95           2 : static CBlockIndex CreateBlockIndex(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
      96             : {
      97           2 :     CBlockIndex index;
      98           2 :     index.nHeight = nHeight;
      99           2 :     index.pprev = ::ChainActive().Tip();
     100           2 :     return index;
     101             : }
     102             : 
     103             : // Test suite for ancestor feerate transaction selection.
     104             : // Implemented as an additional function, rather than a separate test case,
     105             : // to allow reusing the blockchain created in CreateNewBlock_validity.
     106           1 : void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
     107             : {
     108             :     // Test the ancestor feerate transaction selection.
     109           1 :     TestMemPoolEntryHelper entry;
     110             : 
     111             :     // Test that a medium fee transaction will be selected after a higher fee
     112             :     // rate package with a low fee rate parent.
     113           1 :     CMutableTransaction tx;
     114           1 :     tx.vin.resize(1);
     115           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     116           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     117           1 :     tx.vin[0].prevout.n = 0;
     118           1 :     tx.vout.resize(1);
     119           1 :     tx.vout[0].nValue = 5000000000LL - 1000;
     120             :     // This tx has a low fee: 1000 satoshis
     121           1 :     uint256 hashParentTx = tx.GetHash(); // save this txid for later use
     122           1 :     m_node.mempool->addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     123             : 
     124             :     // This tx has a medium fee: 10000 satoshis
     125           1 :     tx.vin[0].prevout.hash = txFirst[1]->GetHash();
     126           1 :     tx.vout[0].nValue = 5000000000LL - 10000;
     127           1 :     uint256 hashMediumFeeTx = tx.GetHash();
     128           1 :     m_node.mempool->addUnchecked(entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     129             : 
     130             :     // This tx has a high fee, but depends on the first transaction
     131           1 :     tx.vin[0].prevout.hash = hashParentTx;
     132           1 :     tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
     133           1 :     uint256 hashHighFeeTx = tx.GetHash();
     134           1 :     m_node.mempool->addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
     135             : 
     136           1 :     std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
     137           1 :     BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
     138           1 :     BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
     139           1 :     BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
     140             : 
     141             :     // Test that a package below the block min tx fee doesn't get included
     142           1 :     tx.vin[0].prevout.hash = hashHighFeeTx;
     143           1 :     tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
     144           1 :     uint256 hashFreeTx = tx.GetHash();
     145           1 :     m_node.mempool->addUnchecked(entry.Fee(0).FromTx(tx));
     146           1 :     size_t freeTxSize = ::GetSerializeSize(tx, PROTOCOL_VERSION);
     147             : 
     148             :     // Calculate a fee on child transaction that will put the package just
     149             :     // below the block min tx fee (assuming 1 child tx of the same size).
     150           1 :     CAmount feeToUse = blockMinFeeRate.GetFee(2*freeTxSize) - 1;
     151             : 
     152           1 :     tx.vin[0].prevout.hash = hashFreeTx;
     153           1 :     tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
     154           1 :     uint256 hashLowFeeTx = tx.GetHash();
     155           1 :     m_node.mempool->addUnchecked(entry.Fee(feeToUse).FromTx(tx));
     156           1 :     pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
     157             :     // Verify that the free tx and the low fee tx didn't get selected
     158           5 :     for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
     159           4 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
     160           4 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx);
     161             :     }
     162             : 
     163             :     // Test that packages above the min relay fee do get included, even if one
     164             :     // of the transactions is below the min relay fee
     165             :     // Remove the low fee transaction and replace with a higher fee transaction
     166           1 :     m_node.mempool->removeRecursive(CTransaction(tx), MemPoolRemovalReason::REPLACED);
     167           1 :     tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
     168           1 :     hashLowFeeTx = tx.GetHash();
     169           1 :     m_node.mempool->addUnchecked(entry.Fee(feeToUse+2).FromTx(tx));
     170           1 :     pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
     171           1 :     BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
     172           1 :     BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
     173             : 
     174             :     // Test that transaction selection properly updates ancestor fee
     175             :     // calculations as ancestor transactions get included in a block.
     176             :     // Add a 0-fee transaction that has 2 outputs.
     177           1 :     tx.vin[0].prevout.hash = txFirst[2]->GetHash();
     178           1 :     tx.vout.resize(2);
     179           1 :     tx.vout[0].nValue = 5000000000LL - 100000000;
     180           1 :     tx.vout[1].nValue = 100000000; // 1BTC output
     181           1 :     uint256 hashFreeTx2 = tx.GetHash();
     182           1 :     m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
     183             : 
     184             :     // This tx can't be mined by itself
     185           1 :     tx.vin[0].prevout.hash = hashFreeTx2;
     186           1 :     tx.vout.resize(1);
     187           1 :     feeToUse = blockMinFeeRate.GetFee(freeTxSize);
     188           1 :     tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
     189           1 :     uint256 hashLowFeeTx2 = tx.GetHash();
     190           1 :     m_node.mempool->addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
     191           1 :     pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
     192             : 
     193             :     // Verify that this tx isn't selected.
     194           7 :     for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
     195           6 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx2);
     196           6 :         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx2);
     197             :     }
     198             : 
     199             :     // This tx will be mineable, and should cause hashLowFeeTx2 to be selected
     200             :     // as well.
     201           1 :     tx.vin[0].prevout.n = 1;
     202           1 :     tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
     203           1 :     m_node.mempool->addUnchecked(entry.Fee(10000).FromTx(tx));
     204           1 :     pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
     205           1 :     BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
     206           1 : }
     207             : 
     208             : // NOTE: These tests rely on CreateNewBlock doing its own self-validation!
     209          95 : BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
     210             : {
     211             :     // Note that by default, these tests run with size accounting enabled.
     212           1 :     const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
     213           1 :     const CChainParams& chainparams = *chainParams;
     214           1 :     CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
     215           1 :     std::unique_ptr<CBlockTemplate> pblocktemplate;
     216           1 :     CMutableTransaction tx;
     217           1 :     CScript script;
     218           1 :     uint256 hash;
     219           1 :     TestMemPoolEntryHelper entry;
     220           1 :     entry.nFee = 11;
     221           1 :     entry.nHeight = 11;
     222             : 
     223           1 :     fCheckpointsEnabled = false;
     224             : 
     225             :     // Simple block creation, nothing special yet:
     226           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     227             : 
     228             :     // We can't make transactions until we have inputs
     229             :     // Therefore, load 110 blocks :)
     230             :     static_assert(sizeof(blockinfo) / sizeof(*blockinfo) == 110, "Should have 110 blocks to import");
     231             :     int baseheight = 0;
     232           1 :     std::vector<CTransactionRef> txFirst;
     233         111 :     for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
     234             :     {
     235         110 :         CBlock *pblock = &pblocktemplate->block; // pointer for convenience
     236             :         {
     237         110 :             LOCK(cs_main);
     238         110 :             pblock->nVersion = 1;
     239         110 :             pblock->nTime = ::ChainActive().Tip()->GetMedianTimePast()+1;
     240         110 :             CMutableTransaction txCoinbase(*pblock->vtx[0]);
     241         110 :             txCoinbase.nVersion = 1;
     242         110 :             txCoinbase.vin[0].scriptSig = CScript();
     243         110 :             txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
     244         110 :             txCoinbase.vin[0].scriptSig.push_back(::ChainActive().Height());
     245         110 :             txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
     246         110 :             txCoinbase.vout[0].scriptPubKey = CScript();
     247         110 :             pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
     248         110 :             if (txFirst.size() == 0)
     249           1 :                 baseheight = ::ChainActive().Height();
     250         110 :             if (txFirst.size() < 4)
     251           4 :                 txFirst.push_back(pblock->vtx[0]);
     252         110 :             pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
     253         110 :             pblock->nNonce = blockinfo[i].nonce;
     254         110 :         }
     255         110 :         std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
     256         220 :         BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(chainparams, shared_pblock, true, nullptr));
     257         110 :         pblock->hashPrevBlock = pblock->GetHash();
     258         110 :     }
     259             : 
     260           1 :     LOCK(cs_main);
     261           1 :     LOCK(m_node.mempool->cs);
     262             : 
     263             :     // Just to make sure we can still make simple blocks
     264           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     265             : 
     266             :     const CAmount BLOCKSUBSIDY = 50*COIN;
     267             :     const CAmount LOWFEE = CENT;
     268             :     const CAmount HIGHFEE = COIN;
     269             :     const CAmount HIGHERFEE = 4*COIN;
     270             : 
     271             :     // block sigops > limit: 1000 CHECKMULTISIG + 1
     272           1 :     tx.vin.resize(1);
     273             :     // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
     274           1 :     tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1;
     275           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     276           1 :     tx.vin[0].prevout.n = 0;
     277           1 :     tx.vout.resize(1);
     278           1 :     tx.vout[0].nValue = BLOCKSUBSIDY;
     279        1002 :     for (unsigned int i = 0; i < 1001; ++i)
     280             :     {
     281        1001 :         tx.vout[0].nValue -= LOWFEE;
     282        1001 :         hash = tx.GetHash();
     283        1001 :         bool spendsCoinbase = i == 0; // only first tx spends coinbase
     284             :         // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
     285        1001 :         m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
     286        1001 :         tx.vin[0].prevout.hash = hash;
     287           0 :     }
     288             : 
     289           1 :     BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops"));
     290           1 :     m_node.mempool->clear();
     291             : 
     292           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     293           1 :     tx.vout[0].nValue = BLOCKSUBSIDY;
     294        1002 :     for (unsigned int i = 0; i < 1001; ++i)
     295             :     {
     296        1001 :         tx.vout[0].nValue -= LOWFEE;
     297        1001 :         hash = tx.GetHash();
     298        1001 :         bool spendsCoinbase = i == 0; // only first tx spends coinbase
     299             :         // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
     300        1001 :         m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
     301        1001 :         tx.vin[0].prevout.hash = hash;
     302           0 :     }
     303           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     304           1 :     m_node.mempool->clear();
     305             : 
     306             :     // block size > limit
     307           1 :     tx.vin[0].scriptSig = CScript();
     308             :     // 18 * (520char + DROP) + OP_1 = 9433 bytes
     309           1 :     std::vector<unsigned char> vchData(520);
     310          19 :     for (unsigned int i = 0; i < 18; ++i)
     311          18 :         tx.vin[0].scriptSig << vchData << OP_DROP;
     312           1 :     tx.vin[0].scriptSig << OP_1;
     313           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     314           1 :     tx.vout[0].nValue = BLOCKSUBSIDY;
     315         129 :     for (unsigned int i = 0; i < 128; ++i)
     316             :     {
     317         128 :         tx.vout[0].nValue -= LOWFEE;
     318         128 :         hash = tx.GetHash();
     319         128 :         bool spendsCoinbase = i == 0; // only first tx spends coinbase
     320         128 :         m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
     321         128 :         tx.vin[0].prevout.hash = hash;
     322           0 :     }
     323           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     324           1 :     m_node.mempool->clear();
     325             : 
     326             :     // orphan in *m_node.mempool, template creation fails
     327           1 :     hash = tx.GetHash();
     328           1 :     m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
     329           1 :     BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
     330           1 :     m_node.mempool->clear();
     331             : 
     332             :     // child with higher feerate than parent
     333           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     334           1 :     tx.vin[0].prevout.hash = txFirst[1]->GetHash();
     335           1 :     tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
     336           1 :     hash = tx.GetHash();
     337           1 :     m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     338           1 :     tx.vin[0].prevout.hash = hash;
     339           1 :     tx.vin.resize(2);
     340           1 :     tx.vin[1].scriptSig = CScript() << OP_1;
     341           1 :     tx.vin[1].prevout.hash = txFirst[0]->GetHash();
     342           1 :     tx.vin[1].prevout.n = 0;
     343           1 :     tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee
     344           1 :     hash = tx.GetHash();
     345           1 :     m_node.mempool->addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     346           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     347           1 :     m_node.mempool->clear();
     348             : 
     349             :     // coinbase in *m_node.mempool, template creation fails
     350           1 :     tx.vin.resize(1);
     351           1 :     tx.vin[0].prevout.SetNull();
     352           1 :     tx.vin[0].scriptSig = CScript() << OP_0 << OP_1;
     353           1 :     tx.vout[0].nValue = 0;
     354           1 :     hash = tx.GetHash();
     355             :     // give it a fee so it'll get mined
     356           1 :     m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
     357             :     // Should throw bad-cb-multiple
     358           1 :     BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
     359           1 :     m_node.mempool->clear();
     360             : 
     361             :     // double spend txn pair in *m_node.mempool, template creation fails
     362           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     363           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     364           1 :     tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
     365           1 :     tx.vout[0].scriptPubKey = CScript() << OP_1;
     366           1 :     hash = tx.GetHash();
     367           1 :     m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     368           1 :     tx.vout[0].scriptPubKey = CScript() << OP_2;
     369           1 :     hash = tx.GetHash();
     370           1 :     m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     371           1 :     BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
     372           1 :     m_node.mempool->clear();
     373             : 
     374             :     // subsidy changing
     375           1 :     int nHeight = ::ChainActive().Height();
     376             :     // Create an actual 209999-long block chain (without valid blocks).
     377      209890 :     while (::ChainActive().Tip()->nHeight < 209999) {
     378      209889 :         CBlockIndex* prev = ::ChainActive().Tip();
     379      209889 :         CBlockIndex* next = new CBlockIndex();
     380      209889 :         next->phashBlock = new uint256(InsecureRand256());
     381      209889 :         ::ChainstateActive().CoinsTip().SetBestBlock(next->GetBlockHash());
     382      209889 :         next->pprev = prev;
     383      209889 :         next->nHeight = prev->nHeight + 1;
     384      209889 :         next->BuildSkip();
     385      209889 :         ::ChainActive().SetTip(next);
     386           0 :     }
     387           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     388             :     // Extend to a 210000-long block chain.
     389           2 :     while (::ChainActive().Tip()->nHeight < 210000) {
     390           1 :         CBlockIndex* prev = ::ChainActive().Tip();
     391           1 :         CBlockIndex* next = new CBlockIndex();
     392           1 :         next->phashBlock = new uint256(InsecureRand256());
     393           1 :         ::ChainstateActive().CoinsTip().SetBestBlock(next->GetBlockHash());
     394           1 :         next->pprev = prev;
     395           1 :         next->nHeight = prev->nHeight + 1;
     396           1 :         next->BuildSkip();
     397           1 :         ::ChainActive().SetTip(next);
     398           0 :     }
     399           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     400             : 
     401             :     // invalid p2sh txn in *m_node.mempool, template creation fails
     402           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash();
     403           1 :     tx.vin[0].prevout.n = 0;
     404           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     405           1 :     tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
     406           1 :     script = CScript() << OP_0;
     407           1 :     tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script));
     408           1 :     hash = tx.GetHash();
     409           1 :     m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     410           1 :     tx.vin[0].prevout.hash = hash;
     411           1 :     tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
     412           1 :     tx.vout[0].nValue -= LOWFEE;
     413           1 :     hash = tx.GetHash();
     414           1 :     m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
     415             :     // Should throw block-validation-failed
     416           1 :     BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
     417           1 :     m_node.mempool->clear();
     418             : 
     419             :     // Delete the dummy blocks again.
     420      209891 :     while (::ChainActive().Tip()->nHeight > nHeight) {
     421      209890 :         CBlockIndex* del = ::ChainActive().Tip();
     422      209890 :         ::ChainActive().SetTip(del->pprev);
     423      209890 :         ::ChainstateActive().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());
     424      209890 :         delete del->phashBlock;
     425      209890 :         delete del;
     426           0 :     }
     427             : 
     428             :     // non-final txs in mempool
     429           1 :     SetMockTime(::ChainActive().Tip()->GetMedianTimePast()+1);
     430             :     int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST;
     431             :     // height map
     432           1 :     std::vector<int> prevheights;
     433             : 
     434             :     // relative height locked
     435           1 :     tx.nVersion = 2;
     436           1 :     tx.vin.resize(1);
     437           1 :     prevheights.resize(1);
     438           1 :     tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
     439           1 :     tx.vin[0].prevout.n = 0;
     440           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
     441           1 :     tx.vin[0].nSequence = ::ChainActive().Tip()->nHeight + 1; // txFirst[0] is the 2nd block
     442           1 :     prevheights[0] = baseheight + 1;
     443           1 :     tx.vout.resize(1);
     444           1 :     tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
     445           1 :     tx.vout[0].scriptPubKey = CScript() << OP_1;
     446           1 :     tx.nLockTime = 0;
     447           1 :     hash = tx.GetHash();
     448           1 :     m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
     449           1 :     BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
     450           1 :     BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
     451           1 :     BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
     452             : 
     453             :     // relative time locked
     454           1 :     tx.vin[0].prevout.hash = txFirst[1]->GetHash();
     455           1 :     tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((::ChainActive().Tip()->GetMedianTimePast()+1-::ChainActive()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
     456           1 :     prevheights[0] = baseheight + 2;
     457           1 :     hash = tx.GetHash();
     458           1 :     m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
     459           1 :     BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
     460           1 :     BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
     461             : 
     462          12 :     for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
     463          11 :         ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
     464           1 :     BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
     465          12 :     for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
     466          11 :         ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
     467             : 
     468             :     // absolute height locked
     469           1 :     tx.vin[0].prevout.hash = txFirst[2]->GetHash();
     470           1 :     tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1;
     471           1 :     prevheights[0] = baseheight + 3;
     472           1 :     tx.nLockTime = ::ChainActive().Tip()->nHeight + 1;
     473           1 :     hash = tx.GetHash();
     474           1 :     m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
     475           1 :     BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
     476           1 :     BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
     477           1 :     BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
     478             : 
     479             :     // absolute time locked
     480           1 :     tx.vin[0].prevout.hash = txFirst[3]->GetHash();
     481           1 :     tx.nLockTime = ::ChainActive().Tip()->GetMedianTimePast();
     482           1 :     prevheights.resize(1);
     483           1 :     prevheights[0] = baseheight + 4;
     484           1 :     hash = tx.GetHash();
     485           1 :     m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
     486           1 :     BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
     487           1 :     BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
     488           1 :     BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
     489             : 
     490             :     // mempool-dependent transactions (not added)
     491           1 :     tx.vin[0].prevout.hash = hash;
     492           1 :     prevheights[0] = ::ChainActive().Tip()->nHeight + 1;
     493           1 :     tx.nLockTime = 0;
     494           1 :     tx.vin[0].nSequence = 0;
     495           1 :     BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
     496           1 :     BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
     497           1 :     tx.vin[0].nSequence = 1;
     498           1 :     BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
     499           1 :     tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
     500           1 :     BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
     501           1 :     tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
     502           1 :     BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
     503             : 
     504           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     505             : 
     506             :     // None of the of the absolute height/time locked tx should have made
     507             :     // it into the template because we still check IsFinalTx in CreateNewBlock,
     508             :     // but relative locked txs will if inconsistently added to mempool.
     509             :     // For now these will still generate a valid template until BIP68 soft fork
     510           1 :     BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
     511             :     // However if we advance height by 1 and time by 512, all of them should be mined
     512          12 :     for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
     513          11 :         ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
     514           1 :     ::ChainActive().Tip()->nHeight++;
     515           1 :     SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1);
     516             : 
     517           1 :     BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
     518           1 :     BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
     519             : 
     520           1 :     ::ChainActive().Tip()->nHeight--;
     521           1 :     SetMockTime(0);
     522           1 :     m_node.mempool->clear();
     523             : 
     524           1 :     TestPackageSelection(chainparams, scriptPubKey, txFirst);
     525             : 
     526           1 :     fCheckpointsEnabled = true;
     527           6 : }
     528             : 
     529          89 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.15