Skip to content

Commit

Permalink
[test] MiniMiner::Linearize and manual construction
Browse files Browse the repository at this point in the history
  • Loading branch information
glozow committed Oct 31, 2023
1 parent c861a7d commit a5b6481
Showing 1 changed file with 160 additions and 0 deletions.
160 changes: 160 additions & 0 deletions src/test/miniminer_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,66 @@ BOOST_FIXTURE_TEST_CASE(miniminer_1p1c, TestChain100Setup)
}
}
}

// Check m_inclusion_order for equivalent mempool- and manually-constructed MiniMiners.
// (We cannot check bump fees in manually-constructed MiniMiners because it doesn't know what
// outpoints are requested).
std::vector<node::MiniMinerMempoolEntry> miniminer_info;
{
const int32_t tx0_vsize{tx_dims.at(tx0->GetHash()).vsize};
const int32_t tx1_vsize{tx_dims.at(tx1->GetHash()).vsize};
const int32_t tx2_vsize{tx_dims.at(tx2->GetHash()).vsize};
const int32_t tx3_vsize{tx_dims.at(tx3->GetHash()).vsize};
const int32_t tx4_vsize{tx_dims.at(tx4->GetHash()).vsize};
const int32_t tx5_vsize{tx_dims.at(tx5->GetHash()).vsize};
const int32_t tx6_vsize{tx_dims.at(tx6->GetHash()).vsize};
const int32_t tx7_vsize{tx_dims.at(tx7->GetHash()).vsize};

CAmount tx5_mod_fee{low_fee + CENT/100};

miniminer_info.emplace_back(/*fee_self=*/normal_fee,/*fee_ancestor=*/normal_fee,/*vsize_self=*/tx0_vsize,/*vsize_ancestor=*/tx0_vsize, tx0);
miniminer_info.emplace_back( normal_fee, normal_fee + normal_fee, tx1_vsize, tx0_vsize + tx1_vsize, tx1);
miniminer_info.emplace_back( low_fee, low_fee, tx2_vsize, tx2_vsize, tx2);
miniminer_info.emplace_back( high_fee, low_fee + high_fee, tx3_vsize, tx2_vsize + tx3_vsize, tx3);
miniminer_info.emplace_back( low_fee, low_fee, tx4_vsize, tx4_vsize, tx4);
miniminer_info.emplace_back( tx5_mod_fee, low_fee + tx5_mod_fee, tx5_vsize, tx4_vsize + tx5_vsize, tx5);
miniminer_info.emplace_back( high_fee, high_fee, tx6_vsize, tx6_vsize, tx6);
miniminer_info.emplace_back( low_fee, high_fee + low_fee, tx7_vsize, tx6_vsize + tx7_vsize, tx7);
}
std::map<Txid, std::set<Txid>> descendant_caches;
descendant_caches.emplace(tx0->GetHash(), std::set<Txid>{tx0->GetHash(), tx1->GetHash()});
descendant_caches.emplace(tx1->GetHash(), std::set<Txid>{tx1->GetHash()});
descendant_caches.emplace(tx2->GetHash(), std::set<Txid>{tx2->GetHash(), tx3->GetHash()});
descendant_caches.emplace(tx3->GetHash(), std::set<Txid>{tx3->GetHash()});
descendant_caches.emplace(tx4->GetHash(), std::set<Txid>{tx4->GetHash(), tx5->GetHash()});
descendant_caches.emplace(tx5->GetHash(), std::set<Txid>{tx5->GetHash()});
descendant_caches.emplace(tx6->GetHash(), std::set<Txid>{tx6->GetHash(), tx7->GetHash()});
descendant_caches.emplace(tx7->GetHash(), std::set<Txid>{tx7->GetHash()});

node::MiniMiner miniminer_manual(miniminer_info, descendant_caches);
// Use unspent outpoints to avoid entries being omitted.
node::MiniMiner miniminer_pool(pool, all_unspent_outpoints);
BOOST_CHECK(miniminer_manual.IsReadyToCalculate());
BOOST_CHECK(miniminer_pool.IsReadyToCalculate());
for (const auto& sequences : {miniminer_manual.Linearize(), miniminer_pool.Linearize()}) {
// tx6 is selected first: high feerate with no parents to bump
BOOST_CHECK_EQUAL(Find(sequences, tx6->GetHash()), 0);

// tx2 + tx3 CPFP are selected next
BOOST_CHECK_EQUAL(Find(sequences, tx2->GetHash()), 1);
BOOST_CHECK_EQUAL(Find(sequences, tx3->GetHash()), 1);

// tx4 + prioritised tx5 CPFP
BOOST_CHECK_EQUAL(Find(sequences, tx4->GetHash()), 2);
BOOST_CHECK_EQUAL(Find(sequences, tx5->GetHash()), 2);

BOOST_CHECK_EQUAL(Find(sequences, tx0->GetHash()), 3);
BOOST_CHECK_EQUAL(Find(sequences, tx1->GetHash()), 3);


// tx7 is selected last: low feerate with no children
BOOST_CHECK_EQUAL(Find(sequences, tx7->GetHash()), 4);
}
}

