LCOV - code coverage report
Current view: top level - src/test - orphanage_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 98.9 % 537 531
Test Date: 2026-03-16 05:20:51 Functions: 100.0 % 20 20
Branches: 50.7 % 2660 1348

             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 <arith_uint256.h>
       6                 :             : #include <consensus/validation.h>
       7                 :             : #include <node/txorphanage.h>
       8                 :             : #include <policy/policy.h>
       9                 :             : #include <primitives/transaction.h>
      10                 :             : #include <pubkey.h>
      11                 :             : #include <script/sign.h>
      12                 :             : #include <script/signingprovider.h>
      13                 :             : #include <test/util/common.h>
      14                 :             : #include <test/util/random.h>
      15                 :             : #include <test/util/setup_common.h>
      16                 :             : #include <test/util/transaction_utils.h>
      17                 :             : 
      18                 :             : #include <array>
      19                 :             : #include <cstdint>
      20                 :             : 
      21                 :             : #include <boost/test/unit_test.hpp>
      22                 :             : 
      23                 :             : BOOST_FIXTURE_TEST_SUITE(orphanage_tests, TestingSetup)
      24                 :             : 
      25                 :         161 : static void MakeNewKeyWithFastRandomContext(CKey& key, FastRandomContext& rand_ctx)
      26                 :             : {
      27                 :         161 :     std::vector<unsigned char> keydata;
      28                 :         161 :     keydata = rand_ctx.randbytes(32);
      29   [ -  +  +  - ]:         161 :     key.Set(keydata.data(), keydata.data() + keydata.size(), /*fCompressedIn=*/true);
      30         [ -  + ]:         161 :     assert(key.IsValid());
      31                 :         161 : }
      32                 :             : 
      33                 :             : // Creates a transaction with 2 outputs. Spends all outpoints. If outpoints is empty, spends a random one.
      34                 :         160 : static CTransactionRef MakeTransactionSpending(const std::vector<COutPoint>& outpoints, FastRandomContext& det_rand)
      35                 :             : {
      36                 :         160 :     CKey key;
      37         [ +  - ]:         160 :     MakeNewKeyWithFastRandomContext(key, det_rand);
      38         [ +  - ]:         160 :     CMutableTransaction tx;
      39                 :             :     // If no outpoints are given, create a random one.
      40         [ +  + ]:         160 :     if (outpoints.empty()) {
      41         [ +  - ]:         117 :         tx.vin.emplace_back(Txid::FromUint256(det_rand.rand256()), 0);
      42                 :             :     } else {
      43         [ +  + ]:         704 :         for (const auto& outpoint : outpoints) {
      44         [ +  - ]:         661 :             tx.vin.emplace_back(outpoint);
      45                 :             :         }
      46                 :             :     }
      47                 :             :     // Ensure txid != wtxid
      48   [ +  -  +  - ]:         320 :     tx.vin[0].scriptWitness.stack.push_back({1});
      49         [ +  - ]:         160 :     tx.vout.resize(2);
      50         [ +  - ]:         160 :     tx.vout[0].nValue = CENT;
      51   [ +  -  +  -  :         160 :     tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
                   +  - ]
      52         [ +  - ]:         160 :     tx.vout[1].nValue = 3 * CENT;
      53   [ +  -  +  -  :         160 :     tx.vout[1].scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(key.GetPubKey()));
                   +  - ]
      54         [ +  - ]:         320 :     return MakeTransactionRef(tx);
      55                 :         160 : }
      56                 :             : 
      57                 :             : // Make another (not necessarily valid) tx with the same txid but different wtxid.
      58                 :           3 : static CTransactionRef MakeMutation(const CTransactionRef& ptx)
      59                 :             : {
      60                 :           3 :     CMutableTransaction tx(*ptx);
      61   [ +  -  +  - ]:           6 :     tx.vin[0].scriptWitness.stack.push_back({5});
      62         [ +  - ]:           3 :     auto mutated_tx = MakeTransactionRef(tx);
      63         [ -  + ]:           3 :     assert(ptx->GetHash() == mutated_tx->GetHash());
      64                 :           3 :     return mutated_tx;
      65                 :           3 : }
      66                 :             : 
      67                 :           4 : static bool EqualTxns(const std::set<CTransactionRef>& set_txns, const std::vector<CTransactionRef>& vec_txns)
      68                 :             : {
      69   [ -  +  +  - ]:           4 :     if (vec_txns.size() != set_txns.size()) return false;
      70         [ +  + ]:           9 :     for (const auto& tx : vec_txns) {
      71         [ +  - ]:           5 :         if (!set_txns.contains(tx)) return false;
      72                 :             :     }
      73                 :             :     return true;
      74                 :             : }
      75                 :             : 
      76   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(peer_dos_limits)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
      77                 :             : {
      78                 :           1 :     FastRandomContext det_rand{true};
      79                 :             : 
      80                 :             :     // Construct transactions to use. They must all be the same size.
      81                 :           1 :     static constexpr unsigned int NUM_TXNS_CREATED = 100;
      82                 :           1 :     static constexpr int64_t TX_SIZE{469};
      83                 :           1 :     static constexpr int64_t TOTAL_SIZE = NUM_TXNS_CREATED * TX_SIZE;
      84                 :             : 
      85                 :           1 :     std::vector<CTransactionRef> txns;
      86         [ +  - ]:           1 :     txns.reserve(NUM_TXNS_CREATED);
      87                 :             :     // All transactions are the same size.
      88         [ +  + ]:         101 :     for (unsigned int i{0}; i < NUM_TXNS_CREATED; ++i) {
      89         [ +  - ]:         100 :         auto ptx = MakeTransactionSpending({}, det_rand);
      90         [ +  - ]:         100 :         txns.emplace_back(ptx);
      91   [ +  -  +  -  :         100 :         BOOST_CHECK_EQUAL(TX_SIZE, GetTransactionWeight(*ptx));
                   +  - ]
      92                 :         100 :     }
      93                 :             : 
      94                 :             :     // Single peer: eviction is triggered if either limit is hit
      95                 :           1 :     {
      96                 :             :         // Test announcement limits
      97                 :           1 :         NodeId peer{8};
      98                 :           1 :         auto orphanage_low_ann = node::MakeTxOrphanage(/*max_global_latency_score=*/1, /*reserved_peer_usage=*/TX_SIZE * 10);
      99                 :           1 :         auto orphanage_low_mem = node::MakeTxOrphanage(/*max_global_latency_score=*/10, /*reserved_peer_usage=*/TX_SIZE);
     100                 :             : 
     101                 :             :         // Add the first transaction
     102   [ +  -  +  - ]:           1 :         orphanage_low_ann->AddTx(txns.at(0), peer);
     103   [ +  -  +  - ]:           1 :         orphanage_low_mem->AddTx(txns.at(0), peer);
     104                 :             : 
     105                 :             :         // Add more. One of the limits is exceeded, so LimitOrphans evicts 1.
     106   [ +  -  +  - ]:           1 :         orphanage_low_ann->AddTx(txns.at(1), peer);
     107   [ +  -  +  - ]:           1 :         orphanage_low_mem->AddTx(txns.at(1), peer);
     108                 :             : 
     109                 :             :         // The older transaction is evicted.
     110   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage_low_ann->HaveTx(txns.at(0)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     111   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage_low_mem->HaveTx(txns.at(0)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     112   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage_low_ann->HaveTx(txns.at(1)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     113   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage_low_mem->HaveTx(txns.at(1)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     114                 :             : 
     115         [ +  - ]:           1 :         orphanage_low_ann->SanityCheck();
     116         [ +  - ]:           1 :         orphanage_low_mem->SanityCheck();
     117                 :           1 :     }
     118                 :             : 
     119                 :             :     // Single peer: latency score includes inputs
     120                 :           1 :     {
     121                 :             :         // Test latency score limits
     122                 :           1 :         NodeId peer{10};
     123                 :           1 :         auto orphanage_low_ann = node::MakeTxOrphanage(/*max_global_latency_score=*/5, /*reserved_peer_usage=*/TX_SIZE * 1000);
     124                 :             : 
     125                 :             :         // Add the first transaction
     126   [ +  -  +  - ]:           1 :         orphanage_low_ann->AddTx(txns.at(0), peer);
     127                 :             : 
     128                 :             :         // Add 1 more transaction with 45 inputs. Even though there are only 2 announcements, this pushes the orphanage above its maximum latency score.
     129                 :           1 :         std::vector<COutPoint> outpoints_45;
     130         [ +  + ]:          46 :         for (unsigned int j{0}; j < 45; ++j) {
     131         [ +  - ]:          45 :             outpoints_45.emplace_back(Txid::FromUint256(det_rand.rand256()), j);
     132                 :             :         }
     133         [ +  - ]:           1 :         auto ptx = MakeTransactionSpending(outpoints_45, det_rand);
     134         [ +  - ]:           1 :         orphanage_low_ann->AddTx(ptx, peer);
     135                 :             : 
     136                 :             :         // The older transaction is evicted.
     137   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage_low_ann->HaveTx(txns.at(0)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     138   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage_low_ann->HaveTx(ptx->GetWitnessHash()));
             +  -  +  - ]
     139                 :             : 
     140         [ +  - ]:           1 :         orphanage_low_ann->SanityCheck();
     141                 :           1 :     }
     142                 :             : 
     143                 :             :     // Single peer: eviction order is FIFO on non-reconsiderable, then reconsiderable orphans.
     144                 :           1 :     {
     145                 :             :         // Construct parent + child pairs
     146                 :           1 :         std::vector<CTransactionRef> parents;
     147                 :           1 :         std::vector<CTransactionRef> children;
     148         [ +  + ]:          11 :         for (unsigned int i{0}; i < 10; ++i) {
     149         [ +  - ]:          10 :             CTransactionRef parent = MakeTransactionSpending({}, det_rand);
     150   [ +  -  +  -  :          20 :             CTransactionRef child = MakeTransactionSpending({{parent->GetHash(), 0}}, det_rand);
                   +  - ]
     151         [ +  - ]:          10 :             parents.emplace_back(parent);
     152         [ +  - ]:          10 :             children.emplace_back(child);
     153         [ +  - ]:          20 :         }
     154                 :             : 
     155                 :             :         // Test announcement limits
     156                 :           1 :         NodeId peer{9};
     157                 :           1 :         auto orphanage = node::MakeTxOrphanage(/*max_global_latency_score=*/3, /*reserved_peer_usage=*/TX_SIZE * 10);
     158                 :             : 
     159                 :             :         // First add a tx which will be made reconsiderable.
     160   [ +  -  +  - ]:           1 :         orphanage->AddTx(children.at(0), peer);
     161                 :             : 
     162                 :             :         // Then add 2 more orphans... not oversize yet.
     163   [ +  -  +  - ]:           1 :         orphanage->AddTx(children.at(1), peer);
     164   [ +  -  +  - ]:           1 :         orphanage->AddTx(children.at(2), peer);
     165                 :             : 
     166                 :             :         // Make child0 ready to reconsider
     167   [ +  -  +  - ]:           1 :         const std::vector<std::pair<Wtxid, NodeId>> expected_set_c0{std::make_pair(children.at(0)->GetWitnessHash(), peer)};
     168   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddChildrenToWorkSet(*parents.at(0), det_rand) == expected_set_c0);
          +  -  +  -  +  
                      - ]
     169   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTxToReconsider(peer));
             +  -  +  - ]
     170                 :             : 
     171                 :             :         // Add 1 more orphan, causing the orphanage to be oversize. child1 is evicted.
     172   [ +  -  +  - ]:           1 :         orphanage->AddTx(children.at(3), peer);
     173   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(0)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     174   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->HaveTx(children.at(1)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     175   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(2)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     176   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     177         [ +  - ]:           1 :         orphanage->SanityCheck();
     178                 :             : 
     179                 :             :         // Add 1 more... child2 is evicted.
     180   [ +  -  +  - ]:           1 :         orphanage->AddTx(children.at(4), peer);
     181   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(0)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     182   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->HaveTx(children.at(2)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     183   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     184   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(4)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     185                 :             : 
     186                 :             :         // Eviction order is FIFO within the orphans that are read
     187   [ +  -  +  - ]:           1 :         const std::vector<std::pair<Wtxid, NodeId>> expected_set_c4{std::make_pair(children.at(4)->GetWitnessHash(), peer)};
     188   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddChildrenToWorkSet(*parents.at(4), det_rand) == expected_set_c4);
          +  -  +  -  +  
                      - ]
     189   [ +  -  +  - ]:           1 :         const std::vector<std::pair<Wtxid, NodeId>> expected_set_c3{std::make_pair(children.at(3)->GetWitnessHash(), peer)};
     190   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddChildrenToWorkSet(*parents.at(3), det_rand) == expected_set_c3);
          +  -  +  -  +  
                      - ]
     191                 :             : 
     192                 :             :         // child5 is evicted immediately because it is the only non-reconsiderable orphan.
     193   [ +  -  +  - ]:           1 :         orphanage->AddTx(children.at(5), peer);
     194   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(0)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     195   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     196   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(4)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     197   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->HaveTx(children.at(5)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     198                 :             : 
     199                 :             :         // Transactions are marked non-reconsiderable again when returned through GetTxToReconsider
     200   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(peer), children.at(0));
          +  -  +  -  +  
                      - ]
     201   [ +  -  +  - ]:           1 :         orphanage->AddTx(children.at(6), peer);
     202   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->HaveTx(children.at(0)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     203   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     204   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(4)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     205   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(children.at(6)->GetWitnessHash()));
          +  -  +  -  +  
                      - ]
     206                 :             : 
     207                 :             :         // The first transaction returned from GetTxToReconsider is the older one, not the one that was marked for
     208                 :             :         // reconsideration earlier.
     209   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(peer), children.at(3));
          +  -  +  -  +  
                      - ]
     210   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(peer), children.at(4));
          +  -  +  -  +  
                      - ]
     211                 :             : 
     212         [ +  - ]:           1 :         orphanage->SanityCheck();
     213                 :           1 :     }
     214                 :             : 
     215                 :             :     // Multiple peers: when limit is exceeded, we choose the DoSiest peer and evict their oldest transaction.
     216                 :           1 :     {
     217                 :           1 :         NodeId peer_dosy{0};
     218                 :           1 :         NodeId peer1{1};
     219                 :           1 :         NodeId peer2{2};
     220                 :             : 
     221                 :           1 :         unsigned int max_announcements = 60;
     222                 :             :         // Set a high per-peer reservation so announcement limit is always hit first.
     223                 :           1 :         auto orphanage = node::MakeTxOrphanage(max_announcements, TOTAL_SIZE * 10);
     224                 :             : 
     225                 :             :         // No evictions happen before the global limit is reached.
     226         [ +  + ]:          61 :         for (unsigned int i{0}; i < max_announcements; ++i) {
     227   [ +  -  +  - ]:          60 :             orphanage->AddTx(txns.at(i), peer_dosy);
     228                 :             :         }
     229         [ +  - ]:           1 :         orphanage->SanityCheck();
     230   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_dosy), max_announcements);
                   +  - ]
     231   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer1), 0);
                   +  - ]
     232   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer2), 0);
                   +  - ]
     233                 :             : 
     234                 :             :         // Add 10 unique transactions from peer1.
     235                 :             :         // LimitOrphans should evict from peer_dosy, because that's the one exceeding announcement limits.
     236                 :           1 :         unsigned int num_from_peer1 = 10;
     237         [ +  + ]:          11 :         for (unsigned int i{0}; i < num_from_peer1; ++i) {
     238   [ +  -  +  - ]:          10 :             orphanage->AddTx(txns.at(max_announcements + i), peer1);
     239                 :             :             // The announcement limit per peer has halved, but LimitOrphans does not evict beyond what is necessary to
     240                 :             :             // bring the total announcements within its global limit.
     241   [ +  -  +  -  :          20 :             BOOST_CHECK(orphanage->AnnouncementsFromPeer(peer_dosy) > orphanage->MaxPeerLatencyScore());
          +  -  +  -  +  
                      - ]
     242                 :             : 
     243   [ +  -  +  -  :          10 :             BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer1), i + 1);
                   +  - ]
     244   [ +  -  +  -  :          10 :             BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_dosy), max_announcements - i - 1);
                   +  - ]
     245                 :             : 
     246                 :             :             // Evictions are FIFO within a peer, so the ith transaction sent by peer_dosy is the one that was evicted.
     247   [ +  -  +  -  :          20 :             BOOST_CHECK(!orphanage->HaveTx(txns.at(i)->GetWitnessHash()));
             +  -  +  - ]
     248                 :             :         }
     249                 :             :         // Add 10 transactions that are duplicates of the ones sent by peer_dosy. We need to add 10 because the first 10
     250                 :             :         // were just evicted in the previous block additions.
     251         [ +  + ]:          11 :         for (unsigned int i{num_from_peer1}; i < num_from_peer1 + 10; ++i) {
     252                 :             :             // Tx has already been sent by peer_dosy
     253   [ +  -  +  -  :          20 :             BOOST_CHECK(orphanage->HaveTxFromPeer(txns.at(i)->GetWitnessHash(), peer_dosy));
          +  -  +  -  +  
                      - ]
     254   [ +  -  +  - ]:          10 :             orphanage->AddTx(txns.at(i), peer2);
     255                 :             : 
     256                 :             :             // peer_dosy is still the only one getting evicted
     257   [ +  -  +  -  :          10 :             BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_dosy), max_announcements - i - 1);
                   +  - ]
     258   [ +  -  +  -  :          10 :             BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer1), num_from_peer1);
                   +  - ]
     259   [ +  -  +  -  :          10 :             BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer2), i + 1 - num_from_peer1);
                   +  - ]
     260                 :             : 
     261                 :             :             // Evictions are FIFO within a peer, so the ith transaction sent by peer_dosy is the one that was evicted.
     262   [ +  -  +  -  :          20 :             BOOST_CHECK(!orphanage->HaveTxFromPeer(txns.at(i)->GetWitnessHash(), peer_dosy));
          +  -  +  -  +  
                      - ]
     263   [ +  -  +  -  :          20 :             BOOST_CHECK(orphanage->HaveTx(txns.at(i)->GetWitnessHash()));
             +  -  +  - ]
     264                 :             :         }
     265                 :             : 
     266                 :             :         // With 6 peers, each can add 10, and still only peer_dosy's orphans are evicted.
     267                 :           1 :         const unsigned int max_per_peer{max_announcements / 6};
     268         [ +  - ]:           1 :         const unsigned int num_announcements{orphanage->CountAnnouncements()};
     269         [ +  + ]:           4 :         for (NodeId peer{3}; peer < 6; ++peer) {
     270         [ +  + ]:          33 :             for (unsigned int i{0}; i < max_per_peer; ++i) {
     271                 :             :                 // Each addition causes 1 eviction.
     272   [ +  -  +  - ]:          30 :                 orphanage->AddTx(txns.at(peer * max_per_peer + i), peer);
     273   [ +  -  +  -  :          30 :                 BOOST_CHECK_EQUAL(orphanage->CountAnnouncements(), num_announcements);
                   +  - ]
     274                 :             :             }
     275                 :             :         }
     276         [ +  + ]:           7 :         for (NodeId peer{0}; peer < 6; ++peer) {
     277   [ +  -  +  -  :           6 :             BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer), max_per_peer);
                   +  - ]
     278                 :             :         }
     279         [ +  - ]:           1 :         orphanage->SanityCheck();
     280                 :           1 :     }
     281                 :             : 
     282                 :             :     // Limits change as more peers are added.
     283                 :           1 :     {
     284                 :           1 :         auto orphanage{node::MakeTxOrphanage()};
     285                 :             :         // These stay the same regardless of number of peers
     286   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     287   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     288                 :             : 
     289                 :             :         // These change with number of peers
     290   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     291   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     292                 :             : 
     293                 :             :         // Number of peers = 1
     294   [ +  -  +  - ]:           1 :         orphanage->AddTx(txns.at(0), 0);
     295   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     296   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     297   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     298   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     299                 :             : 
     300                 :             :         // Number of peers = 2
     301   [ +  -  +  - ]:           1 :         orphanage->AddTx(txns.at(1), 1);
     302   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     303   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     304   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 2);
                   +  - ]
     305   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 2);
                   +  - ]
     306                 :             : 
     307                 :             :         // Number of peers = 3
     308   [ +  -  +  - ]:           1 :         orphanage->AddTx(txns.at(2), 2);
     309   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     310   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     311   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 3);
                   +  - ]
     312   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 3);
                   +  - ]
     313                 :             : 
     314                 :             :         // Number of peers didn't change.
     315   [ +  -  +  - ]:           1 :         orphanage->AddTx(txns.at(3), 2);
     316   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     317   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     318   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 3);
                   +  - ]
     319   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 3);
                   +  - ]
     320                 :             : 
     321                 :             :         // Once a peer has no orphans, it is not considered in the limits.
     322                 :             :         // Number of peers = 2
     323         [ +  - ]:           1 :         orphanage->EraseForPeer(2);
     324   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     325   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     326   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER * 2);
                   +  - ]
     327   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE / 2);
                   +  - ]
     328                 :             : 
     329                 :             :         // Number of peers = 1
     330   [ +  -  +  - ]:           1 :         orphanage->EraseTx(txns.at(0)->GetWitnessHash());
     331   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     332   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     333   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
                   +  - ]
     334   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
                   +  - ]
     335                 :             : 
     336         [ +  - ]:           1 :         orphanage->SanityCheck();
     337                 :           1 :     }
     338                 :             : 
     339                 :             :     // Test eviction of multiple transactions at a time
     340                 :           1 :     {
     341                 :             :         // Create a large transaction that is 10 times larger than the normal size transaction.
     342         [ +  - ]:           1 :         CMutableTransaction tx_large;
     343         [ +  - ]:           1 :         tx_large.vin.resize(1);
     344         [ +  - ]:           1 :         BulkTransaction(tx_large, 10 * TX_SIZE);
     345         [ +  - ]:           1 :         auto ptx_large = MakeTransactionRef(tx_large);
     346                 :             : 
     347                 :           1 :         const auto large_tx_size = GetTransactionWeight(*ptx_large);
     348   [ +  -  +  -  :           2 :         BOOST_CHECK(large_tx_size > 10 * TX_SIZE);
                   +  - ]
     349   [ +  -  +  - ]:           2 :         BOOST_CHECK(large_tx_size < 11 * TX_SIZE);
     350                 :             : 
     351                 :           1 :         auto orphanage = node::MakeTxOrphanage(20, large_tx_size);
     352                 :             :         // One peer sends 10 normal size transactions. The other peer sends 10 normal transactions and 1 very large one
     353                 :           1 :         NodeId peer_normal{0};
     354                 :           1 :         NodeId peer_large{1};
     355         [ +  + ]:          21 :         for (unsigned int i = 0; i < 20; i++) {
     356   [ +  +  +  -  :          30 :             orphanage->AddTx(txns.at(i), i < 10 ? peer_normal : peer_large);
                   +  - ]
     357                 :             :         }
     358   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->TotalLatencyScore() <= orphanage->MaxGlobalLatencyScore());
          +  -  +  -  +  
                      - ]
     359   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->TotalOrphanUsage() <= orphanage->MaxGlobalUsage());
          +  -  +  -  +  
                      - ]
     360                 :             : 
     361                 :             :         // Add the large transaction. This should cause evictions of all the previous 10 transactions from that peer.
     362         [ +  - ]:           1 :         orphanage->AddTx(ptx_large, peer_large);
     363                 :             : 
     364                 :             :         // peer_normal should still have 10 transactions, and peer_large should have 1.
     365   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_normal), 10);
                   +  - ]
     366   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_large), 1);
                   +  - ]
     367   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTxFromPeer(ptx_large->GetWitnessHash(), peer_large));
             +  -  +  - ]
     368   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountAnnouncements(), 11);
                   +  - ]
     369                 :             : 
     370         [ +  - ]:           1 :         orphanage->SanityCheck();
     371         [ +  - ]:           2 :     }
     372                 :             : 
     373                 :             :     // Test that latency score includes number of inputs.
     374                 :           1 :     {
     375                 :           1 :         auto orphanage = node::MakeTxOrphanage();
     376                 :             : 
     377                 :             :         // Add 10 transactions with 9 inputs each.
     378                 :           1 :         std::vector<COutPoint> outpoints_9;
     379         [ +  + ]:          10 :         for (unsigned int j{0}; j < 9; ++j) {
     380         [ +  - ]:           9 :             outpoints_9.emplace_back(Txid::FromUint256(m_rng.rand256()), j);
     381                 :             :         }
     382         [ +  + ]:          11 :         for (unsigned int i{0}; i < 10; ++i) {
     383         [ +  - ]:          10 :             auto ptx = MakeTransactionSpending(outpoints_9, m_rng);
     384         [ +  - ]:          10 :             orphanage->AddTx(ptx, 0);
     385                 :          10 :         }
     386   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountAnnouncements(), 10);
                   +  - ]
     387   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->TotalLatencyScore(), 10);
                   +  - ]
     388                 :             : 
     389                 :             :         // Add 10 transactions with 50 inputs each.
     390                 :           1 :         std::vector<COutPoint> outpoints_50;
     391         [ +  + ]:          51 :         for (unsigned int j{0}; j < 50; ++j) {
     392         [ +  - ]:          50 :             outpoints_50.emplace_back(Txid::FromUint256(m_rng.rand256()), j);
     393                 :             :         }
     394                 :             : 
     395         [ +  + ]:          11 :         for (unsigned int i{0}; i < 10; ++i) {
     396         [ +  - ]:          10 :             CMutableTransaction tx;
     397                 :          10 :             std::shuffle(outpoints_50.begin(), outpoints_50.end(), m_rng);
     398         [ +  - ]:          10 :             auto ptx = MakeTransactionSpending(outpoints_50, m_rng);
     399   [ +  -  +  -  :          20 :             BOOST_CHECK(orphanage->AddTx(ptx, 0));
             +  -  +  + ]
     400   [ +  +  +  -  :          15 :             if (i < 5) BOOST_CHECK(!orphanage->AddTx(ptx, 1));
             +  -  +  - ]
     401                 :          20 :         }
     402                 :             :         // 10 of the 9-input transactions + 10 of the 50-input transactions + 5 more announcements of the 50-input transactions
     403   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountAnnouncements(), 25);
                   +  - ]
     404                 :             :         // Base of 25 announcements, plus 10 * 5 for the 50-input transactions (counted just once)
     405   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->TotalLatencyScore(), 25 + 50);
                   +  - ]
     406                 :             : 
     407                 :             :         // Peer 0 sent all 20 transactions
     408   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(0), 20);
                   +  - ]
     409   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->LatencyScoreFromPeer(0), 20 + 10 * 5);
                   +  - ]
     410                 :             : 
     411                 :             :         // Peer 1 sent 5 of the 10 transactions with many inputs
     412   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(1), 5);
                   +  - ]
     413   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->LatencyScoreFromPeer(1), 5 + 5 * 5);
                   +  - ]
     414                 :             : 
     415         [ +  - ]:           1 :         orphanage->SanityCheck();
     416                 :           1 :     }
     417                 :           1 : }
     418   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     419                 :             : {
     420                 :             :     // This test had non-deterministic coverage due to
     421                 :             :     // randomly selected seeds.
     422                 :             :     // This seed is chosen so that all branches of the function
     423                 :             :     // ecdsa_signature_parse_der_lax are executed during this test.
     424                 :             :     // Specifically branches that run only when an ECDSA
     425                 :             :     // signature's R and S values have leading zeros.
     426                 :           1 :     m_rng.Reseed(uint256{33});
     427                 :             : 
     428                 :           1 :     std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};
     429                 :           1 :     CKey key;
     430         [ +  - ]:           1 :     MakeNewKeyWithFastRandomContext(key, m_rng);
     431                 :           1 :     FillableSigningProvider keystore;
     432   [ +  -  +  -  :           2 :     BOOST_CHECK(keystore.AddKey(key));
                   +  - ]
     433                 :             : 
     434                 :             :     // Freeze time for length of test
     435                 :           1 :     auto now{GetTime<std::chrono::seconds>()};
     436         [ +  - ]:           1 :     SetMockTime(now);
     437                 :             : 
     438                 :           1 :     std::vector<CTransactionRef> orphans_added;
     439                 :             : 
     440                 :             :     // 50 orphan transactions:
     441         [ +  + ]:          51 :     for (int i = 0; i < 50; i++)
     442                 :             :     {
     443         [ +  - ]:          50 :         CMutableTransaction tx;
     444         [ +  - ]:          50 :         tx.vin.resize(1);
     445                 :          50 :         tx.vin[0].prevout.n = 0;
     446         [ +  - ]:          50 :         tx.vin[0].prevout.hash = Txid::FromUint256(m_rng.rand256());
     447         [ +  - ]:          50 :         tx.vin[0].scriptSig << OP_1;
     448         [ +  - ]:          50 :         tx.vout.resize(1);
     449         [ +  - ]:          50 :         tx.vout[0].nValue = i*CENT;
     450   [ +  -  +  -  :          50 :         tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
                   +  - ]
     451                 :             : 
     452         [ +  - ]:          50 :         auto ptx = MakeTransactionRef(tx);
     453         [ +  - ]:          50 :         orphanage->AddTx(ptx, i);
     454         [ +  - ]:          50 :         orphans_added.emplace_back(ptx);
     455                 :         100 :     }
     456                 :             : 
     457                 :             :     // ... and 50 that depend on other orphans:
     458         [ +  + ]:          51 :     for (int i = 0; i < 50; i++)
     459                 :             :     {
     460   [ -  +  +  - ]:          50 :         const auto& txPrev = orphans_added[m_rng.randrange(orphans_added.size())];
     461                 :             : 
     462         [ +  - ]:          50 :         CMutableTransaction tx;
     463         [ +  - ]:          50 :         tx.vin.resize(1);
     464         [ +  - ]:          50 :         tx.vin[0].prevout.n = 0;
     465         [ +  - ]:          50 :         tx.vin[0].prevout.hash = txPrev->GetHash();
     466         [ +  - ]:          50 :         tx.vout.resize(1);
     467         [ +  - ]:          50 :         tx.vout[0].nValue = i*CENT;
     468   [ +  -  +  -  :          50 :         tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
                   +  - ]
     469                 :          50 :         SignatureData empty;
     470   [ +  -  +  -  :         100 :         BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
             +  -  +  - ]
     471                 :             : 
     472         [ +  - ]:          50 :         auto ptx = MakeTransactionRef(tx);
     473         [ +  - ]:          50 :         orphanage->AddTx(ptx, i);
     474         [ +  - ]:          50 :         orphans_added.emplace_back(ptx);
     475                 :         100 :     }
     476                 :             : 
     477                 :             :     // This really-big orphan should be ignored:
     478         [ +  + ]:          11 :     for (int i = 0; i < 10; i++)
     479                 :             :     {
     480   [ -  +  +  - ]:          10 :         const auto& txPrev = orphans_added[m_rng.randrange(orphans_added.size())];
     481                 :             : 
     482         [ +  - ]:          10 :         CMutableTransaction tx;
     483         [ +  - ]:          10 :         tx.vout.resize(1);
     484         [ +  - ]:          10 :         tx.vout[0].nValue = 1*CENT;
     485   [ +  -  +  -  :          10 :         tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
                   +  - ]
     486         [ +  - ]:          10 :         tx.vin.resize(2777);
     487   [ -  +  +  + ]:       27780 :         for (unsigned int j = 0; j < tx.vin.size(); j++)
     488                 :             :         {
     489                 :       27770 :             tx.vin[j].prevout.n = j;
     490                 :       27770 :             tx.vin[j].prevout.hash = txPrev->GetHash();
     491                 :             :         }
     492                 :          10 :         SignatureData empty;
     493   [ +  -  +  -  :          20 :         BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
                   +  - ]
     494                 :             :         // Reuse same signature for other inputs
     495                 :             :         // (they don't have to be valid for this test)
     496   [ -  +  +  + ]:       27770 :         for (unsigned int j = 1; j < tx.vin.size(); j++)
     497                 :       27760 :             tx.vin[j].scriptSig = tx.vin[0].scriptSig;
     498                 :             : 
     499   [ +  -  +  -  :          40 :         BOOST_CHECK(!orphanage->AddTx(MakeTransactionRef(tx), i));
          +  -  +  -  +  
                      - ]
     500                 :          20 :     }
     501                 :             : 
     502         [ +  - ]:           1 :     size_t expected_num_orphans = orphanage->CountUniqueOrphans();
     503                 :             : 
     504                 :             :     // Non-existent peer; nothing should be deleted
     505         [ +  - ]:           1 :     orphanage->EraseForPeer(/*peer=*/-1);
     506   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_num_orphans);
                   +  - ]
     507                 :             : 
     508                 :             :     // Each of first three peers stored
     509                 :             :     // two transactions each.
     510         [ +  + ]:           4 :     for (NodeId i = 0; i < 3; i++)
     511                 :             :     {
     512         [ +  - ]:           3 :         orphanage->EraseForPeer(i);
     513                 :           3 :         expected_num_orphans -= 2;
     514   [ +  -  +  -  :           3 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_num_orphans);
                   +  - ]
     515                 :             :     }
     516                 :           1 : }
     517                 :             : 
     518   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(same_txid_diff_witness)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     519                 :             : {
     520                 :           1 :     FastRandomContext det_rand{true};
     521                 :           1 :     std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};
     522                 :           1 :     NodeId peer{0};
     523                 :             : 
     524                 :           1 :     std::vector<COutPoint> empty_outpoints;
     525         [ +  - ]:           1 :     auto parent = MakeTransactionSpending(empty_outpoints, det_rand);
     526                 :             : 
     527                 :             :     // Create children to go into orphanage.
     528   [ +  -  +  -  :           2 :     auto child_normal = MakeTransactionSpending({{parent->GetHash(), 0}}, det_rand);
                   +  - ]
     529         [ +  - ]:           1 :     auto child_mutated = MakeMutation(child_normal);
     530                 :             : 
     531         [ +  - ]:           1 :     const auto& normal_wtxid = child_normal->GetWitnessHash();
     532                 :           1 :     const auto& mutated_wtxid = child_mutated->GetWitnessHash();
     533   [ +  -  +  -  :           2 :     BOOST_CHECK(normal_wtxid != mutated_wtxid);
                   +  - ]
     534                 :             : 
     535   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->AddTx(child_normal, peer));
             +  -  +  - ]
     536                 :             :     // EraseTx fails as transaction by this wtxid doesn't exist.
     537   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(orphanage->EraseTx(mutated_wtxid), 0);
                   +  - ]
     538   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->HaveTx(normal_wtxid));
             +  -  +  - ]
     539   [ +  -  +  -  :           3 :     BOOST_CHECK(orphanage->GetTx(normal_wtxid) == child_normal);
          +  -  +  -  +  
                      - ]
     540   [ +  -  +  -  :           2 :     BOOST_CHECK(!orphanage->HaveTx(mutated_wtxid));
             +  -  +  - ]
     541   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->GetTx(mutated_wtxid) == nullptr);
          +  -  -  +  +  
                      - ]
     542                 :             : 
     543                 :             :     // Must succeed. Both transactions should be present in orphanage.
     544   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->AddTx(child_mutated, peer));
             +  -  +  - ]
     545   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->HaveTx(normal_wtxid));
             +  -  +  - ]
     546   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->HaveTx(mutated_wtxid));
             +  -  +  - ]
     547                 :             : 
     548                 :             :     // Outpoints map should track all entries: check that both are returned as children of the parent.
     549   [ +  +  +  -  :           3 :     std::set<CTransactionRef> expected_children{child_normal, child_mutated};
             -  -  -  - ]
     550   [ +  -  +  -  :           2 :     BOOST_CHECK(EqualTxns(expected_children, orphanage->GetChildrenFromSamePeer(parent, peer)));
             +  -  +  - ]
     551                 :             : 
     552                 :             :     // Erase by wtxid: mutated first
     553   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(orphanage->EraseTx(mutated_wtxid), 1);
                   +  - ]
     554   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->HaveTx(normal_wtxid));
             +  -  +  - ]
     555   [ +  -  +  -  :           2 :     BOOST_CHECK(!orphanage->HaveTx(mutated_wtxid));
             +  -  +  - ]
     556                 :             : 
     557   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(orphanage->EraseTx(normal_wtxid), 1);
                   +  - ]
     558   [ +  -  +  -  :           2 :     BOOST_CHECK(!orphanage->HaveTx(normal_wtxid));
             +  -  +  - ]
     559   [ +  -  +  -  :           2 :     BOOST_CHECK(!orphanage->HaveTx(mutated_wtxid));
                   +  - ]
     560   [ +  -  +  -  :           7 : }
          -  +  +  -  +  
                -  +  - ]
     561                 :             : 
     562                 :             : 
     563   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(get_children)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     564                 :             : {
     565                 :           1 :     FastRandomContext det_rand{true};
     566                 :           1 :     std::vector<COutPoint> empty_outpoints;
     567                 :             : 
     568         [ +  - ]:           1 :     auto parent1 = MakeTransactionSpending(empty_outpoints, det_rand);
     569         [ +  - ]:           1 :     auto parent2 = MakeTransactionSpending(empty_outpoints, det_rand);
     570                 :             : 
     571                 :             :     // Make sure these parents have different txids otherwise this test won't make sense.
     572         [ -  + ]:           1 :     while (parent1->GetHash() == parent2->GetHash()) {
     573   [ #  #  #  # ]:           0 :         parent2 = MakeTransactionSpending(empty_outpoints, det_rand);
     574                 :             :     }
     575                 :             : 
     576                 :             :     // Create children to go into orphanage.
     577   [ +  -  +  -  :           2 :     auto child_p1n0 = MakeTransactionSpending({{parent1->GetHash(), 0}}, det_rand);
                   +  - ]
     578   [ +  -  +  -  :           2 :     auto child_p2n1 = MakeTransactionSpending({{parent2->GetHash(), 1}}, det_rand);
                   +  - ]
     579                 :             :     // Spends the same tx twice. Should not cause duplicates.
     580   [ +  -  +  -  :           2 :     auto child_p1n0_p1n1 = MakeTransactionSpending({{parent1->GetHash(), 0}, {parent1->GetHash(), 1}}, det_rand);
                   +  - ]
     581                 :             :     // Spends the same outpoint as previous tx. Should still be returned; don't assume outpoints are unique.
     582   [ +  -  +  - ]:           2 :     auto child_p1n0_p2n0 = MakeTransactionSpending({{parent1->GetHash(), 0}, {parent2->GetHash(), 0}}, det_rand);
     583                 :             : 
     584                 :           1 :     const NodeId node0{0};
     585                 :           1 :     const NodeId node1{1};
     586                 :           1 :     const NodeId node2{2};
     587                 :           1 :     const NodeId node3{3};
     588                 :             : 
     589                 :             :     // All orphans provided by node1
     590                 :           1 :     {
     591                 :           1 :         auto orphanage{node::MakeTxOrphanage()};
     592   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p1n0, node1));
             +  -  +  - ]
     593   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p2n1, node1));
             +  -  +  - ]
     594   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p1n0_p1n1, node1));
             +  -  +  - ]
     595   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p1n0_p2n0, node1));
             +  -  +  - ]
     596                 :             : 
     597                 :             :         // Also add some other announcers for the same transactions
     598   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(child_p1n0_p1n1, node0));
             +  -  +  - ]
     599   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(child_p2n1, node0));
             +  -  +  - ]
     600   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(child_p1n0, node3));
             +  -  +  - ]
     601                 :             : 
     602                 :             : 
     603   [ +  +  +  -  :           4 :         std::vector<CTransactionRef> expected_parent1_children{child_p1n0_p2n0, child_p1n0_p1n1, child_p1n0};
             -  -  -  - ]
     604   [ +  +  +  -  :           3 :         std::vector<CTransactionRef> expected_parent2_children{child_p1n0_p2n0, child_p2n1};
             -  -  -  - ]
     605                 :             : 
     606   [ +  -  +  -  :           2 :         BOOST_CHECK(expected_parent1_children == orphanage->GetChildrenFromSamePeer(parent1, node1));
             +  -  +  - ]
     607   [ +  -  +  -  :           2 :         BOOST_CHECK(expected_parent2_children == orphanage->GetChildrenFromSamePeer(parent2, node1));
             +  -  +  - ]
     608                 :             : 
     609                 :             :         // The peer must match
     610   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->GetChildrenFromSamePeer(parent1, node2).empty());
             +  -  +  - ]
     611   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->GetChildrenFromSamePeer(parent2, node2).empty());
             +  -  +  - ]
     612                 :             : 
     613                 :             :         // There shouldn't be any children of this tx in the orphanage
     614   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->GetChildrenFromSamePeer(child_p1n0_p2n0, node1).empty());
             +  -  +  - ]
     615   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->GetChildrenFromSamePeer(child_p1n0_p2n0, node2).empty());
                   +  - ]
     616                 :           1 :     }
     617                 :             : 
     618                 :             :     // Orphans provided by node1 and node2
     619                 :           1 :     {
     620                 :           1 :         std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};
     621   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p1n0, node1));
             +  -  +  - ]
     622   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p2n1, node1));
             +  -  +  - ]
     623   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p1n0_p1n1, node2));
             +  -  +  - ]
     624   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(child_p1n0_p2n0, node2));
             +  -  +  - ]
     625                 :             : 
     626                 :             :         // +----------------+---------------+----------------------------------+
     627                 :             :         // |                | sender=node1  |           sender=node2           |
     628                 :             :         // +----------------+---------------+----------------------------------+
     629                 :             :         // | spends parent1 | child_p1n0    | child_p1n0_p1n1, child_p1n0_p2n0 |
     630                 :             :         // | spends parent2 | child_p2n1    | child_p1n0_p2n0                  |
     631                 :             :         // +----------------+---------------+----------------------------------+
     632                 :             : 
     633                 :             :         // Children of parent1 from node1:
     634                 :           1 :         {
     635   [ +  +  +  -  :           2 :             std::set<CTransactionRef> expected_parent1_node1{child_p1n0};
             -  -  -  - ]
     636                 :             : 
     637   [ +  -  +  -  :           2 :             BOOST_CHECK_EQUAL(orphanage->GetChildrenFromSamePeer(parent1, node1).size(), 1);
                   +  - ]
     638   [ +  -  +  -  :           2 :             BOOST_CHECK(orphanage->HaveTxFromPeer(child_p1n0->GetWitnessHash(), node1));
             +  -  +  - ]
     639   [ +  -  +  -  :           2 :             BOOST_CHECK(EqualTxns(expected_parent1_node1, orphanage->GetChildrenFromSamePeer(parent1, node1)));
                   +  - ]
     640                 :           0 :         }
     641                 :             : 
     642                 :             :         // Children of parent2 from node1:
     643                 :           1 :         {
     644   [ +  +  +  -  :           2 :             std::set<CTransactionRef> expected_parent2_node1{child_p2n1};
             -  -  -  - ]
     645                 :             : 
     646   [ +  -  +  -  :           2 :             BOOST_CHECK(EqualTxns(expected_parent2_node1, orphanage->GetChildrenFromSamePeer(parent2, node1)));
                   +  - ]
     647                 :           0 :         }
     648                 :             : 
     649                 :             :         // Children of parent1 from node2: newest returned first.
     650                 :           1 :         {
     651   [ +  +  +  -  :           3 :             std::vector<CTransactionRef> expected_parent1_node2{child_p1n0_p2n0, child_p1n0_p1n1};
             -  -  -  - ]
     652   [ +  -  +  -  :           2 :             BOOST_CHECK(orphanage->HaveTxFromPeer(child_p1n0_p1n1->GetWitnessHash(), node2));
             +  -  +  - ]
     653   [ +  -  +  -  :           2 :             BOOST_CHECK(orphanage->HaveTxFromPeer(child_p1n0_p2n0->GetWitnessHash(), node2));
             +  -  +  - ]
     654   [ +  -  +  -  :           2 :             BOOST_CHECK(expected_parent1_node2 == orphanage->GetChildrenFromSamePeer(parent1, node2));
                   +  - ]
     655                 :           1 :         }
     656                 :             : 
     657                 :             :         // Children of parent2 from node2:
     658                 :           1 :         {
     659   [ +  +  +  -  :           2 :             std::set<CTransactionRef> expected_parent2_node2{child_p1n0_p2n0};
             -  -  -  - ]
     660                 :             : 
     661   [ +  -  +  -  :           2 :             BOOST_CHECK_EQUAL(1, orphanage->GetChildrenFromSamePeer(parent2, node2).size());
                   +  - ]
     662   [ +  -  +  -  :           2 :             BOOST_CHECK(orphanage->HaveTxFromPeer(child_p1n0_p2n0->GetWitnessHash(), node2));
             +  -  +  - ]
     663   [ +  -  +  -  :           2 :             BOOST_CHECK(EqualTxns(expected_parent2_node2, orphanage->GetChildrenFromSamePeer(parent2, node2)));
                   +  - ]
     664                 :           0 :         }
     665         [ +  - ]:           1 :     }
     666   [ +  -  +  -  :          22 : }
          +  -  -  +  +  
          -  +  -  -  +  
          +  -  -  +  +  
          -  -  +  +  -  
          +  -  -  +  +  
          -  -  +  +  -  
          +  -  +  -  +  
                -  +  - ]
     667                 :             : 
     668   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(too_large_orphan_tx)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     669                 :             : {
     670                 :           1 :     std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};
     671         [ +  - ]:           1 :     CMutableTransaction tx;
     672         [ +  - ]:           1 :     tx.vin.resize(1);
     673                 :             : 
     674                 :             :     // check that txs larger than MAX_STANDARD_TX_WEIGHT are not added to the orphanage
     675         [ +  - ]:           1 :     BulkTransaction(tx, MAX_STANDARD_TX_WEIGHT + 4);
     676   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(tx)), MAX_STANDARD_TX_WEIGHT + 4);
                   +  - ]
     677   [ +  -  +  -  :           4 :     BOOST_CHECK(!orphanage->AddTx(MakeTransactionRef(tx), 0));
          +  -  +  -  +  
                      - ]
     678                 :             : 
     679                 :           1 :     tx.vout.clear();
     680         [ +  - ]:           1 :     BulkTransaction(tx, MAX_STANDARD_TX_WEIGHT);
     681   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(tx)), MAX_STANDARD_TX_WEIGHT);
                   +  - ]
     682   [ +  -  +  -  :           4 :     BOOST_CHECK(orphanage->AddTx(MakeTransactionRef(tx), 0));
          +  -  +  -  +  
                      - ]
     683                 :           1 : }
     684                 :             : 
     685   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(process_block)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     686                 :             : {
     687                 :           1 :     FastRandomContext det_rand{true};
     688                 :           1 :     std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};
     689                 :             : 
     690                 :             :     // Create outpoints that will be spent by transactions in the block
     691                 :           1 :     std::vector<COutPoint> outpoints;
     692                 :           1 :     const uint32_t num_outpoints{6};
     693         [ +  - ]:           1 :     outpoints.reserve(num_outpoints);
     694         [ +  + ]:           7 :     for (uint32_t i{0}; i < num_outpoints; ++i) {
     695                 :             :         // All the hashes should be different, but change the n just in case.
     696         [ +  - ]:           6 :         outpoints.emplace_back(Txid::FromUint256(det_rand.rand256()), i);
     697                 :             :     }
     698                 :             : 
     699                 :           1 :     CBlock block;
     700                 :           1 :     const NodeId node{0};
     701                 :             : 
     702         [ +  - ]:           1 :     auto control_tx = MakeTransactionSpending({}, det_rand);
     703   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->AddTx(control_tx, node));
             +  -  +  - ]
     704                 :             : 
     705   [ +  -  +  -  :           2 :     auto bo_tx_same_txid = MakeTransactionSpending({outpoints.at(0)}, det_rand);
             +  -  +  - ]
     706   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->AddTx(bo_tx_same_txid, node));
             +  -  +  - ]
     707         [ +  - ]:           1 :     block.vtx.emplace_back(bo_tx_same_txid);
     708                 :             : 
     709                 :             :     // 2 transactions with the same txid but different witness
     710   [ +  -  +  -  :           2 :     auto b_tx_same_txid_diff_witness = MakeTransactionSpending({outpoints.at(1)}, det_rand);
             +  -  +  - ]
     711         [ +  - ]:           1 :     block.vtx.emplace_back(b_tx_same_txid_diff_witness);
     712                 :             : 
     713         [ +  - ]:           1 :     auto o_tx_same_txid_diff_witness = MakeMutation(b_tx_same_txid_diff_witness);
     714   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->AddTx(o_tx_same_txid_diff_witness, node));
             +  -  +  - ]
     715                 :             : 
     716                 :             :     // 2 different transactions that spend the same input.
     717   [ +  -  +  -  :           2 :     auto b_tx_conflict = MakeTransactionSpending({outpoints.at(2)}, det_rand);
             +  -  +  - ]
     718         [ +  - ]:           1 :     block.vtx.emplace_back(b_tx_conflict);
     719                 :             : 
     720   [ +  -  +  -  :           2 :     auto o_tx_conflict = MakeTransactionSpending({outpoints.at(2)}, det_rand);
             +  -  +  - ]
     721   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->AddTx(o_tx_conflict, node));
             +  -  +  - ]
     722                 :             : 
     723                 :             :     // 2 different transactions that have 1 overlapping input.
     724   [ +  -  +  -  :           2 :     auto b_tx_conflict_partial = MakeTransactionSpending({outpoints.at(3), outpoints.at(4)}, det_rand);
          +  -  +  -  +  
                      - ]
     725         [ +  - ]:           1 :     block.vtx.emplace_back(b_tx_conflict_partial);
     726                 :             : 
     727   [ +  -  +  -  :           2 :     auto o_tx_conflict_partial_2 = MakeTransactionSpending({outpoints.at(4), outpoints.at(5)}, det_rand);
          +  -  +  -  +  
                      - ]
     728   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->AddTx(o_tx_conflict_partial_2, node));
             +  -  +  - ]
     729                 :             : 
     730         [ +  - ]:           1 :     orphanage->EraseForBlock(block);
     731   [ +  -  +  -  :          17 :     for (const auto& expected_removed : {bo_tx_same_txid, o_tx_same_txid_diff_witness, o_tx_conflict, o_tx_conflict_partial_2}) {
          +  -  +  -  +  
             +  +  -  -  
                      - ]
     732         [ +  - ]:           4 :         const auto& expected_removed_wtxid = expected_removed->GetWitnessHash();
     733   [ +  -  +  -  :           8 :         BOOST_CHECK(!orphanage->HaveTx(expected_removed_wtxid));
                   +  - ]
     734   [ +  +  -  - ]:           5 :     }
     735                 :             :     // Only remaining tx is control_tx
     736   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), 1);
                   +  - ]
     737   [ +  -  +  -  :           2 :     BOOST_CHECK(orphanage->HaveTx(control_tx->GetWitnessHash()));
             +  -  +  - ]
     738   [ +  -  +  -  :           8 : }
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     739                 :             : 
     740   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(multiple_announcers)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     741                 :             : {
     742                 :           1 :     const NodeId node0{0};
     743                 :           1 :     const NodeId node1{1};
     744                 :           1 :     const NodeId node2{2};
     745                 :           1 :     size_t expected_total_count{0};
     746                 :           1 :     FastRandomContext det_rand{true};
     747                 :           1 :     std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};
     748                 :             : 
     749                 :             :     // Check accounting per peer.
     750                 :             :     // Check that EraseForPeer works with multiple announcers.
     751                 :           1 :     {
     752         [ +  - ]:           1 :         auto ptx = MakeTransactionSpending({}, det_rand);
     753         [ +  - ]:           1 :         const auto& wtxid = ptx->GetWitnessHash();
     754   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(ptx, node0));
             +  -  +  - ]
     755   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(wtxid));
             +  -  +  - ]
     756                 :           1 :         expected_total_count += 1;
     757   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     758                 :             : 
     759                 :             :         // Adding again should do nothing.
     760   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(ptx, node0));
             +  -  +  - ]
     761   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     762                 :             : 
     763                 :             :         // We can add another tx with the same txid but different witness.
     764         [ +  - ]:           1 :         auto ptx_mutated{MakeMutation(ptx)};
     765   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(ptx_mutated, node0));
             +  -  +  - ]
     766   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(ptx_mutated->GetWitnessHash()));
             +  -  +  - ]
     767                 :           1 :         expected_total_count += 1;
     768                 :             : 
     769   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(ptx, node0));
             +  -  +  - ]
     770                 :             : 
     771                 :             :         // Adding a new announcer should not change overall accounting.
     772   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddAnnouncer(ptx->GetWitnessHash(), node2));
             +  -  +  - ]
     773   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     774                 :             : 
     775                 :             :         // If we already have this announcer, AddAnnouncer returns false.
     776   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTxFromPeer(ptx->GetWitnessHash(), node2));
             +  -  +  - ]
     777   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddAnnouncer(ptx->GetWitnessHash(), node2));
             +  -  +  - ]
     778                 :             : 
     779                 :             :         // Same with using AddTx for an existing tx, which is equivalent to using AddAnnouncer
     780   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(ptx, node1));
             +  -  +  - ]
     781   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     782                 :             : 
     783                 :             :         // if EraseForPeer is called for an orphan with multiple announcers, the orphanage should only
     784                 :             :         // erase that peer from the announcers set.
     785         [ +  - ]:           1 :         orphanage->EraseForPeer(node0);
     786   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(ptx->GetWitnessHash()));
             +  -  +  - ]
     787   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->HaveTxFromPeer(ptx->GetWitnessHash(), node0));
             +  -  +  - ]
     788                 :             :         // node0 is the only one that announced ptx_mutated
     789   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->HaveTx(ptx_mutated->GetWitnessHash()));
             +  -  +  - ]
     790                 :           1 :         expected_total_count -= 1;
     791   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     792                 :             : 
     793                 :             :         // EraseForPeer should delete the orphan if it's the only announcer left.
     794         [ +  - ]:           1 :         orphanage->EraseForPeer(node1);
     795   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     796   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->HaveTx(ptx->GetWitnessHash()));
             +  -  +  - ]
     797         [ +  - ]:           1 :         orphanage->EraseForPeer(node2);
     798                 :           1 :         expected_total_count -= 1;
     799   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     800   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->HaveTx(ptx->GetWitnessHash()));
             +  -  +  - ]
     801         [ +  - ]:           1 :     }
     802                 :             : 
     803                 :             :     // Check that erasure for blocks removes for all peers.
     804                 :           1 :     {
     805                 :           1 :         CBlock block;
     806         [ +  - ]:           1 :         auto tx_block = MakeTransactionSpending({}, det_rand);
     807         [ +  - ]:           1 :         block.vtx.emplace_back(tx_block);
     808   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(tx_block, node0));
             +  -  +  - ]
     809   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(tx_block, node1));
             +  -  +  - ]
     810                 :             : 
     811                 :           1 :         expected_total_count += 1;
     812                 :             : 
     813   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
                   +  - ]
     814                 :             : 
     815         [ +  - ]:           1 :         orphanage->EraseForBlock(block);
     816                 :             : 
     817                 :           1 :         expected_total_count -= 1;
     818                 :             : 
     819   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);
             +  -  +  - ]
     820                 :           1 :     }
     821                 :           1 : }
     822   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(peer_worksets)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     823                 :             : {
     824                 :           1 :     const NodeId node0{0};
     825                 :           1 :     const NodeId node1{1};
     826                 :           1 :     const NodeId node2{2};
     827                 :           1 :     FastRandomContext det_rand{true};
     828                 :           1 :     std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};
     829                 :             :     // AddChildrenToWorkSet should pick an announcer randomly
     830                 :           1 :     {
     831         [ +  - ]:           1 :         auto tx_missing_parent = MakeTransactionSpending({}, det_rand);
     832   [ +  -  +  -  :           2 :         auto tx_orphan = MakeTransactionSpending({COutPoint{tx_missing_parent->GetHash(), 0}}, det_rand);
                   +  - ]
     833         [ +  - ]:           1 :         const auto& orphan_wtxid = tx_orphan->GetWitnessHash();
     834                 :             : 
     835                 :             :         // All 3 peers are announcers.
     836   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddTx(tx_orphan, node0));
             +  -  +  - ]
     837   [ +  -  +  -  :           2 :         BOOST_CHECK(!orphanage->AddTx(tx_orphan, node1));
             +  -  +  - ]
     838   [ +  -  +  -  :           2 :         BOOST_CHECK(orphanage->AddAnnouncer(orphan_wtxid, node2));
                   +  - ]
     839         [ +  + ]:           4 :         for (NodeId node = node0; node <= node2; ++node) {
     840   [ +  -  +  -  :           6 :             BOOST_CHECK(orphanage->HaveTxFromPeer(orphan_wtxid, node));
                   +  - ]
     841                 :             :         }
     842                 :             : 
     843                 :             :         // Parent accepted: child is added to 1 of 3 worksets.
     844         [ +  - ]:           1 :         auto newly_reconsiderable = orphanage->AddChildrenToWorkSet(*tx_missing_parent, det_rand);
     845   [ +  -  -  +  :           1 :         BOOST_CHECK_EQUAL(newly_reconsiderable.size(), 1);
                   +  - ]
     846         [ +  - ]:           1 :         int node0_reconsider = orphanage->HaveTxToReconsider(node0);
     847         [ +  - ]:           1 :         int node1_reconsider = orphanage->HaveTxToReconsider(node1);
     848         [ +  - ]:           1 :         int node2_reconsider = orphanage->HaveTxToReconsider(node2);
     849   [ +  -  +  - ]:           1 :         BOOST_CHECK_EQUAL(node0_reconsider + node1_reconsider + node2_reconsider, 1);
     850                 :             : 
     851                 :           1 :         NodeId assigned_peer;
     852         [ +  - ]:           1 :         if (node0_reconsider) {
     853                 :             :             assigned_peer = node0;
     854         [ -  + ]:           1 :         } else if (node1_reconsider) {
     855                 :             :             assigned_peer = node1;
     856                 :             :         } else {
     857   [ #  #  #  # ]:           0 :             BOOST_CHECK(node2_reconsider);
     858                 :           0 :             assigned_peer = node2;
     859                 :             :         }
     860                 :             : 
     861                 :             :         // EraseForPeer also removes that tx from the workset.
     862         [ +  - ]:           1 :         orphanage->EraseForPeer(assigned_peer);
     863   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(node0), nullptr);
             +  -  -  + ]
     864                 :             : 
     865                 :             :         // Delete this tx, clearing the orphanage.
     866   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->EraseTx(orphan_wtxid), 1);
                   +  - ]
     867   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), 0);
                   +  - ]
     868         [ +  + ]:           4 :         for (NodeId node = node0; node <= node2; ++node) {
     869   [ +  -  +  -  :           3 :             BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(node), nullptr);
             +  -  -  + ]
     870   [ +  -  +  -  :           6 :             BOOST_CHECK(!orphanage->HaveTxFromPeer(orphan_wtxid, node));
                   +  - ]
     871                 :             :         }
     872   [ +  -  +  - ]:           2 :     }
     873                 :           1 : }
     874                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1