/root/bitcoin/src/txmempool.h
Line | Count | Source |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-present The Bitcoin Core developers |
3 | | // Distributed under the MIT software license, see the accompanying |
4 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | | |
6 | | #ifndef BITCOIN_TXMEMPOOL_H |
7 | | #define BITCOIN_TXMEMPOOL_H |
8 | | |
9 | | #include <coins.h> |
10 | | #include <consensus/amount.h> |
11 | | #include <indirectmap.h> |
12 | | #include <kernel/cs_main.h> |
13 | | #include <kernel/mempool_entry.h> // IWYU pragma: export |
14 | | #include <kernel/mempool_limits.h> // IWYU pragma: export |
15 | | #include <kernel/mempool_options.h> // IWYU pragma: export |
16 | | #include <kernel/mempool_removal_reason.h> // IWYU pragma: export |
17 | | #include <policy/feerate.h> |
18 | | #include <policy/packages.h> |
19 | | #include <primitives/transaction.h> |
20 | | #include <primitives/transaction_identifier.h> |
21 | | #include <sync.h> |
22 | | #include <txgraph.h> |
23 | | #include <util/feefrac.h> |
24 | | #include <util/hasher.h> |
25 | | #include <util/result.h> |
26 | | |
27 | | #include <boost/multi_index/hashed_index.hpp> |
28 | | #include <boost/multi_index/identity.hpp> |
29 | | #include <boost/multi_index/indexed_by.hpp> |
30 | | #include <boost/multi_index/ordered_index.hpp> |
31 | | #include <boost/multi_index/sequenced_index.hpp> |
32 | | #include <boost/multi_index/tag.hpp> |
33 | | #include <boost/multi_index_container.hpp> |
34 | | |
35 | | #include <atomic> |
36 | | #include <map> |
37 | | #include <optional> |
38 | | #include <set> |
39 | | #include <string> |
40 | | #include <string_view> |
41 | | #include <utility> |
42 | | #include <vector> |
43 | | |
44 | | class CChain; |
45 | | class ValidationSignals; |
46 | | |
47 | | struct bilingual_str; |
48 | | |
49 | | /** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */ |
50 | | static const uint32_t MEMPOOL_HEIGHT = 0x7FFFFFFF; |
51 | | |
52 | | /** How much linearization cost required for TxGraph clusters to have |
53 | | * "acceptable" quality, if they cannot be optimally linearized with less cost. */ |
54 | | static constexpr uint64_t ACCEPTABLE_COST = 75'000; |
55 | | |
56 | | /** How much work we ask TxGraph to do after a mempool change occurs (either |
57 | | * due to a changeset being applied, a new block being found, or a reorg). */ |
58 | | static constexpr uint64_t POST_CHANGE_COST = 5 * ACCEPTABLE_COST; |
59 | | |
60 | | /** |
61 | | * Test whether the LockPoints height and time are still valid on the current chain |
62 | | */ |
63 | | bool TestLockPointValidity(CChain& active_chain, const LockPoints& lp) EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
64 | | |
65 | | // extracts a transaction hash from CTxMemPoolEntry or CTransactionRef |
66 | | struct mempoolentry_txid |
67 | | { |
68 | | typedef Txid result_type; |
69 | | result_type operator() (const CTxMemPoolEntry &entry) const |
70 | 0 | { |
71 | 0 | return entry.GetTx().GetHash(); |
72 | 0 | } |
73 | | |
74 | | result_type operator() (const CTransactionRef& tx) const |
75 | 0 | { |
76 | 0 | return tx->GetHash(); |
77 | 0 | } |
78 | | }; |
79 | | |
80 | | // extracts a transaction witness-hash from CTxMemPoolEntry or CTransactionRef |
81 | | struct mempoolentry_wtxid |
82 | | { |
83 | | typedef Wtxid result_type; |
84 | | result_type operator() (const CTxMemPoolEntry &entry) const |
85 | 0 | { |
86 | 0 | return entry.GetTx().GetWitnessHash(); |
87 | 0 | } |
88 | | |
89 | | result_type operator() (const CTransactionRef& tx) const |
90 | 0 | { |
91 | 0 | return tx->GetWitnessHash(); |
92 | 0 | } |
93 | | }; |
94 | | |
95 | | class CompareTxMemPoolEntryByEntryTime |
96 | | { |
97 | | public: |
98 | | bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const |
99 | 0 | { |
100 | 0 | return a.GetTime() < b.GetTime(); |
101 | 0 | } |
102 | | }; |
103 | | |
104 | | // Multi_index tag names |
105 | | struct entry_time {}; |
106 | | struct index_by_wtxid {}; |
107 | | |
108 | | /** |
109 | | * Information about a mempool transaction. |
110 | | */ |
111 | | struct TxMempoolInfo |
112 | | { |
113 | | /** The transaction itself */ |
114 | | CTransactionRef tx; |
115 | | |
116 | | /** Time the transaction entered the mempool. */ |
117 | | std::chrono::seconds m_time; |
118 | | |
119 | | /** Fee of the transaction. */ |
120 | | CAmount fee; |
121 | | |
122 | | /** Virtual size of the transaction. */ |
123 | | int32_t vsize; |
124 | | |
125 | | /** The fee delta. */ |
126 | | int64_t nFeeDelta; |
127 | | }; |
128 | | |
129 | | /** |
130 | | * CTxMemPool stores valid-according-to-the-current-best-chain transactions |
131 | | * that may be included in the next block. |
132 | | * |
133 | | * Transactions are added when they are seen on the network (or created by the |
134 | | * local node), but not all transactions seen are added to the pool. For |
135 | | * example, the following new transactions will not be added to the mempool: |
136 | | * - a transaction which doesn't meet the minimum fee requirements. |
137 | | * - a new transaction that double-spends an input of a transaction already in |
138 | | * the pool where the new transaction does not meet the Replace-By-Fee |
139 | | * requirements as defined in doc/policy/mempool-replacements.md. |
140 | | * - a non-standard transaction. |
141 | | * |
142 | | * TxGraph (CTxMemPool::m_txgraph) provides an abstraction layer for separating |
143 | | * the transaction graph parts of the mempool from the rest of the |
144 | | * Bitcoin-specific logic. Specifically, TxGraph handles (for each transaction) |
145 | | * managing the in-mempool parents and children, and has knowledge of the fee |
146 | | * and size of every transaction. It uses this to partition the mempool into |
147 | | * connected clusters, and it implements (among other things): |
148 | | * - limits on the size of a cluster (in both number of transactions |
149 | | * and total weight) |
150 | | * - sorting the mempool optimally for block inclusion, taking into account |
151 | | * dependencies |
152 | | * - selecting transactions for removal due to cluster size limit violations |
153 | | * after a reorg. |
154 | | * See txgraph.h and txgraph.cpp for more details. |
155 | | * |
156 | | * CTxMemPool itself handles the Bitcoin-specific parts of mempool |
157 | | * transactions; it stores the full transaction inside CTxMemPoolEntry, along |
158 | | * with other consensus-specific fields (such as whether a transaction spends a |
159 | | * coinbase, or the LockPoints for transaction finality). And it provides |
160 | | * interfaces to the rest of the codebase, such as: |
161 | | * - to validation for replace-by-fee calculations and cluster size limits |
162 | | * when evaluating unconfirmed transactions |
163 | | * - to validation for evicting transactions due to expiry or the mempool size |
164 | | * limit being hit |
165 | | * - to validation for updating the mempool to be consistent with the best |
166 | | * chain after a new block is connected or after a reorg. |
167 | | * - to net_processing for ordering transactions that are to-be-announced to |
168 | | * other peers |
169 | | * - to RPC code for inspecting the mempool |
170 | | * |
171 | | * (Many of these interfaces are just wrappers around corresponding TxGraph |
172 | | * functions.) |
173 | | * |
174 | | * Within CTxMemPool, the mempool entries are stored in a boost::multi_index |
175 | | * mapTx, which sorts the mempool on 3 criteria: |
176 | | * - transaction hash (txid) |
177 | | * - witness-transaction hash (wtxid) |
178 | | * - time in mempool |
179 | | * |
180 | | * We also maintain a map from COutPoint to the (in-mempool) transaction that |
181 | | * spends it (mapNextTx). This allows us to recover from a reorg and find |
182 | | * transactions in the mempool that conflict with transactions that are |
183 | | * confirmed in a block. |
184 | | * |
185 | | */ |
186 | | class CTxMemPool |
187 | | { |
188 | | protected: |
189 | | std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation |
190 | | |
191 | | uint64_t totalTxSize GUARDED_BY(cs){0}; //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141. |
192 | | CAmount m_total_fee GUARDED_BY(cs){0}; //!< sum of all mempool tx's fees (NOT modified fee) |
193 | | uint64_t cachedInnerUsage GUARDED_BY(cs){0}; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves) |
194 | | |
195 | | mutable int64_t lastRollingFeeUpdate GUARDED_BY(cs){GetTime()}; |
196 | | mutable bool blockSinceLastRollingFeeBump GUARDED_BY(cs){false}; |
197 | | mutable double rollingMinimumFeeRate GUARDED_BY(cs){0}; //!< minimum fee to get into the pool, decreases exponentially |
198 | | |
199 | | // In-memory counter for external mempool tracking purposes. |
200 | | // This number is incremented once every time a transaction |
201 | | // is added or removed from the mempool for any reason. |
202 | | mutable uint64_t m_sequence_number GUARDED_BY(cs){1}; |
203 | | |
204 | | void trackPackageRemoved(const CFeeRate& rate) EXCLUSIVE_LOCKS_REQUIRED(cs); |
205 | | |
206 | | bool m_load_tried GUARDED_BY(cs){false}; |
207 | | |
208 | | CFeeRate GetMinFee(size_t sizelimit) const; |
209 | | |
210 | | public: |
211 | | |
212 | | static const int ROLLING_FEE_HALFLIFE = 60 * 60 * 12; // public only for testing |
213 | | |
214 | | struct CTxMemPoolEntry_Indices final : boost::multi_index::indexed_by< |
215 | | // sorted by txid |
216 | | boost::multi_index::hashed_unique<mempoolentry_txid, SaltedTxidHasher>, |
217 | | // sorted by wtxid |
218 | | boost::multi_index::hashed_unique< |
219 | | boost::multi_index::tag<index_by_wtxid>, |
220 | | mempoolentry_wtxid, |
221 | | SaltedWtxidHasher |
222 | | >, |
223 | | // sorted by entry time |
224 | | boost::multi_index::ordered_non_unique< |
225 | | boost::multi_index::tag<entry_time>, |
226 | | boost::multi_index::identity<CTxMemPoolEntry>, |
227 | | CompareTxMemPoolEntryByEntryTime |
228 | | > |
229 | | > |
230 | | {}; |
231 | | typedef boost::multi_index_container< |
232 | | CTxMemPoolEntry, |
233 | | CTxMemPoolEntry_Indices |
234 | | > indexed_transaction_set; |
235 | | |
236 | | /** |
237 | | * This mutex needs to be locked when accessing `mapTx` or other members |
238 | | * that are guarded by it. |
239 | | * |
240 | | * @par Consistency guarantees |
241 | | * By design, it is guaranteed that: |
242 | | * 1. Locking both `cs_main` and `mempool.cs` will give a view of mempool |
243 | | * that is consistent with current chain tip (`ActiveChain()` and |
244 | | * `CoinsTip()`) and is fully populated. Fully populated means that if the |
245 | | * current active chain is missing transactions that were present in a |
246 | | * previously active chain, all the missing transactions will have been |
247 | | * re-added to the mempool and should be present if they meet size and |
248 | | * consistency constraints. |
249 | | * 2. Locking `mempool.cs` without `cs_main` will give a view of a mempool |
250 | | * consistent with some chain that was active since `cs_main` was last |
251 | | * locked, and that is fully populated as described above. It is ok for |
252 | | * code that only needs to query or remove transactions from the mempool |
253 | | * to lock just `mempool.cs` without `cs_main`. |
254 | | * |
255 | | * To provide these guarantees, it is necessary to lock both `cs_main` and |
256 | | * `mempool.cs` whenever adding transactions to the mempool and whenever |
257 | | * changing the chain tip. It's necessary to keep both mutexes locked until |
258 | | * the mempool is consistent with the new chain tip and fully populated. |
259 | | */ |
260 | | mutable RecursiveMutex cs ACQUIRED_AFTER(::cs_main); |
261 | | std::unique_ptr<TxGraph> m_txgraph GUARDED_BY(cs); |
262 | | mutable std::unique_ptr<TxGraph::BlockBuilder> m_builder GUARDED_BY(cs); |
263 | | indexed_transaction_set mapTx GUARDED_BY(cs); |
264 | | |
265 | | using txiter = indexed_transaction_set::nth_index<0>::type::const_iterator; |
266 | | std::vector<std::pair<Wtxid, txiter>> txns_randomized GUARDED_BY(cs); //!< All transactions in mapTx with their wtxids, in arbitrary order |
267 | | |
268 | | typedef std::set<txiter, CompareIteratorByHash> setEntries; |
269 | | |
270 | | using Limits = kernel::MemPoolLimits; |
271 | | |
272 | | std::tuple<size_t, size_t, CAmount> CalculateAncestorData(const CTxMemPoolEntry& entry) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
273 | | std::tuple<size_t, size_t, CAmount> CalculateDescendantData(const CTxMemPoolEntry& entry) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
274 | 0 | int64_t GetDescendantCount(txiter it) const { LOCK(cs); return m_txgraph->GetDescendants(*it, TxGraph::Level::MAIN).size(); } |
275 | 0 | int64_t GetDescendantCount(const CTxMemPoolEntry &e) const { LOCK(cs); return m_txgraph->GetDescendants(e, TxGraph::Level::MAIN).size(); }Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
276 | 0 | int64_t GetAncestorCount(const CTxMemPoolEntry &e) const { LOCK(cs); return m_txgraph->GetAncestors(e, TxGraph::Level::MAIN).size(); }Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
277 | | std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef> GetChildren(const CTxMemPoolEntry &entry) const; |
278 | | std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef> GetParents(const CTxMemPoolEntry &entry) const; |
279 | | |
280 | | private: |
281 | | std::vector<indexed_transaction_set::const_iterator> GetSortedScoreWithTopology() const EXCLUSIVE_LOCKS_REQUIRED(cs); |
282 | | |
283 | | /** |
284 | | * Track locally submitted transactions to periodically retry initial broadcast. |
285 | | */ |
286 | | std::set<Txid> m_unbroadcast_txids GUARDED_BY(cs); |
287 | | |
288 | | static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) |
289 | 0 | { |
290 | 0 | return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()}; |
291 | 0 | } |
292 | | |
293 | | // Helper to remove all transactions that conflict with a given |
294 | | // transaction (used for transactions appearing in a block). |
295 | | void removeConflicts(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs); |
296 | | |
297 | | public: |
298 | | indirectmap<COutPoint, txiter> mapNextTx GUARDED_BY(cs); |
299 | | std::map<Txid, CAmount> mapDeltas GUARDED_BY(cs); |
300 | | |
301 | | using Options = kernel::MemPoolOptions; |
302 | | |
303 | | const Options m_opts; |
304 | | |
305 | | /** Create a new CTxMemPool. |
306 | | * Sanity checks will be off by default for performance, because otherwise |
307 | | * accepting transactions becomes O(N^2) where N is the number of transactions |
308 | | * in the pool. |
309 | | */ |
310 | | explicit CTxMemPool(Options opts, bilingual_str& error); |
311 | | |
312 | | /** |
313 | | * If sanity-checking is turned on, check makes sure the pool is |
314 | | * consistent (does not contain two transactions that spend the same inputs, |
315 | | * all inputs are in the mapNextTx array). If sanity-checking is turned off, |
316 | | * check does nothing. |
317 | | */ |
318 | | void check(const CCoinsViewCache& active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
319 | | |
320 | | /** |
321 | | * Remove a transaction from the mempool along with any descendants. |
322 | | * If the transaction is not already in the mempool, find any descendants |
323 | | * and remove them. |
324 | | */ |
325 | | void removeRecursive(const CTransaction& tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs); |
326 | | /** After reorg, filter the entries that would no longer be valid in the next block, and update |
327 | | * the entries' cached LockPoints if needed. The mempool does not have any knowledge of |
328 | | * consensus rules. It just applies the callable function and removes the ones for which it |
329 | | * returns true. |
330 | | * @param[in] filter_final_and_mature Predicate that checks the relevant validation rules |
331 | | * and updates an entry's LockPoints. |
332 | | * */ |
333 | | void removeForReorg(CChain& chain, std::function<bool(txiter)> filter_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); |
334 | | void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs); |
335 | | |
336 | | bool CompareMiningScoreWithTopology(const Wtxid& hasha, const Wtxid& hashb) const; |
337 | | bool isSpent(const COutPoint& outpoint) const; |
338 | | unsigned int GetTransactionsUpdated() const; |
339 | | void AddTransactionsUpdated(unsigned int n); |
340 | | /** |
341 | | * Check that none of this transactions inputs are in the mempool, and thus |
342 | | * the tx is not dependent on other mempool transactions to be included in a block. |
343 | | */ |
344 | | bool HasNoInputsOf(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
345 | | |
346 | | /** Affect CreateNewBlock prioritisation of transactions */ |
347 | | void PrioritiseTransaction(const Txid& hash, const CAmount& nFeeDelta); |
348 | | void ApplyDelta(const Txid& hash, CAmount &nFeeDelta) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
349 | | void ClearPrioritisation(const Txid& hash) EXCLUSIVE_LOCKS_REQUIRED(cs); |
350 | | |
351 | | struct delta_info { |
352 | | /** Whether this transaction is in the mempool. */ |
353 | | const bool in_mempool; |
354 | | /** The fee delta added using PrioritiseTransaction(). */ |
355 | | const CAmount delta; |
356 | | /** The modified fee (base fee + delta) of this entry. Only present if in_mempool=true. */ |
357 | | std::optional<CAmount> modified_fee; |
358 | | /** The prioritised transaction's txid. */ |
359 | | const Txid txid; |
360 | | }; |
361 | | /** Return a vector of all entries in mapDeltas with their corresponding delta_info. */ |
362 | | std::vector<delta_info> GetPrioritisedTransactions() const EXCLUSIVE_LOCKS_REQUIRED(!cs); |
363 | | |
364 | | /** Get the transaction in the pool that spends the same prevout */ |
365 | | const CTransaction* GetConflictTx(const COutPoint& prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
366 | | |
367 | | /** Returns an iterator to the given hash, if found */ |
368 | | std::optional<txiter> GetIter(const Txid& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
369 | | std::optional<txiter> GetIter(const Wtxid& wtxid) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
370 | | |
371 | | /** Translate a set of hashes into a set of pool iterators to avoid repeated lookups. |
372 | | * Does not require that all of the hashes correspond to actual transactions in the mempool, |
373 | | * only returns the ones that exist. */ |
374 | | setEntries GetIterSet(const std::set<Txid>& hashes) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
375 | | |
376 | | /** Translate a list of hashes into a list of mempool iterators to avoid repeated lookups. |
377 | | * The nth element in txids becomes the nth element in the returned vector. If any of the txids |
378 | | * don't actually exist in the mempool, returns an empty vector. */ |
379 | | std::vector<txiter> GetIterVec(const std::vector<Txid>& txids) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
380 | | |
381 | | /** UpdateTransactionsFromBlock is called when adding transactions from a |
382 | | * disconnected block back to the mempool, new mempool entries may have |
383 | | * children in the mempool (which is generally not the case when otherwise |
384 | | * adding transactions). |
385 | | * @post updated descendant state for descendants of each transaction in |
386 | | * vHashesToUpdate (excluding any child transactions present in |
387 | | * vHashesToUpdate, which are already accounted for). Updated state |
388 | | * includes add fee/size information for such descendants to the |
389 | | * parent and updated ancestor state to include the parent. |
390 | | * |
391 | | * @param[in] vHashesToUpdate The set of txids from the |
392 | | * disconnected block that have been accepted back into the mempool. |
393 | | */ |
394 | | void UpdateTransactionsFromBlock(const std::vector<Txid>& vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); |
395 | | |
396 | | std::vector<FeePerWeight> GetFeerateDiagram() const EXCLUSIVE_LOCKS_REQUIRED(cs); |
397 | 0 | FeePerWeight GetMainChunkFeerate(const CTxMemPoolEntry& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs) { |
398 | 0 | return m_txgraph->GetMainChunkFeerate(tx); |
399 | 0 | } |
400 | 0 | std::vector<const CTxMemPoolEntry*> GetCluster(Txid txid) const EXCLUSIVE_LOCKS_REQUIRED(cs) { |
401 | 0 | auto tx = GetIter(txid); |
402 | 0 | if (!tx) return {}; |
403 | 0 | auto cluster = m_txgraph->GetCluster(**tx, TxGraph::Level::MAIN); |
404 | 0 | std::vector<const CTxMemPoolEntry*> ret; |
405 | 0 | ret.reserve(cluster.size()); |
406 | 0 | for (const auto& tx : cluster) { |
407 | 0 | ret.emplace_back(static_cast<const CTxMemPoolEntry*>(tx)); |
408 | 0 | } |
409 | 0 | return ret; |
410 | 0 | } |
411 | | |
412 | | |
413 | 0 | size_t GetUniqueClusterCount(const setEntries& iters_conflicting) const EXCLUSIVE_LOCKS_REQUIRED(cs) { |
414 | 0 | std::vector<const TxGraph::Ref *> entries; |
415 | 0 | entries.reserve(iters_conflicting.size()); |
416 | 0 | for (auto it : iters_conflicting) { |
417 | 0 | entries.emplace_back(&*it); |
418 | 0 | } |
419 | 0 | Assume(!m_txgraph->IsOversized(TxGraph::Level::MAIN)); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
420 | 0 | return m_txgraph->CountDistinctClusters(entries, TxGraph::Level::MAIN); |
421 | 0 | } |
422 | | |
423 | | /** |
424 | | * Calculate all in-mempool ancestors of entry (not including the tx itself) |
425 | | * |
426 | | * @param[in] entry CTxMemPoolEntry of which all in-mempool ancestors are calculated |
427 | | * |
428 | | * @return all in-mempool ancestors |
429 | | */ |
430 | | setEntries CalculateMemPoolAncestors(const CTxMemPoolEntry& entry) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
431 | | |
432 | | bool HasDescendants(const Txid& txid) const; |
433 | | |
434 | | /** Collect the entire cluster of connected transactions for each transaction in txids. |
435 | | * All txids must correspond to transaction entries in the mempool, otherwise this returns an |
436 | | * empty vector. This call will also exit early and return an empty vector if it collects 500 or |
437 | | * more transactions as a DoS protection. */ |
438 | | std::vector<txiter> GatherClusters(const std::vector<Txid>& txids) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
439 | | |
440 | | /** Populate setDescendants with all in-mempool descendants of given transaction. |
441 | | * Assumes that setDescendants includes all in-mempool descendants of anything |
442 | | * already in it. */ |
443 | | void CalculateDescendants(txiter it, setEntries& setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
444 | | CTxMemPool::txiter CalculateDescendants(const CTxMemPoolEntry& entry, setEntries& setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs); |
445 | | |
446 | | /** The minimum fee to get into the mempool, which may itself not be enough |
447 | | * for larger-sized transactions. |
448 | | * The m_incremental_relay_feerate policy variable is used to bound the time it |
449 | | * takes the fee rate to go back down all the way to 0. When the feerate |
450 | | * would otherwise be half of this, it is set to 0 instead. |
451 | | */ |
452 | 0 | CFeeRate GetMinFee() const { |
453 | 0 | return GetMinFee(m_opts.max_size_bytes); |
454 | 0 | } |
455 | | |
456 | | /** Remove transactions from the mempool until its dynamic size is <= sizelimit. |
457 | | * pvNoSpendsRemaining, if set, will be populated with the list of outpoints |
458 | | * which are not in mempool which no longer have any spends in this mempool. |
459 | | */ |
460 | | void TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpendsRemaining = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs); |
461 | | |
462 | | /** Expire all transaction (and their dependencies) in the mempool older than time. Return the number of removed transactions. */ |
463 | | int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs); |
464 | | |
465 | | /** |
466 | | * Calculate the ancestor and cluster count for the given transaction. |
467 | | * The counts include the transaction itself. |
468 | | * When ancestors is non-zero (ie, the transaction itself is in the mempool), |
469 | | * ancestorsize and ancestorfees will also be set to the appropriate values. |
470 | | */ |
471 | | void GetTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& cluster_count, size_t* ancestorsize = nullptr, CAmount* ancestorfees = nullptr) const; |
472 | | |
473 | | /** |
474 | | * @returns true if an initial attempt to load the persisted mempool was made, regardless of |
475 | | * whether the attempt was successful or not |
476 | | */ |
477 | | bool GetLoadTried() const; |
478 | | |
479 | | /** |
480 | | * Set whether or not an initial attempt to load the persisted mempool was made (regardless |
481 | | * of whether the attempt was successful or not) |
482 | | */ |
483 | | void SetLoadTried(bool load_tried); |
484 | | |
485 | | unsigned long size() const |
486 | 0 | { |
487 | 0 | LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
488 | 0 | return mapTx.size(); |
489 | 0 | } |
490 | | |
491 | | uint64_t GetTotalTxSize() const EXCLUSIVE_LOCKS_REQUIRED(cs) |
492 | 0 | { |
493 | 0 | AssertLockHeld(cs); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
494 | 0 | return totalTxSize; |
495 | 0 | } |
496 | | |
497 | | CAmount GetTotalFee() const EXCLUSIVE_LOCKS_REQUIRED(cs) |
498 | 0 | { |
499 | 0 | AssertLockHeld(cs); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
500 | 0 | return m_total_fee; |
501 | 0 | } |
502 | | |
503 | | bool exists(const Txid& txid) const |
504 | 0 | { |
505 | 0 | LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
506 | 0 | return (mapTx.count(txid) != 0); |
507 | 0 | } |
508 | | |
509 | | bool exists(const Wtxid& wtxid) const |
510 | 0 | { |
511 | 0 | LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
512 | 0 | return (mapTx.get<index_by_wtxid>().count(wtxid) != 0); |
513 | 0 | } |
514 | | |
515 | | const CTxMemPoolEntry* GetEntry(const Txid& txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs); |
516 | | |
517 | | CTransactionRef get(const Txid& hash) const; |
518 | | |
519 | | template <TxidOrWtxid T> |
520 | | TxMempoolInfo info(const T& id) const |
521 | 0 | { |
522 | 0 | LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
| LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
523 | 0 | auto i{GetIter(id)}; |
524 | 0 | return i.has_value() ? GetInfo(*i) : TxMempoolInfo{}; |
525 | 0 | } Unexecuted instantiation: _ZNK10CTxMemPool4infoITk11TxidOrWtxid22transaction_identifierILb0EEEE13TxMempoolInfoRKT_ Unexecuted instantiation: _ZNK10CTxMemPool4infoITk11TxidOrWtxid22transaction_identifierILb1EEEE13TxMempoolInfoRKT_ |
526 | | |
527 | | /** Returns info for a transaction if its entry_sequence < last_sequence */ |
528 | | template <TxidOrWtxid T> |
529 | | TxMempoolInfo info_for_relay(const T& id, uint64_t last_sequence) const |
530 | 0 | { |
531 | 0 | LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
| LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
532 | 0 | auto i{GetIter(id)}; |
533 | 0 | return (i.has_value() && i.value()->GetSequence() < last_sequence) ? GetInfo(*i) : TxMempoolInfo{}; |
534 | 0 | } Unexecuted instantiation: _ZNK10CTxMemPool14info_for_relayITk11TxidOrWtxid22transaction_identifierILb0EEEE13TxMempoolInfoRKT_m Unexecuted instantiation: _ZNK10CTxMemPool14info_for_relayITk11TxidOrWtxid22transaction_identifierILb1EEEE13TxMempoolInfoRKT_m |
535 | | |
536 | | std::vector<CTxMemPoolEntryRef> entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs); |
537 | | std::vector<TxMempoolInfo> infoAll() const; |
538 | | |
539 | | size_t DynamicMemoryUsage() const; |
540 | | |
541 | | /** Adds a transaction to the unbroadcast set */ |
542 | | void AddUnbroadcastTx(const Txid& txid) |
543 | 0 | { |
544 | 0 | LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
545 | | // Sanity check the transaction is in the mempool & insert into |
546 | | // unbroadcast set. |
547 | 0 | if (exists(txid)) m_unbroadcast_txids.insert(txid); |
548 | 0 | }; |
549 | | |
550 | | bool CheckPolicyLimits(const CTransactionRef& tx); |
551 | | |
552 | | /** Removes a transaction from the unbroadcast set */ |
553 | | void RemoveUnbroadcastTx(const Txid& txid, bool unchecked = false); |
554 | | |
555 | | /** Returns transactions in unbroadcast set */ |
556 | | std::set<Txid> GetUnbroadcastTxs() const |
557 | 0 | { |
558 | 0 | LOCK(cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
559 | 0 | return m_unbroadcast_txids; |
560 | 0 | } |
561 | | |
562 | | /** Returns whether a txid is in the unbroadcast set */ |
563 | | bool IsUnbroadcastTx(const Txid& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs) |
564 | 0 | { |
565 | 0 | AssertLockHeld(cs); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
566 | 0 | return m_unbroadcast_txids.contains(txid); |
567 | 0 | } |
568 | | |
569 | | /** Guards this internal counter for external reporting */ |
570 | 0 | uint64_t GetAndIncrementSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs) { |
571 | 0 | return m_sequence_number++; |
572 | 0 | } |
573 | | |
574 | 0 | uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs) { |
575 | 0 | return m_sequence_number; |
576 | 0 | } |
577 | | |
578 | | private: |
579 | | /** Remove a set of transactions from the mempool. |
580 | | * If a transaction is in this set, then all in-mempool descendants must |
581 | | * also be in the set, unless this transaction is being removed for being |
582 | | * in a block. |
583 | | */ |
584 | | void RemoveStaged(setEntries& stage, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs); |
585 | | |
586 | | /* Helper for the public removeRecursive() */ |
587 | | void removeRecursive(txiter to_remove, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs); |
588 | | |
589 | | /* Removal from the mempool also triggers removal of the entry's Ref from txgraph. */ |
590 | | void removeUnchecked(txiter entry, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs); |
591 | | public: |
592 | | /* |
593 | | * CTxMemPool::ChangeSet: |
594 | | * |
595 | | * This class is used for all mempool additions and associated removals (eg |
596 | | * due to rbf). Removals that don't need to be evaluated for acceptance, |
597 | | * such as removing transactions that appear in a block, or due to reorg, |
598 | | * or removals related to mempool limiting or expiry do not need to use |
599 | | * this. |
600 | | * |
601 | | * Callers can interleave calls to StageAddition()/StageRemoval(), and |
602 | | * removals may be invoked in any order, but additions must be done in a |
603 | | * topological order in the case of transaction packages (ie, parents must |
604 | | * be added before children). |
605 | | * |
606 | | * CalculateChunksForRBF() can be used to calculate the feerate diagram of |
607 | | * the proposed set of new transactions and compare with the existing |
608 | | * mempool. |
609 | | * |
610 | | * CalculateMemPoolAncestors() calculates the in-mempool (not including |
611 | | * what is in the change set itself) ancestors of a given transaction. |
612 | | * |
613 | | * Apply() will apply the removals and additions that are staged into the |
614 | | * mempool. |
615 | | * |
616 | | * Only one changeset may exist at a time. While a changeset is |
617 | | * outstanding, no removals or additions may be made directly to the |
618 | | * mempool. |
619 | | */ |
620 | | class ChangeSet { |
621 | | public: |
622 | 0 | explicit ChangeSet(CTxMemPool* pool) : m_pool(pool) { m_pool->m_txgraph->StartStaging(); } |
623 | 0 | ~ChangeSet() EXCLUSIVE_LOCKS_REQUIRED(m_pool->cs) { |
624 | 0 | AssertLockHeld(m_pool->cs); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
625 | 0 | if (m_pool->m_txgraph->HaveStaging()) { |
626 | 0 | m_pool->m_txgraph->AbortStaging(); |
627 | 0 | } |
628 | 0 | m_pool->m_have_changeset = false; |
629 | 0 | } |
630 | | |
631 | | ChangeSet(const ChangeSet&) = delete; |
632 | | ChangeSet& operator=(const ChangeSet&) = delete; |
633 | | |
634 | | using TxHandle = CTxMemPool::txiter; |
635 | | |
636 | | TxHandle StageAddition(const CTransactionRef& tx, CAmount fee, int64_t time, unsigned int entry_height, uint64_t entry_sequence, bool spends_coinbase, int64_t sigops_cost, LockPoints lp); |
637 | | |
638 | | void StageRemoval(CTxMemPool::txiter it); |
639 | | |
640 | 0 | const CTxMemPool::setEntries& GetRemovals() const { return m_to_remove; } |
641 | | |
642 | | /** Check if any cluster limits are exceeded. Returns true if pass, false if fail. */ |
643 | | bool CheckMemPoolPolicyLimits(); |
644 | | |
645 | | CTxMemPool::setEntries CalculateMemPoolAncestors(TxHandle tx) |
646 | 0 | { |
647 | | // Look up transaction in our cache first |
648 | 0 | auto it = m_ancestors.find(tx); |
649 | 0 | if (it != m_ancestors.end()) return it->second; |
650 | | |
651 | | // If not found, try to have the mempool calculate it, and cache |
652 | | // for later. |
653 | 0 | LOCK(m_pool->cs); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
654 | 0 | auto ret = m_pool->CalculateMemPoolAncestors(*tx); |
655 | 0 | m_ancestors.try_emplace(tx, ret); |
656 | 0 | return ret; |
657 | 0 | } |
658 | | |
659 | 0 | std::vector<CTransactionRef> GetAddedTxns() const { |
660 | 0 | std::vector<CTransactionRef> ret; |
661 | 0 | ret.reserve(m_entry_vec.size()); |
662 | 0 | for (const auto& entry : m_entry_vec) { |
663 | 0 | ret.emplace_back(entry->GetSharedTx()); |
664 | 0 | } |
665 | 0 | return ret; |
666 | 0 | } |
667 | | |
668 | | /** |
669 | | * Calculate the sorted chunks for the old and new mempool relating to the |
670 | | * clusters that would be affected by a potential replacement transaction. |
671 | | * |
672 | | * @return old and new diagram pair respectively, or an error string if the conflicts don't match a calculable topology |
673 | | */ |
674 | | util::Result<std::pair<std::vector<FeeFrac>, std::vector<FeeFrac>>> CalculateChunksForRBF(); |
675 | | |
676 | 0 | size_t GetTxCount() const { return m_entry_vec.size(); } |
677 | 0 | const CTransaction& GetAddedTxn(size_t index) const { return m_entry_vec.at(index)->GetTx(); } |
678 | | |
679 | | void Apply() EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
680 | | |
681 | | private: |
682 | | void ProcessDependencies(); |
683 | | |
684 | | CTxMemPool* m_pool; |
685 | | CTxMemPool::indexed_transaction_set m_to_add; |
686 | | std::vector<CTxMemPool::txiter> m_entry_vec; // track the added transactions' insertion order |
687 | | // map from the m_to_add index to the ancestors for the transaction |
688 | | std::map<CTxMemPool::txiter, CTxMemPool::setEntries, CompareIteratorByHash> m_ancestors; |
689 | | CTxMemPool::setEntries m_to_remove; |
690 | | bool m_dependencies_processed{false}; |
691 | | |
692 | | friend class CTxMemPool; |
693 | | }; |
694 | | |
695 | 0 | std::unique_ptr<ChangeSet> GetChangeSet() EXCLUSIVE_LOCKS_REQUIRED(cs) { |
696 | 0 | Assume(!m_have_changeset); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
697 | 0 | m_have_changeset = true; |
698 | 0 | return std::make_unique<ChangeSet>(this); |
699 | 0 | } |
700 | | |
701 | | bool m_have_changeset GUARDED_BY(cs){false}; |
702 | | |
703 | | friend class CTxMemPool::ChangeSet; |
704 | | |
705 | | private: |
706 | | // Apply the given changeset to the mempool, by removing transactions in |
707 | | // the to_remove set and adding transactions in the to_add set. |
708 | | void Apply(CTxMemPool::ChangeSet* changeset) EXCLUSIVE_LOCKS_REQUIRED(cs); |
709 | | |
710 | | // addNewTransaction must update state for all ancestors of a given transaction, |
711 | | // to track size/count of descendant transactions. First version of |
712 | | // addNewTransaction can be used to have it call CalculateMemPoolAncestors(), and |
713 | | // then invoke the second version. |
714 | | // Note that addNewTransaction is ONLY called (via Apply()) from ATMP |
715 | | // outside of tests and any other callers may break wallet's in-mempool |
716 | | // tracking (due to lack of CValidationInterface::TransactionAddedToMempool |
717 | | // callbacks). |
718 | | void addNewTransaction(CTxMemPool::txiter it) EXCLUSIVE_LOCKS_REQUIRED(cs); |
719 | | public: |
720 | 0 | void StartBlockBuilding() const EXCLUSIVE_LOCKS_REQUIRED(cs) { assert(!m_builder); m_builder = m_txgraph->GetBlockBuilder(); } |
721 | | FeePerWeight GetBlockBuilderChunk(std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef>& entries) const EXCLUSIVE_LOCKS_REQUIRED(cs) |
722 | 0 | { |
723 | 0 | if (!m_builder) { return {}; } |
724 | | |
725 | 0 | auto res = m_builder->GetCurrentChunk(); |
726 | 0 | if (!res) { return {}; } |
727 | | |
728 | 0 | auto [chunk_entries, chunk_feerate] = *res; |
729 | 0 | for (TxGraph::Ref* ref : chunk_entries) { |
730 | 0 | entries.emplace_back(static_cast<const CTxMemPoolEntry&>(*ref)); |
731 | 0 | } |
732 | 0 | return chunk_feerate; |
733 | 0 | } |
734 | 0 | void IncludeBuilderChunk() const EXCLUSIVE_LOCKS_REQUIRED(cs) { m_builder->Include(); } |
735 | 0 | void SkipBuilderChunk() const EXCLUSIVE_LOCKS_REQUIRED(cs) { m_builder->Skip(); } |
736 | 0 | void StopBlockBuilding() const EXCLUSIVE_LOCKS_REQUIRED(cs) { m_builder.reset(); } |
737 | | }; |
738 | | |
739 | | /** |
740 | | * CCoinsView that brings transactions from a mempool into view. |
741 | | * It does not check for spendings by memory pool transactions. |
742 | | * Instead, it provides access to all Coins which are either unspent in the |
743 | | * base CCoinsView, are outputs from any mempool transaction, or are |
744 | | * tracked temporarily to allow transaction dependencies in package validation. |
745 | | * This allows transaction replacement to work as expected, as you want to |
746 | | * have all inputs "available" to check signatures, and any cycles in the |
747 | | * dependency graph are checked directly in AcceptToMemoryPool. |
748 | | * It also allows you to sign a double-spend directly in |
749 | | * signrawtransactionwithkey and signrawtransactionwithwallet, |
750 | | * as long as the conflicting transaction is not yet confirmed. |
751 | | */ |
752 | | class CCoinsViewMemPool : public CCoinsViewBacked |
753 | | { |
754 | | /** |
755 | | * Coins made available by transactions being validated. Tracking these allows for package |
756 | | * validation, since we can access transaction outputs without submitting them to mempool. |
757 | | */ |
758 | | std::unordered_map<COutPoint, Coin, SaltedOutpointHasher> m_temp_added; |
759 | | |
760 | | /** |
761 | | * Set of all coins that have been fetched from mempool or created using PackageAddTransaction |
762 | | * (not base). Used to track the origin of a coin, see GetNonBaseCoins(). |
763 | | */ |
764 | | mutable std::unordered_set<COutPoint, SaltedOutpointHasher> m_non_base_coins; |
765 | | protected: |
766 | | const CTxMemPool& mempool; |
767 | | |
768 | | public: |
769 | | CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn); |
770 | | /** GetCoin, returning whether it exists and is not spent. Also updates m_non_base_coins if the |
771 | | * coin is not fetched from base. */ |
772 | | std::optional<Coin> GetCoin(const COutPoint& outpoint) const override; |
773 | | /** Add the coins created by this transaction. These coins are only temporarily stored in |
774 | | * m_temp_added and cannot be flushed to the back end. Only used for package validation. */ |
775 | | void PackageAddTransaction(const CTransactionRef& tx); |
776 | | /** Get all coins in m_non_base_coins. */ |
777 | 0 | const std::unordered_set<COutPoint, SaltedOutpointHasher>& GetNonBaseCoins() const { return m_non_base_coins; } |
778 | | /** Clear m_temp_added and m_non_base_coins. */ |
779 | | void Reset(); |
780 | | }; |
781 | | #endif // BITCOIN_TXMEMPOOL_H |