Skip to content

Commit bbf9e4e

Browse files
committed
Reapply pending ChannelMonitorUpdates on startup
If a `ChannelMonitorUpdate` was created and given to the user but left uncompleted when the `ChannelManager` is persisted prior to a restart, the user likely lost the `ChannelMonitorUpdate`(s). Thus, we need to replay them for the user, which we do here using the new `BackgroundEvent::MonitorUpdateRegeneratedOnStartup` variant.
1 parent 7d6cd94 commit bbf9e4e

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

lightning/src/ln/channel.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5030,10 +5030,20 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
50305030
self.pending_monitor_updates.is_empty()
50315031
}
50325032

5033+
pub fn complete_all_mon_updates_through(&mut self, update_id: u64) {
5034+
self.pending_monitor_updates.retain(|upd| upd.update.update_id > update_id);
5035+
}
5036+
50335037
pub fn complete_one_mon_update(&mut self, update_id: u64) {
50345038
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
50355039
}
50365040

5041+
/// Returns an iterator over all unblocked monitor updates which have not yet completed.
5042+
pub fn uncompleted_unblocked_mon_updates(&self) -> impl Iterator<Item=&ChannelMonitorUpdate> {
5043+
self.pending_monitor_updates.iter()
5044+
.filter_map(|upd| if upd.blocked { None } else { Some(&upd.update) })
5045+
}
5046+
50375047
/// Returns true if funding_created was sent/received.
50385048
pub fn is_funding_initiated(&self) -> bool {
50395049
self.channel_state >= ChannelState::FundingSent as u32

lightning/src/ln/channelmanager.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7702,7 +7702,10 @@ where
77027702
}
77037703
}
77047704
} else {
7705-
log_info!(args.logger, "Successfully loaded channel {}", log_bytes!(channel.channel_id()));
7705+
log_info!(args.logger, "Successfully loaded channel {} at update_id {} against monitor at update id {}",
7706+
log_bytes!(channel.channel_id()), channel.get_latest_monitor_update_id(),
7707+
monitor.get_latest_update_id());
7708+
channel.complete_all_mon_updates_through(monitor.get_latest_update_id());
77067709
if let Some(short_channel_id) = channel.get_short_channel_id() {
77077710
short_to_chan_info.insert(short_channel_id, (channel.get_counterparty_node_id(), channel.channel_id()));
77087711
}
@@ -7817,6 +7820,23 @@ where
78177820
}
78187821
}
78197822

7823+
for (node_id, peer_mtx) in per_peer_state.iter() {
7824+
let peer_state = peer_mtx.lock().unwrap();
7825+
for (_, chan) in peer_state.channel_by_id.iter() {
7826+
for monitor_update in chan.uncompleted_unblocked_mon_updates() {
7827+
if let Some(funding_outpoint) = chan.get_funding_txo() {
7828+
log_trace!(args.logger, "Replaying ChannelMonitorUpdate {} for channel {}",
7829+
monitor_update.update_id, log_bytes!(funding_outpoint.to_channel_id()));
7830+
pending_background_events.push(
7831+
BackgroundEvent::MonitorUpdateRegeneratedOnStartup(
7832+
(*node_id, funding_outpoint, monitor_update.clone())));
7833+
} else {
7834+
return Err(DecodeError::InvalidValue);
7835+
}
7836+
}
7837+
}
7838+
}
7839+
78207840
let _last_node_announcement_serial: u32 = Readable::read(reader)?; // Only used < 0.0.111
78217841
let highest_seen_timestamp: u32 = Readable::read(reader)?;
78227842

0 commit comments

Comments
 (0)