]> Untitled Git - bdk/commitdiff
fix(bdk): remove rand dependency
authorrustaceanrob <rob.netzke@gmail.com>
Wed, 3 Apr 2024 00:31:18 +0000 (14:31 -1000)
committerRob N <rob.netzke@gmail.com>
Tue, 18 Jun 2024 01:27:58 +0000 (15:27 -1000)
20 files changed:
.github/workflows/cont_integration.yml
crates/wallet/Cargo.toml
crates/wallet/README.md
crates/wallet/examples/mnemonic_to_descriptors.rs
crates/wallet/src/keys/bip39.rs
crates/wallet/src/keys/mod.rs
crates/wallet/src/wallet/coin_selection.rs
crates/wallet/src/wallet/error.rs
crates/wallet/src/wallet/mod.rs
crates/wallet/src/wallet/signer.rs
crates/wallet/src/wallet/tx_builder.rs
crates/wallet/src/wallet/utils.rs
crates/wallet/tests/psbt.rs
crates/wallet/tests/wallet.rs
example-crates/wallet_electrum/Cargo.toml
example-crates/wallet_electrum/src/main.rs
example-crates/wallet_esplora_async/Cargo.toml
example-crates/wallet_esplora_async/src/main.rs
example-crates/wallet_esplora_blocking/Cargo.toml
example-crates/wallet_esplora_blocking/src/main.rs

index 510af1dbfa7a629fd15f98fdfdeea214815741b2..8d63a86383538bc50e2286f1bdb4cb18b660bb22 100644 (file)
@@ -92,7 +92,7 @@ jobs:
         uses: Swatinem/rust-cache@v2.2.1
       - name: Check bdk wallet
         working-directory: ./crates/wallet
-        run: cargo check --target wasm32-unknown-unknown --no-default-features --features miniscript/no-std,bdk_chain/hashbrown,dev-getrandom-wasm
+        run: cargo check --target wasm32-unknown-unknown --no-default-features --features miniscript/no-std,bdk_chain/hashbrown
       - name: Check esplora
         working-directory: ./crates/esplora
         run: cargo check --target wasm32-unknown-unknown --no-default-features --features miniscript/no-std,bdk_chain/hashbrown,async
index e7e02093f820727edcf5243d8a18790a2413c0b0..758ebf0fd5bce5867cfb067031c30ffa493968fc 100644 (file)
@@ -13,9 +13,9 @@ edition = "2021"
 rust-version = "1.63"
 
 [dependencies]
-rand = "^0.8"
+rand_core = { version = "0.6.0" }
 miniscript = { version = "12.0.0", features = ["serde"], default-features = false }
-bitcoin = { version = "0.32.0", features = ["serde", "base64", "rand-std"], default-features = false }
+bitcoin = { version = "0.32.0", features = ["serde", "base64"], default-features = false }
 serde = { version = "^1.0", features = ["derive"] }
 serde_json = { version = "^1.0" }
 bdk_chain = { path = "../chain", version = "0.16.0", features = ["miniscript", "serde"], default-features = false }
@@ -23,10 +23,6 @@ bdk_chain = { path = "../chain", version = "0.16.0", features = ["miniscript", "
 # Optional dependencies
 bip39 = { version = "2.0", optional = true }
 
-[target.'cfg(target_arch = "wasm32")'.dependencies]
-getrandom = "0.2"
-js-sys = "0.3"
-
 [features]
 default = ["std"]
 std = ["bitcoin/std", "miniscript/std", "bdk_chain/std"]
@@ -34,11 +30,6 @@ compiler = ["miniscript/compiler"]
 all-keys = ["keys-bip39"]
 keys-bip39 = ["bip39"]
 
-# This feature is used to run `cargo check` in our CI targeting wasm. It's not recommended
-# for libraries to explicitly include the "getrandom/js" feature, so we only do it when
-# necessary for running our CI. See: https://docs.rs/getrandom/0.2.8/getrandom/#webassembly-support
-dev-getrandom-wasm = ["getrandom/js"]
-
 [dev-dependencies]
 lazy_static = "1.4"
 assert_matches = "1.5.0"
@@ -46,6 +37,7 @@ tempfile = "3"
 bdk_sqlite = { path = "../sqlite" }
 bdk_file_store = { path = "../file_store" }
 anyhow = "1"
+rand = "^0.8"
 
 [package.metadata.docs.rs]
 all-features = true
index ffe99474ebf4d61f68e111d62cd1f10ff8e8249a..865a4fee373e6d8b0114a8b0a3e21be66b66795e 100644 (file)
@@ -154,6 +154,7 @@ fn main() {
 <!-- use bitcoin::base64; -->
 <!-- use bdk_wallet::bitcoin::consensus::serialize; -->
 <!-- use bdk_wallet::bitcoin::Network; -->
+<!-- use rand::thread_rng(); -->
 
 <!-- fn main() -> Result<(), bdk_wallet::Error> { -->
 <!--     let blockchain = ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002")?); -->
@@ -173,7 +174,7 @@ fn main() {
 <!--             .enable_rbf() -->
 <!--             .do_not_spend_change() -->
 <!--             .fee_rate(FeeRate::from_sat_per_vb(5.0)); -->
-<!--         builder.finish()? -->
+<!--         builder.finish_with_aux_rand(&mut thread_rng())? -->
 <!--     }; -->
 
 <!--     println!("Transaction details: {:#?}", details); -->
index 76c53cf292343742195a7562a783829ef4881ccc..ad1f1badc769287097ca76033815b1ac7055d99c 100644 (file)
@@ -15,6 +15,7 @@ use bdk_wallet::descriptor::IntoWalletDescriptor;
 use bdk_wallet::keys::bip39::{Language, Mnemonic, WordCount};
 use bdk_wallet::keys::{GeneratableKey, GeneratedKey};
 use bdk_wallet::miniscript::Tap;
+use rand::thread_rng;
 use std::str::FromStr;
 
 /// This example demonstrates how to generate a mnemonic phrase
@@ -25,8 +26,9 @@ fn main() -> Result<(), anyhow::Error> {
     // In this example we are generating a 12 words mnemonic phrase
     // but it is also possible generate 15, 18, 21 and 24 words
     // using their respective `WordCount` variant.
+    let mut rng = thread_rng();
     let mnemonic: GeneratedKey<_, Tap> =
-        Mnemonic::generate((WordCount::Words12, Language::English))
+        Mnemonic::generate((WordCount::Words12, Language::English), &mut rng)
             .map_err(|_| anyhow!("Mnemonic generation error"))?;
 
     println!("Mnemonic phrase: {}", *mnemonic);
index 7158505f3889af5b5ecc594236eeb6accf17825d..d1a8a4bac7434baaf5f59dfeda82866a29cf0099 100644 (file)
@@ -158,6 +158,8 @@ mod test {
 
     use bip39::{Language, Mnemonic};
 
+    use rand::thread_rng;
+
     use crate::keys::{any_network, GeneratableKey, GeneratedKey};
 
     use super::WordCount;
@@ -216,12 +218,12 @@ mod test {
 
     #[test]
     fn test_keys_generate_bip39_random() {
+        let mut rng = thread_rng();
         let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
-            Mnemonic::generate((WordCount::Words12, Language::English)).unwrap();
+            Mnemonic::generate((WordCount::Words12, Language::English), &mut rng).unwrap();
         assert_eq!(generated_mnemonic.valid_networks, any_network());
-
         let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
-            Mnemonic::generate((WordCount::Words24, Language::English)).unwrap();
+            Mnemonic::generate((WordCount::Words24, Language::English), &mut rng).unwrap();
         assert_eq!(generated_mnemonic.valid_networks, any_network());
     }
 }
index 10827034886443583f6f1c4e39b628575f88c423..939f8d8a8c696ca32cf3e1ab3337f92862849cd6 100644 (file)
@@ -20,6 +20,8 @@ use core::marker::PhantomData;
 use core::ops::Deref;
 use core::str::FromStr;
 
+use rand_core::{CryptoRng, RngCore};
+
 use bitcoin::secp256k1::{self, Secp256k1, Signing};
 
 use bitcoin::bip32;
@@ -632,11 +634,12 @@ pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
     ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>;
 
     /// Generate a key given the options with a random entropy
-    fn generate(options: Self::Options) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        use rand::{thread_rng, Rng};
-
+    fn generate(
+        options: Self::Options,
+        rng: &mut (impl CryptoRng + RngCore),
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
         let mut entropy = Self::Entropy::default();
-        thread_rng().fill(entropy.as_mut());
+        rng.fill_bytes(entropy.as_mut());
         Self::generate_with_entropy(options, entropy)
     }
 }
@@ -657,8 +660,10 @@ where
     }
 
     /// Generate a key with the default options and a random entropy
-    fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        Self::generate(Default::default())
+    fn generate_default(
+        rng: &mut (impl CryptoRng + RngCore),
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        Self::generate(Default::default(), rng)
     }
 }
 
index 819a15edbaa52de5746b7b09739abdca8fe5ef2e..6a7617fbcb441d5a7f881f4d10f7d077de31c2ef 100644 (file)
@@ -31,6 +31,8 @@
 //! # use bdk_wallet::*;
 //! # use bdk_wallet::wallet::coin_selection::decide_change;
 //! # use anyhow::Error;
+//! # use rand::{thread_rng, RngCore};
+//!
 //! #[derive(Debug)]
 //! struct AlwaysSpendEverything;
 //!
@@ -92,7 +94,7 @@
 //! let psbt = {
 //!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
 //!     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-//!     builder.finish()?
+//!     builder.finish_with_aux_rand(&mut thread_rng())?
 //! };
 //!
 //! // inspect, sign, broadcast, ...
@@ -114,8 +116,9 @@ use bitcoin::{Script, Weight};
 
 use core::convert::TryInto;
 use core::fmt::{self, Formatter};
-use rand::seq::SliceRandom;
+use rand_core::RngCore;
 
+use super::utils::shuffle_slice;
 /// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
 /// overridden
 pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
@@ -516,27 +519,16 @@ impl CoinSelectionAlgorithm for BranchAndBoundCoinSelection {
             ));
         }
 
-        Ok(self
-            .bnb(
-                required_utxos.clone(),
-                optional_utxos.clone(),
-                curr_value,
-                curr_available_value,
-                target_amount,
-                cost_of_change,
-                drain_script,
-                fee_rate,
-            )
-            .unwrap_or_else(|_| {
-                self.single_random_draw(
-                    required_utxos,
-                    optional_utxos,
-                    curr_value,
-                    target_amount,
-                    drain_script,
-                    fee_rate,
-                )
-            }))
+        self.bnb(
+            required_utxos.clone(),
+            optional_utxos.clone(),
+            curr_value,
+            curr_available_value,
+            target_amount,
+            cost_of_change,
+            drain_script,
+            fee_rate,
+        )
     }
 }
 
