Skip to content

Commit 5564c76

Browse files
committed
refactor hashmap to channelliquidities struct
Wrap the liquidities hash map into a struct so that decay and serialization functionality can be attached. This allows external data to be serialized into this struct and decayed to make it comparable and mergeable.
1 parent b1fc7d8 commit 5564c76

File tree

1 file changed

+80
-33
lines changed

1 file changed

+80
-33
lines changed

lightning/src/routing/scoring.rs

Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,14 @@ use crate::routing::router::{Path, CandidateRouteHop, PublicHopCandidate};
5757
use crate::routing::log_approx;
5858
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
5959
use crate::util::logger::Logger;
60-
6160
use crate::prelude::*;
61+
use crate::prelude::hash_map::Entry;
6262
use core::{cmp, fmt};
6363
use core::ops::{Deref, DerefMut};
6464
use core::time::Duration;
6565
use crate::io::{self, Read};
6666
use crate::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
67+
use bucketed_history::{LegacyHistoricalBucketRangeTracker, HistoricalBucketRangeTracker, DirectedHistoricalLiquidityTracker, HistoricalLiquidityTracker};
6768
#[cfg(not(c_bindings))]
6869
use {
6970
core::cell::{RefCell, RefMut, Ref},
@@ -474,7 +475,79 @@ where L::Target: Logger {
474475
decay_params: ProbabilisticScoringDecayParameters,
475476
network_graph: G,
476477
logger: L,
477-
channel_liquidities: HashMap<u64, ChannelLiquidity>,
478+
channel_liquidities: ChannelLiquidities,
479+
}
480+
/// Container for live and historical liquidity bounds for each channel.
481+
pub struct ChannelLiquidities(HashMap<u64, ChannelLiquidity>);
482+
483+
impl ChannelLiquidities {
484+
fn new() -> Self {
485+
Self(new_hash_map())
486+
}
487+
488+
fn time_passed(&mut self, duration_since_epoch: Duration, decay_params: ProbabilisticScoringDecayParameters) {
489+
self.0.retain(|_scid, liquidity| {
490+
liquidity.min_liquidity_offset_msat =
491+
liquidity.decayed_offset(liquidity.min_liquidity_offset_msat, duration_since_epoch, decay_params);
492+
liquidity.max_liquidity_offset_msat =
493+
liquidity.decayed_offset(liquidity.max_liquidity_offset_msat, duration_since_epoch, decay_params);
494+
liquidity.last_updated = duration_since_epoch;
495+
496+
let elapsed_time =
497+
duration_since_epoch.saturating_sub(liquidity.offset_history_last_updated);
498+
if elapsed_time > decay_params.historical_no_updates_half_life {
499+
let half_life = decay_params.historical_no_updates_half_life.as_secs_f64();
500+
if half_life != 0.0 {
501+
liquidity.liquidity_history.decay_buckets(elapsed_time.as_secs_f64() / half_life);
502+
liquidity.offset_history_last_updated = duration_since_epoch;
503+
}
504+
}
505+
liquidity.min_liquidity_offset_msat != 0 || liquidity.max_liquidity_offset_msat != 0 ||
506+
liquidity.liquidity_history.has_datapoints()
507+
});
508+
}
509+
510+
fn get(&self, short_channel_id: &u64) -> Option<&ChannelLiquidity> {
511+
self.0.get(short_channel_id)
512+
}
513+
514+
fn insert(&mut self, short_channel_id: u64, liquidity: ChannelLiquidity) -> Option<ChannelLiquidity> {
515+
self.0.insert(short_channel_id, liquidity)
516+
}
517+
518+
fn iter(&self) -> impl Iterator<Item = (&u64, &ChannelLiquidity)> {
519+
self.0.iter()
520+
}
521+
522+
fn entry(&mut self, short_channel_id: u64) -> Entry<u64, ChannelLiquidity, RandomState> {
523+
self.0.entry(short_channel_id)
524+
}
525+
526+
#[cfg(test)]
527+
fn get_mut(&mut self, short_channel_id: &u64) -> Option<&mut ChannelLiquidity> {
528+
self.0.get_mut(short_channel_id)
529+
}
530+
}
531+
532+
impl Readable for ChannelLiquidities {
533+
#[inline]
534+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
535+
let mut channel_liquidities = new_hash_map();
536+
read_tlv_fields!(r, {
537+
(0, channel_liquidities, required),
538+
});
539+
Ok(ChannelLiquidities(channel_liquidities))
540+
}
541+
}
542+
543+
impl Writeable for ChannelLiquidities {
544+
#[inline]
545+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
546+
write_tlv_fields!(w, {
547+
(0, self.0, required),
548+
});
549+
Ok(())
550+
}
478551
}
479552

