Skip to content

Commit 785bdb8

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 e5070c4 commit 785bdb8

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

lightning/src/ln/channel.rs

+15
Original file line numberDiff line numberDiff line change
@@ -5050,10 +5050,25 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
50505050
self.pending_monitor_updates.is_empty()
50515051
}
50525052

5053+
pub fn complete_all_mon_updates_through(&mut self, update_id: u64) {
5054+
self.pending_monitor_updates.retain(|upd| {
5055+
if upd.update.update_id <= update_id {
5056+
assert!(!upd.blocked, "Completed update must have flown");
5057+
false
5058+
} else { true }
5059+
});
5060+
}
5061+
50535062
pub fn complete_one_mon_update(&mut self, update_id: u64) {
50545063
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
50555064
}
50565065

5066+
/// Returns an iterator over all unblocked monitor updates which have not yet completed.
5067+
pub fn uncompleted_unblocked_mon_updates(&self) -> impl Iterator<Item=&ChannelMonitorUpdate> {
5068+
self.pending_monitor_updates.iter()
5069+
.filter_map(|upd| if upd.blocked { None } else { Some(&upd.update) })
5070+
}
5071+
50575072
/// Returns true if funding_created was sent/received.
50585073
pub fn is_funding_initiated(&self) -> bool {
50595074
self.channel_state >= ChannelState::FundingSent as u32

lightning/src/ln/channelmanager.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -7882,7 +7882,10 @@ where
78827882
}
78837883
}
78847884
} else {
7885-
log_info!(args.logger, "Successfully loaded channel {}", log_bytes!(channel.channel_id()));
7885+
log_info!(args.logger, "Successfully loaded channel {} at update_id {} against monitor at update id {}",
7886+
log_bytes!(channel.channel_id()), channel.get_latest_monitor_update_id(),
7887+
monitor.get_latest_update_id());
7888+
channel.complete_all_mon_updates_through(monitor.get_latest_update_id());
78867889
if let Some(short_channel_id) = channel.get_short_channel_id() {
78877890
short_to_chan_info.insert(short_channel_id, (channel.get_counterparty_node_id(), channel.channel_id()));
78887891
}
@@ -7996,6 +7999,24 @@ where
79967999
}
79978000
}
79988001

8002+
for (node_id, peer_mtx) in per_peer_state.iter() {
8003+
let peer_state = peer_mtx.lock().unwrap();
8004+
for (_, chan) in peer_state.channel_by_id.iter() {
8005+
for update in chan.uncompleted_unblocked_mon_updates() {
8006+
if let Some(funding_txo) = chan.get_funding_txo() {
8007+
log_trace!(args.logger, "Replaying ChannelMonitorUpdate {} for channel {}",
8008+
update.update_id, log_bytes!(funding_txo.to_channel_id()));
8009+
pending_background_events.push(
8010+
BackgroundEvent::MonitorUpdateRegeneratedOnStartup {
8011+
counterparty_node_id: *node_id, funding_txo, update: update.clone(),
8012+
});
8013+
} else {
8014+
return Err(DecodeError::InvalidValue);
8015+
}
8016+
}
8017+
}
8018+
}
8019+
79998020
let _last_node_announcement_serial: u32 = Readable::read(reader)?; // Only used < 0.0.111
80008021
let highest_seen_timestamp: u32 = Readable::read(reader)?;
80018022

0 commit comments

Comments
 (0)