Skip to content

Commit f6c1c61

Browse files
committed
Merge #1737: fix(tx_builder)!: make TxBuilder Send safe, remove Clone trait
663fb13 fix(tx_builder)!: make TxBuilder Send safe, remove Clone trait (Steve Myers) Pull request description: ### Description Inspired by discord chat with @stevenroose as a way to make the `TxBuilder` Send safe. See his original patch on 1.0.0-beta.5: https://gist.github.com/stevenroose/f7736dfedfaa64bbdbb0da5875df28fc ### Notes to the reviewers I had to remove the `Clone` trait on `TxBuilder` but it was only being used in tests. ### Changelog notice - TxBuilder is now Send safe and does not implement the Clone trait ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] I've added tests for the new feature * [ ] I've added docs for the new feature ACKs for top commit: evanlinjin: ACK 663fb13 Tree-SHA512: 026c0f5f227b5613bbab069b2c5238266aea6f6c2ae184cf77d37777fee2ddd52a99c9e305c107a2edd855dbd182d1b9194de361703995732061649f155cb65f
2 parents 74c31da + 663fb13 commit f6c1c61

File tree

3 files changed

+22
-26
lines changed

3 files changed

+22
-26
lines changed

crates/wallet/src/wallet/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,7 @@ impl Wallet {
12051205
/// [`TxBuilder`]: crate::TxBuilder
12061206
pub fn build_tx(&mut self) -> TxBuilder<'_, DefaultCoinSelectionAlgorithm> {
12071207
TxBuilder {
1208-
wallet: alloc::rc::Rc::new(core::cell::RefCell::new(self)),
1208+
wallet: self,
12091209
params: TxParams::default(),
12101210
coin_selection: DefaultCoinSelectionAlgorithm::default(),
12111211
}
@@ -1711,7 +1711,7 @@ impl Wallet {
17111711
};
17121712

17131713
Ok(TxBuilder {
1714-
wallet: alloc::rc::Rc::new(core::cell::RefCell::new(self)),
1714+
wallet: self,
17151715
params,
17161716
coin_selection: DefaultCoinSelectionAlgorithm::default(),
17171717
})

crates/wallet/src/wallet/tx_builder.rs

+5-18
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@
3636
//! # Ok::<(), anyhow::Error>(())
3737
//! ```
3838
39-
use alloc::{boxed::Box, rc::Rc, string::String, vec::Vec};
40-
use core::cell::RefCell;
39+
use alloc::{boxed::Box, string::String, vec::Vec};
4140
use core::fmt;
4241

4342
use alloc::sync::Arc;
@@ -111,7 +110,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
111110
/// [`coin_selection`]: Self::coin_selection
112111
#[derive(Debug)]
113112
pub struct TxBuilder<'a, Cs> {
114-
pub(crate) wallet: Rc<RefCell<&'a mut Wallet>>,
113+
pub(crate) wallet: &'a mut Wallet,
115114
pub(crate) params: TxParams,
116115
pub(crate) coin_selection: Cs,
117116
}
@@ -161,16 +160,6 @@ impl Default for FeePolicy {
161160
}
162161
}
163162

164-
impl<'a, Cs: Clone> Clone for TxBuilder<'a, Cs> {
165-
fn clone(&self) -> Self {
166-
TxBuilder {
167-
wallet: self.wallet.clone(),
168-
params: self.params.clone(),
169-
coin_selection: self.coin_selection.clone(),
170-
}
171-
}
172-
}
173-
174163
// Methods supported for any CoinSelectionAlgorithm.
175164
impl<'a, Cs> TxBuilder<'a, Cs> {
176165
/// Set a custom fee rate.
@@ -286,7 +275,7 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
286275
/// the "utxos" and the "unspendable" list, it will be spent.
287276
pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, AddUtxoError> {
288277
{
289-
let wallet = self.wallet.borrow();
278+
let wallet = &mut self.wallet;
290279
let utxos = outpoints
291280
.iter()
292281
.map(|outpoint| {
@@ -682,9 +671,7 @@ impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs> {
682671
/// **WARNING**: To avoid change address reuse you must persist the changes resulting from one
683672
/// or more calls to this method before closing the wallet. See [`Wallet::reveal_next_address`].
684673
pub fn finish_with_aux_rand(self, rng: &mut impl RngCore) -> Result<Psbt, CreateTxError> {
685-
self.wallet
686-
.borrow_mut()
687-
.create_tx(self.coin_selection, self.params, rng)
674+
self.wallet.create_tx(self.coin_selection, self.params, rng)
688675
}
689676
}
690677

@@ -750,7 +737,7 @@ impl fmt::Display for AddForeignUtxoError {
750737
#[cfg(feature = "std")]
751738
impl std::error::Error for AddForeignUtxoError {}
752739

753-
type TxSort<T> = dyn Fn(&T, &T) -> core::cmp::Ordering;
740+
type TxSort<T> = dyn (Fn(&T, &T) -> core::cmp::Ordering) + Send + Sync;
754741

755742
/// Ordering of the transaction's inputs and outputs
756743
#[derive(Clone, Default)]

crates/wallet/tests/wallet.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -1649,11 +1649,10 @@ fn test_add_foreign_utxo_only_witness_utxo() {
16491649
.max_weight_to_satisfy()
16501650
.unwrap();
16511651

1652-
let mut builder = wallet1.build_tx();
1653-
builder.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000));
1654-
16551652
{
1656-
let mut builder = builder.clone();
1653+
let mut builder = wallet1.build_tx();
1654+
builder.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000));
1655+
16571656
let psbt_input = psbt::Input {
16581657
witness_utxo: Some(utxo2.txout.clone()),
16591658
..Default::default()
@@ -1668,7 +1667,9 @@ fn test_add_foreign_utxo_only_witness_utxo() {
16681667
}
16691668

16701669
{
1671-
let mut builder = builder.clone();
1670+
let mut builder = wallet1.build_tx();
1671+
builder.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000));
1672+
16721673
let psbt_input = psbt::Input {
16731674
witness_utxo: Some(utxo2.txout.clone()),
16741675
..Default::default()
@@ -1684,7 +1685,9 @@ fn test_add_foreign_utxo_only_witness_utxo() {
16841685
}
16851686

16861687
{
1687-
let mut builder = builder.clone();
1688+
let mut builder = wallet1.build_tx();
1689+
builder.add_recipient(addr.script_pubkey(), Amount::from_sat(60_000));
1690+
16881691
let tx2 = wallet2.get_tx(txid2).unwrap().tx_node.tx;
16891692
let psbt_input = psbt::Input {
16901693
non_witness_utxo: Some(tx2.as_ref().clone()),
@@ -4192,3 +4195,9 @@ fn test_transactions_sort_by() {
41924195
.collect();
41934196
assert_eq!([None, Some(2000), Some(1000)], conf_heights.as_slice());
41944197
}
4198+
4199+
#[test]
4200+
fn test_tx_builder_is_send_safe() {
4201+
let (mut wallet, _txid) = get_funded_wallet_wpkh();
4202+
let _box: Box<dyn Send + Sync> = Box::new(wallet.build_tx());
4203+
}

0 commit comments

Comments
 (0)