Skip to content

Commit fac7774

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 0eb6190 commit fac7774

2 files changed

Lines changed: 47 additions & 18 deletions

File tree

lightning/src/ln/channel.rs

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6457,7 +6457,9 @@ trait FailHTLCContents {
64576457
type Message: FailHTLCMessageName;
64586458
fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message;
64596459
fn to_inbound_htlc_state(self) -> InboundHTLCState;
6460-
fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK;
6460+
fn to_htlc_update_awaiting_ack(
6461+
self, htlc_id: u64, monitor_event_source: Option<MonitorEventSource>,
6462+
) -> HTLCUpdateAwaitingACK;
64616463
}
64626464
impl FailHTLCContents for msgs::OnionErrorPacket {
64636465
type Message = msgs::UpdateFailHTLC;
@@ -6472,8 +6474,10 @@ impl FailHTLCContents for msgs::OnionErrorPacket {
64726474
fn to_inbound_htlc_state(self) -> InboundHTLCState {
64736475
InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(self))
64746476
}
6475-
fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK {
6476-
HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet: self, monitor_event_source: None }
6477+
fn to_htlc_update_awaiting_ack(
6478+
self, htlc_id: u64, monitor_event_source: Option<MonitorEventSource>,
6479+
) -> HTLCUpdateAwaitingACK {
6480+
HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet: self, monitor_event_source }
64776481
}
64786482
}
64796483
impl FailHTLCContents for ([u8; 32], u16) {
@@ -6492,12 +6496,14 @@ impl FailHTLCContents for ([u8; 32], u16) {
64926496
failure_code: self.1,
64936497
})
64946498
}
6495-
fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK {
6499+
fn to_htlc_update_awaiting_ack(
6500+
self, htlc_id: u64, monitor_event_source: Option<MonitorEventSource>,
6501+
) -> HTLCUpdateAwaitingACK {
64966502
HTLCUpdateAwaitingACK::FailMalformedHTLC {
64976503
htlc_id,
64986504
sha256_of_onion: self.0,
64996505
failure_code: self.1,
6500-
monitor_event_source: None,
6506+
monitor_event_source,
65016507
}
65026508
}
65036509
}
@@ -7190,9 +7196,10 @@ where
71907196
/// Returns `Err` (always with [`ChannelError::Ignore`]) if the HTLC could not be failed (e.g.
71917197
/// if it was already resolved). Otherwise returns `Ok`.
71927198
pub fn queue_fail_htlc<L: Logger>(
7193-
&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, logger: &L,
7199+
&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket,
7200+
monitor_event_source: Option<MonitorEventSource>, logger: &L,
71947201
) -> Result<(), ChannelError> {
7195-
self.fail_htlc(htlc_id_arg, err_packet, true, logger)
7202+
self.fail_htlc(htlc_id_arg, err_packet, true, monitor_event_source, logger)
71967203
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
71977204
}
71987205

@@ -7201,18 +7208,25 @@ where
72017208
///
72027209
/// See [`Self::queue_fail_htlc`] for more info.
72037210
pub fn queue_fail_malformed_htlc<L: Logger>(
7204-
&mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32], logger: &L,
7211+
&mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32],
7212+
monitor_event_source: Option<MonitorEventSource>, logger: &L,
72057213
) -> Result<(), ChannelError> {
7206-
self.fail_htlc(htlc_id_arg, (sha256_of_onion, failure_code), true, logger)
7207-
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
7214+
self.fail_htlc(
7215+
htlc_id_arg,
7216+
(sha256_of_onion, failure_code),
7217+
true,
7218+
monitor_event_source,
7219+
logger,
7220+
)
7221+
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
72087222
}
72097223

72107224
/// Returns `Err` (always with [`ChannelError::Ignore`]) if the HTLC could not be failed (e.g.
72117225
/// if it was already resolved). Otherwise returns `Ok`.
72127226
#[rustfmt::skip]
72137227
fn fail_htlc<L: Logger, E: FailHTLCContents + Clone>(
72147228
&mut self, htlc_id_arg: u64, err_contents: E, mut force_holding_cell: bool,
7215-
logger: &L
7229+
monitor_event_source: Option<MonitorEventSource>, logger: &L
72167230
) -> Result<Option<E::Message>, ChannelError> {
72177231
if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
72187232
panic!("Was asked to fail an HTLC when channel was not in an operational state");
@@ -7267,7 +7281,7 @@ where
72677281
}
72687282
}
72697283
log_trace!(logger, "Placing failure for HTLC ID {} in holding cell.", htlc_id_arg);
7270-
self.context.holding_cell_htlc_updates.push(err_contents.to_htlc_update_awaiting_ack(htlc_id_arg));
7284+
self.context.holding_cell_htlc_updates.push(err_contents.to_htlc_update_awaiting_ack(htlc_id_arg, monitor_event_source));
72717285
return Ok(None);
72727286
}
72737287

@@ -8297,7 +8311,7 @@ where
82978311
None
82988312
},
82998313
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, ref err_packet, .. } => Some(
8300-
self.fail_htlc(htlc_id, err_packet.clone(), false, logger)
8314+
self.fail_htlc(htlc_id, err_packet.clone(), false, None, logger)
83018315
.map(|fail_msg_opt| fail_msg_opt.map(|_| ())),
83028316
),
83038317
&HTLCUpdateAwaitingACK::FailMalformedHTLC {
@@ -8306,8 +8320,14 @@ where
83068320
sha256_of_onion,
83078321
..
83088322
} => Some(
8309-
self.fail_htlc(htlc_id, (sha256_of_onion, failure_code), false, logger)
8310-
.map(|fail_msg_opt| fail_msg_opt.map(|_| ())),
8323+
self.fail_htlc(
8324+
htlc_id,
8325+
(sha256_of_onion, failure_code),
8326+
false,
8327+
None,
8328+
logger,
8329+
)
8330+
.map(|fail_msg_opt| fail_msg_opt.map(|_| ())),
83118331
),
83128332
};
83138333
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
@@ -8079,15 +8079,23 @@ impl<
80798079
}
80808080
None
80818081
},
8082-
HTLCForwardInfo::FailHTLC { htlc_id, ref err_packet, .. } => {
8082+
HTLCForwardInfo::FailHTLC { htlc_id, ref err_packet, monitor_event_source } => {
80838083
if let Some(chan) = peer_state
80848084
.channel_by_id
80858085
.get_mut(&forward_chan_id)
80868086
.and_then(Channel::as_funded_mut)
80878087
{
80888088
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
80898089
log_trace!(logger, "Failing HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id);
8090-
Some((chan.queue_fail_htlc(htlc_id, err_packet.clone(), &&logger), htlc_id))
8090+
Some((
8091+
chan.queue_fail_htlc(
8092+
htlc_id,
8093+
err_packet.clone(),
8094+
monitor_event_source,
8095+
&&logger,
8096+
),
8097+
htlc_id,
8098+
))
80918099
} else {
80928100
self.forwarding_channel_not_found(
80938101
core::iter::once(forward_info).chain(draining_pending_forwards),
@@ -8103,7 +8111,7 @@ impl<
81038111
htlc_id,
81048112
failure_code,
81058113
sha256_of_onion,
8106-
..
8114+
monitor_event_source,
81078115
} => {
81088116
if let Some(chan) = peer_state
81098117
.channel_by_id
@@ -8116,6 +8124,7 @@ impl<
81168124
htlc_id,
81178125
failure_code,
81188126
sha256_of_onion,
8127+
monitor_event_source,
81198128
&&logger,
81208129
);
81218130
Some((res, htlc_id))

0 commit comments

Comments
 (0)