-
Couldn't load subscription status.
- Fork 421
Scorer serialization #1146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scorer serialization #1146
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1146 +/- ##
==========================================
- Coverage 90.22% 90.15% -0.07%
==========================================
Files 70 70
Lines 36361 36224 -137
==========================================
- Hits 32805 32658 -147
- Misses 3556 3566 +10
Continue to review full report at Codecov.
|
|
I'm not really sure if I buy that we care about |
bc516ff to
fc1323b
Compare
I made I'm gonna need the parameterization to test this, though, so there really isn't much extra needed to support no-std. I think it's mostly just one line of code in |
lightning/src/routing/scorer.rs
Outdated
| fn elapsed(&self) -> Duration; | ||
| } | ||
|
|
||
| impl<C: Clock + Sub<Duration, Output = C>> ScorerUsingClock<C> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just make the Sub requirement a direct parent of Clock?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Done!
fc1323b to
d465e4a
Compare
lightning/src/routing/scorer.rs
Outdated
| #[inline] | ||
| fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> { | ||
| self.undecayed_penalty_msat.write(w)?; | ||
| (duration_since_epoch() - self.last_failed.elapsed()).write(w) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I wonder if we should document somewhere that an LDK node serialized by std should never be deserialized by no-std and vice versa. Seems like some weird negative durations could occur here in those situations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated docs about mixing types being undefined. Also, moved duration_since_epoch into Time trait to make the association clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shaping up! Just these last few comments I think.
lightning/src/routing/scorer.rs
Outdated
| channel_failures: HashMap<u64, (u64, Instant)>, | ||
| #[cfg(feature = "no-std")] | ||
| channel_failures: HashMap<u64, u64>, | ||
| channel_failures: HashMap<u64, ChannelFailure<C>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we'll need a mutex/multi-threaded access to channel_failures if we're gonna be persisting it in the background
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to change anything since the scorer will be accessed using a LockableScore (e.g., a Mutex).
lightning/src/routing/scorer.rs
Outdated
| channel_failures: HashMap<u64, (u64, Instant)>, | ||
| #[cfg(feature = "no-std")] | ||
| channel_failures: HashMap<u64, u64>, | ||
| channel_failures: HashMap<u64, ChannelFailure<C>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems self.channel_failures may grow over time, may be nice to have a TODO for pruning it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good observation. I suppose a scorer should be notified of changes to the NetworkGraph to allow for this. Added a TODO.
lightning/src/routing/scorer.rs
Outdated
| /// A clock that is always present, now or after time has passed. | ||
| pub struct AlwaysPresent; | ||
|
|
||
| impl Clock for AlwaysPresent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO Instant would be clearer than Clock for this API, though not sure what ScorerUsingClock would be renamed to 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed Clock to Time which is more consistent with how SystemTime and Instant are described. Also, renamed AlwaysPresent to Eternity (i.e., where time has no meaning) since "present" in the former could have been read with a different meaning (e.g., a field that is always present).
This also will work better with testing where time will be read from a Clock, which the tests will advance as needed.
5713d28 to
73ffbcf
Compare
73ffbcf to
960854c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
I think a new warning may have been introduced ("unused variable: network_graph")
lightning/src/routing/scorer.rs
Outdated
| fn now() -> Self; | ||
|
|
||
| /// Returns the amount of time elapsed since the clock was created. | ||
| /// Returns the amount of time elapsed since created. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: prefer slightly more explicit "since this Time instance was created"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used the less verbose self.
| /// # Note | ||
| /// | ||
| /// When time is an [`Eternity`], as is default when enabling feature `no-std`, it will never | ||
| /// elapse. Therefore, this penalty will never decay. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: s/this penalty/failure_penalty_msat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That wouldn't be accurate since failure_penalty_msat is added each time the channel fails to relay a payment, i.e., "this penalty" is referring to "any accumulated channel failure penalties". I've re-worded a bit and included a link to failure_penalty_msat.
960854c to
6f9c9e5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you squash?
Move channel failure penalty logic into a ChannelFailure abstraction. This encapsulates the logic for accumulating penalties and decaying them over time. It also is responsible for the no-std behavior. This cleans up Scorer and will make it easier to serialize it.
Scorer uses time to determine how much to penalize a channel after a failure occurs. Parameterizing it by time cleans up the code such that no-std support is in a single AlwaysPresent struct, which implements the Time trait. Time is implemented for std::time::Instant when std is available. This parameterization also allows for deterministic testing since a clock could be devised to advance forward as needed.
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.
6f9c9e5 to
ae210e7
Compare
|
Squashed without diff, will land after CI: |
Scorershould be serialized to retain penalty data between restarts. Implement (de)serialization forScorerby serializing last failure times as duration since the UNIX epoch. For no-std, the zero-Durationis used.Parameterize
Scorerwith a newClocktrait to simplify no-std support and allow for tesing without using a real clock.Based on #1144.
TODO: Test
Scorernow that it can be parameterized by a fakeClock.