From f0ecc3ec73dcdb9303b1bd5ac687a361decce2dd Mon Sep 17 00:00:00 2001 From: jbesraa Date: Wed, 6 Sep 2023 16:04:08 +0300 Subject: [PATCH] Use `CandidateRouteHop` as input for `channel_penalty_msat` We remove `source`, `target` and `scid` from `channel_penalty_msat` inputs to consume them from `candidate` of type `CandidateRouteHop` --- lightning-background-processor/src/lib.rs | 4 +- lightning/src/routing/router.rs | 62 ++- lightning/src/routing/scoring.rs | 490 ++++++++++++++-------- lightning/src/util/test_utils.rs | 37 +- 4 files changed, 399 insertions(+), 194 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 95796e860..1e6d447c8 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -863,8 +863,8 @@ mod tests { 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::router::{DefaultRouter, Path, RouteHop}; use lightning::routing::scoring::{ChannelUsage, ScoreUpdate, ScoreLookUp, LockableScore}; + use lightning::routing::router::{DefaultRouter, Path, RouteHop, CandidateRouteHop}; use lightning::util::config::UserConfig; use lightning::util::ser::Writeable; use lightning::util::test_utils; @@ -1071,7 +1071,7 @@ mod tests { impl ScoreLookUp for TestScorer { type ScoreParams = (); fn channel_penalty_msat( - &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, _candidate: &CandidateRouteHop, _usage: ChannelUsage, _score_params: &Self::ScoreParams ) -> u64 { unimplemented!(); } } diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 5e906878d..c33a0d36d 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -130,18 +130,27 @@ impl<'a, S: Deref> ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: Scor impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: ScoreLookUp { type ScoreParams = ::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, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 { + let target = match candidate.target() { + Some(target) => target, + None => return self.scorer.channel_penalty_msat(candidate, usage, score_params), + }; + let short_channel_id = match candidate.short_channel_id() { + Some(short_channel_id) => short_channel_id, + None => return self.scorer.channel_penalty_msat(candidate, usage, score_params), + }; + let source = candidate.source(); if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( - source, target, short_channel_id + &source, &target, short_channel_id ) { let usage = ChannelUsage { inflight_htlc_msat: usage.inflight_htlc_msat.saturating_add(used_liquidity), ..usage }; - self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params) + self.scorer.channel_penalty_msat(candidate, usage, score_params) } else { - self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params) + self.scorer.channel_penalty_msat(candidate, usage, score_params) } } } @@ -1068,7 +1077,7 @@ impl<'a> CandidateRouteHop<'a> { /// For `Blinded` and `OneHopBlinded` we return `None` because next hop is not known. pub fn short_channel_id(&self) -> Option { match self { - CandidateRouteHop::FirstHop { details, .. } => Some(details.get_outbound_payment_scid().unwrap()), + CandidateRouteHop::FirstHop { details, .. } => details.get_outbound_payment_scid(), CandidateRouteHop::PublicHop { short_channel_id, .. } => Some(*short_channel_id), CandidateRouteHop::PrivateHop { hint, .. } => Some(hint.short_channel_id), CandidateRouteHop::Blinded { .. } => None, @@ -1173,7 +1182,7 @@ impl<'a> CandidateRouteHop<'a> { CandidateRouteHop::PublicHop { info, .. } => *info.source(), CandidateRouteHop::PrivateHop { hint, .. } => hint.src_node_id.into(), CandidateRouteHop::Blinded { hint, .. } => hint.1.introduction_node_id.into(), - CandidateRouteHop::OneHopBlinded { hint, .. } => hint.1.introduction_node_id.into() + CandidateRouteHop::OneHopBlinded { hint, .. } => hint.1.introduction_node_id.into(), } } /// Returns the target node id of this hop, if known. @@ -2011,9 +2020,10 @@ where L::Target: Logger { inflight_htlc_msat: used_liquidity_msat, effective_capacity, }; - 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)); + let channel_penalty_msat = + scorer.channel_penalty_msat($candidate, + channel_usage, + score_params); let path_penalty_msat = $next_hops_path_penalty_msat .saturating_add(channel_penalty_msat); let new_graph_node = RouteGraphNode { @@ -2324,7 +2334,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 + &candidate, channel_usage, score_params ); aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat .saturating_add(channel_penalty_msat); @@ -2879,13 +2889,13 @@ fn build_route_from_hops_internal( impl ScoreLookUp for HopScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, _short_channel_id: u64, source: &NodeId, target: &NodeId, + fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 { let mut cur_id = self.our_node_id; for i in 0..self.hop_ids.len() { if let Some(next_id) = self.hop_ids[i] { - if cur_id == *source && next_id == *target { + if cur_id == candidate.source() && Some(next_id) == candidate.target() { return 0; } cur_id = next_id; @@ -2926,7 +2936,7 @@ mod tests { use crate::routing::utxo::UtxoResult; use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features, BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, - DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE, RouteParameters}; + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE, RouteParameters, CandidateRouteHop}; use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, ScoreLookUp, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters}; use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel}; use crate::chain::transaction::OutPoint; @@ -6231,8 +6241,8 @@ mod tests { } impl ScoreLookUp for BadChannelScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { - if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 } + fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { + if candidate.short_channel_id() == Some(self.short_channel_id) { u64::max_value() } else { 0 } } } @@ -6247,8 +6257,8 @@ mod tests { impl ScoreLookUp for BadNodeScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { - if *target == self.node_id { u64::max_value() } else { 0 } + fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { + if candidate.target() == Some(self.node_id) { u64::max_value() } else { 0 } } } @@ -6736,26 +6746,32 @@ 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); + let network_graph = network_graph.read_only(); + let channels = network_graph.channels(); + let channel = channels.get(&5).unwrap(); + let info = channel.as_directed_from(&NodeId::from_pubkey(&nodes[3])).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info: info.0, + short_channel_id: 5, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, &scorer_params), 456); // Then check we can get a normal route let payment_params = PaymentParameters::from_node_id(nodes[10], 42); let route_params = RouteParameters::from_payment_params_and_value( payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, + let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes); assert!(route.is_ok()); // Then check that we can't get a route if we ban an intermediate node. scorer_params.add_banned(&NodeId::from_pubkey(&nodes[3])); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes); + let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes); assert!(route.is_err()); // Finally make sure we can route again, when we remove the ban. scorer_params.remove_banned(&NodeId::from_pubkey(&nodes[3])); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes); + let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes); assert!(route.is_ok()); } diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index de40b295e..5d637a859 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -58,7 +58,7 @@ use crate::ln::msgs::DecodeError; use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId}; -use crate::routing::router::Path; +use crate::routing::router::{Path, CandidateRouteHop}; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; use crate::util::logger::Logger; use crate::util::time::Time; @@ -103,7 +103,7 @@ pub trait ScoreLookUp { /// [`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, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams ) -> u64; } @@ -137,9 +137,9 @@ impl Score for T {} impl> ScoreLookUp 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, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams ) -> u64 { - self.deref().channel_penalty_msat(short_channel_id, source, target, usage, score_params) + self.deref().channel_penalty_msat(candidate, usage, score_params) } } @@ -315,10 +315,9 @@ impl<'a, T: 'a + Score> Deref for MultiThreadedScoreLockRead<'a, T> { #[cfg(c_bindings)] impl<'a, T: Score> ScoreLookUp for MultiThreadedScoreLockRead<'a, T> { type ScoreParams = T::ScoreParams; - fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, - target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams + fn channel_penalty_msat(&self, candidate:&CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams ) -> u64 { - self.0.channel_penalty_msat(short_channel_id, source, target, usage, score_params) + self.0.channel_penalty_msat(candidate, usage, score_params) } } @@ -394,7 +393,7 @@ impl FixedPenaltyScorer { impl ScoreLookUp for FixedPenaltyScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, _: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 { self.penalty_msat } } @@ -1343,9 +1342,18 @@ impl, BRT: DerefMut>, L: Deref, T: Time> ScoreLookUp 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, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters ) -> u64 { - if let Some(penalty) = score_params.manual_node_penalties.get(target) { + let scid = match candidate.short_channel_id() { + Some(scid) => scid, + None => return 0, + }; + let target = match candidate.target() { + Some(target) => target, + None => return 0, + }; + let source = candidate.source(); + if let Some(penalty) = score_params.manual_node_penalties.get(&target) { return *penalty; } @@ -1375,9 +1383,9 @@ impl>, L: Deref, T: Time> ScoreLookUp for Prob let amount_msat = usage.amount_msat.saturating_add(usage.inflight_htlc_msat); let capacity_msat = usage.effective_capacity.as_msat(); self.channel_liquidities - .get(&short_channel_id) + .get(&scid) .unwrap_or(&ChannelLiquidity::new()) - .as_directed(source, target, capacity_msat, self.decay_params) + .as_directed(&source, &target, capacity_msat, self.decay_params) .penalty_msat(amount_msat, score_params) .saturating_add(anti_probing_penalty_msat) .saturating_add(base_penalty_msat) @@ -2174,7 +2182,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::router::{BlindedTail, Path, RouteHop}; + use crate::routing::router::{BlindedTail, Path, RouteHop, CandidateRouteHop}; use crate::routing::scoring::{ChannelUsage, ScoreLookUp, ScoreUpdate}; use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_utils::{self, TestLogger}; @@ -2541,39 +2549,45 @@ mod tests { let decay_params = ProbabilisticScoringDecayParameters::default(); let scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 1_024, 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); + let network_graph = network_graph.read_only(); + let channel = network_graph.channel(42).unwrap(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 902); } #[test] @@ -2597,19 +2611,24 @@ mod tests { max_liquidity_offset_history: HistoricalBucketRangeTracker::new(), }); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 39, 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 0); + assert_ne!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), u64::max_value()); } #[test] @@ -2621,7 +2640,6 @@ mod tests { ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - let sender = sender_node_id(); let source = source_node_id(); let usage = ChannelUsage { amount_msat: 500, @@ -2630,14 +2648,20 @@ mod tests { }; let failed_path = payment_path_for_amount(500); let successful_path = payment_path_for_amount(200); + let channel = &network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 41, + }; - assert_eq!(scorer.channel_penalty_msat(41, &sender, &source, usage, ¶ms), 301); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 301); } #[test] @@ -2650,7 +2674,6 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let path = payment_path_for_amount(500); let usage = ChannelUsage { @@ -2658,20 +2681,26 @@ 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 300); } #[test] @@ -2685,7 +2714,6 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let path = payment_path_for_amount(500); let usage = ChannelUsage { @@ -2693,20 +2721,26 @@ 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), u64::max_value()); } #[test] @@ -2741,7 +2775,6 @@ mod tests { let node_a = NodeId::from_pubkey(&pub_a); let node_b = NodeId::from_pubkey(&pub_b); let node_c = NodeId::from_pubkey(&pub_c); - let node_d = NodeId::from_pubkey(&pub_d); let params = ProbabilisticScoringFeeParameters { liquidity_penalty_multiplier_msat: 1_000, @@ -2754,17 +2787,53 @@ 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&node_a).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&node_b).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 43, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); + let channel = network_graph.read_only().channel(44).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&node_c).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 44, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&node_a).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&node_b).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 43, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); + let channel = network_graph.read_only().channel(44).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&node_c).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 44, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); } #[test] @@ -2776,25 +2845,39 @@ mod tests { ..ProbabilisticScoringFeeParameters::zero_penalty() }; let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - let sender = sender_node_id(); let source = source_node_id(); - let target = target_node_id(); - let recipient = recipient_node_id(); let usage = ChannelUsage { amount_msat: 250, inflight_htlc_msat: 0, 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); + let network_graph = network_graph.read_only().channels().clone(); + let channel_42 = network_graph.get(&42).unwrap(); + let channel_43 = network_graph.get(&43).unwrap(); + let (info, _) = channel_42.as_directed_from(&source).unwrap(); + let candidate_41 = CandidateRouteHop::PublicHop { + info, + short_channel_id: 41, + }; + let (info, target) = channel_42.as_directed_from(&source).unwrap(); + let candidate_42 = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + let (info, _) = channel_43.as_directed_from(&target).unwrap(); + let candidate_43 = CandidateRouteHop::PublicHop { + info, + short_channel_id: 43, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate_41, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(&candidate_42, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(&candidate_43, usage, ¶ms), 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(&candidate_41, usage, ¶ms), 128); + assert_eq!(scorer.channel_penalty_msat(&candidate_42, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(&candidate_43, usage, ¶ms), 300); } #[test] @@ -2812,86 +2895,91 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 0, 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, target) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 106); let usage = ChannelUsage { amount_msat: 768, ..usage }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 921); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 921); 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), u64::max_value()); } #[test] @@ -2908,24 +2996,29 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 256, 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, target) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 125); } #[test] @@ -2942,37 +3035,42 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 512, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, }; + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 300); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 280); } #[test] @@ -2990,7 +3088,6 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 500, inflight_htlc_msat: 0, @@ -2998,13 +3095,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()); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 300); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); @@ -3012,7 +3115,7 @@ 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(&candidate, usage, ¶ms), 300); } #[test] @@ -3030,7 +3133,6 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 500, inflight_htlc_msat: 0, @@ -3038,7 +3140,13 @@ 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()); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value()); let mut serialized_scorer = Vec::new(); scorer.write(&mut serialized_scorer).unwrap(); @@ -3048,13 +3156,13 @@ 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 300); SinceEpoch::advance(Duration::from_secs(10)); - assert_eq!(deserialized_scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 370); + assert_eq!(deserialized_scorer.channel_penalty_msat(&candidate, usage, ¶ms), 370); } #[test] @@ -3066,54 +3174,59 @@ mod tests { let params = ProbabilisticScoringFeeParameters::default(); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 100_000_000, 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), 11497); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 11497); 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), 7408); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 7408); 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), 6151); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 6151); 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), 5427); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 5427); 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), 4955); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 4955); 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), 4736); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 4736); 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), 4484); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 4484); 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), 4484); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 4484); 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), 4263); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 4263); 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), 4263); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 4263); 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), 4044); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 4044); } #[test] @@ -3121,7 +3234,6 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 128, inflight_htlc_msat: 0, @@ -3133,14 +3245,20 @@ 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 558); let params = ProbabilisticScoringFeeParameters { base_penalty_msat: 500, liquidity_penalty_multiplier_msat: 1_000, @@ -3149,7 +3267,7 @@ 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(&candidate, usage, ¶ms), 558 + 128); } #[test] @@ -3157,7 +3275,6 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 512_000, inflight_htlc_msat: 0, @@ -3170,7 +3287,13 @@ 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); let params = ProbabilisticScoringFeeParameters { liquidity_penalty_multiplier_msat: 1_000, @@ -3178,7 +3301,7 @@ 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(&candidate, usage, ¶ms), 337); } #[test] @@ -3186,20 +3309,24 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: u64::max_value(), inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Infinite, }; - let params = ProbabilisticScoringFeeParameters { liquidity_penalty_multiplier_msat: 40_000, ..ProbabilisticScoringFeeParameters::zero_penalty() }; let decay_params = ProbabilisticScoringDecayParameters::zero_penalty(); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; 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(&candidate, usage, ¶ms), 80_000); } #[test] @@ -3212,17 +3339,23 @@ mod tests { }; let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 750, 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()); + let network_graph = network_graph.read_only(); + let channel = network_graph.channel(42).unwrap(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_ne!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), u64::max_value()); } #[test] @@ -3232,7 +3365,6 @@ mod tests { let params = ProbabilisticScoringFeeParameters::default(); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let base_penalty_msat = params.base_penalty_msat; let usage = ChannelUsage { @@ -3240,16 +3372,22 @@ 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); + let network_graph = network_graph.read_only(); + let channel = network_graph.channel(42).unwrap(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), u64::max_value()); } - #[test] fn remembers_historical_failures() { let logger = TestLogger::new(); let network_graph = network_graph(&logger); @@ -3264,7 +3402,6 @@ mod tests { }; let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 100, @@ -3276,17 +3413,24 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, }; + let network_graph = network_graph.read_only(); + let channel = network_graph.channel(42).unwrap(); + let (info, target) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; // With no historical data the normal liquidity penalty calculation is used. - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 168); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 168); assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - None); + None); assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms), - None); + 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_1, ¶ms), 249); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2048); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage_1, ¶ms), 249); // The "it failed" increment is 32, where the probability should lie several buckets into // the first octile. assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), @@ -3300,7 +3444,7 @@ 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), 105); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 105); // The first points should be decayed just slightly and the last bucket has a new point. assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), Some(([31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0], @@ -3320,7 +3464,7 @@ 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), 168); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 168); // 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), @@ -3333,16 +3477,16 @@ 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), 2050); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2050); usage.inflight_htlc_msat = 0; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 866); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 866); 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(&candidate, usage, ¶ms), 2048); // Advance to decay all liquidity offsets to zero. SinceEpoch::advance(Duration::from_secs(60 * 60 * 10)); @@ -3362,7 +3506,6 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let source = source_node_id(); - let target = target_node_id(); let params = ProbabilisticScoringFeeParameters { anti_probing_penalty_msat: 500, ..ProbabilisticScoringFeeParameters::zero_penalty() @@ -3375,7 +3518,14 @@ 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); + let network_graph = network_graph.read_only(); + let channel = network_graph.channel(42).unwrap(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); // Check we receive anti-probing penalty for htlc_maximum_msat == channel_capacity. let usage = ChannelUsage { @@ -3383,7 +3533,7 @@ 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(&candidate, usage, ¶ms), 500); // Check we receive anti-probing penalty for htlc_maximum_msat == channel_capacity/2. let usage = ChannelUsage { @@ -3391,7 +3541,7 @@ 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(&candidate, usage, ¶ms), 500); // Check we receive no anti-probing penalty for htlc_maximum_msat == channel_capacity/2 - 1. let usage = ChannelUsage { @@ -3399,7 +3549,7 @@ 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(&candidate, usage, ¶ms), 0); } #[test] @@ -3414,13 +3564,18 @@ mod tests { let decay_params = ProbabilisticScoringDecayParameters::default(); let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let usage = ChannelUsage { amount_msat: 512, 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, target) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); let mut path = payment_path_for_amount(768); let recipient_hop = path.hops.pop().unwrap(); @@ -3476,7 +3631,6 @@ mod tests { let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); let source = source_node_id(); - let target = target_node_id(); let mut amount_msat = 10_000_000; let usage = ChannelUsage { @@ -3484,9 +3638,15 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: capacity_msat }, }; + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, target) = channel.as_directed_from(&source).unwrap(); + let candidate = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; // With no historical data the normal liquidity penalty calculation is used, which results // in a success probability of ~75%. - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 1269); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 1269); assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms), @@ -3496,7 +3656,7 @@ mod tests { scorer.payment_path_failed(&payment_path_for_amount(amount_msat), 42); // The penalty should be the maximum penalty, as the payment we're scoring is now in the // same bucket which is the only maximum datapoint. - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2048 + 2048 * amount_msat / super::AMOUNT_PENALTY_DIVISOR); // The "it failed" increment is 32, which we should apply to the first upper-bound (between // 6k sats and 12k sats). diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index a6c2d7745..9bbbec0d7 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -17,6 +17,7 @@ use crate::chain::chainmonitor::{MonitorUpdateId, UpdateOrigin}; use crate::chain::channelmonitor; use crate::chain::channelmonitor::MonitorEvent; use crate::chain::transaction::OutPoint; +use crate::routing::router::CandidateRouteHop; use crate::sign; use crate::events; use crate::events::bump_transaction::{WalletSource, Utxo}; @@ -139,10 +140,34 @@ 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, &Default::default()); + let first_hops = match first_hops { + Some(hops) => hops, + None => continue, + }; + if first_hops.len() == 0 { + continue; + } + let idx = if first_hops.len() > 1 { route.paths.iter().position(|p| p == path).unwrap_or(0) } else { 0 }; + let candidate = CandidateRouteHop::FirstHop { + details: first_hops[idx], + node_id: NodeId::from_pubkey(payer) + }; + scorer.channel_penalty_msat(&candidate, usage, &()); } 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, &Default::default()); + let network_graph = self.network_graph.read_only(); + let channel = match network_graph.channel(hop.short_channel_id) { + Some(channel) => channel, + None => continue, + }; + let channel = match channel.as_directed_to(&NodeId::from_pubkey(&hop.pubkey)) { + Some(channel) => channel, + None => panic!("Channel directed to {} was not found", hop.pubkey), + }; + let candidate = CandidateRouteHop::PublicHop { + info: channel.0, + short_channel_id: hop.short_channel_id, + }; + scorer.channel_penalty_msat(&candidate, usage, &()); } } } @@ -1297,8 +1322,12 @@ impl crate::util::ser::Writeable for TestScorer { impl ScoreLookUp for TestScorer { type ScoreParams = (); fn channel_penalty_msat( - &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, _score_params: &Self::ScoreParams ) -> u64 { + let short_channel_id = match candidate.short_channel_id() { + Some(scid) => scid, + None => return 0, + }; if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() { match scorer_expectations.pop_front() { Some((scid, expectation)) => { -- 2.39.5