From 29e0520fe9fe9aa6625af59036f326a157281cfd Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 13 Nov 2024 01:23:03 +0000 Subject: [PATCH] Check in-flight updates before completing events on closed chans When we handle a `ChannelMonitorUpdate` completion we always complete everything that was waiting on any updates to the same channel all at once. Thus, we need to skip all updates if there's pending updates besides the one that was just completed. We handled this correctly for open channels, but the shortcut for closed channels ignored any other pending updates entirely. Here we fix this, which is ultimately required for tests which are added in a few commits to pass. --- lightning/src/ln/channelmanager.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index fb5e86d89d6..9f05a89e3ad 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -7665,10 +7665,21 @@ where if peer_state_mutex_opt.is_none() { return } peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; + + let remaining_in_flight = + if let Some(pending) = peer_state.in_flight_monitor_updates.get_mut(funding_txo) { + pending.retain(|upd| upd.update_id > highest_applied_update_id); + pending.len() + } else { 0 }; + let channel = if let Some(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get_mut(channel_id) { chan } else { + if remaining_in_flight != 0 { + return; + } + let update_actions = peer_state.monitor_update_blocked_actions .remove(channel_id).unwrap_or(Vec::new()); mem::drop(peer_state_lock); @@ -7676,16 +7687,12 @@ where self.handle_monitor_update_completion_actions(update_actions); return; }; - let remaining_in_flight = - if let Some(pending) = peer_state.in_flight_monitor_updates.get_mut(funding_txo) { - pending.retain(|upd| upd.update_id > highest_applied_update_id); - pending.len() - } else { 0 }; + let logger = WithChannelContext::from(&self.logger, &channel.context, None); log_trace!(logger, "ChannelMonitor updated to {}. Current highest is {}. {} pending in-flight updates.", highest_applied_update_id, channel.context.get_latest_monitor_update_id(), remaining_in_flight); - if !channel.is_awaiting_monitor_update() || remaining_in_flight != 0 { + if remaining_in_flight != 0 || !channel.is_awaiting_monitor_update() { return; } handle_monitor_update_completion!(self, peer_state_lock, peer_state, per_peer_state, channel);