Skip to content

Commit b5cdfcc

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 1f82219 commit b5cdfcc

File tree

3 files changed

+408
-163
lines changed

3 files changed

+408
-163
lines changed

lightning-invoice/src/payment.rs

Lines changed: 4 additions & 3 deletions
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/router.rs

Lines changed: 30 additions & 14 deletions
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};
@@ -431,7 +431,8 @@ impl<'a> CandidateRouteHop<'a> {
431431

432432
fn available_liquidity(&self) -> AvailableLiquidity {
433433
AvailableLiquidity {
434-
remaining_liquidity_msat: self.htlc_maximum_msat(),
434+
allocated_liquidity_msat: self.htlc_maximum_msat(),
435+
in_use_liquidity_msat: 0,
435436
}
436437
}
437438
}
@@ -446,21 +447,22 @@ impl<'a> CandidateRouteHop<'a> {
446447
/// This information is ephemeral in that it does not carry across calls to `find_route`. Rather it
447448
/// is used simply to inform whether a channel can be used in multiple paths.
448449
struct AvailableLiquidity {
449-
remaining_liquidity_msat: u64,
450+
allocated_liquidity_msat: u64,
451+
in_use_liquidity_msat: u64,
450452
}
451453

452454
impl AvailableLiquidity {
453455
fn as_msat(&self) -> u64 {
454-
self.remaining_liquidity_msat
456+
self.allocated_liquidity_msat - self.in_use_liquidity_msat
455457
}
456458

457459
fn reduce_by(&mut self, amount_msat: u64) -> &mut Self {
458-
self.remaining_liquidity_msat -= amount_msat;
460+
self.in_use_liquidity_msat += amount_msat;
459461
self
460462
}
461463

462464
fn exhaust(&mut self) {
463-
self.remaining_liquidity_msat = 0;
465+
self.in_use_liquidity_msat = self.allocated_liquidity_msat;
464466
}
465467
}
466468

@@ -1071,9 +1073,16 @@ where L::Target: Logger {
10711073
}
10721074
}
10731075

1074-
let path_penalty_msat = $next_hops_path_penalty_msat.saturating_add(
1075-
scorer.channel_penalty_msat(short_channel_id, amount_to_transfer_over_msat,
1076-
available_liquidity_msat, &$src_node_id, &$dest_node_id));
1076+
let channel_usage = ChannelUsage {
1077+
amount_msat: amount_to_transfer_over_msat,
1078+
inflight_htlc_msat: available_liquidity.in_use_liquidity_msat,
1079+
effective_capacity: $candidate.effective_capacity(),
1080+
};
1081+
let channel_penalty_msat = scorer.channel_penalty_msat(
1082+
short_channel_id, &$src_node_id, &$dest_node_id, channel_usage
1083+
);
1084+
let path_penalty_msat = $next_hops_path_penalty_msat
1085+
.saturating_add(channel_penalty_msat);
10771086
let new_graph_node = RouteGraphNode {
10781087
node_id: $src_node_id,
10791088
lowest_fee_to_peer_through_node: total_fee_msat,
@@ -1285,9 +1294,16 @@ where L::Target: Logger {
12851294
short_channel_id: hop.short_channel_id,
12861295
})
12871296
.unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop });
1288-
let capacity_msat = candidate.effective_capacity().as_msat();
1297+
let channel_usage = ChannelUsage {
1298+
amount_msat: final_value_msat,
1299+
inflight_htlc_msat: 0,
1300+
effective_capacity: candidate.effective_capacity(),
1301+
};
1302+
let channel_penalty_msat = scorer.channel_penalty_msat(
1303+
hop.short_channel_id, &source, &target, channel_usage
1304+
);
12891305
aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat
1290-
.saturating_add(scorer.channel_penalty_msat(hop.short_channel_id, final_value_msat, capacity_msat, &source, &target));
1306+
.saturating_add(channel_penalty_msat);
12911307

12921308
aggregate_next_hops_cltv_delta = aggregate_next_hops_cltv_delta
12931309
.saturating_add(hop.cltv_expiry_delta as u32);
@@ -1744,7 +1760,7 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
17441760
mod tests {
17451761
use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId};
17461762
use routing::router::{get_route, add_random_cltv_offset, default_node_features, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA};
1747-
use routing::scoring::Score;
1763+
use routing::scoring::{ChannelUsage, Score};
17481764
use chain::transaction::OutPoint;
17491765
use chain::keysinterface::KeysInterface;
17501766
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
@@ -5085,7 +5101,7 @@ mod tests {
50855101
fn write<W: Writer>(&self, _w: &mut W) -> Result<(), ::io::Error> { unimplemented!() }
50865102
}
50875103
impl Score for BadChannelScorer {
5088-
fn channel_penalty_msat(&self, short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, _target: &NodeId) -> u64 {
5104+
fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage) -> u64 {
50895105
if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 }
50905106
}
50915107

@@ -5103,7 +5119,7 @@ mod tests {
51035119
}
51045120

51055121
impl Score for BadNodeScorer {
5106-
fn channel_penalty_msat(&self, _short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, target: &NodeId) -> u64 {
5122+
fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage) -> u64 {
51075123
if *target == self.node_id { u64::max_value() } else { 0 }
51085124
}
51095125

0 commit comments

Comments
 (0)