Skip to content

Commit 2e0e61e

Browse files
committed
Stop failing back HTLCs on peer disconnection
Previously, if we got disconnected from a peer while there were HTLCs pending forwarding in the holding cell, we'd clear them and fail them all backwards. This is largely fine, but since we now have support for handling such HTLCs on reconnect, we might as well not, instead relying on our timeout logic to fail them backwards if it takes too long to forward them.
1 parent d6c9667 commit 2e0e61e

File tree

2 files changed

+17
-61
lines changed

2 files changed

+17
-61
lines changed

lightning/src/ln/channel.rs

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,13 +2698,11 @@ impl<Signer: Sign> Channel<Signer> {
26982698
/// implicitly dropping) and the payment_hashes of HTLCs we tried to add but are dropping.
26992699
/// No further message handling calls may be made until a channel_reestablish dance has
27002700
/// completed.
2701-
pub fn remove_uncommitted_htlcs_and_mark_paused<L: Deref>(&mut self, logger: &L) -> Vec<(HTLCSource, PaymentHash)> where L::Target: Logger {
2702-
let mut outbound_drops = Vec::new();
2703-
2701+
pub fn remove_uncommitted_htlcs_and_mark_paused<L: Deref>(&mut self, logger: &L) where L::Target: Logger {
27042702
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
27052703
if self.channel_state < ChannelState::FundingSent as u32 {
27062704
self.channel_state = ChannelState::ShutdownComplete as u32;
2707-
return outbound_drops;
2705+
return;
27082706
}
27092707
// Upon reconnect we have to start the closing_signed dance over, but shutdown messages
27102708
// will be retransmitted.
@@ -2747,23 +2745,8 @@ impl<Signer: Sign> Channel<Signer> {
27472745
}
27482746
}
27492747

2750-
self.holding_cell_htlc_updates.retain(|htlc_update| {
2751-
match htlc_update {
2752-
// Note that currently on channel reestablish we assert that there are
2753-
// no holding cell HTLC update_adds, so if in the future we stop
2754-
// dropping added HTLCs here and failing them backwards, then there will
2755-
// need to be corresponding changes made in the Channel's re-establish
2756-
// logic.
2757-
&HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, .. } => {
2758-
outbound_drops.push((source.clone(), payment_hash.clone()));
2759-
false
2760-
},
2761-
&HTLCUpdateAwaitingACK::ClaimHTLC {..} | &HTLCUpdateAwaitingACK::FailHTLC {..} => true,
2762-
}
2763-
});
27642748
self.channel_state |= ChannelState::PeerDisconnected as u32;
2765-
log_debug!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops and {} waiting-to-locally-announced HTLC drops on channel {}", outbound_drops.len(), inbound_drop_count, log_bytes!(self.channel_id()));
2766-
outbound_drops
2749+
log_debug!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", inbound_drop_count, log_bytes!(self.channel_id()));
27672750
}
27682751

27692752
/// Indicates that a ChannelMonitor update failed to be stored by the client and further
@@ -2922,7 +2905,7 @@ impl<Signer: Sign> Channel<Signer> {
29222905

29232906
/// May panic if some calls other than message-handling calls (which will all Err immediately)
29242907
/// have been called between remove_uncommitted_htlcs_and_mark_paused and this call.
2925-
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, Option<msgs::Shutdown>), ChannelError> where L::Target: Logger {
2908+
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 {
29262909
if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
29272910
// While BOLT 2 doesn't indicate explicitly we should error this channel here, it
29282911
// almost certainly indicates we are going to end up out-of-sync in some way, so we
@@ -2973,15 +2956,15 @@ impl<Signer: Sign> Channel<Signer> {
29732956
return Err(ChannelError::Close("Peer claimed they saw a revoke_and_ack but we haven't sent funding_locked yet".to_owned()));
29742957
}
29752958
// Short circuit the whole handler as there is nothing we can resend them
2976-
return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg));
2959+
return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, Vec::new(), shutdown_msg));
29772960
}
29782961

