46
46
//!
47
47
//! # Note
48
48
//!
49
- //! If persisting [`Scorer`], it must be restored using the same [`Time`] parameterization. Using a
50
- //! different type results in undefined behavior. Specifically, persisting when built with feature
51
- //! `no-std` and restoring without it, or vice versa, uses different types and thus is undefined.
49
+ //! Persisting when built with feature `no-std` and restoring without it, or vice versa, uses
50
+ //! different types and thus is undefined.
52
51
//!
53
52
//! [`find_route`]: crate::routing::router::find_route
54
53
@@ -59,14 +58,27 @@ use util::ser::{Readable, Writeable, Writer};
59
58
60
59
use prelude:: * ;
61
60
use core:: cell:: { RefCell , RefMut } ;
62
- use core:: ops:: { DerefMut , Sub } ;
61
+ use core:: ops:: DerefMut ;
63
62
use core:: time:: Duration ;
64
- use io:: { self , Read } ; use sync:: { Mutex , MutexGuard } ;
63
+ use io:: { self , Read } ;
64
+ use sync:: { Mutex , MutexGuard } ;
65
65
66
+ /// We define Score ever-so-slightly differently based on whether we are being built for C bindings
67
+ /// or not. For users, `LockableScore` must somehow be writeable to disk. For Rust users, this is
68
+ /// no problem - you move a `Score` that implements `Writeable` into a `Mutex`, lock it, and now
69
+ /// you have the original, concrete, `Score` type, which presumably implements `Writeable`.
70
+ ///
71
+ /// For C users, once you've moved the `Score` into a `LockableScore` all you have after locking it
72
+ /// is an opaque trait object with an opaque pointer with no type info. Users could take the unsafe
73
+ /// approach of blindly casting that opaque pointer to a concrete type and calling `Writeable` from
74
+ /// there, but other languages downstream of the C bindings (e.g. Java) can't even do that.
75
+ /// Instead, we really want `Score` and `LockableScore` to implement `Writeable` directly, which we
76
+ /// do here by defining `Score` differently for `cfg(c_bindings)`.
77
+ macro_rules! define_score { ( $( $supertrait: path) * ) => {
66
78
/// An interface used to score payment channels for path finding.
67
79
///
68
80
/// Scoring is in terms of fees willing to be paid in order to avoid routing through a channel.
69
- pub trait Score {
81
+ pub trait Score $ ( : $supertrait ) * {
70
82
/// Returns the fee in msats willing to be paid to avoid routing `send_amt_msat` through the
71
83
/// given channel in the direction from `source` to `target`.
72
84
///
@@ -85,6 +97,22 @@ pub trait Score {
85
97
fn payment_path_failed( & mut self , path: & [ & RouteHop ] , short_channel_id: u64 ) ;
86
98
}
87
99
100
+ impl <S : Score , T : DerefMut <Target =S > $( + $supertrait) * > Score for T {
101
+ fn channel_penalty_msat( & self , short_channel_id: u64 , send_amt_msat: u64 , channel_capacity_msat: Option <u64 >, source: & NodeId , target: & NodeId ) -> u64 {
102
+ self . deref( ) . channel_penalty_msat( short_channel_id, send_amt_msat, channel_capacity_msat, source, target)
103
+ }
104
+
105
+ fn payment_path_failed( & mut self , path: & [ & RouteHop ] , short_channel_id: u64 ) {
106
+ self . deref_mut( ) . payment_path_failed( path, short_channel_id)
107
+ }
108
+ }
109
+ } }
110
+
111
+ #[ cfg( c_bindings) ]
112
+ define_score ! ( Writeable ) ;
113
+ #[ cfg( not( c_bindings) ) ]
114
+ define_score ! ( ) ;
115
+
88
116
/// A scorer that is accessed under a lock.
89
117
///
90
118
/// Needed so that calls to [`Score::channel_penalty_msat`] in [`find_route`] can be made while
@@ -101,6 +129,7 @@ pub trait LockableScore<'a> {
101
129
fn lock ( & ' a self ) -> Self :: Locked ;
102
130
}
103
131
132
+ /// (C-not exported)
104
133
impl < ' a , T : ' a + Score > LockableScore < ' a > for Mutex < T > {
105
134
type Locked = MutexGuard < ' a , T > ;
106
135
@@ -117,13 +146,34 @@ impl<'a, T: 'a + Score> LockableScore<'a> for RefCell<T> {
117
146
}
118
147
}
119
148
120
- impl < S : Score , T : DerefMut < Target =S > > Score for T {
121
- fn channel_penalty_msat ( & self , short_channel_id : u64 , send_amt_msat : u64 , channel_capacity_msat : Option < u64 > , source : & NodeId , target : & NodeId ) -> u64 {
122
- self . deref ( ) . channel_penalty_msat ( short_channel_id, send_amt_msat, channel_capacity_msat, source, target)
149
+ #[ cfg( c_bindings) ]
150
+ /// A concrete implementation of [`LockableScore`] which supports multi-threading.
151
+ pub struct MultiThreadedLockableScore < S : Score > {
152
+ score : Mutex < S > ,
153
+ }
154
+ #[ cfg( c_bindings) ]
155
+ /// (C-not exported)
156
+ impl < ' a , T : Score + ' a > LockableScore < ' a > for MultiThreadedLockableScore < T > {
157
+ type Locked = MutexGuard < ' a , T > ;
158
+
159
+ fn lock ( & ' a self ) -> MutexGuard < ' a , T > {
160
+ Mutex :: lock ( & self . score ) . unwrap ( )
161
+ }
162
+ }
163
+
164
+ #[ cfg( c_bindings) ]
165
+ /// (C-not exported)
166
+ impl < ' a , T : Writeable > Writeable for RefMut < ' a , T > {
167
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
168
+ T :: write ( & * * self , writer)
123
169
}
170
+ }
124
171
125
- fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
126
- self . deref_mut ( ) . payment_path_failed ( path, short_channel_id)
172
+ #[ cfg( c_bindings) ]
173
+ /// (C-not exported)
174
+ impl < ' a , S : Writeable > Writeable for MutexGuard < ' a , S > {
175
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
176
+ S :: write ( & * * self , writer)
127
177
}
128
178
}
129
179
@@ -135,23 +185,33 @@ impl<S: Score, T: DerefMut<Target=S>> Score for T {
135
185
/// See [module-level documentation] for usage.
136
186
///
137
187
/// [module-level documentation]: crate::routing::scoring
138
- pub type Scorer = ScorerUsingTime :: < DefaultTime > ;
139
-
140
- /// Time used by [`Scorer`].
141
188
#[ cfg( not( feature = "no-std" ) ) ]
142
- pub type DefaultTime = std:: time:: Instant ;
143
-
144
- /// Time used by [`Scorer`].
189
+ pub type Scorer = ScorerUsingTime :: < std:: time:: Instant > ;
190
+ /// [`Score`] implementation that provides reasonable default behavior.
191
+ ///
192
+ /// Used to apply a fixed penalty to each channel, thus avoiding long paths when shorter paths with
193
+ /// slightly higher fees are available. Will further penalize channels that fail to relay payments.
194
+ ///
195
+ /// See [module-level documentation] for usage.
196
+ ///
197
+ /// [module-level documentation]: crate::routing::scoring
145
198
#[ cfg( feature = "no-std" ) ]
146
- pub type DefaultTime = Eternity ;
199
+ pub type Scorer = ScorerUsingTime :: < time :: Eternity > ;
147
200
148
- /// [`Score`] implementation parameterized by [`Time`].
201
+ // Note that ideally we'd hide ScorerUsingTime from public view by sealing it as well, but rustdoc
202
+ // doesn't handle this well - instead exposing a `Scorer` which has no trait implementation(s) or
203
+ // methods at all.
204
+
205
+ /// [`Score`] implementation.
149
206
///
150
207
/// See [`Scorer`] for details.
151
208
///
152
209
/// # Note
153
210
///
154
- /// Mixing [`Time`] types between serialization and deserialization results in undefined behavior.
211
+ /// Mixing the `no-std` feature between serialization and deserialization results in undefined
212
+ /// behavior.
213
+ ///
214
+ /// (C-not exported) generally all users should use the [`Scorer`] type alias.
155
215
pub struct ScorerUsingTime < T : Time > {
156
216
params : ScoringParameters ,
157
217
// TODO: Remove entries of closed channels.
@@ -197,8 +257,8 @@ pub struct ScoringParameters {
197
257
///
198
258
/// # Note
199
259
///
200
- /// When time is an [`Eternity`], as is default when enabling feature `no-std`, it will never
201
- /// elapse. Therefore, this penalty will never decay.
260
+ /// When built with the `no-std` feature, time will never elapse. Therefore, this penalty will
261
+ /// never decay.
202
262
///
203
263
/// [`failure_penalty_msat`]: Self::failure_penalty_msat
204
264
pub failure_penalty_half_life : Duration ,
@@ -223,20 +283,6 @@ struct ChannelFailure<T: Time> {
223
283
last_failed : T ,
224
284
}
225
285
226
- /// A measurement of time.
227
- pub trait Time : Sub < Duration , Output = Self > where Self : Sized {
228
- /// Returns an instance corresponding to the current moment.
229
- fn now ( ) -> Self ;
230
-
231
- /// Returns the amount of time elapsed since `self` was created.
232
- fn elapsed ( & self ) -> Duration ;
233
-
234
- /// Returns the amount of time passed since the beginning of [`Time`].
235
- ///
236
- /// Used during (de-)serialization.
237
- fn duration_since_epoch ( ) -> Duration ;
238
- }
239
-
240
286
impl < T : Time > ScorerUsingTime < T > {
241
287
/// Creates a new scorer using the given scoring parameters.
242
288
pub fn new ( params : ScoringParameters ) -> Self {
@@ -333,48 +379,6 @@ impl<T: Time> Score for ScorerUsingTime<T> {
333
379
}
334
380
}
335
381
336
- #[ cfg( not( feature = "no-std" ) ) ]
337
- impl Time for std:: time:: Instant {
338
- fn now ( ) -> Self {
339
- std:: time:: Instant :: now ( )
340
- }
341
-
342
- fn duration_since_epoch ( ) -> Duration {
343
- use std:: time:: SystemTime ;
344
- SystemTime :: now ( ) . duration_since ( SystemTime :: UNIX_EPOCH ) . unwrap ( )
345
- }
346
-
347
- fn elapsed ( & self ) -> Duration {
348
- std:: time:: Instant :: elapsed ( self )
349
- }
350
- }
351
-
352
- /// A state in which time has no meaning.
353
- #[ derive( Debug , PartialEq , Eq ) ]
354
- pub struct Eternity ;
355
-
356
- impl Time for Eternity {
357
- fn now ( ) -> Self {
358
- Self
359
- }
360
-
361
- fn duration_since_epoch ( ) -> Duration {
362
- Duration :: from_secs ( 0 )
363
- }
364
-
365
- fn elapsed ( & self ) -> Duration {
366
- Duration :: from_secs ( 0 )
367
- }
368
- }
369
-
370
- impl Sub < Duration > for Eternity {
371
- type Output = Self ;
372
-
373
- fn sub ( self , _other : Duration ) -> Self {
374
- self
375
- }
376
- }
377
-
378
382
impl < T : Time > Writeable for ScorerUsingTime < T > {
379
383
#[ inline]
380
384
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
@@ -425,9 +429,72 @@ impl<T: Time> Readable for ChannelFailure<T> {
425
429
}
426
430
}
427
431
432
+ pub ( crate ) mod time {
433
+ use core:: ops:: Sub ;
434
+ use core:: time:: Duration ;
435
+ /// A measurement of time.
436
+ pub trait Time : Sub < Duration , Output = Self > where Self : Sized {
437
+ /// Returns an instance corresponding to the current moment.
438
+ fn now ( ) -> Self ;
439
+
440
+ /// Returns the amount of time elapsed since `self` was created.
441
+ fn elapsed ( & self ) -> Duration ;
442
+
443
+ /// Returns the amount of time passed since the beginning of [`Time`].
444
+ ///
445
+ /// Used during (de-)serialization.
446
+ fn duration_since_epoch ( ) -> Duration ;
447
+ }
448
+
449
+ /// A state in which time has no meaning.
450
+ #[ derive( Debug , PartialEq , Eq ) ]
451
+ pub struct Eternity ;
452
+
453
+ #[ cfg( not( feature = "no-std" ) ) ]
454
+ impl Time for std:: time:: Instant {
455
+ fn now ( ) -> Self {
456
+ std:: time:: Instant :: now ( )
457
+ }
458
+
459
+ fn duration_since_epoch ( ) -> Duration {
460
+ use std:: time:: SystemTime ;
461
+ SystemTime :: now ( ) . duration_since ( SystemTime :: UNIX_EPOCH ) . unwrap ( )
462
+ }
463
+
464
+ fn elapsed ( & self ) -> Duration {
465
+ std:: time:: Instant :: elapsed ( self )
466
+ }
467
+ }
468
+
469
+ impl Time for Eternity {
470
+ fn now ( ) -> Self {
471
+ Self
472
+ }
473
+
474
+ fn duration_since_epoch ( ) -> Duration {
475
+ Duration :: from_secs ( 0 )
476
+ }
477
+
478
+ fn elapsed ( & self ) -> Duration {
479
+ Duration :: from_secs ( 0 )
480
+ }
481
+ }
482
+
483
+ impl Sub < Duration > for Eternity {
484
+ type Output = Self ;
485
+
486
+ fn sub ( self , _other : Duration ) -> Self {
487
+ self
488
+ }
489
+ }
490
+ }
491
+
492
+ pub ( crate ) use self :: time:: Time ;
493
+
428
494
#[ cfg( test) ]
429
495
mod tests {
430
- use super :: { Eternity , ScoringParameters , ScorerUsingTime , Time } ;
496
+ use super :: { ScoringParameters , ScorerUsingTime , Time } ;
497
+ use super :: time:: Eternity ;
431
498
432
499
use routing:: scoring:: Score ;
433
500
use routing:: network_graph:: NodeId ;
0 commit comments