Skip to content

Commit 98be4e8

Browse files
committed
Decode fully committed incoming HTLC onions upon channel resumption
This is currently done as soon as we receive the `UpdateAddHTLC` message, but it will be phased out as we transition to decoding incoming HTLC onions once the HTLC has been fully committed to by both sides. Doing so within the monitor update completion path meshes well as it already handles forwarding and failing back HTLCs – the two possible outcomes of decoding an incoming HTLC onion.
1 parent 0951b7f commit 98be4e8

File tree

2 files changed

+64
-13
lines changed

2 files changed

+64
-13
lines changed

lightning/src/ln/channel.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -4240,13 +4240,15 @@ impl<SP: Deref> Channel<SP> where
42404240
mem::swap(&mut failed_htlcs, &mut self.context.monitor_pending_failures);
42414241
let mut finalized_claimed_htlcs = Vec::new();
42424242
mem::swap(&mut finalized_claimed_htlcs, &mut self.context.monitor_pending_finalized_fulfills);
4243+
let mut pending_htlc_status = Vec::new();
4244+
mem::swap(&mut pending_htlc_status, &mut self.context.monitor_pending_htlc_status);
42434245

42444246
if self.context.channel_state.is_peer_disconnected() {
42454247
self.context.monitor_pending_revoke_and_ack = false;
42464248
self.context.monitor_pending_commitment_signed = false;
42474249
return MonitorRestoreUpdates {
42484250
raa: None, commitment_update: None, order: RAACommitmentOrder::RevokeAndACKFirst,
4249-
accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, channel_ready, announcement_sigs
4251+
accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, pending_htlc_status, funding_broadcastable, channel_ready, announcement_sigs
42504252
};
42514253
}
42524254

@@ -4268,7 +4270,7 @@ impl<SP: Deref> Channel<SP> where
42684270
if commitment_update.is_some() { "a" } else { "no" }, if raa.is_some() { "an" } else { "no" },
42694271
match order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"});
42704272
MonitorRestoreUpdates {
4271-
raa, commitment_update, order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, channel_ready, announcement_sigs
4273+
raa, commitment_update, order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, pending_htlc_status, funding_broadcastable, channel_ready, announcement_sigs
42724274
}
42734275
}
42744276

lightning/src/ln/channelmanager.rs

+60-11
Original file line numberDiff line numberDiff line change
@@ -2189,16 +2189,17 @@ macro_rules! handle_monitor_update_completion {
21892189
let update_actions = $peer_state.monitor_update_blocked_actions
21902190
.remove(&$chan.context.channel_id()).unwrap_or(Vec::new());
21912191

2192-
let htlc_forwards = $self.handle_channel_resumption(
2192+
let (htlc_forwards, mut htlc_fails) = $self.handle_channel_resumption(
21932193
&mut $peer_state.pending_msg_events, $chan, updates.raa,
2194-
updates.commitment_update, updates.order, updates.accepted_htlcs,
2194+
updates.commitment_update, updates.order, updates.accepted_htlcs, updates.pending_htlc_status,
21952195
updates.funding_broadcastable, updates.channel_ready,
21962196
updates.announcement_sigs);
21972197
if let Some(upd) = channel_update {
21982198
$peer_state.pending_msg_events.push(upd);
21992199
}
22002200

22012201
let channel_id = $chan.context.channel_id();
2202+
let scid = $chan.context.get_short_channel_id().or($chan.context.latest_inbound_scid_alias());
22022203
let unbroadcasted_batch_funding_txid = $chan.context.unbroadcasted_batch_funding_txid();
22032204
core::mem::drop($peer_state_lock);
22042205
core::mem::drop($per_peer_state_lock);
@@ -2253,6 +2254,37 @@ macro_rules! handle_monitor_update_completion {
22532254
$self.forward_htlcs(&mut [forwards][..]);
22542255
}
22552256
$self.finalize_claims(updates.finalized_claimed_htlcs);
2257+
for (htlc_fail, outgoing_scid) in htlc_fails.drain(..) {
2258+
if let Some(scid) = scid {
2259+
let (channel_id, failure) = match htlc_fail {
2260+
HTLCFailureMsg::Relay(fail_htlc) => (fail_htlc.channel_id, HTLCForwardInfo::FailHTLC {
2261+
htlc_id: fail_htlc.htlc_id,
2262+
err_packet: fail_htlc.reason,
2263+
}),
2264+
HTLCFailureMsg::Malformed(fail_malformed_htlc) => (fail_malformed_htlc.channel_id, HTLCForwardInfo::FailMalformedHTLC {
2265+
htlc_id: fail_malformed_htlc.htlc_id,
2266+
sha256_of_onion: fail_malformed_htlc.sha256_of_onion,
2267+
failure_code: fail_malformed_htlc.failure_code,
2268+
}),
2269+
};
2270+
let destination = if let Some(outgoing_scid) = outgoing_scid {
2271+
match $self.short_to_chan_info.read().unwrap().get(&outgoing_scid) {
2272+
Some((_, outgoing_channel_id)) => HTLCDestination::NextHopChannel {
2273+
node_id: Some(counterparty_node_id),
2274+
channel_id: *outgoing_channel_id,
2275+
},
2276+
None => HTLCDestination::UnknownNextHop {
2277+
requested_forward_scid: outgoing_scid,
2278+
},
2279+
}
2280+
} else {
2281+
HTLCDestination::InvalidOnion
2282+
};
2283+
$self.push_htlc_failure(scid, channel_id, failure, destination);
2284+
} else {
2285+
debug_assert!(false, "Channel with failed HTLC should have a real/alias short_channel_id")
2286+
}
2287+
}
22562288
for failure in updates.failed_htlcs.drain(..) {
22572289
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
22582290
$self.fail_htlc_backwards_internal(&failure.0, &failure.1, &failure.2, receiver);
@@ -5871,9 +5903,10 @@ where
58715903
fn handle_channel_resumption(&self, pending_msg_events: &mut Vec<MessageSendEvent>,
58725904
channel: &mut Channel<SP>, raa: Option<msgs::RevokeAndACK>,
58735905
commitment_update: Option<msgs::CommitmentUpdate>, order: RAACommitmentOrder,
5874-
pending_forwards: Vec<(PendingHTLCInfo, u64)>, funding_broadcastable: Option<Transaction>,
5906+
mut pending_forwards: Vec<(PendingHTLCInfo, u64)>, pending_htlc_status: Vec<msgs::UpdateAddHTLC>,
5907+
funding_broadcastable: Option<Transaction>,
58755908
channel_ready: Option<msgs::ChannelReady>, announcement_sigs: Option<msgs::AnnouncementSignatures>)
5876-
-> Option<(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)> {
5909+
-> (Option<(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)>, Vec<(HTLCFailureMsg, Option<u64>)>) {
58775910
let logger = WithChannelContext::from(&self.logger, &channel.context);
58785911
log_trace!(logger, "Handling channel resumption for channel {} with {} RAA, {} commitment update, {} pending forwards, {}broadcasting funding, {} channel ready, {} announcement",
58795912
&channel.context.channel_id(),
@@ -5884,10 +5917,26 @@ where
58845917
if announcement_sigs.is_some() { "sending" } else { "without" });
58855918

58865919
let mut htlc_forwards = None;
5887-
5920+
let mut htlc_fails = Vec::new();
58885921
let counterparty_node_id = channel.context.get_counterparty_node_id();
5922+
let short_channel_id = channel.context.get_short_channel_id().unwrap_or(channel.context.outbound_scid_alias());
5923+
for update_add_htlc in pending_htlc_status {
5924+
let decoded_hop_res = self.decode_update_add_htlc_onion(&update_add_htlc, &counterparty_node_id, Some(channel));
5925+
match decoded_hop_res {
5926+
Ok((next_hop, shared_secret, next_packet_pk_opt)) => {
5927+
match self.construct_pending_htlc_status(
5928+
&update_add_htlc, &counterparty_node_id, shared_secret, next_hop,
5929+
channel.context.config().accept_underpaying_htlcs, next_packet_pk_opt,
5930+
) {
5931+
PendingHTLCStatus::Forward(htlc_forward) => pending_forwards.push((htlc_forward, update_add_htlc.htlc_id)),
5932+
PendingHTLCStatus::Fail(htlc_fail) => htlc_fails.push((htlc_fail, None)),
5933+
}
5934+
},
5935+
Err(e) => htlc_fails.push(e),
5936+
};
5937+
}
58895938
if !pending_forwards.is_empty() {
5890-
htlc_forwards = Some((channel.context.get_short_channel_id().unwrap_or(channel.context.outbound_scid_alias()),
5939+
htlc_forwards = Some((short_channel_id,
58915940
channel.context.get_funding_txo().unwrap(), channel.context.get_user_id(), pending_forwards));
58925941
}
58935942

@@ -5939,7 +5988,7 @@ where
59395988
emit_channel_ready_event!(pending_events, channel);
59405989
}
59415990

5942-
htlc_forwards
5991+
(htlc_forwards, htlc_fails)
59435992
}
59445993

59455994
fn channel_monitor_updated(&self, funding_txo: &OutPoint, highest_applied_update_id: u64, counterparty_node_id: Option<&PublicKey>) {
@@ -6687,7 +6736,7 @@ where
66876736
msg, counterparty_node_id, shared_secret, next_hop,
66886737
chan.context.config().accept_underpaying_htlcs, next_packet_pk_opt,
66896738
),
6690-
Err(e) => PendingHTLCStatus::Fail(e)
6739+
Err((fail_msg, _)) => PendingHTLCStatus::Fail(fail_msg)
66916740
};
66926741
let create_pending_htlc_status = |chan: &Channel<SP>, pending_forward_info: PendingHTLCStatus, error_code: u16| {
66936742
if msg.blinding_point.is_some() {
@@ -7198,10 +7247,10 @@ where
71987247
}
71997248
}
72007249
let need_lnd_workaround = chan.context.workaround_lnd_bug_4006.take();
7201-
let htlc_forwards = self.handle_channel_resumption(
7250+
let (htlc_forwards, htlc_fails) = self.handle_channel_resumption(
72027251
&mut peer_state.pending_msg_events, chan, responses.raa, responses.commitment_update, responses.order,
7203-
Vec::new(), None, responses.channel_ready, responses.announcement_sigs);
7204-
debug_assert!(htlc_forwards.is_none());
7252+
Vec::new(), Vec::new(), None, responses.channel_ready, responses.announcement_sigs);
7253+
debug_assert!(htlc_forwards.is_none() && htlc_fails.is_empty());
72057254
if let Some(upd) = channel_update {
72067255
peer_state.pending_msg_events.push(upd);
72077256
}

0 commit comments

Comments
 (0)