mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 07:39:08 +01:00
[refactor] make TxOrphanage keep itself trimmed
This commit is contained in:
@@ -72,15 +72,6 @@ static bool EqualTxns(const std::set<CTransactionRef>& set_txns, const std::vect
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int CheckNumEvictions(node::TxOrphanage& orphanage)
|
||||
{
|
||||
const auto original_total_count{orphanage.CountAnnouncements()};
|
||||
orphanage.LimitOrphans();
|
||||
assert(orphanage.TotalLatencyScore() <= orphanage.MaxGlobalLatencyScore());
|
||||
assert(orphanage.TotalOrphanUsage() <= orphanage.MaxGlobalUsage());
|
||||
return original_total_count - orphanage.CountAnnouncements();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
{
|
||||
FastRandomContext det_rand{true};
|
||||
@@ -106,30 +97,22 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
auto orphanage_low_ann = node::MakeTxOrphanage(/*max_global_ann=*/1, /*reserved_peer_usage=*/TX_SIZE * 10);
|
||||
auto orphanage_low_mem = node::MakeTxOrphanage(/*max_global_ann=*/10, /*reserved_peer_usage=*/TX_SIZE);
|
||||
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage_low_mem), 0);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage_low_ann), 0);
|
||||
|
||||
// Add the first transaction
|
||||
orphanage_low_ann->AddTx(txns.at(0), peer);
|
||||
orphanage_low_mem->AddTx(txns.at(0), peer);
|
||||
|
||||
// Add more. One of the limits is exceeded, so LimitOrphans evicts 1.
|
||||
orphanage_low_ann->AddTx(txns.at(1), peer);
|
||||
BOOST_CHECK(orphanage_low_ann->TotalLatencyScore() > orphanage_low_ann->MaxGlobalLatencyScore());
|
||||
BOOST_CHECK(orphanage_low_ann->TotalOrphanUsage() <= orphanage_low_ann->MaxGlobalUsage());
|
||||
|
||||
orphanage_low_mem->AddTx(txns.at(1), peer);
|
||||
BOOST_CHECK(orphanage_low_mem->TotalLatencyScore() <= orphanage_low_mem->MaxGlobalLatencyScore());
|
||||
BOOST_CHECK(orphanage_low_mem->TotalOrphanUsage() > orphanage_low_mem->MaxGlobalUsage());
|
||||
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage_low_mem), 1);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage_low_ann), 1);
|
||||
|
||||
// The older transaction is evicted.
|
||||
BOOST_CHECK(!orphanage_low_ann->HaveTx(txns.at(0)->GetWitnessHash()));
|
||||
BOOST_CHECK(!orphanage_low_mem->HaveTx(txns.at(0)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage_low_ann->HaveTx(txns.at(1)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage_low_mem->HaveTx(txns.at(1)->GetWitnessHash()));
|
||||
|
||||
orphanage_low_ann->SanityCheck();
|
||||
orphanage_low_mem->SanityCheck();
|
||||
}
|
||||
|
||||
// Single peer: latency score includes inputs
|
||||
@@ -138,8 +121,6 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
NodeId peer{10};
|
||||
auto orphanage_low_ann = node::MakeTxOrphanage(/*max_global_ann=*/5, /*reserved_peer_usage=*/TX_SIZE * 1000);
|
||||
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage_low_ann), 0);
|
||||
|
||||
// Add the first transaction
|
||||
orphanage_low_ann->AddTx(txns.at(0), peer);
|
||||
|
||||
@@ -151,14 +132,11 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
auto ptx = MakeTransactionSpending(outpoints_45, det_rand);
|
||||
orphanage_low_ann->AddTx(ptx, peer);
|
||||
|
||||
BOOST_CHECK(orphanage_low_ann->TotalLatencyScore() > orphanage_low_ann->MaxGlobalLatencyScore());
|
||||
BOOST_CHECK(orphanage_low_ann->LatencyScoreFromPeer(peer) > orphanage_low_ann->MaxPeerLatencyScore());
|
||||
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage_low_ann), 1);
|
||||
|
||||
// The older transaction is evicted.
|
||||
BOOST_CHECK(!orphanage_low_ann->HaveTx(txns.at(0)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage_low_ann->HaveTx(ptx->GetWitnessHash()));
|
||||
|
||||
orphanage_low_ann->SanityCheck();
|
||||
}
|
||||
|
||||
// Single peer: eviction order is FIFO on non-reconsiderable, then reconsiderable orphans.
|
||||
@@ -191,15 +169,14 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
|
||||
// Add 1 more orphan, causing the orphanage to be oversize. child1 is evicted.
|
||||
orphanage->AddTx(children.at(3), peer);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 1);
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(0)->GetWitnessHash()));
|
||||
BOOST_CHECK(!orphanage->HaveTx(children.at(1)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(2)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
|
||||
orphanage->SanityCheck();
|
||||
|
||||
// Add 1 more... child2 is evicted.
|
||||
orphanage->AddTx(children.at(4), peer);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 1);
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(0)->GetWitnessHash()));
|
||||
BOOST_CHECK(!orphanage->HaveTx(children.at(2)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
|
||||
@@ -213,7 +190,6 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
|
||||
// child5 is evicted immediately because it is the only non-reconsiderable orphan.
|
||||
orphanage->AddTx(children.at(5), peer);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 1);
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(0)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(4)->GetWitnessHash()));
|
||||
@@ -222,7 +198,6 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
// Transactions are marked non-reconsiderable again when returned through GetTxToReconsider
|
||||
BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(peer), children.at(0));
|
||||
orphanage->AddTx(children.at(6), peer);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 1);
|
||||
BOOST_CHECK(!orphanage->HaveTx(children.at(0)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(3)->GetWitnessHash()));
|
||||
BOOST_CHECK(orphanage->HaveTx(children.at(4)->GetWitnessHash()));
|
||||
@@ -232,6 +207,8 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
// reconsideration earlier.
|
||||
BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(peer), children.at(3));
|
||||
BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(peer), children.at(4));
|
||||
|
||||
orphanage->SanityCheck();
|
||||
}
|
||||
|
||||
// Multiple peers: when limit is exceeded, we choose the DoSiest peer and evict their oldest transaction.
|
||||
@@ -247,8 +224,8 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
// No evictions happen before the global limit is reached.
|
||||
for (unsigned int i{0}; i < max_announcements; ++i) {
|
||||
orphanage->AddTx(txns.at(i), peer_dosy);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 0);
|
||||
}
|
||||
orphanage->SanityCheck();
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_dosy), max_announcements);
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer1), 0);
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer2), 0);
|
||||
@@ -260,7 +237,6 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
orphanage->AddTx(txns.at(max_announcements + i), peer1);
|
||||
// The announcement limit per peer has halved, but LimitOrphans does not evict beyond what is necessary to
|
||||
// bring the total announcements within its global limit.
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 1);
|
||||
BOOST_CHECK(orphanage->AnnouncementsFromPeer(peer_dosy) > orphanage->MaxPeerLatencyScore());
|
||||
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer1), i + 1);
|
||||
@@ -276,9 +252,6 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
BOOST_CHECK(orphanage->HaveTxFromPeer(txns.at(i)->GetWitnessHash(), peer_dosy));
|
||||
orphanage->AddTx(txns.at(i), peer2);
|
||||
|
||||
// Announcement limit is by entry, not by unique orphans
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 1);
|
||||
|
||||
// peer_dosy is still the only one getting evicted
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_dosy), max_announcements - i - 1);
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer1), num_from_peer1);
|
||||
@@ -291,15 +264,18 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
|
||||
// With 6 peers, each can add 10, and still only peer_dosy's orphans are evicted.
|
||||
const unsigned int max_per_peer{max_announcements / 6};
|
||||
const unsigned int num_announcements{orphanage->CountAnnouncements()};
|
||||
for (NodeId peer{3}; peer < 6; ++peer) {
|
||||
for (unsigned int i{0}; i < max_per_peer; ++i) {
|
||||
// Each addition causes 1 eviction.
|
||||
orphanage->AddTx(txns.at(peer * max_per_peer + i), peer);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 1);
|
||||
BOOST_CHECK_EQUAL(orphanage->CountAnnouncements(), num_announcements);
|
||||
}
|
||||
}
|
||||
for (NodeId peer{0}; peer < 6; ++peer) {
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer), max_per_peer);
|
||||
}
|
||||
orphanage->SanityCheck();
|
||||
}
|
||||
|
||||
// Limits change as more peers are added.
|
||||
@@ -355,6 +331,8 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
BOOST_CHECK_EQUAL(orphanage->ReservedPeerUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
|
||||
BOOST_CHECK_EQUAL(orphanage->MaxGlobalUsage(), node::DEFAULT_RESERVED_ORPHAN_WEIGHT_PER_PEER);
|
||||
BOOST_CHECK_EQUAL(orphanage->MaxPeerLatencyScore(), node::DEFAULT_MAX_ORPHANAGE_LATENCY_SCORE);
|
||||
|
||||
orphanage->SanityCheck();
|
||||
}
|
||||
|
||||
// Test eviction of multiple transactions at a time
|
||||
@@ -378,17 +356,17 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
}
|
||||
BOOST_CHECK(orphanage->TotalLatencyScore() <= orphanage->MaxGlobalLatencyScore());
|
||||
BOOST_CHECK(orphanage->TotalOrphanUsage() <= orphanage->MaxGlobalUsage());
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 0);
|
||||
|
||||
// Add the large transaction. This should cause evictions of all the previous 10 transactions from that peer.
|
||||
orphanage->AddTx(ptx_large, peer_large);
|
||||
BOOST_CHECK_EQUAL(CheckNumEvictions(*orphanage), 10);
|
||||
|
||||
// peer_normal should still have 10 transactions, and peer_large should have 1.
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_normal), 10);
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(peer_large), 1);
|
||||
BOOST_CHECK(orphanage->HaveTxFromPeer(ptx_large->GetWitnessHash(), peer_large));
|
||||
BOOST_CHECK_EQUAL(orphanage->CountAnnouncements(), 11);
|
||||
|
||||
orphanage->SanityCheck();
|
||||
}
|
||||
|
||||
// Test that latency score includes number of inputs.
|
||||
@@ -432,6 +410,8 @@ BOOST_AUTO_TEST_CASE(peer_dos_limits)
|
||||
// Peer 1 sent 5 of the 10 transactions with many inputs
|
||||
BOOST_CHECK_EQUAL(orphanage->AnnouncementsFromPeer(1), 5);
|
||||
BOOST_CHECK_EQUAL(orphanage->LatencyScoreFromPeer(1), 5 + 5 * 5);
|
||||
|
||||
orphanage->SanityCheck();
|
||||
}
|
||||
}
|
||||
BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
||||
|
||||
Reference in New Issue
Block a user