Branch data Line data Source code
1 : : // Copyright (c) 2021-2022 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 [ + - + - ]: 1226 : class TxOrphanage {
39 : : public:
40 : : using Usage = int64_t;
41 : : using Count = unsigned int;
42 : :
43 : : /** Allows providing orphan information externally */
44 : : struct OrphanTxBase {
45 : : CTransactionRef tx;
46 : : /** Peers added with AddTx or AddAnnouncer. */
47 : : std::set<NodeId> announcers;
48 : :
49 : : // Constructor with moved announcers
50 : 1798379 : OrphanTxBase(CTransactionRef tx, std::set<NodeId>&& announcers) :
51 : 1798379 : tx(std::move(tx)),
52 : 1798379 : announcers(std::move(announcers))
53 : : {}
54 : : };
55 : :
56 : 1226 : 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 : : /** Limit the orphanage to MaxGlobalLatencyScore and MaxGlobalUsage. */
92 : : virtual void LimitOrphans() = 0;
93 : :
94 : : /** Add any orphans that list a particular tx as a parent into the from peer's work set */
95 : : virtual std::vector<std::pair<Wtxid, NodeId>> AddChildrenToWorkSet(const CTransaction& tx, FastRandomContext& rng) = 0;
96 : :
97 : : /** Does this peer have any work to do? */
98 : : virtual bool HaveTxToReconsider(NodeId peer) = 0;
99 : :
100 : : /** Get all children that spend from this tx and were received from nodeid. Sorted from most
101 : : * recent to least recent. */
102 : : virtual std::vector<CTransactionRef> GetChildrenFromSamePeer(const CTransactionRef& parent, NodeId nodeid) const = 0;
103 : :
104 : : /** Return how many entries exist in the orphange */
105 : : virtual size_t Size() const = 0;
106 : :
107 : : /** Get all orphan transactions */
108 : : virtual std::vector<OrphanTxBase> GetOrphanTransactions() const = 0;
109 : :
110 : : /** Get the total usage (weight) of all orphans. If an orphan has multiple announcers, its usage is
111 : : * only counted once within this total. */
112 : : virtual Usage TotalOrphanUsage() const = 0;
113 : :
114 : : /** Total usage (weight) of orphans for which this peer is an announcer. If an orphan has multiple
115 : : * announcers, its weight will be accounted for in each PeerOrphanInfo, so the total of all
116 : : * peers' UsageByPeer() may be larger than TotalOrphanUsage(). Similarly, UsageByPeer() may be far higher than
117 : : * ReservedPeerUsage(), particularly if many peers have provided the same orphans. */
118 : : virtual Usage UsageByPeer(NodeId peer) const = 0;
119 : :
120 : : /** Check consistency between PeerOrphanInfo and m_orphans. Recalculate counters and ensure they
121 : : * match what is cached. */
122 : : virtual void SanityCheck() const = 0;
123 : :
124 : : /** Number of announcements, i.e. total size of m_orphans. Ones for the same wtxid are not de-duplicated.
125 : : * Not the same as TotalLatencyScore(). */
126 : : virtual Count CountAnnouncements() const = 0;
127 : :
128 : : /** Number of unique orphans (by wtxid). */
129 : : virtual Count CountUniqueOrphans() const = 0;
130 : :
131 : : /** Number of orphans stored from this peer. */
132 : : virtual Count AnnouncementsFromPeer(NodeId peer) const = 0;
133 : :
134 : : /** Latency score of transactions announced by this peer. */
135 : : virtual Count LatencyScoreFromPeer(NodeId peer) const = 0;
136 : :
137 : : /** Get the maximum global latency score allowed */
138 : : virtual Count MaxGlobalLatencyScore() const = 0;
139 : :
140 : : /** Get the total latency score of all orphans */
141 : : virtual Count TotalLatencyScore() const = 0;
142 : :
143 : : /** Get the reserved usage per peer */
144 : : virtual Usage ReservedPeerUsage() const = 0;
145 : :
146 : : /** Get the maximum latency score allowed per peer */
147 : : virtual Count MaxPeerLatencyScore() const = 0;
148 : :
149 : : /** Get the maximum global usage allowed */
150 : : virtual Usage MaxGlobalUsage() const = 0;
151 : : };
152 : :
153 : : /** Create a new TxOrphanage instance */
154 : : std::unique_ptr<TxOrphanage> MakeTxOrphanage() noexcept;
155 : : std::unique_ptr<TxOrphanage> MakeTxOrphanage(TxOrphanage::Count max_global_ann, TxOrphanage::Usage reserved_peer_usage) noexcept;
156 : : } // namespace node
157 : : #endif // BITCOIN_NODE_TXORPHANAGE_H
|