Bitcoin ABC 0.30.5
P2P Digital Currency
disconnected_transactions.h
Go to the documentation of this file.
1// Copyright (c) 2023 The Bitcoin Core developers
2// Copyright (c) 2024 The Bitcoin 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_KERNEL_DISCONNECTED_TRANSACTIONS_H
7#define BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H
8
9#include <consensus/amount.h>
10#include <memusage.h>
11#include <threadsafety.h>
12#include <txmempool.h>
13#include <util/hasher.h>
14
15#include <boost/multi_index/hashed_index.hpp>
16#include <boost/multi_index/sequenced_index.hpp>
17#include <boost/multi_index_container.hpp>
18
19#include <cassert>
20#include <unordered_map>
21#include <vector>
22
41// multi_index tag names
42struct txid_index {};
44
46private:
47 typedef boost::multi_index_container<
48 CTransactionRef, boost::multi_index::indexed_by<
49 // hashed by txid
50 boost::multi_index::hashed_unique<
51 boost::multi_index::tag<txid_index>,
53 // sorted by order in the blockchain
54 boost::multi_index::sequenced<
55 boost::multi_index::tag<insertion_order>>>>
57
59 uint64_t cachedInnerUsage = 0;
60
61 struct TxInfo {
62 const std::chrono::seconds time;
64 const unsigned height;
65 TxInfo(const std::chrono::seconds &time_, Amount feeDelta_,
66 unsigned height_) noexcept
67 : time(time_), feeDelta(feeDelta_), height(height_) {}
68 };
69
70 using TxInfoMap = std::unordered_map<TxId, TxInfo, SaltedTxIdHasher>;
73
75 queuedTx.insert(tx);
77 }
78
82 const TxInfo *getTxInfo(const CTransactionRef &tx) const;
83
84public:
85 // It's almost certainly a logic bug if we don't clear out queuedTx before
86 // destruction, as we add to it while disconnecting blocks, and then we
87 // need to re-process remaining transactions to ensure mempool consistency.
88 // For now, assert() that we've emptied out this object on destruction.
89 // This assert() can always be removed if the reorg-processing code were
90 // to be refactored such that this assumption is no longer true (for
91 // instance if there was some other way we cleaned up the mempool after a
92 // reorg, besides draining this object).
94
95 // Estimate the overhead of queuedTx to be 6 pointers + an allocation, as
96 // no exact formula for boost::multi_index_contained is implemented.
97 size_t DynamicMemoryUsage() const {
99 6 * sizeof(void *)) *
100 queuedTx.size() +
102 }
103
105 return queuedTx;
106 }
107
108 // Import mempool entries in topological order into queuedTx and clear the
109 // mempool. Caller should call updateMempoolForReorg to reprocess these
110 // transactions
112
113 // Add entries for a block while reconstructing the topological ordering so
114 // they can be added back to the mempool simply.
115 void addForBlock(const std::vector<CTransactionRef> &vtx, CTxMemPool &pool)
117
118 // Remove entries based on txid_index, and update memory usage.
119 void removeForBlock(const std::vector<CTransactionRef> &vtx) {
120 // Short-circuit in the common case of a block being added to the tip
121 if (queuedTx.empty()) {
122 return;
123 }
124 for (auto const &tx : vtx) {
125 auto it = queuedTx.find(tx->GetId());
126 if (it != queuedTx.end()) {
128 queuedTx.erase(it);
129 txInfo.erase(tx->GetId());
130 }
131 }
132 }
133
134 void removeForBlock(const std::vector<CTransactionRef> &vtx,
135 CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
136
137 // Remove an entry by insertion_order index, and update memory usage.
138 void removeEntry(indexed_disconnected_transactions::index<
139 insertion_order>::type::iterator entry) {
141 txInfo.erase((*entry)->GetId());
142 queuedTx.get<insertion_order>().erase(entry);
143 }
144
145 bool isEmpty() const { return queuedTx.empty(); }
146
147 void clear() {
149 queuedTx.clear();
150 txInfo.clear();
151 }
152
166 void updateMempoolForReorg(Chainstate &active_chainstate,
167 bool fAddToMempool, CTxMemPool &pool)
169};
170
171#endif // BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:212
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:699
std::unordered_map< TxId, TxInfo, SaltedTxIdHasher > TxInfoMap
void removeEntry(indexed_disconnected_transactions::index< insertion_order >::type::iterator entry)
indexed_disconnected_transactions queuedTx
TxInfoMap txInfo
populated by importMempool(); the original tx entry times and feeDeltas
void removeForBlock(const std::vector< CTransactionRef > &vtx)
boost::multi_index_container< CTransactionRef, boost::multi_index::indexed_by< boost::multi_index::hashed_unique< boost::multi_index::tag< txid_index >, mempoolentry_txid, SaltedTxIdHasher >, boost::multi_index::sequenced< boost::multi_index::tag< insertion_order > > > > indexed_disconnected_transactions
const TxInfo * getTxInfo(const CTransactionRef &tx) const
void addTransaction(const CTransactionRef &tx)
void updateMempoolForReorg(Chainstate &active_chainstate, bool fAddToMempool, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Make mempool consistent after a reorg, by re-adding or recursively erasing disconnected block transac...
void addForBlock(const std::vector< CTransactionRef > &vtx, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
const indexed_disconnected_transactions & GetQueuedTx() const
void importMempool(CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
static size_t RecursiveDynamicUsage(const CScript &script)
Definition: core_memusage.h:12
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
Definition: memusage.h:27
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
Definition: memusage.h:73
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
Definition: amount.h:19
TxInfo(const std::chrono::seconds &time_, Amount feeDelta_, unsigned height_) noexcept
DisconnectedBlockTransactions.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
assert(!tx.IsCoinBase())