1 // Copyright (c) 2024 The Limenka 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 LIMENKA_NODE_TXDOWNLOADMAN_H
6 #define LIMENKA_NODE_TXDOWNLOADMAN_H
7 8 #include <net.h>
9 #include <policy/packages.h>
10 #include <txorphanage.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 /** Maximum number of transactions allowed in orphanage. */
45 uint32_t m_max_orphan_txs;
46 /** Instantiate TxRequestTracker as deterministic (used for tests). */
47 bool m_deterministic_txrequest{false};
48 };
49 struct TxDownloadConnectionInfo {
50 /** Whether this peer is preferred for transaction download. */
51 const bool m_preferred;
52 /** Whether this peer has Relay permissions. */
53 const bool m_relay_permissions;
54 /** Whether this peer supports wtxid relay. */
55 const bool m_wtxid_relay;
56 };
57 struct PackageToValidate {
58 Package m_txns;
59 std::vector<NodeId> m_senders;
60 /** Construct a 1-parent-1-child package. */
61 explicit PackageToValidate(const CTransactionRef& parent,
62 const CTransactionRef& child,
63 NodeId parent_sender,
64 NodeId child_sender) :
65 m_txns{parent, child},
66 m_senders{parent_sender, child_sender}
67 {}
68 69 // Move ctor
70 PackageToValidate(PackageToValidate&& other) : m_txns{std::move(other.m_txns)}, m_senders{std::move(other.m_senders)} {}
71 // Copy ctor
72 PackageToValidate(const PackageToValidate& other) = default;
73 74 // Move assignment
75 PackageToValidate& operator=(PackageToValidate&& other) {
76 this->m_txns = std::move(other.m_txns);
77 this->m_senders = std::move(other.m_senders);
78 return *this;
79 }
80 81 std::string ToString() const {
82 Assume(m_txns.size() == 2);
83 return strprintf("parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)",
84 m_txns.front()->GetHash().ToString(),
85 m_txns.front()->GetWitnessHash().ToString(),
86 m_senders.front(),
87 m_txns.back()->GetHash().ToString(),
88 m_txns.back()->GetWitnessHash().ToString(),
89 m_senders.back());
90 }
91 };
92 struct RejectedTxTodo
93 {
94 bool m_should_add_extra_compact_tx;
95 std::vector<Txid> m_unique_parents;
96 std::optional<PackageToValidate> m_package_to_validate;
97 };
98 99 100 /**
101 * Class responsible for deciding what transactions to request and, once
102 * downloaded, whether and how to validate them. It is also responsible for
103 * deciding what transaction packages to validate and how to resolve orphan
104 * transactions. Its data structures include TxRequestTracker for scheduling
105 * requests, rolling bloom filters for remembering transactions that have
106 * already been {accepted, rejected, confirmed}, an orphanage, and a registry of
107 * each peer's transaction relay-related information.
108 *
109 * Caller needs to interact with TxDownloadManager:
110 * - ValidationInterface callbacks.
111 * - When a potential transaction relay peer connects or disconnects.
112 * - When a transaction or package is accepted or rejected from mempool
113 * - When a inv, notfound, or tx message is received
114 * - To get instructions for which getdata messages to send
115 *
116 * This class is not thread-safe. Access must be synchronized using an
117 * external mutex.
118 */
119 class TxDownloadManager {
120 const std::unique_ptr<TxDownloadManagerImpl> m_impl;
121 122 public:
123 explicit TxDownloadManager(const TxDownloadOptions& options);
124 ~TxDownloadManager();
125 126 // Responses to chain events. TxDownloadManager is not an actual client of ValidationInterface, these are called through PeerManager.
127 void ActiveTipChange();
128 void BlockConnected(const std::shared_ptr<const CBlock>& pblock);
129 void BlockDisconnected();
130 131 /** Creates a new PeerInfo. Saves the connection info to calculate tx announcement delays later. */
132 void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info);
133 134 /** Deletes all txrequest announcements and orphans for a given peer. */
135 void DisconnectedPeer(NodeId nodeid);
136 137 /** Consider adding this tx hash to txrequest. Should be called whenever a new inv has been received.
138 * Also called internally when a transaction is missing parents so that we can request them.
139 * Returns true if this was a dropped inv (p2p_inv=true and we already have the tx), false otherwise. */
140 bool AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now);
141 142 /** Get getdata requests to send. */
143 std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
144 145 /** Should be called when a notfound for a tx has been received. */
146 void ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes);
147 148 /** Respond to successful transaction submission to mempool */
149 void MempoolAcceptedTx(const CTransactionRef& tx);
150 151 /** Respond to transaction rejected from mempool */
152 RejectedTxTodo MempoolRejectedTx(const CTransactionRef& ptx, const TxValidationState& state, NodeId nodeid, bool first_time_failure);
153 154 /** Respond to package rejected from mempool */
155 void MempoolRejectedPackage(const Package& package);
156 157 /** Marks a tx as ReceivedResponse in txrequest and checks whether AlreadyHaveTx.
158 * Return a bool indicating whether this tx should be validated. If false, optionally, a
159 * PackageToValidate. */
160 std::pair<bool, std::optional<PackageToValidate>> ReceivedTx(NodeId nodeid, const CTransactionRef& ptx);
161 162 /** Whether there are any orphans to reconsider for this peer. */
163 bool HaveMoreWork(NodeId nodeid) const;
164 165 /** Returns next orphan tx to consider, or nullptr if none exist. */
166 CTransactionRef GetTxToReconsider(NodeId nodeid);
167 168 /** Check that all data structures are empty. */
169 void CheckIsEmpty() const;
170 171 /** Check that all data structures that track per-peer information have nothing for this peer. */
172 void CheckIsEmpty(NodeId nodeid) const;
173 174 /** Wrapper for TxOrphanage::GetOrphanTransactions */
175 std::vector<TxOrphanage::OrphanTxBase> GetOrphanTransactions() const;
176 177 void SetMaxOrphanTxs(uint32_t max_orphan_txs);
178 };
179 } // namespace node
180 #endif // LIMENKA_NODE_TXDOWNLOADMAN_H
181