52
52
//! [`find_route`]: crate::routing::router::find_route
53
53
54
54
use crate :: ln:: msgs:: DecodeError ;
55
- use crate :: routing:: gossip:: { EffectiveCapacity , NetworkGraph , NodeId } ;
55
+ use crate :: routing:: gossip:: { DirectedChannelInfo , EffectiveCapacity , NetworkGraph , NodeId } ;
56
56
use crate :: routing:: router:: { Path , CandidateRouteHop , PublicHopCandidate } ;
57
57
use crate :: routing:: log_approx;
58
58
use crate :: util:: ser:: { Readable , ReadableArgs , Writeable , Writer } ;
@@ -956,32 +956,67 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
956
956
/// with `scid` towards the given `target` node, based on the historical estimated liquidity
957
957
/// bounds.
958
958
///
959
- /// Returns `None` if there is no (or insufficient) historical data for the given channel (or
960
- /// the provided `target` is not a party to the channel).
959
+ /// Returns `None` if:
960
+ /// - the given channel is not in the network graph, the provided `target` is not a party to
961
+ /// the channel, or we don't have forwarding parameters for either direction in the channel.
962
+ /// - `allow_fallback_estimation` is *not* set and there is no (or insufficient) historical
963
+ /// data for the given channel.
961
964
///
962
965
/// These are the same bounds as returned by
963
966
/// [`Self::historical_estimated_channel_liquidity_probabilities`] (but not those returned by
964
967
/// [`Self::estimated_channel_liquidity_range`]).
965
968
pub fn historical_estimated_payment_success_probability (
966
- & self , scid : u64 , target : & NodeId , amount_msat : u64 , params : & ProbabilisticScoringFeeParameters )
967
- -> Option < f64 > {
969
+ & self , scid : u64 , target : & NodeId , amount_msat : u64 , params : & ProbabilisticScoringFeeParameters ,
970
+ allow_fallback_estimation : bool ,
971
+ ) -> Option < f64 > {
968
972
let graph = self . network_graph . read_only ( ) ;
969
973
970
974
if let Some ( chan) = graph. channels ( ) . get ( & scid) {
971
- if let Some ( liq ) = self . channel_liquidities . get ( & scid ) {
972
- if let Some ( ( directed_info , source ) ) = chan . as_directed_to ( target ) {
975
+ if let Some ( ( directed_info , source ) ) = chan . as_directed_to ( target ) {
976
+ if let Some ( liq ) = self . channel_liquidities . get ( & scid ) {
973
977
let capacity_msat = directed_info. effective_capacity ( ) . as_msat ( ) ;
974
978
let dir_liq = liq. as_directed ( source, target, capacity_msat) ;
975
979
976
- return dir_liq. liquidity_history . calculate_success_probability_times_billion (
980
+ let res = dir_liq. liquidity_history . calculate_success_probability_times_billion (
977
981
& params, amount_msat, capacity_msat
978
982
) . map ( |p| p as f64 / ( 1024 * 1024 * 1024 ) as f64 ) ;
983
+ if res. is_some ( ) {
984
+ return res;
985
+ }
986
+ }
987
+ if allow_fallback_estimation {
988
+ let amt = amount_msat;
989
+ return Some (
990
+ self . calc_live_prob ( scid, source, target, directed_info, amt, params, true )
991
+ ) ;
979
992
}
980
993
}
981
994
}
982
995
None
983
996
}
984
997
998
+ fn calc_live_prob (
999
+ & self , scid : u64 , source : & NodeId , target : & NodeId , directed_info : DirectedChannelInfo ,
1000
+ amt : u64 , params : & ProbabilisticScoringFeeParameters ,
1001
+ min_zero_penalty : bool ,
1002
+ ) -> f64 {
1003
+ let capacity_msat = directed_info. effective_capacity ( ) . as_msat ( ) ;
1004
+ let dummy_liq = ChannelLiquidity :: new ( Duration :: ZERO ) ;
1005
+ let liq = self . channel_liquidities . get ( & scid)
1006
+ . unwrap_or ( & dummy_liq)
1007
+ . as_directed ( & source, & target, capacity_msat) ;
1008
+ let min_liq = liq. min_liquidity_msat ( ) ;
1009
+ let max_liq = liq. max_liquidity_msat ( ) ;
1010
+ if amt <= liq. min_liquidity_msat ( ) {
1011
+ return 1.0 ;
1012
+ } else if amt > liq. max_liquidity_msat ( ) {
1013
+ return 0.0 ;
1014
+ }
1015
+ let ( num, den) =
1016
+ success_probability ( amt, min_liq, max_liq, capacity_msat, & params, min_zero_penalty) ;
1017
+ num as f64 / den as f64
1018
+ }
1019
+
985
1020
/// Query the probability of payment success sending the given `amount_msat` over the channel
986
1021
/// with `scid` towards the given `target` node, based on the live estimated liquidity bounds.
987
1022
///
@@ -994,20 +1029,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
994
1029
995
1030
if let Some ( chan) = graph. channels ( ) . get ( & scid) {
996
1031
if let Some ( ( directed_info, source) ) = chan. as_directed_to ( target) {
997
- let capacity_msat = directed_info. effective_capacity ( ) . as_msat ( ) ;
998
- let dummy_liq = ChannelLiquidity :: new ( Duration :: ZERO ) ;
999
- let liq = self . channel_liquidities . get ( & scid)
1000
- . unwrap_or ( & dummy_liq)
1001
- . as_directed ( & source, & target, capacity_msat) ;
1002
- let min_liq = liq. min_liquidity_msat ( ) ;
1003
- let max_liq = liq. max_liquidity_msat ( ) ;
1004
- if amount_msat <= liq. min_liquidity_msat ( ) {
1005
- return Some ( 1.0 ) ;
1006
- } else if amount_msat > liq. max_liquidity_msat ( ) {
1007
- return Some ( 0.0 ) ;
1008
- }
1009
- let ( num, den) = success_probability ( amount_msat, min_liq, max_liq, capacity_msat, & params, false ) ;
1010
- return Some ( num as f64 / den as f64 ) ;
1032
+ return Some ( self . calc_live_prob ( scid, source, target, directed_info, amount_msat, params, false ) ) ;
1011
1033
}
1012
1034
}
1013
1035
None
@@ -3234,7 +3256,7 @@ mod tests {
3234
3256
}
3235
3257
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
3236
3258
None ) ;
3237
- assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 42 , & params) ,
3259
+ assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 42 , & params, false ) ,
3238
3260
None ) ;
3239
3261
3240
3262
scorer. payment_path_failed ( & payment_path_for_amount ( 1 ) , 42 , Duration :: ZERO ) ;
@@ -3255,9 +3277,9 @@ mod tests {
3255
3277
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
3256
3278
Some ( ( [ 32 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
3257
3279
[ 0 , 0 , 0 , 0 , 0 , 0 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ) ) ;
3258
- assert ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 1 , & params)
3280
+ assert ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 1 , & params, false )
3259
3281
. unwrap( ) > 0.35 ) ;
3260
- assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 500 , & params) ,
3282
+ assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 500 , & params, false ) ,
3261
3283
Some ( 0.0 ) ) ;
3262
3284
3263
3285
// Even after we tell the scorer we definitely have enough available liquidity, it will
@@ -3282,11 +3304,11 @@ mod tests {
3282
3304
// The exact success probability is a bit complicated and involves integer rounding, so we
3283
3305
// simply check bounds here.
3284
3306
let five_hundred_prob =
3285
- scorer. historical_estimated_payment_success_probability ( 42 , & target, 500 , & params) . unwrap ( ) ;
3307
+ scorer. historical_estimated_payment_success_probability ( 42 , & target, 500 , & params, false ) . unwrap ( ) ;
3286
3308
assert ! ( five_hundred_prob > 0.59 ) ;
3287
3309
assert ! ( five_hundred_prob < 0.60 ) ;
3288
3310
let one_prob =
3289
- scorer. historical_estimated_payment_success_probability ( 42 , & target, 1 , & params) . unwrap ( ) ;
3311
+ scorer. historical_estimated_payment_success_probability ( 42 , & target, 1 , & params, false ) . unwrap ( ) ;
3290
3312
assert ! ( one_prob < 0.85 ) ;
3291
3313
assert ! ( one_prob > 0.84 ) ;
3292
3314
@@ -3308,7 +3330,7 @@ mod tests {
3308
3330
// data entirely instead.
3309
3331
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
3310
3332
Some ( ( [ 0 ; 32 ] , [ 0 ; 32 ] ) ) ) ;
3311
- assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 1 , & params) , None ) ;
3333
+ assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 1 , & params, false ) , None ) ;
3312
3334
3313
3335
let usage = ChannelUsage {
3314
3336
amount_msat : 100 ,
@@ -3494,7 +3516,7 @@ mod tests {
3494
3516
assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 1269 ) ;
3495
3517
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
3496
3518
None ) ;
3497
- assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 42 , & params) ,
3519
+ assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, 42 , & params, false ) ,
3498
3520
None ) ;
3499
3521
3500
3522
// Fail to pay once, and then check the buckets and penalty.
@@ -3509,14 +3531,14 @@ mod tests {
3509
3531
Some ( ( [ 32 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
3510
3532
[ 0 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ) ) ;
3511
3533
// The success probability estimate itself should be zero.
3512
- assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, amount_msat, & params) ,
3534
+ assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, amount_msat, & params, false ) ,
3513
3535
Some ( 0.0 ) ) ;
3514
3536
3515
3537
// Now test again with the amount in the bottom bucket.
3516
3538
amount_msat /= 2 ;
3517
3539
// The new amount is entirely within the only minimum bucket with score, so the probability
3518
3540
// we assign is 1/2.
3519
- assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, amount_msat, & params) ,
3541
+ assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, amount_msat, & params, false ) ,
3520
3542
Some ( 0.5 ) ) ;
3521
3543
3522
3544
// ...but once we see a failure, we consider the payment to be substantially less likely,
@@ -3526,7 +3548,7 @@ mod tests {
3526
3548
assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
3527
3549
Some ( ( [ 63 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
3528
3550
[ 32 , 31 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ) ) ;
3529
- assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, amount_msat, & params) ,
3551
+ assert_eq ! ( scorer. historical_estimated_payment_success_probability( 42 , & target, amount_msat, & params, false ) ,
3530
3552
Some ( 0.0 ) ) ;
3531
3553
}
3532
3554
}
0 commit comments