From 9e098a5b6d0802eb39f3e200605b8576c77030eb Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 2 Feb 2024 01:24:39 +0000 Subject: [PATCH] tx_builder: Support setting explicit nSequence for foreign inputs --- crates/bdk/src/types.rs | 13 ++++++++++++- crates/bdk/src/wallet/mod.rs | 7 +++++-- crates/bdk/src/wallet/tx_builder.rs | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/crates/bdk/src/types.rs b/crates/bdk/src/types.rs index b52635e5..5f217359 100644 --- a/crates/bdk/src/types.rs +++ b/crates/bdk/src/types.rs @@ -14,7 +14,7 @@ use core::convert::AsRef; use core::ops::Sub; use bdk_chain::ConfirmationTime; -use bitcoin::blockdata::transaction::{OutPoint, TxOut}; +use bitcoin::blockdata::transaction::{OutPoint, Sequence, TxOut}; use bitcoin::{psbt, Weight}; use serde::{Deserialize, Serialize}; @@ -197,6 +197,8 @@ pub enum Utxo { Foreign { /// The location of the output. outpoint: OutPoint, + /// The nSequence value to set for this input. + sequence: Option, /// The information about the input we require to add it to a PSBT. // Box it to stop the type being too big. psbt_input: Box, @@ -219,6 +221,7 @@ impl Utxo { Utxo::Foreign { outpoint, psbt_input, + .. } => { if let Some(prev_tx) = &psbt_input.non_witness_utxo { return &prev_tx.output[outpoint.vout as usize]; @@ -232,6 +235,14 @@ impl Utxo { } } } + + /// Get the sequence number if an explicit sequence number has to be set for this input. + pub fn sequence(&self) -> Option { + match self { + Utxo::Local(_) => None, + Utxo::Foreign { sequence, .. } => *sequence, + } + } } #[cfg(test)] diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index c6c922d5..a6b4f987 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -1400,6 +1400,7 @@ impl Wallet { } }; + // The nSequence to be by default for inputs unless an explicit sequence is specified. let n_sequence = match (params.rbf, requirements.csv) { // No RBF or CSV but there's an nLockTime, so the nSequence cannot be final (None, None) if lock_time != absolute::LockTime::ZERO => { @@ -1558,7 +1559,7 @@ impl Wallet { .map(|u| bitcoin::TxIn { previous_output: u.outpoint(), script_sig: ScriptBuf::default(), - sequence: n_sequence, + sequence: u.sequence().unwrap_or(n_sequence), witness: Witness::new(), }) .collect(); @@ -1738,6 +1739,7 @@ impl Wallet { satisfaction_weight, utxo: Utxo::Foreign { outpoint: txin.previous_output, + sequence: Some(txin.sequence), psbt_input: Box::new(psbt::Input { witness_utxo: Some(txout.clone()), non_witness_utxo: Some(prev_tx.clone()), @@ -2218,8 +2220,9 @@ impl Wallet { } } Utxo::Foreign { - psbt_input: foreign_psbt_input, outpoint, + psbt_input: foreign_psbt_input, + .. } => { let is_taproot = foreign_psbt_input .witness_utxo diff --git a/crates/bdk/src/wallet/tx_builder.rs b/crates/bdk/src/wallet/tx_builder.rs index f914aaef..4af7b3bf 100644 --- a/crates/bdk/src/wallet/tx_builder.rs +++ b/crates/bdk/src/wallet/tx_builder.rs @@ -389,6 +389,22 @@ impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D, outpoint: OutPoint, psbt_input: psbt::Input, satisfaction_weight: usize, + ) -> Result<&mut Self, AddForeignUtxoError> { + self.add_foreign_utxo_with_sequence( + outpoint, + psbt_input, + satisfaction_weight, + Sequence::MAX, + ) + } + + /// Same as [add_foreign_utxo](TxBuilder::add_foreign_utxo) but allows to set the nSequence value. + pub fn add_foreign_utxo_with_sequence( + &mut self, + outpoint: OutPoint, + psbt_input: psbt::Input, + satisfaction_weight: usize, + sequence: Sequence, ) -> Result<&mut Self, AddForeignUtxoError> { if psbt_input.witness_utxo.is_none() { match psbt_input.non_witness_utxo.as_ref() { @@ -413,6 +429,7 @@ impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D, satisfaction_weight, utxo: Utxo::Foreign { outpoint, + sequence: Some(sequence), psbt_input: Box::new(psbt_input), }, });