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