@@ -2337,22 +2337,23 @@ impl InteractiveTxConstructor {
23372337pub ( super ) fn calculate_change_output_value (
23382338 context : & FundingNegotiationContext , is_splice : bool , shared_output_funding_script : & ScriptBuf ,
23392339 change_output_dust_limit : u64 ,
2340- ) -> Result < Option < u64 > , AbortReason > {
2340+ ) -> Result < Option < Amount > , AbortReason > {
23412341 assert ! ( context. our_funding_contribution > SignedAmount :: ZERO ) ;
2342- let our_funding_contribution_satoshis = context. our_funding_contribution . to_sat ( ) as u64 ;
2342+ let our_funding_contribution = context. our_funding_contribution . to_unsigned ( ) . unwrap ( ) ;
23432343
2344- let mut total_input_satoshis = 0u64 ;
2344+ let mut total_input_value = Amount :: ZERO ;
23452345 let mut our_funding_inputs_weight = 0u64 ;
23462346 for FundingTxInput { utxo, .. } in context. our_funding_inputs . iter ( ) {
2347- total_input_satoshis = total_input_satoshis . saturating_add ( utxo. output . value . to_sat ( ) ) ;
2347+ total_input_value = total_input_value . checked_add ( utxo. output . value ) . unwrap_or ( Amount :: MAX ) ;
23482348
23492349 let weight = BASE_INPUT_WEIGHT + utxo. satisfaction_weight ;
23502350 our_funding_inputs_weight = our_funding_inputs_weight. saturating_add ( weight) ;
23512351 }
23522352
23532353 let funding_outputs = & context. our_funding_outputs ;
2354- let total_output_satoshis =
2355- funding_outputs. iter ( ) . fold ( 0u64 , |total, out| total. saturating_add ( out. value . to_sat ( ) ) ) ;
2354+ let total_output_value = funding_outputs
2355+ . iter ( )
2356+ . fold ( Amount :: ZERO , |total, out| total. checked_add ( out. value ) . unwrap_or ( Amount :: MAX ) ) ;
23562357 let our_funding_outputs_weight = funding_outputs. iter ( ) . fold ( 0u64 , |weight, out| {
23572358 weight. saturating_add ( get_output_weight ( & out. script_pubkey ) . to_wu ( ) )
23582359 } ) ;
@@ -2376,15 +2377,22 @@ pub(super) fn calculate_change_output_value(
23762377 }
23772378 }
23782379
2379- let fees_sats = fee_for_weight ( context. funding_feerate_sat_per_1000_weight , weight) ;
2380- let net_total_less_fees =
2381- total_input_satoshis. saturating_sub ( total_output_satoshis) . saturating_sub ( fees_sats) ;
2382- if net_total_less_fees < our_funding_contribution_satoshis {
2380+ let contributed_fees =
2381+ Amount :: from_sat ( fee_for_weight ( context. funding_feerate_sat_per_1000_weight , weight) ) ;
2382+ let net_total_less_fees = total_input_value
2383+ . checked_sub ( total_output_value)
2384+ . unwrap_or ( Amount :: ZERO )
2385+ . checked_sub ( contributed_fees)
2386+ . unwrap_or ( Amount :: ZERO ) ;
2387+ if net_total_less_fees < our_funding_contribution {
23832388 // Not enough to cover contribution plus fees
23842389 return Err ( AbortReason :: InsufficientFees ) ;
23852390 }
2386- let remaining_value = net_total_less_fees. saturating_sub ( our_funding_contribution_satoshis) ;
2387- if remaining_value < change_output_dust_limit {
2391+
2392+ let remaining_value = net_total_less_fees
2393+ . checked_sub ( our_funding_contribution)
2394+ . expect ( "remaining_value should not be negative" ) ;
2395+ if remaining_value. to_sat ( ) < change_output_dust_limit {
23882396 // Enough to cover contribution plus fees, but leftover is below dust limit; no change
23892397 Ok ( None )
23902398 } else {
@@ -3440,14 +3448,14 @@ mod tests {
34403448 total_inputs - total_outputs - context. our_funding_contribution . to_unsigned ( ) . unwrap ( ) ;
34413449 assert_eq ! (
34423450 calculate_change_output_value( & context, false , & ScriptBuf :: new( ) , 300 ) ,
3443- Ok ( Some ( ( gross_change - fees - common_fees) . to_sat ( ) ) ) ,
3451+ Ok ( Some ( gross_change - fees - common_fees) ) ,
34443452 ) ;
34453453
34463454 // There is leftover for change, without common fees
34473455 let context = FundingNegotiationContext { is_initiator : false , ..context } ;
34483456 assert_eq ! (
34493457 calculate_change_output_value( & context, false , & ScriptBuf :: new( ) , 300 ) ,
3450- Ok ( Some ( ( gross_change - fees) . to_sat ( ) ) ) ,
3458+ Ok ( Some ( gross_change - fees) ) ,
34513459 ) ;
34523460
34533461 // Insufficient inputs, no leftover
@@ -3482,7 +3490,7 @@ mod tests {
34823490 total_inputs - total_outputs - context. our_funding_contribution . to_unsigned ( ) . unwrap ( ) ;
34833491 assert_eq ! (
34843492 calculate_change_output_value( & context, false , & ScriptBuf :: new( ) , 100 ) ,
3485- Ok ( Some ( ( gross_change - fees) . to_sat ( ) ) ) ,
3493+ Ok ( Some ( gross_change - fees) ) ,
34863494 ) ;
34873495
34883496 // Larger fee, smaller change
@@ -3496,7 +3504,7 @@ mod tests {
34963504 total_inputs - total_outputs - context. our_funding_contribution . to_unsigned ( ) . unwrap ( ) ;
34973505 assert_eq ! (
34983506 calculate_change_output_value( & context, false , & ScriptBuf :: new( ) , 300 ) ,
3499- Ok ( Some ( ( gross_change - fees * 3 - common_fees * 3 ) . to_sat ( ) ) ) ,
3507+ Ok ( Some ( gross_change - fees * 3 - common_fees * 3 ) ) ,
35003508 ) ;
35013509 }
35023510
0 commit comments