@@ -179,23 +179,21 @@ bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid,
179
179
// - exists in orphanage
180
180
// - peer can be an orphan resolution candidate
181
181
if (gtxid.IsWtxid ()) {
182
- if (auto orphan_tx{m_orphanage.GetTx (Wtxid::FromUint256 (gtxid.GetHash ()))}) {
182
+ const auto wtxid{Wtxid::FromUint256 (gtxid.GetHash ())};
183
+ if (auto orphan_tx{m_orphanage.GetTx (wtxid)}) {
183
184
auto unique_parents{GetUniqueParents (*orphan_tx)};
184
185
std::erase_if (unique_parents, [&](const auto & txid){
185
186
return AlreadyHaveTx (GenTxid::Txid (txid), /* include_reconsiderable=*/ false );
186
187
});
187
188
188
- if (unique_parents.empty ()) return true ;
189
-
190
- if (auto delay{OrphanResolutionCandidate (peer, Wtxid::FromUint256 (gtxid.GetHash ()), unique_parents.size ())}) {
191
- m_orphanage.AddAnnouncer (Wtxid::FromUint256 (gtxid.GetHash ()), peer);
192
-
193
- const auto & info = m_peer_info.at (peer).m_connection_info ;
194
- for (const auto & parent_txid : unique_parents) {
195
- m_txrequest.ReceivedInv (peer, GenTxid::Txid (parent_txid), info.m_preferred , now + *delay);
196
- }
189
+ // The missing parents may have all been rejected or accepted since the orphan was added to the orphanage.
190
+ // Do not delete from the orphanage, as it may be queued for processing.
191
+ if (unique_parents.empty ()) {
192
+ return true ;
193
+ }
197
194
198
- LogDebug (BCLog::TXPACKAGES, " added peer=%d as a candidate for resolving orphan %s\n " , peer, gtxid.GetHash ().ToString ());
195
+ if (MaybeAddOrphanResolutionCandidate (unique_parents, wtxid, peer, now)) {
196
+ m_orphanage.AddAnnouncer (orphan_tx->GetWitnessHash (), peer);
199
197
}
200
198
201
199
// Return even if the peer isn't an orphan resolution candidate. This would be caught by AlreadyHaveTx.
@@ -231,21 +229,23 @@ bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid,
231
229
return false ;
232
230
}
233
231
234
- std::optional< std::chrono::seconds> TxDownloadManagerImpl::OrphanResolutionCandidate (NodeId nodeid , const Wtxid& orphan_wtxid, size_t num_parents )
232
+ bool TxDownloadManagerImpl::MaybeAddOrphanResolutionCandidate ( const std::vector<Txid>& unique_parents , const Wtxid& wtxid, NodeId nodeid, std::chrono::microseconds now )
235
233
{
236
- if (m_peer_info.count (nodeid) == 0 ) return std::nullopt;
237
- if (m_orphanage.HaveTxFromPeer (orphan_wtxid, nodeid)) return std::nullopt;
234
+ auto it_peer = m_peer_info.find (nodeid);
235
+ if (it_peer == m_peer_info.end ()) return false ;
236
+ if (m_orphanage.HaveTxFromPeer (wtxid, nodeid)) return false ;
238
237
239
238
const auto & peer_entry = m_peer_info.at (nodeid);
240
239
const auto & info = peer_entry.m_connection_info ;
240
+
241
241
// TODO: add delays and limits based on the amount of orphan resolution we are already doing
242
242
// with this peer, how much they are using the orphanage, etc.
243
243
if (!info.m_relay_permissions ) {
244
244
// This mirrors the delaying and dropping behavior in AddTxAnnouncement in order to preserve
245
245
// existing behavior: drop if we are tracking too many invs for this peer already. Each
246
246
// orphan resolution involves at least 1 transaction request which may or may not be
247
247
// currently tracked in m_txrequest, so we include that in the count.
248
- if (m_txrequest.Count (nodeid) + num_parents > MAX_PEER_TX_ANNOUNCEMENTS) return std::nullopt ;
248
+ if (m_txrequest.Count (nodeid) + unique_parents. size () > MAX_PEER_TX_ANNOUNCEMENTS) return false ;
249
249
}
250
250
251
251
std::chrono::seconds delay{0s};
@@ -258,7 +258,13 @@ std::optional<std::chrono::seconds> TxDownloadManagerImpl::OrphanResolutionCandi
258
258
const bool overloaded = !info.m_relay_permissions && m_txrequest.CountInFlight (nodeid) >= MAX_PEER_TX_REQUEST_IN_FLIGHT;
259
259
if (overloaded) delay += OVERLOADED_PEER_TX_DELAY;
260
260
261
- return delay;
261
+ // Treat finding orphan resolution candidate as equivalent to the peer announcing all missing parents.
262
+ // In the future, orphan resolution may include more explicit steps
263
+ for (const auto & parent_txid : unique_parents) {
264
+ m_txrequest.ReceivedInv (nodeid, GenTxid::Txid (parent_txid), info.m_preferred , now + delay);
265
+ }
266
+ LogDebug (BCLog::TXPACKAGES, " added peer=%d as a candidate for resolving orphan %s\n " , nodeid, wtxid.ToString ());
267
+ return true ;
262
268
}
263
269
264
270
std::vector<GenTxid> TxDownloadManagerImpl::GetRequestsToSend (NodeId nodeid, std::chrono::microseconds current_time)
@@ -327,7 +333,7 @@ void TxDownloadManagerImpl::MempoolAcceptedTx(const CTransactionRef& tx)
327
333
m_txrequest.ForgetTxHash (tx->GetHash ());
328
334
m_txrequest.ForgetTxHash (tx->GetWitnessHash ());
329
335
330
- m_orphanage.AddChildrenToWorkSet (*tx);
336
+ m_orphanage.AddChildrenToWorkSet (*tx, m_opts. m_rng );
331
337
// If it came from the orphanage, remove it. No-op if the tx is not in txorphanage.
332
338
m_orphanage.EraseTx (tx->GetWitnessHash ());
333
339
}
@@ -400,27 +406,19 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
400
406
// means it was already added to vExtraTxnForCompact.
401
407
add_extra_compact_tx &= !m_orphanage.HaveTx (wtxid);
402
408
403
- auto add_orphan_reso_candidate = [&](const CTransactionRef& orphan_tx, const std::vector<Txid>& unique_parents, NodeId nodeid, std::chrono::microseconds now) {
404
- const auto & wtxid = orphan_tx->GetWitnessHash ();
405
- if (auto delay{OrphanResolutionCandidate (nodeid, wtxid, unique_parents.size ())}) {
406
- const auto & info = m_peer_info.at (nodeid).m_connection_info ;
407
- m_orphanage.AddTx (orphan_tx, nodeid);
408
-
409
- // Treat finding orphan resolution candidate as equivalent to the peer announcing all missing parents
410
- // In the future, orphan resolution may include more explicit steps
411
- for (const auto & parent_txid : unique_parents) {
412
- m_txrequest.ReceivedInv (nodeid, GenTxid::Txid (parent_txid), info.m_preferred , now + *delay);
413
- }
414
- LogDebug (BCLog::TXPACKAGES, " added peer=%d as a candidate for resolving orphan %s\n " , nodeid, wtxid.ToString ());
415
- }
416
- };
417
-
418
409
// If there is no candidate for orphan resolution, AddTx will not be called. This means
419
410
// that if a peer is overloading us with invs and orphans, they will eventually not be
420
411
// able to add any more transactions to the orphanage.
421
- add_orphan_reso_candidate (ptx, unique_parents, nodeid, now);
422
- for (const auto & candidate : m_txrequest.GetCandidatePeers (ptx)) {
423
- add_orphan_reso_candidate (ptx, unique_parents, candidate, now);
412
+ //
413
+ // Search by txid and, if the tx has a witness, wtxid
414
+ std::vector<NodeId> orphan_resolution_candidates{nodeid};
415
+ m_txrequest.GetCandidatePeers (ptx->GetHash ().ToUint256 (), orphan_resolution_candidates);
416
+ if (ptx->HasWitness ()) m_txrequest.GetCandidatePeers (ptx->GetWitnessHash ().ToUint256 (), orphan_resolution_candidates);
417
+
418
+ for (const auto & nodeid : orphan_resolution_candidates) {
419
+ if (MaybeAddOrphanResolutionCandidate (unique_parents, ptx->GetWitnessHash (), nodeid, now)) {
420
+ m_orphanage.AddTx (ptx, nodeid);
421
+ }
424
422
}
425
423
426
424
// Once added to the orphan pool, a tx is considered AlreadyHave, and we shouldn't request it anymore.
0 commit comments