Skip to content

Commit b36589c

Browse files
Impl Jeff refactor: the advantage is that it keeps channel checks and updating pending_forward_info inside Channel rather than split between Channel and ChannelManager.
1 parent e86cecf commit b36589c

File tree

2 files changed

+61
-62
lines changed

2 files changed

+61
-62
lines changed

lightning/src/ln/channel.rs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,8 +1733,18 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17331733
self.commit_tx_fee_msat(their_acked_htlcs + addl_htlcs)
17341734
}
17351735

1736-
pub fn update_add_htlc<F>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_state: PendingHTLCStatus, create_onion_error_packet: F) -> Result<(), ChannelError>
1737-
where F: for<'a, 'b> Fn(&'a Self, &'b PendingHTLCStatus) -> Option<msgs::OnionErrorPacket> {
1736+
pub fn update_add_htlc<F>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_state: PendingHTLCStatus, create_pending_htlc_status: F) -> Result<(), ChannelError>
1737+
where F: for<'a, 'b> Fn(&'a Self, &'b PendingHTLCStatus, u16) -> Option<PendingHTLCStatus> {
1738+
if !self.is_usable() {
1739+
// TODO: Note that |20 is defined as "channel FROM the processing
1740+
// node has been disabled" (emphasis mine), which seems to imply
1741+
// that we can't return |20 for an inbound channel being disabled.
1742+
// This probably needs a spec update but should definitely be
1743+
// allowed.
1744+
if let Some(new_state) = create_pending_htlc_status(self, &pending_forward_state, 0x1000|20) {
1745+
pending_forward_state = new_state;
1746+
}
1747+
}
17381748
if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) {
17391749
return Err(ChannelError::Close("Got add HTLC message when channel was not in an operational state"));
17401750
}
@@ -1807,13 +1817,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
18071817
// but should help protect us from stuck channels).
18081818
let remote_fee_cost_incl_stuck_buffer_msat = 2 * self.next_remote_commit_tx_fee_msat(1 + 1);
18091819
if pending_remote_value_msat - msg.amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
1810-
let onion_error_packet = create_onion_error_packet(self, &pending_forward_state);
1811-
if let Some(reason) = onion_error_packet {
1812-
pending_forward_state = PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
1813-
channel_id: msg.channel_id,
1814-
htlc_id: msg.htlc_id,
1815-
reason,
1816-
}));
1820+
if let Some(new_state) = create_pending_htlc_status(self, &pending_forward_state, 0x1000|7) {
1821+
pending_forward_state = new_state;
18171822
}
18181823
}
18191824
} else {
@@ -4431,11 +4436,11 @@ mod tests {
44314436
use bitcoin::network::constants::Network;
44324437
use bitcoin::hashes::hex::FromHex;
44334438
use hex;
4434-
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash, PendingHTLCStatus, PendingHTLCInfo, PendingHTLCRouting};
4439+
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash, PendingHTLCStatus, PendingHTLCInfo, PendingHTLCRouting, HTLCFailureMsg};
44354440
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys, ChannelError};
44364441
use ln::channel::MAX_FUNDING_SATOSHIS;
44374442
use ln::features::{InitFeatures, NodeFeatures};
4438-
use ln::msgs::{OptionalField, DataLossProtect, UpdateAddHTLC, OnionErrorPacket, OnionPacket};
4443+
use ln::msgs::{OptionalField, DataLossProtect, UpdateAddHTLC, UpdateFailHTLC, OnionErrorPacket, OnionPacket};
44394444
use ln::{chan_utils, onion_utils};
44404445
use ln::chan_utils::{LocalCommitmentTransaction, ChannelPublicKeys};
44414446
use ln::features::ChannelFeatures;
@@ -4691,12 +4696,18 @@ mod tests {
46914696
amt_to_forward: max_can_recv + 1,
46924697
outgoing_cltv_value: htlc_cltv
46934698
});
4694-
let create_onion_closure = |_chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus| {
4695-
Some(OnionErrorPacket{ data: vec![] })
4699+
let create_pending_htlc_status = |chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus, _error_code: u16| {
4700+
Some(PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(
4701+
UpdateFailHTLC{
4702+
channel_id: chan.channel_id,
4703+
htlc_id: 0,
4704+
reason: OnionErrorPacket { data: vec![] },
4705+
}
4706+
)))
46964707
};
46974708

