@@ -1695,6 +1695,22 @@ impl InteractiveTxConstructor {
16951695/// `Err(AbortReason::InsufficientFees)`
16961696#[ allow( dead_code) ] // TODO(dual_funding): Remove once begin_interactive_funding_tx_construction() is used
16971697pub ( super ) fn calculate_change_output_value (
1698+ is_initiator : bool , our_contribution : u64 ,
1699+ funding_inputs : & Vec < ( TxIn , TransactionU16LenLimited ) > , funding_outputs : & Vec < OutputOwned > ,
1700+ funding_feerate_sat_per_1000_weight : u32 , change_output_dust_limit : u64 ,
1701+ ) -> Result < Option < u64 > , AbortReason > {
1702+ let funding_input_prev_outs = txouts_from_input_prev_txs ( & funding_inputs) ?;
1703+ calculate_change_output_value_prevout (
1704+ is_initiator,
1705+ our_contribution,
1706+ & funding_input_prev_outs,
1707+ funding_outputs,
1708+ funding_feerate_sat_per_1000_weight,
1709+ change_output_dust_limit,
1710+ )
1711+ }
1712+
1713+ fn calculate_change_output_value_prevout (
16981714 is_initiator : bool , our_contribution : u64 , funding_inputs_prev_outputs : & Vec < & TxOut > ,
16991715 funding_outputs : & Vec < OutputOwned > , funding_feerate_sat_per_1000_weight : u32 ,
17001716 change_output_dust_limit : u64 ,
@@ -1734,12 +1750,34 @@ pub(super) fn calculate_change_output_value(
17341750 }
17351751}
17361752
1753+ /// Obtain prev outputs for each supplied input and matching transaction.
1754+ /// Will error when a prev tx does not have an output for the specified vout.
1755+ /// Also checks for matching of transaction IDs.
1756+ fn txouts_from_input_prev_txs (
1757+ inputs : & Vec < ( TxIn , TransactionU16LenLimited ) > ,
1758+ ) -> Result < Vec < & TxOut > , AbortReason > {
1759+ let mut prev_outputs: Vec < & TxOut > = Vec :: with_capacity ( inputs. len ( ) ) ;
1760+ // Check that vouts exist for each TxIn in provided transactions.
1761+ for ( idx, ( txin, tx) ) in inputs. iter ( ) . enumerate ( ) {
1762+ let txid = tx. as_transaction ( ) . compute_txid ( ) ;
1763+ if txin. previous_output . txid != txid {
1764+ return Err ( AbortReason :: ProvidedInputsAndPrevtxsTxIdMismatch ( idx as u32 ) ) ;
1765+ }
1766+ if let Some ( output) = tx. as_transaction ( ) . output . get ( txin. previous_output . vout as usize ) {
1767+ prev_outputs. push ( output) ;
1768+ } else {
1769+ return Err ( AbortReason :: ProvidedInputsAndPrevtxsVoutNotFound ( idx as u32 ) ) ;
1770+ }
1771+ }
1772+ Ok ( prev_outputs)
1773+ }
1774+
17371775#[ cfg( test) ]
17381776mod tests {
17391777 use crate :: chain:: chaininterface:: { fee_for_weight, FEERATE_FLOOR_SATS_PER_KW } ;
17401778 use crate :: ln:: channel:: TOTAL_BITCOIN_SUPPLY_SATOSHIS ;
17411779 use crate :: ln:: interactivetxs:: {
1742- calculate_change_output_value , generate_holder_serial_id, AbortReason ,
1780+ calculate_change_output_value_prevout , generate_holder_serial_id, AbortReason ,
17431781 HandleTxCompleteValue , InteractiveTxConstructor , InteractiveTxConstructorArgs ,
17441782 InteractiveTxMessageSend , MAX_INPUTS_OUTPUTS_COUNT , MAX_RECEIVED_TX_ADD_INPUT_COUNT ,
17451783 MAX_RECEIVED_TX_ADD_OUTPUT_COUNT ,
@@ -2686,7 +2724,7 @@ mod tests {
26862724 let common_fees = 126 ;
26872725 {
26882726 // There is leftover for change
2689- let res = calculate_change_output_value (
2727+ let res = calculate_change_output_value_prevout (
26902728 true ,
26912729 our_contributed,
26922730 & input_prevouts,
@@ -2698,7 +2736,7 @@ mod tests {
26982736 }
26992737 {
27002738 // There is leftover for change, without common fees
2701- let res = calculate_change_output_value (
2739+ let res = calculate_change_output_value_prevout (
27022740 false ,
27032741 our_contributed,
27042742 & input_prevouts,
@@ -2710,7 +2748,7 @@ mod tests {
27102748 }
27112749 {
27122750 // Larger fee, smaller change
2713- let res = calculate_change_output_value (
2751+ let res = calculate_change_output_value_prevout (
27142752 true ,
27152753 our_contributed,
27162754 & input_prevouts,
@@ -2722,7 +2760,7 @@ mod tests {
27222760 }
27232761 {
27242762 // Insufficient inputs, no leftover
2725- let res = calculate_change_output_value (
2763+ let res = calculate_change_output_value_prevout (
27262764 false ,
27272765 130_000 ,
27282766 & input_prevouts,
@@ -2734,7 +2772,7 @@ mod tests {
27342772 }
27352773 {
27362774 // Very small leftover
2737- let res = calculate_change_output_value (
2775+ let res = calculate_change_output_value_prevout (
27382776 false ,
27392777 128_100 ,
27402778 & input_prevouts,
@@ -2746,7 +2784,7 @@ mod tests {
27462784 }
27472785 {
27482786 // Small leftover, but not dust
2749- let res = calculate_change_output_value (
2787+ let res = calculate_change_output_value_prevout (
27502788 false ,
27512789 128_100 ,
27522790 & input_prevouts,
0 commit comments