use anyhow::{anyhow, Result};
use lightning_signer::bitcoin::absolute::LockTime;
use lightning_signer::bitcoin::transaction::Version;
use lightning_signer::bitcoin::{ScriptBuf, Sequence, Transaction, TxIn, Witness};
use lightning_signer::lightning::sign::DelayedPaymentOutputDescriptor;
use lightning_signer::util::transaction_utils;
use lightning_signer::util::transaction_utils::MAX_VALUE_MSAT;
use std::collections::HashSet;
pub fn create_spending_transaction(
descriptors: &[DelayedPaymentOutputDescriptor],
output_script: ScriptBuf,
feerate_sat_per_1000_weight: u32,
) -> Result<Transaction> {
let mut input = Vec::new();
let mut input_value = 0;
let mut witness_weight = 0;
let mut output_set = HashSet::with_capacity(descriptors.len());
for descriptor in descriptors {
input.push(TxIn {
previous_output: descriptor.outpoint.into_bitcoin_outpoint(),
script_sig: ScriptBuf::new(),
sequence: Sequence(descriptor.to_self_delay as u32),
witness: Witness::default(),
});
witness_weight += DelayedPaymentOutputDescriptor::MAX_WITNESS_LENGTH;
input_value += descriptor.output.value.to_sat();
if !output_set.insert(descriptor.outpoint) {
return Err(anyhow!("duplicate"));
}
if input_value > MAX_VALUE_MSAT / 1000 {
return Err(anyhow!("overflow"));
}
}
let mut spend_tx =
Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input, output: vec![] };
transaction_utils::maybe_add_change_output(
&mut spend_tx,
input_value,
witness_weight,
feerate_sat_per_1000_weight,
output_script,
)
.map_err(|()| anyhow!("could not add change"))?;
Ok(spend_tx)
}