1 // Copyright (c) 2021-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_TXORPHANAGE_H
6 #define BITCOIN_NODE_TXORPHANAGE_H
7 8 #include <consensus/validation.h>
9 #include <net.h>
10 #include <primitives/block.h>
11 #include <primitives/transaction.h>
12 #include <sync.h>
13 #include <util/time.h>
14 15 #include <map>
16 #include <set>
17 18 namespace node {
19 /** Default value for TxOrphanage::m_reserved_usage_per_peer. Helps limit the total amount of memory used by the orphanage. */
20 static constexpr int64_t DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER{404'000};
21 /** Default value for TxOrphanage::m_max_global_latency_score. Helps limit the maximum latency for operations like
22 * EraseForBlock and LimitOrphans. */
23 static constexpr unsigned int DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE{3000};
24 25 /** A class to track orphan transactions (failed on TX_MISSING_INPUTS)
26 * Since we cannot distinguish orphans from bad transactions with non-existent inputs, we heavily limit the amount of
27 * announcements (unique (NodeId, wtxid) pairs), the number of inputs, and size of the orphans stored (both individual
28 * and summed). We also try to prevent adversaries from churning this data structure: once global limits are reached, we
29 * continuously evict the oldest announcement (sorting non-reconsiderable orphans before reconsiderable ones) from the
30 * most resource-intensive peer until we are back within limits.
31 * - Peers can exceed their individual limits (e.g. because they are very useful transaction relay peers) as long as the
32 * global limits are not exceeded.
33 * - As long as the orphan has 1 announcer, it remains in the orphanage.
34 * - No peer can trigger the eviction of another peer's orphans.
35 * - Peers' orphans are effectively protected from eviction as long as they don't exceed their limits.
36 * Not thread-safe. Requires external synchronization.
37 */
38 class TxOrphanage {
39 public:
40 using Usage = int64_t;
41 using Count = unsigned int;
42 43 /** Allows providing orphan information externally */
44 struct OrphanInfo {
45 CTransactionRef tx;
46 /** Peers added with AddTx or AddAnnouncer. */
47 std::set<NodeId> announcers;
48 49 // Constructor with moved announcers
50 OrphanInfo(CTransactionRef tx, std::set<NodeId>&& announcers) :
51 tx(std::move(tx)),
52 announcers(std::move(announcers))
53 {}
54 };
55 56 virtual ~TxOrphanage() = default;
57 58 /** Add a new orphan transaction */
59 virtual bool AddTx(const CTransactionRef& tx, NodeId peer) = 0;
60 61 /** Add an additional announcer to an orphan if it exists. Otherwise, do nothing. */
62 virtual bool AddAnnouncer(const Wtxid& wtxid, NodeId peer) = 0;
63 64 /** Get a transaction by its witness txid */
65 virtual CTransactionRef GetTx(const Wtxid& wtxid) const = 0;
66 67 /** Check if we already have an orphan transaction (by wtxid only) */
68 virtual bool HaveTx(const Wtxid& wtxid) const = 0;
69 70 /** Check if a {tx, peer} exists in the orphanage.*/
71 virtual bool HaveTxFromPeer(const Wtxid& wtxid, NodeId peer) const = 0;
72 73 /** Extract a transaction from a peer's work set, and flip it back to non-reconsiderable.
74 * Returns nullptr if there are no transactions to work on.
75 * Otherwise returns the transaction reference, and removes
76 * it from the work set.
77 */
78 virtual CTransactionRef GetTxToReconsider(NodeId peer) = 0;
79 80 /** Erase an orphan by wtxid, including all announcements if there are multiple.
81 * Returns true if an orphan was erased, false if no tx with this wtxid exists. */
82 virtual bool EraseTx(const Wtxid& wtxid) = 0;
83 84 /** Maybe erase all orphans announced by a peer (eg, after that peer disconnects). If an orphan
85 * has been announced by another peer, don't erase, just remove this peer from the list of announcers. */
86 virtual void EraseForPeer(NodeId peer) = 0;
87 88 /** Erase all orphans included in or invalidated by a new block */
89 virtual void EraseForBlock(const CBlock& block) = 0;
90 91 /** Add any orphans that list a particular tx as a parent into the from peer's work set */
92 virtual std::vector<std::pair<Wtxid, NodeId>> AddChildrenToWorkSet(const CTransaction& tx, FastRandomContext& rng) = 0;
93 94 /** Does this peer have any work to do? */
95 virtual bool HaveTxToReconsider(NodeId peer) = 0;
96 97 /** Get all children that spend from this tx and were received from nodeid. Sorted
98 * reconsiderable before non-reconsiderable, then from most recent to least recent. */
99 virtual std::vector<CTransactionRef> GetChildrenFromSamePeer(const CTransactionRef& parent, NodeId nodeid) const = 0;
100 101 /** Get all orphan transactions */
102 virtual std::vector<OrphanInfo> GetOrphanTransactions() const = 0;
103 104 /** Get the total usage (weight) of all orphans. If an orphan has multiple announcers, its usage is
105 * only counted once within this total. */
106 virtual Usage TotalOrphanUsage() const = 0;
107 108 /** Total usage (weight) of orphans for which this peer is an announcer. If an orphan has multiple
109 * announcers, its weight will be accounted for in each PeerOrphanInfo, so the total of all
110 * peers' UsageByPeer() may be larger than TotalOrphanUsage(). Similarly, UsageByPeer() may be far higher than
111 * ReservedPeerUsage(), particularly if many peers have provided the same orphans. */
112 virtual Usage UsageByPeer(NodeId peer) const = 0;
113 114 /** Check consistency between PeerOrphanInfo and m_orphans. Recalculate counters and ensure they
115 * match what is cached. */
116 virtual void SanityCheck() const = 0;
117 118 /** Number of announcements, i.e. total size of m_orphans. Ones for the same wtxid are not de-duplicated.
119 * Not the same as TotalLatencyScore(). */
120 virtual Count CountAnnouncements() const = 0;
121 122 /** Number of unique orphans (by wtxid). */
123 virtual Count CountUniqueOrphans() const = 0;
124 125 /** Number of orphans stored from this peer. */
126 virtual Count AnnouncementsFromPeer(NodeId peer) const = 0;
127 128 /** Latency score of transactions announced by this peer. */
129 virtual Count LatencyScoreFromPeer(NodeId peer) const = 0;
130 131 /** Get the maximum global latency score allowed */
132 virtual Count MaxGlobalLatencyScore() const = 0;
133 134 /** Get the total latency score of all orphans */
135 virtual Count TotalLatencyScore() const = 0;
136 137 /** Get the reserved usage per peer */
138 virtual Usage ReservedPeerUsage() const = 0;
139 140 /** Get the maximum latency score allowed per peer */
141 virtual Count MaxPeerLatencyScore() const = 0;
142 143 /** Get the maximum global usage allowed */
144 virtual Usage MaxGlobalUsage() const = 0;
145 };
146 147 /** Create a new TxOrphanage instance */
148 std::unique_ptr<TxOrphanage> MakeTxOrphanage() noexcept;
149 std::unique_ptr<TxOrphanage> MakeTxOrphanage(TxOrphanage::Count max_global_latency_score, TxOrphanage::Usage reserved_peer_usage) noexcept;
150 } // namespace node
151 #endif // BITCOIN_NODE_TXORPHANAGE_H
152