@@ -366,6 +366,14 @@ pub struct ProbabilisticScoringParameters {
366
366
///
367
367
/// (C-not exported)
368
368
pub banned_nodes : HashSet < NodeId > ,
369
+
370
+ /// This penalty is applied when `htlc_maximum_msat` is equal to or larger than half of the
371
+ /// channel's capacity, which makes us prefer nodes with a smaller `htlc_maximum_msat`. We
372
+ /// treat such nodes preferentially as this makes balance discovery attacks harder to execute,
373
+ /// thereby creating an incentive to restrict `htlc_maximum_msat` and improve privacy.
374
+ ///
375
+ /// Default value: 250 msat
376
+ pub anti_probing_penalty_msat : u64 ,
369
377
}
370
378
371
379
/// Accounting for channel liquidity balance uncertainty.
@@ -483,6 +491,7 @@ impl ProbabilisticScoringParameters {
483
491
liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
484
492
amount_penalty_multiplier_msat : 0 ,
485
493
banned_nodes : HashSet :: new ( ) ,
494
+ anti_probing_penalty_msat : 0 ,
486
495
}
487
496
}
488
497
@@ -503,6 +512,7 @@ impl Default for ProbabilisticScoringParameters {
503
512
liquidity_offset_half_life : Duration :: from_secs ( 3600 ) ,
504
513
amount_penalty_multiplier_msat : 256 ,
505
514
banned_nodes : HashSet :: new ( ) ,
515
+ anti_probing_penalty_msat : 250 ,
506
516
}
507
517
}
508
518
}
@@ -707,12 +717,21 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
707
717
return u64:: max_value ( ) ;
708
718
}
709
719
710
- if let EffectiveCapacity :: ExactLiquidity { liquidity_msat } = usage. effective_capacity {
711
- if usage. amount_msat > liquidity_msat {
712
- return u64:: max_value ( ) ;
713
- } else {
714
- return self . params . base_penalty_msat ;
715
- } ;
720
+ let mut anti_probing_penalty_msat = 0 ;
721
+ match usage. effective_capacity {
722
+ EffectiveCapacity :: ExactLiquidity { liquidity_msat } => {
723
+ if usage. amount_msat > liquidity_msat {
724
+ return u64:: max_value ( ) ;
725
+ } else {
726
+ return self . params . base_penalty_msat ;
727
+ }
728
+ } ,
729
+ EffectiveCapacity :: Total { capacity_msat, htlc_maximum_msat : Some ( htlc_maximum_msat) } => {
730
+ if htlc_maximum_msat >= capacity_msat/2 {
731
+ anti_probing_penalty_msat = self . params . anti_probing_penalty_msat ;
732
+ }
733
+ } ,
734
+ _ => { } ,
716
735
}
717
736
718
737
let liquidity_offset_half_life = self . params . liquidity_offset_half_life ;
@@ -724,6 +743,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> Score for Probabilis
724
743
. unwrap_or ( & ChannelLiquidity :: new ( ) )
725
744
. as_directed ( source, target, capacity_msat, liquidity_offset_half_life)
726
745
. penalty_msat ( amount_msat, & self . params )
746
+ . saturating_add ( anti_probing_penalty_msat)
727
747
}
728
748
729
749
fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
@@ -1547,7 +1567,7 @@ mod tests {
1547
1567
let usage = ChannelUsage {
1548
1568
amount_msat : 1_024 ,
1549
1569
inflight_htlc_msat : 0 ,
1550
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 } ,
1570
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1551
1571
} ;
1552
1572
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
1553
1573
let usage = ChannelUsage { amount_msat : 10_240 , ..usage } ;
@@ -1560,7 +1580,7 @@ mod tests {
1560
1580
let usage = ChannelUsage {
1561
1581
amount_msat : 128 ,
1562
1582
inflight_htlc_msat : 0 ,
1563
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 } ,
1583
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 , htlc_maximum_msat : Some ( 1_000 ) } ,
1564
1584
} ;
1565
1585
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 58 ) ;
1566
1586
let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
@@ -1597,7 +1617,7 @@ mod tests {
1597
1617
let usage = ChannelUsage {
1598
1618
amount_msat : 39 ,
1599
1619
inflight_htlc_msat : 0 ,
1600
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 100 } ,
1620
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 100 , htlc_maximum_msat : Some ( 1_000 ) } ,
1601
1621
} ;
1602
1622
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
1603
1623
let usage = ChannelUsage { amount_msat : 50 , ..usage } ;
@@ -1621,7 +1641,7 @@ mod tests {
1621
1641
let usage = ChannelUsage {
1622
1642
amount_msat : 500 ,
1623
1643
inflight_htlc_msat : 0 ,
1624
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 } ,
1644
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1625
1645
} ;
1626
1646
let failed_path = payment_path_for_amount ( 500 ) ;
1627
1647
let successful_path = payment_path_for_amount ( 200 ) ;
@@ -1651,7 +1671,7 @@ mod tests {
1651
1671
let usage = ChannelUsage {
1652
1672
amount_msat : 250 ,
1653
1673
inflight_htlc_msat : 0 ,
1654
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 } ,
1674
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1655
1675
} ;
1656
1676
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 128 ) ;
1657
1677
let usage = ChannelUsage { amount_msat : 500 , ..usage } ;
@@ -1685,7 +1705,7 @@ mod tests {
1685
1705
let usage = ChannelUsage {
1686
1706
amount_msat : 250 ,
1687
1707
inflight_htlc_msat : 0 ,
1688
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 } ,
1708
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1689
1709
} ;
1690
1710
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 128 ) ;
1691
1711
let usage = ChannelUsage { amount_msat : 500 , ..usage } ;
@@ -1719,7 +1739,7 @@ mod tests {
1719
1739
let usage = ChannelUsage {
1720
1740
amount_msat : 250 ,
1721
1741
inflight_htlc_msat : 0 ,
1722
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 } ,
1742
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1723
1743
} ;
1724
1744
let path = payment_path_for_amount ( 500 ) ;
1725
1745
@@ -1750,7 +1770,7 @@ mod tests {
1750
1770
let usage = ChannelUsage {
1751
1771
amount_msat : 0 ,
1752
1772
inflight_htlc_msat : 0 ,
1753
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 } ,
1773
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 , htlc_maximum_msat : Some ( 1_000 ) } ,
1754
1774
} ;
1755
1775
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
1756
1776
let usage = ChannelUsage { amount_msat : 1_024 , ..usage } ;
@@ -1828,7 +1848,7 @@ mod tests {
1828
1848
let usage = ChannelUsage {
1829
1849
amount_msat : 256 ,
1830
1850
inflight_htlc_msat : 0 ,
1831
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 } ,
1851
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 , htlc_maximum_msat : Some ( 1_000 ) } ,
1832
1852
} ;
1833
1853
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 125 ) ;
1834
1854
@@ -1859,7 +1879,7 @@ mod tests {
1859
1879
let usage = ChannelUsage {
1860
1880
amount_msat : 512 ,
1861
1881
inflight_htlc_msat : 0 ,
1862
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 } ,
1882
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 , htlc_maximum_msat : Some ( 1_000 ) } ,
1863
1883
} ;
1864
1884
1865
1885
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 300 ) ;
@@ -1903,7 +1923,7 @@ mod tests {
1903
1923
let usage = ChannelUsage {
1904
1924
amount_msat : 500 ,
1905
1925
inflight_htlc_msat : 0 ,
1906
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 } ,
1926
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1907
1927
} ;
1908
1928
1909
1929
scorer. payment_path_failed ( & payment_path_for_amount ( 500 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
@@ -1939,7 +1959,7 @@ mod tests {
1939
1959
let usage = ChannelUsage {
1940
1960
amount_msat : 500 ,
1941
1961
inflight_htlc_msat : 0 ,
1942
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 } ,
1962
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1943
1963
} ;
1944
1964
1945
1965
scorer. payment_path_failed ( & payment_path_for_amount ( 500 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
@@ -1976,47 +1996,47 @@ mod tests {
1976
1996
let usage = ChannelUsage {
1977
1997
amount_msat : 100_000_000 ,
1978
1998
inflight_htlc_msat : 0 ,
1979
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 } ,
1999
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
1980
2000
} ;
1981
2001
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 3613 ) ;
1982
2002
let usage = ChannelUsage {
1983
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 } , ..usage
2003
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
1984
2004
} ;
1985
2005
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1977 ) ;
1986
2006
let usage = ChannelUsage {
1987
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 } , ..usage
2007
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 2_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
1988
2008
} ;
1989
2009
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1474 ) ;
1990
2010
let usage = ChannelUsage {
1991
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 } , ..usage
2011
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 3_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
1992
2012
} ;
1993
2013
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 1223 ) ;
1994
2014
let usage = ChannelUsage {
1995
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 } , ..usage
2015
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 4_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
1996
2016
} ;
1997
2017
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 877 ) ;
1998
2018
let usage = ChannelUsage {
1999
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 } , ..usage
2019
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 5_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2000
2020
} ;
2001
2021
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 845 ) ;
2002
2022
let usage = ChannelUsage {
2003
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 } , ..usage
2023
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 6_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2004
2024
} ;
2005
2025
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2006
2026
let usage = ChannelUsage {
2007
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 } , ..usage
2027
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_450_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2008
2028
} ;
2009
2029
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2010
2030
let usage = ChannelUsage {
2011
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 } , ..usage
2031
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 7_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2012
2032
} ;
2013
2033
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2014
2034
let usage = ChannelUsage {
2015
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 } , ..usage
2035
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 8_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2016
2036
} ;
2017
2037
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2018
2038
let usage = ChannelUsage {
2019
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 } , ..usage
2039
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 9_950_000_000 , htlc_maximum_msat : Some ( 1_000 ) } , ..usage
2020
2040
} ;
2021
2041
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2022
2042
}
@@ -2030,7 +2050,7 @@ mod tests {
2030
2050
let usage = ChannelUsage {
2031
2051
amount_msat : 128 ,
2032
2052
inflight_htlc_msat : 0 ,
2033
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 } ,
2053
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024 , htlc_maximum_msat : Some ( 1_000 ) } ,
2034
2054
} ;
2035
2055
2036
2056
let params = ProbabilisticScoringParameters {
@@ -2041,7 +2061,8 @@ mod tests {
2041
2061
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 58 ) ;
2042
2062
2043
2063
let params = ProbabilisticScoringParameters {
2044
- base_penalty_msat : 500 , liquidity_penalty_multiplier_msat : 1_000 , ..Default :: default ( )
2064
+ base_penalty_msat : 500 , liquidity_penalty_multiplier_msat : 1_000 ,
2065
+ anti_probing_penalty_msat : 0 , ..Default :: default ( )
2045
2066
} ;
2046
2067
let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2047
2068
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 558 ) ;
@@ -2056,7 +2077,7 @@ mod tests {
2056
2077
let usage = ChannelUsage {
2057
2078
amount_msat : 512_000 ,
2058
2079
inflight_htlc_msat : 0 ,
2059
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 } ,
2080
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
2060
2081
} ;
2061
2082
2062
2083
let params = ProbabilisticScoringParameters {
@@ -2108,7 +2129,7 @@ mod tests {
2108
2129
let usage = ChannelUsage {
2109
2130
amount_msat : 750 ,
2110
2131
inflight_htlc_msat : 0 ,
2111
- effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 } ,
2132
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
2112
2133
} ;
2113
2134
assert_ne ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , u64 :: max_value( ) ) ;
2114
2135
@@ -2139,4 +2160,49 @@ mod tests {
2139
2160
let usage = ChannelUsage { amount_msat : 1_001 , ..usage } ;
2140
2161
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , u64 :: max_value( ) ) ;
2141
2162
}
2163
+
2164
+ #[ test]
2165
+ fn adds_anti_probing_penalty ( ) {
2166
+ let logger = TestLogger :: new ( ) ;
2167
+ let network_graph = network_graph ( & logger) ;
2168
+ let source = source_node_id ( ) ;
2169
+ let target = target_node_id ( ) ;
2170
+ let params = ProbabilisticScoringParameters {
2171
+ anti_probing_penalty_msat : 500 ,
2172
+ ..ProbabilisticScoringParameters :: zero_penalty ( )
2173
+ } ;
2174
+ let scorer = ProbabilisticScorer :: new ( params, & network_graph, & logger) ;
2175
+
2176
+ // Check we receive no penalty for a low htlc_maximum_msat.
2177
+ let usage = ChannelUsage {
2178
+ amount_msat : 512_000 ,
2179
+ inflight_htlc_msat : 0 ,
2180
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 , htlc_maximum_msat : Some ( 1_000 ) } ,
2181
+ } ;
2182
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
2183
+
2184
+ // Check we receive anti-probing penalty for htlc_maximum_msat == channel_capacity.
2185
+ let usage = ChannelUsage {
2186
+ amount_msat : 512_000 ,
2187
+ inflight_htlc_msat : 0 ,
2188
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 , htlc_maximum_msat : Some ( 1_024_000 ) } ,
2189
+ } ;
2190
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2191
+
2192
+ // Check we receive anti-probing penalty for htlc_maximum_msat == channel_capacity/2.
2193
+ let usage = ChannelUsage {
2194
+ amount_msat : 512_000 ,
2195
+ inflight_htlc_msat : 0 ,
2196
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 , htlc_maximum_msat : Some ( 512_000 ) } ,
2197
+ } ;
2198
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 500 ) ;
2199
+
2200
+ // Check we receive no anti-probing penalty for htlc_maximum_msat == channel_capacity/2 - 1.
2201
+ let usage = ChannelUsage {
2202
+ amount_msat : 512_000 ,
2203
+ inflight_htlc_msat : 0 ,
2204
+ effective_capacity : EffectiveCapacity :: Total { capacity_msat : 1_024_000 , htlc_maximum_msat : Some ( 511_999 ) } ,
2205
+ } ;
2206
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
2207
+ }
2142
2208
}
0 commit comments