Skip to content

Conversation

achow101
Copy link
Member

@achow101 achow101 commented May 21, 2021

Instead of returning a set of selected coins and their total value as separate items, encapsulate both of these, and other variables, into a new SelectionResult struct. This allows us to have all of the things relevant to a coin selection solution be in a single object. SelectionResult enables us to implement the waste calculation in a cleaner way.

All of the coin selection functions (SelectCoinsBnB, KnapsackSolver, AttemptSelection, and SelectCoins) are changed to use a SelectionResult as the output parameter.

Based on #22009

@DrahtBot
Copy link
Contributor

DrahtBot commented May 22, 2021

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #23534 (wallet: Allow negtive effective value inputs when subtracting fee from outputs by achow101)
  • #23497 (Add src/node/ and src/wallet/ code to node:: and wallet:: namespaces by ryanofsky)
  • #23475 (wallet: add config to prioritize a solution that doesn't create change in coin selection by brunoerg)
  • #23367 (Optimize coin selection by dropping BnB upper limit by S3RK)
  • #23202 (wallet: allow psbtbumpfee to work with txs with external inputs by achow101)
  • #23201 (wallet: Allow users to specify input weights when funding a transaction by achow101)
  • #13226 (Optimize SelectCoinsBnB by tracking the selection by index rather than by position by Empact)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK

@achow101 achow101 force-pushed the selectionresult branch 2 times, most recently from 4681b17 to 0d8fe54 Compare September 1, 2021 21:19
@achow101 achow101 marked this pull request as ready for review September 1, 2021 21:20
Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Light review, concept ACK

@@ -178,15 +197,15 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// Select 1 Cent
add_coin(1 * CENT, 1, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 1 * CENT, 0.5 * CENT, selection, value_ret));
BOOST_CHECK(equal_sets(selection, actual_selection));
BOOST_CHECK(equivalent_sets(selection, actual_selection));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit 80402a1: This may be more a comment on the commit message, but shouldn't the result of BnB be deterministic? Are the OutputGroups unsorted, or how is this happening?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember the specifics, but I think it had to with different txids being in utxo_pool and actual_selection

@achow101 achow101 force-pushed the selectionresult branch 4 times, most recently from dd05b60 to e142d9a Compare November 23, 2021 23:26
@laanwj
Copy link
Member

laanwj commented Dec 2, 2021

Code review ACK e142d9a
Seems pretty close to merge, found some last minute nits (sorry).

Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK e142d9a, a few suggestions/questions

Introduces a SelectionResult struct which contains the set of selected
inputs and the total transaction fee for the transaction. This will be
used by the various SelectCoins* functions. Additionally helpers are
provided to compute the total input value and result comparisons.
Replace the CoinSet actual_selection with a SelectionResult
expected_result. We don't use the SelectionResult functions yet, but
will soon.

-BEGIN VERIFY SCRIPT-
sed -i 's/CoinSet actual_selection/SelectionResult expected_result(CAmount(0))/' src/wallet/test/coinselector_tests.cpp
sed -i 's/actual_selection/expected_result.m_selected_inputs/' src/wallet/test/coinselector_tests.cpp
sed -i 's/expected_result.m_selected_inputs.clear/expected_result.Clear/' src/wallet/test/coinselector_tests.cpp
-END VERIFY SCRIPT-
Removes coins_out and value_ret has SelectCoinsBnB return a
std::optional<SelectionResult>
Returns a std::optional<SelectionResult> from KnapsackSolver instead of
using out parameters for the inputs set and selected value.
Changes SelectCoinsSRD to return a SelectionResult.
In SelectCoins, for our preset inputs, we combine all of the preset
inputs into a single OutputGroup. This allows us to combine the preset
inputs with additional selection algo results.
Replace setCoinsRet and nValueRet with a SelectionResult in
AttemptSelection
Replace setCoinsRet and nValueRet with SelectionResult
@laanwj
Copy link
Member

laanwj commented Dec 9, 2021

Code review ACK 05300c1

@laanwj laanwj merged commit c840ab0 into bitcoin:master Dec 9, 2021
Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reACK 05300c1. Thanks for taking suggestions!

Comment on lines -422 to +413
const auto& best_result = std::min_element(results.begin(), results.end(), [](const auto& a, const auto& b) {
return std::get<0>(a) < std::get<0>(b) || (std::get<0>(a) == std::get<0>(b) && std::get<1>(a).size() > std::get<1>(b).size());
});
setCoinsRet = std::get<1>(*best_result);
nValueRet = std::get<2>(*best_result);
return true;
auto& best_result = *std::min_element(results.begin(), results.end());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😗 👌

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some q


CAmount SelectionResult::GetWaste() const
{
Assume(m_waste != std::nullopt);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to be Assert, otherwise you might run into UB, no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assume(m_waste != std::nullopt);
Assume(other.m_waste != std::nullopt);
// As this operator is only used in std::min_element, we want the result that has more inputs when waste are equal.
return *m_waste < *other.m_waste || (*m_waste == *other.m_waste && m_selected_inputs.size() > other.m_selected_inputs.size());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

RandyMcMillan pushed a commit to RandyMcMillan/mempool-tab that referenced this pull request Dec 23, 2021
…capsulating a coin selection solution

b09b4f2 Use SelectionResult in SelectCoins (Andrew Chow)
ee30ea0 Use SelectionResult in AttemptSelection (Andrew Chow)
ffacd8b Use SelectionResult for waste calculation (Andrew Chow)
4e02a76 Make an OutputGroup for preset inputs (Andrew Chow)
c63ef3d Return SelectionResult from SelectCoinsSRD (Andrew Chow)
ac4f10a Return SelectionResult from KnapsackSolver (Andrew Chow)
361c7c2 Return SelectionResult from SelectCoinsBnB (Andrew Chow)
d099e74 Make member variables of SelectionResult private (Andrew Chow)
af51708 scripted-diff: Use SelectionResult in coin selector tests (Andrew Chow)
c6aca86 Introduce SelectionResult struct (Andrew Chow)
3f4a86b Fix bnb_search_test to use set equivalence for (Andrew Chow)

Pull request description:

  Instead of returning a set of selected coins and their total value as separate items, encapsulate both of these, and other variables, into a new `SelectionResult` struct. This allows us to have all of the things relevant to a coin selection solution be in a single object. `SelectionResult` enables us to implement the waste calculation in a cleaner way.

  All of the coin selection functions (`SelectCoinsBnB`, `KnapsackSolver`, `AttemptSelection`, and `SelectCoins`) are changed to use a `SelectionResult` as the output parameter.

  Based on #22009

ACKs for top commit:
  laanwj:
    Code review ACK b09b4f2

Tree-SHA512: e4dbb4d78a6cda9c237d230b19e7265591efac5a101a64e6970f0654e2c4f93d13bb5d07b98e8c7b8d37321753dbfc94c28c3a7810cb1c59b5bc29b08a8493ef
@bitcoin bitcoin locked and limited conversation to collaborators Dec 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants