• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bitcoindevkit / bdk / 5834188079

pending completion
5834188079

Pull #1071

github

web-flow
Merge 68b42331c into 0ba6bbe11
Pull Request #1071: Update rust bitcoin (BDK 0.28)

563 of 563 new or added lines in 28 files covered. (100.0%)

14625 of 18342 relevant lines covered (79.74%)

9267.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.6
/src/wallet/tx_builder.rs
1
// Bitcoin Dev Kit
2
// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
3
//
4
// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
5
//
6
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9
// You may not use this file except in accordance with one or both of these
10
// licenses.
11

12
//! Transaction builder
13
//!
14
//! ## Example
15
//!
16
//! ```
17
//! # use std::str::FromStr;
18
//! # use bitcoin::*;
19
//! # use bdk::*;
20
//! # use bdk::wallet::tx_builder::CreateTx;
21
//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
22
//! # let wallet = doctest_wallet!();
23
//! // create a TxBuilder from a wallet
24
//! let mut tx_builder = wallet.build_tx();
25
//!
26
//! tx_builder
27
//!     // Create a transaction with one output to `to_address` of 50_000 satoshi
28
//!     .add_recipient(to_address.script_pubkey(), 50_000)
29
//!     // With a custom fee rate of 5.0 satoshi/vbyte
30
//!     .fee_rate(bdk::FeeRate::from_sat_per_vb(5.0))
31
//!     // Only spend non-change outputs
32
//!     .do_not_spend_change()
33
//!     // Turn on RBF signaling
34
//!     .enable_rbf();
35
//! let (psbt, tx_details) = tx_builder.finish()?;
36
//! # Ok::<(), bdk::Error>(())
37
//! ```
38

39
use std::collections::BTreeMap;
40
use std::collections::HashSet;
41
use std::default::Default;
42
use std::marker::PhantomData;
43

44
use bitcoin::psbt::{self, PartiallySignedTransaction as Psbt};
45
use bitcoin::{absolute, script::PushBytes, OutPoint, ScriptBuf, Sequence, Transaction};
46

47
use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
48
use crate::{database::BatchDatabase, Error, Utxo, Wallet};
49
use crate::{
50
    types::{FeeRate, KeychainKind, LocalUtxo, WeightedUtxo},
51
    TransactionDetails,
52
};
53
/// Context in which the [`TxBuilder`] is valid
54
pub trait TxBuilderContext: std::fmt::Debug + Default + Clone {}
55

56
/// Marker type to indicate the [`TxBuilder`] is being used to create a new transaction (as opposed
57
/// to bumping the fee of an existing one).
58
#[derive(Debug, Default, Clone)]
×
59
pub struct CreateTx;
60
impl TxBuilderContext for CreateTx {}
61

62
/// Marker type to indicate the [`TxBuilder`] is being used to bump the fee of an existing transaction.
63
#[derive(Debug, Default, Clone)]
×
64
pub struct BumpFee;
65
impl TxBuilderContext for BumpFee {}
66

67
/// A transaction builder
68
///
69
/// A `TxBuilder` is created by calling [`build_tx`] or [`build_fee_bump`] on a wallet. After
70
/// assigning it, you set options on it until finally calling [`finish`] to consume the builder and
71
/// generate the transaction.
72
///
73
/// Each option setting method on `TxBuilder` takes and returns `&mut self` so you can chain calls
74
/// as in the following example:
75
///
76
/// ```
77
/// # use bdk::*;
78
/// # use bdk::wallet::tx_builder::*;
79
/// # use bitcoin::*;
80
/// # use core::str::FromStr;
81
/// # let wallet = doctest_wallet!();
82
/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
83
/// # let addr2 = addr1.clone();
84
/// // chaining
85
/// let (psbt1, details) = {
86
///     let mut builder = wallet.build_tx();
87
///     builder
88
///         .ordering(TxOrdering::Untouched)
89
///         .add_recipient(addr1.script_pubkey(), 50_000)
90
///         .add_recipient(addr2.script_pubkey(), 50_000);
91
///     builder.finish()?
92
/// };
93
///
94
/// // non-chaining
95
/// let (psbt2, details) = {
96
///     let mut builder = wallet.build_tx();
97
///     builder.ordering(TxOrdering::Untouched);
98
///     for addr in &[addr1, addr2] {
99
///         builder.add_recipient(addr.script_pubkey(), 50_000);
100
///     }
101
///     builder.finish()?
102
/// };
103
///
104
/// assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
105
/// # Ok::<(), bdk::Error>(())
106
/// ```
107
///
108
/// At the moment [`coin_selection`] is an exception to the rule as it consumes `self`.
109
/// This means it is usually best to call [`coin_selection`] on the return value of `build_tx` before assigning it.
110
///
111
/// For further examples see [this module](super::tx_builder)'s documentation;
112
///
113
/// [`build_tx`]: Wallet::build_tx
114
/// [`build_fee_bump`]: Wallet::build_fee_bump
115
/// [`finish`]: Self::finish
116
/// [`coin_selection`]: Self::coin_selection
117
#[derive(Debug)]
×
118
pub struct TxBuilder<'a, D, Cs, Ctx> {
119
    pub(crate) wallet: &'a Wallet<D>,
120
    pub(crate) params: TxParams,
121
    pub(crate) coin_selection: Cs,
122
    pub(crate) phantom: PhantomData<Ctx>,
123
}
124

125
/// The parameters for transaction creation sans coin selection algorithm.
126
//TODO: TxParams should eventually be exposed publicly.
127
#[derive(Default, Debug, Clone)]
384✔
128
pub(crate) struct TxParams {
129
    pub(crate) recipients: Vec<(ScriptBuf, u64)>,
130
    pub(crate) drain_wallet: bool,
131
    pub(crate) drain_to: Option<ScriptBuf>,
132
    pub(crate) fee_policy: Option<FeePolicy>,
133
    pub(crate) internal_policy_path: Option<BTreeMap<String, Vec<usize>>>,
134
    pub(crate) external_policy_path: Option<BTreeMap<String, Vec<usize>>>,
135
    pub(crate) utxos: Vec<WeightedUtxo>,
136
    pub(crate) unspendable: HashSet<OutPoint>,
137
    pub(crate) manually_selected_only: bool,
138
    pub(crate) sighash: Option<psbt::PsbtSighashType>,
139
    pub(crate) ordering: TxOrdering,
140
    pub(crate) locktime: Option<absolute::LockTime>,
141
    pub(crate) rbf: Option<RbfValue>,
142
    pub(crate) version: Option<Version>,
143
    pub(crate) change_policy: ChangeSpendPolicy,
144
    pub(crate) only_witness_utxo: bool,
145
    pub(crate) add_global_xpubs: bool,
146
    pub(crate) include_output_redeem_witness_script: bool,
147
    pub(crate) bumping_fee: Option<PreviousFee>,
148
    pub(crate) current_height: Option<absolute::LockTime>,
149
    pub(crate) allow_dust: bool,
150
}
151

152
#[derive(Clone, Copy, Debug)]
×
153
pub(crate) struct PreviousFee {
154
    pub absolute: u64,
155
    pub rate: f32,
156
}
157

158
#[derive(Debug, Clone, Copy)]
×
159
pub(crate) enum FeePolicy {
160
    FeeRate(FeeRate),
161
    FeeAmount(u64),
162
}
163

164
impl std::default::Default for FeePolicy {
165
    fn default() -> Self {
×
166
        FeePolicy::FeeRate(FeeRate::default_min_relay_fee())
×
167
    }
×
168
}
169

170
impl<'a, Cs: Clone, Ctx, D> Clone for TxBuilder<'a, D, Cs, Ctx> {
171
    fn clone(&self) -> Self {
6✔
172
        TxBuilder {
6✔
173
            wallet: self.wallet,
6✔
174
            params: self.params.clone(),
6✔
175
            coin_selection: self.coin_selection.clone(),
6✔
176
            phantom: PhantomData,
6✔
177
        }
6✔
178
    }
6✔
179
}
180

181
// methods supported by both contexts, for any CoinSelectionAlgorithm
182
impl<'a, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext>
183
    TxBuilder<'a, D, Cs, Ctx>
