Skip to content

Commit cb6f322

Browse files
committed
Make ChannelClosed persistence idempotent and retry on failure
Fall back to the already-persisted record for is_outbound/is_announced when in-memory sets are empty on replay, use insert_or_update to avoid overwriting correct values, and propagate persist failures as ReplayEvent.
1 parent 34558a4 commit cb6f322

1 file changed

Lines changed: 16 additions & 3 deletions

File tree

src/event.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,17 +1671,27 @@ where
16711671
log_info!(self.logger, "Channel {} closed due to: {}", channel_id, reason);
16721672

16731673
let user_channel_id = UserChannelId(user_channel_id);
1674-
let is_outbound = self
1674+
let is_outbound_from_set = self
16751675
.outbound_channel_ids
16761676
.lock()
16771677
.expect("Lock poisoned")
16781678
.remove(&user_channel_id);
1679-
let is_announced = self
1679+
let is_announced_from_set = self
16801680
.announced_channel_ids
16811681
.lock()
16821682
.expect("Lock poisoned")
16831683
.remove(&user_channel_id);
16841684

1685+
// On replay (after a restart or after handle_event returns ReplayEvent),
1686+
// the channel is no longer in list_channels() and the in-memory sets are
1687+
// not repopulated for it, so .remove() returns false. Fall back to any
1688+
// already-persisted record so we don't overwrite correct values with false.
1689+
let (is_outbound, is_announced) = self
1690+
.closed_channel_store
1691+
.get(&user_channel_id)
1692+
.map(|existing| (existing.is_outbound, existing.is_announced))
1693+
.unwrap_or((is_outbound_from_set, is_announced_from_set));
1694+
16851695
let closed_at = SystemTime::now()
16861696
.duration_since(UNIX_EPOCH)
16871697
.unwrap_or(Duration::ZERO)
@@ -1703,19 +1713,22 @@ where
17031713
closed_at,
17041714
};
17051715

1706-
if let Err(e) = self.closed_channel_store.insert(record).await {
1716+
if let Err(e) = self.closed_channel_store.insert_or_update(record).await {
17071717
log_error!(
17081718
self.logger,
17091719
"Failed to persist closed channel {}: {}",
17101720
channel_id,
17111721
e
17121722
);
1723+
return Err(ReplayEvent());
17131724
}
17141725

17151726
let event = Event::ChannelClosed {
17161727
channel_id,
17171728
user_channel_id,
17181729
counterparty_node_id: counterparty_node_id
1730+
// Since LDK Node v0.2 this is expected to always be set. See
1731+
// CHANGELOG.md for details on the serialization compatibility break.
17191732
.expect("counterparty_node_id must be set for closed channels"),
17201733
reason: Some(reason),
17211734
channel_capacity_sats,

0 commit comments

Comments
 (0)