Skip to content

Commit 81afc2f

Browse files
committed
Require directional updates for a DirectionalChannelInfo
We currently construct `DirectedChannelInfo`s for routing before checking if the given direction has its directional info filled in. We then always check for directional info before actually deciding to route over a channel, as otherwise we assume the channel is not online. This makes for somewhat redundant checks, and `DirectedCHannelInfo` isn't, by itself, a very useful API. Because fetching the HTLC-max or effective channel capacity gives spurious data if no directional info is available, there's little reason to have that data available, and so we here check for directional info first. This effectively merges `DirectionalChannelInfo` and `DirectionalChannelInfoWithUpdate`.
1 parent 6957fb6 commit 81afc2f

File tree

2 files changed

+30
-74
lines changed

2 files changed

+30
-74
lines changed

lightning/src/routing/gossip.rs

+15-52
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ impl ChannelInfo {
750750
return None;
751751
}
752752
};
753-
Some((DirectedChannelInfo::new(self, direction), source))
753+
direction.map(|dir| (DirectedChannelInfo::new(self, dir), source))
754754
}
755755

756756
/// Returns a [`DirectedChannelInfo`] for the channel directed from the given `source` to a
@@ -765,7 +765,7 @@ impl ChannelInfo {
765765
return None;
766766
}
767767
};
768-
Some((DirectedChannelInfo::new(self, direction), target))
768+
direction.map(|dir| (DirectedChannelInfo::new(self, dir), target))
769769
}
770770

771771
/// Returns a [`ChannelUpdateInfo`] based on the direction implied by the channel_flag.
@@ -860,29 +860,23 @@ impl Readable for ChannelInfo {
860860
#[derive(Clone)]
861861
pub struct DirectedChannelInfo<'a> {
862862
channel: &'a ChannelInfo,
863-
direction: Option<&'a ChannelUpdateInfo>,
863+
direction: &'a ChannelUpdateInfo,
864864
htlc_maximum_msat: u64,
865865
effective_capacity: EffectiveCapacity,
866866
}
867867

868868
impl<'a> DirectedChannelInfo<'a> {
869869
#[inline]
870-
fn new(channel: &'a ChannelInfo, direction: Option<&'a ChannelUpdateInfo>) -> Self {
871-
let htlc_maximum_msat = direction.map(|direction| direction.htlc_maximum_msat);
870+
fn new(channel: &'a ChannelInfo, direction: &'a ChannelUpdateInfo) -> Self {
871+
let mut htlc_maximum_msat = direction.htlc_maximum_msat;
872872
let capacity_msat = channel.capacity_sats.map(|capacity_sats| capacity_sats * 1000);
873873

874-
let (htlc_maximum_msat, effective_capacity) = match (htlc_maximum_msat, capacity_msat) {
875-
(Some(amount_msat), Some(capacity_msat)) => {
876-
let htlc_maximum_msat = cmp::min(amount_msat, capacity_msat);
877-
(htlc_maximum_msat, EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: Some(htlc_maximum_msat) })
874+
let effective_capacity = match capacity_msat {
875+
Some(capacity_msat) => {
876+
htlc_maximum_msat = cmp::min(htlc_maximum_msat, capacity_msat);
877+
EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: Some(htlc_maximum_msat) }
878878
},
879-
(Some(amount_msat), None) => {
880-
(amount_msat, EffectiveCapacity::MaximumHTLC { amount_msat })
881-
},
882-
(None, Some(capacity_msat)) => {
883-
(capacity_msat, EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: None })
884-
},
885-
(None, None) => (EffectiveCapacity::Unknown.as_msat(), EffectiveCapacity::Unknown),
879+
None => EffectiveCapacity::MaximumHTLC { amount_msat: htlc_maximum_msat },
886880
};
887881

888882
Self {
@@ -891,12 +885,11 @@ impl<'a> DirectedChannelInfo<'a> {
891885
}
892886

893887
/// Returns information for the channel.
888+
#[inline]
894889
pub fn channel(&self) -> &'a ChannelInfo { self.channel }
895890

896-
/// Returns information for the direction.
897-
pub fn direction(&self) -> Option<&'a ChannelUpdateInfo> { self.direction }
898-
899891
/// Returns the maximum HTLC amount allowed over the channel in the direction.
892+
#[inline]
900893
pub fn htlc_maximum_msat(&self) -> u64 {
901894
self.htlc_maximum_msat
902895
}
@@ -910,13 +903,9 @@ impl<'a> DirectedChannelInfo<'a> {
910903
self.effective_capacity
911904
}
912905

913-
/// Returns `Some` if [`ChannelUpdateInfo`] is available in the direction.
914-
pub(super) fn with_update(self) -> Option<DirectedChannelInfoWithUpdate<'a>> {
915-
match self.direction {
916-
Some(_) => Some(DirectedChannelInfoWithUpdate { inner: self }),
917-
None => None,
918-
}
919-
}
906+
/// Returns information for the direction.
907+
#[inline]
908+
pub(super) fn direction(&self) -> &'a ChannelUpdateInfo { self.direction }
920909
}
921910

922911
impl<'a> fmt::Debug for DirectedChannelInfo<'a> {
@@ -927,32 +916,6 @@ impl<'a> fmt::Debug for DirectedChannelInfo<'a> {
927916
}
928917
}
929918

930-
/// A [`DirectedChannelInfo`] with [`ChannelUpdateInfo`] available in its direction.
931-
#[derive(Clone)]
932-
pub(super) struct DirectedChannelInfoWithUpdate<'a> {
933-
inner: DirectedChannelInfo<'a>,
934-
}
935-
936-
impl<'a> DirectedChannelInfoWithUpdate<'a> {
937-
/// Returns information for the channel.
938-
#[inline]
939-
pub(super) fn channel(&self) -> &'a ChannelInfo { &self.inner.channel }
940-
941-
/// Returns information for the direction.
942-
#[inline]
943-
pub(super) fn direction(&self) -> &'a ChannelUpdateInfo { self.inner.direction.unwrap() }
944-
945-
/// Returns the [`EffectiveCapacity`] of the channel in the direction.
946-
#[inline]
947-
pub(super) fn effective_capacity(&self) -> EffectiveCapacity { self.inner.effective_capacity() }
948-
}
949-
950-
impl<'a> fmt::Debug for DirectedChannelInfoWithUpdate<'a> {
951-
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
952-
self.inner.fmt(f)
953-
}
954-
}
955-
956919
/// The effective capacity of a channel for routing purposes.
957920
///
958921
/// While this may be smaller than the actual channel capacity, amounts greater than

