@@ -295,6 +295,7 @@ struct HTLCStats {
295
295
on_holder_tx_dust_exposure_msat : u64 ,
296
296
holding_cell_msat : u64 ,
297
297
on_holder_tx_holding_cell_htlcs_count : u32 , // dust HTLCs *non*-included
298
+ on_holder_tx_included_htlcs : u32 ,
298
299
}
299
300
300
301
/// An enum gathering stats on commitment transaction, either local or remote.
@@ -413,6 +414,12 @@ pub(crate) const CONCURRENT_INBOUND_HTLC_FEE_BUFFER: u32 = 2;
413
414
/// transaction (not counting the value of the HTLCs themselves).
414
415
pub ( crate ) const MIN_AFFORDABLE_HTLC_COUNT : usize = 4 ;
415
416
417
+ /// If after this value tick periods, the channel feerate isn't satisfying, we auto-close the
418
+ /// channel and goes on-chain to avoid unsafe situations where a commitment transaction with
419
+ /// time-sensitive outputs won't confirm due to staling feerate too far away from the upper feerate
420
+ /// groups of network mempools.
421
+ const AUTOCLOSE_TIMEOUT : u16 = 60 ;
422
+
416
423
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
417
424
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
418
425
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
@@ -435,6 +442,14 @@ pub(super) struct Channel<Signer: Sign> {
435
442
436
443
latest_monitor_update_id : u64 ,
437
444
445
+ // Auto-close timer, if the channel is outbound, we sent a `update_fee`, and we didn't
446
+ // receive a RAA from counterparty committing this state after `AUTOCLOSE_TIMEOUT` periods,
447
+ // this channel must be force-closed.
448
+ // If the channel is inbound, it has been observed the channel feerate should increase,
449
+ // and we didn't receive a RAA from counterparty committing an `update_fee` after
450
+ // `AUTOCLOSE_TIMEOUT` periods, this channel must be force-closed.
451
+ autoclose_timer : u16 ,
452
+
438
453
holder_signer : Signer ,
439
454
shutdown_scriptpubkey : Option < ShutdownScript > ,
440
455
destination_script : Script ,
@@ -747,6 +762,8 @@ impl<Signer: Sign> Channel<Signer> {
747
762
748
763
latest_monitor_update_id : 0 ,
749
764
765
+ autoclose_timer : 0 ,
766
+
750
767
holder_signer,
751
768
shutdown_scriptpubkey,
752
769
destination_script : keys_provider. get_destination_script ( ) ,
@@ -1037,6 +1054,8 @@ impl<Signer: Sign> Channel<Signer> {
1037
1054
1038
1055
latest_monitor_update_id : 0 ,
1039
1056
1057
+ autoclose_timer : 0 ,
1058
+
1040
1059
holder_signer,
1041
1060
shutdown_scriptpubkey,
1042
1061
destination_script : keys_provider. get_destination_script ( ) ,
@@ -2042,6 +2061,7 @@ impl<Signer: Sign> Channel<Signer> {
2042
2061
on_holder_tx_dust_exposure_msat : 0 ,
2043
2062
holding_cell_msat : 0 ,
2044
2063
on_holder_tx_holding_cell_htlcs_count : 0 ,
2064
+ on_holder_tx_included_htlcs : 0 ,
2045
2065
} ;
2046
2066
2047
2067
let counterparty_dust_limit_timeout_sat = ( self . get_dust_buffer_feerate ( outbound_feerate_update) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
@@ -2053,6 +2073,8 @@ impl<Signer: Sign> Channel<Signer> {
2053
2073
}
2054
2074
if htlc. amount_msat / 1000 < holder_dust_limit_success_sat {
2055
2075
stats. on_holder_tx_dust_exposure_msat += htlc. amount_msat ;
2076
+ } else {
2077
+ stats. on_holder_tx_included_htlcs += 1 ;
2056
2078
}
2057
2079
}
2058
2080
stats
@@ -2067,6 +2089,7 @@ impl<Signer: Sign> Channel<Signer> {
2067
2089
on_holder_tx_dust_exposure_msat : 0 ,
2068
2090
holding_cell_msat : 0 ,
2069
2091
on_holder_tx_holding_cell_htlcs_count : 0 ,
2092
+ on_holder_tx_included_htlcs : 0 ,
2070
2093
} ;
2071
2094
2072
2095
let counterparty_dust_limit_success_sat = ( self . get_dust_buffer_feerate ( outbound_feerate_update) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
@@ -2078,6 +2101,8 @@ impl<Signer: Sign> Channel<Signer> {
2078
2101
}
2079
2102
if htlc. amount_msat / 1000 < holder_dust_limit_timeout_sat {
2080
2103
stats. on_holder_tx_dust_exposure_msat += htlc. amount_msat ;
2104
+ } else {
2105
+ stats. on_holder_tx_included_htlcs += 1 ;
2081
2106
}
2082
2107
}
2083
2108
@@ -2711,16 +2736,16 @@ impl<Signer: Sign> Channel<Signer> {
2711
2736
/// Public version of the below, checking relevant preconditions first.
2712
2737
/// If we're not in a state where freeing the holding cell makes sense, this is a no-op and
2713
2738
/// returns `(None, Vec::new())`.
2714
- pub fn maybe_free_holding_cell_htlcs < L : Deref > ( & mut self , logger : & L ) -> Result < ( Option < ( msgs:: CommitmentUpdate , ChannelMonitorUpdate ) > , Vec < ( HTLCSource , PaymentHash ) > ) , ChannelError > where L :: Target : Logger {
2739
+ pub fn maybe_free_holding_cell_htlcs < L : Deref > ( & mut self , background_feerate : u32 , logger : & L ) -> Result < ( Option < ( msgs:: CommitmentUpdate , ChannelMonitorUpdate ) > , Vec < ( HTLCSource , PaymentHash ) > ) , ChannelError > where L :: Target : Logger {
2715
2740
if self . channel_state >= ChannelState :: ChannelFunded as u32 &&
2716
2741
( self . channel_state & ( ChannelState :: AwaitingRemoteRevoke as u32 | ChannelState :: PeerDisconnected as u32 | ChannelState :: MonitorUpdateFailed as u32 ) ) == 0 {
2717
- self . free_holding_cell_htlcs ( logger)
2742
+ self . free_holding_cell_htlcs ( background_feerate , logger)
2718
2743
} else { Ok ( ( None , Vec :: new ( ) ) ) }
2719
2744
}
2720
2745
2721
2746
/// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them
2722
2747
/// fulfilling or failing the last pending HTLC)
2723
- fn free_holding_cell_htlcs < L : Deref > ( & mut self , logger : & L ) -> Result < ( Option < ( msgs:: CommitmentUpdate , ChannelMonitorUpdate ) > , Vec < ( HTLCSource , PaymentHash ) > ) , ChannelError > where L :: Target : Logger {
2748
+ fn free_holding_cell_htlcs < L : Deref > ( & mut self , background_feerate : u32 , logger : & L ) -> Result < ( Option < ( msgs:: CommitmentUpdate , ChannelMonitorUpdate ) > , Vec < ( HTLCSource , PaymentHash ) > ) , ChannelError > where L :: Target : Logger {
2724
2749
assert_eq ! ( self . channel_state & ChannelState :: MonitorUpdateFailed as u32 , 0 ) ;
2725
2750
if self . holding_cell_htlc_updates . len ( ) != 0 || self . holding_cell_update_fee . is_some ( ) {
2726
2751
log_trace ! ( logger, "Freeing holding cell with {} HTLC updates{} in channel {}" , self . holding_cell_htlc_updates. len( ) ,
@@ -2804,7 +2829,7 @@ impl<Signer: Sign> Channel<Signer> {
2804
2829
return Ok ( ( None , htlcs_to_fail) ) ;
2805
2830
}
2806
2831
let update_fee = if let Some ( feerate) = self . holding_cell_update_fee . take ( ) {
2807
- self . send_update_fee ( feerate, logger)
2832
+ self . send_update_fee ( feerate, background_feerate , logger)
2808
2833
} else {
2809
2834
None
2810
2835
} ;
@@ -2832,13 +2857,35 @@ impl<Signer: Sign> Channel<Signer> {
2832
2857
}
2833
2858
}
2834
2859
2860
+ /// Trigger the autoclose timer if it's in the starting position
2861
+ pub fn maybe_trigger_autoclose_timer ( & mut self , current_feerate : u32 , new_feerate : u32 , background_feerate : u32 ) -> bool {
2862
+
2863
+ // Verify the new feerate is at least superior by 30% of current feerate before to
2864
+ // start a autoclose timer.
2865
+ if new_feerate < current_feerate * 1300 / 1000 && new_feerate < background_feerate {
2866
+ return false ;
2867
+ }
2868
+
2869
+ // Start an auto-close timer, if the channel feerate doesn't increase before its
2870
+ // expiration (i.e this outbound feerate update has been committed on both sides),
2871
+ // the channel will be marked as unsafe and force-closed.
2872
+ // If a timer is already pending, no-op, as a higher-feerate `update_fee` will
2873
+ // implicitly override a lower-feerate `update_fee` part of the same update sequence.
2874
+ if self . autoclose_timer == 0 {
2875
+ self . autoclose_timer = 1 ;
2876
+ return true ;
2877
+ }
2878
+ return false ;
2879
+ }
2880
+
2835
2881
/// Handles receiving a remote's revoke_and_ack. Note that we may return a new
2836
2882
/// commitment_signed message here in case we had pending outbound HTLCs to add which were
2837
2883
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
2838
2884
/// generating an appropriate error *after* the channel state has been updated based on the
2839
2885
/// revoke_and_ack message.
2840
- pub fn revoke_and_ack < L : Deref > ( & mut self , msg : & msgs:: RevokeAndACK , logger : & L ) -> Result < RAAUpdates , ChannelError >
2886
+ pub fn revoke_and_ack < L : Deref , F : Deref > ( & mut self , msg : & msgs:: RevokeAndACK , logger : & L , fee_estimator : & F ) -> Result < RAAUpdates , ChannelError >
2841
2887
where L :: Target : Logger ,
2888
+ F :: Target : FeeEstimator
2842
2889
{
2843
2890
if ( self . channel_state & ( ChannelState :: ChannelFunded as u32 ) ) != ( ChannelState :: ChannelFunded as u32 ) {
2844
2891
return Err ( ChannelError :: Close ( "Got revoke/ACK message when channel was not in an operational state" . to_owned ( ) ) ) ;
@@ -2999,6 +3046,7 @@ impl<Signer: Sign> Channel<Signer> {
2999
3046
log_trace ! ( logger, " ...promoting outbound fee update {} to Committed" , feerate) ;
3000
3047
self . feerate_per_kw = feerate;
3001
3048
self . pending_update_fee = None ;
3049
+ self . autoclose_timer = 0 ;
3002
3050
} ,
3003
3051
FeeUpdateState :: RemoteAnnounced => { debug_assert ! ( !self . is_outbound( ) ) ; } ,
3004
3052
FeeUpdateState :: AwaitingRemoteRevokeToAnnounce => {
@@ -3007,6 +3055,7 @@ impl<Signer: Sign> Channel<Signer> {
3007
3055
require_commitment = true ;
3008
3056
self . feerate_per_kw = feerate;
3009
3057
self . pending_update_fee = None ;
3058
+ self . autoclose_timer = 0 ;
3010
3059
} ,
3011
3060
}
3012
3061
}
@@ -3037,7 +3086,8 @@ impl<Signer: Sign> Channel<Signer> {
3037
3086
} ) ;
3038
3087
}
3039
3088
3040
- match self . free_holding_cell_htlcs ( logger) ? {
3089
+ let background_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Background ) ;
3090
+ match self . free_holding_cell_htlcs ( background_feerate, logger) ? {
3041
3091
( Some ( ( mut commitment_update, mut additional_update) ) , htlcs_to_fail) => {
3042
3092
commitment_update. update_fail_htlcs . reserve ( update_fail_htlcs. len ( ) ) ;
3043
3093
for fail_msg in update_fail_htlcs. drain ( ..) {
@@ -3104,7 +3154,7 @@ impl<Signer: Sign> Channel<Signer> {
3104
3154
/// If our balance is too low to cover the cost of the next commitment transaction at the
3105
3155
/// new feerate, the update is cancelled.
3106
3156
/// You MUST call send_commitment prior to any other calls on this Channel
3107
- fn send_update_fee < L : Deref > ( & mut self , feerate_per_kw : u32 , logger : & L ) -> Option < msgs:: UpdateFee > where L :: Target : Logger {
3157
+ fn send_update_fee < L : Deref > ( & mut self , feerate_per_kw : u32 , background_feerate : u32 , logger : & L ) -> Option < msgs:: UpdateFee > where L :: Target : Logger {
3108
3158
if !self . is_outbound ( ) {
3109
3159
panic ! ( "Cannot send fee from inbound channel" ) ;
3110
3160
}
@@ -3145,6 +3195,8 @@ impl<Signer: Sign> Channel<Signer> {
3145
3195
return None ;
3146
3196
}
3147
3197
3198
+ self . maybe_trigger_autoclose_timer ( self . get_feerate ( ) , feerate_per_kw, background_feerate) ;
3199
+
3148
3200
debug_assert ! ( self . pending_update_fee. is_none( ) ) ;
3149
3201
self . pending_update_fee = Some ( ( feerate_per_kw, FeeUpdateState :: Outbound ) ) ;
3150
3202
@@ -3154,8 +3206,8 @@ impl<Signer: Sign> Channel<Signer> {
3154
3206
} )
3155
3207
}
3156
3208
3157
- pub fn send_update_fee_and_commit < L : Deref > ( & mut self , feerate_per_kw : u32 , logger : & L ) -> Result < Option < ( msgs:: UpdateFee , msgs:: CommitmentSigned , ChannelMonitorUpdate ) > , ChannelError > where L :: Target : Logger {
3158
- match self . send_update_fee ( feerate_per_kw, logger) {
3209
+ pub fn send_update_fee_and_commit < L : Deref > ( & mut self , feerate_per_kw : u32 , background_feerate : u32 , logger : & L ) -> Result < Option < ( msgs:: UpdateFee , msgs:: CommitmentSigned , ChannelMonitorUpdate ) > , ChannelError > where L :: Target : Logger {
3210
+ match self . send_update_fee ( feerate_per_kw, background_feerate , logger) {
3159
3211
Some ( update_fee) => {
3160
3212
let ( commitment_signed, monitor_update) = self . send_commitment_no_status_check ( logger) ?;
3161
3213
Ok ( Some ( ( update_fee, commitment_signed, monitor_update) ) )
@@ -3343,6 +3395,26 @@ impl<Signer: Sign> Channel<Signer> {
3343
3395
Ok ( ( ) )
3344
3396
}
3345
3397
3398
+ /// If the auto-close timer is reached following the triggering of a auto-close condition
3399
+ /// (i.e a non-satisfying feerate to ensure efficient confirmation), we force-close
3400
+ /// channel, hopefully narrowing the safety risks for the user funds.
3401
+ pub fn check_autoclose ( & mut self ) -> Result < ( ) , ChannelError > {
3402
+ if self . autoclose_timer > 0 && self . autoclose_timer < AUTOCLOSE_TIMEOUT {
3403
+ self . autoclose_timer += 1 ;
3404
+ }
3405
+ if self . autoclose_timer == AUTOCLOSE_TIMEOUT {
3406
+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
3407
+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
3408
+ // If the channel has pending *included* HTLCs to claim on-chain and `should_autoclose`=y, close the channel
3409
+ if inbound_stats. on_holder_tx_included_htlcs + outbound_stats. on_holder_tx_included_htlcs > 0 && self . config . should_autoclose {
3410
+ return Err ( ChannelError :: Close ( "Channel has time-sensitive outputs and the auto-close timer has been reached" . to_owned ( ) ) ) ;
3411
+ }
3412
+ // Otherwise, do not reset the autoclose timer as a substantial HTLC can be committed
3413
+ // at anytime on the still low-feerate channel.
3414
+ }
3415
+ Ok ( ( ) )
3416
+ }
3417
+
3346
3418
fn get_last_revoke_and_ack ( & self ) -> msgs:: RevokeAndACK {
3347
3419
let next_per_commitment_point = self . holder_signer . get_per_commitment_point ( self . cur_holder_commitment_transaction_number , & self . secp_ctx ) ;
3348
3420
let per_commitment_secret = self . holder_signer . release_commitment_secret ( self . cur_holder_commitment_transaction_number + 2 ) ;
@@ -3419,7 +3491,10 @@ impl<Signer: Sign> Channel<Signer> {
3419
3491
3420
3492
/// May panic if some calls other than message-handling calls (which will all Err immediately)
3421
3493
/// have been called between remove_uncommitted_htlcs_and_mark_paused and this call.
3422
- pub fn channel_reestablish < L : Deref > ( & mut self , msg : & msgs:: ChannelReestablish , logger : & L ) -> Result < ( Option < msgs:: FundingLocked > , Option < msgs:: RevokeAndACK > , Option < msgs:: CommitmentUpdate > , Option < ChannelMonitorUpdate > , RAACommitmentOrder , Vec < ( HTLCSource , PaymentHash ) > , Option < msgs:: Shutdown > ) , ChannelError > where L :: Target : Logger {
3494
+ pub fn channel_reestablish < L : Deref , F : Deref > ( & mut self , msg : & msgs:: ChannelReestablish , logger : & L , fee_estimator : & F ) -> Result < ( Option < msgs:: FundingLocked > , Option < msgs:: RevokeAndACK > , Option < msgs:: CommitmentUpdate > , Option < ChannelMonitorUpdate > , RAACommitmentOrder , Vec < ( HTLCSource , PaymentHash ) > , Option < msgs:: Shutdown > ) , ChannelError >
3495
+ where L :: Target : Logger ,
3496
+ F :: Target : FeeEstimator
3497
+ {
3423
3498
if self . channel_state & ( ChannelState :: PeerDisconnected as u32 ) == 0 {
3424
3499
// While BOLT 2 doesn't indicate explicitly we should error this channel here, it
3425
3500
// almost certainly indicates we are going to end up out-of-sync in some way, so we
@@ -3524,7 +3599,8 @@ impl<Signer: Sign> Channel<Signer> {
3524
3599
// channel_reestablish should result in them sending a revoke_and_ack), but we may
3525
3600
// have received some updates while we were disconnected. Free the holding cell
3526
3601
// now!
3527
- match self . free_holding_cell_htlcs ( logger) {
3602
+ let background_feerate = fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: Background ) ;
3603
+ match self . free_holding_cell_htlcs ( background_feerate, logger) {
3528
3604
Err ( ChannelError :: Close ( msg) ) => return Err ( ChannelError :: Close ( msg) ) ,
3529
3605
Err ( ChannelError :: Warn ( _) ) | Err ( ChannelError :: Ignore ( _) ) | Err ( ChannelError :: CloseDelayBroadcast ( _) ) =>
3530
3606
panic ! ( "Got non-channel-failing result from free_holding_cell_htlcs" ) ,
@@ -4865,6 +4941,7 @@ impl<Signer: Sign> Channel<Signer> {
4865
4941
log_trace ! ( logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce fee update {} to Committed" , feerate) ;
4866
4942
self . feerate_per_kw = feerate;
4867
4943
self . pending_update_fee = None ;
4944
+ self . autoclose_timer = 0 ;
4868
4945
}
4869
4946
}
4870
4947
self . resend_order = RAACommitmentOrder :: RevokeAndACKFirst ;
@@ -5384,6 +5461,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
5384
5461
( 9 , self . target_closing_feerate_sats_per_kw, option) ,
5385
5462
( 11 , self . monitor_pending_finalized_fulfills, vec_type) ,
5386
5463
( 13 , self . channel_creation_height, required) ,
5464
+ ( 15 , self . autoclose_timer, required) ,
5387
5465
} ) ;
5388
5466
5389
5467
Ok ( ( ) )
@@ -5623,6 +5701,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
5623
5701
// only, so we default to that if none was written.
5624
5702
let mut channel_type = Some ( ChannelTypeFeatures :: only_static_remote_key ( ) ) ;
5625
5703
let mut channel_creation_height = Some ( serialized_height) ;
5704
+ let mut autoclose_timer = 0 ;
5626
5705
read_tlv_fields ! ( reader, {
5627
5706
( 0 , announcement_sigs, option) ,
5628
5707
( 1 , minimum_depth, option) ,
@@ -5633,6 +5712,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
5633
5712
( 9 , target_closing_feerate_sats_per_kw, option) ,
5634
5713
( 11 , monitor_pending_finalized_fulfills, vec_type) ,
5635
5714
( 13 , channel_creation_height, option) ,
5715
+ ( 15 , autoclose_timer, required) ,
5636
5716
} ) ;
5637
5717
5638
5718
let chan_features = channel_type. as_ref ( ) . unwrap ( ) ;
@@ -5661,6 +5741,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
5661
5741
5662
5742
latest_monitor_update_id,
5663
5743
5744
+ autoclose_timer,
5745
+
5664
5746
holder_signer,
5665
5747
shutdown_scriptpubkey,
5666
5748
destination_script,
0 commit comments