Skip to content

Commit a83e78d

Browse files
committed
fix Simplify calculate_change_output_value, inline prevtx check
1 parent 35ed9d9 commit a83e78d

File tree

1 file changed

+50
-64
lines changed

1 file changed

+50
-64
lines changed

lightning/src/ln/interactivetxs.rs

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,26 +1690,24 @@ pub(super) fn calculate_change_output_value(
16901690
funding_inputs: &Vec<(TxIn, TransactionU16LenLimited)>, funding_outputs: &Vec<OutputOwned>,
16911691
funding_feerate_sat_per_1000_weight: u32, change_output_dust_limit: u64,
16921692
) -> Result<Option<u64>, AbortReason> {
1693-
let funding_input_prev_outs = txouts_from_input_prev_txs(&funding_inputs)?;
1694-
calculate_change_output_value_prevout(
1695-
is_initiator,
1696-
our_contribution,
1697-
&funding_input_prev_outs,
1698-
funding_outputs,
1699-
funding_feerate_sat_per_1000_weight,
1700-
change_output_dust_limit,
1701-
)
1702-
}
1693+
// Process inputs and their prev txs:
1694+
// calculate value sum and weight sum of inputs, also perform checks
1695+
let mut total_input_satoshis = 0u64;
1696+
let mut our_funding_inputs_weight = 0u64;
1697+
for (txin, tx) in funding_inputs.iter() {
1698+
let txid = tx.as_transaction().compute_txid();
1699+
if txin.previous_output.txid != txid {
1700+
return Err(AbortReason::PrevTxOutInvalid);
1701+
}
1702+
if let Some(output) = tx.as_transaction().output.get(txin.previous_output.vout as usize) {
1703+
total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
1704+
our_funding_inputs_weight =
1705+
our_funding_inputs_weight.saturating_add(estimate_input_weight(output).to_wu());
1706+
} else {
1707+
return Err(AbortReason::PrevTxOutInvalid);
1708+
}
1709+
}
17031710

1704-
fn calculate_change_output_value_prevout(
1705-
is_initiator: bool, our_contribution: u64, funding_inputs_prev_outputs: &Vec<&TxOut>,
1706-
funding_outputs: &Vec<OutputOwned>, funding_feerate_sat_per_1000_weight: u32,
1707-
change_output_dust_limit: u64,
1708-
) -> Result<Option<u64>, AbortReason> {
1709-
let our_funding_inputs_weight =
1710-
funding_inputs_prev_outputs.iter().fold(0u64, |weight, prev_output| {
1711-
weight.saturating_add(estimate_input_weight(prev_output).to_wu())
1712-
});
17131711
let our_funding_outputs_weight = funding_outputs.iter().fold(0u64, |weight, out| {
17141712
weight.saturating_add(get_output_weight(&out.tx_out().script_pubkey).to_wu())
17151713
});
@@ -1721,9 +1719,6 @@ fn calculate_change_output_value_prevout(
17211719
}
17221720

17231721
let fees_sats = fee_for_weight(funding_feerate_sat_per_1000_weight, weight);
1724-
let total_input_satoshis: u64 =
1725-
funding_inputs_prev_outputs.iter().map(|out| out.value.to_sat()).sum();
1726-
17271722
// Note: in case of additional outputs, they will have to be subtracted here
17281723

17291724
let total_inputs_less_fees = total_input_satoshis.saturating_sub(fees_sats);
@@ -1741,34 +1736,12 @@ fn calculate_change_output_value_prevout(
17411736
}
17421737
}
17431738

