tx_builder: Support setting explicit nSequence for foreign inputs

This commit is contained in:
Steven Roose 2024-02-02 01:24:39 +00:00
parent c6b9ed3b76
commit 9e098a5b6d
No known key found for this signature in database
GPG Key ID: 2F2A88D7F8D68E87
3 changed files with 34 additions and 3 deletions

View File

@ -14,7 +14,7 @@ use core::convert::AsRef;
use core::ops::Sub; use core::ops::Sub;
use bdk_chain::ConfirmationTime; use bdk_chain::ConfirmationTime;
use bitcoin::blockdata::transaction::{OutPoint, TxOut}; use bitcoin::blockdata::transaction::{OutPoint, Sequence, TxOut};
use bitcoin::{psbt, Weight}; use bitcoin::{psbt, Weight};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -197,6 +197,8 @@ pub enum Utxo {
Foreign { Foreign {
/// The location of the output. /// The location of the output.
outpoint: OutPoint, outpoint: OutPoint,
/// The nSequence value to set for this input.
sequence: Option<Sequence>,
/// The information about the input we require to add it to a PSBT. /// The information about the input we require to add it to a PSBT.
// Box it to stop the type being too big. // Box it to stop the type being too big.
psbt_input: Box<psbt::Input>, psbt_input: Box<psbt::Input>,
@ -219,6 +221,7 @@ impl Utxo {
Utxo::Foreign { Utxo::Foreign {
outpoint, outpoint,
psbt_input, psbt_input,
..
} => { } => {
if let Some(prev_tx) = &psbt_input.non_witness_utxo { if let Some(prev_tx) = &psbt_input.non_witness_utxo {
return &prev_tx.output[outpoint.vout as usize]; 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<Sequence> {
match self {
Utxo::Local(_) => None,
Utxo::Foreign { sequence, .. } => *sequence,
}
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1400,6 +1400,7 @@ impl<D> Wallet<D> {
} }
}; };
// The nSequence to be by default for inputs unless an explicit sequence is specified.
let n_sequence = match (params.rbf, requirements.csv) { let n_sequence = match (params.rbf, requirements.csv) {
// No RBF or CSV but there's an nLockTime, so the nSequence cannot be final // No RBF or CSV but there's an nLockTime, so the nSequence cannot be final
(None, None) if lock_time != absolute::LockTime::ZERO => { (None, None) if lock_time != absolute::LockTime::ZERO => {
@ -1558,7 +1559,7 @@ impl<D> Wallet<D> {
.map(|u| bitcoin::TxIn { .map(|u| bitcoin::TxIn {
previous_output: u.outpoint(), previous_output: u.outpoint(),
script_sig: ScriptBuf::default(), script_sig: ScriptBuf::default(),
sequence: n_sequence, sequence: u.sequence().unwrap_or(n_sequence),
witness: Witness::new(), witness: Witness::new(),
}) })
.collect(); .collect();
@ -1738,6 +1739,7 @@ impl<D> Wallet<D> {
satisfaction_weight, satisfaction_weight,
utxo: Utxo::Foreign { utxo: Utxo::Foreign {
outpoint: txin.previous_output, outpoint: txin.previous_output,
sequence: Some(txin.sequence),
psbt_input: Box::new(psbt::Input { psbt_input: Box::new(psbt::Input {
witness_utxo: Some(txout.clone()), witness_utxo: Some(txout.clone()),
non_witness_utxo: Some(prev_tx.clone()), non_witness_utxo: Some(prev_tx.clone()),
@ -2218,8 +2220,9 @@ impl<D> Wallet<D> {
} }
} }
Utxo::Foreign { Utxo::Foreign {
psbt_input: foreign_psbt_input,
outpoint, outpoint,
psbt_input: foreign_psbt_input,
..
} => { } => {
let is_taproot = foreign_psbt_input let is_taproot = foreign_psbt_input
.witness_utxo .witness_utxo

View File

@ -389,6 +389,22 @@ impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D,
outpoint: OutPoint, outpoint: OutPoint,
psbt_input: psbt::Input, psbt_input: psbt::Input,
satisfaction_weight: usize, 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> { ) -> Result<&mut Self, AddForeignUtxoError> {
if psbt_input.witness_utxo.is_none() { if psbt_input.witness_utxo.is_none() {
match psbt_input.non_witness_utxo.as_ref() { match psbt_input.non_witness_utxo.as_ref() {
@ -413,6 +429,7 @@ impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D,
satisfaction_weight, satisfaction_weight,
utxo: Utxo::Foreign { utxo: Utxo::Foreign {
outpoint, outpoint,
sequence: Some(sequence),
psbt_input: Box::new(psbt_input), psbt_input: Box::new(psbt_input),
}, },
}); });