480553
/// Parameters for configuring [`ProbabilisticScorer`].
@@ -804,7 +877,7 @@ impl ProbabilisticScoringDecayParameters {
804877
/// first node in the ordering of the channel's counterparties. Thus, swapping the two liquidity
805878
/// offset fields gives the opposite direction.
806879
#[repr(C)] // Force the fields in memory to be in the order we specify
807-
struct ChannelLiquidity {
880+
pub struct ChannelLiquidity {
808881
/// Lower channel liquidity bound in terms of an offset from zero.
809882
min_liquidity_offset_msat: u64,
810883

@@ -849,7 +922,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
849922
decay_params,
850923
network_graph,
851924
logger,
852-
channel_liquidities: new_hash_map(),
925+
channel_liquidities: ChannelLiquidities::new(),
853926
}
854927
}
855928

@@ -1603,26 +1676,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreUpdate for Probabilistic
16031676
}
16041677

16051678
fn time_passed(&mut self, duration_since_epoch: Duration) {
1606-
let decay_params = self.decay_params;
1607-
self.channel_liquidities.retain(|_scid, liquidity| {
1608-
liquidity.min_liquidity_offset_msat =
1609-
liquidity.decayed_offset(liquidity.min_liquidity_offset_msat, duration_since_epoch, decay_params);
1610-
liquidity.max_liquidity_offset_msat =
1611-
liquidity.decayed_offset(liquidity.max_liquidity_offset_msat, duration_since_epoch, decay_params);
1612-
liquidity.last_updated = duration_since_epoch;
1613-
1614-
let elapsed_time =
1615-
duration_since_epoch.saturating_sub(liquidity.offset_history_last_updated);
1616-
if elapsed_time > decay_params.historical_no_updates_half_life {
1617-
let half_life = decay_params.historical_no_updates_half_life.as_secs_f64();
1618-
if half_life != 0.0 {
1619-
liquidity.liquidity_history.decay_buckets(elapsed_time.as_secs_f64() / half_life);
1620-
liquidity.offset_history_last_updated = duration_since_epoch;
1621-
}
1622-
}
1623-
liquidity.min_liquidity_offset_msat != 0 || liquidity.max_liquidity_offset_msat != 0 ||
1624-
liquidity.liquidity_history.has_datapoints()
1625-
});
1679+
self.channel_liquidities.time_passed(duration_since_epoch, self.decay_params);
16261680
}
16271681
}
16281682

@@ -2060,15 +2114,11 @@ mod bucketed_history {
20602114
}
20612115
}
20622116
}
2063-
use bucketed_history::{LegacyHistoricalBucketRangeTracker, HistoricalBucketRangeTracker, DirectedHistoricalLiquidityTracker, HistoricalLiquidityTracker};
20642117

20652118
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> Writeable for ProbabilisticScorer<G, L> where L::Target: Logger {
20662119
#[inline]
20672120
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
2068-
write_tlv_fields!(w, {
2069-
(0, self.channel_liquidities, required),
2070-
});
2071-
Ok(())
2121+
self.channel_liquidities.write(w)
20722122
}
20732123
}
20742124

@@ -2079,10 +2129,7 @@ ReadableArgs<(ProbabilisticScoringDecayParameters, G, L)> for ProbabilisticScore
20792129
r: &mut R, args: (ProbabilisticScoringDecayParameters, G, L)
20802130
) -> Result<Self, DecodeError> {
20812131
let (decay_params, network_graph, logger) = args;
2082-
let mut channel_liquidities = new_hash_map();
2083-
read_tlv_fields!(r, {
2084-
(0, channel_liquidities, required),
2085-
});
2132+
let channel_liquidities = ChannelLiquidities::read(r)?;
20862133
Ok(Self {
20872134
decay_params,
20882135
network_graph,

0 commit comments

Comments
 (0)