8000 wallet: Remove redundant waste calculation by yancyribbens · Pull Request #26061 · bitcoin/bitcoin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

wallet: Remove redundant waste calculation #26061

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/wallet/coinselection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,24 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
bool backtrack = false;
if (curr_value + curr_available_value < selection_target || // Cannot possibly reach target with the amount remaining in the curr_available_value.
curr_value > selection_target + cost_of_change || // Selected value is out of range, go back and try other branch
(curr_waste > best_waste && (utxo_pool.at(0).fee - utxo_pool.at(0).long_term_fee) > 0)) { // Don't select things which we know will be more wasteful if the waste is increasing
Copy link
Contributor

Choose a reason for hiding this comment

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

By removing this criteria for backtracking you significantly expand the search space that will lead a) to longer execution time b) overall less less solutions found due to hard cap of TOTAL_TRIES.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This doesn't change the search space. With this extra condition removed, this code path is used instead. And in the case where curr_waste > best_waste using the code path L98, nothing different happens because of this condition. Since best_waste is better than curr_waste, nothing happens and in both branches, backtrack=true is set. Running the benchmarks will show there's no difference.

Copy link
Contributor Author
@yancyribbens yancyribbens Sep 14, 2022

Choose a reason for hiding this comment

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

@S3RK The search space is not changed. The code is now simpler, however, the change could be pulled from this PR and added to a new PR since it's independent of other improvements.

Copy link
Contributor
@S3RK S3RK Sep 14, 2022

Choose a reason for hiding this comment

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

I agree that without limitation to the number of iterations you'd get the same result with your algorithm. But we actually have a hard limit of TOTAL_TRIES. That means if there are more combinations of coins than TOTAL_TRIES we're not going to explore all of them. This is why we want to exit as early as possible, in particular this condition allows to cut off branches where we didn't reach the target yet but the solution is already worse than our current best.

(utxo_pool.at(0).fee - utxo_pool.at(0).long_term_fee) > 0) { // Don't select more things if the current fee rate is expensive.
backtrack = true;
} else if (curr_value >= selection_target) { // Selected value is within range
curr_waste += (curr_value - selection_target); // This is the excess value which is added to the waste for the below comparison

// This is the excess waste for the current iteration.
curr_waste = (curr_value - selection_target);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is just the excess not the waste. Check line42 in this file or GetSelectionWaste for the waste formula.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@S3RK shouldn't the variable be called excess_val or something instead of curr_waste then? To me either would make sense although as the variable is named right now, it doesn't seem to be called excess.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, waste Contains excess but there are other components to it


// Adding another UTXO after this check could bring the waste down if the long term fee is higher than the current fee.
// However we are not going to explore that because this optimization for the waste is only done when we have hit our target
// value. Adding any more UTXOs will be just burning the UTXO; it will go entirely to fees. Thus we aren't going to
// explore any more UTXOs to avoid burning money like that.

// Don't select things which we know will be more wasteful.
if (curr_waste <= best_waste) {
best_selection = curr_selection;
best_waste = curr_waste;
}
curr_waste -= (curr_value - selection_target); // Remove the excess value as we will be selecting different coins now

backtrack = true;
}

Expand All @@ -123,7 +128,6 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
assert(utxo_pool_index == curr_selection.back());
OutputGroup& utxo = utxo_pool.at(utxo_pool_index);
curr_value -= utxo.GetSelectionAmount();
curr_waste -= utxo.fee - utxo.long_term_fee;
curr_selection.pop_back();
} else { // Moving forwards, continuing down this branch
OutputGroup& utxo = utxo_pool.at(utxo_pool_index);
Expand All @@ -142,7 +146,6 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
// Inclusion branch first (Largest First Exploration)
curr_selection.push_back(utxo_pool_index);
curr_value += utxo.GetSelectionAmount();
curr_waste += utxo.fee - utxo.long_term_fee;
}
}
}
Expand All @@ -157,7 +160,6 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
result.AddInput(utxo_pool.at(i));
}
result.ComputeAndSetWaste(cost_of_change, cost_of_change, CAmount{0});
assert(best_waste == result.GetWaste());

return result;
}
Expand Down
0