29792962
// We have OurFundingLocked set!
29802963
let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
29812964
return Ok((Some(msgs::FundingLocked {
29822965
channel_id: self.channel_id(),
29832966
next_per_commitment_point,
2984-
}), None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg));
2967+
}), None, None, None, RAACommitmentOrder::CommitmentFirst, Vec::new(), shutdown_msg));
29852968
}
29862969

29872970
let required_revoke = if msg.next_remote_commitment_number + 1 == INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number {
@@ -3022,14 +3005,6 @@ impl<Signer: Sign> Channel<Signer> {
30223005
}
30233006

30243007
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::MonitorUpdateFailed as u32)) == 0 {
3025-
// Note that if in the future we no longer drop holding cell update_adds on peer
3026-
// disconnect, this logic will need to be updated.
3027-
for htlc_update in self.holding_cell_htlc_updates.iter() {
3028-
if let &HTLCUpdateAwaitingACK::AddHTLC { .. } = htlc_update {
3029-
debug_assert!(false, "There shouldn't be any add-HTLCs in the holding cell now because they should have been dropped on peer disconnect. Panic here because said HTLCs won't be handled correctly.");
3030-
}
3031-
}
3032-
30333008
// We're up-to-date and not waiting on a remote revoke (if we are our
30343009
// channel_reestablish should result in them sending a revoke_and_ack), but we may
30353010
// have received some updates while we were disconnected. Free the holding cell
@@ -3038,20 +3013,14 @@ impl<Signer: Sign> Channel<Signer> {
30383013
Err(ChannelError::Close(msg)) => return Err(ChannelError::Close(msg)),
30393014
Err(ChannelError::Ignore(_)) | Err(ChannelError::CloseDelayBroadcast(_)) => panic!("Got non-channel-failing result from free_holding_cell_htlcs"),
30403015
Ok((Some((commitment_update, monitor_update)), htlcs_to_fail)) => {
3041-
// If in the future we no longer drop holding cell update_adds on peer
3042-
// disconnect, we may be handed some HTLCs to fail backwards here.
3043-
assert!(htlcs_to_fail.is_empty());
3044-
return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(monitor_update), self.resend_order.clone(), shutdown_msg));
3016+
return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(monitor_update), self.resend_order.clone(), htlcs_to_fail, shutdown_msg));
30453017
},
30463018
Ok((None, htlcs_to_fail)) => {
3047-
// If in the future we no longer drop holding cell update_adds on peer
3048-
// disconnect, we may be handed some HTLCs to fail backwards here.
3049-
assert!(htlcs_to_fail.is_empty());
3050-
return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), shutdown_msg));
3019+
return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), htlcs_to_fail, shutdown_msg));
30513020
},
30523021
}
30533022
} else {
3054-
return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), shutdown_msg));
3023+
return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), Vec::new(), shutdown_msg));
30553024
}
30563025
} else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 {
30573026
if required_revoke.is_some() {
@@ -3062,10 +3031,10 @@ impl<Signer: Sign> Channel<Signer> {
30623031

30633032
if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 {
30643033
self.monitor_pending_commitment_signed = true;
3065-
return Ok((resend_funding_locked, None, None, None, self.resend_order.clone(), shutdown_msg));
3034+
return Ok((resend_funding_locked, None, None, None, self.resend_order.clone(), Vec::new(), shutdown_msg));
30663035
}
30673036

3068-
return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update(logger)), None, self.resend_order.clone(), shutdown_msg));
3037+
return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update(logger)), None, self.resend_order.clone(), Vec::new(), shutdown_msg));
30693038
} else {
30703039
return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction".to_owned()));
30713040
}
@@ -4388,7 +4357,7 @@ impl Readable for InboundHTLCRemovalReason {
43884357
impl<Signer: Sign> Writeable for Channel<Signer> {
43894358
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
43904359
// Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been
4391-
// called but include holding cell updates (and obviously we don't modify self).
4360+
// called.
43924361

43934362
writer.write_all(&[SERIALIZATION_VERSION; 1])?;
43944363
writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;

lightning/src/ln/channelmanager.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3286,7 +3286,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32863286
}
32873287

32883288
fn internal_channel_reestablish(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReestablish) -> Result<(), MsgHandleErrInternal> {
3289-
let chan_restoration_res = {
3289+
let (htlcs_failed_forward, chan_restoration_res) = {
32903290
let mut channel_state_lock = self.channel_state.lock().unwrap();
32913291
let channel_state = &mut *channel_state_lock;
32923292

@@ -3299,20 +3299,21 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32993299
// disconnect, so Channel's reestablish will never hand us any holding cell
33003300
// freed HTLCs to fail backwards. If in the future we no longer drop pending
33013301
// add-HTLCs on disconnect, we may be handed HTLCs to fail backwards here.
3302-
let (funding_locked, revoke_and_ack, commitment_update, monitor_update_opt, order, shutdown) =
3302+
let (funding_locked, revoke_and_ack, commitment_update, monitor_update_opt, order, htlcs_failed_forward, shutdown) =
33033303
try_chan_entry!(self, chan.get_mut().channel_reestablish(msg, &self.logger), channel_state, chan);
33043304
if let Some(msg) = shutdown {
33053305
channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
33063306
node_id: counterparty_node_id.clone(),
33073307
msg,
33083308
});
33093309
}
3310-
handle_chan_restoration_locked!(self, channel_state_lock, channel_state, chan, revoke_and_ack, commitment_update, order, monitor_update_opt, Vec::new(), None, funding_locked)
3310+
(htlcs_failed_forward, handle_chan_restoration_locked!(self, channel_state_lock, channel_state, chan, revoke_and_ack, commitment_update, order, monitor_update_opt, Vec::new(), None, funding_locked))
33113311
},
33123312
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
33133313
}
33143314
};
33153315
post_handle_chan_restoration!(self, chan_restoration_res);
3316+
self.fail_holding_cell_htlcs(htlcs_failed_forward, msg.channel_id);
33163317
Ok(())
33173318
}
33183319

