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 #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 <node/txorphanage.h>
14 #include <primitives/transaction.h>
15 #include <policy/packages.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 std::unique_ptr<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 CRollingBloomFilter& RecentRejectsFilter()
66 {
67 if (!m_lazy_recent_rejects) {
68 m_lazy_recent_rejects = std::make_unique<CRollingBloomFilter>(120'000, 0.000'001);
69 }
70 71 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 CRollingBloomFilter& RecentRejectsReconsiderableFilter()
97 {
98 if (!m_lazy_recent_rejects_reconsiderable) {
99 m_lazy_recent_rejects_reconsiderable = std::make_unique<CRollingBloomFilter>(120'000, 0.000'001);
100 }
101 102 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 CRollingBloomFilter& RecentConfirmedTransactionsFilter()
123 {
124 if (!m_lazy_recent_confirmed_transactions) {
125 m_lazy_recent_confirmed_transactions = std::make_unique<CRollingBloomFilter>(48'000, 0.000'001);
126 }
127 128 return *m_lazy_recent_confirmed_transactions;
129 }
130 131 TxDownloadManagerImpl(const TxDownloadOptions& options) : m_opts{options}, m_orphanage{MakeTxOrphanage()}, 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 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);
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<GenTxid>& gtxids);
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::OrphanInfo> GetOrphanTransactions() const;
192 193 protected:
194 /** Helper for getting deduplicated vector of Txids in vin. */
195 std::vector<Txid> GetUniqueParents(const CTransaction& tx);
196 197 /** If this peer is an orphan resolution candidate for this transaction, treat the unique_parents as announced by
198 * this peer; add them as new invs to m_txrequest.
199 * @returns whether this transaction was a valid orphan resolution candidate.
200 * */
201 bool MaybeAddOrphanResolutionCandidate(const std::vector<Txid>& unique_parents, const Wtxid& wtxid, NodeId nodeid, std::chrono::microseconds now);
202 };
203 } // namespace node
204 #endif // BITCOIN_NODE_TXDOWNLOADMAN_IMPL_H
205