Skip to content

Commit b581ee6

Browse files
committed
Pass effective capacity to scorer
Scorers could benefit from having the channel's EffectiveCapacity rather than a u64 msat value. For instance, ProbabilisticScorer can give a more accurate penalty when given the ExactLiquidity variant. Pass a struct wrapping the effective capacity, the proposed amount, and any in-flight HTLC value.
1 parent 9abf105 commit b581ee6

File tree

4 files changed

+411
-163
lines changed

4 files changed

+411
-163
lines changed

lightning-invoice/src/payment.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
//! # use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
3939
//! # use lightning::ln::channelmanager::{ChannelDetails, PaymentId, PaymentSendFailure};
4040
//! # use lightning::ln::msgs::LightningError;
41-
//! # use lightning::routing::scoring::Score;
4241
//! # use lightning::routing::network_graph::NodeId;
4342
//! # use lightning::routing::router::{Route, RouteHop, RouteParameters};
43+
//! # use lightning::routing::scoring::{ChannelUsage, Score};
4444
//! # use lightning::util::events::{Event, EventHandler, EventsProvider};
4545
//! # use lightning::util::logger::{Logger, Record};
4646
//! # use lightning::util::ser::{Writeable, Writer};
@@ -90,7 +90,7 @@
9090
//! # }
9191
//! # impl Score for FakeScorer {
9292
//! # fn channel_penalty_msat(
93-
//! # &self, _short_channel_id: u64, _send_amt: u64, _chan_amt: u64, _source: &NodeId, _target: &NodeId
93+
//! # &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage
9494
//! # ) -> u64 { 0 }
9595
//! # fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
9696
//! # fn payment_path_successful(&mut self, _path: &[&RouteHop]) {}
@@ -534,6 +534,7 @@ mod tests {
534534
use lightning::ln::msgs::{ChannelMessageHandler, ErrorAction, LightningError};
535535
use lightning::routing::network_graph::NodeId;
536536
use lightning::routing::router::{PaymentParameters, Route, RouteHop};
537+
use lightning::routing::scoring::ChannelUsage;
537538
use lightning::util::test_utils::TestLogger;
538539
use lightning::util::errors::APIError;
539540
use lightning::util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
@@ -1327,7 +1328,7 @@ mod tests {
13271328

13281329
impl Score for TestScorer {
13291330
fn channel_penalty_msat(
1330-
&self, _short_channel_id: u64, _send_amt: u64, _chan_amt: u64, _source: &NodeId, _target: &NodeId
1331+
&self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage
13311332
) -> u64 { 0 }
13321333

13331334
fn payment_path_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) {

lightning/src/routing/network_graph.rs

+1
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ impl<'a> fmt::Debug for DirectedChannelInfoWithUpdate<'a> {
828828
///
829829
/// While this may be smaller than the actual channel capacity, amounts greater than
830830
/// [`Self::as_msat`] should not be routed through the channel.
831+
#[derive(Clone, Copy)]
831832
pub enum EffectiveCapacity {
832833
/// The available liquidity in the channel known from being a channel counterparty, and thus a
833834
/// direct hop.

lightning/src/routing/router.rs

+32-14
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use bitcoin::secp256k1::key::PublicKey;
1717
use ln::channelmanager::ChannelDetails;
1818
use ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures};
1919
use ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
20-
use routing::scoring::Score;
20+
use routing::scoring::{ChannelUsage, Score};
2121
use routing::network_graph::{DirectedChannelInfoWithUpdate, EffectiveCapacity, NetworkGraph, ReadOnlyNetworkGraph, NodeId, RoutingFees};
2222
use util::ser::{Writeable, Readable};
2323
use util::logger::{Level, Logger};
@@ -433,7 +433,8 @@ impl<'a> CandidateRouteHop<'a> {
433433
let htlc_maximum_msat = self.htlc_maximum_msat();
434434
AvailableLiquidity {
435435
htlc_maximum_msat,
436-
remaining_liquidity_msat: htlc_maximum_msat,
436+
allocated_liquidity_msat: htlc_maximum_msat,
437+
in_use_liquidity_msat: 0,
437438
}
438439
}
439440
}
@@ -449,21 +450,24 @@ impl<'a> CandidateRouteHop<'a> {
449450
/// is used simply to inform whether a channel can be used in multiple paths.
450451
struct AvailableLiquidity {
451452
htlc_maximum_msat: u64,
452-
remaining_liquidity_msat: u64,
453+
allocated_liquidity_msat: u64,
454+
in_use_liquidity_msat: u64,
453455
}
454456

455457
impl AvailableLiquidity {
456458
fn as_msat(&self) -> u64 {
457-
core::cmp::min(self.htlc_maximum_msat, self.remaining_liquidity_msat)
459+
let remaining_liquidity_msat = self.allocated_liquidity_msat
460+
.saturating_sub(self.in_use_liquidity_msat);
461+
core::cmp::min(self.htlc_maximum_msat, remaining_liquidity_msat)
458462
}
459463

460464
fn reduce_by(&mut self, amount_msat: u64) -> &mut Self {
461-
self.remaining_liquidity_msat -= amount_msat;
465+
self.in_use_liquidity_msat += amount_msat;
462466
self
463467
}
464468

465469
fn exhaust(&mut self) {
466-
self.remaining_liquidity_msat = 0;
470+
self.in_use_liquidity_msat = self.allocated_liquidity_msat;
467471
}
468472
}
469473

@@ -1074,9 +1078,16 @@ where L::Target: Logger {
10741078
}
10751079
}
10761080

1077-
let path_penalty_msat = $next_hops_path_penalty_msat.saturating_add(
1078-
scorer.channel_penalty_msat(short_channel_id, amount_to_transfer_over_msat,
1079-
available_liquidity_msat, &$src_node_id, &$dest_node_id));
1081+
let channel_usage = ChannelUsage {
1082+
amount_msat: amount_to_transfer_over_msat,
1083+
inflight_htlc_msat: available_liquidity.in_use_liquidity_msat,
1084+
effective_capacity: $candidate.effective_capacity(),
1085+
};
1086+
let channel_penalty_msat = scorer.channel_penalty_msat(
1087+
short_channel_id, &$src_node_id, &$dest_node_id, channel_usage
1088+
);
1089+
let path_penalty_msat = $next_hops_path_penalty_msat
1090+
.saturating_add(channel_penalty_msat);
10801091
let new_graph_node = RouteGraphNode {
10811092
node_id: $src_node_id,
10821093
lowest_fee_to_peer_through_node: total_fee_msat,
@@ -1288,9 +1299,16 @@ where L::Target: Logger {
12881299
short_channel_id: hop.short_channel_id,
12891300
})
12901301
.unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop });
1291-
let capacity_msat = candidate.effective_capacity().as_msat();
1302+
let channel_usage = ChannelUsage {
1303+
amount_msat: final_value_msat,
1304+
inflight_htlc_msat: 0,
1305+
effective_capacity: candidate.effective_capacity(),
1306+
};
1307+
let channel_penalty_msat = scorer.channel_penalty_msat(
1308+
hop.short_channel_id, &source, &target, channel_usage
1309+
);
12921310
aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat
1293-
.saturating_add(scorer.channel_penalty_msat(hop.short_channel_id, final_value_msat, capacity_msat, &source, &target));
1311+
.saturating_add(channel_penalty_msat);
12941312

12951313
aggregate_next_hops_cltv_delta = aggregate_next_hops_cltv_delta
12961314
.saturating_add(hop.cltv_expiry_delta as u32);
@@ -1747,7 +1765,7 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
17471765
mod tests {
17481766
use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId};
17491767
use routing::router::{get_route, add_random_cltv_offset, default_node_features, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA};
1750-
use routing::scoring::Score;
1768+
use routing::scoring::{ChannelUsage, Score};
17511769
use chain::transaction::OutPoint;
17521770
use chain::keysinterface::KeysInterface;
17531771
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
@@ -5088,7 +5106,7 @@ mod tests {
50885106
fn write<W: Writer>(&self, _w: &mut W) -> Result<(), ::io::Error> { unimplemented!() }
50895107
}
50905108
impl Score for BadChannelScorer {
5091-
fn channel_penalty_msat(&self, short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, _target: &NodeId) -> u64 {
5109+
fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage) -> u64 {
50925110
if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 }
50935111
}
50945112

@@ -5106,7 +5124,7 @@ mod tests {
51065124
}
51075125

51085126
impl Score for BadNodeScorer {
5109-
fn channel_penalty_msat(&self, _short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, target: &NodeId) -> u64 {
5127+
fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage) -> u64 {
51105128
if *target == self.node_id { u64::max_value() } else { 0 }
51115129
}
51125130

0 commit comments

Comments
 (0)