[wallet] Add "needed" and "available" metadata to Error::InsufficientFunds

This commit is contained in:
Justin Moon 2020-11-17 18:05:33 -06:00 committed by Alekos Filini
parent 733355a6ae
commit 52b45c5b89
No known key found for this signature in database
GPG Key ID: 431401E4A4530061
4 changed files with 34 additions and 11 deletions

View File

@ -47,7 +47,12 @@ pub enum Error {
/// Output created is under the dust limit, 546 satoshis /// Output created is under the dust limit, 546 satoshis
OutputBelowDustLimit(usize), OutputBelowDustLimit(usize),
/// Wallet's UTXO set is not enough to cover recipient's requested plus fee /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
InsufficientFunds, InsufficientFunds {
/// Sats needed for some transaction
needed: u64,
/// Sats available for spending
available: u64,
},
/// Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow /// Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow
/// exponentially, thus a limit is set, and when hit, this error is thrown /// exponentially, thus a limit is set, and when hit, this error is thrown
BnBTotalTriesExceeded, BnBTotalTriesExceeded,

View File

@ -71,9 +71,9 @@
//! }) //! })
//! .collect::<Vec<_>>(); //! .collect::<Vec<_>>();
//! let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0; //! let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
//! //! let amount_needed_with_fees = (fee_amount + additional_fees).ceil() as u64 + amount_needed;
//! if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount { //! if amount_needed_with_fees > selected_amount {
//! return Err(bdk::Error::InsufficientFunds); //! return Err(bdk::Error::InsufficientFunds{ needed: amount_needed_with_fees, available: selected_amount });
//! } //! }
//! //!
//! Ok(CoinSelectionResult { //! Ok(CoinSelectionResult {
@ -221,8 +221,12 @@ impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection {
) )
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if selected_amount < amount_needed + (fee_amount.ceil() as u64) { let amount_needed_with_fees = amount_needed + (fee_amount.ceil() as u64);
return Err(Error::InsufficientFunds); if selected_amount < amount_needed_with_fees {
return Err(Error::InsufficientFunds {
needed: amount_needed_with_fees,
available: selected_amount,
});
} }
Ok(CoinSelectionResult { Ok(CoinSelectionResult {
@ -321,7 +325,10 @@ impl<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection {
let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb(); let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb();
if curr_available_value + curr_value < actual_target { if curr_available_value + curr_value < actual_target {
return Err(Error::InsufficientFunds); return Err(Error::InsufficientFunds {
needed: actual_target,
available: curr_available_value + curr_value,
});
} }
Ok(self Ok(self

View File

@ -59,7 +59,10 @@ pub use utils::IsDust;
use address_validator::AddressValidator; use address_validator::AddressValidator;
use signer::{Signer, SignerId, SignerOrdering, SignersContainer}; use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxBuilderContext}; use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxBuilderContext};
use utils::{check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx}; use utils::{
check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx,
DUST_LIMIT_SATOSHI,
};
use crate::blockchain::{Blockchain, Progress}; use crate::blockchain::{Blockchain, Progress};
use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils}; use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
@ -508,7 +511,11 @@ where
match change_output { match change_output {
None if change_val.is_dust() => { None if change_val.is_dust() => {
// single recipient, but the only output would be below dust limit // single recipient, but the only output would be below dust limit
return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit? // TODO: or OutputBelowDustLimit?
return Err(Error::InsufficientFunds {
needed: DUST_LIMIT_SATOSHI,
available: change_val,
});
} }
Some(_) if change_val.is_dust() => { Some(_) if change_val.is_dust() => {
// skip the change output because it's dust -- just include it in the fee. // skip the change output because it's dust -- just include it in the fee.
@ -786,7 +793,11 @@ where
} }
Some(_) if change_val_after_add.is_dust() => { Some(_) if change_val_after_add.is_dust() => {
// single_recipient but the only output would be below dust limit // single_recipient but the only output would be below dust limit
return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit? // TODO: or OutputBelowDustLimit?
return Err(Error::InsufficientFunds {
needed: DUST_LIMIT_SATOSHI,
available: change_val_after_add,
});
} }
None => { None => {
removed_updatable_output.value = change_val_after_add; removed_updatable_output.value = change_val_after_add;

View File

@ -29,7 +29,7 @@ use miniscript::descriptor::DescriptorPublicKeyCtx;
use miniscript::{MiniscriptKey, Satisfier, ToPublicKey}; use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
// De-facto standard "dust limit" (even though it should change based on the output type) // De-facto standard "dust limit" (even though it should change based on the output type)
const DUST_LIMIT_SATOSHI: u64 = 546; pub const DUST_LIMIT_SATOSHI: u64 = 546;
// MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when // MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when
// spending using CSV in order to enforce CSV rules // spending using CSV in order to enforce CSV rules