Skip to content

Commit 5cea25b

Browse files
murchandamusfurszy
andcommitted
wallet: skip BnB when SFFO is active
Co-authored-by: furszy <matiasfurszyfer@protonmail.com>
1 parent 160d236 commit 5cea25b

File tree

2 files changed

+28
-19
lines changed

2 files changed

+28
-19
lines changed

src/wallet/spend.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -693,9 +693,12 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
693693
// Maximum allowed weight
694694
int max_inputs_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
695695

696-
if (auto bnb_result{SelectCoinsBnB(groups.positive_group, nTargetValue, coin_selection_params.m_cost_of_change, max_inputs_weight)}) {
697-
results.push_back(*bnb_result);
698-
} else append_error(bnb_result);
696+
// SFFO frequently causes issues in the context of changeless input sets: skip BnB when SFFO is active
697+
if (!coin_selection_params.m_subtract_fee_outputs) {
698+
if (auto bnb_result{SelectCoinsBnB(groups.positive_group, nTargetValue, coin_selection_params.m_cost_of_change, max_inputs_weight)}) {
699+
results.push_back(*bnb_result);
700+
} else append_error(bnb_result);
701+
}
699702

700703
// As Knapsack and SRD can create change, also deduce change weight.
701704
max_inputs_weight -= (coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR);

src/wallet/test/coinselector_tests.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,6 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
320320
coin_selection_params_bnb.m_change_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_output_size);
321321
coin_selection_params_bnb.m_cost_of_change = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_spend_size) + coin_selection_params_bnb.m_change_fee;
322322
coin_selection_params_bnb.min_viable_change = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_spend_size);
323-
coin_selection_params_bnb.m_subtract_fee_outputs = true;
324323

325324
{
326325
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
@@ -345,6 +344,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
345344

346345
CoinsResult available_coins;
347346

347+
coin_selection_params_bnb.m_effective_feerate = CFeeRate(0);
348348
add_coin(available_coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
349349
add_coin(available_coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
350350
add_coin(available_coins, *wallet, 2 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
@@ -355,7 +355,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
355355
PreSelectedInputs selected_input;
356356
selected_input.Insert(select_coin, coin_selection_params_bnb.m_subtract_fee_outputs);
357357
available_coins.Erase({available_coins.coins[OutputType::BECH32].begin()->outpoint});
358-
coin_selection_params_bnb.m_effective_feerate = CFeeRate(0);
358+
359359
LOCK(wallet->cs_wallet);
360360
const auto result10 = SelectCoins(*wallet, available_coins, selected_input, 10 * CENT, coin_control, coin_selection_params_bnb);
361361
BOOST_CHECK(result10);
@@ -370,12 +370,14 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
370370
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
371371
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
372372

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

377379
expected_result.Clear();
378-
add_coin(10 * CENT, 2, expected_result);
380+
add_coin(10 * CENT + input_fee, 2, expected_result);
379381
CCoinControl coin_control;
380382
const auto result11 = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/{}, 10 * CENT, coin_control, coin_selection_params_bnb);
381383
BOOST_CHECK(EquivalentResult(expected_result, *result11));
@@ -385,13 +387,15 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
385387
coin_selection_params_bnb.m_effective_feerate = CFeeRate(3000);
386388
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(5000);
387389

388-
add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
389-
add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
390-
add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
390+
// Add selectable outputs, increasing their raw amounts by their input fee to make the effective value equal to the raw amount
391+
input_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(/*num_bytes=*/68); // bech32 input size (default test output type)
392+
add_coin(available_coins, *wallet, 10 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
393+
add_coin(available_coins, *wallet, 9 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
394+
add_coin(available_coins, *wallet, 1 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
391395

392396
expected_result.Clear();
393-
add_coin(9 * CENT, 2, expected_result);
394-
add_coin(1 * CENT, 2, expected_result);
397+
add_coin(9 * CENT + input_fee, 2, expected_result);
398+
add_coin(1 * CENT + input_fee, 2, expected_result);
395399
const auto result12 = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/{}, 10 * CENT, coin_control, coin_selection_params_bnb);
396400
BOOST_CHECK(EquivalentResult(expected_result, *result12));
397401
available_coins.Clear();
@@ -400,13 +404,15 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
400404
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
401405
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
402406

403-
add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
404-
add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
405-
add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
407+
// Add selectable outputs, increasing their raw amounts by their input fee to make the effective value equal to the raw amount
408+
input_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(/*num_bytes=*/68); // bech32 input size (default test output type)
409+
add_coin(available_coins, *wallet, 10 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
410+
add_coin(available_coins, *wallet, 9 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
411+
add_coin(available_coins, *wallet, 1 * CENT + input_fee, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
406412

407413
expected_result.Clear();
408-
add_coin(9 * CENT, 2, expected_result);
409-
add_coin(1 * CENT, 2, expected_result);
414+
add_coin(9 * CENT + input_fee, 2, expected_result);
415+
add_coin(1 * CENT + input_fee, 2, expected_result);
410416
coin_control.m_allow_other_inputs = true;
411417
COutput select_coin = available_coins.All().at(1); // pre select 9 coin
412418
coin_control.Select(select_coin.outpoint);

0 commit comments

Comments
 (0)