forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MOVEONLY: DisconnectedBlockTransactions to its own file
This struct is only used in validation + tests and has very little to do with txmempool.
- Loading branch information
Showing
6 changed files
with
121 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// Copyright (c) 2023 The Bitcoin Core developers | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#ifndef BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H | ||
#define BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H | ||
|
||
#include <core_memusage.h> | ||
#include <memusage.h> | ||
#include <primitives/transaction.h> | ||
#include <util/hasher.h> | ||
|
||
#include <list> | ||
#include <unordered_map> | ||
|
||
/** | ||
* DisconnectedBlockTransactions | ||
* During the reorg, it's desirable to re-add previously confirmed transactions | ||
* to the mempool, so that anything not re-confirmed in the new chain is | ||
* available to be mined. However, it's more efficient to wait until the reorg | ||
* is complete and process all still-unconfirmed transactions at that time, | ||
* since we expect most confirmed transactions to (typically) still be | ||
* confirmed in the new chain, and re-accepting to the memory pool is expensive | ||
* (and therefore better to not do in the middle of reorg-processing). | ||
* Instead, store the disconnected transactions (in order!) as we go, remove any | ||
* that are included in blocks in the new chain, and then process the remaining | ||
* still-unconfirmed transactions at the end. | ||
*/ | ||
struct DisconnectedBlockTransactions { | ||
private: | ||
uint64_t cachedInnerUsage = 0; | ||
std::list<CTransactionRef> queuedTx; | ||
using List = decltype(queuedTx); | ||
std::unordered_map<uint256, List::iterator, SaltedTxidHasher> iters_by_txid; | ||
|
||
void clear() | ||
{ | ||
cachedInnerUsage = 0; | ||
iters_by_txid.clear(); | ||
queuedTx.clear(); | ||
} | ||
public: | ||
// It's almost certainly a logic bug if we don't clear out queuedTx before | ||
// destruction, as we add to it while disconnecting blocks, and then we | ||
// need to re-process remaining transactions to ensure mempool consistency. | ||
// For now, assert() that we've emptied out this object on destruction. | ||
// This assert() can always be removed if the reorg-processing code were | ||
// to be refactored such that this assumption is no longer true (for | ||
// instance if there was some other way we cleaned up the mempool after a | ||
// reorg, besides draining this object). | ||
~DisconnectedBlockTransactions() { | ||
assert(queuedTx.empty()); | ||
assert(iters_by_txid.empty()); | ||
assert(cachedInnerUsage == 0); | ||
} | ||
|
||
size_t DynamicMemoryUsage() const { | ||
return cachedInnerUsage + memusage::DynamicUsage(iters_by_txid) + memusage::DynamicUsage(queuedTx); | ||
} | ||
|
||
// Add transactions from the block, in reverse order. | ||
void AddTransactionsFromBlock(const std::vector<CTransactionRef>& vtx) | ||
{ | ||
// Blocks are disconnected in descending order by block height. Within each block, add | ||
// transactions in reverse order so that transactions with dependencies on other | ||
// transactions (if any) are at the beginning. If this data structure grows too large, we | ||
// will trim transactions from the front. Transactions with fewer dependencies should be | ||
// removed first. | ||
iters_by_txid.reserve(iters_by_txid.size() + vtx.size()); | ||
for (auto block_it = vtx.rbegin(); block_it != vtx.rend(); ++block_it) { | ||
auto it = queuedTx.insert(queuedTx.end(), *block_it); | ||
iters_by_txid.emplace((*block_it)->GetHash(), it); | ||
cachedInnerUsage += RecursiveDynamicUsage(*block_it); | ||
} | ||
} | ||
|
||
// Remove entries that are in this block. | ||
void removeForBlock(const std::vector<CTransactionRef>& vtx) | ||
{ | ||
// Short-circuit in the common case of a block being added to the tip | ||
if (queuedTx.empty()) { | ||
return; | ||
} | ||
for (const auto& tx : vtx) { | ||
auto iter = iters_by_txid.find(tx->GetHash()); | ||
if (iter != iters_by_txid.end()) { | ||
auto list_iter = iter->second; | ||
iters_by_txid.erase(iter); | ||
cachedInnerUsage -= RecursiveDynamicUsage(*list_iter); | ||
queuedTx.erase(list_iter); | ||
} | ||
} | ||
} | ||
|
||
// Remove the first entry and update memory usage. | ||
CTransactionRef take_first() | ||
{ | ||
CTransactionRef first_tx; | ||
if (!queuedTx.empty()) { | ||
first_tx = queuedTx.front(); | ||
cachedInnerUsage -= RecursiveDynamicUsage(queuedTx.front()); | ||
iters_by_txid.erase(queuedTx.front()->GetHash()); | ||
queuedTx.pop_front(); | ||
} | ||
return first_tx; | ||
} | ||
|
||
// Clear all data structures and return the list of transactions. | ||
std::list<CTransactionRef> take() { | ||
std::list<CTransactionRef> ret = std::move(queuedTx); | ||
clear(); | ||
return ret; | ||
} | ||
}; | ||
#endif // BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters