Closed icota closed 2 years ago
Thanks for opening the issue! You're right, there's definitely something weird going on, I'm looking into it.
Out of curiosity: can you actually finalize the psbt? (Using the private descriptors instead of the public ones). If so, what's the feerate of the finalized tx?
I wonder if the problem is that the specified fee_rate
is too high and we don't correctly handle this case
I just wanted to point out that the example code is written as a test and...
/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
/// overridden
#[cfg(not(test))]
pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
#[cfg(test)]
pub type DefaultCoinSelectionAlgorithm = LargestFirstCoinSelection; // make the tests more predictable
Just in case the bug is algorithm-specific.
Thanks for looking into this!
@danielabrozzoni I can finalize the above PSBT without issue.
@evanlinjin my colleague @bitcoinqna noticed this in "production" so it's probably reproducible with both of the above algorithms.
The good news is that @csralvall's #630 fixed the problem (and we didn't even notice in code review 😁). #666 will add a test to make sure we don't introduce those bugs anymore, and me and @afilini are discussing how to better test the fee calculation and the coin selection (spoiler: fuzzing 🌸)
Just for the sake of completeness, the original issue was that we would calculate drain_val
using saturating_sub
:
https://github.com/bitcoindevkit/bdk/blob/3644a452c16717c259c3d6c1b3aff7c9b636a800/src/wallet/mod.rs#L819
Which means that if coin_selection.selected_amount() - outgoing - fee_amount
was supposed to be <0, using saturating_sub
it would result in 0.
Which is fine... unless you suppose the value of drain_val
is precise, and you add it back to the fees when no drain output is created:
https://github.com/bitcoindevkit/bdk/blob/3644a452c16717c259c3d6c1b3aff7c9b636a800/src/wallet/mod.rs#L841-L843
Which is exactly what was happening here: drain_val
was 0, but coin_selection.selected_amount() - outgoing - fee_amount
was -57, which meant that we added 0
instead of -57
to the fee_amount
, and it would result in 286
instead of 229
.
Code:
Output:
At first glance
8630 + 286 = 8916
is greater than bothTransactionDetails
sent value and the balance of UTXOs of the provided tpub which at this time is 8859 sats.Back of envelope calculations say fee for this tx should be 229 sats. Parsing the above PSBT with Core's
decodepsbt
confirms it:Build environment
BDK tag/commit: https://github.com/bitcoindevkit/bdk/commit/a328607d27feb5d556df99ec6beabc41cc655160 OS+version: Ubuntu 22.04 Rust/Cargo version: 1.54.0 Rust/Cargo target: x86_64