184
{
185
    /// Set a custom fee rate
186
    pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self {
60✔
187
        self.params.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
60✔
188
        self
60✔
189
    }
60✔
190

191
    /// Set an absolute fee
192
    pub fn fee_absolute(&mut self, fee_amount: u64) -> &mut Self {
18✔
193
        self.params.fee_policy = Some(FeePolicy::FeeAmount(fee_amount));
18✔
194
        self
18✔
195
    }
18✔
196

197
    /// Set the policy path to use while creating the transaction for a given keychain.
198
    ///
199
    /// This method accepts a map where the key is the policy node id (see
200
    /// [`Policy::id`](crate::descriptor::Policy::id)) and the value is the list of the indexes of
201
    /// the items that are intended to be satisfied from the policy node (see
202
    /// [`SatisfiableItem::Thresh::items`](crate::descriptor::policy::SatisfiableItem::Thresh::items)).
203
    ///
204
    /// ## Example
205
    ///
206
    /// An example of when the policy path is needed is the following descriptor:
207
    /// `wsh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000))))`,
208
    /// derived from the miniscript policy `thresh(2,pk(A),and(pk(B),older(6)),and(pk(C),after(630000)))`.
209
    /// It declares three descriptor fragments, and at the top level it uses `thresh()` to
210
    /// ensure that at least two of them are satisfied. The individual fragments are:
211
    ///
212
    /// 1. `pk(A)`
213
    /// 2. `and(pk(B),older(6))`
214
    /// 3. `and(pk(C),after(630000))`
215
    ///
216
    /// When those conditions are combined in pairs, it's clear that the transaction needs to be created
217
    /// differently depending on how the user intends to satisfy the policy afterwards:
218
    ///
219
    /// * If fragments `1` and `2` are used, the transaction will need to use a specific
220
    ///   `n_sequence` in order to spend an `OP_CSV` branch.
221
    /// * If fragments `1` and `3` are used, the transaction will need to use a specific `locktime`
222
    ///   in order to spend an `OP_CLTV` branch.
223
    /// * If fragments `2` and `3` are used, the transaction will need both.
224
    ///
225
    /// When the spending policy is represented as a tree (see
226
    /// [`Wallet::policies`](super::Wallet::policies)), every node
227
    /// is assigned a unique identifier that can be used in the policy path to specify which of
228
    /// the node's children the user intends to satisfy: for instance, assuming the `thresh()`
229
    /// root node of this example has an id of `aabbccdd`, the policy path map would look like:
230
    ///
231
    /// `{ "aabbccdd" => [0, 1] }`
232
    ///
233
    /// where the key is the node's id, and the value is a list of the children that should be
234
    /// used, in no particular order.
235
    ///
236
    /// If a particularly complex descriptor has multiple ambiguous thresholds in its structure,
237
    /// multiple entries can be added to the map, one for each node that requires an explicit path.
238
    ///
239
    /// ```
240
    /// # use std::str::FromStr;
241
    /// # use std::collections::BTreeMap;
242
    /// # use bitcoin::*;
243
    /// # use bdk::*;
244
    /// # let to_address =
245
    /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
246
    ///     .unwrap()
247
    ///     .assume_checked();
248
    /// # let wallet = doctest_wallet!();
249
    /// let mut path = BTreeMap::new();
250
    /// path.insert("aabbccdd".to_string(), vec![0, 1]);
251
    ///
252
    /// let builder = wallet
253
    ///     .build_tx()
254
    ///     .add_recipient(to_address.script_pubkey(), 50_000)
255
    ///     .policy_path(path, KeychainKind::External);
256
    ///
257
    /// # Ok::<(), bdk::Error>(())
258
    /// ```
259
    pub fn policy_path(
16✔
260
        &mut self,
16✔
261
        policy_path: BTreeMap<String, Vec<usize>>,
16✔
262
        keychain: KeychainKind,
16✔
263
    ) -> &mut Self {
16✔
264
        let to_update = match keychain {
16✔
265
            KeychainKind::Internal => &mut self.params.internal_policy_path,
4✔
266
            KeychainKind::External => &mut self.params.external_policy_path,
12✔
267
        };
268

269
        *to_update = Some(policy_path);
16✔
270
        self
16✔
271
    }
16✔
272

273
    /// Add the list of outpoints to the internal list of UTXOs that **must** be spent.
274
    ///
275
    /// If an error occurs while adding any of the UTXOs then none of them are added and the error is returned.
276
    ///
277
    /// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
278
    /// the "utxos" and the "unspendable" list, it will be spent.
279
    pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, Error> {
26✔
280
        let utxos = outpoints
26✔
281
            .iter()
26✔
282
            .map(|outpoint| self.wallet.get_utxo(*outpoint)?.ok_or(Error::UnknownUtxo))
26✔
283
            .collect::<Result<Vec<_>, _>>()?;
26✔
284

285
        for utxo in utxos {
52✔
286
            let descriptor = self.wallet.get_descriptor_for_keychain(utxo.keychain);
26✔
287
            #[allow(deprecated)]
26✔
288
            let satisfaction_weight = descriptor.max_satisfaction_weight().unwrap();
26✔
289
            self.params.utxos.push(WeightedUtxo {
26✔
290
                satisfaction_weight,
26✔
291
                utxo: Utxo::Local(utxo),
26✔
292
            });
26✔
293
        }
26✔
294

295
        Ok(self)
26✔
296
    }
26✔
297

298
    /// Add a utxo to the internal list of utxos that **must** be spent
299
    ///
300
    /// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
301
    /// the "utxos" and the "unspendable" list, it will be spent.
302
    pub fn add_utxo(&mut self, outpoint: OutPoint) -> Result<&mut Self, Error> {
24✔
303
        self.add_utxos(&[outpoint])
24✔
304
    }
24✔
305

306
    /// Add a foreign UTXO i.e. a UTXO not owned by this wallet.
307
    ///
308
    /// At a minimum to add a foreign UTXO we need:
309
    ///
310
    /// 1. `outpoint`: To add it to the raw transaction.
311
    /// 2. `psbt_input`: To know the value.
312
    /// 3. `satisfaction_weight`: To know how much weight/vbytes the input will add to the transaction for fee calculation.
313
    ///
314
    /// There are several security concerns about adding foreign UTXOs that application
315
    /// developers should consider. First, how do you know the value of the input is correct? If a
316
    /// `non_witness_utxo` is provided in the `psbt_input` then this method implicitly verifies the
317
    /// value by checking it against the transaction. If only a `witness_utxo` is provided then this
318
    /// method doesn't verify the value but just takes it as a given -- it is up to you to check
319
    /// that whoever sent you the `input_psbt` was not lying!
320
    ///
321
    /// Secondly, you must somehow provide `satisfaction_weight` of the input. Depending on your
322
    /// application it may be important that this be known precisely. If not, a malicious
323
    /// counterparty may fool you into putting in a value that is too low, giving the transaction a
324
    /// lower than expected feerate. They could also fool you into putting a value that is too high
325
    /// causing you to pay a fee that is too high. The party who is broadcasting the transaction can
326
    /// of course check the real input weight matches the expected weight prior to broadcasting.
327
    ///
328
    /// To guarantee the `satisfaction_weight` is correct, you can require the party providing the
329
    /// `psbt_input` provide a miniscript descriptor for the input so you can check it against the
330
    /// `script_pubkey` and then ask it for the [`max_satisfaction_weight`].
331
    ///
332
    /// This is an **EXPERIMENTAL** feature, API and other major changes are expected.
333
    ///
334
    /// # Errors
335
    ///
336
    /// This method returns errors in the following circumstances:
337
    ///
338
    /// 1. The `psbt_input` does not contain a `witness_utxo` or `non_witness_utxo`.
339
    /// 2. The data in `non_witness_utxo` does not match what is in `outpoint`.
340
    ///
341
    /// Note unless you set [`only_witness_utxo`] any non-taproot `psbt_input` you pass to this
342
    /// method must have `non_witness_utxo` set otherwise you will get an error when [`finish`]
343
    /// is called.
344
    ///
345
    /// [`only_witness_utxo`]: Self::only_witness_utxo
346
    /// [`finish`]: Self::finish
347
    /// [`max_satisfaction_weight`]: miniscript::Descriptor::max_satisfaction_weight
348
    pub fn add_foreign_utxo(
16✔
349
        &mut self,
16✔
350
        outpoint: OutPoint,
16✔
351
        psbt_input: psbt::Input,
16✔
352
        satisfaction_weight: usize,
16✔
353
    ) -> Result<&mut Self, Error> {
16✔
354
        if psbt_input.witness_utxo.is_none() {
16✔
355
            match psbt_input.non_witness_utxo.as_ref() {
8✔
356
                Some(tx) => {
6✔
357
                    if tx.txid() != outpoint.txid {
6✔
358
                        return Err(Error::Generic(
2✔
359
                            "Foreign utxo outpoint does not match PSBT input".into(),
2✔
360
                        ));
2✔
361
                    }
4✔
362
                    if tx.output.len() <= outpoint.vout as usize {
4✔
363
                        return Err(Error::InvalidOutpoint(outpoint));
×
364
                    }
4✔
365
                }
366
                None => {
367
                    return Err(Error::Generic(
2✔
368
                        "Foreign utxo missing witness_utxo or non_witness_utxo".into(),
2✔
369
                    ))
2✔
370
                }
371
            }
372
        }
8✔
373

374
        self.params.utxos.push(WeightedUtxo {
12✔
375
            satisfaction_weight,
12✔
376
            utxo: Utxo::Foreign {
12✔
377
                outpoint,
12✔
378
                psbt_input: Box::new(psbt_input),
12✔
379
            },
12✔
380
        });
12✔
381

12✔
382
        Ok(self)
12✔
383
    }
16✔
384

385
    /// Only spend utxos added by [`add_utxo`].
386
    ///
387
    /// The wallet will **not** add additional utxos to the transaction even if they are needed to
388
    /// make the transaction valid.
389
    ///
390
    /// [`add_utxo`]: Self::add_utxo
391
    pub fn manually_selected_only(&mut self) -> &mut Self {
12✔
392
        self.params.manually_selected_only = true;
12✔
393
        self
12✔
394
    }
12✔
395

396
    /// Replace the internal list of unspendable utxos with a new list
397
    ///
398
    /// It's important to note that the "must-be-spent" utxos added with [`TxBuilder::add_utxo`]
399
    /// have priority over these. See the docs of the two linked methods for more details.
400
    pub fn unspendable(&mut self, unspendable: Vec<OutPoint>) -> &mut Self {
×
401
        self.params.unspendable = unspendable.into_iter().collect();
×
402
        self
×
403
    }
×
404

405
    /// Add a utxo to the internal list of unspendable utxos
406
    ///
407
    /// It's important to note that the "must-be-spent" utxos added with [`TxBuilder::add_utxo`]
408
    /// have priority over this. See the docs of the two linked methods for more details.
409
    pub fn add_unspendable(&mut self, unspendable: OutPoint) -> &mut Self {
×
410
        self.params.unspendable.insert(unspendable);
×
411
        self
×
412
    }
×
413

414
    /// Sign with a specific sig hash
415
    ///
416
    /// **Use this option very carefully**
417
    pub fn sighash(&mut self, sighash: psbt::PsbtSighashType) -> &mut Self {
8✔
418
        self.params.sighash = Some(sighash);
8✔
419
        self
8✔
420
    }
8✔
421

422
    /// Choose the ordering for inputs and outputs of the transaction
423
    pub fn ordering(&mut self, ordering: TxOrdering) -> &mut Self {
4✔
424
        self.params.ordering = ordering;
4✔
425
        self
4✔
426
    }
4✔
427

428
    /// Use a specific nLockTime while creating the transaction
429
    ///
430
    /// This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.
431
    pub fn nlocktime(&mut self, locktime: absolute::LockTime) -> &mut Self {
6✔
432
        self.params.locktime = Some(locktime);
6✔
433
        self
6✔
434
    }
6✔
435

436
    /// Build a transaction with a specific version
437
    ///
438
    /// The `version` should always be greater than `0` and greater than `1` if the wallet's
439
    /// descriptors contain an "older" (OP_CSV) operator.
440
    pub fn version(&mut self, version: i32) -> &mut Self {
6✔
441
        self.params.version = Some(Version(version));
6✔
442
        self
6✔
443
    }
6✔
444

445
    /// Do not spend change outputs
446
    ///
447
    /// This effectively adds all the change outputs to the "unspendable" list. See
448
    /// [`TxBuilder::unspendable`].
449
    pub fn do_not_spend_change(&mut self) -> &mut Self {
2✔
450
        self.params.change_policy = ChangeSpendPolicy::ChangeForbidden;
2✔
451
        self
2✔
452
    }
2✔
453

454
    /// Only spend change outputs
455
    ///
456
    /// This effectively adds all the non-change outputs to the "unspendable" list. See
457
    /// [`TxBuilder::unspendable`].
458
    pub fn only_spend_change(&mut self) -> &mut Self {
×
459
        self.params.change_policy = ChangeSpendPolicy::OnlyChange;
×
460
        self
×
461
    }
×
462

463
    /// Set a specific [`ChangeSpendPolicy`]. See [`TxBuilder::do_not_spend_change`] and
464
    /// [`TxBuilder::only_spend_change`] for some shortcuts.
465
    pub fn change_policy(&mut self, change_policy: ChangeSpendPolicy) -> &mut Self {
×
466
        self.params.change_policy = change_policy;
×
467
        self
×
468
    }
×
469

470
    /// Only Fill-in the [`psbt::Input::witness_utxo`](bitcoin::psbt::Input::witness_utxo) field when spending from
471
    /// SegWit descriptors.
472
    ///
473
    /// This reduces the size of the PSBT, but some signers might reject them due to the lack of
474
    /// the `non_witness_utxo`.
475
    pub fn only_witness_utxo(&mut self) -> &mut Self {
6✔
476
        self.params.only_witness_utxo = true;
6✔
477
        self
6✔
478
    }
6✔
479

480
    /// Fill-in the [`psbt::Output::redeem_script`](bitcoin::psbt::Output::redeem_script) and
481
    /// [`psbt::Output::witness_script`](bitcoin::psbt::Output::witness_script) fields.
482
    ///
483
    /// This is useful for signers which always require it, like ColdCard hardware wallets.
484
    pub fn include_output_redeem_witness_script(&mut self) -> &mut Self {
4✔
485
        self.params.include_output_redeem_witness_script = true;
4✔
486
        self
4✔
487
    }
4✔
488

489
    /// Fill-in the `PSBT_GLOBAL_XPUB` field with the extended keys contained in both the external
490
    /// and internal descriptors
491
    ///
492
    /// This is useful for offline signers that take part to a multisig. Some hardware wallets like
493
    /// BitBox and ColdCard are known to require this.
494
    pub fn add_global_xpubs(&mut self) -> &mut Self {
6✔
495
        self.params.add_global_xpubs = true;
6✔
496
        self
6✔
497
    }
6✔
498

499
    /// Spend all the available inputs. This respects filters like [`TxBuilder::unspendable`] and the change policy.
500
    pub fn drain_wallet(&mut self) -> &mut Self {
84✔
501
        self.params.drain_wallet = true;
84✔
502
        self
84✔
503
    }
84✔
504

505
    /// Choose the coin selection algorithm
506
    ///
507
    /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
508
    ///
509
    /// Note that this function consumes the builder and returns it so it is usually best to put this as the first call on the builder.
510
    pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
×
511
        self,
×
512
        coin_selection: P,
×
513
    ) -> TxBuilder<'a, D, P, Ctx> {
