@@ -733,6 +733,28 @@ impl<L: DerefMut<Target = u64>, T: Time, U: DerefMut<Target = T>> DirectedChanne
733733 }
734734}
735735
736+ const FRACTIONAL_BITS : u32 = 4 ;
737+ const FRACTIONAL_BITMASK : u64 = ( 1 << FRACTIONAL_BITS ) - 1 ;
738+ const LOG2_FRACTIONAL_PART : [ f64 ; 1 << FRACTIONAL_BITS ] = [
739+ 0.000 , 0.087 , 0.170 , 0.248 , 0.322 , 0.392 , 0.459 , 0.524 ,
740+ 0.585 , 0.644 , 0.700 , 0.755 , 0.807 , 0.858 , 0.907 , 0.954 ,
741+ ] ;
742+ const LOG2_10 : f64 = 3.322 ;
743+
744+ fn log10_approx ( numerator : u64 , denominator : u64 ) -> f64 {
745+ ( log2_approx ( numerator) - log2_approx ( denominator) ) / LOG2_10
746+ }
747+
748+ #[ inline]
749+ fn log2_approx ( x : u64 ) -> f64 {
750+ let leading_zeros = x. leading_zeros ( ) ;
751+ let integer_part = ( 63 - leading_zeros) as f64 ;
752+ let fractional_part = LOG2_FRACTIONAL_PART [
753+ ( ( ( x << leading_zeros) >> ( 63 - FRACTIONAL_BITS ) ) & FRACTIONAL_BITMASK ) as usize
754+ ] ;
755+ integer_part + fractional_part
756+ }
757+
736758impl < G : Deref < Target = NetworkGraph > , T : Time > Score for ProbabilisticScorerUsingTime < G , T > {
737759 fn channel_penalty_msat (
738760 & self , short_channel_id : u64 , amount_msat : u64 , capacity_msat : u64 , source : & NodeId ,
@@ -749,8 +771,8 @@ impl<G: Deref<Target = NetworkGraph>, T: Time> Score for ProbabilisticScorerUsin
749771 Probability :: Zero => u64:: max_value ( ) ,
750772 Probability :: One => 0 ,
751773 Probability :: Ratio { numerator, denominator } => {
752- let success_probability = numerator as f64 / denominator as f64 ;
753- ( -( success_probability . log10 ( ) ) * liquidity_penalty_multiplier_msat as f64 ) as u64
774+ let log_success_probability = log10_approx ( numerator, denominator) ;
775+ ( -log_success_probability * liquidity_penalty_multiplier_msat as f64 ) as u64
754776 }
755777 } ;
756778 // Upper bound the penalty to ensure some channel is selected.
@@ -1625,18 +1647,18 @@ mod tests {
16251647 let source = source_node_id ( ) ;
16261648 let target = target_node_id ( ) ;
16271649
1628- assert_eq ! ( scorer. channel_penalty_msat( 42 , 100 , 100_000 , & source, & target) , 0 ) ;
1629- assert_eq ! ( scorer. channel_penalty_msat( 42 , 1_000 , 100_000 , & source, & target) , 4 ) ;
1630- assert_eq ! ( scorer. channel_penalty_msat( 42 , 10_000 , 100_000 , & source, & target) , 45 ) ;
1631- assert_eq ! ( scorer. channel_penalty_msat( 42 , 100_000 , 100_000 , & source, & target) , 2_000 ) ;
1650+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 1_024 , 1_024_000 , & source, & target) , 0 ) ;
1651+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 10_240 , 1_024_000 , & source, & target) , 14 ) ;
1652+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 102_400 , 1_024_000 , & source, & target) , 44 ) ;
1653+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 1_024_000 , 1_024_000 , & source, & target) , 2_000 ) ;
16321654
1633- assert_eq ! ( scorer. channel_penalty_msat( 42 , 125 , 1_000 , & source, & target) , 57 ) ;
1634- assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 124 ) ;
1635- assert_eq ! ( scorer. channel_penalty_msat( 42 , 375 , 1_000 , & source, & target) , 203 ) ;
1636- assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 300 ) ;
1637- assert_eq ! ( scorer. channel_penalty_msat( 42 , 625 , 1_000 , & source, & target) , 425 ) ;
1638- assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 600 ) ;
1639- assert_eq ! ( scorer. channel_penalty_msat( 42 , 875 , 1_000 , & source, & target) , 900 ) ;
1655+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 128 , 1_024 , & source, & target) , 58 ) ;
1656+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 124 ) ;
1657+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 374 , 1_024 , & source, & target) , 204 ) ;
1658+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 301 ) ;
1659+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 640 , 1_024 , & source, & target) , 425 ) ;
1660+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 768 , 1_024 , & source, & target) , 602 ) ;
1661+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 896 , 1_024 , & source, & target) , 903 ) ;
16401662 }
16411663
16421664 #[ test]
@@ -1672,13 +1694,13 @@ mod tests {
16721694 let failed_path = payment_path_for_amount ( 500 ) ;
16731695 let successful_path = payment_path_for_amount ( 200 ) ;
16741696
1675- assert_eq ! ( scorer. channel_penalty_msat( 41 , 500 , 1_000 , & sender, & source) , 300 ) ;
1697+ assert_eq ! ( scorer. channel_penalty_msat( 41 , 500 , 1_000 , & sender, & source) , 301 ) ;
16761698
16771699 scorer. payment_path_failed ( & failed_path. iter ( ) . collect :: < Vec < _ > > ( ) , 41 ) ;
1678- assert_eq ! ( scorer. channel_penalty_msat( 41 , 500 , 1_000 , & sender, & source) , 300 ) ;
1700+ assert_eq ! ( scorer. channel_penalty_msat( 41 , 500 , 1_000 , & sender, & source) , 301 ) ;
16791701
16801702 scorer. payment_path_successful ( & successful_path. iter ( ) . collect :: < Vec < _ > > ( ) ) ;
1681- assert_eq ! ( scorer. channel_penalty_msat( 41 , 500 , 1_000 , & sender, & source) , 300 ) ;
1703+ assert_eq ! ( scorer. channel_penalty_msat( 41 , 500 , 1_000 , & sender, & source) , 301 ) ;
16821704 }
16831705
16841706 #[ test]
@@ -1692,15 +1714,15 @@ mod tests {
16921714 let target = target_node_id ( ) ;
16931715 let path = payment_path_for_amount ( 500 ) ;
16941716
1695- assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 124 ) ;
1696- assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 300 ) ;
1697- assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 600 ) ;
1717+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 129 ) ;
1718+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 301 ) ;
1719+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 602 ) ;
16981720
16991721 scorer. payment_path_failed ( & path. iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
17001722
17011723 assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 0 ) ;
17021724 assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 0 ) ;
1703- assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 300 ) ;
1725+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 301 ) ;
17041726 }
17051727
17061728 #[ test]
@@ -1714,13 +1736,13 @@ mod tests {
17141736 let target = target_node_id ( ) ;
17151737 let path = payment_path_for_amount ( 500 ) ;
17161738
1717- assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 124 ) ;
1718- assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 300 ) ;
1719- assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 600 ) ;
1739+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 129 ) ;
1740+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 301 ) ;
1741+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 602 ) ;
17201742
17211743 scorer. payment_path_failed ( & path. iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
17221744
1723- assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 300 ) ;
1745+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 301 ) ;
17241746 assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 2_000 ) ;
17251747 assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 2_000 ) ;
17261748 }
@@ -1738,15 +1760,15 @@ mod tests {
17381760 let recipient = recipient_node_id ( ) ;
17391761 let path = payment_path_for_amount ( 500 ) ;
17401762
1741- assert_eq ! ( scorer. channel_penalty_msat( 41 , 250 , 1_000 , & sender, & source) , 124 ) ;
1742- assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 124 ) ;
1743- assert_eq ! ( scorer. channel_penalty_msat( 43 , 250 , 1_000 , & target, & recipient) , 124 ) ;
1763+ assert_eq ! ( scorer. channel_penalty_msat( 41 , 250 , 1_000 , & sender, & source) , 129 ) ;
1764+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 129 ) ;
1765+ assert_eq ! ( scorer. channel_penalty_msat( 43 , 250 , 1_000 , & target, & recipient) , 129 ) ;
17441766
17451767 scorer. payment_path_successful ( & path. iter ( ) . collect :: < Vec < _ > > ( ) ) ;
17461768
1747- assert_eq ! ( scorer. channel_penalty_msat( 41 , 250 , 1_000 , & sender, & source) , 124 ) ;
1748- assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 300 ) ;
1749- assert_eq ! ( scorer. channel_penalty_msat( 43 , 250 , 1_000 , & target, & recipient) , 300 ) ;
1769+ assert_eq ! ( scorer. channel_penalty_msat( 41 , 250 , 1_000 , & sender, & source) , 129 ) ;
1770+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 301 ) ;
1771+ assert_eq ! ( scorer. channel_penalty_msat( 43 , 250 , 1_000 , & target, & recipient) , 301 ) ;
17501772 }
17511773
17521774 #[ test]
@@ -1767,20 +1789,20 @@ mod tests {
17671789 scorer. payment_path_failed ( & payment_path_for_amount ( 128 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
17681790
17691791 assert_eq ! ( scorer. channel_penalty_msat( 42 , 128 , 1_024 , & source, & target) , 0 ) ;
1770- assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 92 ) ;
1771- assert_eq ! ( scorer. channel_penalty_msat( 42 , 768 , 1_024 , & source, & target) , 1_424 ) ;
1792+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 96 ) ;
1793+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 768 , 1_024 , & source, & target) , 1_408 ) ;
17721794 assert_eq ! ( scorer. channel_penalty_msat( 42 , 896 , 1_024 , & source, & target) , 2_000 ) ;
17731795
17741796 SinceEpoch :: advance ( Duration :: from_secs ( 9 ) ) ;
17751797 assert_eq ! ( scorer. channel_penalty_msat( 42 , 128 , 1_024 , & source, & target) , 0 ) ;
1776- assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 92 ) ;
1777- assert_eq ! ( scorer. channel_penalty_msat( 42 , 768 , 1_024 , & source, & target) , 1_424 ) ;
1798+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 96 ) ;
1799+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 768 , 1_024 , & source, & target) , 1_408 ) ;
17781800 assert_eq ! ( scorer. channel_penalty_msat( 42 , 896 , 1_024 , & source, & target) , 2_000 ) ;
17791801
17801802 SinceEpoch :: advance ( Duration :: from_secs ( 1 ) ) ;
17811803 assert_eq ! ( scorer. channel_penalty_msat( 42 , 64 , 1_024 , & source, & target) , 0 ) ;
17821804 assert_eq ! ( scorer. channel_penalty_msat( 42 , 128 , 1_024 , & source, & target) , 34 ) ;
1783- assert_eq ! ( scorer. channel_penalty_msat( 42 , 896 , 1_024 , & source, & target) , 1_812 ) ;
1805+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 896 , 1_024 , & source, & target) , 1_806 ) ;
17841806 assert_eq ! ( scorer. channel_penalty_msat( 42 , 960 , 1_024 , & source, & target) , 2_000 ) ;
17851807
17861808 // Fully decay liquidity lower bound.
@@ -1813,7 +1835,7 @@ mod tests {
18131835 assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 124 ) ;
18141836
18151837 scorer. payment_path_failed ( & payment_path_for_amount ( 512 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
1816- assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 281 ) ;
1838+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 274 ) ;
18171839
18181840 // An unchecked right shift 64 bits or more in DirectedChannelLiquidity::decayed_offset_msat
18191841 // would cause an overflow.
@@ -1835,30 +1857,30 @@ mod tests {
18351857 let source = source_node_id ( ) ;
18361858 let target = target_node_id ( ) ;
18371859
1838- assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 300 ) ;
1860+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 301 ) ;
18391861
18401862 // More knowledge gives higher confidence (256, 768), meaning a lower penalty.
18411863 scorer. payment_path_failed ( & payment_path_for_amount ( 768 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
18421864 scorer. payment_path_failed ( & payment_path_for_amount ( 256 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
1843- assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 281 ) ;
1865+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 274 ) ;
18441866
18451867 // Decaying knowledge gives less confidence (128, 896), meaning a higher penalty.
18461868 SinceEpoch :: advance ( Duration :: from_secs ( 10 ) ) ;
1847- assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 293 ) ;
1869+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 301 ) ;
18481870
18491871 // Reducing the upper bound gives more confidence (128, 832) that the payment amount (512)
18501872 // is closer to the upper bound, meaning a higher penalty.
18511873 scorer. payment_path_successful ( & payment_path_for_amount ( 64 ) . iter ( ) . collect :: < Vec < _ > > ( ) ) ;
1852- assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 333 ) ;
1874+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 342 ) ;
18531875
18541876 // Increasing the lower bound gives more confidence (256, 832) that the payment amount (512)
18551877 // is closer to the lower bound, meaning a lower penalty.
18561878 scorer. payment_path_failed ( & payment_path_for_amount ( 256 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
1857- assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 247 ) ;
1879+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 255 ) ;
18581880
18591881 // Further decaying affects the lower bound more than the upper bound (128, 928).
18601882 SinceEpoch :: advance ( Duration :: from_secs ( 10 ) ) ;
1861- assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 280 ) ;
1883+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 512 , 1_024 , & source, & target) , 284 ) ;
18621884 }
18631885
18641886 #[ test]
@@ -1876,18 +1898,18 @@ mod tests {
18761898 assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 2_000 ) ;
18771899
18781900 SinceEpoch :: advance ( Duration :: from_secs ( 10 ) ) ;
1879- assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 475 ) ;
1901+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 472 ) ;
18801902
18811903 scorer. payment_path_failed ( & payment_path_for_amount ( 250 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
1882- assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 300 ) ;
1904+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 301 ) ;
18831905
18841906 let mut serialized_scorer = Vec :: new ( ) ;
18851907 scorer. write ( & mut serialized_scorer) . unwrap ( ) ;
18861908
18871909 let mut serialized_scorer = io:: Cursor :: new ( & serialized_scorer) ;
18881910 let deserialized_scorer =
18891911 <ProbabilisticScorer >:: read ( & mut serialized_scorer, ( params, & network_graph) ) . unwrap ( ) ;
1890- assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 300 ) ;
1912+ assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 301 ) ;
18911913 }
18921914
18931915 #[ test]
@@ -1912,12 +1934,12 @@ mod tests {
19121934 let mut serialized_scorer = io:: Cursor :: new ( & serialized_scorer) ;
19131935 let deserialized_scorer =
19141936 <ProbabilisticScorer >:: read ( & mut serialized_scorer, ( params, & network_graph) ) . unwrap ( ) ;
1915- assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 475 ) ;
1937+ assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 472 ) ;
19161938
19171939 scorer. payment_path_failed ( & payment_path_for_amount ( 250 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
1918- assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 300 ) ;
1940+ assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 301 ) ;
19191941
19201942 SinceEpoch :: advance ( Duration :: from_secs ( 10 ) ) ;
1921- assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 367 ) ;
1943+ assert_eq ! ( deserialized_scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 370 ) ;
19221944 }
19231945}
0 commit comments