@@ -663,40 +655,6 @@ impl BranchAndBoundCoinSelection {
         ))
     }
 
-    #[allow(clippy::too_many_arguments)]
-    fn single_random_draw(
-        &self,
-        required_utxos: Vec<OutputGroup>,
-        mut optional_utxos: Vec<OutputGroup>,
-        curr_value: i64,
-        target_amount: i64,
-        drain_script: &Script,
-        fee_rate: FeeRate,
-    ) -> CoinSelectionResult {
-        optional_utxos.shuffle(&mut rand::thread_rng());
-        let selected_utxos = optional_utxos.into_iter().fold(
-            (curr_value, vec![]),
-            |(mut amount, mut utxos), utxo| {
-                if amount >= target_amount {
-                    (amount, utxos)
-                } else {
-                    amount += utxo.effective_value;
-                    utxos.push(utxo);
-                    (amount, utxos)
-                }
-            },
-        );
-
-        // remaining_amount can't be negative as that would mean the
-        // selection wasn't successful
-        // target_amount = amount_needed + (fee_amount - vin_fees)
-        let remaining_amount = (selected_utxos.0 - target_amount) as u64;
-
-        let excess = decide_change(remaining_amount, fee_rate, drain_script);
-
-        BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos.1, required_utxos, excess)
-    }
-
     fn calculate_cs_result(
         mut selected_utxos: Vec<OutputGroup>,
         mut required_utxos: Vec<OutputGroup>,
@@ -717,6 +675,58 @@ impl BranchAndBoundCoinSelection {
     }
 }
 
+// Pull UTXOs at random until we have enough to meet the target
+pub(crate) fn single_random_draw(
+    required_utxos: Vec<WeightedUtxo>,
+    optional_utxos: Vec<WeightedUtxo>,
+    target_amount: u64,
+    drain_script: &Script,
+    fee_rate: FeeRate,
+    rng: &mut impl RngCore,
+) -> CoinSelectionResult {
+    let target_amount = target_amount
+        .try_into()
+        .expect("Bitcoin amount to fit into i64");
+
+    let required_utxos: Vec<OutputGroup> = required_utxos
+        .into_iter()
+        .map(|u| OutputGroup::new(u, fee_rate))
+        .collect();
+
+    let mut optional_utxos: Vec<OutputGroup> = optional_utxos
+        .into_iter()
+        .map(|u| OutputGroup::new(u, fee_rate))
+        .collect();
+
+    let curr_value = required_utxos
+        .iter()
+        .fold(0, |acc, x| acc + x.effective_value);
+
+    shuffle_slice(&mut optional_utxos, rng);
+
+    let selected_utxos =
+        optional_utxos
+            .into_iter()
+            .fold((curr_value, vec![]), |(mut amount, mut utxos), utxo| {
+                if amount >= target_amount {
+                    (amount, utxos)
+                } else {
+                    amount += utxo.effective_value;
+                    utxos.push(utxo);
+                    (amount, utxos)
+                }
+            });
+
+    // remaining_amount can't be negative as that would mean the
+    // selection wasn't successful
+    // target_amount = amount_needed + (fee_amount - vin_fees)
+    let remaining_amount = (selected_utxos.0 - target_amount) as u64;
+
+    let excess = decide_change(remaining_amount, fee_rate, drain_script);
+
+    BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos.1, required_utxos, excess)
+}
+
 /// Remove duplicate UTXOs.
 ///
 /// If a UTXO appears in both `required` and `optional`, the appearance in `required` is kept.
