LCOV - code coverage report
Current view: top level - src/node - txdownloadman_impl.h (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 100.0 % 19 19
Test Date: 2026-09-03 06:16:07 Functions: 100.0 % 4 4
Branches: 87.5 % 8 7

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2024-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                 :             : #ifndef BITCOIN_NODE_TXDOWNLOADMAN_IMPL_H
       5                 :             : #define BITCOIN_NODE_TXDOWNLOADMAN_IMPL_H
       6                 :             : 
       7                 :             : #include <node/txdownloadman.h>
       8                 :             : 
       9                 :             : #include <common/bloom.h>
      10                 :             : #include <consensus/validation.h>
      11                 :             : #include <kernel/chain.h>
      12                 :             : #include <net.h>
      13                 :             : #include <node/txorphanage.h>
      14                 :             : #include <primitives/transaction.h>
      15                 :             : #include <policy/packages.h>
      16                 :             : #include <random.h>
      17                 :             : #include <txrequest.h>
      18                 :             : 
      19                 :             : class CTxMemPool;
      20                 :             : namespace node {
      21                 :             : class TxDownloadManagerImpl {
      22                 :             : public:
      23                 :             :     const CTxMemPool& m_mempool;
      24                 :             :     FastRandomContext m_rng;
      25                 :             : 
      26                 :             :     /** Manages unvalidated tx data (orphan transactions for which we are downloading ancestors). */
      27                 :             :     std::unique_ptr<TxOrphanage> m_orphanage;
      28                 :             :     /** Tracks candidates for requesting and downloading transaction data. */
      29                 :             :     TxRequestTracker m_txrequest;
      30                 :             : 
      31                 :             :     /**
      32                 :             :      * Filter for transactions that were recently rejected by the mempool.
      33                 :             :      * These are not rerequested until the chain tip changes, at which point
      34                 :             :      * the entire filter is reset.
      35                 :             :      *
      36                 :             :      * Without this filter we'd be re-requesting txs from each of our peers,
      37                 :             :      * increasing bandwidth consumption considerably. For instance, with 100
      38                 :             :      * peers, half of which relay a tx we don't accept, that might be a 50x
      39                 :             :      * bandwidth increase. A flooding attacker attempting to roll-over the
      40                 :             :      * filter using minimum-sized, 60byte, transactions might manage to send
      41                 :             :      * 1000/sec if we have fast peers, so we pick 120,000 to give our peers a
      42                 :             :      * two minute window to send invs to us.
      43                 :             :      *
      44                 :             :      * Decreasing the false positive rate is fairly cheap, so we pick one in a
      45                 :             :      * million to make it highly unlikely for users to have issues with this
      46                 :             :      * filter.
      47                 :             :      *
      48                 :             :      * We typically only add wtxids to this filter. For non-segwit
      49                 :             :      * transactions, the txid == wtxid, so this only prevents us from
      50                 :             :      * re-downloading non-segwit transactions when communicating with
      51                 :             :      * non-wtxidrelay peers -- which is important for avoiding malleation
      52                 :             :      * attacks that could otherwise interfere with transaction relay from
      53                 :             :      * non-wtxidrelay peers. For communicating with wtxidrelay peers, having
      54                 :             :      * the reject filter store wtxids is exactly what we want to avoid
      55                 :             :      * redownload of a rejected transaction.
      56                 :             :      *
      57                 :             :      * In cases where we can tell that a segwit transaction will fail
      58                 :             :      * validation no matter the witness, we may add the txid of such
      59                 :             :      * transaction to the filter as well. This can be helpful when
      60                 :             :      * communicating with txid-relay peers or if we were to otherwise fetch a
      61                 :             :      * transaction via txid (eg in our orphan handling).
      62                 :             :      *
      63                 :             :      * Memory used: 1.3 MB
      64                 :             :      */
      65                 :             :     std::unique_ptr<CRollingBloomFilter> m_lazy_recent_rejects{nullptr};
      66                 :             : 
      67                 :      550677 :     CRollingBloomFilter& RecentRejectsFilter()
      68                 :             :     {
      69         [ +  + ]:      550677 :         if (!m_lazy_recent_rejects) {
      70                 :        3035 :             m_lazy_recent_rejects = std::make_unique<CRollingBloomFilter>(120'000, 0.000'001);
      71                 :             :         }
      72                 :             : 
      73                 :      550677 :         return *m_lazy_recent_rejects;
      74                 :             :     }
      75                 :             : 
      76                 :             :     /**
      77                 :             :      * Filter for:
      78                 :             :      * (1) wtxids of transactions that were recently rejected by the mempool but are
      79                 :             :      * eligible for reconsideration if submitted with other transactions.
      80                 :             :      * (2) packages (see GetPackageHash) we have already rejected before and should not retry.
      81                 :             :      *
      82                 :             :      * Similar to m_lazy_recent_rejects, this filter is used to save bandwidth when e.g. all of our peers
      83                 :             :      * have larger mempools and thus lower minimum feerates than us.
      84                 :             :      *
      85                 :             :      * When a transaction's error is TxValidationResult::TX_RECONSIDERABLE (in a package or by
      86                 :             :      * itself), add its wtxid to this filter. When a package fails for any reason, add the combined
      87                 :             :      * hash to this filter.
      88                 :             :      *
      89                 :             :      * Upon receiving an announcement for a transaction, if it exists in this filter, do not
      90                 :             :      * download the txdata. When considering packages, if it exists in this filter, drop it.
      91                 :             :      *
      92                 :             :      * Reset this filter when the chain tip changes.
      93                 :             :      *
      94                 :             :      * Parameters are picked to be the same as m_lazy_recent_rejects, with the same rationale.
      95                 :             :      */
      96                 :             :     std::unique_ptr<CRollingBloomFilter> m_lazy_recent_rejects_reconsiderable{nullptr};
      97                 :             : 
      98                 :      484889 :     CRollingBloomFilter& RecentRejectsReconsiderableFilter()
      99                 :             :     {
     100         [ +  + ]:      484889 :         if (!m_lazy_recent_rejects_reconsiderable) {
     101                 :        2995 :             m_lazy_recent_rejects_reconsiderable = std::make_unique<CRollingBloomFilter>(120'000, 0.000'001);
     102                 :             :         }
     103                 :             : 
     104                 :      484889 :         return *m_lazy_recent_rejects_reconsiderable;
     105                 :             :     }
     106                 :             : 
     107                 :             :     /*
     108                 :             :      * Filter for transactions that have been recently confirmed.
     109                 :             :      * We use this to avoid requesting transactions that have already been
     110                 :             :      * confirmed.
     111                 :             :      *
     112                 :             :      * Blocks don't typically have more than 4000 transactions, so this should
     113                 :             :      * be at least six blocks (~1 hr) worth of transactions that we can store,
     114                 :             :      * inserting both a txid and wtxid for every observed transaction.
     115                 :             :      * If the number of transactions appearing in a block goes up, or if we are
     116                 :             :      * seeing getdata requests more than an hour after initial announcement, we
     117                 :             :      * can increase this number.
     118                 :             :      * The false positive rate of 1/1M should come out to less than 1
     119                 :             :      * transaction per day that would be inadvertently ignored (which is the
     120                 :             :      * same probability that we have in the reject filter).
     121                 :             :      */
     122                 :             :     std::unique_ptr<CRollingBloomFilter> m_lazy_recent_confirmed_transactions{nullptr};
     123                 :             : 
     124                 :      169420 :     CRollingBloomFilter& RecentConfirmedTransactionsFilter()
     125                 :             :     {
     126         [ +  + ]:      169420 :         if (!m_lazy_recent_confirmed_transactions) {
     127                 :        3215 :             m_lazy_recent_confirmed_transactions = std::make_unique<CRollingBloomFilter>(48'000, 0.000'001);
     128                 :             :         }
     129                 :             : 
     130                 :      169420 :         return *m_lazy_recent_confirmed_transactions;
     131                 :             :     }
     132                 :             : 
     133                 :       13927 :     TxDownloadManagerImpl(const TxDownloadOptions& options)
     134                 :       13927 :         : m_mempool{options.m_mempool},
     135                 :       13927 :           m_rng{options.m_deterministic_txrequest},
     136                 :       13927 :           m_orphanage{MakeTxOrphanage()},
     137         [ +  - ]:       13927 :           m_txrequest{options.m_deterministic_txrequest}
     138                 :       13927 :     {}
     139                 :             : 
     140                 :             :     struct PeerInfo {
     141                 :             :         /** Information relevant to scheduling tx requests. */
     142                 :             :         const TxDownloadConnectionInfo m_connection_info;
     143                 :             : 
     144                 :       16112 :         PeerInfo(const TxDownloadConnectionInfo& info) : m_connection_info{info} {}
     145                 :             :     };
     146                 :             : 
     147                 :             :     /** Information for all of the peers we may download transactions from. This is not necessarily
     148                 :             :      * all peers we are connected to (no block-relay-only and temporary connections). */
     149                 :             :     std::map<NodeId, PeerInfo> m_peer_info;
     150                 :             : 
     151                 :             :     /** Number of wtxid relay peers we have in m_peer_info. */
     152                 :             :     uint32_t m_num_wtxid_peers{0};
     153                 :             : 
     154                 :             :     void ActiveTipChange();
     155                 :             :     void BlockConnected(const std::shared_ptr<const CBlock>& pblock);
     156                 :             :     void BlockDisconnected();
     157                 :             : 
     158                 :             :     /** Check whether we already have this gtxid in:
     159                 :             :      *  - mempool
     160                 :             :      *  - orphanage
     161                 :             :      *  - m_recent_rejects
     162                 :             :      *  - m_recent_rejects_reconsiderable (if include_reconsiderable = true)
     163                 :             :      *  - m_recent_confirmed_transactions
     164                 :             :      *  */
     165                 :             :     bool AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable);
     166                 :             : 
     167                 :             :     void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info);
     168                 :             :     void DisconnectedPeer(NodeId nodeid);
     169                 :             : 
     170                 :             :     /** Consider adding this tx hash to txrequest. Should be called whenever a new inv has been received.
     171                 :             :      * Also called internally when a transaction is missing parents so that we can request them.
     172                 :             :      */
     173                 :             :     bool AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now);
     174                 :             : 
     175                 :             :     /** Get getdata requests to send. */
     176                 :             :     std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
     177                 :             : 
     178                 :             :     /** Marks a tx as ReceivedResponse in txrequest. */
     179                 :             :     void ReceivedNotFound(NodeId nodeid, const std::vector<GenTxid>& gtxids);
     180                 :             : 
     181                 :             :     /** Look for a child of this transaction in the orphanage to form a 1-parent-1-child package,
     182                 :             :      * skipping any combinations that have already been tried. Return the resulting package along with
     183                 :             :      * the senders of its respective transactions, or std::nullopt if no package is found. */
     184                 :             :     std::optional<PackageToValidate> Find1P1CPackage(const CTransactionRef& ptx, NodeId nodeid);
     185                 :             : 
     186                 :             :     void MempoolAcceptedTx(const CTransactionRef& tx);
     187                 :             :     RejectedTxTodo MempoolRejectedTx(const CTransactionRef& ptx, const TxValidationState& state, NodeId nodeid, bool first_time_failure);
     188                 :             :     void MempoolRejectedPackage(const Package& package);
     189                 :             : 
     190                 :             :     std::pair<bool, std::optional<PackageToValidate>> ReceivedTx(NodeId nodeid, const CTransactionRef& ptx);
     191                 :             : 
     192                 :             :     bool HaveMoreWork(NodeId nodeid);
     193                 :             :     CTransactionRef GetTxToReconsider(NodeId nodeid);
     194                 :             : 
     195                 :             :     void CheckIsEmpty();
     196                 :             :     void CheckIsEmpty(NodeId nodeid);
     197                 :             : 
     198                 :             :     std::vector<TxOrphanage::OrphanInfo> GetOrphanTransactions() const;
     199                 :             : 
     200                 :             : protected:
     201                 :             :     /** Helper for getting deduplicated vector of Txids in vin. */
     202                 :             :     std::vector<Txid> GetUniqueParents(const CTransaction& tx);
     203                 :             : 
     204                 :             :     /** If this peer is an orphan resolution candidate for this transaction, treat the unique_parents as announced by
     205                 :             :      * this peer; add them as new invs to m_txrequest.
     206                 :             :      * @returns whether this transaction was a valid orphan resolution candidate.
     207                 :             :      * */
     208                 :             :     bool MaybeAddOrphanResolutionCandidate(const std::vector<Txid>& unique_parents, const Wtxid& wtxid, NodeId nodeid, std::chrono::microseconds now);
     209                 :             : };
     210                 :             : } // namespace node
     211                 :             : #endif // BITCOIN_NODE_TXDOWNLOADMAN_IMPL_H
        

Generated by: LCOV version 2.5.0-full