diff options
author | glozow <gloriajzhao@gmail.com> | 2022-02-21 11:48:10 +0000 |
---|---|---|
committer | Murch <murch@murch.one> | 2023-03-27 17:35:12 -0400 |
commit | 56484f0fdc44261e723563f59df886d5acdd851f (patch) | |
tree | 354fbe250f28b741424519a6b9118e88dba5317f /src/txmempool.cpp | |
parent | 68e484afbbc2e43ad7f2140275cf4e09e45b80ae (diff) |
[mempool] find connected mempool entries with GatherClusters(…)
We limit GatherClusters’s result to a maximum of 500 transactions as
clusters can be made arbitrarily large by third parties.
Co-authored-by: Murch <murch@murch.one>
Diffstat (limited to 'src/txmempool.cpp')
-rw-r--r-- | src/txmempool.cpp | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 378123ce0f..2bac419f84 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -24,6 +24,7 @@ #include <validationinterface.h> #include <cmath> +#include <numeric> #include <optional> #include <string_view> #include <utility> @@ -898,6 +899,19 @@ CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) c return ret; } +std::vector<CTxMemPool::txiter> CTxMemPool::GetIterVec(const std::vector<uint256>& txids) const +{ + AssertLockHeld(cs); + std::vector<txiter> ret; + ret.reserve(txids.size()); + for (const auto& txid : txids) { + const auto it{GetIter(txid)}; + if (!it) return {}; + ret.push_back(*it); + } + return ret; +} + bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const { for (unsigned int i = 0; i < tx.vin.size(); i++) @@ -1127,7 +1141,6 @@ void CTxMemPool::SetLoadTried(bool load_tried) m_load_tried = load_tried; } - std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept { switch (r) { @@ -1140,3 +1153,30 @@ std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept } assert(false); } + +std::vector<CTxMemPool::txiter> CTxMemPool::GatherClusters(const std::vector<uint256>& txids) const +{ + AssertLockHeld(cs); + std::vector<txiter> clustered_txs{GetIterVec(txids)}; + // Use epoch: visiting an entry means we have added it to the clustered_txs vector. It does not + // necessarily mean the entry has been processed. + WITH_FRESH_EPOCH(m_epoch); + for (const auto& it : clustered_txs) { + visited(it); + } + // i = index of where the list of entries to process starts + for (size_t i{0}; i < clustered_txs.size(); ++i) { + // DoS protection: if there are 500 or more entries to process, just quit. + if (clustered_txs.size() > 500) return {}; + const txiter& tx_iter = clustered_txs.at(i); + for (const auto& entries : {tx_iter->GetMemPoolParentsConst(), tx_iter->GetMemPoolChildrenConst()}) { + for (const CTxMemPoolEntry& entry : entries) { + const auto entry_it = mapTx.iterator_to(entry); + if (!visited(entry_it)) { + clustered_txs.push_back(entry_it); + } + } + } + } + return clustered_txs; +} |