BOOST_FIXTURE_TEST_CASE(miniminer_overlap, TestChain100Setup)
Expand Down Expand Up @@ -484,6 +544,50 @@ BOOST_FIXTURE_TEST_CASE(miniminer_overlap, TestChain100Setup)
BOOST_CHECK(tx7_bumpfee != bump_fees.end());
BOOST_CHECK_EQUAL(tx7_bumpfee->second, 0);
}
// Check linearization order
std::vector<node::MiniMinerMempoolEntry> miniminer_info;
miniminer_info.emplace_back(/*fee_self=*/low_fee, /*fee_ancestor=*/low_fee,/*vsize_self=*/tx_vsizes[0], /*vsize_ancestor=*/tx_vsizes[0], tx0);
miniminer_info.emplace_back( med_fee, med_fee, tx_vsizes[1], tx_vsizes[1], tx1);
miniminer_info.emplace_back( high_fee, high_fee, tx_vsizes[2], tx_vsizes[2], tx2);
miniminer_info.emplace_back( high_fee, low_fee+med_fee+2*high_fee, tx_vsizes[3], tx_vsizes[0]+tx_vsizes[1]+tx_vsizes[2]+tx_vsizes[3], tx3);

miniminer_info.emplace_back( high_fee, high_fee, tx_vsizes[4], tx_vsizes[4], tx4);
miniminer_info.emplace_back( low_fee, low_fee + high_fee, tx_vsizes[5], tx_vsizes[4]+tx_vsizes[5], tx5);
miniminer_info.emplace_back( med_fee, high_fee+low_fee+med_fee, tx_vsizes[6], tx_vsizes[4]+tx_vsizes[5]+tx_vsizes[6], tx6);
miniminer_info.emplace_back( high_fee, high_fee+low_fee+high_fee, tx_vsizes[7], tx_vsizes[4]+tx_vsizes[5]+tx_vsizes[7], tx7);

std::map<Txid, std::set<Txid>> descendant_caches;
descendant_caches.emplace(tx0->GetHash(), std::set<Txid>{tx0->GetHash(), tx3->GetHash()});
descendant_caches.emplace(tx1->GetHash(), std::set<Txid>{tx1->GetHash(), tx3->GetHash()});
descendant_caches.emplace(tx2->GetHash(), std::set<Txid>{tx2->GetHash(), tx3->GetHash()});
descendant_caches.emplace(tx3->GetHash(), std::set<Txid>{tx3->GetHash()});
descendant_caches.emplace(tx4->GetHash(), std::set<Txid>{tx4->GetHash(), tx5->GetHash(), tx6->GetHash(), tx7->GetHash()});
descendant_caches.emplace(tx5->GetHash(), std::set<Txid>{tx5->GetHash(), tx6->GetHash(), tx7->GetHash()});
descendant_caches.emplace(tx6->GetHash(), std::set<Txid>{tx6->GetHash()});
descendant_caches.emplace(tx7->GetHash(), std::set<Txid>{tx7->GetHash()});

node::MiniMiner miniminer_manual(miniminer_info, descendant_caches);
// Use unspent outpoints to avoid entries being omitted.
node::MiniMiner miniminer_pool(pool, all_unspent_outpoints);
BOOST_CHECK(miniminer_manual.IsReadyToCalculate());
BOOST_CHECK(miniminer_pool.IsReadyToCalculate());
for (const auto& sequences : {miniminer_manual.Linearize(), miniminer_pool.Linearize()}) {
// tx2 and tx4 selected first: high feerate with nothing to bump
BOOST_CHECK_EQUAL(Find(sequences, tx4->GetHash()), 0);
BOOST_CHECK_EQUAL(Find(sequences, tx2->GetHash()), 1);

// tx5 + tx7 CPFP
BOOST_CHECK_EQUAL(Find(sequences, tx5->GetHash()), 2);
BOOST_CHECK_EQUAL(Find(sequences, tx7->GetHash()), 2);

// tx0 and tx1 CPFP'd by tx3
BOOST_CHECK_EQUAL(Find(sequences, tx0->GetHash()), 3);
BOOST_CHECK_EQUAL(Find(sequences, tx1->GetHash()), 3);
BOOST_CHECK_EQUAL(Find(sequences, tx3->GetHash()), 3);

// tx6 at medium feerate
BOOST_CHECK_EQUAL(Find(sequences, tx6->GetHash()), 4);
}
}
BOOST_FIXTURE_TEST_CASE(calculate_cluster, TestChain100Setup)
{
Expand Down Expand Up @@ -541,4 +645,60 @@ BOOST_FIXTURE_TEST_CASE(calculate_cluster, TestChain100Setup)
}
}

