Skip to content

Commit 754cb70

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 754cb70

File tree

1 file changed

+81
-33
lines changed

1 file changed

+81
-33
lines changed

lightning/src/routing/scoring.rs

Lines changed: 81 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,80 @@ 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+
// TODO: Call decay multiple times.
497+
let elapsed_time =
498+
duration_since_epoch.saturating_sub(liquidity.offset_history_last_updated);
499+
if elapsed_time > decay_params.historical_no_updates_half_life {
500+
let half_life = decay_params.historical_no_updates_half_life.as_secs_f64();
501+
if half_life != 0.0 {
502+
liquidity.liquidity_history.decay_buckets(elapsed_time.as_secs_f64() / half_life);
503+
liquidity.offset_history_last_updated = duration_since_epoch;
504+
}
505+
}
506+
liquidity.min_liquidity_offset_msat != 0 || liquidity.max_liquidity_offset_msat != 0 ||
507+
liquidity.liquidity_history.has_datapoints()
508+
});
509+
}
510+
511+
fn get(&self, short_channel_id: &u64) -> Option<&ChannelLiquidity> {
512+
self.0.get(short_channel_id)
513+
}
514+
515+
fn insert(&mut self, short_channel_id: u64, liquidity: ChannelLiquidity) -> Option<ChannelLiquidity> {
516+
self.0.insert(short_channel_id, liquidity)
517+
}
518+
519+
fn iter(&self) -> impl Iterator<Item = (&u64, &ChannelLiquidity)> {
520+
self.0.iter()
521+
}
522+
523+
fn entry(&mut self, short_channel_id: u64) -> Entry<u64, ChannelLiquidity, RandomState> {
524+
self.0.entry(short_channel_id)
525+
}
526+
527+
#[cfg(test)]
528+
fn get_mut(&mut self, short_channel_id: &u64) -> Option<&mut ChannelLiquidity> {
529+
self.0.get_mut(short_channel_id)
530+
}
531+
}
532+
533+
impl Readable for ChannelLiquidities {
534+
#[inline]
535+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
536+
let mut channel_liquidities = new_hash_map();
537+
read_tlv_fields!(r, {
538+
(0, channel_liquidities, required),
539+
});
540+
Ok(ChannelLiquidities(channel_liquidities))
541+
}
542+
}
543+
544+
impl Writeable for ChannelLiquidities {
545+
#[inline]
546+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
547+
write_tlv_fields!(w, {
548+
(0, self.0, required),
549+
});
550+
Ok(())
551+
}
478552
}
479553

480554
/// Parameters for configuring [`ProbabilisticScorer`].
@@ -804,7 +878,7 @@ impl ProbabilisticScoringDecayParameters {
804878
/// first node in the ordering of the channel's counterparties. Thus, swapping the two liquidity
805879
/// offset fields gives the opposite direction.
806880
#[repr(C)] // Force the fields in memory to be in the order we specify
807-
struct ChannelLiquidity {
881+
pub struct ChannelLiquidity {
808882
/// Lower channel liquidity bound in terms of an offset from zero.
809883
min_liquidity_offset_msat: u64,
810884

@@ -849,7 +923,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ProbabilisticScorer<G, L> whe
849923
decay_params,
850924
network_graph,
851925
logger,
852-
channel_liquidities: new_hash_map(),
926+
channel_liquidities: ChannelLiquidities::new(),
853927
}
854928
}
855929

@@ -1603,26 +1677,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreUpdate for Probabilistic
16031677
}
16041678

16051679
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-
});
1680+
self.channel_liquidities.time_passed(duration_since_epoch, self.decay_params);
16261681
}
16271682
}
16281683

@@ -2060,15 +2115,11 @@ mod bucketed_history {
20602115
}
20612116
}
20622117
}
2063-
use bucketed_history::{LegacyHistoricalBucketRangeTracker, HistoricalBucketRangeTracker, DirectedHistoricalLiquidityTracker, HistoricalLiquidityTracker};
20642118

20652119
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> Writeable for ProbabilisticScorer<G, L> where L::Target: Logger {
20662120
#[inline]
20672121
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(())
2122+
self.channel_liquidities.write(w)
20722123
}
20732124
}
20742125

@@ -2079,10 +2130,7 @@ ReadableArgs<(ProbabilisticScoringDecayParameters, G, L)> for ProbabilisticScore
20792130
r: &mut R, args: (ProbabilisticScoringDecayParameters, G, L)
20802131
) -> Result<Self, DecodeError> {
20812132
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-
});
2133+
let channel_liquidities = ChannelLiquidities::read(r)?;
20862134
Ok(Self {
20872135
decay_params,
20882136
network_graph,

0 commit comments

Comments
 (0)