@@ -740,6 +750,7 @@ where
 mod test {
     use assert_matches::assert_matches;
     use core::str::FromStr;
+    use rand::rngs::StdRng;
 
     use bdk_chain::ConfirmationTime;
     use bitcoin::{Amount, ScriptBuf, TxIn, TxOut};
@@ -748,8 +759,7 @@ mod test {
     use crate::types::*;
     use crate::wallet::coin_selection::filter_duplicates;
 
-    use rand::rngs::StdRng;
-    use rand::seq::SliceRandom;
+    use rand::prelude::SliceRandom;
     use rand::{Rng, RngCore, SeedableRng};
 
     // signature len (1WU) + signature and sighash (72WU)
@@ -1090,13 +1100,12 @@ mod test {
     }
 
     #[test]
+    #[ignore = "SRD fn was moved out of BnB"]
     fn test_bnb_coin_selection_success() {
         // In this case bnb won't find a suitable match and single random draw will
         // select three outputs
         let utxos = generate_same_value_utxos(100_000, 20);
-
         let drain_script = ScriptBuf::default();
-
         let target_amount = 250_000 + FEE_AMOUNT;
 
         let result = BranchAndBoundCoinSelection::default()
@@ -1136,6 +1145,7 @@ mod test {
     }
 
     #[test]
+    #[ignore = "no exact match for bnb, previously fell back to SRD"]
     fn test_bnb_coin_selection_optional_are_enough() {
         let utxos = get_test_utxos();
         let drain_script = ScriptBuf::default();
@@ -1156,6 +1166,26 @@ mod test {
         assert_eq!(result.fee_amount, 136);
     }
 
+    #[test]
+    fn test_single_random_draw_function_success() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let mut utxos = generate_random_utxos(&mut rng, 300);
+        let target_amount = sum_random_utxos(&mut rng, &mut utxos) + FEE_AMOUNT;
+        let fee_rate = FeeRate::from_sat_per_vb_unchecked(1);
+        let drain_script = ScriptBuf::default();
+        let result = single_random_draw(
+            vec![],
+            utxos,
+            target_amount,
+            &drain_script,
+            fee_rate,
+            &mut rng,
+        );
+        assert!(result.selected_amount() > target_amount);
+        assert_eq!(result.fee_amount, (result.selected.len() * 68) as u64);
+    }
+
     #[test]
     #[ignore]
     fn test_bnb_coin_selection_required_not_enough() {
@@ -1410,34 +1440,6 @@ mod test {
         }
     }
 
-    #[test]
-    fn test_single_random_draw_function_success() {
-        let seed = [0; 32];
-        let mut rng: StdRng = SeedableRng::from_seed(seed);
-        let mut utxos = generate_random_utxos(&mut rng, 300);
-        let target_amount = sum_random_utxos(&mut rng, &mut utxos) + FEE_AMOUNT;
-
-        let fee_rate = FeeRate::from_sat_per_vb_unchecked(1);
-        let utxos: Vec<OutputGroup> = utxos
-            .into_iter()
-            .map(|u| OutputGroup::new(u, fee_rate))
-            .collect();
-
-        let drain_script = ScriptBuf::default();
-
-        let result = BranchAndBoundCoinSelection::default().single_random_draw(
-            vec![],
-            utxos,
-            0,
-            target_amount as i64,
-            &drain_script,
-            fee_rate,
-        );
-
-        assert!(result.selected_amount() > target_amount);
-        assert_eq!(result.fee_amount, (result.selected.len() * 68) as u64);
-    }
-
     #[test]
     fn test_bnb_exclude_negative_effective_value() {
         let utxos = get_test_utxos();
index b6c9375a438f16f094f4fde5f1515ca1c9728f5a..4f250f34065069984a0a72cfa9e30e7f88cf43ed 100644 (file)
@@ -44,9 +44,9 @@ impl fmt::Display for MiniscriptPsbtError {
 impl std::error::Error for MiniscriptPsbtError {}
 
 #[derive(Debug)]
-/// Error returned from [`TxBuilder::finish`]
+/// Error returned from [`TxBuilder::finish_with_aux_rand`]
 ///
-/// [`TxBuilder::finish`]: crate::wallet::tx_builder::TxBuilder::finish
+/// [`TxBuilder::finish_with_aux_rand`]: crate::wallet::tx_builder::TxBuilder::finish_with_aux_rand
 pub enum CreateTxError {
     /// There was a problem with the descriptors passed in
     Descriptor(DescriptorError),
index 883e954a7925daf7639d3f5b9adc0d36e6c5d133..0cc5b11320828c24cdf33c09579f63836fbfa395 100644 (file)
@@ -41,6 +41,8 @@ use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
 use bitcoin::{constants::genesis_block, Amount};
 use core::fmt;
 use core::ops::Deref;
+use rand_core::RngCore;
+
 use descriptor::error::Error as DescriptorError;
 use miniscript::psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier};
 
@@ -1210,6 +1212,7 @@ impl Wallet {
     /// # use bdk_wallet::wallet::ChangeSet;
     /// # use bdk_wallet::wallet::error::CreateTxError;
     /// # use anyhow::Error;
+    /// # use rand::thread_rng;
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
     /// # let mut wallet = doctest_wallet!();
     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
@@ -1217,7 +1220,7 @@ impl Wallet {
     ///    let mut builder =  wallet.build_tx();
     ///    builder
     ///        .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-    ///    builder.finish()?
+    ///    builder.finish_with_aux_rand(&mut thread_rng())?
     /// };
     ///
     /// // sign and broadcast ...
@@ -1237,6 +1240,7 @@ impl Wallet {
         &mut self,
         coin_selection: Cs,
         params: TxParams,
+        rng: &mut impl RngCore,
     ) -> Result<Psbt, CreateTxError> {
         let keychains: BTreeMap<_, _> = self.indexed_graph.index.keychains().collect();
         let external_descriptor = keychains.get(&KeychainKind::External).expect("must exist");
@@ -1463,13 +1467,31 @@ impl Wallet {
         let (required_utxos, optional_utxos) =
             coin_selection::filter_duplicates(required_utxos, optional_utxos);
 
-        let coin_selection = coin_selection.coin_select(
-            required_utxos,
-            optional_utxos,
+        let coin_selection = match coin_selection.coin_select(
+            required_utxos.clone(),
+            optional_utxos.clone(),
             fee_rate,
             outgoing.to_sat() + fee_amount,
             &drain_script,
-        )?;
+        ) {
+            Ok(res) => res,
+            Err(e) => match e {
+                coin_selection::Error::InsufficientFunds { .. } => {
+                    return Err(CreateTxError::CoinSelection(e));
+                }
+                coin_selection::Error::BnBNoExactMatch
+                | coin_selection::Error::BnBTotalTriesExceeded => {
+                    coin_selection::single_random_draw(
+                        required_utxos,
+                        optional_utxos,
+                        outgoing.to_sat() + fee_amount,
+                        &drain_script,
+                        fee_rate,
+                        rng,
+                    )
+                }
+            },
+        };
         fee_amount += coin_selection.fee_amount;
         let excess = &coin_selection.excess;
 
@@ -1533,7 +1555,7 @@ impl Wallet {
         };
 
         // sort input/outputs according to the chosen algorithm
-        params.ordering.sort_tx(&mut tx);
+        params.ordering.sort_tx_with_aux_rand(&mut tx, rng);
 
         let psbt = self.complete_transaction(tx, coin_selection.selected, params)?;
         Ok(psbt)
@@ -1555,6 +1577,7 @@ impl Wallet {
     /// # use bdk_wallet::wallet::ChangeSet;
     /// # use bdk_wallet::wallet::error::CreateTxError;
     /// # use anyhow::Error;
+    /// # use rand::thread_rng;
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
     /// # let mut wallet = doctest_wallet!();
     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
@@ -1563,7 +1586,7 @@ impl Wallet {
     ///     builder
     ///         .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
     ///         .enable_rbf();
-    ///     builder.finish()?
+    ///     builder.finish_with_aux_rand(&mut thread_rng())?
     /// };
     /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
     /// let tx = psbt.clone().extract_tx().expect("tx");
@@ -1572,7 +1595,7 @@ impl Wallet {
     ///     let mut builder = wallet.build_fee_bump(tx.compute_txid())?;
     ///     builder
     ///         .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
-    ///     builder.finish()?
+    ///     builder.finish_with_aux_rand(&mut thread_rng())?
     /// };
     ///
     /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
@@ -1732,13 +1755,14 @@ impl Wallet {
     /// # use bdk_wallet::*;
     /// # use bdk_wallet::wallet::ChangeSet;
     /// # use bdk_wallet::wallet::error::CreateTxError;
+    /// # use rand::thread_rng;
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
     /// # let mut wallet = doctest_wallet!();
     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
     /// let mut psbt = {
     ///     let mut builder = wallet.build_tx();
     ///     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-    ///     builder.finish()?
+    ///     builder.finish_with_aux_rand(&mut thread_rng())?
     /// };
     /// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
     /// assert!(finalized, "we should have signed all the inputs");
@@ -1783,7 +1807,6 @@ impl Wallet {
         {
             signer.sign_transaction(psbt, &sign_options, &self.secp)?;
         }
-
         // attempt to finalize
         if sign_options.try_finalize {
             self.finalize_psbt(psbt, sign_options)
index 16194961a32570854eaf1d7ab200403950a1f25b..3967ba413c7d4b8c1e9e8bc9b71aa0c9217a0166 100644 (file)
@@ -607,7 +607,7 @@ fn sign_psbt_schnorr(
     };
 
     let msg = &Message::from(hash);
-    let signature = secp.sign_schnorr(msg, &keypair);
+    let signature = secp.sign_schnorr_no_aux_rand(msg, &keypair);
     secp.verify_schnorr(&signature, msg, &XOnlyPublicKey::from_keypair(&keypair).0)
         .expect("invalid or corrupted schnorr signature");
 
index 02d6df59d181f84e8f18b62030d841c44ee1297a..fbb478ad8ccefcd318f16f4351bdba4222b9fecd 100644 (file)
@@ -20,6 +20,7 @@
 //! # use bdk_wallet::wallet::ChangeSet;
 //! # use bdk_wallet::wallet::error::CreateTxError;
 //! # use anyhow::Error;
+//! # use rand::thread_rng;
 //! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
 //! # let mut wallet = doctest_wallet!();
 //! // create a TxBuilder from a wallet
@@ -34,7 +35,7 @@
 //!     .do_not_spend_change()
 //!     // Turn on RBF signaling
 //!     .enable_rbf();
-//! let psbt = tx_builder.finish()?;
+//! let psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
 //! # Ok::<(), anyhow::Error>(())
 //! ```
 
@@ -45,8 +46,10 @@ use core::fmt;
 use bitcoin::psbt::{self, Psbt};
 use bitcoin::script::PushBytes;
 use bitcoin::{absolute, Amount, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid};
+use rand_core::RngCore;
 
 use super::coin_selection::CoinSelectionAlgorithm;
+use super::utils::shuffle_slice;
 use super::{CreateTxError, Wallet};
 use crate::collections::{BTreeMap, HashSet};
 use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
@@ -54,7 +57,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
 /// A transaction builder
 ///
 /// A `TxBuilder` is created by calling [`build_tx`] or [`build_fee_bump`] on a wallet. After
-/// assigning it, you set options on it until finally calling [`finish`] to consume the builder and
+/// assigning it, you set options on it until finally calling [`finish_with_aux_rand`] to consume the builder and
 /// generate the transaction.
 ///
 /// Each option setting method on `TxBuilder` takes and returns `&mut self` so you can chain calls
@@ -68,6 +71,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
 /// # use bdk_wallet::wallet::ChangeSet;
 /// # use bdk_wallet::wallet::error::CreateTxError;
 /// # use anyhow::Error;
+/// # use rand::thread_rng;
 /// # let mut wallet = doctest_wallet!();
 /// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
 /// # let addr2 = addr1.clone();
@@ -78,7 +82,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
 ///         .ordering(TxOrdering::Untouched)
 ///         .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
 ///         .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
-///     builder.finish()?
+///     builder.finish_with_aux_rand(&mut thread_rng())?
 /// };
 ///
 /// // non-chaining
@@ -88,7 +92,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
 ///     for addr in &[addr1, addr2] {
 ///         builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
 ///     }
-///     builder.finish()?
+///     builder.finish_with_aux_rand(&mut thread_rng())?
 /// };
 ///
 /// assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
@@ -102,7 +106,7 @@ use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
 ///
 /// [`build_tx`]: Wallet::build_tx
 /// [`build_fee_bump`]: Wallet::build_fee_bump
-/// [`finish`]: Self::finish
+/// [`finish_with_aux_rand`]: Self::finish_with_aux_rand
 /// [`coin_selection`]: Self::coin_selection
 #[derive(Debug)]
 pub struct TxBuilder<'a, Cs> {
@@ -354,11 +358,11 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
     /// 2. The data in `non_witness_utxo` does not match what is in `outpoint`.
     ///
     /// Note unless you set [`only_witness_utxo`] any non-taproot `psbt_input` you pass to this
-    /// method must have `non_witness_utxo` set otherwise you will get an error when [`finish`]
+    /// method must have `non_witness_utxo` set otherwise you will get an error when [`finish_with_aux_rand`]
     /// is called.
     ///
     /// [`only_witness_utxo`]: Self::only_witness_utxo
-    /// [`finish`]: Self::finish
+    /// [`finish_with_aux_rand`]: Self::finish_with_aux_rand
     /// [`max_weight_to_satisfy`]: miniscript::Descriptor::max_weight_to_satisfy
     pub fn add_foreign_utxo(
         &mut self,
@@ -639,6 +643,7 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
     /// # use bdk_wallet::wallet::ChangeSet;
     /// # use bdk_wallet::wallet::error::CreateTxError;
     /// # use anyhow::Error;
+    /// # use rand::thread_rng;
     /// # let to_address =
     /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
     ///     .unwrap()
@@ -653,7 +658,7 @@ impl<'a, Cs> TxBuilder<'a, Cs> {
     ///     .drain_to(to_address.script_pubkey())
     ///     .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
     ///     .enable_rbf();
-    /// let psbt = tx_builder.finish()?;
+    /// let psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
     /// # Ok::<(), anyhow::Error>(())
     /// ```
     ///
@@ -675,10 +680,10 @@ impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs> {
     ///
     /// **WARNING**: To avoid change address reuse you must persist the changes resulting from one
     /// or more calls to this method before closing the wallet. See [`Wallet::reveal_next_address`].
-    pub fn finish(self) -> Result<Psbt, CreateTxError> {
+    pub fn finish_with_aux_rand(self, rng: &mut impl RngCore) -> Result<Psbt, CreateTxError> {
         self.wallet
             .borrow_mut()
-            .create_tx(self.coin_selection, self.params)
+            .create_tx(self.coin_selection, self.params, rng)
     }
 }
 
@@ -758,14 +763,12 @@ pub enum TxOrdering {
 
 impl TxOrdering {
     /// Sort transaction inputs and outputs by [`TxOrdering`] variant
-    pub fn sort_tx(&self, tx: &mut Transaction) {
+    pub fn sort_tx_with_aux_rand(self, tx: &mut Transaction, rng: &mut impl RngCore) {
         match self {
             TxOrdering::Untouched => {}
             TxOrdering::Shuffle => {
-                use rand::seq::SliceRandom;
-                let mut rng = rand::thread_rng();
-                tx.input.shuffle(&mut rng);
-                tx.output.shuffle(&mut rng);
+                shuffle_slice(&mut tx.input, rng);
+                shuffle_slice(&mut tx.output, rng);
             }
             TxOrdering::Bip69Lexicographic => {
                 tx.input.sort_unstable_by_key(|txin| {
@@ -849,20 +852,16 @@ mod test {
     use bitcoin::consensus::deserialize;
     use bitcoin::hex::FromHex;
     use bitcoin::TxOut;
+    use rand::thread_rng;
 
     use super::*;
-
-    #[test]
-    fn test_output_ordering_default_shuffle() {
-        assert_eq!(TxOrdering::default(), TxOrdering::Shuffle);
-    }
-
     #[test]
     fn test_output_ordering_untouched() {
         let original_tx = ordering_test_tx!();
         let mut tx = original_tx.clone();
+        let mut rng = thread_rng();
 
-        TxOrdering::Untouched.sort_tx(&mut tx);
+        TxOrdering::Untouched.sort_tx_with_aux_rand(&mut tx, &mut rng);
 
         assert_eq!(original_tx, tx);
     }
@@ -871,10 +870,11 @@ mod test {
     fn test_output_ordering_shuffle() {
         let original_tx = ordering_test_tx!();
         let mut tx = original_tx.clone();
+        let mut rng = thread_rng();
 
         (0..40)
             .find(|_| {
-                TxOrdering::Shuffle.sort_tx(&mut tx);
+                TxOrdering::Shuffle.sort_tx_with_aux_rand(&mut tx, &mut rng);
                 original_tx.input != tx.input
             })
             .expect("it should have moved the inputs at least once");
@@ -882,7 +882,7 @@ mod test {
         let mut tx = original_tx.clone();
         (0..40)
             .find(|_| {
-                TxOrdering::Shuffle.sort_tx(&mut tx);
+                TxOrdering::Shuffle.sort_tx_with_aux_rand(&mut tx, &mut rng);
                 original_tx.output != tx.output
             })
             .expect("it should have moved the outputs at least once");
@@ -894,8 +894,9 @@ mod test {
 
         let original_tx = ordering_test_tx!();
         let mut tx = original_tx;
+        let mut rng = thread_rng();
 
-        TxOrdering::Bip69Lexicographic.sort_tx(&mut tx);
+        TxOrdering::Bip69Lexicographic.sort_tx_with_aux_rand(&mut tx, &mut rng);
 
         assert_eq!(
             tx.input[0].previous_output,
index 402361134bdafac1baae56cf967ec47ab206a30b..b79f1eb2a9b25913c4e57fe0930f3d7cc4dbd819 100644 (file)
@@ -14,6 +14,8 @@ use bitcoin::{absolute, relative, Script, Sequence};
 
 use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
 
+use rand_core::RngCore;
+
 /// Trait to check if a value is below the dust limit.
 /// We are performing dust value calculation for a given script public key using rust-bitcoin to
 /// keep it compatible with network dust rate
@@ -110,6 +112,19 @@ impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for Older {
     }
 }
 
+// The Knuth shuffling algorithm based on the original [Fisher-Yates method](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)
+pub(crate) fn shuffle_slice<T>(list: &mut [T], rng: &mut impl RngCore) {
+    if list.is_empty() {
+        return;
+    }
+    let mut current_index = list.len() - 1;
+    while current_index > 0 {
+        let random_index = rng.next_u32() as usize % (current_index + 1);
+        list.swap(current_index, random_index);
+        current_index -= 1;
+    }
+}
+
 pub(crate) type SecpCtx = Secp256k1<All>;
 
 #[cfg(test)]
@@ -118,9 +133,11 @@ mod test {
     // otherwise it's time-based
     pub(crate) const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 1 << 22;
 
-    use super::{check_nsequence_rbf, IsDust};
+    use super::{check_nsequence_rbf, shuffle_slice, IsDust};
     use crate::bitcoin::{Address, Network, Sequence};
+    use alloc::vec::Vec;
     use core::str::FromStr;
+    use rand::{rngs::StdRng, thread_rng, SeedableRng};
 
     #[test]
     fn test_is_dust() {
@@ -182,4 +199,44 @@ mod test {
         );
         assert!(result);
     }
+
+    #[test]
+    fn test_shuffle_slice_empty_vec() {
+        let mut test: Vec<u8> = vec![];
+        shuffle_slice(&mut test, &mut thread_rng());
+    }
+
+    #[test]
+    fn test_shuffle_slice_single_vec() {
+        let mut test: Vec<u8> = vec![0];
+        shuffle_slice(&mut test, &mut thread_rng());
+    }
+
+    #[test]
+    fn test_shuffle_slice_duple_vec() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let mut test: Vec<u8> = vec![0, 1];
+        shuffle_slice(&mut test, &mut rng);
+        assert_eq!(test, &[0, 1]);
+        let seed = [6; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let mut test: Vec<u8> = vec![0, 1];
+        shuffle_slice(&mut test, &mut rng);
+        assert_eq!(test, &[1, 0]);
+    }
+
+    #[test]
+    fn test_shuffle_slice_multi_vec() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let mut test: Vec<u8> = vec![0, 1, 2, 4, 5];
+        shuffle_slice(&mut test, &mut rng);
+        assert_eq!(test, &[2, 1, 0, 4, 5]);
+        let seed = [25; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let mut test: Vec<u8> = vec![0, 1, 2, 4, 5];
+        shuffle_slice(&mut test, &mut rng);
+        assert_eq!(test, &[0, 4, 1, 2, 5]);
+    }
 }
index 155bb143a95d70d865a36af5202c057a0cfb8889..e0b8381000a09b16d2dc14610c8d099bc7900562 100644 (file)
@@ -1,6 +1,7 @@
 use bdk_wallet::bitcoin::{Amount, FeeRate, Psbt, TxIn};
 use bdk_wallet::{psbt, KeychainKind, SignOptions};
 use core::str::FromStr;
+use rand::thread_rng;
 mod common;
 use common::*;
 
@@ -15,7 +16,7 @@ fn test_psbt_malformed_psbt_input_legacy() {
     let send_to = wallet.peek_address(KeychainKind::External, 0);
     let mut builder = wallet.build_tx();
     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     psbt.inputs.push(psbt_bip.inputs[0].clone());
     let options = SignOptions {
         trust_witness_utxo: true,
@@ -32,7 +33,7 @@ fn test_psbt_malformed_psbt_input_segwit() {
     let send_to = wallet.peek_address(KeychainKind::External, 0);
     let mut builder = wallet.build_tx();
     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     psbt.inputs.push(psbt_bip.inputs[1].clone());
     let options = SignOptions {
         trust_witness_utxo: true,
@@ -48,7 +49,7 @@ fn test_psbt_malformed_tx_input() {
     let send_to = wallet.peek_address(KeychainKind::External, 0);
     let mut builder = wallet.build_tx();
     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     psbt.unsigned_tx.input.push(TxIn::default());
     let options = SignOptions {
         trust_witness_utxo: true,
@@ -64,7 +65,7 @@ fn test_psbt_sign_with_finalized() {
     let send_to = wallet.peek_address(KeychainKind::External, 0);
     let mut builder = wallet.build_tx();
     builder.add_recipient(send_to.script_pubkey(), Amount::from_sat(10_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     // add a finalized input
     psbt.inputs.push(psbt_bip.inputs[0].clone());
@@ -86,7 +87,7 @@ fn test_psbt_fee_rate_with_witness_utxo() {
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
     builder.fee_rate(expected_fee_rate);
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee_amount = psbt.fee_amount();
     assert!(fee_amount.is_some());
 
@@ -111,7 +112,7 @@ fn test_psbt_fee_rate_with_nonwitness_utxo() {
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
     builder.fee_rate(expected_fee_rate);
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee_amount = psbt.fee_amount();
     assert!(fee_amount.is_some());
     let unfinalized_fee_rate = psbt.fee_rate().unwrap();
@@ -135,7 +136,7 @@ fn test_psbt_fee_rate_with_missing_txout() {
     let mut builder = wpkh_wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
     builder.fee_rate(expected_fee_rate);
-    let mut wpkh_psbt = builder.finish().unwrap();
+    let mut wpkh_psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     wpkh_psbt.inputs[0].witness_utxo = None;
     wpkh_psbt.inputs[0].non_witness_utxo = None;
@@ -149,7 +150,7 @@ fn test_psbt_fee_rate_with_missing_txout() {
     let mut builder = pkh_wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
     builder.fee_rate(expected_fee_rate);
-    let mut pkh_psbt = builder.finish().unwrap();
+    let mut pkh_psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     pkh_psbt.inputs[0].non_witness_utxo = None;
     assert!(pkh_psbt.fee_amount().is_none());
@@ -178,7 +179,7 @@ fn test_psbt_multiple_internalkey_signers() {
     let send_to = wallet.peek_address(KeychainKind::External, 0);
     let mut builder = wallet.build_tx();
     builder.drain_to(send_to.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let unsigned_tx = psbt.unsigned_tx.clone();
 
     // Adds a signer for the wrong internal key, bdk should not use this key to sign
index 7303bdcd8a57de3e0bc644588ce7970599ca0e45..61e678594797b20951c380236989769958e00794 100644 (file)
@@ -24,6 +24,8 @@ use bitcoin::{
     absolute, transaction, Address, Amount, BlockHash, FeeRate, Network, OutPoint, ScriptBuf,
     Sequence, Transaction, TxIn, TxOut, Txid, Weight,
 };
+use rand::rngs::StdRng;
+use rand::{thread_rng, SeedableRng};
 
 mod common;
 use common::*;
@@ -496,7 +498,10 @@ macro_rules! from_str {
 #[should_panic(expected = "NoRecipients")]
 fn test_create_tx_empty_recipients() {
     let (mut wallet, _) = get_funded_wallet_wpkh();
-    wallet.build_tx().finish().unwrap();
+    wallet
+        .build_tx()
+        .finish_with_aux_rand(&mut thread_rng())
+        .unwrap();
 }
 
 #[test]
@@ -508,7 +513,7 @@ fn test_create_tx_manually_selected_empty_utxos() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .manually_selected_only();
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -519,7 +524,10 @@ fn test_create_tx_version_0() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .version(0);
-    assert!(matches!(builder.finish(), Err(CreateTxError::Version0)));
+    assert!(matches!(
+        builder.finish_with_aux_rand(&mut thread_rng()),
+        Err(CreateTxError::Version0)
+    ));
 }
 
 #[test]
@@ -530,7 +538,10 @@ fn test_create_tx_version_1_csv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .version(1);
-    assert!(matches!(builder.finish(), Err(CreateTxError::Version1Csv)));
+    assert!(matches!(
+        builder.finish_with_aux_rand(&mut thread_rng()),
+        Err(CreateTxError::Version1Csv)
+    ));
 }
 
 #[test]
@@ -541,7 +552,7 @@ fn test_create_tx_custom_version() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .version(42);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.version.0, 42);
 }
@@ -553,7 +564,7 @@ fn test_create_tx_default_locktime_is_last_sync_height() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     // Since we never synced the wallet we don't have a last_sync_height
     // we could use to try to prevent fee sniping. We default to 0.
@@ -567,7 +578,7 @@ fn test_create_tx_fee_sniping_locktime_last_sync() {
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
 
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     // If there's no current_height we're left with using the last sync height
     assert_eq!(
@@ -582,7 +593,7 @@ fn test_create_tx_default_locktime_cltv() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.lock_time.to_consensus_u32(), 100_000);
 }
@@ -596,7 +607,7 @@ fn test_create_tx_custom_locktime() {
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .current_height(630_001)
         .nlocktime(absolute::LockTime::from_height(630_000).unwrap());
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     // When we explicitly specify a nlocktime
     // we don't try any fee sniping prevention trick
@@ -612,7 +623,7 @@ fn test_create_tx_custom_locktime_compatible_with_cltv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .nlocktime(absolute::LockTime::from_height(630_000).unwrap());
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.lock_time.to_consensus_u32(), 630_000);
 }
@@ -625,7 +636,7 @@ fn test_create_tx_custom_locktime_incompatible_with_cltv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .nlocktime(absolute::LockTime::from_height(50000).unwrap());
-    assert!(matches!(builder.finish(),
+    assert!(matches!(builder.finish_with_aux_rand(&mut thread_rng()),
         Err(CreateTxError::LockTime { requested, required })
         if requested.to_consensus_u32() == 50_000 && required.to_consensus_u32() == 100_000));
 }
@@ -636,7 +647,7 @@ fn test_create_tx_no_rbf_csv() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(6));
 }
@@ -649,7 +660,7 @@ fn test_create_tx_with_default_rbf_csv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
     // It will be set to the OP_CSV value, in this case 6
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(6));
@@ -663,7 +674,7 @@ fn test_create_tx_with_custom_rbf_csv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf_with_sequence(Sequence(3));
-    assert!(matches!(builder.finish(),
+    assert!(matches!(builder.finish_with_aux_rand(&mut thread_rng()),
         Err(CreateTxError::RbfSequenceCsv { rbf, csv })
         if rbf.to_consensus_u32() == 3 && csv.to_consensus_u32() == 6));
 }
@@ -674,7 +685,7 @@ fn test_create_tx_no_rbf_cltv() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE));
 }
@@ -687,7 +698,10 @@ fn test_create_tx_invalid_rbf_sequence() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf_with_sequence(Sequence(0xFFFFFFFE));
-    assert!(matches!(builder.finish(), Err(CreateTxError::RbfSequence)));
+    assert!(matches!(
+        builder.finish_with_aux_rand(&mut thread_rng()),
+        Err(CreateTxError::RbfSequence)
+    ));
 }
 
 #[test]
@@ -698,7 +712,7 @@ fn test_create_tx_custom_rbf_sequence() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf_with_sequence(Sequence(0xDEADBEEF));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xDEADBEEF));
 }
@@ -711,7 +725,7 @@ fn test_create_tx_change_policy() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .do_not_spend_change();
-    assert!(builder.finish().is_ok());
+    assert!(builder.finish_with_aux_rand(&mut thread_rng()).is_ok());
 
     // wallet has no change, so setting `only_spend_change`
     // should cause tx building to fail
@@ -720,7 +734,7 @@ fn test_create_tx_change_policy() {
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .only_spend_change();
     assert!(matches!(
-        builder.finish(),
+        builder.finish_with_aux_rand(&mut thread_rng()),
         Err(CreateTxError::CoinSelection(
             coin_selection::Error::InsufficientFunds { .. }
         )),
@@ -733,7 +747,7 @@ fn test_create_tx_default_sequence() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE));
 }
@@ -753,7 +767,7 @@ fn test_create_tx_drain_wallet_and_drain_to() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(psbt.unsigned_tx.output.len(), 1);
@@ -775,7 +789,7 @@ fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() {
         .add_recipient(addr.script_pubkey(), Amount::from_sat(20_000))
         .drain_to(drain_addr.script_pubkey())
         .drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
     let outputs = psbt.unsigned_tx.output;
 
@@ -805,7 +819,7 @@ fn test_create_tx_drain_to_and_utxos() {
         .drain_to(addr.script_pubkey())
         .add_utxos(&utxos)
         .unwrap();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(psbt.unsigned_tx.output.len(), 1);
@@ -822,7 +836,7 @@ fn test_create_tx_drain_to_no_drain_wallet_no_utxos() {
     let drain_addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(drain_addr.script_pubkey());
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -831,7 +845,7 @@ fn test_create_tx_default_fee_rate() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::BROADCAST_MIN, @add_signature);
@@ -845,7 +859,7 @@ fn test_create_tx_custom_fee_rate() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .fee_rate(FeeRate::from_sat_per_vb_unchecked(5));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_fee_rate!(psbt, fee.unwrap_or(Amount::ZERO), FeeRate::from_sat_per_vb_unchecked(5), @add_signature);
@@ -860,7 +874,7 @@ fn test_create_tx_absolute_fee() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .fee_absolute(Amount::from_sat(100));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::from_sat(100));
@@ -880,7 +894,7 @@ fn test_create_tx_absolute_zero_fee() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .fee_absolute(Amount::ZERO);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(fee.unwrap_or(Amount::ZERO), Amount::ZERO);
@@ -901,20 +915,21 @@ fn test_create_tx_absolute_high_fee() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .fee_absolute(Amount::from_sat(60_000));
-    let _ = builder.finish().unwrap();
+    let _ = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
 fn test_create_tx_add_change() {
     use bdk_wallet::wallet::tx_builder::TxOrdering;
-
+    let seed = [0; 32];
+    let mut rng: StdRng = SeedableRng::from_seed(seed);
     let (mut wallet, _) = get_funded_wallet_wpkh();
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
-        .ordering(TxOrdering::Untouched);
-    let psbt = builder.finish().unwrap();
+        .ordering(TxOrdering::Shuffle);
+    let psbt = builder.finish_with_aux_rand(&mut rng).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(psbt.unsigned_tx.output.len(), 2);
@@ -931,7 +946,7 @@ fn test_create_tx_skip_change_dust() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(49_800));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(psbt.unsigned_tx.output.len(), 1);
@@ -950,7 +965,7 @@ fn test_create_tx_drain_to_dust_amount() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .fee_rate(FeeRate::from_sat_per_vb_unchecked(454));
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -962,7 +977,7 @@ fn test_create_tx_ordering_respected() {
         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000))
         .add_recipient(addr.script_pubkey(), Amount::from_sat(10_000))
         .ordering(bdk_wallet::wallet::tx_builder::TxOrdering::Bip69Lexicographic);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(psbt.unsigned_tx.output.len(), 3);
@@ -980,7 +995,7 @@ fn test_create_tx_default_sighash() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(30_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.inputs[0].sighash_type, None);
 }
@@ -993,7 +1008,7 @@ fn test_create_tx_custom_sighash() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000))
         .sighash(EcdsaSighashType::Single.into());
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(
         psbt.inputs[0].sighash_type,
@@ -1010,7 +1025,7 @@ fn test_create_tx_input_hd_keypaths() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.inputs[0].bip32_derivation.len(), 1);
     assert_eq!(
@@ -1032,7 +1047,7 @@ fn test_create_tx_output_hd_keypaths() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.outputs[0].bip32_derivation.len(), 1);
     let expected_derivation_path = format!("m/44'/0'/0'/0/{}", addr.index);
@@ -1054,7 +1069,7 @@ fn test_create_tx_set_redeem_script_p2sh() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(
         psbt.inputs[0].redeem_script,
@@ -1077,7 +1092,7 @@ fn test_create_tx_set_witness_script_p2wsh() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.inputs[0].redeem_script, None);
     assert_eq!(
@@ -1098,7 +1113,7 @@ fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let script = ScriptBuf::from_hex(
         "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
@@ -1116,7 +1131,7 @@ fn test_create_tx_non_witness_utxo() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert!(psbt.inputs[0].non_witness_utxo.is_some());
     assert!(psbt.inputs[0].witness_utxo.is_none());
@@ -1132,7 +1147,7 @@ fn test_create_tx_only_witness_utxo() {
         .drain_to(addr.script_pubkey())
         .only_witness_utxo()
         .drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert!(psbt.inputs[0].non_witness_utxo.is_none());
     assert!(psbt.inputs[0].witness_utxo.is_some());
@@ -1145,7 +1160,7 @@ fn test_create_tx_shwpkh_has_witness_utxo() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert!(psbt.inputs[0].witness_utxo.is_some());
 }
@@ -1157,7 +1172,7 @@ fn test_create_tx_both_non_witness_utxo_and_witness_utxo_default() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert!(psbt.inputs[0].non_witness_utxo.is_some());
     assert!(psbt.inputs[0].witness_utxo.is_some());
@@ -1195,7 +1210,7 @@ fn test_create_tx_add_utxo() {
             vout: 0,
         })
         .unwrap();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
 
@@ -1246,7 +1261,7 @@ fn test_create_tx_manually_selected_insufficient() {
         })
         .unwrap()
         .manually_selected_only();
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -1259,7 +1274,7 @@ fn test_create_tx_policy_path_required() {
         .assume_checked();
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(10_000));
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -1294,7 +1309,7 @@ fn test_create_tx_policy_path_no_csv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000))
         .policy_path(path, KeychainKind::External);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFF));
 }
@@ -1315,7 +1330,7 @@ fn test_create_tx_policy_path_use_csv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000))
         .policy_path(path, KeychainKind::External);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(144));
 }
@@ -1336,7 +1351,7 @@ fn test_create_tx_policy_path_ignored_subtree_with_csv() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(30_000))
         .policy_path(path, KeychainKind::External);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE));
 }
@@ -1350,7 +1365,7 @@ fn test_create_tx_global_xpubs_with_origin() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .add_global_xpubs();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let key = bip32::Xpub::from_str("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
     let fingerprint = bip32::Fingerprint::from_hex("73756c7f").unwrap();
@@ -1390,7 +1405,7 @@ fn test_add_foreign_utxo() {
             foreign_utxo_satisfaction.to_wu() as usize,
         )
         .unwrap();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     wallet1.insert_txout(utxo.outpoint, utxo.txout);
     let fee = check_fee!(wallet1, psbt);
     let sent_received =
@@ -1470,7 +1485,7 @@ fn test_calculate_fee_with_missing_foreign_utxo() {
             foreign_utxo_satisfaction.to_wu() as usize,
         )
         .unwrap();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let tx = psbt.extract_tx().expect("failed to extract tx");
     wallet1.calculate_fee(&tx).unwrap();
 }
@@ -1569,7 +1584,7 @@ fn test_add_foreign_utxo_only_witness_utxo() {
             )
             .unwrap();
         assert!(
-            builder.finish().is_err(),
+            builder.finish_with_aux_rand(&mut thread_rng()).is_err(),
             "psbt_input with witness_utxo should fail with only witness_utxo"
         );
     }
@@ -1589,7 +1604,7 @@ fn test_add_foreign_utxo_only_witness_utxo() {
             )
             .unwrap();
         assert!(
-            builder.finish().is_ok(),
+            builder.finish_with_aux_rand(&mut thread_rng()).is_ok(),
             "psbt_input with just witness_utxo should succeed when `only_witness_utxo` is enabled"
         );
     }
@@ -1609,7 +1624,7 @@ fn test_add_foreign_utxo_only_witness_utxo() {
             )
             .unwrap();
         assert!(
-            builder.finish().is_ok(),
+            builder.finish_with_aux_rand(&mut thread_rng()).is_ok(),
             "psbt_input with non_witness_utxo should succeed by default"
         );
     }
@@ -1636,7 +1651,7 @@ fn test_create_tx_global_xpubs_origin_missing() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .add_global_xpubs();
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -1648,7 +1663,7 @@ fn test_create_tx_global_xpubs_master_without_origin() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .add_global_xpubs();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let key = bip32::Xpub::from_str("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
     let fingerprint = bip32::Fingerprint::from_hex("997a323b").unwrap();
@@ -1667,14 +1682,18 @@ fn test_bump_fee_irreplaceable_tx() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let txid = tx.compute_txid();
     wallet
         .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
         .unwrap();
-    wallet.build_fee_bump(txid).unwrap().finish().unwrap();
+    wallet
+        .build_fee_bump(txid)
+        .unwrap()
+        .finish_with_aux_rand(&mut thread_rng())
+        .unwrap();
 }
 
 #[test]
@@ -1684,7 +1703,7 @@ fn test_bump_fee_confirmed_tx() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let txid = tx.compute_txid();
@@ -1699,7 +1718,11 @@ fn test_bump_fee_confirmed_tx() {
         )
         .unwrap();
 
-    wallet.build_fee_bump(txid).unwrap().finish().unwrap();
+    wallet
+        .build_fee_bump(txid)
+        .unwrap()
+        .finish_with_aux_rand(&mut thread_rng())
+        .unwrap();
 }
 
 #[test]
@@ -1710,7 +1733,7 @@ fn test_bump_fee_low_fee_rate() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let feerate = psbt.fee_rate().unwrap();
 
     let tx = psbt.extract_tx().expect("failed to extract tx");
@@ -1722,7 +1745,7 @@ fn test_bump_fee_low_fee_rate() {
 
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_rate(FeeRate::BROADCAST_MIN);
-    let res = builder.finish();
+    let res = builder.finish_with_aux_rand(&mut thread_rng());
     assert_matches!(
         res,
         Err(CreateTxError::FeeRateTooLow { .. }),
@@ -1744,7 +1767,7 @@ fn test_bump_fee_low_abs() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let txid = tx.compute_txid();
@@ -1755,7 +1778,7 @@ fn test_bump_fee_low_abs() {
 
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_absolute(Amount::from_sat(10));
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -1767,7 +1790,7 @@ fn test_bump_fee_zero_abs() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let txid = tx.compute_txid();
@@ -1777,7 +1800,7 @@ fn test_bump_fee_zero_abs() {
 
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_absolute(Amount::ZERO);
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -1790,7 +1813,7 @@ fn test_bump_fee_reduce_change() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(25_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let original_sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let original_fee = check_fee!(wallet, psbt);
@@ -1804,7 +1827,7 @@ fn test_bump_fee_reduce_change() {
     let feerate = FeeRate::from_sat_per_kwu(625); // 2.5 sat/vb
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_rate(feerate).enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -1840,7 +1863,7 @@ fn test_bump_fee_reduce_change() {
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_absolute(Amount::from_sat(200));
     builder.enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -1890,7 +1913,7 @@ fn test_bump_fee_reduce_single_recipient() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let tx = psbt.clone().extract_tx().expect("failed to extract tx");
     let original_sent_received = wallet.sent_and_received(&tx);
     let original_fee = check_fee!(wallet, psbt);
@@ -1909,7 +1932,7 @@ fn test_bump_fee_reduce_single_recipient() {
         .drain_to(addr.script_pubkey())
         // drain wallet output amount will be re-calculated with new fee rate
         .drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -1938,7 +1961,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let original_fee = check_fee!(wallet, psbt);
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let original_sent_received = wallet.sent_and_received(&tx);
@@ -1956,7 +1979,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() {
         .drain_to(addr.script_pubkey())
         // drain wallet output amount will be re-calculated with new fee rate
         .drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let tx = &psbt.unsigned_tx;
     let sent_received = wallet.sent_and_received(tx);
     let fee = check_fee!(wallet, psbt);
@@ -2011,7 +2034,7 @@ fn test_bump_fee_drain_wallet() {
         .unwrap()
         .manually_selected_only()
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let original_sent_received = wallet.sent_and_received(&tx);
 
@@ -2027,7 +2050,7 @@ fn test_bump_fee_drain_wallet() {
     builder
         .drain_wallet()
         .fee_rate(FeeRate::from_sat_per_vb_unchecked(5));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received = wallet.sent_and_received(&psbt.extract_tx().expect("failed to extract tx"));
 
     assert_eq!(sent_received.0, Amount::from_sat(75_000));
@@ -2079,7 +2102,7 @@ fn test_bump_fee_remove_output_manually_selected_only() {
         .unwrap()
         .manually_selected_only()
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let original_sent_received = wallet.sent_and_received(&tx);
     let txid = tx.compute_txid();
@@ -2092,7 +2115,7 @@ fn test_bump_fee_remove_output_manually_selected_only() {
     builder
         .manually_selected_only()
         .fee_rate(FeeRate::from_sat_per_vb_unchecked(255));
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -2125,7 +2148,7 @@ fn test_bump_fee_add_input() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let original_details = wallet.sent_and_received(&tx);
     let txid = tx.compute_txid();
@@ -2135,7 +2158,7 @@ fn test_bump_fee_add_input() {
 
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -2182,7 +2205,7 @@ fn test_bump_fee_absolute_add_input() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let tx = psbt.extract_tx().expect("failed to extract tx");
     let original_sent_received = wallet.sent_and_received(&tx);
     let txid = tx.compute_txid();
@@ -2192,7 +2215,7 @@ fn test_bump_fee_absolute_add_input() {
 
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_absolute(Amount::from_sat(6_000));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -2245,7 +2268,7 @@ fn test_bump_fee_no_change_add_input_and_change() {
         .unwrap()
         .manually_selected_only()
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let original_sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let original_fee = check_fee!(wallet, psbt);
@@ -2260,7 +2283,7 @@ fn test_bump_fee_no_change_add_input_and_change() {
     // the original output untouched.
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -2309,7 +2332,7 @@ fn test_bump_fee_add_input_change_dust() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let original_sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let original_fee = check_fee!(wallet, psbt);
@@ -2342,7 +2365,7 @@ fn test_bump_fee_add_input_change_dust() {
     // We use epsilon here to avoid asking for a slightly too high feerate
     let fee_abs = 50_000 + 25_000 - 45_000 - 10;
     builder.fee_rate(Amount::from_sat(fee_abs) / new_tx_weight);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -2386,7 +2409,7 @@ fn test_bump_fee_force_add_input() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let mut tx = psbt.extract_tx().expect("failed to extract tx");
     let original_sent_received = wallet.sent_and_received(&tx);
     let txid = tx.compute_txid();
@@ -2403,7 +2426,7 @@ fn test_bump_fee_force_add_input() {
         .add_utxo(incoming_op)
         .unwrap()
         .fee_rate(FeeRate::from_sat_per_vb_unchecked(5));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -2452,7 +2475,7 @@ fn test_bump_fee_absolute_force_add_input() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000))
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let mut tx = psbt.extract_tx().expect("failed to extract tx");
     let original_sent_received = wallet.sent_and_received(&tx);
     let txid = tx.compute_txid();
@@ -2471,7 +2494,7 @@ fn test_bump_fee_absolute_force_add_input() {
         .add_utxo(incoming_op)
         .unwrap()
         .fee_absolute(Amount::from_sat(250));
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     let fee = check_fee!(wallet, psbt);
@@ -2526,7 +2549,7 @@ fn test_bump_fee_unconfirmed_inputs_only() {
         .drain_wallet()
         .drain_to(addr.script_pubkey())
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     // Now we receive one transaction with 0 confirmations. We won't be able to use that for
     // fee bumping, as it's still unconfirmed!
     receive_output(
@@ -2544,7 +2567,7 @@ fn test_bump_fee_unconfirmed_inputs_only() {
         .unwrap();
     let mut builder = wallet.build_fee_bump(txid).unwrap();
     builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(25));
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -2566,7 +2589,7 @@ fn test_bump_fee_unconfirmed_input() {
         .drain_wallet()
         .drain_to(addr.script_pubkey())
         .enable_rbf();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let mut tx = psbt.extract_tx().expect("failed to extract tx");
     let txid = tx.compute_txid();
     for txin in &mut tx.input {
@@ -2585,7 +2608,7 @@ fn test_bump_fee_unconfirmed_input() {
         .drain_to(addr.script_pubkey())
         // drain wallet output amount will be re-calculated with new fee rate
         .drain_wallet();
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -2612,7 +2635,7 @@ fn test_fee_amount_negative_drain_val() {
         .unwrap()
         .enable_rbf()
         .fee_rate(fee_rate);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     assert_eq!(psbt.inputs.len(), 1);
@@ -2625,7 +2648,7 @@ fn test_sign_single_xprv() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
     assert!(finalized);
@@ -2640,7 +2663,7 @@ fn test_sign_single_xprv_with_master_fingerprint_and_path() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
     assert!(finalized);
@@ -2655,7 +2678,7 @@ fn test_sign_single_xprv_bip44_path() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
     assert!(finalized);
@@ -2670,7 +2693,7 @@ fn test_sign_single_xprv_sh_wpkh() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
     assert!(finalized);
@@ -2686,7 +2709,7 @@ fn test_sign_single_wif() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
     assert!(finalized);
@@ -2701,7 +2724,7 @@ fn test_sign_single_xprv_no_hd_keypaths() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     psbt.inputs[0].bip32_derivation.clear();
     assert_eq!(psbt.inputs[0].bip32_derivation.len(), 0);
@@ -2725,7 +2748,7 @@ fn test_include_output_redeem_witness_script() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000))
         .include_output_redeem_witness_script();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     // p2sh-p2wsh transaction should contain both witness and redeem scripts
     assert!(psbt
@@ -2744,7 +2767,7 @@ fn test_signing_only_one_of_multiple_inputs() {
     builder
         .add_recipient(addr.script_pubkey(), Amount::from_sat(45_000))
         .include_output_redeem_witness_script();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     // add another input to the psbt that is at least passable.
     let dud_input = bitcoin::psbt::Input {
@@ -2788,7 +2811,7 @@ fn test_remove_partial_sigs_after_finalize_sign_option() {
         let addr = wallet.next_unused_address(KeychainKind::External);
         let mut builder = wallet.build_tx();
         builder.drain_to(addr.script_pubkey()).drain_wallet();
-        let mut psbt = builder.finish().unwrap();
+        let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
         assert!(wallet
             .sign(
@@ -2818,7 +2841,7 @@ fn test_try_finalize_sign_option() {
         let addr = wallet.next_unused_address(KeychainKind::External);
         let mut builder = wallet.build_tx();
         builder.drain_to(addr.script_pubkey()).drain_wallet();
-        let mut psbt = builder.finish().unwrap();
+        let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
         let finalized = wallet
             .sign(
@@ -2855,7 +2878,7 @@ fn test_sign_nonstandard_sighash() {
         .drain_to(addr.script_pubkey())
         .sighash(sighash.into())
         .drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let result = wallet.sign(&mut psbt, Default::default());
     assert!(
@@ -3085,7 +3108,7 @@ fn test_sending_to_bip350_bech32m_address() {
         .assume_checked();
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(45_000));
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -3171,7 +3194,7 @@ fn test_taproot_remove_tapfields_after_finalize_sign_option() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let finalized = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
     assert!(finalized);
 
@@ -3198,7 +3221,7 @@ fn test_taproot_psbt_populate_tap_key_origins() {
 
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(
         psbt.inputs[0]
@@ -3241,7 +3264,7 @@ fn test_taproot_psbt_populate_tap_key_origins_repeated_key() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .policy_path(path, KeychainKind::External);
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let mut input_key_origins = psbt.inputs[0]
         .tap_key_origins
@@ -3301,7 +3324,7 @@ fn test_taproot_psbt_input_tap_tree() {
 
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert_eq!(
         psbt.inputs[0].tap_merkle_root,
@@ -3343,7 +3366,7 @@ fn test_taproot_sign_missing_witness_utxo() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let witness_utxo = psbt.inputs[0].witness_utxo.take();
 
     let result = wallet.sign(
@@ -3383,7 +3406,7 @@ fn test_taproot_sign_using_non_witness_utxo() {
     let addr = wallet.next_unused_address(KeychainKind::External);
     let mut builder = wallet.build_tx();
     builder.drain_to(addr.script_pubkey()).drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     psbt.inputs[0].witness_utxo = None;
     psbt.inputs[0].non_witness_utxo =
@@ -3430,7 +3453,7 @@ fn test_taproot_foreign_utxo() {
             foreign_utxo_satisfaction.to_wu() as usize,
         )
         .unwrap();
-    let psbt = builder.finish().unwrap();
+    let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let sent_received =
         wallet1.sent_and_received(&psbt.clone().extract_tx().expect("failed to extract tx"));
     wallet1.insert_txout(utxo.outpoint, utxo.txout);
@@ -3456,7 +3479,7 @@ fn test_spend_from_wallet(mut wallet: Wallet) {
 
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert!(
         wallet.sign(&mut psbt, Default::default()).unwrap(),
@@ -3480,7 +3503,7 @@ fn test_taproot_no_key_spend() {
 
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert!(
         wallet
@@ -3515,7 +3538,7 @@ fn test_taproot_script_spend_sign_all_leaves() {
 
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     assert!(
         wallet
@@ -3546,7 +3569,7 @@ fn test_taproot_script_spend_sign_include_some_leaves() {
 
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let mut script_leaves: Vec<_> = psbt.inputs[0]
         .tap_scripts
         .clone()
@@ -3586,7 +3609,7 @@ fn test_taproot_script_spend_sign_exclude_some_leaves() {
 
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let mut script_leaves: Vec<_> = psbt.inputs[0]
         .tap_scripts
         .clone()
@@ -3624,7 +3647,7 @@ fn test_taproot_script_spend_sign_no_leaves() {
 
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     wallet
         .sign(
@@ -3647,7 +3670,7 @@ fn test_taproot_sign_derive_index_from_psbt() {
 
     let mut builder = wallet.build_tx();
     builder.add_recipient(addr.script_pubkey(), Amount::from_sat(25_000));
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     // re-create the wallet with an empty db
     let wallet_empty = Wallet::new(
@@ -3674,7 +3697,7 @@ fn test_taproot_sign_explicit_sighash_all() {
         .drain_to(addr.script_pubkey())
         .sighash(TapSighashType::All.into())
         .drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let result = wallet.sign(&mut psbt, Default::default());
     assert!(
@@ -3694,7 +3717,7 @@ fn test_taproot_sign_non_default_sighash() {
         .drain_to(addr.script_pubkey())
         .sighash(sighash.into())
         .drain_wallet();
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
     let witness_utxo = psbt.inputs[0].witness_utxo.take();
 
@@ -3812,7 +3835,7 @@ fn test_spend_coinbase() {
         .add_recipient(addr.script_pubkey(), balance.immature / 2)
         .current_height(confirmation_height);
     assert!(matches!(
-        builder.finish(),
+        builder.finish_with_aux_rand(&mut thread_rng()),
         Err(CreateTxError::CoinSelection(
             coin_selection::Error::InsufficientFunds {
                 needed: _,
@@ -3827,7 +3850,7 @@ fn test_spend_coinbase() {
         .add_recipient(addr.script_pubkey(), balance.immature / 2)
         .current_height(not_yet_mature_time);
     assert_matches!(
-        builder.finish(),
+        builder.finish_with_aux_rand(&mut thread_rng()),
         Err(CreateTxError::CoinSelection(
             coin_selection::Error::InsufficientFunds {
                 needed: _,
@@ -3856,7 +3879,7 @@ fn test_spend_coinbase() {
     builder
         .add_recipient(addr.script_pubkey(), balance.confirmed / 2)
         .current_height(maturity_time);
-    builder.finish().unwrap();
+    builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 }
 
 #[test]
@@ -3870,7 +3893,7 @@ fn test_allow_dust_limit() {
     builder.add_recipient(addr.script_pubkey(), Amount::ZERO);
 
     assert_matches!(
-        builder.finish(),
+        builder.finish_with_aux_rand(&mut thread_rng()),
         Err(CreateTxError::OutputBelowDustLimit(0))
     );
 
@@ -3880,7 +3903,7 @@ fn test_allow_dust_limit() {
         .allow_dust(true)
         .add_recipient(addr.script_pubkey(), Amount::ZERO);
 
-    assert!(builder.finish().is_ok());
+    assert!(builder.finish_with_aux_rand(&mut thread_rng()).is_ok());
 }
 
 #[test]
@@ -3898,7 +3921,7 @@ fn test_fee_rate_sign_no_grinding_high_r() {
         .drain_wallet()
         .fee_rate(fee_rate)
         .add_data(&data);
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
     let (op_return_vout, _) = psbt
         .unsigned_tx
@@ -3965,7 +3988,7 @@ fn test_fee_rate_sign_grinding_low_r() {
         .drain_to(addr.script_pubkey())
         .drain_wallet()
         .fee_rate(fee_rate);
-    let mut psbt = builder.finish().unwrap();
+    let mut psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
     let fee = check_fee!(wallet, psbt);
 
     wallet
@@ -4014,7 +4037,7 @@ fn test_tx_cancellation() {
             let mut builder = $wallet.build_tx();
             builder.add_recipient(addr.script_pubkey(), Amount::from_sat(10_000));
 
-            let psbt = builder.finish().unwrap();
+            let psbt = builder.finish_with_aux_rand(&mut thread_rng()).unwrap();
 
             psbt
         }};
index 2f562837fe0bfc3d556149389d3f3c90a7f3a9a8..7ca7fdc6e0b05a73eafb258cb7f5e3cbe0ed259d 100644 (file)
@@ -8,3 +8,4 @@ bdk_wallet = { path = "../../crates/wallet" }
 bdk_electrum = { path = "../../crates/electrum" }
 bdk_file_store = { path = "../../crates/file_store" }
 anyhow = "1"
+rand = "0.8.0"
index 2adf090aa667d9194a6774d1e0161b9a0787b6d9..65aced9dc2c18d347f7f74304825abe41c003c0a 100644 (file)
@@ -14,6 +14,7 @@ use bdk_wallet::bitcoin::{Address, Amount};
 use bdk_wallet::chain::collections::HashSet;
 use bdk_wallet::{bitcoin::Network, Wallet};
 use bdk_wallet::{KeychainKind, SignOptions};
+use rand::thread_rng;
 
 fn main() -> Result<(), anyhow::Error> {
     let db_path = std::env::temp_dir().join("bdk-electrum-example");
@@ -96,7 +97,7 @@ fn main() -> Result<(), anyhow::Error> {
         .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
         .enable_rbf();
 
-    let mut psbt = tx_builder.finish()?;
+    let mut psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
     let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
     assert!(finalized);
 
index 2a71622cac1f0efccdbabd787345f327c5fbc43e..5c1745e415f8d2652347bcaf6f3c1cc6f73ca3b8 100644 (file)
@@ -11,3 +11,4 @@ bdk_esplora = { path = "../../crates/esplora", features = ["async-https"] }
 bdk_sqlite = { path = "../../crates/sqlite" }
 tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
 anyhow = "1"
+rand = "0.8.0"
index 0fd82b98594ce3e0b9f63cacf5ac8ad6089241b0..6b97af7fc2c6241d97e034f210a668481390e302 100644 (file)
@@ -5,6 +5,7 @@ use bdk_wallet::{
     bitcoin::{Address, Amount, Network, Script},
     KeychainKind, SignOptions, Wallet,
 };
+use rand::thread_rng;
 
 use bdk_sqlite::{rusqlite::Connection, Store};
 
@@ -103,7 +104,7 @@ async fn main() -> Result<(), anyhow::Error> {
         .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
         .enable_rbf();
 
-    let mut psbt = tx_builder.finish()?;
+    let mut psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
     let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
     assert!(finalized);
 
index 857660acfbc03d147cd94b071312a527ee9bfe29..88f71cdb1a8551d26235d2c60f675471cafa777f 100644 (file)
@@ -11,3 +11,4 @@ bdk_wallet = { path = "../../crates/wallet" }
 bdk_esplora = { path = "../../crates/esplora", features = ["blocking"] }
 bdk_file_store = { path = "../../crates/file_store" }
 anyhow = "1"
+rand = "0.8.0"
index 32211b04bf69c31fdc729004267e82d2b402ed38..056ed59f41ff4f6411fc9739ffddc7cc3ff1d269 100644 (file)
@@ -11,6 +11,7 @@ use bdk_wallet::{
     bitcoin::{Address, Amount, Network},
     KeychainKind, SignOptions, Wallet,
 };
+use rand::thread_rng;
 
 fn main() -> Result<(), anyhow::Error> {
     let db_path = std::env::temp_dir().join("bdk-esplora-example");
@@ -80,7 +81,7 @@ fn main() -> Result<(), anyhow::Error> {
         .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
         .enable_rbf();
 
-    let mut psbt = tx_builder.finish()?;
+    let mut psbt = tx_builder.finish_with_aux_rand(&mut thread_rng())?;
     let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
     assert!(finalized);