×
514
        TxBuilder {
×
515
            wallet: self.wallet,
×
516
            params: self.params,
×
517
            coin_selection,
×
518
            phantom: PhantomData,
×
519
        }
×
520
    }
×
521

522
    /// Finish building the transaction.
523
    ///
524
    /// Returns the [`BIP174`] "PSBT" and summary details about the transaction.
525
    ///
526
    /// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
527
    pub fn finish(self) -> Result<(Psbt, TransactionDetails), Error> {
376✔
528
        self.wallet.create_tx(self.coin_selection, self.params)
376✔
529
    }
376✔
530

531
    /// Enable signaling RBF
532
    ///
533
    /// This will use the default nSequence value of `0xFFFFFFFD`.
534
    pub fn enable_rbf(&mut self) -> &mut Self {
66✔
535
        self.params.rbf = Some(RbfValue::Default);
66✔
536
        self
66✔
537
    }
66✔
538

539
    /// Enable signaling RBF with a specific nSequence value
540
    ///
541
    /// This can cause conflicts if the wallet's descriptors contain an "older" (OP_CSV) operator
542
    /// and the given `nsequence` is lower than the CSV value.
543
    ///
544
    /// If the `nsequence` is higher than `0xFFFFFFFD` an error will be thrown, since it would not
545
    /// be a valid nSequence to signal RBF.
