@@ -997,10 +997,30 @@ impl<L: Deref<Target = u64>, BRT: Deref<Target = HistoricalBucketRangeTracker>,
997997 }
998998
999999 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+ }
10041024 }
10051025}
10061026
@@ -2192,6 +2212,7 @@ mod tests {
21922212 scorer. payment_path_failed ( & payment_path_for_amount ( 768 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 42 ) ;
21932213 scorer. payment_path_failed ( & payment_path_for_amount ( 128 ) . iter ( ) . collect :: < Vec < _ > > ( ) , 43 ) ;
21942214
2215+ // Initial penalties
21952216 let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
21962217 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
21972218 let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
@@ -2201,7 +2222,8 @@ mod tests {
22012222 let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
22022223 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , u64 :: max_value( ) ) ;
22032224
2204- SinceEpoch :: advance ( Duration :: from_secs ( 9 ) ) ;
2225+ // No decay
2226+ SinceEpoch :: advance ( Duration :: from_secs ( 4 ) ) ;
22052227 let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
22062228 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
22072229 let usage = ChannelUsage { amount_msat : 256 , ..usage } ;
@@ -2211,7 +2233,19 @@ mod tests {
22112233 let usage = ChannelUsage { amount_msat : 896 , ..usage } ;
22122234 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , u64 :: max_value( ) ) ;
22132235
2236+ // Half decay (i.e., three-quarter life)
22142237 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 ) ) ;
22152249 let usage = ChannelUsage { amount_msat : 64 , ..usage } ;
22162250 assert_eq ! ( scorer. channel_penalty_msat( 42 , & source, & target, usage) , 0 ) ;
22172251 let usage = ChannelUsage { amount_msat : 128 , ..usage } ;
0 commit comments