Skip to content

Commit e64a293

Browse files
committed
WIP: Don't apply PathFailure::ChannelUpdateMessage
If we receive a channel update from an intermediary via a failure onion we shouldn't apply them in a persisted and network-observable way to our network graph, as this might introduce a privacy leak. Here, we therefore avoid applying such updates to our network graph. In order to not reduce our test coverage of channel update appliance too much, we opt to make `PathFailure::ChannelUpdateMessage` `#[cfg(test)]`-only where we continue to use it. However, we still don't apply them to the network graph in tests as otherwise the tested behavior might diverge too much from the production case.
1 parent 1dffb20 commit e64a293

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

lightning/src/ln/functional_test_utils.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2190,6 +2190,7 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
21902190
if let Some(chan_closed) = conditions.expected_blamed_chan_closed {
21912191
if let PathFailure::OnPath { network_update: Some(upd) } = failure {
21922192
match upd {
2193+
#[cfg(test)]
21932194
NetworkUpdate::ChannelUpdateMessage { ref msg } if !chan_closed => {
21942195
if let Some(scid) = conditions.expected_blamed_scid {
21952196
assert_eq!(msg.contents.short_channel_id, scid);

lightning/src/ln/onion_utils.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -635,9 +635,12 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(
635635
} else {
636636
log_info!(logger, "Node provided a channel_update for which it was not authoritative, ignoring.");
637637
}
638-
network_update = Some(NetworkUpdate::ChannelUpdateMessage {
639-
msg: chan_update,
640-
})
638+
#[cfg(test)]
639+
{
640+
network_update = Some(NetworkUpdate::ChannelUpdateMessage {
641+
msg: chan_update,
642+
});
643+
}
641644
} else {
642645
// The node in question intentionally encoded a 0-length channel update. This is
643646
// likely due to https://github.com/ElementsProject/lightning/issues/6200.

lightning/src/routing/gossip.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ pub struct ReadOnlyNetworkGraph<'a> {
208208
pub enum NetworkUpdate {
209209
/// An error indicating a `channel_update` messages should be applied via
210210
/// [`NetworkGraph::update_channel`].
211+
#[cfg(test)]
211212
ChannelUpdateMessage {
212213
/// The update to apply via [`NetworkGraph::update_channel`].
213214
msg: ChannelUpdate,
@@ -232,6 +233,7 @@ pub enum NetworkUpdate {
232233
}
233234
}
234235

236+
#[cfg(test)]
235237
impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate,
236238
(0, ChannelUpdateMessage) => {
237239
(0, msg, required),
@@ -246,6 +248,19 @@ impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate,
246248
},
247249
);
248250

251+
#[cfg(not(test))]
252+
impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate,
253+
// 0 used to be ChannelUpdateMessage in LDK versions prior to 0.0.118
254+
(2, ChannelFailure) => {
255+
(0, short_channel_id, required),
256+
(2, is_permanent, required),
257+
},
258+
(4, NodeFailure) => {
259+
(0, node_id, required),
260+
(2, is_permanent, required),
261+
},
262+
);
263+
249264
/// Receives and validates network updates from peers,
250265
/// stores authentic and relevant data as a network graph.
251266
/// This network graph is then used for routing payments.
@@ -345,12 +360,15 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
345360
/// [`Event`]: crate::events::Event
346361
pub fn handle_network_update(&self, network_update: &NetworkUpdate) {
347362
match *network_update {
363+
#[cfg(test)]
348364
NetworkUpdate::ChannelUpdateMessage { ref msg } => {
349365
let short_channel_id = msg.contents.short_channel_id;
350366
let is_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
351367
let status = if is_enabled { "enabled" } else { "disabled" };
352-
log_debug!(self.logger, "Updating channel with channel_update from a payment failure. Channel {} is {}.", short_channel_id, status);
353-
let _ = self.update_channel(msg);
368+
log_debug!(self.logger, "Skipping application of a channel update from a payment failure. Channel {} is {}.", short_channel_id, status);
369+
// While the `ChannelUpdateMessage` variant is available in tests we don't apply
370+
// them to the network graph to avoid having our test behavior diverge too much
371+
// from the production case.
354372
},
355373
NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } => {
356374
if is_permanent {
@@ -2531,7 +2549,8 @@ pub(crate) mod tests {
25312549

25322550
let short_channel_id;
25332551
{
2534-
// Announce a channel we will update
2552+
// Check we won't apply an update via `handle_network_update` for privacy reasons, but
2553+
// can continue fine if we manually apply it.
25352554
let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
25362555
short_channel_id = valid_channel_announcement.contents.short_channel_id;
25372556
let chain_source: Option<&test_utils::TestChainSource> = None;
@@ -2542,10 +2561,11 @@ pub(crate) mod tests {
25422561
assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none());
25432562

25442563
network_graph.handle_network_update(&NetworkUpdate::ChannelUpdateMessage {
2545-
msg: valid_channel_update,
2564+
msg: valid_channel_update.clone(),
25462565
});
25472566

2548-
assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_some());
2567+
assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none());
2568+
network_graph.update_channel(&valid_channel_update).unwrap();
25492569
}
25502570

25512571
// Non-permanent failure doesn't touch the channel at all

0 commit comments

Comments
 (0)