1744-
/// Obtain prev outputs for each supplied input and matching transaction.
1745-
/// Will error when a prev tx does not have an output for the specified vout.
1746-
/// Also checks for matching of transaction IDs.
1747-
fn txouts_from_input_prev_txs(
1748-
inputs: &Vec<(TxIn, TransactionU16LenLimited)>,
1749-
) -> Result<Vec<&TxOut>, AbortReason> {
1750-
let mut prev_outputs: Vec<&TxOut> = Vec::with_capacity(inputs.len());
1751-
// Check that vouts exist for each TxIn in provided transactions.
1752-
for (txin, tx) in inputs.iter() {
1753-
let txid = tx.as_transaction().compute_txid();
1754-
if txin.previous_output.txid != txid {
1755-
return Err(AbortReason::PrevTxOutInvalid);
1756-
}
1757-
if let Some(output) = tx.as_transaction().output.get(txin.previous_output.vout as usize) {
1758-
prev_outputs.push(output);
1759-
} else {
1760-
return Err(AbortReason::PrevTxOutInvalid);
1761-
}
1762-
}
1763-
Ok(prev_outputs)
1764-
}
1765-
17661739
#[cfg(test)]
17671740
mod tests {
17681741
use crate::chain::chaininterface::{fee_for_weight, FEERATE_FLOOR_SATS_PER_KW};
17691742
use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS;
17701743
use crate::ln::interactivetxs::{
1771-
calculate_change_output_value_prevout, generate_holder_serial_id, AbortReason,
1744+
calculate_change_output_value, generate_holder_serial_id, AbortReason,
17721745
HandleTxCompleteValue, InteractiveTxConstructor, InteractiveTxConstructorArgs,
17731746
InteractiveTxMessageSend, MAX_INPUTS_OUTPUTS_COUNT, MAX_RECEIVED_TX_ADD_INPUT_COUNT,
17741747
MAX_RECEIVED_TX_ADD_OUTPUT_COUNT,
@@ -1786,7 +1759,7 @@ mod tests {
17861759
use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
17871760
use bitcoin::transaction::Version;
17881761
use bitcoin::{
1789-
OutPoint, PubkeyHash, ScriptBuf, Sequence, Transaction, TxIn, TxOut, WPubkeyHash,
1762+
OutPoint, PubkeyHash, ScriptBuf, Sequence, Transaction, TxIn, TxOut, WPubkeyHash, Witness,
17901763
};
17911764
use core::ops::Deref;
17921765

@@ -2704,6 +2677,25 @@ mod tests {
27042677
TxOut { value: Amount::from_sat(60_000), script_pubkey: ScriptBuf::new() },
27052678
];
27062679
let input_prevouts: Vec<&TxOut> = input_prevouts_owned.iter().collect();
2680+
let inputs = input_prevouts
2681+
.iter()
2682+
.map(|txout| {
2683+
let tx = Transaction {
2684+
input: Vec::new(),
2685+
output: vec![(*txout).clone()],
2686+
lock_time: AbsoluteLockTime::ZERO,
2687+
version: Version::TWO,
2688+
};
2689+
let txid = tx.compute_txid();
2690+
let txin = TxIn {
2691+
previous_output: OutPoint { txid, vout: 0 },
2692+
script_sig: ScriptBuf::new(),
2693+
sequence: Sequence::ZERO,
2694+
witness: Witness::new(),
2695+
};
2696+
(txin, TransactionU16LenLimited::new(tx).unwrap())
2697+
})
2698+
.collect::<Vec<(TxIn, TransactionU16LenLimited)>>();
27072699
let our_contributed = 110_000;
27082700
let txout = TxOut { value: Amount::from_sat(128_000), script_pubkey: ScriptBuf::new() };
27092701
let outputs = vec![OutputOwned::SharedControlFullyOwned(txout)];
@@ -2715,10 +2707,10 @@ mod tests {
27152707
let common_fees = 126;
27162708
{
27172709
// There is leftover for change
2718-
let res = calculate_change_output_value_prevout(
2710+
let res = calculate_change_output_value(
27192711
true,
27202712
our_contributed,
2721-
&input_prevouts,
2713+
&inputs,
27222714
&outputs,
27232715
funding_feerate_sat_per_1000_weight,
27242716
300,
@@ -2727,10 +2719,10 @@ mod tests {
27272719
}
27282720
{
27292721
// There is leftover for change, without common fees
2730-
let res = calculate_change_output_value_prevout(
2722+
let res = calculate_change_output_value(
27312723
false,
27322724
our_contributed,
2733-
&input_prevouts,
2725+
&inputs,
27342726
&outputs,
27352727
funding_feerate_sat_per_1000_weight,
27362728
300,
@@ -2739,22 +2731,16 @@ mod tests {
27392731
}
27402732
{
27412733
// Larger fee, smaller change
2742-
let res = calculate_change_output_value_prevout(
2743-
true,
2744-
our_contributed,
2745-
&input_prevouts,
2746-
&outputs,
2747-
9000,
2748-
300,
2749-
);
2734+
let res =
2735+
calculate_change_output_value(true, our_contributed, &inputs, &outputs, 9000, 300);
27502736
assert_eq!(res.unwrap().unwrap(), 14384);
27512737
}
27522738
{
27532739
// Insufficient inputs, no leftover
2754-
let res = calculate_change_output_value_prevout(
2740+
let res = calculate_change_output_value(
27552741
false,
27562742
130_000,
2757-
&input_prevouts,
2743+
&inputs,
27582744
&outputs,
27592745
funding_feerate_sat_per_1000_weight,
27602746
300,
@@ -2763,10 +2749,10 @@ mod tests {
27632749
}
27642750
{
27652751
// Very small leftover
2766-
let res = calculate_change_output_value_prevout(
2752+
let res = calculate_change_output_value(
27672753
false,
27682754
128_100,
2769-
&input_prevouts,
2755+
&inputs,
27702756
&outputs,
27712757
funding_feerate_sat_per_1000_weight,
27722758
300,
@@ -2775,10 +2761,10 @@ mod tests {
27752761
}
27762762
{
27772763
// Small leftover, but not dust
2778-
let res = calculate_change_output_value_prevout(
2764+
let res = calculate_change_output_value(
27792765
false,
27802766
128_100,
2781-
&input_prevouts,
2767+
&inputs,
27822768
&outputs,
27832769
funding_feerate_sat_per_1000_weight,
27842770
100,

0 commit comments

Comments
 (0)