From 82632897aaa4ea0ac24803f58fbd13d6dc9c4357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Wed, 1 Nov 2023 12:33:57 +0800 Subject: [PATCH 1/4] refactor(bdk)!: rename `LocalUtxo` to `LocalOutput` --- crates/bdk/src/types.rs | 4 ++-- crates/bdk/src/wallet/coin_selection.rs | 6 +++--- crates/bdk/src/wallet/mod.rs | 14 +++++++------- crates/bdk/src/wallet/tx_builder.rs | 10 +++++----- crates/bdk/tests/common.rs | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/bdk/src/types.rs b/crates/bdk/src/types.rs index 2a88cc374..b52635e55 100644 --- a/crates/bdk/src/types.rs +++ b/crates/bdk/src/types.rs @@ -161,7 +161,7 @@ impl Vbytes for usize { /// /// [`Wallet`]: crate::Wallet #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] -pub struct LocalUtxo { +pub struct LocalOutput { /// Reference to a transaction output pub outpoint: OutPoint, /// Transaction output @@ -192,7 +192,7 @@ pub struct WeightedUtxo { /// An unspent transaction output (UTXO). pub enum Utxo { /// A UTXO owned by the local wallet. - Local(LocalUtxo), + Local(LocalOutput), /// A UTXO owned by another wallet. Foreign { /// The location of the output. diff --git a/crates/bdk/src/wallet/coin_selection.rs b/crates/bdk/src/wallet/coin_selection.rs index a29456fa8..bc4c719a7 100644 --- a/crates/bdk/src/wallet/coin_selection.rs +++ b/crates/bdk/src/wallet/coin_selection.rs @@ -755,7 +755,7 @@ mod test { .unwrap(); WeightedUtxo { satisfaction_weight: P2WPKH_SATISFACTION_SIZE, - utxo: Utxo::Local(LocalUtxo { + utxo: Utxo::Local(LocalOutput { outpoint, txout: TxOut { value, @@ -815,7 +815,7 @@ mod test { for _ in 0..utxos_number { res.push(WeightedUtxo { satisfaction_weight: P2WPKH_SATISFACTION_SIZE, - utxo: Utxo::Local(LocalUtxo { + utxo: Utxo::Local(LocalOutput { outpoint: OutPoint::from_str( "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0", ) @@ -844,7 +844,7 @@ mod test { fn generate_same_value_utxos(utxos_value: u64, utxos_number: usize) -> Vec { let utxo = WeightedUtxo { satisfaction_weight: P2WPKH_SATISFACTION_SIZE, - utxo: Utxo::Local(LocalUtxo { + utxo: Utxo::Local(LocalOutput { outpoint: OutPoint::from_str( "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0", ) diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 240cc1050..f479330fe 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -737,7 +737,7 @@ impl Wallet { } /// Return the list of unspent outputs of this wallet - pub fn list_unspent(&self) -> impl Iterator + '_ { + pub fn list_unspent(&self) -> impl Iterator + '_ { self.indexed_graph .graph() .filter_chain_unspents( @@ -786,7 +786,7 @@ impl Wallet { /// Returns the utxo owned by this wallet corresponding to `outpoint` if it exists in the /// wallet's database. - pub fn get_utxo(&self, op: OutPoint) -> Option { + pub fn get_utxo(&self, op: OutPoint) -> Option { let (&spk_i, _) = self.indexed_graph.index.txout(op)?; self.indexed_graph .graph() @@ -1617,7 +1617,7 @@ impl Wallet { .max_satisfaction_weight() .unwrap(); WeightedUtxo { - utxo: Utxo::Local(LocalUtxo { + utxo: Utxo::Local(LocalOutput { outpoint: txin.previous_output, txout: txout.clone(), keychain, @@ -1944,7 +1944,7 @@ impl Wallet { descriptor.at_derivation_index(child).ok() } - fn get_available_utxos(&self) -> Vec<(LocalUtxo, usize)> { + fn get_available_utxos(&self) -> Vec<(LocalOutput, usize)> { self.list_unspent() .map(|utxo| { let keychain = utxo.keychain; @@ -2141,7 +2141,7 @@ impl Wallet { /// get the corresponding PSBT Input for a LocalUtxo pub fn get_psbt_input( &self, - utxo: LocalUtxo, + utxo: LocalOutput, sighash_type: Option, only_witness_utxo: bool, ) -> Result> @@ -2352,8 +2352,8 @@ fn new_local_utxo( keychain: KeychainKind, derivation_index: u32, full_txo: FullTxOut, -) -> LocalUtxo { - LocalUtxo { +) -> LocalOutput { + LocalOutput { outpoint: full_txo.outpoint, txout: full_txo.txout, is_spent: full_txo.spent_by.is_some(), diff --git a/crates/bdk/src/wallet/tx_builder.rs b/crates/bdk/src/wallet/tx_builder.rs index e99d2fe25..e3474209c 100644 --- a/crates/bdk/src/wallet/tx_builder.rs +++ b/crates/bdk/src/wallet/tx_builder.rs @@ -53,7 +53,7 @@ use bitcoin::{absolute, script::PushBytes, OutPoint, ScriptBuf, Sequence, Transa use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm}; use super::ChangeSet; -use crate::types::{FeeRate, KeychainKind, LocalUtxo, WeightedUtxo}; +use crate::types::{FeeRate, KeychainKind, LocalOutput, WeightedUtxo}; use crate::wallet::CreateTxError; use crate::{Utxo, Wallet}; @@ -889,7 +889,7 @@ impl Default for ChangeSpendPolicy { } impl ChangeSpendPolicy { - pub(crate) fn is_satisfied_by(&self, utxo: &LocalUtxo) -> bool { + pub(crate) fn is_satisfied_by(&self, utxo: &LocalOutput) -> bool { match self { ChangeSpendPolicy::ChangeAllowed => true, ChangeSpendPolicy::OnlyChange => utxo.keychain == KeychainKind::Internal, @@ -994,11 +994,11 @@ mod test { ); } - fn get_test_utxos() -> Vec { + fn get_test_utxos() -> Vec { use bitcoin::hashes::Hash; vec![ - LocalUtxo { + LocalOutput { outpoint: OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), vout: 0, @@ -1009,7 +1009,7 @@ mod test { confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 }, derivation_index: 0, }, - LocalUtxo { + LocalOutput { outpoint: OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), vout: 1, diff --git a/crates/bdk/tests/common.rs b/crates/bdk/tests/common.rs index ee8ed74e1..3e0292a29 100644 --- a/crates/bdk/tests/common.rs +++ b/crates/bdk/tests/common.rs @@ -1,6 +1,6 @@ #![allow(unused)] -use bdk::{wallet::AddressIndex, KeychainKind, LocalUtxo, Wallet}; +use bdk::{wallet::AddressIndex, KeychainKind, LocalOutput, Wallet}; use bdk_chain::indexed_tx_graph::Indexer; use bdk_chain::{BlockId, ConfirmationTime}; use bitcoin::hashes::Hash; From e803ee901002cae4db5ebf3544eb42c6cf81e5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Wed, 1 Nov 2023 13:25:28 +0800 Subject: [PATCH 2/4] feat(bdk): add `Wallet::list_output` method --- crates/bdk/src/wallet/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index f479330fe..a1d834672 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -748,6 +748,20 @@ impl Wallet { .map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo)) } + /// List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed). + /// + /// To list only unspent outputs (UTXOs), use [`Wallet::list_unspent`] instead. + pub fn list_output(&self) -> impl Iterator + '_ { + self.indexed_graph + .graph() + .filter_chain_txouts( + &self.chain, + self.chain.tip().block_id(), + self.indexed_graph.index.outpoints().iter().cloned(), + ) + .map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo)) + } + /// Get all the checkpoints the wallet is currently storing indexed by height. pub fn checkpoints(&self) -> CheckPointIter { self.chain.iter_checkpoints() From 6fb45d8a735ec8db9142489d86107de192e0fa9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Thu, 2 Nov 2023 04:24:25 +0800 Subject: [PATCH 3/4] test(bdk): add `test_list_output` --- crates/bdk/tests/wallet.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/crates/bdk/tests/wallet.rs b/crates/bdk/tests/wallet.rs index 77ec1c8b1..4fa399d86 100644 --- a/crates/bdk/tests/wallet.rs +++ b/crates/bdk/tests/wallet.rs @@ -237,6 +237,25 @@ fn test_get_funded_wallet_tx_fee_rate() { assert_eq!(tx_fee_rate.as_sat_per_vb(), 8.849558); } +#[test] +fn test_list_output() { + let (wallet, txid) = get_funded_wallet(get_test_wpkh()); + let txos = wallet + .list_output() + .map(|op| (op.outpoint, op)) + .collect::>(); + assert_eq!(txos.len(), 2); + for (op, txo) in txos { + if op.txid == txid { + assert_eq!(txo.txout.value, 50_000); + assert!(!txo.is_spent); + } else { + assert_eq!(txo.txout.value, 76_000); + assert!(txo.is_spent); + } + } +} + macro_rules! assert_fee_rate { ($psbt:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({ let psbt = $psbt.clone(); From 278210bb8918923005e80968df3dfcc3372c0a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Tue, 21 Nov 2023 05:06:53 +0800 Subject: [PATCH 4/4] docs(bdk): clarify `insert_txout` docs Inserted txouts will not be shown in `list_unspent` or `list_output`. --- crates/bdk/src/wallet/mod.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index a1d834672..442fe62e2 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -814,15 +814,20 @@ impl Wallet { } /// Inserts a [`TxOut`] at [`OutPoint`] into the wallet's transaction graph. - /// Any inserted TxOuts are not persisted until [`commit`] is called. /// - /// This can be used to add a `TxOut` that the wallet doesn't own but is used as an input to - /// a [`Transaction`] passed to the [`calculate_fee`] or [`calculate_fee_rate`] functions. + /// This is used for providing a previous output's value so that we can use [`calculate_fee`] + /// or [`calculate_fee_rate`] on a given transaction. Outputs inserted with this method will + /// not be returned in [`list_unspent`] or [`list_output`]. /// - /// Only insert TxOuts you trust the values for! + /// Any inserted `TxOut`s are not persisted until [`commit`] is called. + /// + /// **WARNING:** This should only be used to add `TxOut`s that the wallet does not own. Only + /// insert `TxOut`s that you trust the values for! /// /// [`calculate_fee`]: Self::calculate_fee /// [`calculate_fee_rate`]: Self::calculate_fee_rate + /// [`list_unspent`]: Self::list_unspent + /// [`list_output`]: Self::list_output /// [`commit`]: Self::commit pub fn insert_txout(&mut self, outpoint: OutPoint, txout: TxOut) where