Skip to content

Commit 550df93

Browse files
Fix replay of monitor events for outbounds
Currently, the resolution of HTLCs (and decisions on when HTLCs can be forwarded) is the responsibility of Channel objects (a part of ChannelManager) until the channel is closed, and then the ChannelMonitor thereafter. This leads to some complexity around race conditions for HTLCs right around channel closure. Additionally, there is lots of complexity reconstructing the state of all HTLCs in the ChannelManager deserialization/loading logic. Instead, we want to do all resolution in ChannelMonitors (in response to ChannelMonitorUpdates) and pass them back to ChannelManager in the form of MonitorEvents (similar to how HTLCs are resolved after channels are closed). In order to have reliable resolution, we'll need to keep MonitorEvents around in the ChannelMonitor until the ChannelManager has finished processing them. This will simplify things - on restart instead of examining the set of HTLCs in monitors we can simply replay all the pending MonitorEvents. If an outbound payment resolved on-chain and we get a monitor event for it, we want to mark that monitor event as resolved once the user has processed a PaymentSent or a PaymentFailed event.
1 parent 8972f05 commit 550df93

1 file changed

Lines changed: 29 additions & 1 deletion

File tree

lightning/src/ln/channelmanager.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1544,19 +1544,34 @@ enum PostMonitorUpdateChanResume {
15441544
},
15451545
}
15461546

1547-
#[derive(Clone, Debug, PartialEq, Eq)]
1547+
#[derive(Clone, Debug, Eq)]
15481548
pub(crate) struct PaymentCompleteUpdate {
15491549
counterparty_node_id: PublicKey,
15501550
channel_funding_outpoint: OutPoint,
15511551
channel_id: ChannelId,
15521552
htlc_id: SentHTLCId,
1553+
/// If this payment resolution originated from a [`MonitorEvent`], the event ID to acknowledge
1554+
/// once the completion action has been durably handled.
1555+
monitor_event_id: Option<u64>,
1556+
}
1557+
1558+
impl PartialEq for PaymentCompleteUpdate {
1559+
fn eq(&self, other: &Self) -> bool {
1560+
self.counterparty_node_id == other.counterparty_node_id
1561+
&& self.channel_funding_outpoint == other.channel_funding_outpoint
1562+
&& self.channel_id == other.channel_id
1563+
&& self.htlc_id == other.htlc_id
1564+
// monitor_event_id is excluded: it's metadata about the event source,
1565+
// not part of the semantic identity of the payment resolution.
1566+
}
15531567
}
15541568

15551569
impl_writeable_tlv_based!(PaymentCompleteUpdate, {
15561570
(1, channel_funding_outpoint, required),
15571571
(3, counterparty_node_id, required),
15581572
(5, channel_id, required),
15591573
(7, htlc_id, required),
1574+
(9, monitor_event_id, option),
15601575
});
15611576

15621577
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -9871,6 +9886,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
98719886
next_channel_counterparty_node_id: PublicKey, next_channel_outpoint: OutPoint,
98729887
next_channel_id: ChannelId, next_user_channel_id: Option<u128>,
98739888
attribution_data: Option<AttributionData>, send_timestamp: Option<Duration>,
9889+
monitor_event_id: Option<u64>,
98749890
) {
98759891
let startup_replay =
98769892
!self.background_events_processed_since_startup.load(Ordering::Acquire);
@@ -9889,6 +9905,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
98899905
channel_funding_outpoint: next_channel_outpoint,
98909906
channel_id: next_channel_id,
98919907
htlc_id,
9908+
monitor_event_id,
98929909
};
98939910
Some(EventCompletionAction::ReleasePaymentCompleteChannelMonitorUpdate(release))
98949911
} else {
@@ -12474,6 +12491,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1247412491
Some(next_user_channel_id),
1247512492
msg.attribution_data,
1247612493
send_timestamp,
12494+
None,
1247712495
);
1247812496

1247912497
Ok(())
@@ -13297,6 +13315,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1329713315
None,
1329813316
None,
1329913317
None,
13318+
Some(event_id),
1330013319
);
1330113320
} else {
1330213321
log_trace!(logger, "Failing HTLC from our monitor");
@@ -13309,6 +13328,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1330913328
channel_funding_outpoint: funding_outpoint,
1331013329
channel_id,
1331113330
htlc_id: SentHTLCId::from_source(&htlc_update.source),
13331+
monitor_event_id: Some(event_id),
1331213332
});
1331313333
self.fail_htlc_backwards_internal(
1331413334
&htlc_update.source,
@@ -15086,8 +15106,13 @@ impl<
1508615106
channel_funding_outpoint,
1508715107
channel_id,
1508815108
htlc_id,
15109+
monitor_event_id,
1508915110
},
1509015111
) => {
15112+
if let Some(event_id) = monitor_event_id {
15113+
self.chain_monitor
15114+
.ack_monitor_event(MonitorEventSource { channel_id, event_id });
15115+
}
1509115116
let per_peer_state = self.per_peer_state.read().unwrap();
1509215117
let mut peer_state_lock = per_peer_state
1509315118
.get(&counterparty_node_id)
@@ -19460,6 +19485,7 @@ impl<
1946019485
channel_funding_outpoint: monitor.get_funding_txo(),
1946119486
channel_id: monitor.channel_id(),
1946219487
htlc_id,
19488+
monitor_event_id: None,
1946319489
};
1946419490
let mut compl_action = Some(
1946519491
EventCompletionAction::ReleasePaymentCompleteChannelMonitorUpdate(update)
@@ -19539,6 +19565,7 @@ impl<
1953919565
channel_funding_outpoint: monitor.get_funding_txo(),
1954019566
channel_id: monitor.channel_id(),
1954119567
htlc_id: SentHTLCId::from_source(&htlc_source),
19568+
monitor_event_id: None,
1954219569
});
1954319570

1954419571
failed_htlcs.push((
@@ -20296,6 +20323,7 @@ impl<
2029620323
downstream_user_channel_id,
2029720324
None,
2029820325
None,
20326+
None,
2029920327
);
2030020328
}
2030120329

0 commit comments

Comments
 (0)