546
    pub fn enable_rbf_with_sequence(&mut self, nsequence: Sequence) -> &mut Self {
6✔
547
        self.params.rbf = Some(RbfValue::Value(nsequence));
6✔
548
        self
6✔
549
    }
6✔
550

551
    /// Set the current blockchain height.
552
    ///
553
    /// This will be used to:
554
    /// 1. Set the nLockTime for preventing fee sniping.
555
    /// **Note**: This will be ignored if you manually specify a nlocktime using [`TxBuilder::nlocktime`].
556
    /// 2. Decide whether coinbase outputs are mature or not. If the coinbase outputs are not
557
    ///    mature at `current_height`, we ignore them in the coin selection.
558
    ///    If you want to create a transaction that spends immature coinbase inputs, manually
559
    ///    add them using [`TxBuilder::add_utxos`].
560
    ///
561
    /// In both cases, if you don't provide a current height, we use the last sync height.
562
    pub fn current_height(&mut self, height: u32) -> &mut Self {
10✔
563
        self.params.current_height =
10✔
564
            Some(absolute::LockTime::from_height(height).expect("Invalid height"));
10✔
565
        self
10✔
566
    }
10✔
567

568
    /// Set whether or not the dust limit is checked.
569
    ///
570
    /// **Note**: by avoiding a dust limit check you may end up with a transaction that is non-standard.