BOOST_FIXTURE_TEST_CASE(manual_ctor, TestChain100Setup)
{
CTxMemPool& pool = *Assert(m_node.mempool);
LOCK2(cs_main, pool.cs);
{
// 3 pairs of fee-bumping grandparent + parent, plus 1 low-feerate child.
// 0 fee + high fee
auto grandparent_zero_fee = make_tx({{m_coinbase_txns.at(0)->GetHash(), 0}}, 1);
auto parent_high_feerate = make_tx({{grandparent_zero_fee->GetHash(), 0}}, 1);
// double low fee + med fee
auto grandparent_double_low_feerate = make_tx({{m_coinbase_txns.at(2)->GetHash(), 0}}, 1);
auto parent_med_feerate = make_tx({{grandparent_double_low_feerate->GetHash(), 0}}, 1);
// low fee + double low fee
auto grandparent_low_feerate = make_tx({{m_coinbase_txns.at(1)->GetHash(), 0}}, 1);
auto parent_double_low_feerate = make_tx({{grandparent_low_feerate->GetHash(), 0}}, 1);
// child is below the cpfp package feerates
auto child = make_tx({{parent_high_feerate->GetHash(), 0}, {parent_double_low_feerate->GetHash(), 0}, {parent_med_feerate->GetHash(), 0}}, 1);

std::vector<node::MiniMinerMempoolEntry> miniminer_info;
miniminer_info.emplace_back(/*fee_self=*/0,/*fee_ancestor=*/0,/*vsize_self=*/100,/*vsize_ancestor=*/100, grandparent_zero_fee);
miniminer_info.emplace_back( 10000, 10000, 100, 200, parent_high_feerate);
miniminer_info.emplace_back( 200, 200, 100, 100, grandparent_double_low_feerate);
miniminer_info.emplace_back( 1000, 1200, 100, 200, parent_med_feerate);
miniminer_info.emplace_back( 100, 100, 100, 100, grandparent_low_feerate);
miniminer_info.emplace_back( 200, 300, 100, 200, parent_double_low_feerate);
miniminer_info.emplace_back( 10, 11510, 100, 700, child);
std::map<Txid, std::set<Txid>> descendant_caches;
descendant_caches.emplace(grandparent_zero_fee->GetHash(), std::set<Txid>{grandparent_zero_fee->GetHash(), parent_high_feerate->GetHash(), child->GetHash()});
descendant_caches.emplace(grandparent_low_feerate->GetHash(), std::set<Txid>{grandparent_low_feerate->GetHash(), parent_double_low_feerate->GetHash(), child->GetHash()});
descendant_caches.emplace(grandparent_double_low_feerate->GetHash(), std::set<Txid>{grandparent_double_low_feerate->GetHash(), parent_med_feerate->GetHash(), child->GetHash()});
descendant_caches.emplace(parent_high_feerate->GetHash(), std::set<Txid>{parent_high_feerate->GetHash(), child->GetHash()});
descendant_caches.emplace(parent_med_feerate->GetHash(), std::set<Txid>{parent_med_feerate->GetHash(), child->GetHash()});
descendant_caches.emplace(parent_double_low_feerate->GetHash(), std::set<Txid>{parent_double_low_feerate->GetHash(), child->GetHash()});
descendant_caches.emplace(child->GetHash(), std::set<Txid>{child->GetHash()});

node::MiniMiner miniminer_manual(miniminer_info, descendant_caches);
BOOST_CHECK(miniminer_manual.IsReadyToCalculate());
const auto sequences{miniminer_manual.Linearize()};

// CPFP zero + high
BOOST_CHECK_EQUAL(sequences.at(grandparent_zero_fee->GetHash()), 0);
BOOST_CHECK_EQUAL(sequences.at(parent_high_feerate->GetHash()), 0);

// CPFP double low + med
BOOST_CHECK_EQUAL(sequences.at(grandparent_double_low_feerate->GetHash()), 1);
BOOST_CHECK_EQUAL(sequences.at(parent_med_feerate->GetHash()), 1);

// CPFP low + med
BOOST_CHECK_EQUAL(sequences.at(grandparent_low_feerate->GetHash()), 2);
BOOST_CHECK_EQUAL(sequences.at(parent_double_low_feerate->GetHash()), 2);

// Child at the end
BOOST_CHECK_EQUAL(sequences.at(child->GetHash()), 3);
}
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit a5b6481

Please sign in to comment.