@@ -997,10 +997,30 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
997
997
}
998
998
999
999
fn decayed_offset_msat ( & self , offset_msat : u64 ) -> u64 {
1000
- self . now . duration_since ( * self . last_updated ) . as_secs ( )
1001
- . checked_div ( self . params . liquidity_offset_half_life . as_secs ( ) )
1002
- . and_then ( |decays| offset_msat. checked_shr ( decays as u32 ) )
1003
- . unwrap_or ( 0 )
1000
+ let elapsed_time = self . now . duration_since ( * self . last_updated ) . as_secs ( ) ;
1001
+ let half_life = self . params . liquidity_offset_half_life . as_secs ( ) ;
1002
+
1003
+ match elapsed_time. checked_div ( half_life) {
1004
+ None => 0 ,
1005
+ Some ( decays) => match elapsed_time. checked_div ( half_life / 2 ) {
1006
+ None => 0 ,
1007
+ Some ( half_decays) => {
1008
+ // Decay the offset by the appropriate number of half lives. If half of the next
1009
+ // half life has passed, approximate an additional three-quarter life by summing
1010
+ // the results of taking both the *next two* half lives instead. This helps
1011
+ // smooth out the decay.
1012
+ if half_decays % 2 == 0 {
1013
+ offset_msat. checked_shr ( decays as u32 ) . unwrap_or ( 0 )
1014
+ } else {
1015
+ offset_msat
1016
+ . checked_shr ( ( decays + 1 ) as u32 )
1017
+ . map ( |decayed_offset_msat| decayed_offset_msat
1018
+ + offset_msat. checked_shr ( ( decays + 2 ) as u32 ) . unwrap_or ( 0 ) )
1019
+ . unwrap_or ( 0 )
1020
+ }
1021
+ }
1022
+ } ,
1023
+ }
1004
1024
}
1005
1025
}
1006
1026
@@ -2192,6 +2212,7 @@ mod tests {
2192
2212
scorer. payment_path_failed ( & payment_path_for_amount ( 768 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
2193
2213
scorer. payment_path_failed ( & payment_path_for_amount ( 128 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
2194
2214
2215
+ // Initial penalties
2195
2216
let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
2196
2217
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
2197
2218
let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
@@ -2201,7 +2222,8 @@ mod tests {
2201
2222
let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
2202
2223
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , u64 :: max_value( ) ) ;
2203
2224
2204
- SinceEpoch :: advance ( Duration :: from_secs ( 9 ) ) ;
2225
+ // No decay
2226
+ SinceEpoch :: advance ( Duration :: from_secs ( 4 ) ) ;
2205
2227
let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
2206
2228
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
2207
2229
let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
@@ -2211,7 +2233,19 @@ mod tests {
2211
2233
let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
2212
2234
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , u64 :: max_value( ) ) ;
2213
2235
2236
+ // Half decay (i.e., three-quarter life)
2214
2237
SinceEpoch :: advance ( Duration :: from_secs ( 1 ) ) ;
2238
+ let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
2239
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 18 ) ;
2240
+ let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
2241
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 103 ) ;
2242
+ let usage = ChannelUsage { amount_msat : 768 , ..usage } ;
2243
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 957 ) ;
2244
+ let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
2245
+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , u64 :: max_value( ) ) ;
2246
+
2247
+ // One decay (i.e., half life)
2248
+ SinceEpoch :: advance ( Duration :: from_secs ( 5 ) ) ;
2215
2249
let usage = ChannelUsage { amount_msat : 64 , ..usage } ;
2216
2250
assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
2217
2251
let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
0 commit comments