Skip to content

Commit b8bb43b

Browse files
Pipe monitor event source HTLCForwardInfo -> holding cell htlcs
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. To ensure we can resolve HTLC monitor events for forward failures, we need to pipe the event id through the HTLC failure pipeline. Here we pipe the monitor event source from the manager to the channel, so it can be put in the channel's holding cell. In upcoming commits we will eventually get to the point of acking the monitor event when the HTLC is irrevocably removed from the inbound edge via monitor update.
1 parent d2a9e09 commit b8bb43b

2 files changed

Lines changed: 67 additions & 25 deletions

File tree

lightning/src/ln/channel.rs

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6561,7 +6561,9 @@ trait FailHTLCContents {
65616561
type Message: FailHTLCMessageName;
65626562
fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message;
65636563
fn to_inbound_htlc_state(self) -> InboundHTLCState;
6564-
fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK;
6564+
fn to_htlc_update_awaiting_ack(
6565+
self, htlc_id: u64, monitor_event_source: Option<MonitorEventSource>,
6566+
) -> HTLCUpdateAwaitingACK;
65656567
}
65666568
impl FailHTLCContents for msgs::OnionErrorPacket {
65676569
type Message = msgs::UpdateFailHTLC;
@@ -6576,8 +6578,10 @@ impl FailHTLCContents for msgs::OnionErrorPacket {
65766578
fn to_inbound_htlc_state(self) -> InboundHTLCState {
65776579
InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(self))
65786580
}
6579-
fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK {
6580-
HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet: self, monitor_event_source: None }
6581+
fn to_htlc_update_awaiting_ack(
6582+
self, htlc_id: u64, monitor_event_source: Option<MonitorEventSource>,
6583+
) -> HTLCUpdateAwaitingACK {
6584+
HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet: self, monitor_event_source }
65816585
}
65826586
}
65836587
impl FailHTLCContents for ([u8; 32], u16) {
@@ -6596,12 +6600,14 @@ impl FailHTLCContents for ([u8; 32], u16) {
65966600
failure_code: self.1,
65976601
})
65986602
}
6599-
fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK {
6603+
fn to_htlc_update_awaiting_ack(
6604+
self, htlc_id: u64, monitor_event_source: Option<MonitorEventSource>,
6605+
) -> HTLCUpdateAwaitingACK {
66006606
HTLCUpdateAwaitingACK::FailMalformedHTLC {
66016607
htlc_id,
66026608
sha256_of_onion: self.0,
66036609
failure_code: self.1,
6604-
monitor_event_source: None,
6610+
monitor_event_source,
66056611
}
66066612
}
66076613
}
@@ -7343,9 +7349,10 @@ where
73437349
/// Returns `Err` (always with [`ChannelError::Ignore`]) if the HTLC could not be failed (e.g.
73447350
/// if it was already resolved). Otherwise returns `Ok`.
73457351
pub fn queue_fail_htlc<L: Logger>(
7346-
&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, logger: &L,
7352+
&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket,
7353+
monitor_event_source: Option<MonitorEventSource>, logger: &L,
73477354
) -> Result<(), ChannelError> {
7348-
self.fail_htlc(htlc_id_arg, err_packet, true, logger)
7355+
self.fail_htlc(htlc_id_arg, err_packet, true, monitor_event_source, logger)
73497356
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
73507357
}
73517358

@@ -7354,18 +7361,25 @@ where
73547361
///
73557362
/// See [`Self::queue_fail_htlc`] for more info.
73567363
pub fn queue_fail_malformed_htlc<L: Logger>(
7357-
&mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32], logger: &L,
7364+
&mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32],
7365+
monitor_event_source: Option<MonitorEventSource>, logger: &L,
73587366
) -> Result<(), ChannelError> {
7359-
self.fail_htlc(htlc_id_arg, (sha256_of_onion, failure_code), true, logger)
7360-
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
7367+
self.fail_htlc(
7368+
htlc_id_arg,
7369+
(sha256_of_onion, failure_code),
7370+
true,
7371+
monitor_event_source,
7372+
logger,
7373+
)
7374+
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
73617375
}
73627376