46984709
// Assert that the HTLC was successfully added.
4699-
assert!(chans[1].update_add_htlc(&msg, pending_forward_state, create_onion_closure).is_ok());
4710+
assert!(chans[1].update_add_htlc(&msg, pending_forward_state, &create_pending_htlc_status).is_ok());
47004711

47014712
// Check that the HTLC's pending status is failed.
47024713
match &chans[1].pending_inbound_htlcs[0].state {
@@ -4707,8 +4718,14 @@ mod tests {
47074718
}
47084719

47094720
// Check that adding an HTLC worth 1 msat less will succeed.
4710-
let create_onion_closure = |_chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus| {
4711-
Some(OnionErrorPacket{ data: vec![] })
4721+
let create_pending_htlc_status = |chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus, _error_code: u16| {
4722+
Some(PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(
4723+
UpdateFailHTLC{
4724+
channel_id: chan.channel_id,
4725+
htlc_id: 0,
4726+
reason: OnionErrorPacket { data: vec![] },
4727+
}
4728+
)))
47124729
};
47134730
chans[1].pending_inbound_htlcs = vec![];
47144731
let pending_forward_state = PendingHTLCStatus::Forward(PendingHTLCInfo{
@@ -4720,7 +4737,7 @@ mod tests {
47204737
});
47214738
msg.htlc_id = 1;
47224739
msg.amount_msat = max_can_recv;
4723-
assert!(chans[1].update_add_htlc(&msg, pending_forward_state, create_onion_closure).is_ok());
4740+
assert!(chans[1].update_add_htlc(&msg, pending_forward_state, &create_pending_htlc_status).is_ok());
47244741
match &chans[1].pending_inbound_htlcs[0].state {
47254742
&InboundHTLCState::RemoteAnnounced(ref state) => {
47264743
if let &PendingHTLCStatus::Forward(_) = state { } else { panic!() }
@@ -4784,11 +4801,11 @@ mod tests {
47844801
outgoing_cltv_value: htlc_cltv
47854802
});
47864803

4787-
let create_onion_closure = |_chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus| {
4804+
let create_pending_htlc_status = |_chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus, _error_code: u16| {
47884805
None
47894806
};
47904807

4791-
match chans[0].update_add_htlc(&msg, pending_forward_state, create_onion_closure) {
4808+
match chans[0].update_add_htlc(&msg, pending_forward_state, &create_pending_htlc_status) {
47924809
Err(ChannelError::Ignore(msg)) => assert_eq!(msg, "Cannot receive value that would put us under local channel reserve value"),
47934810
_ => panic!()
47944811
}

lightning/src/ln/channelmanager.rs

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,65 +2495,47 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
24952495
//encrypted with the same key. It's not immediately obvious how to usefully exploit that,
24962496
//but we should prevent it anyway.
24972497

2498-
let (mut pending_forward_info, mut channel_state_lock) = self.decode_update_add_htlc_onion(msg);
2498+
let (pending_forward_info, mut channel_state_lock) = self.decode_update_add_htlc_onion(msg);
24992499
let channel_state = &mut *channel_state_lock;
25002500

25012501
match channel_state.by_id.entry(msg.channel_id) {
25022502
hash_map::Entry::Occupied(mut chan) => {
25032503
if chan.get().get_their_node_id() != *their_node_id {
25042504
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
25052505
}
2506-
if !chan.get().is_usable() {
2506+
2507+
let create_pending_htlc_status = |chan: &Channel<ChanSigner>, pending_forward_info: &PendingHTLCStatus, error_code: u16| {
25072508
// If the update_add is completely bogus, the call will Err and we will close,
25082509
// but if we've sent a shutdown and they haven't acknowledged it yet, we just
25092510
// want to reject the new HTLC and fail it backwards instead of forwarding.
2510-
if let PendingHTLCStatus::Forward(PendingHTLCInfo { incoming_shared_secret, .. }) = pending_forward_info {
2511-
let chan_update = self.get_channel_update(chan.get());
2512-
pending_forward_info = PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
2513-
channel_id: msg.channel_id,
2514-
htlc_id: msg.htlc_id,
2515-
reason: if let Ok(update) = chan_update {
2516-
// TODO: Note that |20 is defined as "channel FROM the processing
2517-
// node has been disabled" (emphasis mine), which seems to imply
2518-
// that we can't return |20 for an inbound channel being disabled.
2519-
// This probably needs a spec update but should definitely be
2520-
// allowed.
2521-
onion_utils::build_first_hop_failure_packet(&incoming_shared_secret, 0x1000|20, &{
2522-
let mut res = Vec::with_capacity(8 + 128);
2523-
res.extend_from_slice(&byte_utils::be16_to_array(update.contents.flags));
2524-
res.extend_from_slice(&update.encode_with_len()[..]);
2525-
res
2526-
}[..])
2527-
} else {
2528-
// This can only happen if the channel isn't in the fully-funded
2529-
// state yet, implying our counterparty is trying to route payments
2530-
// over the channel back to themselves (cause no one else should
2531-
// know the short_id is a lightning channel yet). We should have no
2532-
// problem just calling this unknown_next_peer
2533-
onion_utils::build_first_hop_failure_packet(&incoming_shared_secret, 0x4000|10, &[])
2534-
},
2535-
}));
2536-
}
2537-
}
2538-
let create_onion_error_packet = |chan: &Channel<ChanSigner>, pending_forward_info: &PendingHTLCStatus| {
25392511
match pending_forward_info {
25402512
&PendingHTLCStatus::Forward(PendingHTLCInfo { ref incoming_shared_secret, .. }) => {
2541-
match self.get_channel_update(chan) {
2542-
Ok(upd) => {
2543-
Some(onion_utils::build_first_hop_failure_packet(incoming_shared_secret, 0x1000|7, &{
2544-
let mut res = Vec::with_capacity(8 + 128);
2545-
res.extend_from_slice(&byte_utils::be16_to_array(upd.contents.flags));
2546-
res.extend_from_slice(&upd.encode_with_len()[..]);
2547-
res
2548-
}[..]))
2549-
},
2550-
Err(_) => None,
2513+
let mut reason = onion_utils::build_first_hop_failure_packet(incoming_shared_secret, 0x4000|10, &[]);
2514+
// The only case where we'd be unable to successfully get a channel
2515+
// update here is if the channel isn't in the fully-funded
2516+
// state yet, implying our counterparty is trying to route payments
2517+
// over the channel back to themselves (cause no one else should
2518+
// know the short_id is a lightning channel yet). We should have no
2519+
// problem just calling this unknown_next_peer, as above (0x4000|10).
2520+
if let Ok(upd) = self.get_channel_update(chan) {
2521+
reason = onion_utils::build_first_hop_failure_packet(incoming_shared_secret, error_code, &{
2522+
let mut res = Vec::with_capacity(8 + 128);
2523+
res.extend_from_slice(&byte_utils::be16_to_array(upd.contents.flags));
2524+
res.extend_from_slice(&upd.encode_with_len()[..]);
2525+
res
2526+
}[..]);
25512527
}
2528+
let msg = msgs::UpdateFailHTLC {
2529+
channel_id: msg.channel_id,
2530+
htlc_id: msg.htlc_id,
2531+
reason
2532+
};
2533+
Some(PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msg)))
25522534
},
2553-
_ => None,
2535+
_ => None
25542536
}
25552537
};
2556-
try_chan_entry!(self, chan.get_mut().update_add_htlc(&msg, pending_forward_info, create_onion_error_packet), channel_state, chan);
2538+
try_chan_entry!(self, chan.get_mut().update_add_htlc(&msg, pending_forward_info, create_pending_htlc_status), channel_state, chan);
25572539
},
25582540
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
25592541
}

0 commit comments

Comments
 (0)