5 #ifndef BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H 6 #define BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H 14 #include <unordered_map> 39 class DisconnectedBlockTransactions { 43 uint64_t cachedInnerUsage = 0; 44 const size_t m_max_mem_usage; 45 std::list<CTransactionRef> queuedTx; 46 using TxList = decltype(queuedTx); 47 std::unordered_map<uint256, TxList::iterator, SaltedTxidHasher> iters_by_txid; 50 std::vector<CTransactionRef> LimitMemoryUsage() 52 std::vector<CTransactionRef> evicted; 54 while (!queuedTx.empty() && DynamicMemoryUsage() > m_max_mem_usage) { 55 evicted.emplace_back(queuedTx.front()); 56 cachedInnerUsage -= RecursiveDynamicUsage(*queuedTx.front()); 57 iters_by_txid.erase(queuedTx.front()->GetHash()); 64 DisconnectedBlockTransactions(size_t max_mem_usage) : m_max_mem_usage{max_mem_usage} {} 66 // It's almost certainly a logic bug
if we don
't clear out queuedTx before 67 // destruction, as we add to it while disconnecting blocks, and then we 68 // need to re-process remaining transactions to ensure mempool consistency. 69 // For now, assert() that we've emptied
out this object on destruction.
76 assert(iters_by_txid.empty());
77 assert(cachedInnerUsage == 0);
93 iters_by_txid.reserve(iters_by_txid.size() + vtx.size());
94 for (
auto block_it = vtx.rbegin(); block_it != vtx.rend(); ++block_it) {
95 auto it = queuedTx.insert(queuedTx.end(), *block_it);
96 iters_by_txid.emplace((*block_it)->GetHash(), it);
99 return LimitMemoryUsage();
106 if (queuedTx.empty()) {
109 for (
const auto& tx : vtx) {
110 auto iter = iters_by_txid.find(tx->GetHash());
111 if (iter != iters_by_txid.end()) {
112 auto list_iter = iter->second;
113 iters_by_txid.erase(iter);
115 queuedTx.erase(list_iter);
120 size_t size()
const {
return queuedTx.size(); }
124 cachedInnerUsage = 0;
125 iters_by_txid.clear();
130 std::list<CTransactionRef>
take()
132 std::list<CTransactionRef>
ret = std::move(queuedTx);
137 #endif // BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
~DisconnectedBlockTransactions()
std::list< CTransactionRef > take()
Clear all data structures and return the list of transactions.
void removeForBlock(const std::vector< CTransactionRef > &vtx)
Remove any entries that are in this block.
std::vector< CTransactionRef > AddTransactionsFromBlock(const std::vector< CTransactionRef > &vtx)
Add transactions from the block, iterating through vtx in reverse order.
static size_t RecursiveDynamicUsage(const CScript &script)
size_t DynamicMemoryUsage() const
static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE
Maximum kilobytes for transactions to store for processing during reorg.