LCOV - code coverage report
Current view: top level - src/test - mempool_tests.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 100.0 % 328 328
Test Date: 2026-07-17 06:52:43 Functions: 100.0 % 11 11
Branches: 50.1 % 1632 818

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2011-present 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 <common/system.h>
       6                 :             : #include <policy/policy.h>
       7                 :             : #include <test/util/time.h>
       8                 :             : #include <test/util/txmempool.h>
       9                 :             : #include <txmempool.h>
      10                 :             : #include <util/time.h>
      11                 :             : 
      12                 :             : #include <test/util/setup_common.h>
      13                 :             : 
      14                 :             : #include <boost/test/unit_test.hpp>
      15                 :             : #include <vector>
      16                 :             : 
      17                 :             : BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup)
      18                 :             : 
      19                 :             : static constexpr auto REMOVAL_REASON_DUMMY = MemPoolRemovalReason::REPLACED;
      20                 :             : 
      21                 :             : class MemPoolTest final : public CTxMemPool
      22                 :             : {
      23                 :             : public:
      24                 :             :     using CTxMemPool::GetMinFee;
      25                 :             : };
      26                 :             : 
      27   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(MempoolLookupTest)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
      28                 :             : {
      29         [ -  + ]:           1 :     auto& pool = static_cast<MemPoolTest&>(*Assert(m_node.mempool));
      30         [ +  - ]:           1 :     LOCK2(cs_main, pool.cs);
      31                 :           1 :     TestMemPoolEntryHelper entry;
      32                 :             : 
      33         [ +  - ]:           1 :     CMutableTransaction tx = CMutableTransaction();
      34         [ +  - ]:           1 :     tx.vin.resize(1);
      35         [ +  - ]:           1 :     tx.vin[0].scriptSig = CScript() << OP_1;
      36         [ +  - ]:           1 :     tx.vout.resize(1);
      37   [ +  -  +  - ]:           1 :     tx.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
      38         [ +  - ]:           1 :     tx.vout[0].nValue = 10 * COIN;
      39                 :             : 
      40                 :             :     // Not in the mempool, so can't find it by txid or wtxid
      41   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.get(tx.GetHash()));
          +  -  +  -  -  
                +  +  - ]
      42   [ +  -  +  -  :           3 :     BOOST_CHECK(!pool.get(CTransaction(tx).GetWitnessHash()));
          +  -  +  -  -  
                +  +  - ]
      43                 :             : 
      44   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(1000LL).FromTx(tx));
      45                 :             : 
      46                 :             :     // Lookup by Txid
      47   [ +  -  +  -  :           3 :     BOOST_CHECK(pool.get(tx.GetHash()));
          +  -  +  -  +  
                -  +  - ]
      48                 :             : 
      49                 :             :     // Lookup by Wtxid
      50   [ +  -  +  -  :           4 :     BOOST_CHECK(pool.get(CTransaction(tx).GetWitnessHash()));
          +  -  +  -  +  
                      - ]
      51   [ +  -  +  - ]:           3 : }
      52                 :             : 
      53   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
      54                 :             : {
      55                 :             :     // Test CTxMemPool::remove functionality
      56                 :             : 
      57                 :           1 :     TestMemPoolEntryHelper entry;
      58                 :             :     // Parent transaction with three children,
      59                 :             :     // and three grand-children:
      60                 :           1 :     CMutableTransaction txParent;
      61         [ +  - ]:           1 :     txParent.vin.resize(1);
      62         [ +  - ]:           1 :     txParent.vin[0].scriptSig = CScript() << OP_11;
      63         [ +  - ]:           1 :     txParent.vout.resize(3);
      64         [ +  + ]:           4 :     for (int i = 0; i < 3; i++)
      65                 :             :     {
      66   [ +  -  +  - ]:           3 :         txParent.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
      67                 :           3 :         txParent.vout[i].nValue = 33000LL;
      68                 :             :     }
      69   [ +  -  +  +  :          10 :     CMutableTransaction txChild[3];
                   -  - ]
      70         [ +  + ]:           4 :     for (int i = 0; i < 3; i++)
      71                 :             :     {
      72         [ +  - ]:           3 :         txChild[i].vin.resize(1);
      73         [ +  - ]:           3 :         txChild[i].vin[0].scriptSig = CScript() << OP_11;
      74   [ +  -  +  - ]:           3 :         txChild[i].vin[0].prevout.hash = txParent.GetHash();
      75                 :           3 :         txChild[i].vin[0].prevout.n = i;
      76         [ +  - ]:           3 :         txChild[i].vout.resize(1);
      77   [ +  -  +  - ]:           3 :         txChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
      78                 :           3 :         txChild[i].vout[0].nValue = 11000LL;
      79                 :             :     }
      80   [ +  -  +  +  :          11 :     CMutableTransaction txGrandChild[3];
                   -  - ]
      81         [ +  + ]:           4 :     for (int i = 0; i < 3; i++)
      82                 :             :     {
      83         [ +  - ]:           3 :         txGrandChild[i].vin.resize(1);
      84         [ +  - ]:           3 :         txGrandChild[i].vin[0].scriptSig = CScript() << OP_11;
      85   [ +  -  +  - ]:           3 :         txGrandChild[i].vin[0].prevout.hash = txChild[i].GetHash();
      86                 :           3 :         txGrandChild[i].vin[0].prevout.n = 0;
      87         [ +  - ]:           3 :         txGrandChild[i].vout.resize(1);
      88   [ +  -  +  - ]:           3 :         txGrandChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
      89                 :           3 :         txGrandChild[i].vout[0].nValue = 11000LL;
      90                 :             :     }
      91                 :             : 
      92                 :             : 
      93   [ -  +  +  - ]:           1 :     CTxMemPool& testPool = *Assert(m_node.mempool);
      94   [ +  -  +  - ]:           1 :     LOCK2(::cs_main, testPool.cs);
      95                 :             : 
      96                 :             :     // Nothing in pool, remove should do nothing:
      97         [ +  - ]:           1 :     unsigned int poolSize = testPool.size();
      98   [ +  -  +  - ]:           1 :     testPool.removeRecursive(CTransaction(txParent), REMOVAL_REASON_DUMMY);
      99   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), poolSize);
                   +  - ]
     100                 :             : 
     101                 :             :     // Just the parent:
     102   [ +  -  +  - ]:           1 :     TryAddToMempool(testPool, entry.FromTx(txParent));
     103         [ +  - ]:           1 :     poolSize = testPool.size();
     104   [ +  -  +  - ]:           1 :     testPool.removeRecursive(CTransaction(txParent), REMOVAL_REASON_DUMMY);
     105   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1);
                   +  - ]
     106                 :             : 
     107                 :             :     // Parent, children, grandchildren:
     108   [ +  -  +  - ]:           1 :     TryAddToMempool(testPool, entry.FromTx(txParent));
     109         [ +  + ]:           4 :     for (int i = 0; i < 3; i++)
     110                 :             :     {
     111   [ +  -  +  - ]:           3 :         TryAddToMempool(testPool, entry.FromTx(txChild[i]));
     112   [ +  -  +  - ]:           3 :         TryAddToMempool(testPool, entry.FromTx(txGrandChild[i]));
     113                 :             :     }
     114                 :             :     // Remove Child[0], GrandChild[0] should be removed:
     115         [ +  - ]:           1 :     poolSize = testPool.size();
     116   [ +  -  +  - ]:           1 :     testPool.removeRecursive(CTransaction(txChild[0]), REMOVAL_REASON_DUMMY);
     117   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), poolSize - 2);
                   +  - ]
     118                 :             :     // ... make sure grandchild and child are gone:
     119         [ +  - ]:           1 :     poolSize = testPool.size();
     120   [ +  -  +  - ]:           1 :     testPool.removeRecursive(CTransaction(txGrandChild[0]), REMOVAL_REASON_DUMMY);
     121   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), poolSize);
                   +  - ]
     122         [ +  - ]:           1 :     poolSize = testPool.size();
     123   [ +  -  +  - ]:           1 :     testPool.removeRecursive(CTransaction(txChild[0]), REMOVAL_REASON_DUMMY);
     124   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), poolSize);
                   +  - ]
     125                 :             :     // Remove parent, all children/grandchildren should go:
     126         [ +  - ]:           1 :     poolSize = testPool.size();
     127   [ +  -  +  - ]:           1 :     testPool.removeRecursive(CTransaction(txParent), REMOVAL_REASON_DUMMY);
     128   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), poolSize - 5);
                   +  - ]
     129   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), 0U);
                   +  - ]
     130                 :             : 
     131                 :             :     // Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
     132         [ +  + ]:           4 :     for (int i = 0; i < 3; i++)
     133                 :             :     {
     134   [ +  -  +  - ]:           3 :         TryAddToMempool(testPool, entry.FromTx(txChild[i]));
     135   [ +  -  +  - ]:           3 :         TryAddToMempool(testPool, entry.FromTx(txGrandChild[i]));
     136                 :             :     }
     137                 :             :     // Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
     138                 :             :     // put into the mempool (maybe because it is non-standard):
     139         [ +  - ]:           1 :     poolSize = testPool.size();
     140   [ +  -  +  - ]:           1 :     testPool.removeRecursive(CTransaction(txParent), REMOVAL_REASON_DUMMY);
     141   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), poolSize - 6);
                   +  - ]
     142   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(testPool.size(), 0U);
             +  -  +  - ]
     143   [ +  -  +  +  :          10 : }
          +  +  -  -  -  
                      - ]
     144                 :             : 
     145   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     146                 :             : {
     147         [ -  + ]:           1 :     auto& pool = static_cast<MemPoolTest&>(*Assert(m_node.mempool));
     148         [ +  - ]:           1 :     LOCK2(cs_main, pool.cs);
     149                 :           1 :     TestMemPoolEntryHelper entry;
     150                 :             : 
     151         [ +  - ]:           1 :     CMutableTransaction tx1 = CMutableTransaction();
     152         [ +  - ]:           1 :     tx1.vin.resize(1);
     153         [ +  - ]:           1 :     tx1.vin[0].scriptSig = CScript() << OP_1;
     154         [ +  - ]:           1 :     tx1.vout.resize(1);
     155   [ +  -  +  - ]:           1 :     tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
     156         [ +  - ]:           1 :     tx1.vout[0].nValue = 10 * COIN;
     157   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(1000LL).FromTx(tx1));
     158                 :             : 
     159         [ +  - ]:           1 :     CMutableTransaction tx2 = CMutableTransaction();
     160         [ +  - ]:           1 :     tx2.vin.resize(1);
     161         [ +  - ]:           1 :     tx2.vin[0].scriptSig = CScript() << OP_2;
     162         [ +  - ]:           1 :     tx2.vout.resize(1);
     163   [ +  -  +  - ]:           1 :     tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
     164         [ +  - ]:           1 :     tx2.vout[0].nValue = 10 * COIN;
     165   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(500LL).FromTx(tx2));
     166                 :             : 
     167   [ +  -  +  - ]:           1 :     pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
     168   [ +  -  +  -  :           2 :     BOOST_CHECK(pool.exists(tx1.GetHash()));
          +  -  +  -  +  
                      - ]
     169   [ +  -  +  -  :           2 :     BOOST_CHECK(pool.exists(tx2.GetHash()));
          +  -  +  -  +  
                      - ]
     170                 :             : 
     171   [ +  -  +  - ]:           1 :     pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // should remove the lower-feerate transaction
     172   [ +  -  +  -  :           2 :     BOOST_CHECK(pool.exists(tx1.GetHash()));
          +  -  +  -  +  
                      - ]
     173   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx2.GetHash()));
          +  -  +  -  +  
                      - ]
     174                 :             : 
     175   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.FromTx(tx2));
     176         [ +  - ]:           1 :     CMutableTransaction tx3 = CMutableTransaction();
     177         [ +  - ]:           1 :     tx3.vin.resize(1);
     178   [ +  -  +  - ]:           1 :     tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
     179         [ +  - ]:           1 :     tx3.vin[0].scriptSig = CScript() << OP_2;
     180         [ +  - ]:           1 :     tx3.vout.resize(1);
     181   [ +  -  +  - ]:           1 :     tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
     182         [ +  - ]:           1 :     tx3.vout[0].nValue = 10 * COIN;
     183   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(2000LL).FromTx(tx3));
     184                 :             : 
     185   [ +  -  +  - ]:           1 :     pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
     186   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx1.GetHash()));
          +  -  +  -  +  
                      - ]
     187   [ +  -  +  -  :           2 :     BOOST_CHECK(pool.exists(tx2.GetHash()));
          +  -  +  -  +  
                      - ]
     188   [ +  -  +  -  :           2 :     BOOST_CHECK(pool.exists(tx3.GetHash()));
          +  -  +  -  +  
                      - ]
     189                 :             : 
     190   [ +  -  +  - ]:           2 :     pool.TrimToSize(GetVirtualTransactionSize(CTransaction(tx1))); // mempool is limited to tx1's size in memory usage, so nothing fits
     191   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx1.GetHash()));
          +  -  +  -  +  
                      - ]
     192   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx2.GetHash()));
          +  -  +  -  +  
                      - ]
     193   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx3.GetHash()));
          +  -  +  -  +  
                      - ]
     194                 :             : 
     195   [ +  -  +  -  :           4 :     CFeeRate maxFeeRateRemoved(2500, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2)));
                   +  - ]
     196   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE);
                   +  - ]
     197                 :             : 
     198         [ +  - ]:           1 :     CMutableTransaction tx4 = CMutableTransaction();
     199         [ +  - ]:           1 :     tx4.vin.resize(2);
     200                 :           1 :     tx4.vin[0].prevout.SetNull();
     201         [ +  - ]:           1 :     tx4.vin[0].scriptSig = CScript() << OP_4;
     202                 :           1 :     tx4.vin[1].prevout.SetNull();
     203         [ +  - ]:           1 :     tx4.vin[1].scriptSig = CScript() << OP_4;
     204         [ +  - ]:           1 :     tx4.vout.resize(2);
     205   [ +  -  +  - ]:           1 :     tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
     206         [ +  - ]:           1 :     tx4.vout[0].nValue = 10 * COIN;
     207   [ +  -  +  - ]:           1 :     tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
     208         [ +  - ]:           1 :     tx4.vout[1].nValue = 10 * COIN;
     209                 :             : 
     210         [ +  - ]:           1 :     CMutableTransaction tx5 = CMutableTransaction();
     211         [ +  - ]:           1 :     tx5.vin.resize(2);
     212   [ +  -  +  - ]:           1 :     tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0);
     213         [ +  - ]:           1 :     tx5.vin[0].scriptSig = CScript() << OP_4;
     214                 :           1 :     tx5.vin[1].prevout.SetNull();
     215         [ +  - ]:           1 :     tx5.vin[1].scriptSig = CScript() << OP_5;
     216         [ +  - ]:           1 :     tx5.vout.resize(2);
     217   [ +  -  +  - ]:           1 :     tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
     218         [ +  - ]:           1 :     tx5.vout[0].nValue = 10 * COIN;
     219   [ +  -  +  - ]:           1 :     tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
     220         [ +  - ]:           1 :     tx5.vout[1].nValue = 10 * COIN;
     221                 :             : 
     222         [ +  - ]:           1 :     CMutableTransaction tx6 = CMutableTransaction();
     223         [ +  - ]:           1 :     tx6.vin.resize(2);
     224   [ +  -  +  - ]:           1 :     tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1);
     225         [ +  - ]:           1 :     tx6.vin[0].scriptSig = CScript() << OP_4;
     226                 :           1 :     tx6.vin[1].prevout.SetNull();
     227         [ +  - ]:           1 :     tx6.vin[1].scriptSig = CScript() << OP_6;
     228         [ +  - ]:           1 :     tx6.vout.resize(2);
     229   [ +  -  +  - ]:           1 :     tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
     230         [ +  - ]:           1 :     tx6.vout[0].nValue = 10 * COIN;
     231   [ +  -  +  - ]:           1 :     tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
     232         [ +  - ]:           1 :     tx6.vout[1].nValue = 10 * COIN;
     233                 :             : 
     234         [ +  - ]:           1 :     CMutableTransaction tx7 = CMutableTransaction();
     235         [ +  - ]:           1 :     tx7.vin.resize(2);
     236   [ +  -  +  - ]:           1 :     tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0);
     237         [ +  - ]:           1 :     tx7.vin[0].scriptSig = CScript() << OP_5;
     238   [ +  -  +  - ]:           1 :     tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0);
     239         [ +  - ]:           1 :     tx7.vin[1].scriptSig = CScript() << OP_6;
     240         [ +  - ]:           1 :     tx7.vout.resize(2);
     241   [ +  -  +  - ]:           1 :     tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
     242         [ +  - ]:           1 :     tx7.vout[0].nValue = 10 * COIN;
     243   [ +  -  +  - ]:           1 :     tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
     244         [ +  - ]:           1 :     tx7.vout[1].nValue = 10 * COIN;
     245                 :             : 
     246   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(700LL).FromTx(tx4));
     247         [ +  - ]:           1 :     auto usage_with_tx4_only = pool.DynamicMemoryUsage();
     248   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
     249   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
     250   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
     251                 :             : 
     252                 :             :     // From the topology above, tx7 must be sorted last, so it should
     253                 :             :     // definitely evicted first if we must trim. tx4 should definitely remain
     254                 :             :     // in the mempool since it has a higher feerate than its descendants and
     255                 :             :     // should be in its own chunk.
     256   [ +  -  +  - ]:           1 :     pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
     257   [ +  -  +  -  :           2 :     BOOST_CHECK(pool.exists(tx4.GetHash()));
          +  -  +  -  +  
                      - ]
     258   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx7.GetHash()));
          +  -  +  -  +  
                      - ]
     259                 :             : 
     260                 :             :     // Tx5 and Tx6 may be removed as well because they're in the same chunk as
     261                 :             :     // tx7, but this behavior need not be guaranteed.
     262                 :             : 
     263   [ +  -  +  -  :           1 :     if (!pool.exists(tx5.GetHash()))
                   +  - ]
     264   [ +  -  +  - ]:           1 :         TryAddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
     265   [ +  -  +  -  :           1 :     if (!pool.exists(tx6.GetHash()))
                   +  - ]
     266   [ +  -  +  - ]:           1 :         TryAddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
     267   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
     268                 :             : 
     269                 :             :     // If we trim sufficiently, everything but tx4 should be removed.
     270         [ +  - ]:           1 :     pool.TrimToSize(usage_with_tx4_only + 1);
     271   [ +  -  +  -  :           2 :     BOOST_CHECK(pool.exists(tx4.GetHash()));
          +  -  +  -  +  
                      - ]
     272   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx5.GetHash()));
          +  -  +  -  +  
                      - ]
     273   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx6.GetHash()));
          +  -  +  -  +  
                      - ]
     274   [ +  -  +  -  :           2 :     BOOST_CHECK(!pool.exists(tx7.GetHash()));
          +  -  +  -  +  
                      - ]
     275                 :             : 
     276   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
     277   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
     278   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
     279                 :             : 
     280                 :           1 :     std::vector<CTransactionRef> vtx;
     281         [ +  - ]:           1 :     FakeNodeClock clock{42s};
     282                 :           1 :     constexpr std::chrono::seconds HALFLIFE{CTxMemPool::ROLLING_FEE_HALFLIFE};
     283         [ +  - ]:           1 :     clock += HALFLIFE;
     284   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE);
                   +  - ]
     285                 :             :     // ... we should keep the same min fee until we get a block
     286         [ +  - ]:           1 :     pool.removeForBlock(vtx, 1);
     287         [ +  - ]:           1 :     clock += HALFLIFE;
     288   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE)/2.0));
                   +  - ]
     289                 :             :     // ... then feerate should drop 1/2 each halflife
     290                 :             : 
     291         [ +  - ]:           1 :     clock += HALFLIFE / 2;
     292   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE)/4.0));
             +  -  +  - ]
     293                 :             :     // ... with a 1/2 halflife when mempool is < 1/2 its target size
     294                 :             : 
     295         [ +  - ]:           1 :     clock += HALFLIFE / 4;
     296   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE)/8.0));
             +  -  +  - ]
     297                 :             :     // ... with a 1/4 halflife when mempool is < 1/4 its target size
     298                 :             : 
     299         [ +  - ]:           1 :     clock += 5 * HALFLIFE;
     300   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), DEFAULT_INCREMENTAL_RELAY_FEE);
                   +  - ]
     301                 :             :     // ... but feerate should never drop below DEFAULT_INCREMENTAL_RELAY_FEE
     302                 :             : 
     303         [ +  - ]:           1 :     clock += HALFLIFE;
     304   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 0);
                   +  - ]
     305                 :             :     // ... unless it has gone all the way to 0 (after getting past DEFAULT_INCREMENTAL_RELAY_FEE/2)
     306   [ +  -  +  - ]:          10 : }
     307                 :             : 
     308                 :          14 : inline CTransactionRef make_tx(std::vector<CAmount>&& output_values, std::vector<CTransactionRef>&& inputs=std::vector<CTransactionRef>(), std::vector<uint32_t>&& input_indices=std::vector<uint32_t>())
     309                 :             : {
     310                 :          14 :     CMutableTransaction tx = CMutableTransaction();
     311   [ -  +  +  - ]:          14 :     tx.vin.resize(inputs.size());
     312   [ -  +  +  - ]:          14 :     tx.vout.resize(output_values.size());
     313   [ -  +  +  + ]:          27 :     for (size_t i = 0; i < inputs.size(); ++i) {
     314         [ -  + ]:          13 :         tx.vin[i].prevout.hash = inputs[i]->GetHash();
     315   [ -  +  +  + ]:          13 :         tx.vin[i].prevout.n = input_indices.size() > i ? input_indices[i] : 0;
     316                 :             :     }
     317   [ -  +  +  + ]:          32 :     for (size_t i = 0; i < output_values.size(); ++i) {
     318   [ +  -  +  - ]:          18 :         tx.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
     319                 :          18 :         tx.vout[i].nValue = output_values[i];
     320                 :             :     }
     321         [ +  - ]:          28 :     return MakeTransactionRef(tx);
     322                 :          14 : }
     323                 :             : 
     324                 :             : 
     325   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     326                 :             : {
     327                 :           1 :     size_t ancestors, clustersize;
     328                 :             : 
     329         [ -  + ]:           1 :     CTxMemPool& pool = *Assert(m_node.mempool);
     330         [ +  - ]:           1 :     LOCK2(cs_main, pool.cs);
     331                 :           1 :     TestMemPoolEntryHelper entry;
     332                 :             : 
     333                 :             :     /* Base transaction */
     334                 :             :     //
     335                 :             :     // [tx1]
     336                 :             :     //
     337   [ +  -  +  - ]:           2 :     CTransactionRef tx1 = make_tx(/*output_values=*/{10 * COIN});
     338   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx1));
     339                 :             : 
     340                 :             :     // Ancestors / clustersize should be 1 / 1 (itself / itself)
     341         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
     342   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 1ULL);
     343   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 1ULL);
     344                 :             : 
     345                 :             :     /* Child transaction */
     346                 :             :     //
     347                 :             :     // [tx1].0 <- [tx2]
     348                 :             :     //
     349   [ +  -  +  -  :           3 :     CTransactionRef tx2 = make_tx(/*output_values=*/{495 * CENT, 5 * COIN}, /*inputs=*/{tx1});
          +  +  +  -  -  
                -  -  - ]
     350   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx2));
     351                 :             : 
     352                 :             :     // Ancestors / clustersize should be:
     353                 :             :     // transaction  ancestors   clustersize
     354                 :             :     // ============ =========== ===========
     355                 :             :     // tx1          1 (tx1)     2 (tx1,2)
     356                 :             :     // tx2          2 (tx1,2)   2 (tx1,2)
     357         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
     358   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 1ULL);
     359   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 2ULL);
     360         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
     361   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 2ULL);
     362   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 2ULL);
     363                 :             : 
     364                 :             :     /* Grand-child 1 */
     365                 :             :     //
     366                 :             :     // [tx1].0 <- [tx2].0 <- [tx3]
     367                 :             :     //
     368   [ +  -  +  -  :           3 :     CTransactionRef tx3 = make_tx(/*output_values=*/{290 * CENT, 200 * CENT}, /*inputs=*/{tx2});
          +  +  +  -  -  
                -  -  - ]
     369   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx3));
     370                 :             : 
     371                 :             :     // Ancestors / clustersize should be:
     372                 :             :     // transaction  ancestors   clustersize
     373                 :             :     // ============ =========== ===========
     374                 :             :     // tx1          1 (tx1)     3 (tx1,2,3)
     375                 :             :     // tx2          2 (tx1,2)   3 (tx1,2,3)
     376                 :             :     // tx3          3 (tx1,2,3) 3 (tx1,2,3)
     377         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
     378   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 1ULL);
     379   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 3ULL);
     380         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
     381   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 2ULL);
     382   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 3ULL);
     383         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize);
     384   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 3ULL);
     385   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 3ULL);
     386                 :             : 
     387                 :             :     /* Grand-child 2 */
     388                 :             :     //
     389                 :             :     // [tx1].0 <- [tx2].0 <- [tx3]
     390                 :             :     //              |
     391                 :             :     //              \---1 <- [tx4]
     392                 :             :     //
     393   [ +  -  +  -  :           5 :     CTransactionRef tx4 = make_tx(/*output_values=*/{290 * CENT, 250 * CENT}, /*inputs=*/{tx2}, /*input_indices=*/{1});
          +  -  +  +  +  
          -  +  -  -  -  
                   -  - ]
     394   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tx4));
     395                 :             : 
     396                 :             :     // Ancestors / clustersize should be:
     397                 :             :     // transaction  ancestors   clustersize
     398                 :             :     // ============ =========== ===========
     399                 :             :     // tx1          1 (tx1)     4 (tx1,2,3,4)
     400                 :             :     // tx2          2 (tx1,2)   4 (tx1,2,3,4)
     401                 :             :     // tx3          3 (tx1,2,3) 4 (tx1,2,3,4)
     402                 :             :     // tx4          3 (tx1,2,4) 4 (tx1,2,3,4)
     403         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
     404   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 1ULL);
     405   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 4ULL);
     406         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
     407   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 2ULL);
     408   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 4ULL);
     409         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize);
     410   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 3ULL);
     411   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 4ULL);
     412         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx4->GetHash(), ancestors, clustersize);
     413   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 3ULL);
     414   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 4ULL);
     415                 :             : 
     416                 :             :     /* Make an alternate branch that is longer and connect it to tx3 */
     417                 :             :     //
     418                 :             :     // [ty1].0 <- [ty2].0 <- [ty3].0 <- [ty4].0 <- [ty5].0
     419                 :             :     //                                              |
     420                 :             :     // [tx1].0 <- [tx2].0 <- [tx3].0 <- [ty6] --->--/
     421                 :             :     //              |
     422                 :             :     //              \---1 <- [tx4]
     423                 :             :     //
     424                 :           1 :     CTransactionRef ty1, ty2, ty3, ty4, ty5;
     425                 :           1 :     CTransactionRef* ty[5] = {&ty1, &ty2, &ty3, &ty4, &ty5};
     426                 :           1 :     CAmount v = 5 * COIN;
     427         [ +  + ]:           6 :     for (uint64_t i = 0; i < 5; i++) {
     428                 :           5 :         CTransactionRef& tyi = *ty[i];
     429   [ +  +  +  -  :          22 :         tyi = make_tx(/*output_values=*/{v}, /*inputs=*/i > 0 ? std::vector<CTransactionRef>{*ty[i - 1]} : std::vector<CTransactionRef>{});
          +  -  +  -  -  
          +  +  +  +  +  
          +  -  -  -  -  
                -  -  - ]
     430                 :           5 :         v -= 50 * CENT;
     431   [ +  -  +  - ]:           5 :         TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tyi));
     432         [ +  - ]:           5 :         pool.GetTransactionAncestry(tyi->GetHash(), ancestors, clustersize);
     433   [ +  -  +  - ]:           5 :         BOOST_CHECK_EQUAL(ancestors, i+1);
     434   [ +  -  +  - ]:           5 :         BOOST_CHECK_EQUAL(clustersize, i+1);
     435                 :             :     }
     436   [ +  -  +  -  :           4 :     CTransactionRef ty6 = make_tx(/*output_values=*/{5 * COIN}, /*inputs=*/{tx3, ty5});
          +  +  +  -  -  
                -  -  - ]
     437   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(ty6));
     438                 :             : 
     439                 :             :     // Ancestors / clustersize should be:
     440                 :             :     // transaction  ancestors           clustersize
     441                 :             :     // ============ =================== ===========
     442                 :             :     // tx1          1 (tx1)             10 (tx1-5, ty1-5)
     443                 :             :     // tx2          2 (tx1,2)           10
     444                 :             :     // tx3          3 (tx1,2,3)         10
     445                 :             :     // tx4          3 (tx1,2,4)         10
     446                 :             :     // ty1          1 (ty1)             10
     447                 :             :     // ty2          2 (ty1,2)           10
     448                 :             :     // ty3          3 (ty1,2,3)         10
     449                 :             :     // ty4          4 (y1234)           10
     450                 :             :     // ty5          5 (y12345)          10
     451                 :             :     // ty6          9 (tx123, ty123456) 10
     452         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
     453   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 1ULL);
     454   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     455         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
     456   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 2ULL);
     457   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     458         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize);
     459   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 3ULL);
     460   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     461         [ +  - ]:           1 :     pool.GetTransactionAncestry(tx4->GetHash(), ancestors, clustersize);
     462   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 3ULL);
     463   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     464         [ +  - ]:           1 :     pool.GetTransactionAncestry(ty1->GetHash(), ancestors, clustersize);
     465   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 1ULL);
     466   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     467         [ +  - ]:           1 :     pool.GetTransactionAncestry(ty2->GetHash(), ancestors, clustersize);
     468   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 2ULL);
     469   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     470         [ +  - ]:           1 :     pool.GetTransactionAncestry(ty3->GetHash(), ancestors, clustersize);
     471   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 3ULL);
     472   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     473         [ +  - ]:           1 :     pool.GetTransactionAncestry(ty4->GetHash(), ancestors, clustersize);
     474   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 4ULL);
     475   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     476         [ +  - ]:           1 :     pool.GetTransactionAncestry(ty5->GetHash(), ancestors, clustersize);
     477   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 5ULL);
     478   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
     479         [ +  - ]:           1 :     pool.GetTransactionAncestry(ty6->GetHash(), ancestors, clustersize);
     480   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 9ULL);
     481   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(clustersize, 10ULL);
                   +  - ]
     482   [ +  -  +  -  :          25 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     483                 :             : 
     484   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(MempoolAncestryTestsDiamond)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     485                 :             : {
     486                 :           1 :     size_t ancestors, descendants;
     487                 :             : 
     488         [ -  + ]:           1 :     CTxMemPool& pool = *Assert(m_node.mempool);
     489         [ +  - ]:           1 :     LOCK2(::cs_main, pool.cs);
     490                 :           1 :     TestMemPoolEntryHelper entry;
     491                 :             : 
     492                 :             :     /* Ancestors represented more than once ("diamond") */
     493                 :             :     //
     494                 :             :     // [ta].0 <- [tb].0 -----<------- [td].0
     495                 :             :     //            |                    |
     496                 :             :     //            \---1 <- [tc].0 --<--/
     497                 :             :     //
     498                 :           1 :     CTransactionRef ta, tb, tc, td;
     499   [ +  -  +  -  :           2 :     ta = make_tx(/*output_values=*/{10 * COIN});
                   -  + ]
     500   [ +  -  +  -  :           3 :     tb = make_tx(/*output_values=*/{5 * COIN, 3 * COIN}, /*inputs=*/ {ta});
          -  +  +  +  +  
             -  -  -  -  
                      - ]
     501   [ +  -  +  -  :           5 :     tc = make_tx(/*output_values=*/{2 * COIN}, /*inputs=*/{tb}, /*input_indices=*/{1});
          +  -  -  +  +  
          +  +  -  +  -  
             -  -  -  - ]
     502   [ +  -  +  -  :           6 :     td = make_tx(/*output_values=*/{6 * COIN}, /*inputs=*/{tb, tc}, /*input_indices=*/{0, 0});
          +  -  -  +  +  
          +  +  -  +  -  
             -  -  -  - ]
     503   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(ta));
     504   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tb));
     505   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(tc));
     506   [ +  -  +  - ]:           1 :     TryAddToMempool(pool, entry.Fee(10000LL).FromTx(td));
     507                 :             : 
     508                 :             :     // Ancestors / descendants should be:
     509                 :             :     // transaction  ancestors           descendants
     510                 :             :     // ============ =================== ===========
     511                 :             :     // ta           1 (ta               4 (ta,tb,tc,td)
     512                 :             :     // tb           2 (ta,tb)           4 (ta,tb,tc,td)
     513                 :             :     // tc           3 (ta,tb,tc)        4 (ta,tb,tc,td)
     514                 :             :     // td           4 (ta,tb,tc,td)     4 (ta,tb,tc,td)
     515         [ +  - ]:           1 :     pool.GetTransactionAncestry(ta->GetHash(), ancestors, descendants);
     516   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 1ULL);
     517   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(descendants, 4ULL);
     518         [ +  - ]:           1 :     pool.GetTransactionAncestry(tb->GetHash(), ancestors, descendants);
     519   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 2ULL);
     520   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(descendants, 4ULL);
     521         [ +  - ]:           1 :     pool.GetTransactionAncestry(tc->GetHash(), ancestors, descendants);
     522   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 3ULL);
     523   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(descendants, 4ULL);
     524         [ +  - ]:           1 :     pool.GetTransactionAncestry(td->GetHash(), ancestors, descendants);
     525   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ancestors, 4ULL);
     526   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(descendants, 4ULL);
                   +  - ]
     527   [ +  -  +  -  :          13 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     528                 :             : 
     529                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1