Skip to content

Commit 9ef23fe

Browse files
committed
Implement (de)serialization for Scorer
Scorer should be serialized to retain penalty data between restarts. Implement (de)serialization for Scorer by serializing last failure times as duration since the UNIX epoch. For no-std, the zero-Duration is used.
1 parent 506f178 commit 9ef23fe

File tree

2 files changed

+87
-6
lines changed

2 files changed

+87
-6
lines changed

lightning/src/routing/scorer.rs

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@
4848
4949
use routing;
5050

51+
use ln::msgs::DecodeError;
5152
use routing::network_graph::NodeId;
5253
use routing::router::RouteHop;
54+
use util::ser::{Readable, Writeable, Writer};
5355

5456
use prelude::*;
57+
use core::ops::Sub;
5558
use core::time::Duration;
59+
use io::{self, Read};
5660

5761
/// [`routing::Score`] implementation that provides reasonable default behavior.
5862
///
@@ -75,7 +79,7 @@ pub type DefaultTime = Eternity;
7579
/// [`routing::Score`] implementation parameterized by [`Time`].
7680
///
7781
/// See [`Scorer`] for details.
78-
pub struct ScorerUsingTime<T: Time> {
82+
pub struct ScorerUsingTime<T: Time + Sub<Duration, Output = T>> {
7983
params: ScoringParameters,
8084
// TODO: Remove entries of closed channels.
8185
channel_failures: HashMap<u64, ChannelFailure<T>>,
@@ -103,10 +107,16 @@ pub struct ScoringParameters {
103107
pub failure_penalty_half_life: Duration,
104108
}
105109

110+
impl_writeable_tlv_based!(ScoringParameters, {
111+
(0, base_penalty_msat, required),
112+
(2, failure_penalty_msat, required),
113+
(4, failure_penalty_half_life, required),
114+
});
115+
106116
/// Accounting for penalties from channel failures.
107117
///
108118
/// Penalties decay over time, though accumulate as more failures occur.
109-
struct ChannelFailure<T: Time> {
119+
struct ChannelFailure<T: Time + Sub<Duration, Output = T>> {
110120
/// Accumulated penalty in msats for the channel as of `last_failed`.
111121
undecayed_penalty_msat: u64,
112122

@@ -123,7 +133,7 @@ pub trait Time {
123133
fn elapsed(&self) -> Duration;
124134
}
125135

126-
impl<T: Time> ScorerUsingTime<T> {
136+
impl<T: Time + Sub<Duration, Output = T>> ScorerUsingTime<T> {
127137
/// Creates a new scorer using the given scoring parameters.
128138
pub fn new(params: ScoringParameters) -> Self {
129139
Self {
@@ -143,7 +153,7 @@ impl<T: Time> ScorerUsingTime<T> {
143153
}
144154
}
145155

146-
impl<T: Time> ChannelFailure<T> {
156+
impl<T: Time + Sub<Duration, Output = T>> ChannelFailure<T> {
147157
fn new(failure_penalty_msat: u64) -> Self {
148158
Self {
149159
undecayed_penalty_msat: failure_penalty_msat,
@@ -165,7 +175,7 @@ impl<T: Time> ChannelFailure<T> {
165175
}
166176
}
167177

168-
impl<T: Time> Default for ScorerUsingTime<T> {
178+
impl<T: Time + Sub<Duration, Output = T>> Default for ScorerUsingTime<T> {
169179
fn default() -> Self {
170180
Self::new(ScoringParameters::default())
171181
}
@@ -181,7 +191,7 @@ impl Default for ScoringParameters {
181191
}
182192
}
183193

184-
impl<T: Time> routing::Score for ScorerUsingTime<T> {
194+
impl<T: Time + Sub<Duration, Output = T>> routing::Score for ScorerUsingTime<T> {
185195
fn channel_penalty_msat(
186196
&self, short_channel_id: u64, _source: &NodeId, _target: &NodeId
187197
) -> u64 {
@@ -225,3 +235,57 @@ impl Time for Eternity {
225235
Duration::from_secs(0)
226236
}
227237
}
238+
239+
impl Sub<Duration> for Eternity {
240+
type Output = Self;
241+
242+
fn sub(self, _other: Duration) -> Self {
243+
self
244+
}
245+
}
246+
247+
impl<T: Time + Sub<Duration, Output = T>> Writeable for ScorerUsingTime<T> {
248+
#[inline]
249+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
250+
self.params.write(w)?;
251+
self.channel_failures.write(w)
252+
}
253+
}
254+
255+
impl<T: Time + Sub<Duration, Output = T>> Readable for ScorerUsingTime<T> {
256+
#[inline]
257+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
258+
Ok(Self {
259+
params: Readable::read(r)?,
260+
channel_failures: Readable::read(r)?,
261+
})
262+
}
263+
}
264+
265+
impl<T: Time + Sub<Duration, Output = T>> Writeable for ChannelFailure<T> {
266+
#[inline]
267+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
268+
self.undecayed_penalty_msat.write(w)?;
269+
(duration_since_epoch() - self.last_failed.elapsed()).write(w)
270+
}
271+
}
272+
273+
impl<T: Time + Sub<Duration, Output = T>> Readable for ChannelFailure<T> {
274+
#[inline]
275+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
276+
Ok(Self {
277+
undecayed_penalty_msat: Readable::read(r)?,
278+
last_failed: T::now() - (duration_since_epoch() - Readable::read(r)?),
279+
})
280+
}
281+
}
282+
283+
fn duration_since_epoch() -> Duration {
284+
#[cfg(not(feature = "no-std"))]
285+
{
286+
use std::time::SystemTime;
287+
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap()
288+
}
289+
#[cfg(feature = "no-std")]
290+
return Duration::from_secs(0);
291+
}

lightning/src/util/ser.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use bitcoin::consensus::Encodable;
2727
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
2828
use bitcoin::hash_types::{Txid, BlockHash};
2929
use core::marker::Sized;
30+
use core::time::Duration;
3031
use ln::msgs::DecodeError;
3132
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
3233

@@ -911,3 +912,19 @@ impl Readable for String {
911912
Ok(ret)
912913
}
913914
}
915+
916+
impl Writeable for Duration {
917+
#[inline]
918+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
919+
self.as_secs().write(w)?;
920+
self.subsec_nanos().write(w)
921+
}
922+
}
923+
impl Readable for Duration {
924+
#[inline]
925+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
926+
let secs = Readable::read(r)?;
927+
let nanos = Readable::read(r)?;
928+
Ok(Duration::new(secs, nanos))
929+
}
930+
}

0 commit comments

Comments
 (0)