571
    pub fn allow_dust(&mut self, allow_dust: bool) -> &mut Self {
2✔
572
        self.params.allow_dust = allow_dust;
2✔
573
        self
2✔
574
    }
2✔
575
}
576

577
impl<'a, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, D, Cs, CreateTx> {
578
    /// Replace the recipients already added with a new list
579
    pub fn set_recipients(&mut self, recipients: Vec<(ScriptBuf, u64)>) -> &mut Self {
×
580
        self.params.recipients = recipients;
×
581
        self
×
582
    }
×
583

584
    /// Add a recipient to the internal list
585
    pub fn add_recipient(&mut self, script_pubkey: ScriptBuf, amount: u64) -> &mut Self {
234✔
586
        self.params.recipients.push((script_pubkey, amount));
234✔
587
        self
234✔
588
    }
234✔
589

590
    /// Add data as an output, using OP_RETURN
591
    pub fn add_data<T: AsRef<PushBytes>>(&mut self, data: &T) -> &mut Self {
6✔
592
        let script = ScriptBuf::new_op_return(data);
6✔
593
        self.add_recipient(script, 0u64);
6✔
594
        self
6✔
595
    }
6✔
596

597
    /// Sets the address to *drain* excess coins to.
598
    ///
599
    /// Usually, when there are excess coins they are sent to a change address generated by the
600
    /// wallet. This option replaces the usual change address with an arbitrary `script_pubkey` of
601
    /// your choosing. Just as with a change output, if the drain output is not needed (the excess
602
    /// coins are too small) it will not be included in the resulting transaction. The only
603
    /// difference is that it is valid to use `drain_to` without setting any ordinary recipients
604
    /// with [`add_recipient`] (but it is perfectly fine to add recipients as well).
605
    ///
606
    /// If you choose not to set any recipients, you should either provide the utxos that the
607
    /// transaction should spend via [`add_utxos`], or set [`drain_wallet`] to spend all of them.
608
    ///
609
    /// When bumping the fees of a transaction made with this option, you probably want to
610
    /// use [`allow_shrinking`] to allow this output to be reduced to pay for the extra fees.
611
    ///
612
    /// # Example
613
    ///
614
    /// `drain_to` is very useful for draining all the coins in a wallet with [`drain_wallet`] to a
615
    /// single address.
616
    ///
617
    /// ```
618
    /// # use std::str::FromStr;
619
    /// # use bitcoin::*;
620
    /// # use bdk::*;
621
    /// # use bdk::wallet::tx_builder::CreateTx;
622
    /// # let to_address =
623
    /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
624
    ///     .unwrap()
625
    ///     .assume_checked();
626
    /// # let wallet = doctest_wallet!();
627
    /// let mut tx_builder = wallet.build_tx();
628
    ///
629
    /// tx_builder
630
    ///     // Spend all outputs in this wallet.
631
    ///     .drain_wallet()
632
    ///     // Send the excess (which is all the coins minus the fee) to this address.
633
    ///     .drain_to(to_address.script_pubkey())
634
    ///     .fee_rate(bdk::FeeRate::from_sat_per_vb(5.0))
635
    ///     .enable_rbf();
636
    /// let (psbt, tx_details) = tx_builder.finish()?;
637
    /// # Ok::<(), bdk::Error>(())
638
    /// ```
639
    ///
640
    /// [`allow_shrinking`]: Self::allow_shrinking
641
    /// [`add_recipient`]: Self::add_recipient
642
    /// [`add_utxos`]: Self::add_utxos
643
    /// [`drain_wallet`]: Self::drain_wallet
644
    pub fn drain_to(&mut self, script_pubkey: ScriptBuf) -> &mut Self {
92✔
645
        self.params.drain_to = Some(script_pubkey);
92✔
646
        self
92✔
647
    }
92✔
648
}
649

650
// methods supported only by bump_fee
651
impl<'a, D: BatchDatabase> TxBuilder<'a, D, DefaultCoinSelectionAlgorithm, BumpFee> {
652
    /// Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this
653
    /// `script_pubkey` in order to bump the transaction fee. Without specifying this the wallet
654
    /// will attempt to find a change output to shrink instead.
655
    ///
656
    /// **Note** that the output may shrink to below the dust limit and therefore be removed. If it is
657
    /// preserved then it is currently not guaranteed to be in the same position as it was
658
    /// originally.
659
    ///
660
    /// Returns an `Err` if `script_pubkey` can't be found among the recipients of the
661
    /// transaction we are bumping.
662
    pub fn allow_shrinking(&mut self, script_pubkey: ScriptBuf) -> Result<&mut Self, Error> {
8✔
663
        match self
8✔
664
            .params
8✔
665
            .recipients
8✔
666
            .iter()
8✔
667
            .position(|(recipient_script, _)| *recipient_script == script_pubkey)
8✔
668
        {
669
            Some(position) => {
8✔
670
                self.params.recipients.remove(position);
8✔
671
                self.params.drain_to = Some(script_pubkey);
8✔
672
                Ok(self)
8✔
673
            }
674
            None => Err(Error::Generic(format!(
×
675
                "{} was not in the original transaction",
×
676
                script_pubkey
×
677
            ))),
×
678
        }
679
    }
8✔
680
}
681

