5252//! [`find_route`]: crate::routing::router::find_route
5353
5454use crate :: ln:: msgs:: DecodeError ;
55- use crate :: routing:: gossip:: { EffectiveCapacity , NetworkGraph , NodeId } ;
55+ use crate :: routing:: gossip:: { DirectedChannelInfo , EffectiveCapacity , NetworkGraph , NodeId } ;
5656use crate :: routing:: router:: { Path , CandidateRouteHop , PublicHopCandidate } ;
5757use crate :: routing:: log_approx;
5858use crate :: util:: ser:: { Readable , ReadableArgs , Writeable , Writer } ;
@@ -956,32 +956,67 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
956956 /// with `scid` towards the given `target` node, based on the historical estimated liquidity
957957 /// bounds.
958958 ///
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.
961964 ///
962965 /// These are the same bounds as returned by
963966 /// [`Self::historical_estimated_channel_liquidity_probabilities`] (but not those returned by
964967 /// [`Self::estimated_channel_liquidity_range`]).
965968 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 > {
968972 let graph = self . network_graph . read_only ( ) ;
969973
970974 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 ) {
973977 let capacity_msat = directed_info. effective_capacity ( ) . as_msat ( ) ;
974978 let dir_liq = liq. as_directed ( source, target, capacity_msat) ;
975979
976- return dir_liq. liquidity_history . calculate_success_probability_times_billion (
980+ let res = dir_liq. liquidity_history . calculate_success_probability_times_billion (
977981 & params, amount_msat, capacity_msat
978982 ) . 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+ ) ;
979992 }
980993 }
981994 }
982995 None
983996 }
984997
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+
9851020 /// Query the probability of payment success sending the given `amount_msat` over the channel
9861021 /// with `scid` towards the given `target` node, based on the live estimated liquidity bounds.
9871022 ///
@@ -994,20 +1029,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
9941029
9951030 if let Some ( chan) = graph. channels ( ) . get ( & scid) {
9961031 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 ) ) ;
10111033 }
10121034 }
10131035 None
@@ -3234,7 +3256,7 @@ mod tests {
32343256 }
32353257 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
32363258 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 ) ,
32383260 None ) ;
32393261
32403262 scorer. payment_path_failed ( & payment_path_for_amount ( 1 ) , 42 , Duration :: ZERO ) ;
@@ -3255,9 +3277,9 @@ mod tests {
32553277 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
32563278 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 ] ,
32573279 [ 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 )
32593281 . 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 ) ,
32613283 Some ( 0.0 ) ) ;
32623284
32633285 // Even after we tell the scorer we definitely have enough available liquidity, it will
@@ -3282,11 +3304,11 @@ mod tests {
32823304 // The exact success probability is a bit complicated and involves integer rounding, so we
32833305 // simply check bounds here.
32843306 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 ( ) ;
32863308 assert ! ( five_hundred_prob > 0.59 ) ;
32873309 assert ! ( five_hundred_prob < 0.60 ) ;
32883310 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 ( ) ;
32903312 assert ! ( one_prob < 0.85 ) ;
32913313 assert ! ( one_prob > 0.84 ) ;
32923314
@@ -3308,7 +3330,7 @@ mod tests {
33083330 // data entirely instead.
33093331 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
33103332 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 ) ;
33123334
33133335 let usage = ChannelUsage {
33143336 amount_msat : 100 ,
@@ -3494,7 +3516,7 @@ mod tests {
34943516 assert_eq ! ( scorer. channel_penalty_msat( & candidate, usage, & params) , 1269 ) ;
34953517 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
34963518 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 ) ,
34983520 None ) ;
34993521
35003522 // Fail to pay once, and then check the buckets and penalty.
@@ -3509,14 +3531,14 @@ mod tests {
35093531 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 ] ,
35103532 [ 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 ] ) ) ) ;
35113533 // 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 ) ,
35133535 Some ( 0.0 ) ) ;
35143536
35153537 // Now test again with the amount in the bottom bucket.
35163538 amount_msat /= 2 ;
35173539 // The new amount is entirely within the only minimum bucket with score, so the probability
35183540 // 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 ) ,
35203542 Some ( 0.5 ) ) ;
35213543
35223544 // ...but once we see a failure, we consider the payment to be substantially less likely,
@@ -3526,7 +3548,7 @@ mod tests {
35263548 assert_eq ! ( scorer. historical_estimated_channel_liquidity_probabilities( 42 , & target) ,
35273549 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 ] ,
35283550 [ 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 ) ,
35303552 Some ( 0.0 ) ) ;
35313553 }
35323554}
0 commit comments