Skip to content

Commit b0fced1

Browse files
committed
Track lowest inbound channel fees per channel direction.
This allows to avoid iterating through the nodes data to see what would be the cost to reach a given node while routing.
1 parent 15a5966 commit b0fced1

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed

lightning/src/routing/gossip.rs

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -707,37 +707,43 @@ pub struct ChannelInfo {
707707
/// (which we can probably assume we are - no-std environments probably won't have a full
708708
/// network graph in memory!).
709709
announcement_received_time: u64,
710+
// Lowest fees to enter the first direction, based on the cheapest channel to the source node.
711+
// Both fees correspond to the same channel.
712+
pub lowest_inbound_channel_fees_to_one: Option<RoutingFees>,
713+
// Lowest fees to enter the second direction, based on the cheapest channel to the source node.
714+
// Both fees correspond to the same channel.
715+
pub lowest_inbound_channel_fees_to_two: Option<RoutingFees>,
710716
}
711717

712718
impl ChannelInfo {
713719
/// Returns a [`DirectedChannelInfo`] for the channel directed to the given `target` from a
714720
/// returned `source`, or `None` if `target` is not one of the channel's counterparties.
715721
pub fn as_directed_to(&self, target: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
716-
let (direction, source) = {
722+
let (direction, source, lowest_inbound_channel_fees) = {
717723
if target == &self.node_one {
718-
(self.two_to_one.as_ref(), &self.node_two)
724+
(self.two_to_one.as_ref(), &self.node_two, self.lowest_inbound_channel_fees_to_two)
719725
} else if target == &self.node_two {
720-
(self.one_to_two.as_ref(), &self.node_one)
726+
(self.one_to_two.as_ref(), &self.node_one, self.lowest_inbound_channel_fees_to_one)
721727
} else {
722728
return None;
723729
}
724730
};
725-
Some((DirectedChannelInfo::new(self, direction), source))
731+
Some((DirectedChannelInfo::new(self, direction, lowest_inbound_channel_fees), source))
726732
}
727733

728734
/// Returns a [`DirectedChannelInfo`] for the channel directed from the given `source` to a
729735
/// returned `target`, or `None` if `source` is not one of the channel's counterparties.
730736
pub fn as_directed_from(&self, source: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
731-
let (direction, target) = {
737+
let (direction, target, lowest_inbound_channel_fees) = {
732738
if source == &self.node_one {
733-
(self.one_to_two.as_ref(), &self.node_two)
739+
(self.one_to_two.as_ref(), &self.node_two, self.lowest_inbound_channel_fees_to_two)
734740
} else if source == &self.node_two {
735-
(self.two_to_one.as_ref(), &self.node_one)
741+
(self.two_to_one.as_ref(), &self.node_one, self.lowest_inbound_channel_fees_to_one)
736742
} else {
737743
return None;
738744
}
739745
};
740-
Some((DirectedChannelInfo::new(self, direction), target))
746+
Some((DirectedChannelInfo::new(self, direction, lowest_inbound_channel_fees), target))
741747
}
742748

743749
/// Returns a [`ChannelUpdateInfo`] based on the direction implied by the channel_flag.
@@ -770,6 +776,8 @@ impl Writeable for ChannelInfo {
770776
(8, self.two_to_one, required),
771777
(10, self.capacity_sats, required),
772778
(12, self.announcement_message, required),
779+
(14, self.lowest_inbound_channel_fees_to_one, option),
780+
(16, self.lowest_inbound_channel_fees_to_two, option),
773781
});
774782
Ok(())
775783
}
@@ -803,6 +811,8 @@ impl Readable for ChannelInfo {
803811
let mut two_to_one_wrap: Option<ChannelUpdateInfoDeserWrapper> = None;
804812
init_tlv_field_var!(capacity_sats, required);
805813
init_tlv_field_var!(announcement_message, required);
814+
init_tlv_field_var!(lowest_inbound_channel_fees_to_one, option);
815+
init_tlv_field_var!(lowest_inbound_channel_fees_to_two, option);
806816
read_tlv_fields!(reader, {
807817
(0, features, required),
808818
(1, announcement_received_time, (default_value, 0)),
@@ -812,6 +822,8 @@ impl Readable for ChannelInfo {
812822
(8, two_to_one_wrap, ignorable),
813823
(10, capacity_sats, required),
814824
(12, announcement_message, required),
825+
(14, lowest_inbound_channel_fees_to_one, option),
826+
(16, lowest_inbound_channel_fees_to_two, option),
815827
});
816828

817829
Ok(ChannelInfo {
@@ -823,6 +835,8 @@ impl Readable for ChannelInfo {
823835
capacity_sats: init_tlv_based_struct_field!(capacity_sats, required),
824836
announcement_message: init_tlv_based_struct_field!(announcement_message, required),
825837
announcement_received_time: init_tlv_based_struct_field!(announcement_received_time, (default_value, 0)),
838+
lowest_inbound_channel_fees_to_one: init_tlv_based_struct_field!(lowest_inbound_channel_fees_to_one, option),
839+
lowest_inbound_channel_fees_to_two: init_tlv_based_struct_field!(lowest_inbound_channel_fees_to_two, option),
826840
})
827841
}
828842
}
@@ -835,11 +849,12 @@ pub struct DirectedChannelInfo<'a> {
835849
direction: Option<&'a ChannelUpdateInfo>,
836850
htlc_maximum_msat: u64,
837851
effective_capacity: EffectiveCapacity,
852+
lowest_inbound_channel_fees: Option<RoutingFees>,
838853
}
839854

840855
impl<'a> DirectedChannelInfo<'a> {
841856
#[inline]
842-
fn new(channel: &'a ChannelInfo, direction: Option<&'a ChannelUpdateInfo>) -> Self {
857+
fn new(channel: &'a ChannelInfo, direction: Option<&'a ChannelUpdateInfo>, lowest_inbound_channel_fees: Option<RoutingFees>) -> Self {
843858
let htlc_maximum_msat = direction.map(|direction| direction.htlc_maximum_msat);
844859
let capacity_msat = channel.capacity_sats.map(|capacity_sats| capacity_sats * 1000);
845860

@@ -858,7 +873,7 @@ impl<'a> DirectedChannelInfo<'a> {
858873
};
859874

860875
Self {
861-
channel, direction, htlc_maximum_msat, effective_capacity
876+
channel, direction, htlc_maximum_msat, effective_capacity, lowest_inbound_channel_fees,
862877
}
863878
}
864879

@@ -882,6 +897,10 @@ impl<'a> DirectedChannelInfo<'a> {
882897
self.effective_capacity
883898
}
884899

900+
pub fn lowest_inbound_channel_fees(&self) -> Option<RoutingFees> {
901+
self.lowest_inbound_channel_fees
902+
}
903+
885904
/// Returns `Some` if [`ChannelUpdateInfo`] is available in the direction.
886905
pub(super) fn with_update(self) -> Option<DirectedChannelInfoWithUpdate<'a>> {
887906
match self.direction {
@@ -917,6 +936,10 @@ impl<'a> DirectedChannelInfoWithUpdate<'a> {
917936
/// Returns the [`EffectiveCapacity`] of the channel in the direction.
918937
#[inline]
919938
pub(super) fn effective_capacity(&self) -> EffectiveCapacity { self.inner.effective_capacity() }
939+
940+
#[inline]
941+
pub(super) fn lowest_inbound_channel_fees(&self) -> Option<RoutingFees> { self.inner.lowest_inbound_channel_fees() }
942+
920943
}
921944

922945
impl<'a> fmt::Debug for DirectedChannelInfoWithUpdate<'a> {
@@ -1382,6 +1405,8 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
13821405
capacity_sats: None,
13831406
announcement_message: None,
13841407
announcement_received_time: timestamp,
1408+
lowest_inbound_channel_fees_to_one: None,
1409+
lowest_inbound_channel_fees_to_two: None,
13851410
};
13861411

13871412
self.add_channel_between_nodes(short_channel_id, channel_info, None)
@@ -1524,6 +1549,8 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
15241549
announcement_message: if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY
15251550
{ full_msg.cloned() } else { None },
15261551
announcement_received_time,
1552+
lowest_inbound_channel_fees_to_one: None,
1553+
lowest_inbound_channel_fees_to_two: None,
15271554
};
15281555

15291556
self.add_channel_between_nodes(msg.short_channel_id, chan_info, utxo_value)
@@ -1752,22 +1779,20 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
17521779
}
17531780

17541781
let mut nodes = self.nodes.write().unwrap();
1782+
let node = nodes.get_mut(&dest_node_id).unwrap();
1783+
let mut updated_lowest_inbound_channel_fee = None;
17551784
if chan_enabled {
1756-
let node = nodes.get_mut(&dest_node_id).unwrap();
17571785
let mut base_msat = msg.fee_base_msat;
17581786
let mut proportional_millionths = msg.fee_proportional_millionths;
17591787
if let Some(fees) = node.lowest_inbound_channel_fees {
17601788
base_msat = cmp::min(base_msat, fees.base_msat);
17611789
proportional_millionths = cmp::min(proportional_millionths, fees.proportional_millionths);
17621790
}
1763-
node.lowest_inbound_channel_fees = Some(RoutingFees {
1791+
updated_lowest_inbound_channel_fee = Some(RoutingFees {
17641792
base_msat,
17651793
proportional_millionths
17661794
});
17671795
} else if chan_was_enabled {
1768-
let node = nodes.get_mut(&dest_node_id).unwrap();
1769-
let mut lowest_inbound_channel_fees = None;
1770-
17711796
for chan_id in node.channels.iter() {
17721797
let chan = channels.get(chan_id).unwrap();
17731798
let chan_info_opt;
@@ -1778,15 +1803,27 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
17781803
}
17791804
if let Some(chan_info) = chan_info_opt {
17801805
if chan_info.enabled {
1781-
let fees = lowest_inbound_channel_fees.get_or_insert(RoutingFees {
1806+
let fees = updated_lowest_inbound_channel_fee.get_or_insert(RoutingFees {
17821807
base_msat: u32::max_value(), proportional_millionths: u32::max_value() });
17831808
fees.base_msat = cmp::min(fees.base_msat, chan_info.fees.base_msat);
17841809
fees.proportional_millionths = cmp::min(fees.proportional_millionths, chan_info.fees.proportional_millionths);
17851810
}
17861811
}
17871812
}
1813+
}
17881814

1789-
node.lowest_inbound_channel_fees = lowest_inbound_channel_fees;
1815+
if updated_lowest_inbound_channel_fee.is_some() {
1816+
node.lowest_inbound_channel_fees = updated_lowest_inbound_channel_fee;
1817+
1818+
for (_, chan) in channels.iter_mut() {
1819+
if chan.node_one == dest_node_id {
1820+
chan.lowest_inbound_channel_fees_to_two = updated_lowest_inbound_channel_fee;
1821+
}
1822+
1823+
if chan.node_two == dest_node_id {
1824+
chan.lowest_inbound_channel_fees_to_one = updated_lowest_inbound_channel_fee;
1825+
}
1826+
}
17901827
}
17911828

17921829
Ok(())
@@ -3019,6 +3056,8 @@ mod tests {
30193056
capacity_sats: None,
30203057
announcement_message: None,
30213058
announcement_received_time: 87654,
3059+
lowest_inbound_channel_fees_to_one: None,
3060+
lowest_inbound_channel_fees_to_two: None,
30223061
};
30233062

30243063
let mut encoded_chan_info: Vec<u8> = Vec::new();
@@ -3037,6 +3076,8 @@ mod tests {
30373076
capacity_sats: None,
30383077
announcement_message: None,
30393078
announcement_received_time: 87654,
3079+
lowest_inbound_channel_fees_to_one: None,
3080+
lowest_inbound_channel_fees_to_two: None,
30403081
};
30413082

30423083
let mut encoded_chan_info: Vec<u8> = Vec::new();

lightning/src/routing/router.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,16 @@ impl<'a> CandidateRouteHop<'a> {
483483
CandidateRouteHop::PrivateHop { .. } => EffectiveCapacity::Infinite,
484484
}
485485
}
486+
487+
fn lowest_inbound_channel_fees(&self) -> Option<RoutingFees> {
488+
match self {
489+
CandidateRouteHop::FirstHop { .. } => Some(RoutingFees {
490+
base_msat: 0, proportional_millionths: 0,
491+
}),
492+
CandidateRouteHop::PublicHop { info, .. } => info.lowest_inbound_channel_fees(),
493+
CandidateRouteHop::PrivateHop { .. } => None,
494+
}
495+
}
486496
}
487497

488498
#[inline]
@@ -1070,7 +1080,7 @@ where L::Target: Logger {
10701080
// as a way to reach the $dest_node_id.
10711081
let mut fee_base_msat = 0;
10721082
let mut fee_proportional_millionths = 0;
1073-
if let Some(Some(fees)) = network_nodes.get(&$src_node_id).map(|node| node.lowest_inbound_channel_fees) {
1083+
if let Some(fees) = $candidate.lowest_inbound_channel_fees() {
10741084
fee_base_msat = fees.base_msat;
10751085
fee_proportional_millionths = fees.proportional_millionths;
10761086
}

0 commit comments

Comments
 (0)