682
/// Ordering of the transaction's inputs and outputs
683
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
6✔
684
pub enum TxOrdering {
685
    /// Randomized (default)
686
    Shuffle,
687
    /// Unchanged
688
    Untouched,
689
    /// BIP69 / Lexicographic
690
    Bip69Lexicographic,
691
}
692

693
impl Default for TxOrdering {
694
    fn default() -> Self {
506✔
695
        TxOrdering::Shuffle
506✔
696
    }
506✔
697
}
698

699
impl TxOrdering {
700
    /// Sort transaction inputs and outputs by [`TxOrdering`] variant
701
    pub fn sort_tx(&self, tx: &mut Transaction) {
445✔
702
        match self {
445✔
703
            TxOrdering::Untouched => {}
34✔
704
            TxOrdering::Shuffle => {
407✔
705
                use rand::seq::SliceRandom;
407✔
706
                #[cfg(test)]
407✔
707
                use rand::SeedableRng;
407✔
708

407✔
709
                #[cfg(not(test))]
407✔
710
                let mut rng = rand::thread_rng();
407✔
711
                #[cfg(test)]
407✔
712
                let mut rng = rand::rngs::StdRng::seed_from_u64(12345);
407✔
713

407✔
714
                tx.output.shuffle(&mut rng);
407✔
715
            }
407✔
716
            TxOrdering::Bip69Lexicographic => {
4✔
717
                tx.input.sort_unstable_by_key(|txin| {
14✔
718
                    (txin.previous_output.txid, txin.previous_output.vout)
12✔
719
                });
14✔
720
                tx.output
4✔
721
                    .sort_unstable_by_key(|txout| (txout.value, txout.script_pubkey.clone()));
26✔
722
            }
4✔
723
        }
724
    }
445✔
725
}
726

727
/// Transaction version
728
///
729
/// Has a default value of `1`
730
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
×
731
pub(crate) struct Version(pub(crate) i32);
732

733
impl Default for Version {
734
    fn default() -> Self {
2✔
735
        Version(1)
2✔
736
    }
2✔
737
}
738

739
/// RBF nSequence value
740
///
741
/// Has a default value of `0xFFFFFFFD`
742
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
×
743
pub(crate) enum RbfValue {
744
    Default,
745
    Value(Sequence),
746
}
747

748
impl RbfValue {
749
    pub(crate) fn get_value(&self) -> Sequence {
96✔
750
        match self {
96✔
751
            RbfValue::Default => Sequence::ENABLE_RBF_NO_LOCKTIME,
94✔
752
            RbfValue::Value(v) => *v,
2✔
753
        }
754
    }
96✔
755
}
756

757
/// Policy regarding the use of change outputs when creating a transaction
758
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
818✔
759
pub enum ChangeSpendPolicy {
760
    /// Use both change and non-change outputs (default)
761
    ChangeAllowed,
762
    /// Only use change outputs (see [`TxBuilder::only_spend_change`])
763
    OnlyChange,
764
    /// Only use non-change outputs (see [`TxBuilder::do_not_spend_change`])
765
    ChangeForbidden,
766
}
767

768
impl Default for ChangeSpendPolicy {
769
    fn default() -> Self {
506✔
770
        ChangeSpendPolicy::ChangeAllowed
506✔
771
    }
506✔
772
}
773

774
impl ChangeSpendPolicy {
775
    pub(crate) fn is_satisfied_by(&self, utxo: &LocalUtxo) -> bool {
479✔
776
        match self {
479✔
777
            ChangeSpendPolicy::ChangeAllowed => true,
456✔
778
            ChangeSpendPolicy::OnlyChange => utxo.keychain == KeychainKind::Internal,
4✔
779
            ChangeSpendPolicy::ChangeForbidden => utxo.keychain == KeychainKind::External,
19✔
780
        }
781
    }
479✔
782
}
783

