Skip to content

Commit 7db6f01

Browse files
committed
test: Move BnB feerate sensitivity tests
Originally these tests verified that at a SelectCoins level that a solution with fewer inputs gets preferred at high feerates, and a solution with more inputs gets preferred at low feerates. This outcome relies on the behavior of BnB, so we move these tests under the umbrella of BnB tests. Originally these tests relied on SFFO to work.
1 parent 2bafc46 commit 7db6f01

File tree

2 files changed

+27
-37
lines changed

2 files changed

+27
-37
lines changed

src/wallet/test/coinselection_tests.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,12 @@ static std::string InputAmountsToString(const SelectionResult& selection)
8686
return "[" + util::Join(selection.GetInputSet(), " ", [](const auto& input){ return util::ToString(input->txout.nValue);}) + "]";
8787
}
8888

89-
static void TestBnBSuccess(std::string test_title, std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const std::vector<CAmount>& expected_input_amounts, const CoinSelectionParams& cs_params = default_cs_params)
89+
static void TestBnBSuccess(std::string test_title, std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const std::vector<CAmount>& expected_input_amounts, const CoinSelectionParams& cs_params = default_cs_params, int custom_spending_vsize = 68)
9090
{
9191
SelectionResult expected_result(CAmount(0), SelectionAlgorithm::BNB);
9292
CAmount expected_amount = 0;
9393
for (CAmount input_amount : expected_input_amounts) {
94-
OutputGroup group = MakeCoin(input_amount, true, cs_params);
94+
OutputGroup group = MakeCoin(input_amount, true, cs_params, custom_spending_vsize);
9595
expected_amount += group.m_value;
9696
expected_result.AddInput(group);
9797
}
@@ -118,5 +118,28 @@ BOOST_AUTO_TEST_CASE(bnb_test)
118118
TestBnBSuccess("Select upper bound", utxo_pool, /*selection_target=*/4 * CENT - default_cs_params.m_cost_of_change, /*expected_input_amounts=*/{1 * CENT, 3 * CENT});
119119
}
120120

121+
BOOST_AUTO_TEST_CASE(bnb_feerate_sensitivity_test)
122+
{
123+
// Create sets of UTXOs with the same effective amounts at different feerates (but different absolute amounts)
124+
std::vector<OutputGroup> low_feerate_pool; // 5 sat/vB (default, and lower than long_term_feerate of 10 sat/vB)
125+
AddCoins(low_feerate_pool, {2 * CENT, 3 * CENT, 5 * CENT, 10 * CENT});
126+
TestBnBSuccess("Select many inputs at low feerates", low_feerate_pool, /*selection_target=*/10 * CENT, /*expected_input_amounts=*/{2 * CENT, 3 * CENT, 5 * CENT});
127+
128+
CoinSelectionParams high_feerate_params = init_default_params();
129+
high_feerate_params.m_effective_feerate = CFeeRate{25'000};
130+
std::vector<OutputGroup> high_feerate_pool; // 25 sat/vB (greater than long_term_feerate of 10 sat/vB)
131+
AddCoins(high_feerate_pool, {2 * CENT, 3 * CENT, 5 * CENT, 10 * CENT}, high_feerate_params);
132+
TestBnBSuccess("Select one input at high feerates", high_feerate_pool, /*selection_target=*/10 * CENT, /*expected_input_amounts=*/{10 * CENT}, high_feerate_params);
133+
134+
// Add heavy inputs {6, 7} to existing {2, 3, 5, 10}
135+
low_feerate_pool.push_back(MakeCoin(6 * CENT, true, default_cs_params, /*custom_spending_vsize=*/500));
136+
low_feerate_pool.push_back(MakeCoin(7 * CENT, true, default_cs_params, /*custom_spending_vsize=*/500));
137+
TestBnBSuccess("Prefer two heavy inputs over two light inputs at low feerates", low_feerate_pool, /*selection_target=*/13 * CENT, /*expected_input_amounts=*/{6 * CENT, 7 * CENT}, default_cs_params, /*custom_spending_vsize=*/500);
138+
139+
high_feerate_pool.push_back(MakeCoin(6 * CENT, true, high_feerate_params, /*custom_spending_vsize=*/500));
140+
high_feerate_pool.push_back(MakeCoin(7 * CENT, true, high_feerate_params, /*custom_spending_vsize=*/500));
141+
TestBnBSuccess("Prefer two light inputs over two heavy inputs at high feerates", high_feerate_pool, /*selection_target=*/13 * CENT, /*expected_input_amounts=*/{3 * CENT, 10 * CENT}, high_feerate_params);
142+
}
143+
121144
BOOST_AUTO_TEST_SUITE_END()
122145
} // namespace wallet

src/wallet/test/coinselector_tests.cpp

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -321,53 +321,20 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
321321

322322
CoinsResult available_coins;
323323

324-
// single coin should be selected when effective fee > long term fee
325-
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
326-
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
327-
328-
// Add selectable outputs, increasing their raw amounts by their input fee to make the effective value equal to the raw amount
329-
CAmount input_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(/*num_bytes=*/68); // bech32 input size (default test output type)
330-
add_coin(available_coins, *wallet, 10 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
331-
add_coin(available_coins, *wallet, 9 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
332-
add_coin(available_coins, *wallet, 1 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
333-
334-
expected_result.Clear();
335-
add_coin(10 * CENT + input_fee, 2, expected_result);
336-
CCoinControl coin_control;
337-
const auto result11 = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/{}, 10 * CENT, coin_control, coin_selection_params_bnb);
338-
BOOST_CHECK(EquivalentResult(expected_result, *result11));
339-
available_coins.Clear();
340-
341-
// more coins should be selected when effective fee < long term fee
342-
coin_selection_params_bnb.m_effective_feerate = CFeeRate(3000);
343-
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(5000);
344-
345-
// Add selectable outputs, increasing their raw amounts by their input fee to make the effective value equal to the raw amount
346-
input_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(/*num_bytes=*/68); // bech32 input size (default test output type)
347-
add_coin(available_coins, *wallet, 10 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
348-
add_coin(available_coins, *wallet, 9 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
349-
add_coin(available_coins, *wallet, 1 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
350-
351-
expected_result.Clear();
352-
add_coin(9 * CENT + input_fee, 2, expected_result);
353-
add_coin(1 * CENT + input_fee, 2, expected_result);
354-
const auto result12 = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/{}, 10 * CENT, coin_control, coin_selection_params_bnb);
355-
BOOST_CHECK(EquivalentResult(expected_result, *result12));
356-
available_coins.Clear();
357-
358324
// pre selected coin should be selected even if disadvantageous
359325
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
360326
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
361327

362328
// Add selectable outputs, increasing their raw amounts by their input fee to make the effective value equal to the raw amount
363-
input_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(/*num_bytes=*/68); // bech32 input size (default test output type)
329+
CAmount input_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(/*num_bytes=*/68); // bech32 input size (default test output type)
364330
add_coin(available_coins, *wallet, 10 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
365331
add_coin(available_coins, *wallet, 9 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
366332
add_coin(available_coins, *wallet, 1 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
367333

368334
expected_result.Clear();
369335
add_coin(9 * CENT + input_fee, 2, expected_result);
370336
add_coin(1 * CENT + input_fee, 2, expected_result);
337+
CCoinControl coin_control;
371338
coin_control.m_allow_other_inputs = true;
372339
COutput select_coin = available_coins.All().at(1); // pre select 9 coin
373340
coin_control.Select(select_coin.outpoint);

0 commit comments

Comments
 (0)