@@ -52,7 +52,6 @@ use routing::network_graph::NodeId;
52
52
use routing:: router:: RouteHop ;
53
53
54
54
use prelude:: * ;
55
- #[ cfg( not( feature = "no-std" ) ) ]
56
55
use core:: time:: Duration ;
57
56
#[ cfg( not( feature = "no-std" ) ) ]
58
57
use std:: time:: Instant ;
@@ -67,10 +66,7 @@ use std::time::Instant;
67
66
/// [module-level documentation]: crate::routing::scorer
68
67
pub struct Scorer {
69
68
params : ScoringParameters ,
70
- #[ cfg( not( feature = "no-std" ) ) ]
71
- channel_failures : HashMap < u64 , ( u64 , Instant ) > ,
72
- #[ cfg( feature = "no-std" ) ]
73
- channel_failures : HashMap < u64 , u64 > ,
69
+ channel_failures : HashMap < u64 , ChannelFailure > ,
74
70
}
75
71
76
72
/// Parameters for configuring [`Scorer`].
@@ -86,10 +82,21 @@ pub struct ScoringParameters {
86
82
pub failure_penalty_msat : u64 ,
87
83
88
84
/// The time needed before any accumulated channel failure penalties are cut in half.
89
- #[ cfg( not( feature = "no-std" ) ) ]
90
85
pub failure_penalty_half_life : Duration ,
91
86
}
92
87
88
+ /// Accounting for penalties from channel failures.
89
+ ///
90
+ /// Penalties decay over time, though accumulated as more failures occur.
91
+ struct ChannelFailure {
92
+ /// Accumulated penalty in msats for the channel as of `last_failed`.
93
+ undecayed_penalty_msat : u64 ,
94
+
95
+ /// Last time the channel failed. Used to decay `undecayed_penalty_msat`.
96
+ #[ cfg( not( feature = "no-std" ) ) ]
97
+ last_failed : Instant ,
98
+ }
99
+
93
100
impl Scorer {
94
101
/// Creates a new scorer using the given scoring parameters.
95
102
pub fn new ( params : ScoringParameters ) -> Self {
@@ -105,14 +112,41 @@ impl Scorer {
105
112
Self :: new ( ScoringParameters {
106
113
base_penalty_msat : penalty_msat,
107
114
failure_penalty_msat : 0 ,
108
- #[ cfg( not( feature = "no-std" ) ) ]
109
115
failure_penalty_half_life : Duration :: from_secs ( 0 ) ,
110
116
} )
111
117
}
118
+ }
119
+
120
+ impl ChannelFailure {
121
+ fn new ( failure_penalty_msat : u64 ) -> Self {
122
+ Self {
123
+ undecayed_penalty_msat : failure_penalty_msat,
124
+ #[ cfg( not( feature = "no-std" ) ) ]
125
+ last_failed : Instant :: now ( ) ,
126
+ }
127
+ }
112
128
113
- #[ cfg( not( feature = "no-std" ) ) ]
114
- fn decay_from ( & self , penalty_msat : u64 , last_failure : & Instant ) -> u64 {
115
- decay_from ( penalty_msat, last_failure, self . params . failure_penalty_half_life )
129
+ fn add_penalty ( & mut self , failure_penalty_msat : u64 , half_life : Duration ) {
130
+ self . undecayed_penalty_msat = self . decayed_penalty ( half_life) + failure_penalty_msat;
131
+ #[ cfg( not( feature = "no-std" ) ) ]
132
+ {
133
+ self . last_failed = Instant :: now ( ) ;
134
+ }
135
+ }
136
+
137
+ fn decayed_penalty ( & self , half_life : Duration ) -> u64 {
138
+ let decays = self . elapsed ( ) . as_secs ( ) . checked_div ( half_life. as_secs ( ) ) ;
139
+ match decays {
140
+ Some ( decays) => self . undecayed_penalty_msat >> decays,
141
+ None => 0 ,
142
+ }
143
+ }
144
+
145
+ fn elapsed ( & self ) -> Duration {
146
+ #[ cfg( not( feature = "no-std" ) ) ]
147
+ return self . last_failed . elapsed ( ) ;
148
+ #[ cfg( feature = "no-std" ) ]
149
+ return Duration :: from_secs ( 0 ) ;
116
150
}
117
151
}
118
152
@@ -127,7 +161,6 @@ impl Default for ScoringParameters {
127
161
Self {
128
162
base_penalty_msat : 500 ,
129
163
failure_penalty_msat : 1024 * 1000 ,
130
- #[ cfg( not( feature = "no-std" ) ) ]
131
164
failure_penalty_half_life : Duration :: from_secs ( 3600 ) ,
132
165
}
133
166
}
@@ -137,45 +170,19 @@ impl routing::Score for Scorer {
137
170
fn channel_penalty_msat (
138
171
& self , short_channel_id : u64 , _source : & NodeId , _target : & NodeId
139
172
) -> u64 {
140
- #[ cfg( not( feature = "no-std" ) ) ]
141
- let failure_penalty_msat = match self . channel_failures . get ( & short_channel_id) {
142
- Some ( ( penalty_msat, last_failure) ) => self . decay_from ( * penalty_msat, last_failure) ,
143
- None => 0 ,
144
- } ;
145
- #[ cfg( feature = "no-std" ) ]
146
- let failure_penalty_msat =
147
- self . channel_failures . get ( & short_channel_id) . copied ( ) . unwrap_or ( 0 ) ;
173
+ let failure_penalty_msat = self . channel_failures
174
+ . get ( & short_channel_id)
175
+ . map_or ( 0 , |failure| failure. decayed_penalty ( self . params . failure_penalty_half_life ) ) ;
148
176
149
177
self . params . base_penalty_msat + failure_penalty_msat
150
178
}
151
179
152
180
fn payment_path_failed ( & mut self , _path : & Vec < RouteHop > , short_channel_id : u64 ) {
153
181
let failure_penalty_msat = self . params . failure_penalty_msat ;
154
- #[ cfg( not( feature = "no-std" ) ) ]
155
- {
156
- let half_life = self . params . failure_penalty_half_life ;
157
- self . channel_failures
158
- . entry ( short_channel_id)
159
- . and_modify ( |( penalty_msat, last_failure) | {
160
- let decayed_penalty = decay_from ( * penalty_msat, last_failure, half_life) ;
161
- * penalty_msat = decayed_penalty + failure_penalty_msat;
162
- * last_failure = Instant :: now ( ) ;
163
- } )
164
- . or_insert_with ( || ( failure_penalty_msat, Instant :: now ( ) ) ) ;
165
- }
166
- #[ cfg( feature = "no-std" ) ]
182
+ let half_life = self . params . failure_penalty_half_life ;
167
183
self . channel_failures
168
184
. entry ( short_channel_id)
169
- . and_modify ( |penalty_msat| * penalty_msat += failure_penalty_msat)
170
- . or_insert ( failure_penalty_msat) ;
171
- }
172
- }
173
-
174
- #[ cfg( not( feature = "no-std" ) ) ]
175
- fn decay_from ( penalty_msat : u64 , last_failure : & Instant , half_life : Duration ) -> u64 {
176
- let decays = last_failure. elapsed ( ) . as_secs ( ) . checked_div ( half_life. as_secs ( ) ) ;
177
- match decays {
178
- Some ( decays) => penalty_msat >> decays,
179
- None => 0 ,
185
+ . and_modify ( |failure| failure. add_penalty ( failure_penalty_msat, half_life) )
186
+ . or_insert_with ( || ChannelFailure :: new ( failure_penalty_msat) ) ;
180
187
}
181
188
}
0 commit comments