@@ -733,6 +733,28 @@ impl<L: DerefMut<Target = u64>, T: Time, U: DerefMut<Target = T>> DirectedChanne
733
733
}
734
734
}
735
735
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
+
736
758
impl < G : Deref < Target = NetworkGraph > , T : Time > Score for ProbabilisticScorerUsingTime < G , T > {
737
759
fn channel_penalty_msat (
738
760
& 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
749
771
Probability :: Zero => u64:: max_value ( ) ,
750
772
Probability :: One => 0 ,
751
773
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
754
776
}
755
777
} ;
756
778
// Upper bound the penalty to ensure some channel is selected.
@@ -1625,18 +1647,18 @@ mod tests {
1625
1647
let source = source_node_id ( ) ;
1626
1648
let target = target_node_id ( ) ;
1627
1649
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 ) ;
1632
1654
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 ) ;
1640
1662
}
1641
1663
1642
1664
#[ test]
@@ -1672,13 +1694,13 @@ mod tests {
1672
1694
let failed_path = payment_path_for_amount ( 500 ) ;
1673
1695
let successful_path = payment_path_for_amount ( 200 ) ;
1674
1696
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 ) ;
1676
1698
1677
1699
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 ) ;
1679
1701
1680
1702
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 ) ;
1682
1704
}
1683
1705
1684
1706
#[ test]
@@ -1692,15 +1714,15 @@ mod tests {
1692
1714
let target = target_node_id ( ) ;
1693
1715
let path = payment_path_for_amount ( 500 ) ;
1694
1716
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 ) ;
1698
1720
1699
1721
scorer. payment_path_failed ( & path. iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
1700
1722
1701
1723
assert_eq ! ( scorer. channel_penalty_msat( 42 , 250 , 1_000 , & source, & target) , 0 ) ;
1702
1724
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 ) ;
1704
1726
}
1705
1727
1706
1728
#[ test]
@@ -1714,13 +1736,13 @@ mod tests {
1714
1736
let target = target_node_id ( ) ;
1715
1737
let path = payment_path_for_amount ( 500 ) ;
1716
1738
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 ) ;
1720
1742
1721
1743
scorer. payment_path_failed ( & path. iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
1722
1744
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 ) ;
1724
1746
assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 2_000 ) ;
1725
1747
assert_eq ! ( scorer. channel_penalty_msat( 42 , 750 , 1_000 , & source, & target) , 2_000 ) ;
1726
1748
}
@@ -1738,15 +1760,15 @@ mod tests {
1738
1760
let recipient = recipient_node_id ( ) ;
1739
1761
let path = payment_path_for_amount ( 500 ) ;
1740
1762
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 ) ;
1744
1766
1745
1767
scorer. payment_path_successful ( & path. iter ( ) . collect :: < Vec < _ > > ( ) ) ;
1746
1768
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 ) ;
1750
1772
}
1751
1773
1752
1774
#[ test]
@@ -1767,20 +1789,20 @@ mod tests {
1767
1789
scorer. payment_path_failed ( & payment_path_for_amount ( 128 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
1768
1790
1769
1791
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 ) ;
1772
1794
assert_eq ! ( scorer. channel_penalty_msat( 42 , 896 , 1_024 , & source, & target) , 2_000 ) ;
1773
1795
1774
1796
SinceEpoch :: advance ( Duration :: from_secs ( 9 ) ) ;
1775
1797
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 ) ;
1778
1800
assert_eq ! ( scorer. channel_penalty_msat( 42 , 896 , 1_024 , & source, & target) , 2_000 ) ;
1779
1801
1780
1802
SinceEpoch :: advance ( Duration :: from_secs ( 1 ) ) ;
1781
1803
assert_eq ! ( scorer. channel_penalty_msat( 42 , 64 , 1_024 , & source, & target) , 0 ) ;
1782
1804
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 ) ;
1784
1806
assert_eq ! ( scorer. channel_penalty_msat( 42 , 960 , 1_024 , & source, & target) , 2_000 ) ;
1785
1807
1786
1808
// Fully decay liquidity lower bound.
@@ -1813,7 +1835,7 @@ mod tests {
1813
1835
assert_eq ! ( scorer. channel_penalty_msat( 42 , 256 , 1_024 , & source, & target) , 124 ) ;
1814
1836
1815
1837
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 ) ;
1817
1839
1818
1840
// An unchecked right shift 64 bits or more in DirectedChannelLiquidity::decayed_offset_msat
1819
1841
// would cause an overflow.
@@ -1835,30 +1857,30 @@ mod tests {
1835
1857
let source = source_node_id ( ) ;
1836
1858
let target = target_node_id ( ) ;
1837
1859
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 ) ;
1839
1861
1840
1862
// More knowledge gives higher confidence (256, 768), meaning a lower penalty.
1841
1863
scorer. payment_path_failed ( & payment_path_for_amount ( 768 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
1842
1864
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 ) ;
1844
1866
1845
1867
// Decaying knowledge gives less confidence (128, 896), meaning a higher penalty.
1846
1868
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 ) ;
1848
1870
1849
1871
// Reducing the upper bound gives more confidence (128, 832) that the payment amount (512)
1850
1872
// is closer to the upper bound, meaning a higher penalty.
1851
1873
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 ) ;
1853
1875
1854
1876
// Increasing the lower bound gives more confidence (256, 832) that the payment amount (512)
1855
1877
// is closer to the lower bound, meaning a lower penalty.
1856
1878
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 ) ;
1858
1880
1859
1881
// Further decaying affects the lower bound more than the upper bound (128, 928).
1860
1882
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 ) ;
1862
1884
}
1863
1885
1864
1886
#[ test]
@@ -1876,18 +1898,18 @@ mod tests {
1876
1898
assert_eq ! ( scorer. channel_penalty_msat( 42 , 500 , 1_000 , & source, & target) , 2_000 ) ;
1877
1899
1878
1900
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 ) ;
1880
1902
1881
1903
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 ) ;
1883
1905
1884
1906
let mut serialized_scorer = Vec :: new ( ) ;
1885
1907
scorer. write ( & mut serialized_scorer) . unwrap ( ) ;
1886
1908
1887
1909
let mut serialized_scorer = io:: Cursor :: new ( & serialized_scorer) ;
1888
1910
let deserialized_scorer =
1889
1911
<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 ) ;
1891
1913
}
1892
1914
1893
1915
#[ test]
@@ -1912,12 +1934,12 @@ mod tests {
1912
1934
let mut serialized_scorer = io:: Cursor :: new ( & serialized_scorer) ;
1913
1935
let deserialized_scorer =
1914
1936
<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 ) ;
1916
1938
1917
1939
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 ) ;
1919
1941
1920
1942
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 ) ;
1922
1944
}
1923
1945
}
0 commit comments