2424#include < validationinterface.h>
2525
2626#include < cmath>
27+ #include < numeric>
2728#include < optional>
2829#include < string_view>
2930#include < utility>
@@ -898,6 +899,19 @@ CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) c
898899 return ret;
899900}
900901
902+ std::vector<CTxMemPool::txiter> CTxMemPool::GetIterVec (const std::vector<uint256>& txids) const
903+ {
904+ AssertLockHeld (cs);
905+ std::vector<txiter> ret;
906+ ret.reserve (txids.size ());
907+ for (const auto & txid : txids) {
908+ const auto it{GetIter (txid)};
909+ if (!it) return {};
910+ ret.push_back (*it);
911+ }
912+ return ret;
913+ }
914+
901915bool CTxMemPool::HasNoInputsOf (const CTransaction &tx) const
902916{
903917 for (unsigned int i = 0 ; i < tx.vin .size (); i++)
@@ -1127,7 +1141,6 @@ void CTxMemPool::SetLoadTried(bool load_tried)
11271141 m_load_tried = load_tried;
11281142}
11291143
1130-
11311144std::string RemovalReasonToString (const MemPoolRemovalReason& r) noexcept
11321145{
11331146 switch (r) {
@@ -1140,3 +1153,30 @@ std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept
11401153 }
11411154 assert (false );
11421155}
1156+
1157+ std::vector<CTxMemPool::txiter> CTxMemPool::GatherClusters (const std::vector<uint256>& txids) const
1158+ {
1159+ AssertLockHeld (cs);
1160+ std::vector<txiter> clustered_txs{GetIterVec (txids)};
1161+ // Use epoch: visiting an entry means we have added it to the clustered_txs vector. It does not
1162+ // necessarily mean the entry has been processed.
1163+ WITH_FRESH_EPOCH (m_epoch);
1164+ for (const auto & it : clustered_txs) {
1165+ visited (it);
1166+ }
1167+ // i = index of where the list of entries to process starts
1168+ for (size_t i{0 }; i < clustered_txs.size (); ++i) {
1169+ // DoS protection: if there are 500 or more entries to process, just quit.
1170+ if (clustered_txs.size () > 500 ) return {};
1171+ const txiter& tx_iter = clustered_txs.at (i);
1172+ for (const auto & entries : {tx_iter->GetMemPoolParentsConst (), tx_iter->GetMemPoolChildrenConst ()}) {
1173+ for (const CTxMemPoolEntry& entry : entries) {
1174+ const auto entry_it = mapTx.iterator_to (entry);
1175+ if (!visited (entry_it)) {
1176+ clustered_txs.push_back (entry_it);
1177+ }
1178+ }
1179+ }
1180+ }
1181+ return clustered_txs;
1182+ }
0 commit comments