@@ -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) ]
17671740mod 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