@@ -1054,8 +1054,30 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1054
1054
}
1055
1055
1056
1056
#[ inline]
1057
- fn get_closing_transaction_weight ( a_scriptpubkey : & Script , b_scriptpubkey : & Script ) -> u64 {
1058
- ( 4 + 1 + 36 + 4 + 1 + 1 + 2 * ( 8 +1 ) + 4 + a_scriptpubkey. len ( ) as u64 + b_scriptpubkey. len ( ) as u64 ) * 4 + 2 + 1 + 1 + 2 * ( 1 + 72 )
1057
+ fn get_closing_transaction_weight ( & self , a_scriptpubkey : Option < & Script > , b_scriptpubkey : Option < & Script > ) -> u64 {
1058
+ let mut ret =
1059
+ ( 4 + // version
1060
+ 1 + // input count
1061
+ 36 + // prevout
1062
+ 1 + // script length (0)
1063
+ 4 + // sequence
1064
+ 1 + // output count
1065
+ 4 // lock time
1066
+ ) * 4 + // * 4 for non-witness parts
1067
+ 2 + // witness marker and flag
1068
+ 1 + // witness element count
1069
+ 4 + // 4 element lengths (2 sigs, multisig dummy, and witness script)
1070
+ self . get_funding_redeemscript ( ) . len ( ) as u64 + // funding witness script
1071
+ 2 * ( 1 + 71 ) ; // two signatures + sighash type flags
1072
+ if let Some ( spk) = a_scriptpubkey {
1073
+ ret += ( ( 8 +1 ) + // output values and script length
1074
+ spk. len ( ) as u64 ) * 4 ; // scriptpubkey and witness multiplier
1075
+ }
1076
+ if let Some ( spk) = b_scriptpubkey {
1077
+ ret += ( ( 8 +1 ) + // output values and script length
1078
+ spk. len ( ) as u64 ) * 4 ; // scriptpubkey and witness multiplier
1079
+ }
1080
+ ret
1059
1081
}
1060
1082
1061
1083
#[ inline]
@@ -2880,13 +2902,14 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
2880
2902
if self . feerate_per_kw > proposed_feerate {
2881
2903
proposed_feerate = self . feerate_per_kw ;
2882
2904
}
2883
- let tx_weight = Self :: get_closing_transaction_weight ( & self . get_closing_scriptpubkey ( ) , self . counterparty_shutdown_scriptpubkey . as_ref ( ) . unwrap ( ) ) ;
2905
+ let tx_weight = self . get_closing_transaction_weight ( Some ( & self . get_closing_scriptpubkey ( ) ) , Some ( self . counterparty_shutdown_scriptpubkey . as_ref ( ) . unwrap ( ) ) ) ;
2884
2906
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000 ;
2885
2907
2886
2908
let ( closing_tx, total_fee_satoshis) = self . build_closing_transaction ( proposed_total_fee_satoshis, false ) ;
2887
2909
let sig = self . holder_keys
2888
2910
. sign_closing_transaction ( & closing_tx, & self . secp_ctx )
2889
2911
. ok ( ) ;
2912
+ assert ! ( closing_tx. get_weight( ) as u64 <= tx_weight) ;
2890
2913
if sig. is_none ( ) { return None ; }
2891
2914
2892
2915
self . last_sent_closing_fee = Some ( ( proposed_feerate, total_fee_satoshis, sig. clone ( ) . unwrap ( ) ) ) ;
@@ -3007,7 +3030,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3007
3030
if !self . pending_inbound_htlcs . is_empty ( ) || !self . pending_outbound_htlcs . is_empty ( ) {
3008
3031
return Err ( ChannelError :: Close ( "Remote end sent us a closing_signed while there were still pending HTLCs" . to_owned ( ) ) ) ;
3009
3032
}
3010
- if msg. fee_satoshis > 21000000 * 10000000 { //this is required to stop potential overflow in build_closing_transaction
3033
+ if msg. fee_satoshis > 21_000_000 * 1_0000_0000 { //this is required to stop potential overflow in build_closing_transaction
3011
3034
return Err ( ChannelError :: Close ( "Remote tried to send us a closing tx with > 21 million BTC fee" . to_owned ( ) ) ) ;
3012
3035
}
3013
3036
@@ -3031,9 +3054,14 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3031
3054
} ,
3032
3055
} ;
3033
3056
3057
+ let closing_tx_max_weight = self . get_closing_transaction_weight (
3058
+ if let Some ( oup) = closing_tx. output . get ( 0 ) { Some ( & oup. script_pubkey ) } else { None } ,
3059
+ if let Some ( oup) = closing_tx. output . get ( 1 ) { Some ( & oup. script_pubkey ) } else { None } ) ;
3034
3060
if let Some ( ( _, last_fee, sig) ) = self . last_sent_closing_fee {
3035
3061
if last_fee == msg. fee_satoshis {
3036
3062
self . build_signed_closing_transaction ( & mut closing_tx, & msg. signature , & sig) ;
3063
+ assert ! ( closing_tx. get_weight( ) as u64 <= closing_tx_max_weight) ;
3064
+ debug_assert ! ( closing_tx. get_weight( ) as u64 >= closing_tx_max_weight - 2 ) ;
3037
3065
self . channel_state = ChannelState :: ShutdownComplete as u32 ;
3038
3066
self . update_time_counter += 1 ;
3039
3067
return Ok ( ( None , Some ( closing_tx) ) ) ;
@@ -3042,11 +3070,12 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3042
3070
3043
3071
macro_rules! propose_new_feerate {
3044
3072
( $new_feerate: expr) => {
3045
- let closing_tx_max_weight = Self :: get_closing_transaction_weight( & self . get_closing_scriptpubkey( ) , self . counterparty_shutdown_scriptpubkey. as_ref( ) . unwrap( ) ) ;
3046
- let ( closing_tx, used_total_fee) = self . build_closing_transaction( $new_feerate as u64 * closing_tx_max_weight / 1000 , false ) ;
3073
+ let tx_weight = self . get_closing_transaction_weight( Some ( & self . get_closing_scriptpubkey( ) ) , Some ( self . counterparty_shutdown_scriptpubkey. as_ref( ) . unwrap( ) ) ) ;
3074
+ let ( closing_tx, used_total_fee) = self . build_closing_transaction( $new_feerate as u64 * tx_weight / 1000 , false ) ;
3047
3075
let sig = self . holder_keys
3048
3076
. sign_closing_transaction( & closing_tx, & self . secp_ctx)
3049
3077
. map_err( |_| ChannelError :: Close ( "External signer refused to sign closing transaction" . to_owned( ) ) ) ?;
3078
+ assert!( closing_tx. get_weight( ) as u64 <= tx_weight) ;
3050
3079
self . last_sent_closing_fee = Some ( ( $new_feerate, used_total_fee, sig. clone( ) ) ) ;
3051
3080
return Ok ( ( Some ( msgs:: ClosingSigned {
3052
3081
channel_id: self . channel_id,
@@ -3056,10 +3085,10 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3056
3085
}
3057
3086
}
3058
3087
3059
- let proposed_sat_per_kw = msg . fee_satoshis * 1000 / closing_tx . get_weight ( ) as u64 ;
3088
+ let mut min_feerate = 253 ;
3060
3089
if self . channel_outbound {
3061
3090
let max_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Normal ) ;
3062
- if ( proposed_sat_per_kw as u32 ) > max_feerate {
3091
+ if ( msg . fee_satoshis as u64 ) > max_feerate as u64 * closing_tx_max_weight / 1000 {
3063
3092
if let Some ( ( last_feerate, _, _) ) = self . last_sent_closing_fee {
3064
3093
if max_feerate <= last_feerate {
3065
3094
return Err ( ChannelError :: Close ( format ! ( "Unable to come to consensus about closing feerate, remote wanted something higher ({}) than our Normal feerate ({})" , last_feerate, max_feerate) ) ) ;
@@ -3068,21 +3097,23 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3068
3097
propose_new_feerate ! ( max_feerate) ;
3069
3098
}
3070
3099
} else {
3071
- let min_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Background ) ;
3072
- if ( proposed_sat_per_kw as u32 ) < min_feerate {
3073
- if let Some ( ( last_feerate , _ , _ ) ) = self . last_sent_closing_fee {
3074
- if min_feerate >= last_feerate {
3075
- return Err ( ChannelError :: Close ( format ! ( "Unable to come to consensus about closing feerate, remote wanted something lower ({}) than our Background feerate ({})." , last_feerate, min_feerate ) ) ) ;
3076
- }
3100
+ min_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Background ) ;
3101
+ }
3102
+ if ( msg . fee_satoshis as u64 ) < min_feerate as u64 * closing_tx_max_weight / 1000 {
3103
+ if let Some ( ( last_feerate , _ , _ ) ) = self . last_sent_closing_fee {
3104
+ if min_feerate >= last_feerate {
3105
+ return Err ( ChannelError :: Close ( format ! ( "Unable to come to consensus about closing feerate, remote wanted something lower ({}) than our Background feerate ({})." , last_feerate , min_feerate ) ) ) ;
3077
3106
}
3078
- propose_new_feerate ! ( min_feerate) ;
3079
3107
}
3108
+ propose_new_feerate ! ( min_feerate) ;
3080
3109
}
3081
3110
3082
3111
let sig = self . holder_keys
3083
3112
. sign_closing_transaction ( & closing_tx, & self . secp_ctx )
3084
3113
. map_err ( |_| ChannelError :: Close ( "External signer refused to sign closing transaction" . to_owned ( ) ) ) ?;
3085
3114
self . build_signed_closing_transaction ( & mut closing_tx, & msg. signature , & sig) ;
3115
+ assert ! ( closing_tx. get_weight( ) as u64 <= closing_tx_max_weight) ;
3116
+ debug_assert ! ( closing_tx. get_weight( ) as u64 >= closing_tx_max_weight - 2 ) ;
3086
3117
3087
3118
self . channel_state = ChannelState :: ShutdownComplete as u32 ;
3088
3119
self . update_time_counter += 1 ;
0 commit comments