@@ -3979,7 +3980,6 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
39793980
fn peer_disconnected(&self, counterparty_node_id: &PublicKey, no_connection_possible: bool) {
39803981
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
39813982
let mut failed_channels = Vec::new();
3982-
let mut failed_payments = Vec::new();
39833983
let mut no_channels_remain = true;
39843984
{
39853985
let mut channel_state_lock = self.channel_state.lock().unwrap();
@@ -4008,16 +4008,8 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
40084008
log_debug!(self.logger, "Marking channels with {} disconnected and generating channel_updates", log_pubkey!(counterparty_node_id));
40094009
channel_state.by_id.retain(|_, chan| {
40104010
if chan.get_counterparty_node_id() == *counterparty_node_id {
4011-
// Note that currently on channel reestablish we assert that there are no
4012-
// holding cell add-HTLCs, so if in the future we stop removing uncommitted HTLCs
4013-
// on peer disconnect here, there will need to be corresponding changes in
4014-
// reestablish logic.
4015-
let failed_adds = chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger);
4011+
chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger);
40164012
chan.to_disabled_marked();
4017-
if !failed_adds.is_empty() {
4018-
let chan_update = self.get_channel_update(&chan).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
4019-
failed_payments.push((chan_update, failed_adds));
4020-
}
40214013
if chan.is_shutdown() {
40224014
if let Some(short_id) = chan.get_short_channel_id() {
40234015
short_to_id.remove(&short_id);
@@ -4061,11 +4053,6 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
40614053
for failure in failed_channels.drain(..) {
40624054
self.finish_force_close_channel(failure);
40634055
}
4064-
for (chan_update, mut htlc_sources) in failed_payments {
4065-
for (htlc_source, payment_hash) in htlc_sources.drain(..) {
4066-
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source, &payment_hash, HTLCFailReason::Reason { failure_code: 0x1000 | 7, data: chan_update.clone() });
4067-
}
4068-
}
40694056
}
40704057

40714058
fn peer_connected(&self, counterparty_node_id: &PublicKey, init_msg: &msgs::Init) {

0 commit comments

Comments
 (0)