Skip to content

Add waste metric for coin selection#435

Closed
benthecarman wants to merge 1 commit intobitcoindevkit:masterfrom
benthecarman:coin-selection-waste-metric
Closed

Add waste metric for coin selection#435
benthecarman wants to merge 1 commit intobitcoindevkit:masterfrom
benthecarman:coin-selection-waste-metric

Conversation

@benthecarman
Copy link
Copy Markdown
Contributor

Implementation of the coin selection waste metric from bitcoin/bitcoin#22009

Later this can be used in the wallet to select the most optimal coin selection algo.

I plan on adding more of the tests but wanted to get this out there as I am new to rust and I am guessing I have some things I need to fix.

}
}

struct WasteMetric;
Copy link
Copy Markdown
Member

@notmandatory notmandatory Sep 6, 2021

Choose a reason for hiding this comment

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

This looks like a good direction for improving coin selection, I haven't looked deeply into the code/algorithm but I do have a couple rust style suggestions.

  1. Unless you plan on adding additional fields to the WasteMetric struct I think you can do without it.
  2. And if the idea for calculate_waste is as a helper function to implementations of the CoinSelectionAlgorithm trait then it may be better to make calculate_waste a "default implementation" on the CoinSelectionAlgorithm trait.

If you take this approach then possibly CoinSelectionResult could include a waste metric field.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The waste metric requires a long term fee rate (expected average fee rate of the wallet) so idk if it can be directly be added to CoinSelectionResult.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just to clarify, the "Long Term Feerate Estimate" (LTFRE) is not the average feerate on the wallet, it's more of a minimum feerate that you expect to be able to spend at in the future. The thinking is that if you expect to be able to spend an input at a lower feerate in the future, you should delay spending it to then, hence, anything above that feerate is considered "wasteful". Since you always need to use at least one input, two solutions that each use one input of the same type will see their score increase by the same amount, so it doesn't affect their prioritization. However, if you e.g. have different output types or compare solutions with multiple inputs, you'll prefer the smaller input weight per this heuristic.

Copy link
Copy Markdown
Contributor

@rajarshimaitra rajarshimaitra left a comment

Choose a reason for hiding this comment

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

Thanks for the pull.

tested and concept ACK.

Can you please provide some more doc details within the code on waste metric? Is it used by core too? I would like to learn more about the rationale behind the waste calculations and see how that can be used to make selction-algo choices efficient.

Comment on lines +539 to +546
impl WasteMetric {
fn calculate_waste(
selected: Vec<WeightedUtxo>,
cost_of_change: Option<u64>,
amount_needed: u64,
fee_rate: FeeRate,
long_term_fee_rate: FeeRate,
) -> i64 {
Copy link
Copy Markdown
Contributor

@rajarshimaitra rajarshimaitra Sep 7, 2021

Choose a reason for hiding this comment

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

Instead of returning i64 why not return just return Self? And have i64 or whatever as member of WasteMetric. If we are defining a struct anyway, lets use it. :)

In this way we can also use this inside CoinSelectionResult later. This seems to me like a very nice tool to compare different selection algorithm and we can expose a simple API to users with some default configs (like long term fee rate etc).

@notmandatory
Copy link
Copy Markdown
Member

Some good suggestions came up in our team chat today from @LLFourn and @afilini about his PR.

  • your calculate_waste function could be implemented on the CoinSelectionResult struct, which already contains the .selected utxos.
  • then it would be straight forward to create a function (maybe on Wallet?) that does coin_select() for different CoinSelectionAlgorithm implementations and returns the optimal result.

Also @rajarshimaitra reminded us that tomorrows PR review club will be on this topic, so good for anyone interested to attend.

@notmandatory
Copy link
Copy Markdown
Member

moving this one to DRAFT until we figure out how to integrate it.

@notmandatory notmandatory marked this pull request as draft December 14, 2021 19:49
@csralvall
Copy link
Copy Markdown
Contributor

Hey @benthecarman, are you still working on this? May I continue your work?

@benthecarman
Copy link
Copy Markdown
Contributor Author

Hey @benthecarman, are you still working on this? May I continue your work?

Feel free to!

@csralvall
Copy link
Copy Markdown
Contributor

Some good suggestions came up in our team chat today from @LLFourn and @afilini about his PR.

  • your calculate_waste function could be implemented on the CoinSelectionResult struct, which already contains the .selected utxos.
  • then it would be straight forward to create a function (maybe on Wallet?) that does coin_select() for different CoinSelectionAlgorithm implementations and returns the optimal result.

Also @rajarshimaitra reminded us that tomorrows PR review club will be on this topic, so good for anyone interested to attend.

Although CoinSelectionResult may be related to the calculate_waste function, and the shared selected parameter makes it more natural to think so, I found some drawbacks in this approach.
Schmidty noted in the PR review club that there were two waste metrics in use currently in Bitcoin Core. The one computed by the function GetSelectionWaste and the one used by BnB to improve the selection.
Currently, GetSelectionWaste in Bitcoin Core master branch, is implemented as an independent function, not an associated one nor a method, and SelectionResult implements a public wrapper method around it to make comparisons between different algorithms. This approach allows the future refactoring of the BnB to deduplicate the calculation of the waste metric and, at the same time, the current comparison of the coin selection algorithms.
I suggest to follow the implementation of Bitcoin Core. To make calculate_waste an independent function, with a public wrapper (e.g.: get_waste) method around it in the CoinSelectionResult. This will give us the same flexibility mentioned above.

@rajarshimaitra
Copy link
Copy Markdown
Contributor

@csralvall That makes sense.. Eventually we would want to use the waste function to compare potential wastes between different coin selections.. It makes sense that it can be different than what BnB uses internally..

I think I understand the approach you are suggesting, although would be more clear when I see the code.. Feel free to update the PR (or make new one) and I would review..

@csralvall csralvall mentioned this pull request Mar 6, 2022
6 tasks
@murchandamus
Copy link
Copy Markdown
Contributor

Can you please provide some more doc details within the code on waste metric? Is it used by core too? I would like to learn more about the rationale behind the waste calculations and see how that can be used to make selction-algo choices efficient.

I recently wrote a blog post about this, let me know if you have open questions, I'd be happy to incorporate feedback: https://murch.one/posts/waste-metric/

It makes sense that it can be different than what BnB uses internally.

Yeah, that's actually a good point. So far, I don't see a reason why the two would diverge, but another contributor recently suggested that we could introduce additional heuristics based on privacy and confirmation-reliability to aid in prioritization of SelectionResults. These additional heuristics might only apply to the choice between the solutions from different algorithms rather than internally to BnB.

@danielabrozzoni
Copy link
Copy Markdown
Member

Hey, we are in the process of releasing BDK 1.0, which will under the hood work quite differently from the current BDK. For this reason, I'm closing all the PRs that don't really apply anymore. If you think this is a mistake, feel free to rebase on master and re-open!

(Specifically, the coin selection is being rewritten from scratch)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants