/Users/eugenesiegel/btc/bitcoin/src/node/txdownloadman.h
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2024 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 | 0 |         m_txns{parent, child}, | 
| 64 | 0 |         m_senders{parent_sender, child_sender} | 
| 65 | 0 |     {} | 
| 66 |  |  | 
| 67 |  |     // Move ctor | 
| 68 | 0 |     PackageToValidate(PackageToValidate&& other) : m_txns{std::move(other.m_txns)}, m_senders{std::move(other.m_senders)} {} | 
| 69 |  |     // Copy ctor | 
| 70 | 0 |     PackageToValidate(const PackageToValidate& other) = default; | 
| 71 |  |  | 
| 72 |  |     // Move assignment | 
| 73 | 0 |     PackageToValidate& operator=(PackageToValidate&& other) { | 
| 74 | 0 |         this->m_txns = std::move(other.m_txns); | 
| 75 | 0 |         this->m_senders = std::move(other.m_senders); | 
| 76 | 0 |         return *this; | 
| 77 | 0 |     } | 
| 78 |  |  | 
| 79 | 0 |     std::string ToString() const { | 
| 80 | 0 |         Assume(m_txns.size() == 2); | Line | Count | Source |  | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) | 
 | 
| 81 | 0 |         return strprintf("parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)",| Line | Count | Source |  | 1172 | 0 | #define strprintf tfm::format | 
 | 
| 82 | 0 |                          m_txns.front()->GetHash().ToString(), | 
| 83 | 0 |                          m_txns.front()->GetWitnessHash().ToString(), | 
| 84 | 0 |                          m_senders.front(), | 
| 85 | 0 |                          m_txns.back()->GetHash().ToString(), | 
| 86 | 0 |                          m_txns.back()->GetWitnessHash().ToString(), | 
| 87 | 0 |                          m_senders.back()); | 
| 88 | 0 |     } | 
| 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 |