Skip to content

Commit fc1323b

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 0375e62 commit fc1323b

File tree

2 files changed

+87
-6
lines changed

2 files changed

+87
-6
lines changed

lightning/src/routing/scorer.rs

+70-6
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 DefaultClock = AlwaysPresent;
7579
/// [`routing::Score`] implementation parameterized by a [`Clock`].
7680
///
7781
/// See [`Scorer`] for details.
78-
pub struct ScorerUsingClock<C: Clock> {
82+
pub struct ScorerUsingClock<C: Clock + Sub<Duration, Output = C>> {
7983
params: ScoringParameters,
8084
channel_failures: HashMap<u64, ChannelFailure<C>>,
8185
}
@@ -96,10 +100,16 @@ pub struct ScoringParameters {
96100
pub failure_penalty_half_life: Duration,
97101
}
98102

103+
impl_writeable_tlv_based!(ScoringParameters, {
104+
(0, base_penalty_msat, required),
105+
(2, failure_penalty_msat, required),
106+
(4, failure_penalty_half_life, required),
107+
});
108+
99109
/// Accounting for penalties from channel failures.
100110
///
101111
/// Penalties decay over time, though accumulated as more failures occur.
102-
struct ChannelFailure<C: Clock> {
112+
struct ChannelFailure<C: Clock + Sub<Duration, Output = C>> {
103113
/// Accumulated penalty in msats for the channel as of `last_failed`.
104114
undecayed_penalty_msat: u64,
105115

@@ -116,7 +126,7 @@ pub trait Clock {
116126
fn elapsed(&self) -> Duration;
117127
}
118128

119-
impl<C: Clock> ScorerUsingClock<C> {
129+
impl<C: Clock + Sub<Duration, Output = C>> ScorerUsingClock<C> {
120130
/// Creates a new scorer using the given scoring parameters.
121131
pub fn new(params: ScoringParameters) -> Self {
122132
Self {
@@ -136,7 +146,7 @@ impl<C: Clock> ScorerUsingClock<C> {
136146
}
137147
}
138148

139-
impl<C: Clock> ChannelFailure<C> {
149+
impl<C: Clock + Sub<Duration, Output = C>> ChannelFailure<C> {
140150
fn new(failure_penalty_msat: u64) -> Self {
141151
Self {
142152
undecayed_penalty_msat: failure_penalty_msat,
@@ -158,7 +168,7 @@ impl<C: Clock> ChannelFailure<C> {
158168
}
159169
}
160170

161-
impl<C: Clock> Default for ScorerUsingClock<C> {
171+
impl<C: Clock + Sub<Duration, Output = C>> Default for ScorerUsingClock<C> {
162172
fn default() -> Self {
163173
Self::new(ScoringParameters::default())
164174
}
@@ -174,7 +184,7 @@ impl Default for ScoringParameters {
174184
}
175185
}
176186

177-
impl<C: Clock> routing::Score for ScorerUsingClock<C> {
187+
impl<C: Clock + Sub<Duration, Output = C>> routing::Score for ScorerUsingClock<C> {
178188
fn channel_penalty_msat(
179189
&self, short_channel_id: u64, _source: &NodeId, _target: &NodeId
180190
) -> u64 {
@@ -218,3 +228,57 @@ impl Clock for AlwaysPresent {
218228
Duration::from_secs(0)
219229
}
220230
}
231+
232+
impl Sub<Duration> for AlwaysPresent {
233+
type Output = Self;
234+
235+
fn sub(self, _other: Duration) -> Self {
236+
self
237+
}
238+
}
239+
240+
impl<C: Clock + Sub<Duration, Output = C>> Writeable for ScorerUsingClock<C> {
241+
#[inline]
242+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
243+
self.params.write(w)?;
244+
self.channel_failures.write(w)
245+
}
246+
}
247+
248+
impl<C: Clock + Sub<Duration, Output = C>> Readable for ScorerUsingClock<C> {
249+
#[inline]
250+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
251+
Ok(Self {
252+
params: Readable::read(r)?,
253+
channel_failures: Readable::read(r)?,
254+
})
255+
}
256+
}
257+
258+
impl<C: Clock + Sub<Duration, Output = C>> Writeable for ChannelFailure<C> {
259+
#[inline]
260+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
261+
self.undecayed_penalty_msat.write(w)?;
262+
(duration_since_epoch() - self.last_failed.elapsed()).write(w)
263+
}
264+
}
265+
266+
impl<C: Clock + Sub<Duration, Output = C>> Readable for ChannelFailure<C> {
267+
#[inline]
268+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
269+
Ok(Self {
270+
undecayed_penalty_msat: Readable::read(r)?,
271+
last_failed: C::now() - (duration_since_epoch() - Readable::read(r)?),
272+
})
273+
}
274+
}
275+
276+
fn duration_since_epoch() -> Duration {
277+
#[cfg(not(feature = "no-std"))]
278+
{
279+
use std::time::SystemTime;
280+
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap()
281+
}
282+
#[cfg(feature = "no-std")]
283+
return Duration::from_secs(0);
284+
}

lightning/src/util/ser.rs

+17
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)