@@ -241,3 +241,77 @@ void TxOrphanage::EraseForBlock(const CBlock& block)
241
241
LogPrint (BCLog::TXPACKAGES, " Erased %d orphan tx included or conflicted by block\n " , nErased);
242
242
}
243
243
}
244
+
245
+ std::vector<CTransactionRef> TxOrphanage::GetChildrenFromSamePeer (const CTransactionRef& parent, NodeId nodeid) const
246
+ {
247
+ LOCK (m_mutex);
248
+
249
+ // First construct a vector of iterators to ensure we do not return duplicates of the same tx
250
+ // and so we can sort by nTimeExpire.
251
+ std::vector<OrphanMap::iterator> iters;
252
+
253
+ // For each output, get all entries spending this prevout, filtering for ones from the specified peer.
254
+ for (unsigned int i = 0 ; i < parent->vout .size (); i++) {
255
+ const auto it_by_prev = m_outpoint_to_orphan_it.find (COutPoint (parent->GetHash (), i));
256
+ if (it_by_prev != m_outpoint_to_orphan_it.end ()) {
257
+ for (const auto & elem : it_by_prev->second ) {
258
+ if (elem->second .fromPeer == nodeid) {
259
+ iters.emplace_back (elem);
260
+ }
261
+ }
262
+ }
263
+ }
264
+
265
+ // Sort by address so that duplicates can be deleted. At the same time, sort so that more recent
266
+ // orphans (which expire later) come first. Break ties based on address, as nTimeExpire is
267
+ // quantified in seconds and it is possible for orphans to have the same expiry.
268
+ std::sort (iters.begin (), iters.end (), [](const auto & lhs, const auto & rhs) {
269
+ if (lhs->second .nTimeExpire == rhs->second .nTimeExpire ) {
270
+ return &(*lhs) < &(*rhs);
271
+ } else {
272
+ return lhs->second .nTimeExpire > rhs->second .nTimeExpire ;
273
+ }
274
+ });
275
+ // Erase duplicates
276
+ iters.erase (std::unique (iters.begin (), iters.end ()), iters.end ());
277
+
278
+ // Convert to a vector of CTransactionRef
279
+ std::vector<CTransactionRef> children_found;
280
+ children_found.reserve (iters.size ());
281
+ for (const auto child_iter : iters) {
282
+ children_found.emplace_back (child_iter->second .tx );
283
+ }
284
+ return children_found;
285
+ }
286
+
287
+ std::vector<std::pair<CTransactionRef, NodeId>> TxOrphanage::GetChildrenFromDifferentPeer (const CTransactionRef& parent, NodeId nodeid) const
288
+ {
289
+ LOCK (m_mutex);
290
+
291
+ // First construct vector of iterators to ensure we do not return duplicates of the same tx.
292
+ std::vector<OrphanMap::iterator> iters;
293
+
294
+ // For each output, get all entries spending this prevout, filtering for ones not from the specified peer.
295
+ for (unsigned int i = 0 ; i < parent->vout .size (); i++) {
296
+ const auto it_by_prev = m_outpoint_to_orphan_it.find (COutPoint (parent->GetHash (), i));
297
+ if (it_by_prev != m_outpoint_to_orphan_it.end ()) {
298
+ for (const auto & elem : it_by_prev->second ) {
299
+ if (elem->second .fromPeer != nodeid) {
300
+ iters.emplace_back (elem);
301
+ }
302
+ }
303
+ }
304
+ }
305
+
306
+ // Erase duplicates
307
+ std::sort (iters.begin (), iters.end (), IteratorComparator ());
308
+ iters.erase (std::unique (iters.begin (), iters.end ()), iters.end ());
309
+
310
+ // Convert iterators to pair<CTransactionRef, NodeId>
311
+ std::vector<std::pair<CTransactionRef, NodeId>> children_found;
312
+ children_found.reserve (iters.size ());
313
+ for (const auto child_iter : iters) {
314
+ children_found.emplace_back (child_iter->second .tx , child_iter->second .fromPeer );
315
+ }
316
+ return children_found;
317
+ }
0 commit comments