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