Skip to content

Commit

Permalink
Consider success probability in blinded path
Browse files Browse the repository at this point in the history
How certain a scorer is about a channel's success probability is useful
in determining if the channel should be included in a blinded payment
path. Channels with low success probability for a given amount should be
avoided to facilitate successful payments.

Expand ScoreLookUp with a channel_success_probability method and use it
in DefaultRouter::create_blinded_payment_paths.
  • Loading branch information
jkczyz committed May 31, 2024
1 parent 315cb7c commit 392aadb
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
31 changes: 27 additions & 4 deletions lightning/src/routing/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
// The minimum channel balance certainty required for using a channel in a blinded path.
const MIN_CHANNEL_CERTAINTY: f64 = 0.5;

// The minimum success probability required for using a channel in a blinded path.
const MIN_SUCCESS_PROBABILITY: f64 = 0.25;

let network_graph = self.network_graph.deref().read_only();
let counterparty_channels = first_hops.into_iter()
.filter(|details| details.counterparty.features.supports_route_blinding())
Expand Down Expand Up @@ -175,6 +178,21 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
//
// source --- info ---> counterparty --- counterparty_forward_node ---> recipient
.filter_map(|(introduction_node_id, scid, info, counterparty_forward_node)| {
let amount_msat = amount_msats;
let effective_capacity = info.effective_capacity();
let usage = ChannelUsage { amount_msat, inflight_htlc_msat: 0, effective_capacity };
let success_probability = scorer.channel_success_probability(
scid, &info, usage, &self.score_params
);

if !success_probability.is_finite() {
return None;
}

if success_probability < MIN_SUCCESS_PROBABILITY {
return None;
}

let htlc_minimum_msat = info.direction().htlc_minimum_msat;
let htlc_maximum_msat = info.direction().htlc_maximum_msat;
let payment_relay: PaymentRelay = match info.try_into() {
Expand All @@ -196,12 +214,13 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
node_id: introduction_node_id.as_pubkey().unwrap(),
htlc_maximum_msat,
};
Some(BlindedPath::new_for_payment(
let path = BlindedPath::new_for_payment(
&[introduction_forward_node, counterparty_forward_node], recipient,
tlvs.clone(), u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, entropy_source, secp_ctx
))
})
.take(MAX_PAYMENT_PATHS);
);

Some(path.map(|path| (path, success_probability)))
});

let two_hop_paths = counterparty_channels
.map(|(forward_node, _)| {
Expand All @@ -215,6 +234,10 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
three_hop_paths
.collect::<Result<Vec<_>, _>>().ok()
.and_then(|paths| (!paths.is_empty()).then(|| paths))
.map(|mut paths| {
paths.sort_unstable_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
paths.into_iter().map(|(path, _)| path).take(MAX_PAYMENT_PATHS).collect::<Vec<_>>()
})
.or_else(|| two_hop_paths.collect::<Result<Vec<_>, _>>().ok())
.and_then(|paths| (!paths.is_empty()).then(|| paths))
.or_else(|| network_graph
Expand Down
12 changes: 12 additions & 0 deletions lightning/src/routing/scoring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ pub trait ScoreLookUp {
&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams
) -> u64;

/// Returns the success probability of sending an HTLC through a channel.
///
/// Expected to return a value between `0.0` and `1.0`, inclusive, where `0.0` indicates
/// highly unlikely and `1.0` highly likely.
///
/// This is useful to determine whether a channel should be included in a blinded path and the
/// preferred ordering of blinded paths.
fn channel_success_probability(
&self, _short_channel_id: u64, _info: &DirectedChannelInfo, _usage: ChannelUsage,
_score_params: &Self::ScoreParams
) -> f64 { 0.5 }

/// Returns how certain any knowledge gained about the channel's liquidity balance is.
///
/// Expected to return a value between `0.0` and `1.0`, inclusive, where `0.0` indicates
Expand Down

0 comments on commit 392aadb

Please sign in to comment.