Skip to content

Commit 7e95dae

Browse files
committed
(XXX NEEDS TEST) Use the correct SCID when failing HTLCs to aliased channels
When we fail an HTLC which was destined for a channel that the HTLC sender didn't know the real SCID for, we should ensure we continue to use the alias in the channel_update we provide them. Otherwise we will leak the channel's real SCID to HTLC senders.
1 parent 2e96004 commit 7e95dae

File tree

1 file changed

+34
-7
lines changed

1 file changed

+34
-7
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2524,6 +2524,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25242524
Some(id) => id,
25252525
};
25262526

2527+
self.get_channel_update_for_onion(short_channel_id, chan)
2528+
}
2529+
fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel<Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
2530+
log_trace!(self.logger, "Generating channel update for channel {}", log_bytes!(chan.channel_id()));
25272531
let were_node_one = PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).serialize()[..] < chan.get_counterparty_node_id().serialize()[..];
25282532

25292533
let unsigned = msgs::UnsignedChannelUpdate {
@@ -3213,7 +3217,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32133217
} else {
32143218
panic!("Stated return value requirements in send_htlc() were not met");
32153219
}
3216-
let (failure_code, data) = self.get_htlc_temp_fail_err_and_data(0x1000|7, chan.get());
3220+
let (failure_code, data) = self.get_htlc_temp_fail_err_and_data(0x1000|7, short_chan_id, chan.get());
32173221
failed_forwards.push((htlc_source, payment_hash,
32183222
HTLCFailReason::Reason { failure_code, data }
32193223
));
@@ -3713,9 +3717,32 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
37133717

37143718
/// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code
37153719
/// that we want to return and a channel.
3716-
fn get_htlc_temp_fail_err_and_data(&self, desired_err_code: u16, chan: &Channel<Signer>) -> (u16, Vec<u8>) {
3720+
///
3721+
/// This is for failures on the channel on which the HTLC was *received*, not failures
3722+
/// forwarding
3723+
fn get_htlc_inbound_temp_fail_err_and_data(&self, desired_err_code: u16, chan: &Channel<Signer>) -> (u16, Vec<u8>) {
3724+
// We can't be sure what SCID was used when relaying inbound towards us, so we have to
3725+
// guess somewhat. If its a public channel, we figure best to just use the real SCID (as
3726+
// we're not leaking that we have a channel with the counterparty), otherwise we try to use
3727+
// an inbound SCID alias before the real SCID.
3728+
let scid_pref = if chan.should_announce() {
3729+
chan.get_short_channel_id().or(chan.latest_inbound_scid_alias())
3730+
} else {
3731+
chan.latest_inbound_scid_alias().or(chan.get_short_channel_id())
3732+
};
3733+
if let Some(scid) = scid_pref {
3734+
self.get_htlc_temp_fail_err_and_data(desired_err_code, scid, chan)
3735+
} else {
3736+
(0x4000|10, Vec::new())
3737+
}
3738+
}
3739+
3740+
3741+
/// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code
3742+
/// that we want to return and a channel.
3743+
fn get_htlc_temp_fail_err_and_data(&self, desired_err_code: u16, scid: u64, chan: &Channel<Signer>) -> (u16, Vec<u8>) {
37173744
debug_assert_eq!(desired_err_code & 0x1000, 0x1000);
3718-
if let Ok(upd) = self.get_channel_update_for_unicast(chan) {
3745+
if let Ok(upd) = self.get_channel_update_for_onion(scid, chan) {
37193746
let enc = if desired_err_code == 0x1000 | 20 {
37203747
let mut res = Vec::new();
37213748
// TODO: underspecified, follow https://github.com/lightning/bolts/issues/791
@@ -3743,7 +3770,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
37433770
let (failure_code, onion_failure_data) =
37443771
match self.channel_state.lock().unwrap().by_id.entry(channel_id) {
37453772
hash_map::Entry::Occupied(chan_entry) => {
3746-
self.get_htlc_temp_fail_err_and_data(0x1000|7, &chan_entry.get())
3773+
self.get_htlc_inbound_temp_fail_err_and_data(0x1000|7, &chan_entry.get())
37473774
},
37483775
hash_map::Entry::Vacant(_) => (0x4000|10, Vec::new())
37493776
};
@@ -4633,7 +4660,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46334660
match pending_forward_info {
46344661
PendingHTLCStatus::Forward(PendingHTLCInfo { ref incoming_shared_secret, .. }) => {
46354662
let reason = if (error_code & 0x1000) != 0 {
4636-
let (real_code, error_data) = self.get_htlc_temp_fail_err_and_data(error_code, chan);
4663+
let (real_code, error_data) = self.get_htlc_inbound_temp_fail_err_and_data(error_code, chan);
46374664
onion_utils::build_first_hop_failure_packet(incoming_shared_secret, real_code, &error_data)
46384665
} else {
46394666
onion_utils::build_first_hop_failure_packet(incoming_shared_secret, error_code, &[])
@@ -5626,8 +5653,8 @@ where
56265653
let res = f(channel);
56275654
if let Ok((funding_locked_opt, mut timed_out_pending_htlcs, announcement_sigs)) = res {
56285655
for (source, payment_hash) in timed_out_pending_htlcs.drain(..) {
5629-
let (failure_code, data) = self.get_htlc_temp_fail_err_and_data(0x1000|14 /* expiry_too_soon */, &channel);
5630-
timed_out_htlcs.push((source, payment_hash, HTLCFailReason::Reason {
5656+
let (failure_code, data) = self.get_htlc_inbound_temp_fail_err_and_data(0x1000|14 /* expiry_too_soon */, &channel);
5657+
timed_out_htlcs.push((source, payment_hash, HTLCFailReason::Reason {
56315658
failure_code, data,
56325659
}));
56335660
}

0 commit comments

Comments
 (0)