lightning/src/routing/router.rs

+15-22
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use bitcoin::secp256k1::PublicKey;
1717
use crate::ln::channelmanager::ChannelDetails;
1818
use crate::ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures};
1919
use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
20-
use crate::routing::gossip::{DirectedChannelInfoWithUpdate, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
20+
use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
2121
use crate::routing::scoring::{ChannelUsage, Score};
2222
use crate::util::ser::{Writeable, Readable, Writer};
2323
use crate::util::logger::{Level, Logger};
@@ -421,7 +421,7 @@ enum CandidateRouteHop<'a> {
421421
},
422422
/// A hop found in the [`ReadOnlyNetworkGraph`], where the channel capacity may be unknown.
423423
PublicHop {
424-
info: DirectedChannelInfoWithUpdate<'a>,
424+
info: DirectedChannelInfo<'a>,
425425
short_channel_id: u64,
426426
},
427427
/// A hop to the payee found in the payment invoice, though not necessarily a direct channel.
@@ -1276,13 +1276,11 @@ where L::Target: Logger {
12761276
for chan_id in $node.channels.iter() {
12771277
let chan = network_channels.get(chan_id).unwrap();
12781278
if !chan.features.requires_unknown_bits() {
1279-
let (directed_channel, source) =
1280-
chan.as_directed_to(&$node_id).expect("inconsistent NetworkGraph");
1281-
if first_hops.is_none() || *source != our_node_id {
1282-
if let Some(direction) = directed_channel.direction() {
1283-
if direction.enabled {
1279+
if let Some((directed_channel, source)) = chan.as_directed_to(&$node_id) {
1280+
if first_hops.is_none() || *source != our_node_id {
1281+
if directed_channel.direction().enabled {
12841282
let candidate = CandidateRouteHop::PublicHop {
1285-
info: directed_channel.with_update().unwrap(),
1283+
info: directed_channel,
12861284
short_channel_id: *chan_id,
12871285
};
12881286
add_entry!(candidate, *source, $node_id,
@@ -1367,8 +1365,7 @@ where L::Target: Logger {
13671365
let candidate = network_channels
13681366
.get(&hop.short_channel_id)
13691367
.and_then(|channel| channel.as_directed_to(&target))
1370-
.and_then(|(channel, _)| channel.with_update())
1371-
.map(|info| CandidateRouteHop::PublicHop {
1368+
.map(|(info, _)| CandidateRouteHop::PublicHop {
13721369
info,
13731370
short_channel_id: hop.short_channel_id,
13741371
})
@@ -1816,10 +1813,8 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
18161813
random_channel.as_directed_from(&cur_node_id).map(|(dir_info, next_id)| {
18171814
if !nodes_to_avoid.iter().any(|x| x == next_id) {
18181815
nodes_to_avoid[random_hop] = *next_id;
1819-
dir_info.direction().map(|channel_update_info| {
1820-
random_hop_offset = channel_update_info.cltv_expiry_delta.into();
1821-
cur_hop = Some(*next_id);
1822-
});
1816+
random_hop_offset = dir_info.direction().cltv_expiry_delta.into();
1817+
cur_hop = Some(*next_id);
18231818
}
18241819
});
18251820
}
@@ -5214,14 +5209,12 @@ mod tests {
52145209
for channel_id in &cur_node.channels {
52155210
if let Some(channel_info) = network_channels.get(&channel_id) {
52165211
if let Some((dir_info, next_id)) = channel_info.as_directed_from(&cur_node_id) {
5217-
if let Some(channel_update_info) = dir_info.direction() {
5218-
let next_cltv_expiry_delta = channel_update_info.cltv_expiry_delta as u32;
5219-
if cur_path_cltv_deltas.iter().sum::<u32>()
5220-
.saturating_add(next_cltv_expiry_delta) <= observed_cltv_expiry_delta {
5221-
let mut new_path_cltv_deltas = cur_path_cltv_deltas.clone();
5222-
new_path_cltv_deltas.push(next_cltv_expiry_delta);
5223-
candidates.push_back((*next_id, new_path_cltv_deltas));
5224-
}
5212+
let next_cltv_expiry_delta = dir_info.direction().cltv_expiry_delta as u32;
5213+
if cur_path_cltv_deltas.iter().sum::<u32>()
5214+
.saturating_add(next_cltv_expiry_delta) <= observed_cltv_expiry_delta {
5215+
let mut new_path_cltv_deltas = cur_path_cltv_deltas.clone();
5216+
new_path_cltv_deltas.push(next_cltv_expiry_delta);
5217+
candidates.push_back((*next_id, new_path_cltv_deltas));
52255218
}
52265219
}
52275220
}

0 commit comments

Comments
 (0)