| 27 | } // namespace |
| 28 | |
| 29 | BOOST_AUTO_TEST_CASE(txgraph_trim_zigzag) |
| 30 | { |
| 31 | // T T T T T T T T T T T T T T (50 T's) |
| 32 | // \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / |
| 33 | // \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / |
| 34 | // B B B B B B B B B B B B B (49 B's) |
| 35 | // |
| 36 | /** The maximum cluster count used in this test. */ |
| 37 | static constexpr int MAX_CLUSTER_COUNT = 50; |
| 38 | /** The number of "bottom" transactions, which are in the mempool already. */ |
| 39 | static constexpr int NUM_BOTTOM_TX = 49; |
| 40 | /** The number of "top" transactions, which come from disconnected blocks. These are re-added |
| 41 | * to the mempool and, while connecting them to the already-in-mempool transactions, we |
| 42 | * discover the resulting cluster is oversized. */ |
| 43 | static constexpr int NUM_TOP_TX = 50; |
| 44 | /** The total number of transactions in the test. */ |
| 45 | static constexpr int NUM_TOTAL_TX = NUM_BOTTOM_TX + NUM_TOP_TX; |
| 46 | static_assert(NUM_TOTAL_TX > MAX_CLUSTER_COUNT); |
| 47 | /** Set a very large cluster size limit so that only the count limit is triggered. */ |
| 48 | static constexpr int32_t MAX_CLUSTER_SIZE = 100'000 * 100; |
| 49 | |
| 50 | // Create a new graph for the test. |
| 51 | auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, HIGH_ACCEPTABLE_COST, PointerComparator); |
| 52 | |
| 53 | // Add all transactions and store their Refs. |
| 54 | std::vector<TxGraph::Ref> refs; |
| 55 | refs.reserve(NUM_TOTAL_TX); |
| 56 | // First all bottom transactions: the i'th bottom transaction is at position i. |
| 57 | for (unsigned int i = 0; i < NUM_BOTTOM_TX; ++i) { |
| 58 | graph->AddTransaction(refs.emplace_back(), FeePerWeight{200 - i, 100}); |
| 59 | } |
| 60 | // Then all top transactions: the i'th top transaction is at position NUM_BOTTOM_TX + i. |
| 61 | for (unsigned int i = 0; i < NUM_TOP_TX; ++i) { |
| 62 | graph->AddTransaction(refs.emplace_back(), FeePerWeight{100 - i, 100}); |
| 63 | } |
| 64 | |
| 65 | // Create the zigzag dependency structure. |
| 66 | // Each transaction in the bottom row depends on two adjacent transactions from the top row. |
| 67 | graph->SanityCheck(); |
| 68 | for (unsigned int i = 0; i < NUM_BOTTOM_TX; ++i) { |
| 69 | graph->AddDependency(/*parent=*/refs[NUM_BOTTOM_TX + i], /*child=*/refs[i]); |
| 70 | graph->AddDependency(/*parent=*/refs[NUM_BOTTOM_TX + i + 1], /*child=*/refs[i]); |
| 71 | } |
| 72 | |
| 73 | // Check that the graph is now oversized. This also forces the graph to |
| 74 | // group clusters and compute the oversized status. |
| 75 | graph->SanityCheck(); |
| 76 | BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), NUM_TOTAL_TX); |
| 77 | BOOST_CHECK(graph->IsOversized(TxGraph::Level::TOP)); |
| 78 | |
| 79 | // Call Trim() to remove transactions and bring the cluster back within limits. |
| 80 | auto removed_refs = graph->Trim(); |
| 81 | graph->SanityCheck(); |
| 82 | BOOST_CHECK(!graph->IsOversized(TxGraph::Level::TOP)); |
| 83 | |
| 84 | // We only need to trim the middle bottom transaction to end up with 2 clusters each within cluster limits. |
| 85 | BOOST_CHECK_EQUAL(removed_refs.size(), 1); |
| 86 | BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), MAX_CLUSTER_COUNT * 2 - 2); |
nothing calls this directly
no test coverage detected