mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-23 15:20:49 +01:00
Do both BnB and Knapsack coin selection in SelectCoinsMinConf
Instead of switching which algorithm to use based on use_bnb, just run both in SelectCoinsMinConf. If BnB fails, do Knapsack.
This commit is contained in:
parent
01dc8ebda5
commit
de26eb0e1f
2 changed files with 21 additions and 22 deletions
|
@ -287,9 +287,9 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
|
||||||
empty_wallet();
|
empty_wallet();
|
||||||
add_coin(1 * CENT);
|
add_coin(1 * CENT);
|
||||||
vCoins.at(0).nInputBytes = 40;
|
vCoins.at(0).nInputBytes = 40;
|
||||||
BOOST_CHECK(!testWallet.SelectCoinsMinConf( 1 * CENT, filter_standard, vCoins, setCoinsRet, nValueRet, coin_selection_params_bnb, bnb_used));
|
|
||||||
coin_selection_params_bnb.m_subtract_fee_outputs = true;
|
coin_selection_params_bnb.m_subtract_fee_outputs = true;
|
||||||
BOOST_CHECK(testWallet.SelectCoinsMinConf( 1 * CENT, filter_standard, vCoins, setCoinsRet, nValueRet, coin_selection_params_bnb, bnb_used));
|
BOOST_CHECK(testWallet.SelectCoinsMinConf( 1 * CENT, filter_standard, vCoins, setCoinsRet, nValueRet, coin_selection_params_bnb, bnb_used));
|
||||||
|
BOOST_CHECK(bnb_used);
|
||||||
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT);
|
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT);
|
||||||
|
|
||||||
// Make sure that can use BnB when there are preset inputs
|
// Make sure that can use BnB when there are preset inputs
|
||||||
|
@ -549,17 +549,19 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
|
||||||
for (int i = 0; i < RUN_TESTS; i++) {
|
for (int i = 0; i < RUN_TESTS; i++) {
|
||||||
// picking 50 from 100 coins doesn't depend on the shuffle,
|
// picking 50 from 100 coins doesn't depend on the shuffle,
|
||||||
// but does depend on randomness in the stochastic approximation code
|
// but does depend on randomness in the stochastic approximation code
|
||||||
BOOST_CHECK(testWallet.SelectCoinsMinConf(50 * COIN, filter_standard, vCoins, setCoinsRet , nValueRet, coin_selection_params, bnb_used));
|
BOOST_CHECK(KnapsackSolver(50 * COIN, GroupCoins(vCoins), setCoinsRet, nValueRet));
|
||||||
BOOST_CHECK(testWallet.SelectCoinsMinConf(50 * COIN, filter_standard, vCoins, setCoinsRet2, nValueRet, coin_selection_params, bnb_used));
|
BOOST_CHECK(KnapsackSolver(50 * COIN, GroupCoins(vCoins), setCoinsRet2, nValueRet));
|
||||||
BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2));
|
BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2));
|
||||||
|
|
||||||
int fails = 0;
|
int fails = 0;
|
||||||
for (int j = 0; j < RANDOM_REPEATS; j++)
|
for (int j = 0; j < RANDOM_REPEATS; j++)
|
||||||
{
|
{
|
||||||
// selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
|
// Test that the KnapsackSolver selects randomly from equivalent coins (same value and same input size).
|
||||||
// run the test RANDOM_REPEATS times and only complain if all of them fail
|
// When choosing 1 from 100 identical coins, 1% of the time, this test will choose the same coin twice
|
||||||
BOOST_CHECK(testWallet.SelectCoinsMinConf(COIN, filter_standard, vCoins, setCoinsRet , nValueRet, coin_selection_params, bnb_used));
|
// which will cause it to fail.
|
||||||
BOOST_CHECK(testWallet.SelectCoinsMinConf(COIN, filter_standard, vCoins, setCoinsRet2, nValueRet, coin_selection_params, bnb_used));
|
// To avoid that issue, run the test RANDOM_REPEATS times and only complain if all of them fail
|
||||||
|
BOOST_CHECK(KnapsackSolver(COIN, GroupCoins(vCoins), setCoinsRet, nValueRet));
|
||||||
|
BOOST_CHECK(KnapsackSolver(COIN, GroupCoins(vCoins), setCoinsRet2, nValueRet));
|
||||||
if (equal_sets(setCoinsRet, setCoinsRet2))
|
if (equal_sets(setCoinsRet, setCoinsRet2))
|
||||||
fails++;
|
fails++;
|
||||||
}
|
}
|
||||||
|
@ -579,10 +581,8 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
|
||||||
int fails = 0;
|
int fails = 0;
|
||||||
for (int j = 0; j < RANDOM_REPEATS; j++)
|
for (int j = 0; j < RANDOM_REPEATS; j++)
|
||||||
{
|
{
|
||||||
// selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
|
BOOST_CHECK(KnapsackSolver(90*CENT, GroupCoins(vCoins), setCoinsRet, nValueRet));
|
||||||
// run the test RANDOM_REPEATS times and only complain if all of them fail
|
BOOST_CHECK(KnapsackSolver(90*CENT, GroupCoins(vCoins), setCoinsRet2, nValueRet));
|
||||||
BOOST_CHECK(testWallet.SelectCoinsMinConf(90*CENT, filter_standard, vCoins, setCoinsRet , nValueRet, coin_selection_params, bnb_used));
|
|
||||||
BOOST_CHECK(testWallet.SelectCoinsMinConf(90*CENT, filter_standard, vCoins, setCoinsRet2, nValueRet, coin_selection_params, bnb_used));
|
|
||||||
if (equal_sets(setCoinsRet, setCoinsRet2))
|
if (equal_sets(setCoinsRet, setCoinsRet2))
|
||||||
fails++;
|
fails++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2406,12 +2406,12 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
|
||||||
effective_feerate = coin_selection_params.m_effective_feerate;
|
effective_feerate = coin_selection_params.m_effective_feerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coin_selection_params.use_bnb) {
|
|
||||||
std::vector<OutputGroup> positive_groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, effective_feerate, coin_selection_params.m_long_term_feerate, eligibility_filter, true /* positive_only */);
|
std::vector<OutputGroup> positive_groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, effective_feerate, coin_selection_params.m_long_term_feerate, eligibility_filter, true /* positive_only */);
|
||||||
bnb_used = true;
|
|
||||||
// Note that unlike KnapsackSolver, we do not include the fee for creating a change output as BnB will not create a change output.
|
// Note that unlike KnapsackSolver, we do not include the fee for creating a change output as BnB will not create a change output.
|
||||||
return SelectCoinsBnB(positive_groups, nTargetValue, coin_selection_params.m_cost_of_change, setCoinsRet, nValueRet);
|
if (SelectCoinsBnB(positive_groups, nTargetValue, coin_selection_params.m_cost_of_change, setCoinsRet, nValueRet)) {
|
||||||
} else {
|
bnb_used = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
|
// The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
|
||||||
std::vector<OutputGroup> all_groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, effective_feerate, coin_selection_params.m_long_term_feerate, eligibility_filter, false /* positive_only */);
|
std::vector<OutputGroup> all_groups = GroupOutputs(coins, !coin_selection_params.m_avoid_partial_spends, effective_feerate, coin_selection_params.m_long_term_feerate, eligibility_filter, false /* positive_only */);
|
||||||
bnb_used = false;
|
bnb_used = false;
|
||||||
|
@ -2419,7 +2419,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
|
||||||
// So we need to include that for KnapsackSolver as well, as we are expecting to create a change output.
|
// So we need to include that for KnapsackSolver as well, as we are expecting to create a change output.
|
||||||
return KnapsackSolver(nTargetValue + coin_selection_params.m_change_fee, all_groups, setCoinsRet, nValueRet);
|
return KnapsackSolver(nTargetValue + coin_selection_params.m_change_fee, all_groups, setCoinsRet, nValueRet);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const
|
bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue