@@ -1151,10 +1151,30 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
11511151 }
11521152
11531153 fn decayed_offset_msat ( & self , offset_msat : u64 ) -> u64 {
1154- self . now . duration_since ( * self . last_updated ) . as_secs ( )
1155- . checked_div ( self . decay_params . liquidity_offset_half_life . as_secs ( ) )
1156- . and_then ( |decays| offset_msat. checked_shr ( decays as u32 ) )
1157- . unwrap_or ( 0 )
1154+ let elapsed_time = self . now . duration_since ( * self . last_updated ) . as_secs ( ) ;
1155+ let half_life = self . decay_params . liquidity_offset_half_life . as_secs ( ) ;
1156+
1157+ match elapsed_time. checked_div ( half_life) {
1158+ None => 0 ,
1159+ Some ( decays) => match elapsed_time. checked_div ( half_life / 2 ) {
1160+ None => 0 ,
1161+ Some ( half_decays) => {
1162+ // Decay the offset by the appropriate number of half lives. If half of the next
1163+ // half life has passed, approximate an additional three-quarter life by summing
1164+ // the results of taking both the *next two* half lives instead. This helps
1165+ // smooth out the decay.
1166+ if half_decays % 2 == 0 {
1167+ offset_msat. checked_shr ( decays as u32 ) . unwrap_or ( 0 )
1168+ } else {
1169+ offset_msat
1170+ . checked_shr ( ( decays + 1 ) as u32 )
1171+ . map ( |decayed_offset_msat| decayed_offset_msat
1172+ + offset_msat. checked_shr ( ( decays + 2 ) as u32 ) . unwrap_or ( 0 ) )
1173+ . unwrap_or ( 0 )
1174+ }
1175+ }
1176+ } ,
1177+ }
11581178 }
11591179}
11601180
@@ -2405,6 +2425,7 @@ mod tests {
24052425 scorer. payment_path_failed ( & payment_path_for_amount ( 768 ) , 42 ) ;
24062426 scorer. payment_path_failed ( & payment_path_for_amount ( 128 ) , 43 ) ;
24072427
2428+ // Initial penalties
24082429 let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
24092430 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 0 ) ;
24102431 let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
@@ -2414,7 +2435,8 @@ mod tests {
24142435 let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
24152436 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , u64 :: max_value( ) ) ;
24162437
2417- SinceEpoch :: advance ( Duration :: from_secs ( 9 ) ) ;
2438+ // No decay
2439+ SinceEpoch :: advance ( Duration :: from_secs ( 4 ) ) ;
24182440 let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
24192441 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 0 ) ;
24202442 let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
@@ -2424,7 +2446,19 @@ mod tests {
24242446 let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
24252447 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , u64 :: max_value( ) ) ;
24262448
2449+ // Half decay (i.e., three-quarter life)
24272450 SinceEpoch :: advance ( Duration :: from_secs ( 1 ) ) ;
2451+ let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
2452+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 18 ) ;
2453+ let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
2454+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 103 ) ;
2455+ let usage = ChannelUsage { amount_msat : 768 , ..usage } ;
2456+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 957 ) ;
2457+ let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
2458+ assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , u64 :: max_value( ) ) ;
2459+
2460+ // One decay (i.e., half life)
2461+ SinceEpoch :: advance ( Duration :: from_secs ( 5 ) ) ;
24282462 let usage = ChannelUsage { amount_msat : 64 , ..usage } ;
24292463 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage, & params) , 0 ) ;
24302464 let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
0 commit comments