Skip to content

Commit

Permalink
feat: update wallet::Balance to use bitcoin::Amount
Browse files Browse the repository at this point in the history
- update all fields `immature`, ` trusted_pending`, `unstrusted_pending`
  and `confirmed` to use the `bitcoin::Amount` instead of `u64`
- update all `impl Balance` methods to use `bitcoin::Amount`
- update all tests that relies on `keychain::Balance`
  • Loading branch information
oleonardolima committed May 5, 2024
1 parent 08fac47 commit 8a33d98
Show file tree
Hide file tree
Showing 15 changed files with 127 additions and 120 deletions.
6 changes: 3 additions & 3 deletions crates/bdk/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ use bdk_chain::{
IndexedTxGraph,
};
use bdk_persist::{Persist, PersistBackend};
use bitcoin::constants::genesis_block;
use bitcoin::secp256k1::{All, Secp256k1};
use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
use bitcoin::{
absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence,
Transaction, TxOut, Txid, Witness,
};
use bitcoin::{consensus::encode::serialize, transaction, Amount, BlockHash, Psbt};
use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
use bitcoin::{constants::genesis_block, Amount};
use core::fmt;
use core::ops::Deref;
use descriptor::error::Error as DescriptorError;
Expand Down Expand Up @@ -950,7 +950,7 @@ impl Wallet {
/// [`insert_txout`]: Self::insert_txout
pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> {
self.calculate_fee(tx)
.map(|fee| bitcoin::Amount::from_sat(fee) / tx.weight())
.map(|fee| Amount::from_sat(fee) / tx.weight())
}

/// Compute the `tx`'s sent and received amounts (in satoshis).
Expand Down
1 change: 1 addition & 0 deletions crates/bdk/src/wallet/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,7 @@ impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs, CreateTx> {
self
}

// TODO: (@leonardo) Should this expect/use `bitcoin::Amount` instead ? Would it be a huge breaking change ?
/// Add a recipient to the internal list
pub fn add_recipient(&mut self, script_pubkey: ScriptBuf, amount: u64) -> &mut Self {
self.params.recipients.push((script_pubkey, amount));
Expand Down
4 changes: 2 additions & 2 deletions crates/bdk/tests/psbt.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bdk::bitcoin::{Amount, FeeRate, Psbt, TxIn};
use bdk::bitcoin::{FeeRate, Psbt, TxIn};
use bdk::{psbt, KeychainKind, SignOptions};
use core::str::FromStr;
mod common;
Expand Down Expand Up @@ -201,7 +201,7 @@ fn test_psbt_multiple_internalkey_signers() {
// the prevout we're spending
let prevouts = &[TxOut {
script_pubkey: send_to.script_pubkey(),
value: Amount::from_sat(to_spend),
value: to_spend,
}];
let prevouts = Prevouts::All(prevouts);
let input_index = 0;
Expand Down
24 changes: 12 additions & 12 deletions crates/bdk/tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ fn test_get_funded_wallet_balance() {
// 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!(wallet.get_balance().confirmed, 50_000);
assert_eq!(wallet.get_balance().confirmed.to_sat(), 50_000);
}

#[test]
Expand Down Expand Up @@ -3582,10 +3582,10 @@ fn test_spend_coinbase() {
assert_eq!(
balance,
Balance {
immature: 25_000,
trusted_pending: 0,
untrusted_pending: 0,
confirmed: 0
immature: Amount::from_sat(25_000),
trusted_pending: Amount::ZERO,
untrusted_pending: Amount::ZERO,
confirmed: Amount::ZERO
}
);

Expand All @@ -3596,7 +3596,7 @@ fn test_spend_coinbase() {
.assume_checked();
let mut builder = wallet.build_tx();
builder
.add_recipient(addr.script_pubkey(), balance.immature / 2)
.add_recipient(addr.script_pubkey(), balance.immature.to_sat() / 2)
.current_height(confirmation_height);
assert!(matches!(
builder.finish(),
Expand All @@ -3611,7 +3611,7 @@ fn test_spend_coinbase() {
// Still unspendable...
let mut builder = wallet.build_tx();
builder
.add_recipient(addr.script_pubkey(), balance.immature / 2)
.add_recipient(addr.script_pubkey(), balance.immature.to_sat() / 2)
.current_height(not_yet_mature_time);
assert_matches!(
builder.finish(),
Expand All @@ -3633,15 +3633,15 @@ fn test_spend_coinbase() {
assert_eq!(
balance,
Balance {
immature: 0,
trusted_pending: 0,
untrusted_pending: 0,
confirmed: 25_000
immature: Amount::ZERO,
trusted_pending: Amount::ZERO,
untrusted_pending: Amount::ZERO,
confirmed: Amount::from_sat(25_000)
}
);
let mut builder = wallet.build_tx();
builder
.add_recipient(addr.script_pubkey(), balance.confirmed / 2)
.add_recipient(addr.script_pubkey(), balance.confirmed.to_sat() / 2)
.current_height(maturity_time);
builder.finish().unwrap();
}
Expand Down
6 changes: 3 additions & 3 deletions crates/bitcoind_rpc/tests/test_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
assert_eq!(
get_balance(&recv_chain, &recv_graph)?,
Balance {
confirmed: SEND_AMOUNT.to_sat() * ADDITIONAL_COUNT as u64,
confirmed: SEND_AMOUNT * ADDITIONAL_COUNT as u64,
..Balance::default()
},
"initial balance must be correct",
Expand All @@ -391,8 +391,8 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
assert_eq!(
get_balance(&recv_chain, &recv_graph)?,
Balance {
confirmed: SEND_AMOUNT.to_sat() * (ADDITIONAL_COUNT - reorg_count) as u64,
trusted_pending: SEND_AMOUNT.to_sat() * reorg_count as u64,
confirmed: SEND_AMOUNT * (ADDITIONAL_COUNT - reorg_count) as u64,
trusted_pending: SEND_AMOUNT * reorg_count as u64,
..Balance::default()
},
"reorg_count: {}",
Expand Down
13 changes: 7 additions & 6 deletions crates/chain/src/keychain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{collections::BTreeMap, Append};

#[cfg(feature = "miniscript")]
mod txout_index;
use bitcoin::Amount;
#[cfg(feature = "miniscript")]
pub use txout_index::*;

Expand Down Expand Up @@ -90,26 +91,26 @@ impl<K> AsRef<BTreeMap<K, u32>> for ChangeSet<K> {
)]
pub struct Balance {
/// All coinbase outputs not yet matured
pub immature: u64,
pub immature: Amount,
/// Unconfirmed UTXOs generated by a wallet tx
pub trusted_pending: u64,
pub trusted_pending: Amount,
/// Unconfirmed UTXOs received from an external wallet
pub untrusted_pending: u64,
pub untrusted_pending: Amount,
/// Confirmed and immediately spendable balance
pub confirmed: u64,
pub confirmed: Amount,
}

impl Balance {
/// Get sum of trusted_pending and confirmed coins.
///
/// This is the balance you can spend right now that shouldn't get cancelled via another party
/// double spending it.
pub fn trusted_spendable(&self) -> u64 {
pub fn trusted_spendable(&self) -> Amount {
self.confirmed + self.trusted_pending
}

/// Get the whole balance visible to the wallet.
pub fn total(&self) -> u64 {
pub fn total(&self) -> Amount {
self.confirmed + self.trusted_pending + self.untrusted_pending + self.immature
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/chain/src/spk_txout_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ impl<I: Clone + Ord> SpkTxOutIndex<I> {
self.spk_indices.get(script)
}

// TODO: (@leonardo) Should this also be updated to return `(bitcoin::Amount, bitcoin::Amount)` instead of (u64, u64)
/// Computes the total value transfer effect `tx` has on the script pubkeys in `range`. Value is
/// *sent* when a script pubkey in the `range` is on an input and *received* when it is on an
/// output. For `sent` to be computed correctly, the output being spent must have already been
Expand Down
19 changes: 10 additions & 9 deletions crates/chain/src/tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ use crate::{
use alloc::collections::vec_deque::VecDeque;
use alloc::sync::Arc;
use alloc::vec::Vec;
use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid};
use bitcoin::{Amount, OutPoint, Script, Transaction, TxOut, Txid};
use core::fmt::{self, Formatter};
use core::{
convert::Infallible,
Expand Down Expand Up @@ -1155,27 +1155,28 @@ impl<A: Anchor> TxGraph<A> {
outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
mut trust_predicate: impl FnMut(&OI, &Script) -> bool,
) -> Result<Balance, C::Error> {
let mut immature = 0;
let mut trusted_pending = 0;
let mut untrusted_pending = 0;
let mut confirmed = 0;
let mut immature = Amount::ZERO;
let mut trusted_pending = Amount::ZERO;
let mut untrusted_pending = Amount::ZERO;
let mut confirmed = Amount::ZERO;

for res in self.try_filter_chain_unspents(chain, chain_tip, outpoints) {
let (spk_i, txout) = res?;

// TODO: (@leonardo) Should these operations use `bitcoin::Amount::checked_add()` instead ?
match &txout.chain_position {
ChainPosition::Confirmed(_) => {
if txout.is_confirmed_and_spendable(chain_tip.height) {
confirmed += txout.txout.value.to_sat();
confirmed += txout.txout.value;
} else if !txout.is_mature(chain_tip.height) {
immature += txout.txout.value.to_sat();
immature += txout.txout.value;
}
}
ChainPosition::Unconfirmed(_) => {
if trust_predicate(&spk_i, &txout.txout.script_pubkey) {
trusted_pending += txout.txout.value.to_sat();
trusted_pending += txout.txout.value;
} else {
untrusted_pending += txout.txout.value.to_sat();
untrusted_pending += txout.txout.value;
}
}
}
Expand Down
40 changes: 20 additions & 20 deletions crates/chain/tests/test_indexed_tx_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,10 +341,10 @@ fn test_list_owned_txouts() {
assert_eq!(
balance,
Balance {
immature: 70000, // immature coinbase
trusted_pending: 25000, // tx3 + tx5
untrusted_pending: 20000, // tx4
confirmed: 0 // Nothing is confirmed yet
immature: Amount::from_sat(70000), // immature coinbase
trusted_pending: Amount::from_sat(25000), // tx3 + tx5
untrusted_pending: Amount::from_sat(20000), // tx4
confirmed: Amount::ZERO // Nothing is confirmed yet
}
);
}
Expand Down Expand Up @@ -376,10 +376,10 @@ fn test_list_owned_txouts() {
assert_eq!(
balance,
Balance {
immature: 70000, // immature coinbase
trusted_pending: 25000, // tx3 + tx5
untrusted_pending: 20000, // tx4
confirmed: 0 // Nothing is confirmed yet
immature: Amount::from_sat(70000), // immature coinbase
trusted_pending: Amount::from_sat(25000), // tx3 + tx5
untrusted_pending: Amount::from_sat(20000), // tx4
confirmed: Amount::ZERO // Nothing is confirmed yet
}
);
}
Expand Down Expand Up @@ -408,10 +408,10 @@ fn test_list_owned_txouts() {
assert_eq!(
balance,
Balance {
immature: 70000, // immature coinbase
trusted_pending: 15000, // tx5
untrusted_pending: 20000, // tx4
confirmed: 10000 // tx3 got confirmed
immature: Amount::from_sat(70000), // immature coinbase
trusted_pending: Amount::from_sat(15000), // tx5
untrusted_pending: Amount::from_sat(20000), // tx4
confirmed: Amount::from_sat(10000) // tx3 got confirmed
}
);
}
Expand Down Expand Up @@ -439,10 +439,10 @@ fn test_list_owned_txouts() {
assert_eq!(
balance,
Balance {
immature: 70000, // immature coinbase
trusted_pending: 15000, // tx5
untrusted_pending: 20000, // tx4
confirmed: 10000 // tx1 got matured
immature: Amount::from_sat(70000), // immature coinbase
trusted_pending: Amount::from_sat(15000), // tx5
untrusted_pending: Amount::from_sat(20000), // tx4
confirmed: Amount::from_sat(10000) // tx1 got matured
}
);
}
Expand All @@ -455,10 +455,10 @@ fn test_list_owned_txouts() {
assert_eq!(
balance,
Balance {
immature: 0, // coinbase matured
trusted_pending: 15000, // tx5
untrusted_pending: 20000, // tx4
confirmed: 80000 // tx1 + tx3
immature: Amount::ZERO, // coinbase matured
trusted_pending: Amount::from_sat(15000), // tx5
untrusted_pending: Amount::from_sat(20000), // tx4
confirmed: Amount::from_sat(80000) // tx1 + tx3
}
);
}
Expand Down
Loading

0 comments on commit 8a33d98

Please sign in to comment.