73637377
/// Returns `Err` (always with [`ChannelError::Ignore`]) if the HTLC could not be failed (e.g.
73647378
/// if it was already resolved). Otherwise returns `Ok`.
73657379
#[rustfmt::skip]
73667380
fn fail_htlc<L: Logger, E: FailHTLCContents + Clone>(
73677381
&mut self, htlc_id_arg: u64, err_contents: E, mut force_holding_cell: bool,
7368-
logger: &L
7382+
monitor_event_source: Option<MonitorEventSource>, logger: &L
73697383
) -> Result<Option<E::Message>, ChannelError> {
73707384
if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
73717385
panic!("Was asked to fail an HTLC when channel was not in an operational state");
@@ -7402,25 +7416,28 @@ where
74027416

74037417
// Now update local state:
74047418
if force_holding_cell {
7405-
for pending_update in self.context.holding_cell_htlc_updates.iter() {
7419+
for pending_update in self.context.holding_cell_htlc_updates.iter_mut() {
74067420
match pending_update {
7407-
&HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => {
7421+
&mut HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => {
74087422
if htlc_id_arg == htlc_id {
74097423
return Err(ChannelError::Ignore(format!("HTLC {} was already claimed!", htlc_id)));
74107424
}
74117425
},
7412-
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } |
7413-
&HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } =>
7426+
&mut HTLCUpdateAwaitingACK::FailHTLC { htlc_id, monitor_event_source: ref mut src, .. } |
7427+
&mut HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, monitor_event_source: ref mut src, .. } =>
74147428
{
74157429
if htlc_id_arg == htlc_id {
7430+
if src.is_none() {
7431+
*src = monitor_event_source;
7432+
}
74167433
return Err(ChannelError::Ignore(format!("HTLC {} was already pending failure", htlc_id)));
74177434
}
74187435
},
74197436
_ => {}
74207437
}
74217438
}
74227439
log_trace!(logger, "Placing failure for HTLC ID {} in holding cell.", htlc_id_arg);
7423-
self.context.holding_cell_htlc_updates.push(err_contents.to_htlc_update_awaiting_ack(htlc_id_arg));
7440+
self.context.holding_cell_htlc_updates.push(err_contents.to_htlc_update_awaiting_ack(htlc_id_arg, monitor_event_source));
74247441
return Ok(None);
74257442
}
74267443

@@ -8449,18 +8466,34 @@ where
84498466
monitor_update.updates.append(&mut additional_monitor_update.updates);
84508467
None
84518468
},
8452-
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, ref err_packet, .. } => Some(
8453-
self.fail_htlc(htlc_id, err_packet.clone(), false, logger)
8454-
.map(|fail_msg_opt| fail_msg_opt.map(|_| ())),
8469+
&HTLCUpdateAwaitingACK::FailHTLC {
8470+
htlc_id,
8471+
ref err_packet,
8472+
monitor_event_source,
8473+
} => Some(
8474+
self.fail_htlc(
8475+
htlc_id,
8476+
err_packet.clone(),
8477+
false,
8478+
monitor_event_source,
8479+
logger,
8480+
)
8481+
.map(|fail_msg_opt| fail_msg_opt.map(|_| ())),
84558482
),
84568483
&HTLCUpdateAwaitingACK::FailMalformedHTLC {
84578484
htlc_id,
84588485
failure_code,
84598486
sha256_of_onion,
8460-
..
8487+
monitor_event_source,
84618488
} => Some(
8462-
self.fail_htlc(htlc_id, (sha256_of_onion, failure_code), false, logger)
8463-
.map(|fail_msg_opt| fail_msg_opt.map(|_| ())),
8489+
self.fail_htlc(
8490+
htlc_id,
8491+
(sha256_of_onion, failure_code),
8492+
false,
8493+
monitor_event_source,
8494+
logger,
8495+
)
8496+
.map(|fail_msg_opt| fail_msg_opt.map(|_| ())),
84648497
),
84658498
};
84668499
if let Some(res) = fail_htlc_res {

lightning/src/ln/channelmanager.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8176,15 +8176,23 @@ impl<
81768176
}
81778177
None
81788178
},
8179-
HTLCForwardInfo::FailHTLC { htlc_id, ref err_packet, .. } => {
8179+
HTLCForwardInfo::FailHTLC { htlc_id, ref err_packet, monitor_event_source } => {
81808180
if let Some(chan) = peer_state
81818181
.channel_by_id
81828182
.get_mut(&forward_chan_id)
81838183
.and_then(Channel::as_funded_mut)
81848184
{
81858185
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
81868186
log_trace!(logger, "Failing HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id);
8187-
Some((chan.queue_fail_htlc(htlc_id, err_packet.clone(), &&logger), htlc_id))
8187+
Some((
8188+
chan.queue_fail_htlc(
8189+
htlc_id,
8190+
err_packet.clone(),
8191+
monitor_event_source,
8192+
&&logger,
8193+
),
8194+
htlc_id,
8195+
))
81888196
} else {
81898197
self.forwarding_channel_not_found(
81908198
core::iter::once(forward_info).chain(draining_pending_forwards),
@@ -8200,7 +8208,7 @@ impl<
82008208
htlc_id,
82018209
failure_code,
82028210
sha256_of_onion,
8203-
..
8211+
monitor_event_source,
82048212
} => {
82058213
if let Some(chan) = peer_state
82068214
.channel_by_id
@@ -8213,6 +8221,7 @@ impl<
82138221
htlc_id,
82148222
failure_code,
82158223
sha256_of_onion,
8224+
monitor_event_source,
82168225
&&logger,
82178226
);
82188227
Some((res, htlc_id))

0 commit comments

Comments
 (0)