Skip to content
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

Fix the early InsufficientFunds error in the branch and bound #693

Merged
merged 1 commit into from
Aug 3, 2022

Conversation

afilini
Copy link
Member

@afilini afilini commented Jul 30, 2022

Description

We were wrongly considering the sum of "effective value" (i.e. value -
fee cost) when reporting an early "insufficient funds" error in the
branch and bound coin selection.

This commit fixes essentially two issues:

  • Very high fee rates could cause a panic during the i64 -> u64
    conversion because we assumed the sum of effective values would never
    be negative
  • Since we were comparing the sum of effective values of all the UTXOs
    (even the optional UTXOs with negative effective value) with the target
    we'd like to reach, we could in some cases error and tell the user we
    don't have enough funds, while in fact we do! Since we are not required
    to spend any of the optional UTXOs, so we could just ignore the ones
    that cost us money to spend and excluding them could potentially
    allow us to reach the target.

There's a third issue that was present before and remains even with this
fix: when we report the "available" funds in the error, we are ignoring
UTXOs with negative effective value, so it may look like there are less
funds in the wallet than there actually are.

I don't know how to convey the right message the user: if we actually
consider them we just make the "needed" value larger and larger (which
may be confusing, because if the user asks BDK to send 10k satoshis, why
do we say that we actually need 100k?), while if we don't we could report
an incorrect "available" value.

Notes to the reviewers

I'm opening this as a draft before adding tests because I want to gather some feedback on the available vs needed error reporting. I personally think reporting a reasonable "needed" value is more important than the "available", because in a wallet app I would expect this is the value that would be shown to the user.

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

Bugfixes:

  • This pull request breaks the existing API
  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

@afilini afilini added the bug Something isn't working label Jul 30, 2022
@afilini afilini added this to the Release 0.21.0 Feature Freeze milestone Jul 30, 2022
let optional_utxos: Vec<OutputGroup> = optional_utxos
.into_iter()
.map(|u| OutputGroup::new(u, fee_rate))
.filter(|u| u.effective_value.is_positive())
Copy link
Contributor

@csralvall csralvall Aug 2, 2022

Choose a reason for hiding this comment

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

I think this is fine to compute the curr_value but there might be a reason to still include the output_groups with negative effective value in the vector consumed by bnb and single_random_draw. E.g.:
There are three utxos in the wallet:
(A) with effective value of 100
(B) with effective value of 100
(C) with effective value of -75
If actual_target is equal to 125, wouldn't be Vec<A,B,C> the best selection possible for bnb or single_random_draw?

Copy link
Member Author

@afilini afilini Aug 3, 2022

Choose a reason for hiding this comment

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

I don't think so, with your solution you would spend all three UTXOs and not create a change. The final balance of the wallet would be zero.

If you exclude C, then the coin selection would pick A + B and create a change so at the end the balance of your wallet is C + the change. Which is arguably a better outcome for the user.

Remember that the effective value isn't fixed for a given UTXO, it depends on the fee rate. So maybe at a high fee rate both the change and C are negative, but at a lower fee rate they are not. Maybe today there's a fee spike or you are just in a hurry and use a high fee rate, tomorrow you can consolidate whatever is left at the min relay fee.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that's clear. I was thinking in a situation where even at the min_relay_fee the utxos were uneconomical. But, would be probably fixed by the consolidation you mentioned in the last line.

@csralvall
Copy link
Contributor

csralvall commented Aug 2, 2022

I agree with your approach. I think that we can't do better than this with the current available fields. If we wanted to go further we would have to provide more information about the uneconomical outputs, adding more complexity.

@afilini
Copy link
Member Author

afilini commented Aug 3, 2022

Since we are running late for the release I think we should just merge this as-is, since it's still a pretty big improvements over the current error. I tried experimenting with adding a fees and ignored fields to InsufficientFunds, but I think it gets a bit messy and we need more time to discuss that. Time we don't really have now.

So I'm gonna add some tests for my fixes and mark this ready for review

@afilini afilini marked this pull request as ready for review August 3, 2022 10:13
@afilini afilini force-pushed the fix/bnb-early-error branch 2 times, most recently from 1c4910e to a399fd0 Compare August 3, 2022 10:38
@@ -0,0 +1,46 @@
diff a/src/wallet/mod.rs b/src/wallet/mod.rs (rejected hunks)
Copy link
Member

Choose a reason for hiding this comment

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

This file has probably been commited by mistake :)

We were wrongly considering the sum of "effective value" (i.e. value -
fee cost) when reporting an early "insufficient funds" error in the
branch and bound coin selection.

This commit fixes essentially two issues:
- Very high fee rates could cause a panic during the i64 -> u64
  conversion because we assumed the sum of effective values would never
  be negative
- Since we were comparing the sum of effective values of *all* the UTXOs
  (even the optional UTXOs with negative effective value) with the target
  we'd like to reach, we could in some cases error and tell the user we
  don't have enough funds, while in fact we do! Since we are not required
  to spend any of the optional UTXOs, so we could just ignore the ones
  that *cost us* money to spend and excluding them could potentially
  allow us to reach the target.

There's a third issue that was present before and remains even with this
fix: when we report the "available" funds in the error, we are ignoring
UTXOs with negative effective value, so it may look like there are less
funds in the wallet than there actually are.

I don't know how to convey the right message the user: if we actually
consider them we just make the "needed" value larger and larger (which
may be confusing, because if the user asks BDK to send 10k satoshis, why
do we say that we actually need 100k?), while if we don't we could report
an incorrect "available" value.
@danielabrozzoni
Copy link
Member

utACK 9d85c96

@danielabrozzoni danielabrozzoni merged commit ef03da0 into bitcoindevkit:master Aug 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants