Skip to content

Commit b5f80c2

Browse files
Refactor: move channel checks for HTLC adds into Channel
This also includes adding a closure that creates a new pending HTLC status as a parameter for Channel's update_add_htlc. This will later be useful when we add the check for fee spike buffer violations, which will also result in changing an HTLC's pending status to failing.
1 parent 2087032 commit b5f80c2

File tree

2 files changed

+40
-28
lines changed

2 files changed

+40
-28
lines changed

lightning/src/ln/channel.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,8 +1665,19 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
16651665
cmp::min(self.value_to_self_msat as i64 - self.get_outbound_pending_htlc_stats().1 as i64, 0) as u64)
16661666
}
16671667

1668-
pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingHTLCStatus) -> Result<(), ChannelError> {
1669-
if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) {
1668+
pub fn update_add_htlc<F>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_state: PendingHTLCStatus, create_pending_htlc_status: F) -> Result<(), ChannelError>
1669+
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus {
1670+
if !self.is_usable() {
1671+
// TODO: Note that |20 is defined as "channel FROM the processing
1672+
// node has been disabled" (emphasis mine), which seems to imply
1673+
// that we can't return |20 for an inbound channel being disabled.
1674+
// This probably needs a spec update but should definitely be
1675+
// allowed.
1676+
pending_forward_state = create_pending_htlc_status(self, pending_forward_state, 0x1000|20);
1677+
}
1678+
// If the remote has sent a shutdown prior to adding this HTLC, then they are in violation of the spec.
1679+
let remote_sent_shutdown = (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32);
1680+
if remote_sent_shutdown {
16701681
return Err(ChannelError::Close("Got add HTLC message when channel was not in an operational state"));
16711682
}
16721683
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {

lightning/src/ln/channelmanager.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,47 +2472,48 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
24722472
//encrypted with the same key. It's not immediately obvious how to usefully exploit that,
24732473
//but we should prevent it anyway.
24742474

2475-
let (mut pending_forward_info, mut channel_state_lock) = self.decode_update_add_htlc_onion(msg);
2475+
let (pending_forward_info, mut channel_state_lock) = self.decode_update_add_htlc_onion(msg);
24762476
let channel_state = &mut *channel_state_lock;
24772477

24782478
match channel_state.by_id.entry(msg.channel_id) {
24792479
hash_map::Entry::Occupied(mut chan) => {
24802480
if chan.get().get_their_node_id() != *their_node_id {
24812481
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
24822482
}
2483-
if !chan.get().is_usable() {
2483+
2484+
let create_pending_htlc_status = |chan: &Channel<ChanSigner>, pending_forward_info: PendingHTLCStatus, error_code: u16| {
24842485
// If the update_add is completely bogus, the call will Err and we will close,
24852486
// but if we've sent a shutdown and they haven't acknowledged it yet, we just
24862487
// want to reject the new HTLC and fail it backwards instead of forwarding.
2487-
if let PendingHTLCStatus::Forward(PendingHTLCInfo { incoming_shared_secret, .. }) = pending_forward_info {
2488-
let chan_update = self.get_channel_update(chan.get());
2489-
pending_forward_info = PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
2490-
channel_id: msg.channel_id,
2491-
htlc_id: msg.htlc_id,
2492-
reason: if let Ok(update) = chan_update {
2493-
// TODO: Note that |20 is defined as "channel FROM the processing
2494-
// node has been disabled" (emphasis mine), which seems to imply
2495-
// that we can't return |20 for an inbound channel being disabled.
2496-
// This probably needs a spec update but should definitely be
2497-
// allowed.
2498-
onion_utils::build_first_hop_failure_packet(&incoming_shared_secret, 0x1000|20, &{
2488+
match pending_forward_info {
2489+
PendingHTLCStatus::Forward(PendingHTLCInfo { ref incoming_shared_secret, .. }) => {
2490+
// The only case where we'd be unable to successfully get a channel
2491+
// update here is if the channel isn't in the fully-funded
2492+
// state yet, implying our counterparty is trying to route payments
2493+
// over the channel back to themselves (cause no one else should
2494+
// know the short_id is a lightning channel yet). We should have no
2495+
// problem just calling this unknown_next_peer, as above (0x4000|10).
2496+
let reason = if let Ok(upd) = self.get_channel_update(chan) {
2497+
onion_utils::build_first_hop_failure_packet(incoming_shared_secret, error_code, &{
24992498
let mut res = Vec::with_capacity(8 + 128);
2500-
res.extend_from_slice(&byte_utils::be16_to_array(update.contents.flags));
2501-
res.extend_from_slice(&update.encode_with_len()[..]);
2499+
res.extend_from_slice(&byte_utils::be16_to_array(upd.contents.flags));
2500+
res.extend_from_slice(&upd.encode_with_len()[..]);
25022501
res
25032502
}[..])
25042503
} else {
2505-
// This can only happen if the channel isn't in the fully-funded
2506-
// state yet, implying our counterparty is trying to route payments
2507-
// over the channel back to themselves (cause no one else should
2508-
// know the short_id is a lightning channel yet). We should have no
2509-
// problem just calling this unknown_next_peer
2510-
onion_utils::build_first_hop_failure_packet(&incoming_shared_secret, 0x4000|10, &[])
2511-
},
2512-
}));
2504+
onion_utils::build_first_hop_failure_packet(incoming_shared_secret, 0x4000|10, &[])
2505+
};
2506+
let msg = msgs::UpdateFailHTLC {
2507+
channel_id: msg.channel_id,
2508+
htlc_id: msg.htlc_id,
2509+
reason
2510+
};
2511+
PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msg))
2512+
},
2513+
_ => pending_forward_info
25132514
}
2514-
}
2515-
try_chan_entry!(self, chan.get_mut().update_add_htlc(&msg, pending_forward_info), channel_state, chan);
2515+
};
2516+
try_chan_entry!(self, chan.get_mut().update_add_htlc(&msg, pending_forward_info, create_pending_htlc_status), channel_state, chan);
25162517
},
25172518
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
25182519
}

0 commit comments

Comments
 (0)