Skip to content

Commit 22b023b

Browse files
committed
[unit test] multiple orphan announcers
1 parent 96c1a82 commit 22b023b

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

src/test/orphanage_tests.cpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,4 +446,130 @@ BOOST_AUTO_TEST_CASE(process_block)
446446
BOOST_CHECK_EQUAL(orphanage.Size(), 1);
447447
BOOST_CHECK(orphanage.HaveTx(control_tx->GetWitnessHash()));
448448
}
449+
450+
BOOST_AUTO_TEST_CASE(multiple_announcers)
451+
{
452+
const NodeId node0{0};
453+
const NodeId node1{1};
454+
const NodeId node2{2};
455+
size_t expected_total_count{0};
456+
FastRandomContext det_rand{true};
457+
TxOrphanageTest orphanage{det_rand};
458+
459+
// Check accounting per peer.
460+
// Check that EraseForPeer works with multiple announcers.
461+
{
462+
auto ptx = MakeTransactionSpending({}, det_rand);
463+
const auto& wtxid = ptx->GetWitnessHash();
464+
BOOST_CHECK(orphanage.AddTx(ptx, node0));
465+
BOOST_CHECK(orphanage.HaveTx(wtxid));
466+
expected_total_count += 1;
467+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
468+
469+
// Adding again should do nothing.
470+
BOOST_CHECK(!orphanage.AddTx(ptx, node0));
471+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
472+
473+
// We can add another tx with the same txid but different witness.
474+
auto ptx_mutated{MakeMutation(ptx)};
475+
BOOST_CHECK(orphanage.AddTx(ptx_mutated, node0));
476+
BOOST_CHECK(orphanage.HaveTx(ptx_mutated->GetWitnessHash()));
477+
expected_total_count += 1;
478+
479+
BOOST_CHECK(!orphanage.AddTx(ptx, node0));
480+
481+
// Adding a new announcer should not change overall accounting.
482+
BOOST_CHECK(orphanage.AddAnnouncer(ptx->GetWitnessHash(), node2));
483+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
484+
485+
// If we already have this announcer, AddAnnouncer returns false.
486+
BOOST_CHECK(orphanage.HaveTxFromPeer(ptx->GetWitnessHash(), node2));
487+
BOOST_CHECK(!orphanage.AddAnnouncer(ptx->GetWitnessHash(), node2));
488+
489+
// Same with using AddTx for an existing tx, which is equivalent to using AddAnnouncer
490+
BOOST_CHECK(!orphanage.AddTx(ptx, node1));
491+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
492+
493+
// if EraseForPeer is called for an orphan with multiple announcers, the orphanage should only
494+
// erase that peer from the announcers set.
495+
orphanage.EraseForPeer(node0);
496+
BOOST_CHECK(orphanage.HaveTx(ptx->GetWitnessHash()));
497+
BOOST_CHECK(!orphanage.HaveTxFromPeer(ptx->GetWitnessHash(), node0));
498+
// node0 is the only one that announced ptx_mutated
499+
BOOST_CHECK(!orphanage.HaveTx(ptx_mutated->GetWitnessHash()));
500+
expected_total_count -= 1;
501+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
502+
503+
// EraseForPeer should delete the orphan if it's the only announcer left.
504+
orphanage.EraseForPeer(node1);
505+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
506+
BOOST_CHECK(orphanage.HaveTx(ptx->GetWitnessHash()));
507+
orphanage.EraseForPeer(node2);
508+
expected_total_count -= 1;
509+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
510+
BOOST_CHECK(!orphanage.HaveTx(ptx->GetWitnessHash()));
511+
}
512+
513+
// Check that erasure for blocks removes for all peers.
514+
{
515+
CBlock block;
516+
auto tx_block = MakeTransactionSpending({}, det_rand);
517+
block.vtx.emplace_back(tx_block);
518+
BOOST_CHECK(orphanage.AddTx(tx_block, node0));
519+
BOOST_CHECK(!orphanage.AddTx(tx_block, node1));
520+
521+
expected_total_count += 1;
522+
523+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
524+
525+
orphanage.EraseForBlock(block);
526+
527+
expected_total_count -= 1;
528+
529+
BOOST_CHECK_EQUAL(orphanage.Size(), expected_total_count);
530+
}
531+
}
532+
BOOST_AUTO_TEST_CASE(peer_worksets)
533+
{
534+
const NodeId node0{0};
535+
const NodeId node1{1};
536+
const NodeId node2{2};
537+
FastRandomContext det_rand{true};
538+
TxOrphanageTest orphanage{det_rand};
539+
// AddChildrenToWorkSet should pick an announcer randomly
540+
{
541+
auto tx_missing_parent = MakeTransactionSpending({}, det_rand);
542+
auto tx_orphan = MakeTransactionSpending({COutPoint{tx_missing_parent->GetHash(), 0}}, det_rand);
543+
const auto& orphan_wtxid = tx_orphan->GetWitnessHash();
544+
545+
// All 3 peers are announcers.
546+
BOOST_CHECK(orphanage.AddTx(tx_orphan, node0));
547+
BOOST_CHECK(!orphanage.AddTx(tx_orphan, node1));
548+
BOOST_CHECK(orphanage.AddAnnouncer(orphan_wtxid, node2));
549+
for (NodeId node = node0; node <= node2; ++node) {
550+
BOOST_CHECK(orphanage.HaveTxFromPeer(orphan_wtxid, node));
551+
}
552+
553+
// Parent accepted: add child to all 3 worksets.
554+
orphanage.AddChildrenToWorkSet(*tx_missing_parent);
555+
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node0), tx_orphan);
556+
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node1), tx_orphan);
557+
// Don't call GetTxToReconsider(node2) yet because it mutates the workset.
558+
559+
// EraseForPeer also removes that tx from the workset.
560+
orphanage.EraseForPeer(node0);
561+
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node0), nullptr);
562+
563+
// However, the other peers' worksets are not touched.
564+
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node2), tx_orphan);
565+
566+
// Delete this tx, clearing the orphanage.
567+
BOOST_CHECK_EQUAL(orphanage.EraseTx(orphan_wtxid), 1);
568+
BOOST_CHECK_EQUAL(orphanage.Size(), 0);
569+
for (NodeId node = node0; node <= node2; ++node) {
570+
BOOST_CHECK_EQUAL(orphanage.GetTxToReconsider(node), nullptr);
571+
BOOST_CHECK(!orphanage.HaveTxFromPeer(orphan_wtxid, node));
572+
}
573+
}
574+
}
449575
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)