spend: don't use database's Coin type
We could use a trait but instead there is just a couple fields we need so simply copy them over.
This commit is contained in:
parent
08ce0ad1d7
commit
c63a120794
@ -202,6 +202,21 @@ fn unsigned_tx_max_vbytes(tx: &bitcoin::Transaction, max_sat_weight: u64) -> u64
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn coin_to_candidate(
|
||||
coin: &Coin,
|
||||
must_select: bool,
|
||||
sequence: Option<bitcoin::Sequence>,
|
||||
) -> CandidateCoin {
|
||||
CandidateCoin {
|
||||
outpoint: coin.outpoint,
|
||||
amount: coin.amount,
|
||||
deriv_index: coin.derivation_index,
|
||||
is_change: coin.is_change,
|
||||
must_select,
|
||||
sequence,
|
||||
}
|
||||
}
|
||||
|
||||
impl DaemonControl {
|
||||
// Get the derived descriptor for this coin
|
||||
fn derived_desc(&self, coin: &Coin) -> descriptors::DerivedSinglePathLianaDesc {
|
||||
@ -472,10 +487,8 @@ impl DaemonControl {
|
||||
db_conn
|
||||
.coins(&[CoinStatus::Confirmed], &[])
|
||||
.into_values()
|
||||
.map(|c| CandidateCoin {
|
||||
coin: c,
|
||||
must_select: false, // No coin is mandatory.
|
||||
sequence: None, // No specific nSequence is required.
|
||||
.map(|c| {
|
||||
coin_to_candidate(&c, /*must_select=*/ false, /*sequence=*/ None)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
@ -492,11 +505,7 @@ impl DaemonControl {
|
||||
}
|
||||
coins
|
||||
.into_values()
|
||||
.map(|c| CandidateCoin {
|
||||
coin: c,
|
||||
must_select: true, // All coins must be selected.
|
||||
sequence: None, // No specific nSequence is required.
|
||||
})
|
||||
.map(|c| coin_to_candidate(&c, /*must_select=*/ true, /*sequence=*/ None))
|
||||
.collect()
|
||||
};
|
||||
|
||||
@ -792,10 +801,8 @@ impl DaemonControl {
|
||||
// transaction in this way, then we set candidates in the same way as for the `!is_cancel` case.
|
||||
let mut candidate_coins: Vec<CandidateCoin> = prev_coins
|
||||
.values()
|
||||
.map(|c| CandidateCoin {
|
||||
coin: *c,
|
||||
must_select: !is_cancel,
|
||||
sequence: None, // No specific nSequence is required.
|
||||
.map(|c| {
|
||||
coin_to_candidate(c, /*must_select=*/ !is_cancel, /*sequence=*/ None)
|
||||
})
|
||||
.collect();
|
||||
let confirmed_cands: Vec<CandidateCoin> = db_conn
|
||||
@ -805,11 +812,9 @@ impl DaemonControl {
|
||||
// Make sure we don't have duplicate candidates in case any of the coins are not
|
||||
// currently set as spending in the DB (and are therefore still confirmed).
|
||||
if !prev_coins.contains_key(&c.outpoint) {
|
||||
Some(CandidateCoin {
|
||||
coin: c,
|
||||
must_select: false,
|
||||
sequence: None, // No specific nSequence is required.
|
||||
})
|
||||
Some(coin_to_candidate(
|
||||
&c, /*must_select=*/ false, /*sequence=*/ None,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -992,11 +997,11 @@ impl DaemonControl {
|
||||
.map(|b| current_height + 1 >= b.height + height_delta)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Some(CandidateCoin {
|
||||
coin: c,
|
||||
must_select: true, // All coins must be selected.
|
||||
sequence: Some(bitcoin::Sequence::from_height(timelock)),
|
||||
})
|
||||
Some(coin_to_candidate(
|
||||
&c,
|
||||
/*must_select=*/ true,
|
||||
/*sequence=*/ Some(bitcoin::Sequence::from_height(timelock)),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
27
src/spend.rs
27
src/spend.rs
@ -1,4 +1,4 @@
|
||||
use crate::{database::Coin, descriptors};
|
||||
use crate::descriptors;
|
||||
|
||||
use std::{collections::BTreeMap, convert::TryInto, fmt};
|
||||
|
||||
@ -166,8 +166,14 @@ fn sanity_check_psbt(
|
||||
/// A candidate for coin selection when creating a transaction.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct CandidateCoin {
|
||||
/// The candidate coin.
|
||||
pub coin: Coin,
|
||||
/// Unique identifier of this coin.
|
||||
pub outpoint: bitcoin::OutPoint,
|
||||
/// The value of this coin.
|
||||
pub amount: bitcoin::Amount,
|
||||
/// The derivation index used to generate the scriptpubkey of this coin.
|
||||
pub deriv_index: bip32::ChildNumber,
|
||||
/// Whether this coin pays to a scriptpubkey derived from the internal keychain.
|
||||
pub is_change: bool,
|
||||
/// Whether or not this coin must be selected by the coin selection algorithm.
|
||||
pub must_select: bool,
|
||||
/// The nSequence field to set for an input spending this coin.
|
||||
@ -254,7 +260,7 @@ fn select_coins_for_spend(
|
||||
.iter()
|
||||
.map(|cand| Candidate {
|
||||
input_count: 1,
|
||||
value: cand.coin.amount.to_sat(),
|
||||
value: cand.amount.to_sat(),
|
||||
weight: max_input_weight,
|
||||
is_segwit: true, // We only support receiving on Segwit scripts.
|
||||
})
|
||||
@ -351,14 +357,14 @@ fn select_coins_for_spend(
|
||||
fn derived_desc(
|
||||
secp: &secp256k1::Secp256k1<secp256k1::VerifyOnly>,
|
||||
desc: &descriptors::LianaDescriptor,
|
||||
coin: &Coin,
|
||||
coin: &CandidateCoin,
|
||||
) -> descriptors::DerivedSinglePathLianaDesc {
|
||||
let desc = if coin.is_change {
|
||||
desc.change_descriptor()
|
||||
} else {
|
||||
desc.receive_descriptor()
|
||||
};
|
||||
desc.derive(coin.derivation_index, secp)
|
||||
desc.derive(coin.deriv_index, secp)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@ -547,25 +553,24 @@ pub fn create_spend(
|
||||
// Iterate through selected coins and add necessary information to the PSBT inputs.
|
||||
let mut psbt_ins = Vec::with_capacity(selected_coins.len());
|
||||
for cand in &selected_coins {
|
||||
let coin = &cand.coin;
|
||||
let sequence = cand
|
||||
.sequence
|
||||
.unwrap_or(bitcoin::Sequence::ENABLE_RBF_NO_LOCKTIME);
|
||||
tx.input.push(bitcoin::TxIn {
|
||||
previous_output: coin.outpoint,
|
||||
previous_output: cand.outpoint,
|
||||
sequence,
|
||||
// TODO: once we move to Taproot, anti-fee-sniping using nSequence
|
||||
..bitcoin::TxIn::default()
|
||||
});
|
||||
|
||||
// Populate the PSBT input with the information needed by signers.
|
||||
let coin_desc = derived_desc(secp, main_descriptor, coin);
|
||||
let coin_desc = derived_desc(secp, main_descriptor, cand);
|
||||
let witness_script = Some(coin_desc.witness_script());
|
||||
let witness_utxo = Some(bitcoin::TxOut {
|
||||
value: coin.amount.to_sat(),
|
||||
value: cand.amount.to_sat(),
|
||||
script_pubkey: coin_desc.script_pubkey(),
|
||||
});
|
||||
let non_witness_utxo = tx_getter.get_tx(&coin.outpoint.txid);
|
||||
let non_witness_utxo = tx_getter.get_tx(&cand.outpoint.txid);
|
||||
let bip32_derivation = coin_desc.bip32_derivations();
|
||||
psbt_ins.push(PsbtIn {
|
||||
witness_script,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user