From 5f2d6cbf08106028558dda570a28de50690496d5 Mon Sep 17 00:00:00 2001 From: Leonardo Lima Date: Sun, 5 May 2024 17:41:31 -0300 Subject: [PATCH] feat: use `Amount` on `calculate_fee`, `fee_absolute`, `fee_amount` and others - update to use `bitcoin::Amount` on `CreateTxError::FeeTooLow` variant. - update to use `bitcoin::Amount` on `Wallet::calculate_fee()`. - update to use `bitcoin::Amount` on `FeePolicy::fee_absolute()`. - update to use `bitcoin::SignedAmount` on `CalculateFeeError::NegativeFee` variant. - update to use `bitcoin::Amount` on `TxGraph::calculate_fee()`. - update to use `bitcoin::Amount` on `PsbUtils::fee_amount()` --- crates/chain/src/tx_graph.rs | 27 +++-- crates/chain/tests/test_tx_graph.rs | 10 +- crates/electrum/tests/test_electrum.rs | 3 +- crates/esplora/tests/async_ext.rs | 3 +- crates/esplora/tests/blocking_ext.rs | 3 +- crates/wallet/src/psbt/mod.rs | 15 +-- crates/wallet/src/wallet/error.rs | 8 +- crates/wallet/src/wallet/mod.rs | 24 ++-- crates/wallet/src/wallet/tx_builder.rs | 12 +- crates/wallet/tests/wallet.rs | 151 +++++++++++++------------ 10 files changed, 128 insertions(+), 128 deletions(-) diff --git a/crates/chain/src/tx_graph.rs b/crates/chain/src/tx_graph.rs index d097b8fa57..c83162a6d8 100644 --- a/crates/chain/src/tx_graph.rs +++ b/crates/chain/src/tx_graph.rs @@ -95,7 +95,7 @@ use crate::{ use alloc::collections::vec_deque::VecDeque; use alloc::sync::Arc; use alloc::vec::Vec; -use bitcoin::{Amount, OutPoint, Script, Transaction, TxOut, Txid}; +use bitcoin::{Amount, OutPoint, Script, SignedAmount, Transaction, TxOut, Txid}; use core::fmt::{self, Formatter}; use core::{ convert::Infallible, @@ -182,7 +182,7 @@ pub enum CalculateFeeError { /// Missing `TxOut` for one or more of the inputs of the tx MissingTxOut(Vec), /// When the transaction is invalid according to the graph it has a negative fee - NegativeFee(i64), + NegativeFee(SignedAmount), } impl fmt::Display for CalculateFeeError { @@ -196,7 +196,7 @@ impl fmt::Display for CalculateFeeError { CalculateFeeError::NegativeFee(fee) => write!( f, "transaction is invalid according to the graph and has negative fee: {}", - fee + fee.display_dynamic() ), } } @@ -307,7 +307,7 @@ impl TxGraph { }) } - /// Calculates the fee of a given transaction. Returns 0 if `tx` is a coinbase transaction. + /// Calculates the fee of a given transaction. Returns [`Amount::ZERO`] if `tx` is a coinbase transaction. /// Returns `OK(_)` if we have all the [`TxOut`]s being spent by `tx` in the graph (either as /// the full transactions or individual txouts). /// @@ -318,20 +318,20 @@ impl TxGraph { /// Note `tx` does not have to be in the graph for this to work. /// /// [`insert_txout`]: Self::insert_txout - pub fn calculate_fee(&self, tx: &Transaction) -> Result { + pub fn calculate_fee(&self, tx: &Transaction) -> Result { if tx.is_coinbase() { - return Ok(0); + return Ok(Amount::ZERO); } let (inputs_sum, missing_outputs) = tx.input.iter().fold( - (0_i64, Vec::new()), + (SignedAmount::ZERO, Vec::new()), |(mut sum, mut missing_outpoints), txin| match self.get_txout(txin.previous_output) { None => { missing_outpoints.push(txin.previous_output); (sum, missing_outpoints) } Some(txout) => { - sum += txout.value.to_sat() as i64; + sum += txout.value.to_signed().expect("valid `SignedAmount`"); (sum, missing_outpoints) } }, @@ -343,14 +343,13 @@ impl TxGraph { let outputs_sum = tx .output .iter() - .map(|txout| txout.value.to_sat() as i64) - .sum::(); + .map(|txout| txout.value.to_signed().expect("valid `SignedAmount`")) + .sum::(); let fee = inputs_sum - outputs_sum; - if fee < 0 { - Err(CalculateFeeError::NegativeFee(fee)) - } else { - Ok(fee as u64) + match fee.to_unsigned() { + Ok(fee) => Ok(fee), + Err(_) => Err(CalculateFeeError::NegativeFee(fee)), } } diff --git a/crates/chain/tests/test_tx_graph.rs b/crates/chain/tests/test_tx_graph.rs index 26e29ed122..6377588623 100644 --- a/crates/chain/tests/test_tx_graph.rs +++ b/crates/chain/tests/test_tx_graph.rs @@ -10,8 +10,8 @@ use bdk_chain::{ Anchor, Append, BlockId, ChainOracle, ChainPosition, ConfirmationHeightAnchor, }; use bitcoin::{ - absolute, hashes::Hash, transaction, Amount, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn, - TxOut, Txid, + absolute, hashes::Hash, transaction, Amount, BlockHash, OutPoint, ScriptBuf, SignedAmount, + Transaction, TxIn, TxOut, Txid, }; use common::*; use core::iter; @@ -466,14 +466,14 @@ fn test_calculate_fee() { }], }; - assert_eq!(graph.calculate_fee(&tx), Ok(100)); + assert_eq!(graph.calculate_fee(&tx), Ok(Amount::from_sat(100))); tx.input.remove(2); // fee would be negative, should return CalculateFeeError::NegativeFee assert_eq!( graph.calculate_fee(&tx), - Err(CalculateFeeError::NegativeFee(-200)) + Err(CalculateFeeError::NegativeFee(SignedAmount::from_sat(-200))) ); // If we have an unknown outpoint, fee should return CalculateFeeError::MissingTxOut. @@ -505,7 +505,7 @@ fn test_calculate_fee_on_coinbase() { let graph = TxGraph::<()>::default(); - assert_eq!(graph.calculate_fee(&tx), Ok(0)); + assert_eq!(graph.calculate_fee(&tx), Ok(Amount::ZERO)); } // `test_walk_ancestors` uses the following transaction structure: diff --git a/crates/electrum/tests/test_electrum.rs b/crates/electrum/tests/test_electrum.rs index dd7ee6a922..3971649f91 100644 --- a/crates/electrum/tests/test_electrum.rs +++ b/crates/electrum/tests/test_electrum.rs @@ -101,7 +101,8 @@ fn scan_detects_confirmed_tx() -> anyhow::Result<()> { .fee .expect("Fee must exist") .abs() - .to_sat() as u64; + .to_unsigned() + .expect("valid `SignedAmount"); // Check that the calculated fee matches the fee from the transaction data. assert_eq!(fee, tx_fee); diff --git a/crates/esplora/tests/async_ext.rs b/crates/esplora/tests/async_ext.rs index c6f7d6ce3d..2258c9d60b 100644 --- a/crates/esplora/tests/async_ext.rs +++ b/crates/esplora/tests/async_ext.rs @@ -92,7 +92,8 @@ pub async fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { .fee .expect("Fee must exist") .abs() - .to_sat() as u64; + .to_unsigned() + .expect("valid `Amount`"); // Check that the calculated fee matches the fee from the transaction data. assert_eq!(fee, tx_fee); diff --git a/crates/esplora/tests/blocking_ext.rs b/crates/esplora/tests/blocking_ext.rs index 1d8d8d78dd..2e363f4e6d 100644 --- a/crates/esplora/tests/blocking_ext.rs +++ b/crates/esplora/tests/blocking_ext.rs @@ -92,7 +92,8 @@ pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> { .fee .expect("Fee must exist") .abs() - .to_sat() as u64; + .to_unsigned() + .expect("valid `Amount`"); // Check that the calculated fee matches the fee from the transaction data. assert_eq!(fee, tx_fee); diff --git a/crates/wallet/src/psbt/mod.rs b/crates/wallet/src/psbt/mod.rs index 7a66989e98..9b3aea843d 100644 --- a/crates/wallet/src/psbt/mod.rs +++ b/crates/wallet/src/psbt/mod.rs @@ -26,7 +26,7 @@ pub trait PsbtUtils { /// The total transaction fee amount, sum of input amounts minus sum of output amounts, in sats. /// If the PSBT is missing a TxOut for an input returns None. - fn fee_amount(&self) -> Option; + fn fee_amount(&self) -> Option; /// The transaction's fee rate. This value will only be accurate if calculated AFTER the /// `Psbt` is finalized and all witness/signature data is added to the @@ -49,18 +49,13 @@ impl PsbtUtils for Psbt { } } - fn fee_amount(&self) -> Option { + fn fee_amount(&self) -> Option { let tx = &self.unsigned_tx; let utxos: Option> = (0..tx.input.len()).map(|i| self.get_utxo_for(i)).collect(); utxos.map(|inputs| { - let input_amount: u64 = inputs.iter().map(|i| i.value.to_sat()).sum(); - let output_amount: u64 = self - .unsigned_tx - .output - .iter() - .map(|o| o.value.to_sat()) - .sum(); + let input_amount: Amount = inputs.iter().map(|i| i.value).sum(); + let output_amount: Amount = self.unsigned_tx.output.iter().map(|o| o.value).sum(); input_amount .checked_sub(output_amount) .expect("input amount must be greater than output amount") @@ -70,6 +65,6 @@ impl PsbtUtils for Psbt { fn fee_rate(&self) -> Option { let fee_amount = self.fee_amount(); let weight = self.clone().extract_tx().ok()?.weight(); - fee_amount.map(|fee| Amount::from_sat(fee) / weight) + fee_amount.map(|fee| fee / weight) } } diff --git a/crates/wallet/src/wallet/error.rs b/crates/wallet/src/wallet/error.rs index eaf811d6fc..56612c54e0 100644 --- a/crates/wallet/src/wallet/error.rs +++ b/crates/wallet/src/wallet/error.rs @@ -16,7 +16,7 @@ use crate::descriptor::DescriptorError; use crate::wallet::coin_selection; use crate::{descriptor, KeychainKind}; use alloc::string::String; -use bitcoin::{absolute, psbt, OutPoint, Sequence, Txid}; +use bitcoin::{absolute, psbt, Amount, OutPoint, Sequence, Txid}; use core::fmt; /// Errors returned by miniscript when updating inconsistent PSBTs @@ -78,8 +78,8 @@ pub enum CreateTxError { }, /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee FeeTooLow { - /// Required fee absolute value (satoshi) - required: u64, + /// Required fee absolute value [`Amount`] + required: Amount, }, /// When bumping a tx the fee rate requested is lower than required FeeRateTooLow { @@ -160,7 +160,7 @@ impl fmt::Display for CreateTxError { ) } CreateTxError::FeeTooLow { required } => { - write!(f, "Fee to low: required {} sat", required) + write!(f, "Fee to low: required {}", required.display_dynamic()) } CreateTxError::FeeRateTooLow { required } => { write!( diff --git a/crates/wallet/src/wallet/mod.rs b/crates/wallet/src/wallet/mod.rs index 61ec5893b2..6aa9583f25 100644 --- a/crates/wallet/src/wallet/mod.rs +++ b/crates/wallet/src/wallet/mod.rs @@ -1041,7 +1041,7 @@ impl Wallet { self.persist.stage(ChangeSet::from(additions)); } - /// Calculates the fee of a given transaction. Returns 0 if `tx` is a coinbase transaction. + /// Calculates the fee of a given transaction. Returns [`Amount::ZERO`] if `tx` is a coinbase transaction. /// /// To calculate the fee for a [`Transaction`] with inputs not owned by this wallet you must /// manually insert the TxOut(s) into the tx graph using the [`insert_txout`] function. @@ -1068,7 +1068,7 @@ impl Wallet { /// let fee = wallet.calculate_fee(tx).expect("fee"); /// ``` /// [`insert_txout`]: Self::insert_txout - pub fn calculate_fee(&self, tx: &Transaction) -> Result { + pub fn calculate_fee(&self, tx: &Transaction) -> Result { self.indexed_graph.graph().calculate_fee(tx) } @@ -1100,8 +1100,7 @@ impl Wallet { /// ``` /// [`insert_txout`]: Self::insert_txout pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result { - self.calculate_fee(tx) - .map(|fee| Amount::from_sat(fee) / tx.weight()) + self.calculate_fee(tx).map(|fee| fee / tx.weight()) } /// Compute the `tx`'s sent and received [`Amount`]s. @@ -1530,7 +1529,7 @@ impl Wallet { if let Some(previous_fee) = params.bumping_fee { if fee < previous_fee.absolute { return Err(CreateTxError::FeeTooLow { - required: previous_fee.absolute, + required: Amount::from_sat(previous_fee.absolute), }); } } @@ -1563,9 +1562,8 @@ impl Wallet { return Err(CreateTxError::NoUtxosSelected); } - // we keep it as a float while we accumulate it, and only round it at the end - let mut outgoing: u64 = 0; - let mut received: u64 = 0; + let mut outgoing = Amount::ZERO; + let mut received = Amount::ZERO; let recipients = params.recipients.iter().map(|(r, v)| (r, *v)); @@ -1578,7 +1576,7 @@ impl Wallet { } if self.is_mine(script_pubkey) { - received += value; + received += Amount::from_sat(value); } let new_out = TxOut { @@ -1588,7 +1586,7 @@ impl Wallet { tx.output.push(new_out); - outgoing += value; + outgoing += Amount::from_sat(value); } fee_amount += (fee_rate * tx.weight()).to_sat(); @@ -1630,7 +1628,7 @@ impl Wallet { required_utxos, optional_utxos, fee_rate, - outgoing + fee_amount, + outgoing.to_sat() + fee_amount, &drain_script, )?; fee_amount += coin_selection.fee_amount; @@ -1678,7 +1676,7 @@ impl Wallet { } => fee_amount += remaining_amount, Change { amount, fee } => { if self.is_mine(&drain_script) { - received += amount; + received += Amount::from_sat(*amount); } fee_amount += fee; @@ -1862,7 +1860,7 @@ impl Wallet { .collect(), utxos: original_utxos, bumping_fee: Some(tx_builder::PreviousFee { - absolute: fee, + absolute: fee.to_sat(), rate: fee_rate, }), ..Default::default() diff --git a/crates/wallet/src/wallet/tx_builder.rs b/crates/wallet/src/wallet/tx_builder.rs index 28b70a8bc3..6bcf7770c3 100644 --- a/crates/wallet/src/wallet/tx_builder.rs +++ b/crates/wallet/src/wallet/tx_builder.rs @@ -204,16 +204,16 @@ impl<'a, Cs, Ctx> TxBuilder<'a, Cs, Ctx> { } /// Set an absolute fee - /// The fee_absolute method refers to the absolute transaction fee in satoshis (sats). - /// If anyone sets both the fee_absolute method and the fee_rate method, - /// the FeePolicy enum will be set by whichever method was called last, - /// as the FeeRate and FeeAmount are mutually exclusive. + /// The fee_absolute method refers to the absolute transaction fee in [`Amount`]. + /// If anyone sets both the `fee_absolute` method and the `fee_rate` method, + /// the `FeePolicy` enum will be set by whichever method was called last, + /// as the [`FeeRate`] and `FeeAmount` are mutually exclusive. /// /// Note that this is really a minimum absolute fee -- it's possible to /// overshoot it slightly since adding a change output to drain the remaining /// excess might not be viable. - pub fn fee_absolute(&mut self, fee_amount: u64) -> &mut Self { - self.params.fee_policy = Some(FeePolicy::FeeAmount(fee_amount)); + pub fn fee_absolute(&mut self, fee_amount: Amount) -> &mut Self { + self.params.fee_policy = Some(FeePolicy::FeeAmount(fee_amount.to_sat())); self } diff --git a/crates/wallet/tests/wallet.rs b/crates/wallet/tests/wallet.rs index 58b25061d2..fade444e1e 100644 --- a/crates/wallet/tests/wallet.rs +++ b/crates/wallet/tests/wallet.rs @@ -290,7 +290,7 @@ fn test_get_funded_wallet_tx_fees() { // The funded wallet contains a tx with a 76_000 sats input and two outputs, one spending 25_000 // to a foreign address and one returning 50_000 back to the wallet as change. The remaining 1000 // sats are the transaction fee. - assert_eq!(tx_fee, 1000) + assert_eq!(tx_fee, Amount::from_sat(1000)) } #[test] @@ -355,16 +355,16 @@ macro_rules! assert_fee_rate { let fee_amount = psbt .inputs .iter() - .fold(0, |acc, i| acc + i.witness_utxo.as_ref().unwrap().value.to_sat()) + .fold(Amount::ZERO, |acc, i| acc + i.witness_utxo.as_ref().unwrap().value) - psbt .unsigned_tx .output .iter() - .fold(0, |acc, o| acc + o.value.to_sat()); + .fold(Amount::ZERO, |acc, o| acc + o.value); assert_eq!(fee_amount, $fees); - let tx_fee_rate = (Amount::from_sat(fee_amount) / tx.weight()) + let tx_fee_rate = (fee_amount / tx.weight()) .to_sat_per_kwu(); let fee_rate = $fee_rate.to_sat_per_kwu(); let half_default = FeeRate::BROADCAST_MIN.checked_div(2) @@ -646,8 +646,8 @@ fn test_create_tx_drain_wallet_and_drain_to() { assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!( - psbt.unsigned_tx.output[0].value.to_sat(), - 50_000 - fee.unwrap_or(0) + psbt.unsigned_tx.output[0].value, + Amount::from_sat(50_000) - fee.unwrap_or(Amount::ZERO) ); } @@ -676,8 +676,11 @@ fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() { .iter() .find(|x| x.script_pubkey == drain_addr.script_pubkey()) .unwrap(); - assert_eq!(main_output.value.to_sat(), 20_000,); - assert_eq!(drain_output.value.to_sat(), 30_000 - fee.unwrap_or(0)); + assert_eq!(main_output.value, Amount::from_sat(20_000)); + assert_eq!( + drain_output.value, + Amount::from_sat(30_000) - fee.unwrap_or(Amount::ZERO) + ); } #[test] @@ -695,8 +698,8 @@ fn test_create_tx_drain_to_and_utxos() { assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!( - psbt.unsigned_tx.output[0].value.to_sat(), - 50_000 - fee.unwrap_or(0) + psbt.unsigned_tx.output[0].value, + Amount::from_sat(50_000) - fee.unwrap_or(Amount::ZERO) ); } @@ -719,7 +722,7 @@ fn test_create_tx_default_fee_rate() { let psbt = builder.finish().unwrap(); let fee = check_fee!(wallet, psbt); - assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::BROADCAST_MIN, @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::BROADCAST_MIN, @add_signature); } #[test] @@ -733,7 +736,7 @@ fn test_create_tx_custom_fee_rate() { let psbt = builder.finish().unwrap(); let fee = check_fee!(wallet, psbt); - assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(5), @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::from_sat_per_vb_unchecked(5), @add_signature); } #[test] @@ -744,15 +747,15 @@ fn test_create_tx_absolute_fee() { builder .drain_to(addr.script_pubkey()) .drain_wallet() - .fee_absolute(100); + .fee_absolute(Amount::from_sat(100)); let psbt = builder.finish().unwrap(); let fee = check_fee!(wallet, psbt); - assert_eq!(fee.unwrap_or(0), 100); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(100)); assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!( - psbt.unsigned_tx.output[0].value.to_sat(), - 50_000 - fee.unwrap_or(0) + psbt.unsigned_tx.output[0].value, + Amount::from_sat(50_000) - fee.unwrap_or(Amount::ZERO) ); } @@ -764,15 +767,15 @@ fn test_create_tx_absolute_zero_fee() { builder .drain_to(addr.script_pubkey()) .drain_wallet() - .fee_absolute(0); + .fee_absolute(Amount::from_sat(0)); let psbt = builder.finish().unwrap(); let fee = check_fee!(wallet, psbt); - assert_eq!(fee.unwrap_or(0), 0); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::ZERO); assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!( - psbt.unsigned_tx.output[0].value.to_sat(), - 50_000 - fee.unwrap_or(0) + psbt.unsigned_tx.output[0].value, + Amount::from_sat(50_000) - fee.unwrap_or(Amount::ZERO) ); } @@ -785,7 +788,7 @@ fn test_create_tx_absolute_high_fee() { builder .drain_to(addr.script_pubkey()) .drain_wallet() - .fee_absolute(60_000); + .fee_absolute(Amount::from_sat(60_000)); let _ = builder.finish().unwrap(); } @@ -803,10 +806,10 @@ fn test_create_tx_add_change() { let fee = check_fee!(wallet, psbt); assert_eq!(psbt.unsigned_tx.output.len(), 2); - assert_eq!(psbt.unsigned_tx.output[0].value.to_sat(), 25_000); + assert_eq!(psbt.unsigned_tx.output[0].value, Amount::from_sat(25_000)); assert_eq!( - psbt.unsigned_tx.output[1].value.to_sat(), - 25_000 - fee.unwrap_or(0) + psbt.unsigned_tx.output[1].value, + Amount::from_sat(25_000) - fee.unwrap_or(Amount::ZERO) ); } @@ -821,7 +824,7 @@ fn test_create_tx_skip_change_dust() { assert_eq!(psbt.unsigned_tx.output.len(), 1); assert_eq!(psbt.unsigned_tx.output[0].value.to_sat(), 49_800); - assert_eq!(fee.unwrap_or(0), 200); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(200)); } #[test] @@ -852,11 +855,11 @@ fn test_create_tx_ordering_respected() { assert_eq!(psbt.unsigned_tx.output.len(), 3); assert_eq!( - psbt.unsigned_tx.output[0].value.to_sat(), - 10_000 - fee.unwrap_or(0) + psbt.unsigned_tx.output[0].value, + Amount::from_sat(10_000) - fee.unwrap_or(Amount::ZERO) ); - assert_eq!(psbt.unsigned_tx.output[1].value.to_sat(), 10_000); - assert_eq!(psbt.unsigned_tx.output[2].value.to_sat(), 30_000); + assert_eq!(psbt.unsigned_tx.output[1].value, Amount::from_sat(10_000)); + assert_eq!(psbt.unsigned_tx.output[2].value, Amount::from_sat(30_000)); } #[test] @@ -1283,8 +1286,8 @@ fn test_add_foreign_utxo() { wallet1.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); assert_eq!( - (sent_received.0 - sent_received.1).to_sat(), - 10_000 + fee.unwrap_or(0), + (sent_received.0 - sent_received.1), + Amount::from_sat(10_000) + fee.unwrap_or(Amount::ZERO), "we should have only net spent ~10_000" ); @@ -1623,7 +1626,7 @@ fn test_bump_fee_low_abs() { .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); - builder.fee_absolute(10); + builder.fee_absolute(Amount::from_sat(10)); builder.finish().unwrap(); } @@ -1645,7 +1648,7 @@ fn test_bump_fee_zero_abs() { .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); - builder.fee_absolute(0); + builder.fee_absolute(Amount::from_sat(0)); builder.finish().unwrap(); } @@ -1680,10 +1683,10 @@ fn test_bump_fee_reduce_change() { assert_eq!(sent_received.0, original_sent_received.0); assert_eq!( - sent_received.1 + Amount::from_sat(fee.unwrap_or(0)), - original_sent_received.1 + Amount::from_sat(original_fee.unwrap_or(0)) + sent_received.1 + fee.unwrap_or(Amount::ZERO), + original_sent_received.1 + original_fee.unwrap_or(Amount::ZERO) ); - assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0)); + assert!(fee.unwrap_or(Amount::ZERO) > original_fee.unwrap_or(Amount::ZERO)); let tx = &psbt.unsigned_tx; assert_eq!(tx.output.len(), 2); @@ -1704,10 +1707,10 @@ fn test_bump_fee_reduce_change() { sent_received.1 ); - assert_fee_rate!(psbt, fee.unwrap_or(0), feerate, @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), feerate, @add_signature); let mut builder = wallet.build_fee_bump(txid).unwrap(); - builder.fee_absolute(200); + builder.fee_absolute(Amount::from_sat(200)); builder.enable_rbf(); let psbt = builder.finish().unwrap(); let sent_received = @@ -1716,14 +1719,14 @@ fn test_bump_fee_reduce_change() { assert_eq!(sent_received.0, original_sent_received.0); assert_eq!( - sent_received.1 + Amount::from_sat(fee.unwrap_or(0)), - original_sent_received.1 + Amount::from_sat(original_fee.unwrap_or(0)) + sent_received.1 + fee.unwrap_or(Amount::ZERO), + original_sent_received.1 + original_fee.unwrap_or(Amount::ZERO) ); assert!( - fee.unwrap_or(0) > original_fee.unwrap_or(0), + fee.unwrap_or(Amount::ZERO) > original_fee.unwrap_or(Amount::ZERO), "{} > {}", - fee.unwrap_or(0), - original_fee.unwrap_or(0) + fee.unwrap_or(Amount::ZERO), + original_fee.unwrap_or(Amount::ZERO) ); let tx = &psbt.unsigned_tx; @@ -1745,7 +1748,7 @@ fn test_bump_fee_reduce_change() { sent_received.1 ); - assert_eq!(fee.unwrap_or(0), 200); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(200)); } #[test] @@ -1780,16 +1783,16 @@ fn test_bump_fee_reduce_single_recipient() { let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0); - assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0)); + assert!(fee.unwrap_or(Amount::ZERO) > original_fee.unwrap_or(Amount::ZERO)); let tx = &psbt.unsigned_tx; assert_eq!(tx.output.len(), 1); assert_eq!( - tx.output[0].value + Amount::from_sat(fee.unwrap_or(0)), + tx.output[0].value + fee.unwrap_or(Amount::ZERO), sent_received.0 ); - assert_fee_rate!(psbt, fee.unwrap_or(0), feerate, @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), feerate, @add_signature); } #[test] @@ -1816,22 +1819,22 @@ fn test_bump_fee_absolute_reduce_single_recipient() { builder .allow_shrinking(addr.script_pubkey()) .unwrap() - .fee_absolute(300); + .fee_absolute(Amount::from_sat(300)); let psbt = builder.finish().unwrap(); let tx = &psbt.unsigned_tx; let sent_received = wallet.sent_and_received(tx); let fee = check_fee!(wallet, psbt); assert_eq!(sent_received.0, original_sent_received.0); - assert!(fee.unwrap_or(0) > original_fee.unwrap_or(0)); + assert!(fee.unwrap_or(Amount::ZERO) > original_fee.unwrap_or(Amount::ZERO)); assert_eq!(tx.output.len(), 1); assert_eq!( - tx.output[0].value + Amount::from_sat(fee.unwrap_or(0)), + tx.output[0].value + fee.unwrap_or(Amount::ZERO), sent_received.0 ); - assert_eq!(fee.unwrap_or(0), 300); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(300)); } #[test] @@ -2010,7 +2013,7 @@ fn test_bump_fee_add_input() { original_details.0 + Amount::from_sat(25_000) ); assert_eq!( - Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, + fee.unwrap_or(Amount::ZERO) + sent_received.1, Amount::from_sat(30_000) ); @@ -2034,7 +2037,7 @@ fn test_bump_fee_add_input() { sent_received.1 ); - assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(50), @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::from_sat_per_vb_unchecked(50), @add_signature); } #[test] @@ -2057,7 +2060,7 @@ fn test_bump_fee_absolute_add_input() { .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); - builder.fee_absolute(6_000); + builder.fee_absolute(Amount::from_sat(6_000)); let psbt = builder.finish().unwrap(); let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); @@ -2068,7 +2071,7 @@ fn test_bump_fee_absolute_add_input() { original_sent_received.0 + Amount::from_sat(25_000) ); assert_eq!( - Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, + fee.unwrap_or(Amount::ZERO) + sent_received.1, Amount::from_sat(30_000) ); @@ -2092,7 +2095,7 @@ fn test_bump_fee_absolute_add_input() { sent_received.1 ); - assert_eq!(fee.unwrap_or(0), 6_000); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(6_000)); } #[test] @@ -2131,15 +2134,14 @@ fn test_bump_fee_no_change_add_input_and_change() { wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); let fee = check_fee!(wallet, psbt); - let original_send_all_amount = - original_sent_received.0 - Amount::from_sat(original_fee.unwrap_or(0)); + let original_send_all_amount = original_sent_received.0 - original_fee.unwrap_or(Amount::ZERO); assert_eq!( sent_received.0, original_sent_received.0 + Amount::from_sat(50_000) ); assert_eq!( sent_received.1, - Amount::from_sat(75_000) - original_send_all_amount - Amount::from_sat(fee.unwrap_or(0)) + Amount::from_sat(75_000) - original_send_all_amount - fee.unwrap_or(Amount::ZERO) ); let tx = &psbt.unsigned_tx; @@ -2159,10 +2161,10 @@ fn test_bump_fee_no_change_add_input_and_change() { .find(|txout| txout.script_pubkey != addr.script_pubkey()) .unwrap() .value, - Amount::from_sat(75_000) - original_send_all_amount - Amount::from_sat(fee.unwrap_or(0)) + Amount::from_sat(75_000) - original_send_all_amount - fee.unwrap_or(Amount::ZERO) ); - assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(50), @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::from_sat_per_vb_unchecked(50), @add_signature); } #[test] @@ -2216,14 +2218,14 @@ fn test_bump_fee_add_input_change_dust() { assert_eq!( original_sent_received.1, - Amount::from_sat(5_000 - original_fee.unwrap_or(0)) + Amount::from_sat(5_000) - original_fee.unwrap_or(Amount::ZERO) ); assert_eq!( sent_received.0, original_sent_received.0 + Amount::from_sat(25_000) ); - assert_eq!(fee.unwrap_or(0), 30_000); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(30_000)); assert_eq!(sent_received.1, Amount::ZERO); let tx = &psbt.unsigned_tx; @@ -2238,7 +2240,7 @@ fn test_bump_fee_add_input_change_dust() { Amount::from_sat(45_000) ); - assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(140), @dust_change, @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::from_sat_per_vb_unchecked(140), @dust_change, @add_signature); } #[test] @@ -2280,7 +2282,7 @@ fn test_bump_fee_force_add_input() { original_sent_received.0 + Amount::from_sat(25_000) ); assert_eq!( - Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, + fee.unwrap_or(Amount::ZERO) + sent_received.1, Amount::from_sat(30_000) ); @@ -2304,7 +2306,7 @@ fn test_bump_fee_force_add_input() { sent_received.1 ); - assert_fee_rate!(psbt, fee.unwrap_or(0), FeeRate::from_sat_per_vb_unchecked(5), @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::from_sat_per_vb_unchecked(5), @add_signature); } #[test] @@ -2334,7 +2336,10 @@ fn test_bump_fee_absolute_force_add_input() { // the new fee_rate is low enough that just reducing the change would be fine, but we force // the addition of an extra input with `add_utxo()` let mut builder = wallet.build_fee_bump(txid).unwrap(); - builder.add_utxo(incoming_op).unwrap().fee_absolute(250); + builder + .add_utxo(incoming_op) + .unwrap() + .fee_absolute(Amount::from_sat(250)); let psbt = builder.finish().unwrap(); let sent_received = wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx")); @@ -2345,7 +2350,7 @@ fn test_bump_fee_absolute_force_add_input() { original_sent_received.0 + Amount::from_sat(25_000) ); assert_eq!( - Amount::from_sat(fee.unwrap_or(0)) + sent_received.1, + fee.unwrap_or(Amount::ZERO) + sent_received.1, Amount::from_sat(30_000) ); @@ -2369,7 +2374,7 @@ fn test_bump_fee_absolute_force_add_input() { sent_received.1 ); - assert_eq!(fee.unwrap_or(0), 250); + assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(250)); } #[test] @@ -2476,7 +2481,7 @@ fn test_fee_amount_negative_drain_val() { let fee = check_fee!(wallet, psbt); assert_eq!(psbt.inputs.len(), 1); - assert_fee_rate!(psbt, fee.unwrap_or(0), fee_rate, @add_signature); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), fee_rate, @add_signature); } #[test] @@ -3313,7 +3318,7 @@ fn test_taproot_foreign_utxo() { assert_eq!( sent_received.0 - sent_received.1, - Amount::from_sat(10_000 + fee.unwrap_or(0)), + Amount::from_sat(10_000) + fee.unwrap_or(Amount::ZERO), "we should have only net spent ~10_000" ); @@ -3817,7 +3822,7 @@ fn test_fee_rate_sign_no_grinding_high_r() { ) .unwrap(); // ...and checking that everything is fine - assert_fee_rate!(psbt, fee.unwrap_or(0), fee_rate); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), fee_rate); } #[test] @@ -3851,7 +3856,7 @@ fn test_fee_rate_sign_grinding_low_r() { let key = psbt.inputs[0].partial_sigs.keys().next().unwrap(); let sig_len = psbt.inputs[0].partial_sigs[key].sig.serialize_der().len(); assert_eq!(sig_len, 70); - assert_fee_rate!(psbt, fee.unwrap_or(0), fee_rate); + assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), fee_rate); } #[test]