/ src / node / txdownloadman.h
txdownloadman.h
  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  
  5  #ifndef BITCOIN_NODE_TXDOWNLOADMAN_H
  6  #define BITCOIN_NODE_TXDOWNLOADMAN_H
  7  
  8  #include <net.h>
  9  #include <node/txorphanage.h>
 10  #include <policy/packages.h>
 11  
 12  #include <cstdint>
 13  #include <memory>
 14  
 15  class CBlock;
 16  class CRollingBloomFilter;
 17  class CTxMemPool;
 18  class GenTxid;
 19  class TxRequestTracker;
 20  namespace node {
 21  class TxDownloadManagerImpl;
 22  
 23  /** Maximum number of in-flight transaction requests from a peer. It is not a hard limit, but the threshold at which
 24   *  point the OVERLOADED_PEER_TX_DELAY kicks in. */
 25  static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT = 100;
 26  /** Maximum number of transactions to consider for requesting, per peer. It provides a reasonable DoS limit to
 27   *  per-peer memory usage spent on announcements, while covering peers continuously sending INVs at the maximum
 28   *  rate (by our own policy, see INVENTORY_BROADCAST_PER_SECOND) for several minutes, while not receiving
 29   *  the actual transaction (from any peer) in response to requests for them. */
 30  static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS = 5000;
 31  /** How long to delay requesting transactions via txids, if we have wtxid-relaying peers */
 32  static constexpr auto TXID_RELAY_DELAY{2s};
 33  /** How long to delay requesting transactions from non-preferred peers */
 34  static constexpr auto NONPREF_PEER_TX_DELAY{2s};
 35  /** How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT). */
 36  static constexpr auto OVERLOADED_PEER_TX_DELAY{2s};
 37  /** How long to wait before downloading a transaction from an additional peer */
 38  static constexpr auto GETDATA_TX_INTERVAL{60s};
 39  struct TxDownloadOptions {
 40      /** Read-only reference to mempool. */
 41      const CTxMemPool& m_mempool;
 42      /** RNG provided by caller. */
 43      FastRandomContext& m_rng;
 44      /** Instantiate TxRequestTracker as deterministic (used for tests). */
 45      bool m_deterministic_txrequest{false};
 46  };
 47  struct TxDownloadConnectionInfo {
 48      /** Whether this peer is preferred for transaction download. */
 49      const bool m_preferred;
 50      /** Whether this peer has Relay permissions. */
 51      const bool m_relay_permissions;
 52      /** Whether this peer supports wtxid relay. */
 53      const bool m_wtxid_relay;
 54  };
 55  struct PackageToValidate {
 56      Package m_txns;
 57      std::vector<NodeId> m_senders;
 58      /** Construct a 1-parent-1-child package. */
 59      explicit PackageToValidate(const CTransactionRef& parent,
 60                                 const CTransactionRef& child,
 61                                 NodeId parent_sender,
 62                                 NodeId child_sender) :
 63          m_txns{parent, child},
 64          m_senders{parent_sender, child_sender}
 65      {}
 66  
 67      // Move ctor
 68      PackageToValidate(PackageToValidate&& other) : m_txns{std::move(other.m_txns)}, m_senders{std::move(other.m_senders)} {}
 69      // Copy ctor
 70      PackageToValidate(const PackageToValidate& other) = default;
 71  
 72      // Move assignment
 73      PackageToValidate& operator=(PackageToValidate&& other) {
 74          this->m_txns = std::move(other.m_txns);
 75          this->m_senders = std::move(other.m_senders);
 76          return *this;
 77      }
 78  
 79      std::string ToString() const {
 80          Assume(m_txns.size() == 2);
 81          return strprintf("parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)",
 82                           m_txns.front()->GetHash().ToString(),
 83                           m_txns.front()->GetWitnessHash().ToString(),
 84                           m_senders.front(),
 85                           m_txns.back()->GetHash().ToString(),
 86                           m_txns.back()->GetWitnessHash().ToString(),
 87                           m_senders.back());
 88      }
 89  };
 90  struct RejectedTxTodo
 91  {
 92      bool m_should_add_extra_compact_tx;
 93      std::vector<Txid> m_unique_parents;
 94      std::optional<PackageToValidate> m_package_to_validate;
 95  };
 96  
 97  
 98  /**
 99   * Class responsible for deciding what transactions to request and, once
100   * downloaded, whether and how to validate them. It is also responsible for
101   * deciding what transaction packages to validate and how to resolve orphan
102   * transactions. Its data structures include TxRequestTracker for scheduling
103   * requests, rolling bloom filters for remembering transactions that have
104   * already been {accepted, rejected, confirmed}, an orphanage, and a registry of
105   * each peer's transaction relay-related information.
106   *
107   * Caller needs to interact with TxDownloadManager:
108   * - ValidationInterface callbacks.
109   * - When a potential transaction relay peer connects or disconnects.
110   * - When a transaction or package is accepted or rejected from mempool
111   * - When a inv, notfound, or tx message is received
112   * - To get instructions for which getdata messages to send
113   *
114   * This class is not thread-safe. Access must be synchronized using an
115   * external mutex.
116   */
117  class TxDownloadManager {
118      const std::unique_ptr<TxDownloadManagerImpl> m_impl;
119  
120  public:
121      explicit TxDownloadManager(const TxDownloadOptions& options);
122      ~TxDownloadManager();
123  
124      // Responses to chain events. TxDownloadManager is not an actual client of ValidationInterface, these are called through PeerManager.
125      void ActiveTipChange();
126      void BlockConnected(const std::shared_ptr<const CBlock>& pblock);
127      void BlockDisconnected();
128  
129      /** Creates a new PeerInfo. Saves the connection info to calculate tx announcement delays later. */
130      void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info);
131  
132      /** Deletes all txrequest announcements and orphans for a given peer. */
133      void DisconnectedPeer(NodeId nodeid);
134  
135      /** Consider adding this tx hash to txrequest. Should be called whenever a new inv has been received.
136       * Also called internally when a transaction is missing parents so that we can request them.
137       * Returns true if this was a dropped inv (p2p_inv=true and we already have the tx), false otherwise. */
138      bool AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now);
139  
140      /** Get getdata requests to send. */
141      std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
142  
143      /** Should be called when a notfound for a tx has been received. */
144      void ReceivedNotFound(NodeId nodeid, const std::vector<GenTxid>& gtxids);
145  
146      /** Respond to successful transaction submission to mempool */
147      void MempoolAcceptedTx(const CTransactionRef& tx);
148  
149      /** Respond to transaction rejected from mempool */
150      RejectedTxTodo MempoolRejectedTx(const CTransactionRef& ptx, const TxValidationState& state, NodeId nodeid, bool first_time_failure);
151  
152      /** Respond to package rejected from mempool */
153      void MempoolRejectedPackage(const Package& package);
154  
155      /** Marks a tx as ReceivedResponse in txrequest and checks whether AlreadyHaveTx.
156       * Return a bool indicating whether this tx should be validated. If false, optionally, a
157       * PackageToValidate. */
158      std::pair<bool, std::optional<PackageToValidate>> ReceivedTx(NodeId nodeid, const CTransactionRef& ptx);
159  
160      /** Whether there are any orphans to reconsider for this peer. */
161      bool HaveMoreWork(NodeId nodeid) const;
162  
163      /** Returns next orphan tx to consider, or nullptr if none exist. */
164      CTransactionRef GetTxToReconsider(NodeId nodeid);
165  
166      /** Check that all data structures are empty. */
167      void CheckIsEmpty() const;
168  
169      /** Check that all data structures that track per-peer information have nothing for this peer. */
170      void CheckIsEmpty(NodeId nodeid) const;
171  
172      /** Wrapper for TxOrphanage::GetOrphanTransactions */
173      std::vector<TxOrphanage::OrphanInfo> GetOrphanTransactions() const;
174  };
175  } // namespace node
176  #endif // BITCOIN_NODE_TXDOWNLOADMAN_H