/root/bitcoin/src/kernel/mempool_entry.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2009-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_KERNEL_MEMPOOL_ENTRY_H |
6 | | #define BITCOIN_KERNEL_MEMPOOL_ENTRY_H |
7 | | |
8 | | #include <consensus/amount.h> |
9 | | #include <consensus/validation.h> |
10 | | #include <core_memusage.h> |
11 | | #include <policy/policy.h> |
12 | | #include <policy/settings.h> |
13 | | #include <primitives/transaction.h> |
14 | | #include <util/epochguard.h> |
15 | | #include <util/overflow.h> |
16 | | |
17 | | #include <chrono> |
18 | | #include <functional> |
19 | | #include <memory> |
20 | | #include <set> |
21 | | #include <stddef.h> |
22 | | #include <stdint.h> |
23 | | |
24 | | class CBlockIndex; |
25 | | |
26 | | struct LockPoints { |
27 | | // Will be set to the blockchain height and median time past |
28 | | // values that would be necessary to satisfy all relative locktime |
29 | | // constraints (BIP68) of this tx given our view of block chain history |
30 | | int height{0}; |
31 | | int64_t time{0}; |
32 | | // As long as the current chain descends from the highest height block |
33 | | // containing one of the inputs used in the calculation, then the cached |
34 | | // values are still valid even after a reorg. |
35 | | CBlockIndex* maxInputBlock{nullptr}; |
36 | | }; |
37 | | |
38 | | struct CompareIteratorByHash { |
39 | | // SFINAE for T where T is either a pointer type (e.g., a txiter) or a reference_wrapper<T> |
40 | | // (e.g. a wrapped CTxMemPoolEntry&) |
41 | | template <typename T> |
42 | | bool operator()(const std::reference_wrapper<T>& a, const std::reference_wrapper<T>& b) const |
43 | 0 | { |
44 | 0 | return a.get().GetTx().GetHash() < b.get().GetTx().GetHash(); |
45 | 0 | } |
46 | | template <typename T> |
47 | | bool operator()(const T& a, const T& b) const |
48 | 0 | { |
49 | 0 | return a->GetTx().GetHash() < b->GetTx().GetHash(); |
50 | 0 | } |
51 | | }; |
52 | | |
53 | | /** \class CTxMemPoolEntry |
54 | | * |
55 | | * CTxMemPoolEntry stores data about the corresponding transaction, as well |
56 | | * as data about all in-mempool transactions that depend on the transaction |
57 | | * ("descendant" transactions). |
58 | | * |
59 | | * When a new entry is added to the mempool, we update the descendant state |
60 | | * (m_count_with_descendants, nSizeWithDescendants, and nModFeesWithDescendants) for |
61 | | * all ancestors of the newly added transaction. |
62 | | * |
63 | | */ |
64 | | |
65 | | class CTxMemPoolEntry |
66 | | { |
67 | | public: |
68 | | typedef std::reference_wrapper<const CTxMemPoolEntry> CTxMemPoolEntryRef; |
69 | | // two aliases, should the types ever diverge |
70 | | typedef std::set<CTxMemPoolEntryRef, CompareIteratorByHash> Parents; |
71 | | typedef std::set<CTxMemPoolEntryRef, CompareIteratorByHash> Children; |
72 | | |
73 | | private: |
74 | 0 | CTxMemPoolEntry(const CTxMemPoolEntry&) = default; |
75 | | struct ExplicitCopyTag { |
76 | | explicit ExplicitCopyTag() = default; |
77 | | }; |
78 | | |
79 | | const CTransactionRef tx; |
80 | | mutable Parents m_parents; |
81 | | mutable Children m_children; |
82 | | const CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups |
83 | | const int32_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize()) |
84 | | const size_t nUsageSize; //!< ... and total memory usage |
85 | | const int64_t nTime; //!< Local time when entering the mempool |
86 | | const uint64_t entry_sequence; //!< Sequence number used to determine whether this transaction is too recent for relay |
87 | | const unsigned int entryHeight; //!< Chain height when entering the mempool |
88 | | const bool spendsCoinbase; //!< keep track of transactions that spend a coinbase |
89 | | const int64_t sigOpCost; //!< Total sigop cost |
90 | | CAmount m_modified_fee; //!< Used for determining the priority of the transaction for mining in a block |
91 | | mutable LockPoints lockPoints; //!< Track the height and time at which tx was final |
92 | | |
93 | | // Information about descendants of this transaction that are in the |
94 | | // mempool; if we remove this transaction we must remove all of these |
95 | | // descendants as well. |
96 | | int64_t m_count_with_descendants{1}; //!< number of descendant transactions |
97 | | // Using int64_t instead of int32_t to avoid signed integer overflow issues. |
98 | | int64_t nSizeWithDescendants; //!< ... and size |
99 | | CAmount nModFeesWithDescendants; //!< ... and total fees (all including us) |
100 | | |
101 | | // Analogous statistics for ancestor transactions |
102 | | int64_t m_count_with_ancestors{1}; |
103 | | // Using int64_t instead of int32_t to avoid signed integer overflow issues. |
104 | | int64_t nSizeWithAncestors; |
105 | | CAmount nModFeesWithAncestors; |
106 | | int64_t nSigOpCostWithAncestors; |
107 | | |
108 | | public: |
109 | | CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee, |
110 | | int64_t time, unsigned int entry_height, uint64_t entry_sequence, |
111 | | bool spends_coinbase, |
112 | | int64_t sigops_cost, LockPoints lp) |
113 | 0 | : tx{tx}, |
114 | 0 | nFee{fee}, |
115 | 0 | nTxWeight{GetTransactionWeight(*tx)}, |
116 | 0 | nUsageSize{RecursiveDynamicUsage(tx)}, |
117 | 0 | nTime{time}, |
118 | 0 | entry_sequence{entry_sequence}, |
119 | 0 | entryHeight{entry_height}, |
120 | 0 | spendsCoinbase{spends_coinbase}, |
121 | 0 | sigOpCost{sigops_cost}, |
122 | 0 | m_modified_fee{nFee}, |
123 | 0 | lockPoints{lp}, |
124 | 0 | nSizeWithDescendants{GetTxSize()}, |
125 | 0 | nModFeesWithDescendants{nFee}, |
126 | 0 | nSizeWithAncestors{GetTxSize()}, |
127 | 0 | nModFeesWithAncestors{nFee}, |
128 | 0 | nSigOpCostWithAncestors{sigOpCost} {} |
129 | | |
130 | 0 | CTxMemPoolEntry(ExplicitCopyTag, const CTxMemPoolEntry& entry) : CTxMemPoolEntry(entry) {} |
131 | | CTxMemPoolEntry& operator=(const CTxMemPoolEntry&) = delete; |
132 | | CTxMemPoolEntry(CTxMemPoolEntry&&) = delete; |
133 | | CTxMemPoolEntry& operator=(CTxMemPoolEntry&&) = delete; |
134 | | |
135 | | static constexpr ExplicitCopyTag ExplicitCopy{}; |
136 | | |
137 | 0 | const CTransaction& GetTx() const { return *this->tx; } |
138 | 0 | CTransactionRef GetSharedTx() const { return this->tx; } |
139 | 0 | const CAmount& GetFee() const { return nFee; } |
140 | | int32_t GetTxSize() const |
141 | 0 | { |
142 | 0 | return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp); |
143 | 0 | } |
144 | 0 | int32_t GetTxWeight() const { return nTxWeight; } |
145 | 0 | std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; } |
146 | 0 | unsigned int GetHeight() const { return entryHeight; } |
147 | 0 | uint64_t GetSequence() const { return entry_sequence; } |
148 | 0 | int64_t GetSigOpCost() const { return sigOpCost; } |
149 | 0 | CAmount GetModifiedFee() const { return m_modified_fee; } |
150 | 0 | size_t DynamicMemoryUsage() const { return nUsageSize; } |
151 | 0 | const LockPoints& GetLockPoints() const { return lockPoints; } |
152 | | |
153 | | // Adjusts the descendant state. |
154 | | void UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount); |
155 | | // Adjusts the ancestor state |
156 | | void UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps); |
157 | | // Updates the modified fees with descendants/ancestors. |
158 | | void UpdateModifiedFee(CAmount fee_diff) |
159 | 0 | { |
160 | 0 | nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, fee_diff); |
161 | 0 | nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, fee_diff); |
162 | 0 | m_modified_fee = SaturatingAdd(m_modified_fee, fee_diff); |
163 | 0 | } |
164 | | |
165 | | // Update the LockPoints after a reorg |
166 | | void UpdateLockPoints(const LockPoints& lp) const |
167 | 0 | { |
168 | 0 | lockPoints = lp; |
169 | 0 | } |
170 | | |
171 | 0 | uint64_t GetCountWithDescendants() const { return m_count_with_descendants; } |
172 | 0 | int64_t GetSizeWithDescendants() const { return nSizeWithDescendants; } |
173 | 0 | CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; } |
174 | | |
175 | 0 | bool GetSpendsCoinbase() const { return spendsCoinbase; } |
176 | | |
177 | 0 | uint64_t GetCountWithAncestors() const { return m_count_with_ancestors; } |
178 | 0 | int64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } |
179 | 0 | CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } |
180 | 0 | int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; } |
181 | | |
182 | 0 | const Parents& GetMemPoolParentsConst() const { return m_parents; } |
183 | 0 | const Children& GetMemPoolChildrenConst() const { return m_children; } |
184 | 0 | Parents& GetMemPoolParents() const { return m_parents; } |
185 | 0 | Children& GetMemPoolChildren() const { return m_children; } |
186 | | |
187 | | mutable size_t idx_randomized; //!< Index in mempool's txns_randomized |
188 | | mutable Epoch::Marker m_epoch_marker; //!< epoch when last touched, useful for graph algorithms |
189 | | }; |
190 | | |
191 | | using CTxMemPoolEntryRef = CTxMemPoolEntry::CTxMemPoolEntryRef; |
192 | | |
193 | | struct TransactionInfo { |
194 | | const CTransactionRef m_tx; |
195 | | /* The fee the transaction paid */ |
196 | | const CAmount m_fee; |
197 | | /** |
198 | | * The virtual transaction size. |
199 | | * |
200 | | * This is a policy field which considers the sigop cost of the |
201 | | * transaction as well as its weight, and reinterprets it as bytes. |
202 | | * |
203 | | * It is the primary metric by which the mining algorithm selects |
204 | | * transactions. |
205 | | */ |
206 | | const int64_t m_virtual_transaction_size; |
207 | | /* The block height the transaction entered the mempool */ |
208 | | const unsigned int txHeight; |
209 | | |
210 | | TransactionInfo(const CTransactionRef& tx, const CAmount& fee, const int64_t vsize, const unsigned int height) |
211 | 0 | : m_tx{tx}, |
212 | 0 | m_fee{fee}, |
213 | 0 | m_virtual_transaction_size{vsize}, |
214 | 0 | txHeight{height} {} |
215 | | }; |
216 | | |
217 | | struct RemovedMempoolTransactionInfo { |
218 | | TransactionInfo info; |
219 | | explicit RemovedMempoolTransactionInfo(const CTxMemPoolEntry& entry) |
220 | 0 | : info{entry.GetSharedTx(), entry.GetFee(), entry.GetTxSize(), entry.GetHeight()} {} |
221 | | }; |
222 | | |
223 | | struct NewMempoolTransactionInfo { |
224 | | TransactionInfo info; |
225 | | /* |
226 | | * This boolean indicates whether the transaction was added |
227 | | * without enforcing mempool fee limits. |
228 | | */ |
229 | | const bool m_mempool_limit_bypassed; |
230 | | /* This boolean indicates whether the transaction is part of a package. */ |
231 | | const bool m_submitted_in_package; |
232 | | /* |
233 | | * This boolean indicates whether the blockchain is up to date when the |
234 | | * transaction is added to the mempool. |
235 | | */ |
236 | | const bool m_chainstate_is_current; |
237 | | /* Indicates whether the transaction has unconfirmed parents. */ |
238 | | const bool m_has_no_mempool_parents; |
239 | | |
240 | | explicit NewMempoolTransactionInfo(const CTransactionRef& tx, const CAmount& fee, |
241 | | const int64_t vsize, const unsigned int height, |
242 | | const bool mempool_limit_bypassed, const bool submitted_in_package, |
243 | | const bool chainstate_is_current, |
244 | | const bool has_no_mempool_parents) |
245 | 0 | : info{tx, fee, vsize, height}, |
246 | 0 | m_mempool_limit_bypassed{mempool_limit_bypassed}, |
247 | 0 | m_submitted_in_package{submitted_in_package}, |
248 | 0 | m_chainstate_is_current{chainstate_is_current}, |
249 | 0 | m_has_no_mempool_parents{has_no_mempool_parents} {} |
250 | | }; |
251 | | |
252 | | #endif // BITCOIN_KERNEL_MEMPOOL_ENTRY_H |