@@ -1690,26 +1690,24 @@ pub(super) fn calculate_change_output_value(
1690
1690
funding_inputs : & Vec < ( TxIn , TransactionU16LenLimited ) > , funding_outputs : & Vec < OutputOwned > ,
1691
1691
funding_feerate_sat_per_1000_weight : u32 , change_output_dust_limit : u64 ,
1692
1692
) -> 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
+ }
1703
1710
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
- } ) ;
1713
1711
let our_funding_outputs_weight = funding_outputs. iter ( ) . fold ( 0u64 , |weight, out| {
1714
1712
weight. saturating_add ( get_output_weight ( & out. tx_out ( ) . script_pubkey ) . to_wu ( ) )
1715
1713
} ) ;
@@ -1721,9 +1719,6 @@ fn calculate_change_output_value_prevout(
1721
1719
}
1722
1720
1723
1721
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
-
1727
1722
// Note: in case of additional outputs, they will have to be subtracted here
1728
1723
1729
1724
let total_inputs_less_fees = total_input_satoshis. saturating_sub ( fees_sats) ;
@@ -1741,34 +1736,12 @@ fn calculate_change_output_value_prevout(
1741
1736
}
1742
1737
}
1743
1738
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
-
1766
1739
#[ cfg( test) ]
1767
1740
mod tests {
1768
1741
use crate :: chain:: chaininterface:: { fee_for_weight, FEERATE_FLOOR_SATS_PER_KW } ;
1769
1742
use crate :: ln:: channel:: TOTAL_BITCOIN_SUPPLY_SATOSHIS ;
1770
1743
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 ,
1772
1745
HandleTxCompleteValue , InteractiveTxConstructor , InteractiveTxConstructorArgs ,
1773
1746
InteractiveTxMessageSend , MAX_INPUTS_OUTPUTS_COUNT , MAX_RECEIVED_TX_ADD_INPUT_COUNT ,
1774
1747
MAX_RECEIVED_TX_ADD_OUTPUT_COUNT ,
@@ -1786,7 +1759,7 @@ mod tests {
1786
1759
use bitcoin:: secp256k1:: { Keypair , PublicKey , Secp256k1 , SecretKey } ;
1787
1760
use bitcoin:: transaction:: Version ;
1788
1761
use bitcoin:: {
1789
- OutPoint , PubkeyHash , ScriptBuf , Sequence , Transaction , TxIn , TxOut , WPubkeyHash ,
1762
+ OutPoint , PubkeyHash , ScriptBuf , Sequence , Transaction , TxIn , TxOut , WPubkeyHash , Witness ,
1790
1763
} ;
1791
1764
use core:: ops:: Deref ;
1792
1765
@@ -2704,6 +2677,25 @@ mod tests {
2704
2677
TxOut { value: Amount :: from_sat( 60_000 ) , script_pubkey: ScriptBuf :: new( ) } ,
2705
2678
] ;
2706
2679
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 ) > > ( ) ;
2707
2699
let our_contributed = 110_000 ;
2708
2700
let txout = TxOut { value : Amount :: from_sat ( 128_000 ) , script_pubkey : ScriptBuf :: new ( ) } ;
2709
2701
let outputs = vec ! [ OutputOwned :: SharedControlFullyOwned ( txout) ] ;
@@ -2715,10 +2707,10 @@ mod tests {
2715
2707
let common_fees = 126 ;
2716
2708
{
2717
2709
// There is leftover for change
2718
- let res = calculate_change_output_value_prevout (
2710
+ let res = calculate_change_output_value (
2719
2711
true ,
2720
2712
our_contributed,
2721
- & input_prevouts ,
2713
+ & inputs ,
2722
2714
& outputs,
2723
2715
funding_feerate_sat_per_1000_weight,
2724
2716
300 ,
@@ -2727,10 +2719,10 @@ mod tests {
2727
2719
}
2728
2720
{
2729
2721
// There is leftover for change, without common fees
2730
- let res = calculate_change_output_value_prevout (
2722
+ let res = calculate_change_output_value (
2731
2723
false ,
2732
2724
our_contributed,
2733
- & input_prevouts ,
2725
+ & inputs ,
2734
2726
& outputs,
2735
2727
funding_feerate_sat_per_1000_weight,
2736
2728
300 ,
@@ -2739,22 +2731,16 @@ mod tests {
2739
2731
}
2740
2732
{
2741
2733
// 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 ) ;
2750
2736
assert_eq ! ( res. unwrap( ) . unwrap( ) , 14384 ) ;
2751
2737
}
2752
2738
{
2753
2739
// Insufficient inputs, no leftover
2754
- let res = calculate_change_output_value_prevout (
2740
+ let res = calculate_change_output_value (
2755
2741
false ,
2756
2742
130_000 ,
2757
- & input_prevouts ,
2743
+ & inputs ,
2758
2744
& outputs,
2759
2745
funding_feerate_sat_per_1000_weight,
2760
2746
300 ,
@@ -2763,10 +2749,10 @@ mod tests {
2763
2749
}
2764
2750
{
2765
2751
// Very small leftover
2766
- let res = calculate_change_output_value_prevout (
2752
+ let res = calculate_change_output_value (
2767
2753
false ,
2768
2754
128_100 ,
2769
- & input_prevouts ,
2755
+ & inputs ,
2770
2756
& outputs,
2771
2757
funding_feerate_sat_per_1000_weight,
2772
2758
300 ,
@@ -2775,10 +2761,10 @@ mod tests {
2775
2761
}
2776
2762
{
2777
2763
// Small leftover, but not dust
2778
- let res = calculate_change_output_value_prevout (
2764
+ let res = calculate_change_output_value (
2779
2765
false ,
2780
2766
128_100 ,
2781
- & input_prevouts ,
2767
+ & inputs ,
2782
2768
& outputs,
2783
2769
funding_feerate_sat_per_1000_weight,
2784
2770
100 ,
0 commit comments