24
24
#include < validationinterface.h>
25
25
26
26
#include < cmath>
27
+ #include < numeric>
27
28
#include < optional>
28
29
#include < string_view>
29
30
#include < utility>
@@ -898,6 +899,19 @@ CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) c
898
899
return ret;
899
900
}
900
901
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
+
901
915
bool CTxMemPool::HasNoInputsOf (const CTransaction &tx) const
902
916
{
903
917
for (unsigned int i = 0 ; i < tx.vin .size (); i++)
@@ -1127,7 +1141,6 @@ void CTxMemPool::SetLoadTried(bool load_tried)
1127
1141
m_load_tried = load_tried;
1128
1142
}
1129
1143
1130
-
1131
1144
std::string RemovalReasonToString (const MemPoolRemovalReason& r) noexcept
1132
1145
{
1133
1146
switch (r) {
@@ -1140,3 +1153,30 @@ std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept
1140
1153
}
1141
1154
assert (false );
1142
1155
}
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