784
#[cfg(test)]
785
mod test {
786
    const ORDERING_TEST_TX: &str = "0200000003c26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f54\
787
                                    85d1fd600f0100000000ffffffffc26f3eb7932f7acddc5ddd26602b77e75160\
788
                                    79b03090a16e2c2f5485d1fd600f0000000000ffffffff571fb3e02278217852\
789
                                    dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e0500000000ffffffff\
790
                                    03e80300000000000002aaeee80300000000000001aa200300000000000001ff\
791
                                    00000000";
792
    macro_rules! ordering_test_tx {
793
        () => {
794
            deserialize::<bitcoin::Transaction>(&Vec::<u8>::from_hex(ORDERING_TEST_TX).unwrap())
795
                .unwrap()
796
        };
797
    }
798

799
    use bitcoin::consensus::deserialize;
800
    use bitcoin::hashes::hex::FromHex;
801
    use std::str::FromStr;
802

803
    use super::*;
804

805
    #[test]
2✔
806
    fn test_output_ordering_default_shuffle() {
2✔
807
        assert_eq!(TxOrdering::default(), TxOrdering::Shuffle);
2✔
808
    }
2✔
809

810
    #[test]
2✔
811
    fn test_output_ordering_untouched() {
2✔
812
        let original_tx = ordering_test_tx!();
2✔
813
        let mut tx = original_tx.clone();
2✔
814

2✔
815
        TxOrdering::Untouched.sort_tx(&mut tx);
2✔
816

2✔
817
        assert_eq!(original_tx, tx);
2✔
818
    }
2✔
819

820
    #[test]
2✔
821
    fn test_output_ordering_shuffle() {
2✔
822
        let original_tx = ordering_test_tx!();
2✔
823
        let mut tx = original_tx.clone();
2✔
824

2✔
825
        TxOrdering::Shuffle.sort_tx(&mut tx);
2✔
826

2✔
827
        assert_eq!(original_tx.input, tx.input);
2✔
828
        assert_ne!(original_tx.output, tx.output);
2✔
829
    }
2✔
830

831
    #[test]
2✔
832
    fn test_output_ordering_bip69() {
2✔
833
        let original_tx = ordering_test_tx!();
2✔
834
        let mut tx = original_tx;
2✔
835

2✔
836
        TxOrdering::Bip69Lexicographic.sort_tx(&mut tx);
2✔
837

2✔
838
        assert_eq!(
2✔
839
            tx.input[0].previous_output,
2✔
840
            bitcoin::OutPoint::from_str(
2✔
841
                "0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57:5"
2✔
842
            )
2✔
843
            .unwrap()
2✔
844
        );
2✔
845
        assert_eq!(
2✔
846
            tx.input[1].previous_output,
2✔
847
            bitcoin::OutPoint::from_str(
2✔
848
                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:0"
2✔
849
            )
2✔
850
            .unwrap()
2✔
851
        );
2✔
852
        assert_eq!(
2✔
853
            tx.input[2].previous_output,
2✔
854
            bitcoin::OutPoint::from_str(
2✔
855
                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:1"
2✔
856
            )
2✔
857
            .unwrap()
2✔
858
        );
2✔
859

860
        assert_eq!(tx.output[0].value, 800);
2✔
861
        assert_eq!(tx.output[1].script_pubkey, ScriptBuf::from(vec![0xAA]));
2✔
862
        assert_eq!(
2✔
863
            tx.output[2].script_pubkey,
2✔
864
            ScriptBuf::from(vec![0xAA, 0xEE])
2✔
865
        );
2✔
866
    }
2✔
867

868
    fn get_test_utxos() -> Vec<LocalUtxo> {
6✔
869
        use bitcoin::hashes::Hash;
6✔
870

6✔
871
        vec![
6✔
872
            LocalUtxo {
6✔
873
                outpoint: OutPoint {
6✔
874
                    txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
6✔
875
                    vout: 0,
6✔
876
                },
6✔
877
                txout: Default::default(),
6✔
878
                keychain: KeychainKind::External,
6✔
879
                is_spent: false,
6✔
880
            },
6✔
881
            LocalUtxo {
6✔
882
                outpoint: OutPoint {
6✔
883
                    txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
6✔
884
                    vout: 1,
6✔
885
                },
6✔
886
                txout: Default::default(),
6✔
887
                keychain: KeychainKind::Internal,
6✔
888
                is_spent: false,
6✔
889
            },
6✔
890
        ]
6✔
891
    }
6✔
892

893
    #[test]
2✔
894
    fn test_change_spend_policy_default() {
2✔
895
        let change_spend_policy = ChangeSpendPolicy::default();
2✔
896
        let filtered = get_test_utxos()
2✔
897
            .into_iter()
2✔
898
            .filter(|u| change_spend_policy.is_satisfied_by(u))
5✔
899
            .count();
2✔
900

2✔
901
        assert_eq!(filtered, 2);
2✔
902
    }
2✔
903

904
    #[test]
2✔
905
    fn test_change_spend_policy_no_internal() {
2✔
906
        let change_spend_policy = ChangeSpendPolicy::ChangeForbidden;
2✔
907
        let filtered = get_test_utxos()
2✔
908
            .into_iter()
2✔
909
            .filter(|u| change_spend_policy.is_satisfied_by(u))
5✔
910
            .collect::<Vec<_>>();
2✔
911

2✔
912
        assert_eq!(filtered.len(), 1);
2✔
913
        assert_eq!(filtered[0].keychain, KeychainKind::External);
2✔
914
    }
2✔
915

916
    #[test]
2✔
917
    fn test_change_spend_policy_only_internal() {
2✔
918
        let change_spend_policy = ChangeSpendPolicy::OnlyChange;
2✔
919
        let filtered = get_test_utxos()
2✔
920
            .into_iter()
2✔
921
            .filter(|u| change_spend_policy.is_satisfied_by(u))
5✔
922
            .collect::<Vec<_>>();
2✔
923

2✔
924
        assert_eq!(filtered.len(), 1);
2✔
925
        assert_eq!(filtered[0].keychain, KeychainKind::Internal);
2✔
926
    }
2✔
927

928
    #[test]
2✔
929
    fn test_default_tx_version_1() {
2✔
930
        let version = Version::default();
2✔
931
        assert_eq!(version.0, 1);
2✔
932
    }
2✔
933
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc