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 % 14 14
Test Date: 2024-12-04 04:00:22 Functions: 100.0 % 4 4
Branches: 87.5 % 8 7

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

Generated by: LCOV version 2.0-1