Skip to content

Commit 7426afb

Browse files
committed
[p2p] assign just 1 random announcer in AddChildrenToWorkSet
1 parent 4c1fa6b commit 7426afb

File tree

5 files changed

+38
-24
lines changed

5 files changed

+38
-24
lines changed

src/node/txdownloadman_impl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ void TxDownloadManagerImpl::MempoolAcceptedTx(const CTransactionRef& tx)
333333
m_txrequest.ForgetTxHash(tx->GetHash());
334334
m_txrequest.ForgetTxHash(tx->GetWitnessHash());
335335

336-
m_orphanage.AddChildrenToWorkSet(*tx);
336+
m_orphanage.AddChildrenToWorkSet(*tx, m_opts.m_rng);
337337
// If it came from the orphanage, remove it. No-op if the tx is not in txorphanage.
338338
m_orphanage.EraseTx(tx->GetWitnessHash());
339339
}

src/test/fuzz/txorphan.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void initialize_orphanage()
3333
FUZZ_TARGET(txorphan, .init = initialize_orphanage)
3434
{
3535
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
36-
FastRandomContext limit_orphans_rng{/*fDeterministic=*/true};
36+
FastRandomContext orphanage_rng{/*fDeterministic=*/true};
3737
SetMockTime(ConsumeTime(fuzzed_data_provider));
3838

3939
TxOrphanage orphanage;
@@ -79,7 +79,7 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
7979
// previous loop and potentially the parent of this tx.
8080
if (ptx_potential_parent) {
8181
// Set up future GetTxToReconsider call.
82-
orphanage.AddChildrenToWorkSet(*ptx_potential_parent);
82+
orphanage.AddChildrenToWorkSet(*ptx_potential_parent, orphanage_rng);
8383

8484
// Check that all txns returned from GetChildrenFrom* are indeed a direct child of this tx.
8585
NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<NodeId>();
@@ -154,7 +154,7 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
154154
// test mocktime and expiry
155155
SetMockTime(ConsumeTime(fuzzed_data_provider));
156156
auto limit = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
157-
orphanage.LimitOrphans(limit, limit_orphans_rng);
157+
orphanage.LimitOrphans(limit, orphanage_rng);
158158
Assert(orphanage.Size() <= limit);
159159
});
160160

src/test/orphanage_tests.cpp

+17-9
Original file line numberDiff line numberDiff line change
@@ -532,19 +532,27 @@ BOOST_AUTO_TEST_CASE(peer_worksets)
532532
BOOST_CHECK(orphanage.HaveTxFromPeer(orphan_wtxid, node));
533533
}
534534

535-
// Parent accepted: add child to all 3 worksets.
536-
orphanage.AddChildrenToWorkSet(*tx_missing_parent);
537-
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node0), tx_orphan);
538-
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node1), tx_orphan);
539-
// Don't call GetTxToReconsider(node2) yet because it mutates the workset.
535+
// Parent accepted: child is added to 1 of 3 worksets.
536+
orphanage.AddChildrenToWorkSet(*tx_missing_parent, det_rand);
537+
int node0_reconsider = orphanage.HaveTxToReconsider(node0);
538+
int node1_reconsider = orphanage.HaveTxToReconsider(node1);
539+
int node2_reconsider = orphanage.HaveTxToReconsider(node2);
540+
BOOST_CHECK_EQUAL(node0_reconsider + node1_reconsider + node2_reconsider, 1);
541+
542+
NodeId assigned_peer;
543+
if (node0_reconsider) {
544+
assigned_peer = node0;
545+
} else if (node1_reconsider) {
546+
assigned_peer = node1;
547+
} else {
548+
BOOST_CHECK(node2_reconsider);
549+
assigned_peer = node2;
550+
}
540551

541552
// EraseForPeer also removes that tx from the workset.
542-
orphanage.EraseForPeer(node0);
553+
orphanage.EraseForPeer(assigned_peer);
543554
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node0), nullptr);
544555

545-
// However, the other peers' worksets are not touched.
546-
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node2), tx_orphan);
547-
548556
// Delete this tx, clearing the orphanage.
549557
BOOST_CHECK_EQUAL(orphanage.EraseTx(orphan_wtxid), 1);
550558
BOOST_CHECK_EQUAL(orphanage.Size(), 0);

src/txorphanage.cpp

+16-10
Original file line numberDiff line numberDiff line change
@@ -152,23 +152,29 @@ void TxOrphanage::LimitOrphans(unsigned int max_orphans, FastRandomContext& rng)
152152
if (nEvicted > 0) LogDebug(BCLog::TXPACKAGES, "orphanage overflow, removed %u tx\n", nEvicted);
153153
}
154154

155-
void TxOrphanage::AddChildrenToWorkSet(const CTransaction& tx)
155+
void TxOrphanage::AddChildrenToWorkSet(const CTransaction& tx, FastRandomContext& rng)
156156
{
157157
for (unsigned int i = 0; i < tx.vout.size(); i++) {
158158
const auto it_by_prev = m_outpoint_to_orphan_it.find(COutPoint(tx.GetHash(), i));
159159
if (it_by_prev != m_outpoint_to_orphan_it.end()) {
160160
for (const auto& elem : it_by_prev->second) {
161161
// Belt and suspenders, each orphan should always have at least 1 announcer.
162162
if (!Assume(!elem->second.announcers.empty())) continue;
163-
for (const auto announcer: elem->second.announcers) {
164-
// Get this source peer's work set, emplacing an empty set if it didn't exist
165-
// (note: if this peer wasn't still connected, we would have removed the orphan tx already)
166-
std::set<Wtxid>& orphan_work_set = m_peer_work_set.try_emplace(announcer).first->second;
167-
// Add this tx to the work set
168-
orphan_work_set.insert(elem->first);
169-
LogDebug(BCLog::TXPACKAGES, "added %s (wtxid=%s) to peer %d workset\n",
170-
tx.GetHash().ToString(), tx.GetWitnessHash().ToString(), announcer);
171-
}
163+
164+
// Select a random peer to assign orphan processing, reducing wasted work if the orphan is still missing
165+
// inputs. However, we don't want to create an issue in which the assigned peer can purposefully stop us
166+
// from processing the orphan by disconnecting.
167+
auto announcer_iter = std::begin(elem->second.announcers);
168+
std::advance(announcer_iter, rng.randrange(elem->second.announcers.size()));
169+
auto announcer = *(announcer_iter);
170+
171+
// Get this source peer's work set, emplacing an empty set if it didn't exist
172+
// (note: if this peer wasn't still connected, we would have removed the orphan tx already)
173+
std::set<Wtxid>& orphan_work_set = m_peer_work_set.try_emplace(announcer).first->second;
174+
// Add this tx to the work set
175+
orphan_work_set.insert(elem->first);
176+
LogDebug(BCLog::TXPACKAGES, "added %s (wtxid=%s) to peer %d workset\n",
177+
tx.GetHash().ToString(), tx.GetWitnessHash().ToString(), announcer);
172178
}
173179
}
174180
}

src/txorphanage.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class TxOrphanage {
6262
void LimitOrphans(unsigned int max_orphans, FastRandomContext& rng);
6363

6464
/** Add any orphans that list a particular tx as a parent into the from peer's work set */
65-
void AddChildrenToWorkSet(const CTransaction& tx);
65+
void AddChildrenToWorkSet(const CTransaction& tx, FastRandomContext& rng);
6666

6767
/** Does this peer have any work to do? */
6868
bool HaveTxToReconsider(NodeId peer);

0 commit comments

Comments
 (0)