diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 1ed6a2a8345..2508ac4acbb 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -856,7 +856,7 @@ mod tests { use lightning::ln::functional_test_utils::*; use lightning::ln::msgs::{ChannelMessageHandler, Init}; use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler}; - use lightning::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync}; + use lightning::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync, RoutingFees}; use lightning::routing::router::{DefaultRouter, Path, RouteHop}; use lightning::routing::scoring::{ChannelUsage, Score}; use lightning::util::config::UserConfig; @@ -1036,7 +1036,7 @@ mod tests { impl Score for TestScorer { type ScoreParams = (); fn channel_penalty_msat( - &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage, _score_params: &Self::ScoreParams, _routing_fees: &RoutingFees ) -> u64 { unimplemented!(); } fn payment_path_failed(&mut self, actual_path: &Path, actual_short_channel_id: u64) { diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 04fc9927bb7..96627576a1c 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -135,7 +135,7 @@ impl<'a, S: Score, SP: Sized> Writeable for ScorerAccountingFo impl<'a, S: Score, SP: Sized> Score for ScorerAccountingForInFlightHtlcs<'a, S, SP> { type ScoreParams = S::ScoreParams; - fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams, routing_fees: &RoutingFees) -> u64 { if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( source, target, short_channel_id ) { @@ -144,9 +144,9 @@ impl<'a, S: Score, SP: Sized> Score for ScorerAccountingForInF ..usage }; - self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params) + self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params, routing_fees) } else { - self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params) + self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params, routing_fees) } } @@ -1662,7 +1662,7 @@ where L::Target: Logger { // Returns whether this channel caused an update to `targets`. ( $candidate: expr, $src_node_id: expr, $dest_node_id: expr, $next_hops_fee_msat: expr, $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr, - $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => { { + $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr, $next_hops_path_length: expr, $routing_fees: expr) => { { // We "return" whether we updated the path at the end, and how much we can route via // this channel, via this: let mut did_add_update_path_to_src_node = None; @@ -1822,7 +1822,7 @@ where L::Target: Logger { }; let channel_penalty_msat = scid_opt.map_or(0, |scid| scorer.channel_penalty_msat(scid, &$src_node_id, &$dest_node_id, - channel_usage, score_params)); + channel_usage, score_params, $routing_fees)); let path_penalty_msat = $next_hops_path_penalty_msat .saturating_add(channel_penalty_msat); let new_graph_node = RouteGraphNode { @@ -1918,7 +1918,7 @@ where L::Target: Logger { macro_rules! add_entries_to_cheapest_to_target_node { ( $node: expr, $node_id: expr, $fee_to_target_msat: expr, $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr, $next_hops_path_penalty_msat: expr, - $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => { + $next_hops_cltv_delta: expr, $next_hops_path_length: expr, $routing_fees: expr ) => { let skip_node = if let Some(elem) = dist.get_mut(&$node_id) { let was_processed = elem.was_processed; elem.was_processed = true; @@ -1938,7 +1938,7 @@ where L::Target: Logger { add_entry!(candidate, our_node_id, $node_id, $fee_to_target_msat, $next_hops_value_contribution, $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat, - $next_hops_cltv_delta, $next_hops_path_length); + $next_hops_cltv_delta, $next_hops_path_length, $routing_fees); } } @@ -1964,7 +1964,7 @@ where L::Target: Logger { $next_hops_value_contribution, $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat, - $next_hops_cltv_delta, $next_hops_path_length); + $next_hops_cltv_delta, $next_hops_path_length, $routing_fees); } } } @@ -1990,8 +1990,8 @@ where L::Target: Logger { payee_node_id_opt.map(|payee| first_hop_targets.get(&payee).map(|first_channels| { for details in first_channels { let candidate = CandidateRouteHop::FirstHop { details }; - let added = add_entry!(candidate, our_node_id, payee, 0, path_value_msat, - 0, 0u64, 0, 0).is_some(); + let added = add_entry!(candidate, our_node_id, payee, 0, + path_value_msat, 0, 0u64, 0, 0, &candidate.fees()).is_some(); log_trace!(logger, "{} direct route to payee via {}", if added { "Added" } else { "Skipped" }, LoggedCandidateHop(&candidate)); } @@ -2006,7 +2006,7 @@ where L::Target: Logger { // If not, targets.pop() will not even let us enter the loop in step 2. None => {}, Some(node) => { - add_entries_to_cheapest_to_target_node!(node, payee, 0, path_value_msat, 0, 0u64, 0, 0); + add_entries_to_cheapest_to_target_node!(node, payee, 0, path_value_msat, 0, 0u64, 0, 0, &RoutingFees { base_msat: 0, proportional_millionths: 0 }); }, }); @@ -2028,7 +2028,7 @@ where L::Target: Logger { } else { CandidateRouteHop::Blinded { hint, hint_idx } }; let mut path_contribution_msat = path_value_msat; if let Some(hop_used_msat) = add_entry!(candidate, intro_node_id, maybe_dummy_payee_node_id, - 0, path_contribution_msat, 0, 0_u64, 0, 0) + 0, path_contribution_msat, 0, 0_u64, 0, 0, &candidate.fees()) { path_contribution_msat = hop_used_msat; } else { continue } @@ -2038,7 +2038,7 @@ where L::Target: Logger { for details in first_channels { let first_hop_candidate = CandidateRouteHop::FirstHop { details }; add_entry!(first_hop_candidate, our_node_id, intro_node_id, 0, path_contribution_msat, 0, - 0_u64, 0, 0); + 0_u64, 0, 0, &first_hop_candidate.fees()); } } } @@ -2081,7 +2081,7 @@ where L::Target: Logger { if let Some(hop_used_msat) = add_entry!(candidate, source, target, aggregate_next_hops_fee_msat, aggregate_path_contribution_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, - aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length) + aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length, &candidate.fees()) { aggregate_path_contribution_msat = hop_used_msat; } else { @@ -2100,7 +2100,7 @@ where L::Target: Logger { effective_capacity: candidate.effective_capacity(), }; let channel_penalty_msat = scorer.channel_penalty_msat( - hop.short_channel_id, &source, &target, channel_usage, score_params + hop.short_channel_id, &source, &target, channel_usage, score_params, &hop.fees ); aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat .saturating_add(channel_penalty_msat); @@ -2120,7 +2120,7 @@ where L::Target: Logger { add_entry!(first_hop_candidate, our_node_id, NodeId::from_pubkey(&prev_hop_id), aggregate_next_hops_fee_msat, aggregate_path_contribution_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, - aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length); + aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length, &first_hop_candidate.fees()); } } @@ -2165,7 +2165,7 @@ where L::Target: Logger { aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta, - aggregate_next_hops_path_length); + aggregate_next_hops_path_length, &first_hop_candidate.fees()); } } } @@ -2321,7 +2321,7 @@ where L::Target: Logger { Some(node) => { add_entries_to_cheapest_to_target_node!(node, node_id, lowest_fee_to_node, value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat, - total_cltv_delta, path_length_to_node); + total_cltv_delta, path_length_to_node, &RoutingFees { base_msat: 0, proportional_millionths: 0 }); }, } } @@ -2617,7 +2617,7 @@ fn build_route_from_hops_internal( impl Score for HopScorer { type ScoreParams = (); fn channel_penalty_msat(&self, _short_channel_id: u64, source: &NodeId, target: &NodeId, - _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 + _usage: ChannelUsage, _score_params: &Self::ScoreParams, _routing_fees: &RoutingFees) -> u64 { let mut cur_id = self.our_node_id; for i in 0..self.hop_ids.len() { @@ -5722,7 +5722,7 @@ mod tests { } impl Score for BadChannelScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams, routing_fees: &RoutingFees) -> u64 { if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 } } @@ -5743,7 +5743,7 @@ mod tests { impl Score for BadNodeScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams, _: &RoutingFees) -> u64 { if *target == self.node_id { u64::max_value() } else { 0 } } @@ -6213,7 +6213,7 @@ mod tests { }; scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123); scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456); - assert_eq!(scorer.channel_penalty_msat(42, &NodeId::from_pubkey(&nodes[3]), &NodeId::from_pubkey(&nodes[4]), usage, &scorer_params), 456); + assert_eq!(scorer.channel_penalty_msat(42, &NodeId::from_pubkey(&nodes[3]), &NodeId::from_pubkey(&nodes[4]), usage, &scorer_params, &RoutingFees { base_msat: 0, proportional_millionths: 0 } ), 456); // Then check we can get a normal route let payment_params = PaymentParameters::from_node_id(nodes[10], 42); diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 75dae72248b..7f99ebaa760 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -57,7 +57,7 @@ //! [`find_route`]: crate::routing::router::find_route use crate::ln::msgs::DecodeError; -use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId}; +use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees}; use crate::routing::router::Path; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; use crate::util::logger::Logger; @@ -101,7 +101,7 @@ pub trait Score $(: $supertrait)* { /// [`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, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams + &self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams, routing_fees: &RoutingFees ) -> u64; /// Handles updating channel penalties after failing to route through a channel. @@ -120,9 +120,9 @@ pub trait Score $(: $supertrait)* { impl $(+ $supertrait)*> Score for T { type ScoreParams = S::ScoreParams; fn channel_penalty_msat( - &self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams + &self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams, routing_fees: &RoutingFees ) -> u64 { - self.deref().channel_penalty_msat(short_channel_id, source, target, usage, score_params) + self.deref().channel_penalty_msat(short_channel_id, source, target, usage, score_params, routing_fees) } fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64) { @@ -287,7 +287,7 @@ impl FixedPenaltyScorer { impl Score for FixedPenaltyScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, _: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, _: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params: &Self::ScoreParams, _: &RoutingFees) -> u64 { self.penalty_msat } @@ -1238,7 +1238,7 @@ impl, BRT: DerefMut>, L: Deref, T: Time> Score for ProbabilisticScorerUsingTime where L::Target: Logger { type ScoreParams = ProbabilisticScoringFeeParameters; fn channel_penalty_msat( - &self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters + &self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters, _: &RoutingFees ) -> u64 { if let Some(penalty) = score_params.manual_node_penalties.get(target) { return *penalty; @@ -1755,7 +1755,7 @@ mod tests { use crate::ln::channelmanager; use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, UnsignedChannelAnnouncement, UnsignedChannelUpdate}; - use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId}; + use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees}; use crate::routing::router::{BlindedTail, Path, RouteHop}; use crate::routing::scoring::{ChannelUsage, Score}; use crate::util::ser::{ReadableArgs, Writeable}; @@ -2129,32 +2129,54 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 10_240, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 102_400, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 47); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 47); let usage = ChannelUsage { amount_msat: 1_023_999, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 2_000); let usage = ChannelUsage { amount_msat: 128, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 58); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 58); let usage = ChannelUsage { amount_msat: 256, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 125); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 125); let usage = ChannelUsage { amount_msat: 374, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 198); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 198); let usage = ChannelUsage { amount_msat: 512, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 300); let usage = ChannelUsage { amount_msat: 640, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 425); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 425); let usage = ChannelUsage { amount_msat: 768, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 602); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 602); let usage = ChannelUsage { amount_msat: 896, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 902); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + } ), 902); } #[test] @@ -2185,12 +2207,20 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 100, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 50, ..usage }; - assert_ne!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); - assert_ne!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_ne!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); + assert_ne!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); let usage = ChannelUsage { amount_msat: 61, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); } #[test] @@ -2212,13 +2242,19 @@ 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, &sender, &source, usage, ¶ms), 301); + assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + } ), 301); scorer.payment_path_failed(&failed_path, 41); - assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms), 301); + assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 301); scorer.payment_path_successful(&successful_path); - assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms), 301); + assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 301); } #[test] @@ -2239,20 +2275,32 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); let usage = ChannelUsage { amount_msat: 500, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 301); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 301); let usage = ChannelUsage { amount_msat: 750, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 602); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 602); scorer.payment_path_failed(&path, 43); let usage = ChannelUsage { amount_msat: 250, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 500, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 750, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 300); } #[test] @@ -2274,20 +2322,32 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); let usage = ChannelUsage { amount_msat: 500, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 301); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 301); let usage = ChannelUsage { amount_msat: 750, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 602); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 602); scorer.payment_path_failed(&path, 42); let usage = ChannelUsage { amount_msat: 250, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 300); let usage = ChannelUsage { amount_msat: 500, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); let usage = ChannelUsage { amount_msat: 750, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); } #[test] @@ -2335,17 +2395,29 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &node_a, &node_b, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(42, &node_a, &node_b, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); // Note that a default liquidity bound is used for B -> C as no channel exists - assert_eq!(scorer.channel_penalty_msat(43, &node_b, &node_c, usage, ¶ms), 128); - assert_eq!(scorer.channel_penalty_msat(44, &node_c, &node_d, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(43, &node_b, &node_c, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); + assert_eq!(scorer.channel_penalty_msat(44, &node_c, &node_d, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); scorer.payment_path_failed(&Path { hops: path, blinded_tail: None }, 43); - assert_eq!(scorer.channel_penalty_msat(42, &node_a, &node_b, usage, ¶ms), 80); + assert_eq!(scorer.channel_penalty_msat(42, &node_a, &node_b, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 80); // Note that a default liquidity bound is used for B -> C as no channel exists - assert_eq!(scorer.channel_penalty_msat(43, &node_b, &node_c, usage, ¶ms), 128); - assert_eq!(scorer.channel_penalty_msat(44, &node_c, &node_d, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(43, &node_b, &node_c, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); + assert_eq!(scorer.channel_penalty_msat(44, &node_c, &node_d, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); } #[test] @@ -2367,15 +2439,27 @@ mod tests { effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms), 128); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 128); - assert_eq!(scorer.channel_penalty_msat(43, &target, &recipient, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); + assert_eq!(scorer.channel_penalty_msat(43, &target, &recipient, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); scorer.payment_path_successful(&payment_path_for_amount(500)); - assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms), 128); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); - assert_eq!(scorer.channel_penalty_msat(43, &target, &recipient, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 128); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 300); + assert_eq!(scorer.channel_penalty_msat(43, &target, &recipient, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 300); } #[test] @@ -2400,79 +2484,131 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 1_023, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 2_000); scorer.payment_path_failed(&payment_path_for_amount(768), 42); scorer.payment_path_failed(&payment_path_for_amount(128), 43); // Initial penalties let usage = ChannelUsage { amount_msat: 128, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 256, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 93); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 93); let usage = ChannelUsage { amount_msat: 768, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1_479); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 1_479); let usage = ChannelUsage { amount_msat: 896, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); // No decay SinceEpoch::advance(Duration::from_secs(4)); let usage = ChannelUsage { amount_msat: 128, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 256, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 93); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 93); let usage = ChannelUsage { amount_msat: 768, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1_479); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 1_479); let usage = ChannelUsage { amount_msat: 896, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); // Half decay (i.e., three-quarter life) SinceEpoch::advance(Duration::from_secs(1)); let usage = ChannelUsage { amount_msat: 128, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 22); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 22); let usage = ChannelUsage { amount_msat: 256, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 106); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 106); let usage = ChannelUsage { amount_msat: 768, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 916); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 916); let usage = ChannelUsage { amount_msat: 896, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); // One decay (i.e., half life) SinceEpoch::advance(Duration::from_secs(5)); let usage = ChannelUsage { amount_msat: 64, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 128, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 34); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 34); let usage = ChannelUsage { amount_msat: 896, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1_970); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 1_970); let usage = ChannelUsage { amount_msat: 960, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), u64::max_value()); // Fully decay liquidity lower bound. SinceEpoch::advance(Duration::from_secs(10 * 7)); let usage = ChannelUsage { amount_msat: 0, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 1, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 1_023, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 2_000); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 2_000); let usage = ChannelUsage { amount_msat: 1_024, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); // Fully decay liquidity upper bound. SinceEpoch::advance(Duration::from_secs(10)); let usage = ChannelUsage { amount_msat: 0, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 1_024, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); SinceEpoch::advance(Duration::from_secs(10)); let usage = ChannelUsage { amount_msat: 0, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 0); let usage = ChannelUsage { amount_msat: 1_024, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), u64::max_value()); } #[test] @@ -2495,18 +2631,26 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 125); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat: 0, proportional_millionths: 0, + }), 125); scorer.payment_path_failed(&payment_path_for_amount(512), 42); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 281); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 281); // 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, &source, &target, usage, ¶ms), 125); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 125); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 125); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 125); } #[test] @@ -2530,30 +2674,42 @@ mod tests { effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 300); // More knowledge gives higher confidence (256, 768), meaning a lower penalty. scorer.payment_path_failed(&payment_path_for_amount(768), 42); scorer.payment_path_failed(&payment_path_for_amount(256), 43); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 281); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 281); // Decaying knowledge gives less confidence (128, 896), meaning a higher penalty. SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 291); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 291); // 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)); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 331); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 331); // 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), 43); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 245); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 245); // 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, &source, &target, usage, ¶ms), 280); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 280); } #[test] @@ -2579,13 +2735,19 @@ mod tests { }; scorer.payment_path_failed(&payment_path_for_amount(500), 42); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), u64::max_value()); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 473); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 473); scorer.payment_path_failed(&payment_path_for_amount(250), 43); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 300); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); @@ -2593,7 +2755,9 @@ mod tests { let mut serialized_scorer = io::Cursor::new(&serialized_scorer); let deserialized_scorer = ::read(&mut serialized_scorer, (decay_params, &network_graph, &logger)).unwrap(); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 300); } #[test] @@ -2619,7 +2783,9 @@ mod tests { }; scorer.payment_path_failed(&payment_path_for_amount(500), 42); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), u64::max_value()); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); @@ -2629,13 +2795,19 @@ mod tests { let mut serialized_scorer = io::Cursor::new(&serialized_scorer); let deserialized_scorer = ::read(&mut serialized_scorer, (decay_params, &network_graph, &logger)).unwrap(); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 473); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 473); scorer.payment_path_failed(&payment_path_for_amount(250), 43); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 300); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 365); + assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 365); } #[test] @@ -2654,47 +2826,69 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 950_000_000, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 4375); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 4375); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 2739); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 2739); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 2_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 2236); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 2236); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 3_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1983); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1983); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 4_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1637); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1637); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 5_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1606); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1606); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 6_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1331); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1331); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 7_450_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1387); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1387); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 7_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1379); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1379); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 8_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1363); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1363); let usage = ChannelUsage { effective_capacity: EffectiveCapacity::Total { capacity_msat: 9_950_000_000, htlc_maximum_msat: 1_000 }, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1355); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 1355); } #[test] @@ -2714,14 +2908,18 @@ mod tests { ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 58); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 58); let params = ProbabilisticScoringFeeParameters { base_penalty_msat: 500, liquidity_penalty_multiplier_msat: 1_000, anti_probing_penalty_msat: 0, ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 558); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 558); let params = ProbabilisticScoringFeeParameters { base_penalty_msat: 500, liquidity_penalty_multiplier_msat: 1_000, @@ -2730,7 +2928,9 @@ mod tests { }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 558 + 128); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 558 + 128); } #[test] @@ -2751,7 +2951,9 @@ mod tests { ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 300); let params = ProbabilisticScoringFeeParameters { liquidity_penalty_multiplier_msat: 1_000, @@ -2759,7 +2961,9 @@ mod tests { ..ProbabilisticScoringFeeParameters::zero_penalty() }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 337); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 337); } #[test] @@ -2780,7 +2984,9 @@ mod tests { }; let decay_params = ProbabilisticScoringDecayParameters::zero_penalty(); let scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 80_000); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 80_000); } #[test] @@ -2800,10 +3006,14 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, }; - assert_ne!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_ne!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), u64::max_value()); let usage = ChannelUsage { inflight_htlc_msat: 251, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), u64::max_value()); } #[test] @@ -2821,13 +3031,19 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::ExactLiquidity { liquidity_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), base_penalty_msat); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), base_penalty_msat); let usage = ChannelUsage { amount_msat: 1_000, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), base_penalty_msat); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), base_penalty_msat); let usage = ChannelUsage { amount_msat: 1_001, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), u64::max_value()); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), u64::max_value()); } #[test] @@ -2853,12 +3069,16 @@ mod tests { effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, }; // With no historical data the normal liquidity penalty calculation is used. - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 47); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 47); assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); scorer.payment_path_failed(&payment_path_for_amount(1), 42); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 2048); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 2048); // The "it failed" increment is 32, where the probability should lie fully in the first // octile. assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), @@ -2867,7 +3087,9 @@ mod tests { // Even after we tell the scorer we definitely have enough available liquidity, it will // still remember that there was some failure in the past, and assign a non-0 penalty. scorer.payment_path_failed(&payment_path_for_amount(1000), 43); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 198); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 198); // The first octile should be decayed just slightly and the last octile has a new point. assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), Some(([31, 0, 0, 0, 0, 0, 0, 32], [31, 0, 0, 0, 0, 0, 0, 32]))); @@ -2875,7 +3097,9 @@ mod tests { // Advance the time forward 16 half-lives (which the docs claim will ensure all data is // gone), and check that we're back to where we started. SinceEpoch::advance(Duration::from_secs(10 * 16)); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 47); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 47); // Once fully decayed we still have data, but its all-0s. In the future we may remove the // data entirely instead. assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), @@ -2887,14 +3111,18 @@ mod tests { effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, }; scorer.payment_path_failed(&payment_path_for_amount(1), 42); - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 409); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 409); let usage = ChannelUsage { amount_msat: 1, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::AdvertisedMaxHTLC { amount_msat: 0 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &target, &source, usage, ¶ms), 2048); + assert_eq!(scorer.channel_penalty_msat(42, &target, &source, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 2048); // Advance to decay all liquidity offsets to zero. SinceEpoch::advance(Duration::from_secs(60 * 60 * 10)); @@ -2927,7 +3155,9 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 0); // Check we receive anti-probing penalty for htlc_maximum_msat == channel_capacity. let usage = ChannelUsage { @@ -2935,7 +3165,9 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_024_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 500); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 500); // Check we receive anti-probing penalty for htlc_maximum_msat == channel_capacity/2. let usage = ChannelUsage { @@ -2943,7 +3175,9 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 512_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 500); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 500); // Check we receive no anti-probing penalty for htlc_maximum_msat == channel_capacity/2 - 1. let usage = ChannelUsage { @@ -2951,7 +3185,9 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 511_999 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 0); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 0); } #[test] @@ -2972,7 +3208,9 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms, &RoutingFees { + base_msat:0, proportional_millionths: 0, + }), 300); let mut path = payment_path_for_amount(768); let recipient_hop = path.hops.pop().unwrap(); diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 65c0483a59c..e998be34f00 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -16,6 +16,7 @@ use crate::chain::chainmonitor::MonitorUpdateId; use crate::chain::channelmonitor; use crate::chain::channelmonitor::MonitorEvent; use crate::chain::transaction::OutPoint; +use crate::routing::gossip::RoutingFees; use crate::sign; use crate::events; use crate::events::bump_transaction::{WalletSource, Utxo}; @@ -132,10 +133,10 @@ impl<'a> Router for TestRouter<'a> { // Since the path is reversed, the last element in our iteration is the first // hop. if idx == path.hops.len() - 1 { - scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage, &()); + scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage, &(), &RoutingFees { base_msat: 0, proportional_millionths: 0 }); } else { let curr_hop_path_idx = path.hops.len() - 1 - idx; - scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path.hops[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage, &()); + scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path.hops[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage, &(), &RoutingFees { base_msat: 0, proportional_millionths: 0 }); } } } @@ -1032,7 +1033,7 @@ impl crate::util::ser::Writeable for TestScorer { impl Score for TestScorer { type ScoreParams = (); fn channel_penalty_msat( - &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &Self::ScoreParams, _routing_fees: &RoutingFees ) -> u64 { if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() { match scorer_expectations.pop_front() {