From 72bc65e16bf6e38224a01318f1ad833341fc359d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 24 Mar 2022 05:52:17 +0000 Subject: [PATCH] Pass `EffectiveCapacity` through to scorer instead of a `u64` There is little reason to take the `EffectiveCapacity`, which has a bunch of information about the type of channel, and distill it down to a `u64` when scoring channels. Instead, we here pass the full information we know, in the form of the original `EffectiveCapacity`. This does create more branching in the main router loop, which appears to have a very slight (1-2%) performance loss, but that may well be within noise. Much more importantly, this resolves a panic in our log approximation where we can accidentally call `log(0)` when the channel's effective capacity is `u64::max_value()`. --- lightning-invoice/src/payment.rs | 8 +- lightning/src/routing/network_graph.rs | 56 ++++- lightning/src/routing/router.rs | 21 +- lightning/src/routing/scoring.rs | 313 +++++++++++++------------ 4 files changed, 225 insertions(+), 173 deletions(-) diff --git a/lightning-invoice/src/payment.rs b/lightning-invoice/src/payment.rs index 82c07199f..955e2dc6a 100644 --- a/lightning-invoice/src/payment.rs +++ b/lightning-invoice/src/payment.rs @@ -39,7 +39,7 @@ //! # use lightning::ln::channelmanager::{ChannelDetails, PaymentId, PaymentSendFailure}; //! # use lightning::ln::msgs::LightningError; //! # use lightning::routing::scoring::Score; -//! # use lightning::routing::network_graph::NodeId; +//! # use lightning::routing::network_graph::{EffectiveCapacity, NodeId}; //! # use lightning::routing::router::{Route, RouteHop, RouteParameters}; //! # use lightning::util::events::{Event, EventHandler, EventsProvider}; //! # use lightning::util::logger::{Logger, Record}; @@ -90,7 +90,7 @@ //! # } //! # impl Score for FakeScorer { //! # fn channel_penalty_msat( -//! # &self, _short_channel_id: u64, _send_amt: u64, _chan_amt: u64, _source: &NodeId, _target: &NodeId +//! # &self, _short_channel_id: u64, _send_amt: u64, _cap: EffectiveCapacity, _source: &NodeId, _target: &NodeId //! # ) -> u64 { 0 } //! # fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {} //! # fn payment_path_successful(&mut self, _path: &[&RouteHop]) {} @@ -532,7 +532,7 @@ mod tests { use lightning::ln::features::{ChannelFeatures, NodeFeatures, InitFeatures}; use lightning::ln::functional_test_utils::*; use lightning::ln::msgs::{ChannelMessageHandler, ErrorAction, LightningError}; - use lightning::routing::network_graph::NodeId; + use lightning::routing::network_graph::{EffectiveCapacity, NodeId}; use lightning::routing::router::{PaymentParameters, Route, RouteHop}; use lightning::util::test_utils::TestLogger; use lightning::util::errors::APIError; @@ -1327,7 +1327,7 @@ mod tests { impl Score for TestScorer { fn channel_penalty_msat( - &self, _short_channel_id: u64, _send_amt: u64, _chan_amt: u64, _source: &NodeId, _target: &NodeId + &self, _short_channel_id: u64, _send_amt: u64, _capacity: EffectiveCapacity, _source: &NodeId, _target: &NodeId ) -> u64 { 0 } fn payment_path_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) { diff --git a/lightning/src/routing/network_graph.rs b/lightning/src/routing/network_graph.rs index 012357df3..2f1dee919 100644 --- a/lightning/src/routing/network_graph.rs +++ b/lightning/src/routing/network_graph.rs @@ -758,7 +758,7 @@ impl<'a> DirectedChannelInfo<'a> { }) .or_else(|| capacity_msat.map(|capacity_msat| EffectiveCapacity::Total { capacity_msat })) - .unwrap_or(EffectiveCapacity::Unknown) + .unwrap_or(EffectiveCapacity::Unknown { previously_used_msat: 0 }) } /// Returns `Some` if [`ChannelUpdateInfo`] is available in the direction. @@ -807,7 +807,8 @@ impl<'a> fmt::Debug for DirectedChannelInfoWithUpdate<'a> { /// The effective capacity of a channel for routing purposes. /// /// While this may be smaller than the actual channel capacity, amounts greater than -/// [`Self::as_msat`] should not be routed through the channel. +/// [`Self::as_msat_with_default`] should not be routed through the channel. +#[derive(Copy, Clone, PartialEq)] pub enum EffectiveCapacity { /// The available liquidity in the channel known from being a channel counterparty, and thus a /// direct hop. @@ -831,7 +832,11 @@ pub enum EffectiveCapacity { Infinite, /// A capacity that is unknown possibly because either the chain state is unavailable to know /// the total capacity or the `htlc_maximum_msat` was not advertised on the gossip network. - Unknown, + Unknown { + /// An amount which should be considered "already used". Used during routing to keep track + /// of how much we're already considering routing through this channel. + previously_used_msat: u64, + }, } /// The presumed channel capacity denominated in millisatoshi for [`EffectiveCapacity::Unknown`] to @@ -839,14 +844,53 @@ pub enum EffectiveCapacity { pub const UNKNOWN_CHANNEL_CAPACITY_MSAT: u64 = 250_000 * 1000; impl EffectiveCapacity { - /// Returns the effective capacity denominated in millisatoshi. - pub fn as_msat(&self) -> u64 { + #[inline] + pub(crate) fn as_msat_without_bounds(&self) -> u64 { match self { EffectiveCapacity::ExactLiquidity { liquidity_msat } => *liquidity_msat, EffectiveCapacity::MaximumHTLC { amount_msat } => *amount_msat, EffectiveCapacity::Total { capacity_msat } => *capacity_msat, EffectiveCapacity::Infinite => u64::max_value(), - EffectiveCapacity::Unknown => UNKNOWN_CHANNEL_CAPACITY_MSAT, + EffectiveCapacity::Unknown { previously_used_msat } => UNKNOWN_CHANNEL_CAPACITY_MSAT.saturating_sub(*previously_used_msat), + } + } + + /// Returns the effective capacity denominated in millisatoshi. + /// + /// Returns [`UNKNOWN_CHANNEL_CAPACITY_MSAT`] minus the `previously_used_msat` for + /// [`EffectiveCapacity::Unknown`]. + #[inline] + pub fn as_msat_with_default(&self) -> Option { + match self { + EffectiveCapacity::ExactLiquidity { liquidity_msat } => Some(*liquidity_msat), + EffectiveCapacity::MaximumHTLC { amount_msat } => Some(*amount_msat), + EffectiveCapacity::Total { capacity_msat } => Some(*capacity_msat), + EffectiveCapacity::Infinite => None, + EffectiveCapacity::Unknown { previously_used_msat } => Some(UNKNOWN_CHANNEL_CAPACITY_MSAT.saturating_sub(*previously_used_msat)), + } + } + + /// Returns a new [`EffectiveCapacity`] which is reduced by the given number of millisatoshis + #[inline] + pub fn checked_sub(&self, msats: u64) -> Option { + match self { + Self::ExactLiquidity { liquidity_msat } => match liquidity_msat.checked_sub(msats) { + Some(liquidity_msat) => Some(Self::ExactLiquidity { liquidity_msat }), + None => None, + }, + Self::MaximumHTLC { amount_msat } => match amount_msat.checked_sub(msats) { + Some(amount_msat) => Some(Self::MaximumHTLC { amount_msat }), + None => None, + }, + Self::Total { capacity_msat } => match capacity_msat.checked_sub(msats) { + Some(capacity_msat) => Some(Self::Total { capacity_msat }), + None => None, + }, + Self::Infinite => Some(Self::Infinite), + Self::Unknown { previously_used_msat } => match previously_used_msat.checked_add(msats) { + Some(previously_used_msat) => Some(Self::Unknown { previously_used_msat }), + None => None, + }, } } } diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 677a57162..fbdefb984 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -854,7 +854,7 @@ where L::Target: Logger { let short_channel_id = $candidate.short_channel_id(); let available_liquidity_msat = bookkept_channels_liquidity_available_msat .entry(short_channel_id) - .or_insert_with(|| $candidate.effective_capacity().as_msat()); + .or_insert_with(|| $candidate.effective_capacity()); // It is tricky to substract $next_hops_fee_msat from available liquidity here. // It may be misleading because we might later choose to reduce the value transferred @@ -863,7 +863,7 @@ where L::Target: Logger { // fees caused by one expensive channel, but then this channel could have been used // if the amount being transferred over this path is lower. // We do this for now, but this is a subject for removal. - if let Some(available_value_contribution_msat) = available_liquidity_msat.checked_sub($next_hops_fee_msat) { + if let Some(available_value_contribution) = available_liquidity_msat.checked_sub($next_hops_fee_msat) { // Routing Fragmentation Mitigation heuristic: // @@ -886,6 +886,7 @@ where L::Target: Logger { final_value_msat }; // Verify the liquidity offered by this channel complies to the minimal contribution. + let available_value_contribution_msat = available_value_contribution.as_msat_without_bounds(); let contributes_sufficient_value = available_value_contribution_msat >= minimal_value_contribution_msat; // Do not consider candidates that exceed the maximum total cltv expiry limit. @@ -1220,9 +1221,8 @@ where L::Target: Logger { short_channel_id: hop.short_channel_id, }) .unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop }); - let capacity_msat = candidate.effective_capacity().as_msat(); aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat - .checked_add(scorer.channel_penalty_msat(hop.short_channel_id, final_value_msat, capacity_msat, &source, &target)) + .checked_add(scorer.channel_penalty_msat(hop.short_channel_id, path_value_msat, candidate.effective_capacity(), &source, &target)) .unwrap_or_else(|| u64::max_value()); aggregate_next_hops_cltv_delta = aggregate_next_hops_cltv_delta @@ -1382,12 +1382,13 @@ where L::Target: Logger { let mut spent_on_hop_msat = value_contribution_msat; let next_hops_fee_msat = payment_hop.next_hops_fee_msat; spent_on_hop_msat += next_hops_fee_msat; - if spent_on_hop_msat == *channel_liquidity_available_msat { + if spent_on_hop_msat == channel_liquidity_available_msat.as_msat_without_bounds() { // If this path used all of this channel's available liquidity, we know // this path will not be selected again in the next loop iteration. prevented_redundant_path_selection = true; } - *channel_liquidity_available_msat -= spent_on_hop_msat; + *channel_liquidity_available_msat = channel_liquidity_available_msat + .checked_sub(spent_on_hop_msat).unwrap_or(EffectiveCapacity::ExactLiquidity { liquidity_msat: 0 }); } if !prevented_redundant_path_selection { // If we weren't capped by hitting a liquidity limit on a channel in the path, @@ -1396,7 +1397,7 @@ where L::Target: Logger { let victim_scid = payment_path.hops[(payment_path.hops.len() - 1) / 2].0.candidate.short_channel_id(); log_trace!(logger, "Disabling channel {} for future path building iterations to avoid duplicates.", victim_scid); let victim_liquidity = bookkept_channels_liquidity_available_msat.get_mut(&victim_scid).unwrap(); - *victim_liquidity = 0; + *victim_liquidity = EffectiveCapacity::ExactLiquidity { liquidity_msat: 0 }; } // Track the total amount all our collected paths allow to send so that we: @@ -1664,7 +1665,7 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, #[cfg(test)] mod tests { - use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId}; + use routing::network_graph::{EffectiveCapacity, NetworkGraph, NetGraphMsgHandler, NodeId}; use routing::router::{get_route, add_random_cltv_offset, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA}; use routing::scoring::Score; use chain::transaction::OutPoint; @@ -5001,7 +5002,7 @@ mod tests { fn write(&self, _w: &mut W) -> Result<(), ::io::Error> { unimplemented!() } } impl Score for BadChannelScorer { - fn channel_penalty_msat(&self, short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, _target: &NodeId) -> u64 { + fn channel_penalty_msat(&self, short_channel_id: u64, _send_amt: u64, _capacity: EffectiveCapacity, _source: &NodeId, _target: &NodeId) -> u64 { if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 } } @@ -5019,7 +5020,7 @@ mod tests { } impl Score for BadNodeScorer { - fn channel_penalty_msat(&self, _short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, target: &NodeId) -> u64 { + fn channel_penalty_msat(&self, _short_channel_id: u64, _send_amt: u64, _capacity: EffectiveCapacity, _source: &NodeId, target: &NodeId) -> u64 { if *target == self.node_id { u64::max_value() } else { 0 } } diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index d8b1740c1..1d1c27a84 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -55,7 +55,7 @@ //! [`find_route`]: crate::routing::router::find_route use ln::msgs::DecodeError; -use routing::network_graph::{NetworkGraph, NodeId}; +use routing::network_graph::{EffectiveCapacity, NetworkGraph, NodeId}; use routing::router::RouteHop; use util::ser::{Readable, ReadableArgs, Writeable, Writer}; @@ -86,11 +86,11 @@ pub trait Score $(: $supertrait)* { /// given channel in the direction from `source` to `target`. /// /// The channel's capacity (less any other MPP parts that are also being considered for use in - /// the same payment) is given by `capacity_msat`. It may be determined from various sources + /// the same payment) is given by `capacity`. It may be determined from various sources /// such as a chain data, network gossip, or invoice hints. For invoice hints, a capacity near /// [`u64::max_value`] is given to indicate sufficient capacity for the invoice's full amount. /// Thus, implementations should be overflow-safe. - fn channel_penalty_msat(&self, short_channel_id: u64, send_amt_msat: u64, capacity_msat: u64, source: &NodeId, target: &NodeId) -> u64; + fn channel_penalty_msat(&self, short_channel_id: u64, send_amt_msat: u64, capacity: EffectiveCapacity, source: &NodeId, target: &NodeId) -> u64; /// Handles updating channel penalties after failing to route through a channel. fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64); @@ -100,8 +100,8 @@ pub trait Score $(: $supertrait)* { } impl $(+ $supertrait)*> Score for T { - fn channel_penalty_msat(&self, short_channel_id: u64, send_amt_msat: u64, capacity_msat: u64, source: &NodeId, target: &NodeId) -> u64 { - self.deref().channel_penalty_msat(short_channel_id, send_amt_msat, capacity_msat, source, target) + fn channel_penalty_msat(&self, short_channel_id: u64, send_amt_msat: u64, capacity: EffectiveCapacity, source: &NodeId, target: &NodeId) -> u64 { + self.deref().channel_penalty_msat(short_channel_id, send_amt_msat, capacity, source, target) } fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) { @@ -209,7 +209,7 @@ impl FixedPenaltyScorer { } impl Score for FixedPenaltyScorer { - fn channel_penalty_msat(&self, _: u64, _: u64, _: u64, _: &NodeId, _: &NodeId) -> u64 { + fn channel_penalty_msat(&self, _: u64, _: u64, _: EffectiveCapacity, _: &NodeId, _: &NodeId) -> u64 { self.penalty_msat } @@ -382,19 +382,21 @@ impl Default for ScoringParameters { impl Score for ScorerUsingTime { fn channel_penalty_msat( - &self, short_channel_id: u64, send_amt_msat: u64, capacity_msat: u64, _source: &NodeId, _target: &NodeId + &self, short_channel_id: u64, send_amt_msat: u64, capacity: EffectiveCapacity, _source: &NodeId, _target: &NodeId ) -> u64 { let failure_penalty_msat = self.channel_failures .get(&short_channel_id) .map_or(0, |value| value.decayed_penalty_msat(self.params.failure_penalty_half_life)); let mut penalty_msat = self.params.base_penalty_msat + failure_penalty_msat; - let send_1024ths = send_amt_msat.checked_mul(1024).unwrap_or(u64::max_value()) / capacity_msat; - if send_1024ths > self.params.overuse_penalty_start_1024th as u64 { - penalty_msat = penalty_msat.checked_add( - (send_1024ths - self.params.overuse_penalty_start_1024th as u64) - .checked_mul(self.params.overuse_penalty_msat_per_1024th).unwrap_or(u64::max_value())) - .unwrap_or(u64::max_value()); + if let Some(capacity_msat) = capacity.as_msat_with_default() { + let send_1024ths = send_amt_msat.checked_mul(1024).unwrap_or(u64::max_value()) / capacity_msat; + if send_1024ths > self.params.overuse_penalty_start_1024th as u64 { + penalty_msat = penalty_msat.checked_add( + (send_1024ths - self.params.overuse_penalty_start_1024th as u64) + .checked_mul(self.params.overuse_penalty_msat_per_1024th).unwrap_or(u64::max_value())) + .unwrap_or(u64::max_value()); + } } penalty_msat @@ -734,17 +736,20 @@ impl, T: Time, U: DerefMut> DirectedChanne } impl, T: Time> Score for ProbabilisticScorerUsingTime { + #[inline] fn channel_penalty_msat( - &self, short_channel_id: u64, amount_msat: u64, capacity_msat: u64, source: &NodeId, - target: &NodeId + &self, short_channel_id: u64, amount_msat: u64, capacity: EffectiveCapacity, + source: &NodeId, target: &NodeId ) -> u64 { let liquidity_penalty_multiplier_msat = self.params.liquidity_penalty_multiplier_msat; let liquidity_offset_half_life = self.params.liquidity_offset_half_life; - self.channel_liquidities - .get(&short_channel_id) - .unwrap_or(&ChannelLiquidity::new()) - .as_directed(source, target, capacity_msat, liquidity_offset_half_life) - .penalty_msat(amount_msat, liquidity_penalty_multiplier_msat) + if let Some(capacity_msat) = capacity.as_msat_with_default() { + self.channel_liquidities + .get(&short_channel_id) + .unwrap_or(&ChannelLiquidity::new()) + .as_directed(source, target, capacity_msat, liquidity_offset_half_life) + .penalty_msat(amount_msat, liquidity_penalty_multiplier_msat) + } else { 0 } } fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) { @@ -759,21 +764,22 @@ impl, T: Time> Score for ProbabilisticScorerUsin // Only score announced channels. if let Some((channel, source)) = channel_directed_from_source { - let capacity_msat = channel.effective_capacity().as_msat(); - if hop.short_channel_id == short_channel_id { + if let Some(capacity_msat) = channel.effective_capacity().as_msat_with_default() { + if hop.short_channel_id == short_channel_id { + self.channel_liquidities + .entry(hop.short_channel_id) + .or_insert_with(ChannelLiquidity::new) + .as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life) + .failed_at_channel(amount_msat); + break; + } + self.channel_liquidities .entry(hop.short_channel_id) .or_insert_with(ChannelLiquidity::new) .as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life) - .failed_at_channel(amount_msat); - break; + .failed_downstream(amount_msat); } - - self.channel_liquidities - .entry(hop.short_channel_id) - .or_insert_with(ChannelLiquidity::new) - .as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life) - .failed_downstream(amount_msat); } } } @@ -790,12 +796,13 @@ impl, T: Time> Score for ProbabilisticScorerUsin // Only score announced channels. if let Some((channel, source)) = channel_directed_from_source { - let capacity_msat = channel.effective_capacity().as_msat(); - self.channel_liquidities - .entry(hop.short_channel_id) - .or_insert_with(ChannelLiquidity::new) - .as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life) - .successful(amount_msat); + if let Some(capacity_msat) = channel.effective_capacity().as_msat_with_default() { + self.channel_liquidities + .entry(hop.short_channel_id) + .or_insert_with(ChannelLiquidity::new) + .as_directed_mut(source, &target, capacity_msat, liquidity_offset_half_life) + .successful(amount_msat); + } } } } @@ -1059,7 +1066,7 @@ mod tests { use ln::features::{ChannelFeatures, NodeFeatures}; use ln::msgs::{ChannelAnnouncement, ChannelUpdate, OptionalField, UnsignedChannelAnnouncement, UnsignedChannelUpdate}; use routing::scoring::Score; - use routing::network_graph::{NetworkGraph, NodeId}; + use routing::network_graph::{EffectiveCapacity, NetworkGraph, NodeId}; use routing::router::RouteHop; use util::ser::{Readable, ReadableArgs, Writeable}; @@ -1182,10 +1189,10 @@ mod tests { }); let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); SinceEpoch::advance(Duration::from_secs(1)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); } #[test] @@ -1199,16 +1206,16 @@ mod tests { }); let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_064); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_064); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_128); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_128); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_192); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_192); } #[test] @@ -1222,25 +1229,25 @@ mod tests { }); let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); SinceEpoch::advance(Duration::from_secs(9)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); SinceEpoch::advance(Duration::from_secs(1)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_256); SinceEpoch::advance(Duration::from_secs(10 * 8)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_001); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_001); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); } #[test] @@ -1254,18 +1261,18 @@ mod tests { }); let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); // An unchecked right shift 64 bits or more in ChannelFailure::decayed_penalty_msat would // cause an overflow. SinceEpoch::advance(Duration::from_secs(10 * 64)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); } #[test] @@ -1279,19 +1286,19 @@ mod tests { }); let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_256); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_768); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_768); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_384); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_384); } #[test] @@ -1305,13 +1312,13 @@ mod tests { }); let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_000); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_000); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_256); let hop = RouteHop { pubkey: PublicKey::from_slice(target.as_slice()).unwrap(), @@ -1322,10 +1329,10 @@ mod tests { cltv_expiry_delta: 18, }; scorer.payment_path_successful(&[&hop]); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_128); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_128); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_064); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_064); } #[test] @@ -1341,20 +1348,20 @@ mod tests { let target = target_node_id(); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_256); scorer.payment_path_failed(&[], 43); - assert_eq!(scorer.channel_penalty_msat(43, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(43, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); let deserialized_scorer = ::read(&mut io::Cursor::new(&serialized_scorer)).unwrap(); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256); - assert_eq!(deserialized_scorer.channel_penalty_msat(43, 1, 1, &source, &target), 1_512); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_256); + assert_eq!(deserialized_scorer.channel_penalty_msat(43, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); } #[test] @@ -1370,7 +1377,7 @@ mod tests { let target = target_node_id(); scorer.payment_path_failed(&[], 42); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_512); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_512); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); @@ -1378,10 +1385,10 @@ mod tests { SinceEpoch::advance(Duration::from_secs(10)); let deserialized_scorer = ::read(&mut io::Cursor::new(&serialized_scorer)).unwrap(); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_256); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_256); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, 1, &source, &target), 1_128); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1 }, &source, &target), 1_128); } #[test] @@ -1396,11 +1403,11 @@ mod tests { let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1_000, 1_024_000, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 256_999, 1_024_000, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 257_000, 1_024_000, &source, &target), 100); - assert_eq!(scorer.channel_penalty_msat(42, 258_000, 1_024_000, &source, &target), 200); - assert_eq!(scorer.channel_penalty_msat(42, 512_000, 1_024_000, &source, &target), 256 * 100); + assert_eq!(scorer.channel_penalty_msat(42, 1_000, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 256_999, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 257_000, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 100); + assert_eq!(scorer.channel_penalty_msat(42, 258_000, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 200); + assert_eq!(scorer.channel_penalty_msat(42, 512_000, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 256 * 100); } // `ProbabilisticScorer` tests @@ -1728,18 +1735,18 @@ mod tests { let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024_000, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 10_240, 1_024_000, &source, &target), 14); - assert_eq!(scorer.channel_penalty_msat(42, 102_400, 1_024_000, &source, &target), 43); - assert_eq!(scorer.channel_penalty_msat(42, 1_024_000, 1_024_000, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 1_024, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 10_240, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 14); + assert_eq!(scorer.channel_penalty_msat(42, 102_400, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 43); + assert_eq!(scorer.channel_penalty_msat(42, 1_024_000, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024_000 }, &source, &target), 2_000); - assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 58); - assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 125); - assert_eq!(scorer.channel_penalty_msat(42, 374, 1_024, &source, &target), 204); - assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 301); - assert_eq!(scorer.channel_penalty_msat(42, 640, 1_024, &source, &target), 426); - assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 602); - assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 903); + assert_eq!(scorer.channel_penalty_msat(42, 128, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 58); + assert_eq!(scorer.channel_penalty_msat(42, 256, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 125); + assert_eq!(scorer.channel_penalty_msat(42, 374, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 204); + assert_eq!(scorer.channel_penalty_msat(42, 512, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 301); + assert_eq!(scorer.channel_penalty_msat(42, 640, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 426); + assert_eq!(scorer.channel_penalty_msat(42, 768, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 602); + assert_eq!(scorer.channel_penalty_msat(42, 896, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 903); } #[test] @@ -1757,10 +1764,10 @@ mod tests { let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 39, 100, &source, &target), 0); - assert_ne!(scorer.channel_penalty_msat(42, 50, 100, &source, &target), 0); - assert_ne!(scorer.channel_penalty_msat(42, 50, 100, &source, &target), 2_000); - assert_eq!(scorer.channel_penalty_msat(42, 61, 100, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 39, EffectiveCapacity::ExactLiquidity { liquidity_msat: 100 }, &source, &target), 0); + assert_ne!(scorer.channel_penalty_msat(42, 50, EffectiveCapacity::ExactLiquidity { liquidity_msat: 100 }, &source, &target), 0); + assert_ne!(scorer.channel_penalty_msat(42, 50, EffectiveCapacity::ExactLiquidity { liquidity_msat: 100 }, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 61, EffectiveCapacity::ExactLiquidity { liquidity_msat: 100 }, &source, &target), 2_000); } #[test] @@ -1775,13 +1782,13 @@ mod tests { let failed_path = payment_path_for_amount(500); let successful_path = payment_path_for_amount(200); - assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 300); + assert_eq!(scorer.channel_penalty_msat(41, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &sender, &source), 300); scorer.payment_path_failed(&failed_path.iter().collect::>(), 41); - assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 300); + assert_eq!(scorer.channel_penalty_msat(41, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &sender, &source), 300); scorer.payment_path_successful(&successful_path.iter().collect::>()); - assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 300); + assert_eq!(scorer.channel_penalty_msat(41, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &sender, &source), 300); } #[test] @@ -1795,15 +1802,15 @@ mod tests { let target = target_node_id(); let path = payment_path_for_amount(500); - assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 128); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300); - assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 601); + assert_eq!(scorer.channel_penalty_msat(42, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 128); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); + assert_eq!(scorer.channel_penalty_msat(42, 750, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 601); scorer.payment_path_failed(&path.iter().collect::>(), 43); - assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 300); + assert_eq!(scorer.channel_penalty_msat(42, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 750, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); } #[test] @@ -1817,15 +1824,15 @@ mod tests { let target = target_node_id(); let path = payment_path_for_amount(500); - assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 128); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300); - assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 601); + assert_eq!(scorer.channel_penalty_msat(42, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 128); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); + assert_eq!(scorer.channel_penalty_msat(42, 750, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 601); scorer.payment_path_failed(&path.iter().collect::>(), 42); - assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 300); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 2_000); - assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 750, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 2_000); } #[test] @@ -1841,15 +1848,15 @@ mod tests { let recipient = recipient_node_id(); let path = payment_path_for_amount(500); - assert_eq!(scorer.channel_penalty_msat(41, 250, 1_000, &sender, &source), 128); - assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 128); - assert_eq!(scorer.channel_penalty_msat(43, 250, 1_000, &target, &recipient), 128); + assert_eq!(scorer.channel_penalty_msat(41, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &sender, &source), 128); + assert_eq!(scorer.channel_penalty_msat(42, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 128); + assert_eq!(scorer.channel_penalty_msat(43, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &target, &recipient), 128); scorer.payment_path_successful(&path.iter().collect::>()); - assert_eq!(scorer.channel_penalty_msat(41, 250, 1_000, &sender, &source), 128); - assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 300); - assert_eq!(scorer.channel_penalty_msat(43, 250, 1_000, &target, &recipient), 300); + assert_eq!(scorer.channel_penalty_msat(41, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &sender, &source), 128); + assert_eq!(scorer.channel_penalty_msat(42, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); + assert_eq!(scorer.channel_penalty_msat(43, 250, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &target, &recipient), 300); } #[test] @@ -1863,44 +1870,44 @@ mod tests { let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 0, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 1_024, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); scorer.payment_path_failed(&payment_path_for_amount(768).iter().collect::>(), 42); scorer.payment_path_failed(&payment_path_for_amount(128).iter().collect::>(), 43); - assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 97); - assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_409); - assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 128, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 256, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 97); + assert_eq!(scorer.channel_penalty_msat(42, 768, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 1_409); + assert_eq!(scorer.channel_penalty_msat(42, 896, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); SinceEpoch::advance(Duration::from_secs(9)); - assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 97); - assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_409); - assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 128, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 256, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 97); + assert_eq!(scorer.channel_penalty_msat(42, 768, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 1_409); + assert_eq!(scorer.channel_penalty_msat(42, 896, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); SinceEpoch::advance(Duration::from_secs(1)); - assert_eq!(scorer.channel_penalty_msat(42, 64, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 34); - assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 1_773); - assert_eq!(scorer.channel_penalty_msat(42, 960, 1_024, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 64, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 128, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 34); + assert_eq!(scorer.channel_penalty_msat(42, 896, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 1_773); + assert_eq!(scorer.channel_penalty_msat(42, 960, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); // Fully decay liquidity lower bound. SinceEpoch::advance(Duration::from_secs(10 * 7)); - assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 1, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 1_023, 1_024, &source, &target), 2_000); - assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 0, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 1, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 1_023, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 1_024, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); // Fully decay liquidity upper bound. SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 0, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 1_024, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0); - assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 0, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 0); + assert_eq!(scorer.channel_penalty_msat(42, 1_024, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 2_000); } #[test] @@ -1913,18 +1920,18 @@ mod tests { let mut scorer = ProbabilisticScorer::new(params, &network_graph); let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 125); + assert_eq!(scorer.channel_penalty_msat(42, 256, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 125); scorer.payment_path_failed(&payment_path_for_amount(512).iter().collect::>(), 42); - assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 274); + assert_eq!(scorer.channel_penalty_msat(42, 256, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 274); // An unchecked right shift 64 bits or more in DirectedChannelLiquidity::decayed_offset_msat // would cause an overflow. SinceEpoch::advance(Duration::from_secs(10 * 64)); - assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 125); + assert_eq!(scorer.channel_penalty_msat(42, 256, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 125); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 125); + assert_eq!(scorer.channel_penalty_msat(42, 256, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 125); } #[test] @@ -1938,30 +1945,30 @@ mod tests { let source = source_node_id(); let target = target_node_id(); - assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 301); + assert_eq!(scorer.channel_penalty_msat(42, 512, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 301); // More knowledge gives higher confidence (256, 768), meaning a lower penalty. scorer.payment_path_failed(&payment_path_for_amount(768).iter().collect::>(), 42); scorer.payment_path_failed(&payment_path_for_amount(256).iter().collect::>(), 43); - assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 274); + assert_eq!(scorer.channel_penalty_msat(42, 512, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 274); // Decaying knowledge gives less confidence (128, 896), meaning a higher penalty. SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 301); + assert_eq!(scorer.channel_penalty_msat(42, 512, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 301); // Reducing the upper bound gives more confidence (128, 832) that the payment amount (512) // is closer to the upper bound, meaning a higher penalty. scorer.payment_path_successful(&payment_path_for_amount(64).iter().collect::>()); - assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 342); + assert_eq!(scorer.channel_penalty_msat(42, 512, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 342); // Increasing the lower bound gives more confidence (256, 832) that the payment amount (512) // is closer to the lower bound, meaning a lower penalty. scorer.payment_path_failed(&payment_path_for_amount(256).iter().collect::>(), 43); - assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 255); + assert_eq!(scorer.channel_penalty_msat(42, 512, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 255); // Further decaying affects the lower bound more than the upper bound (128, 928). SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 284); + assert_eq!(scorer.channel_penalty_msat(42, 512, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_024 }, &source, &target), 284); } #[test] @@ -1976,13 +1983,13 @@ mod tests { let target = target_node_id(); scorer.payment_path_failed(&payment_path_for_amount(500).iter().collect::>(), 42); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 2_000); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 472); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 472); scorer.payment_path_failed(&payment_path_for_amount(250).iter().collect::>(), 43); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); @@ -1990,7 +1997,7 @@ mod tests { let mut serialized_scorer = io::Cursor::new(&serialized_scorer); let deserialized_scorer = ::read(&mut serialized_scorer, (params, &network_graph)).unwrap(); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); } #[test] @@ -2005,7 +2012,7 @@ mod tests { let target = target_node_id(); scorer.payment_path_failed(&payment_path_for_amount(500).iter().collect::>(), 42); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 2_000); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); @@ -2015,12 +2022,12 @@ mod tests { let mut serialized_scorer = io::Cursor::new(&serialized_scorer); let deserialized_scorer = ::read(&mut serialized_scorer, (params, &network_graph)).unwrap(); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 472); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 472); scorer.payment_path_failed(&payment_path_for_amount(250).iter().collect::>(), 43); - assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300); + assert_eq!(scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 300); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 371); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, &source, &target), 371); } } -- 2.39.5