/root/bitcoin/src/node/txdownloadman.h
Line | Count | Source |
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); |
81 | 0 | return strprintf("parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)", |
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 |