diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 8648920ec2c..61267b6eb3d 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -861,7 +861,7 @@ 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::router::{DefaultRouter, Path, RouteHop, CandidateRouteHop}; use lightning::routing::scoring::{ChannelUsage, ScoreUpdate, ScoreLookUp}; use lightning::util::config::UserConfig; use lightning::util::ser::Writeable; @@ -1040,7 +1040,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 cf8e6b4cc87..1d553142b1e 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -134,18 +134,27 @@ impl<'a, SP: Sized, Sc: ScoreLookUp, S: Deref> Wr impl<'a, SP: Sized, Sc: 'a + ScoreLookUp, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, SP, Sc, S> { type ScoreParams = Sc::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 0, + }; + let short_channel_id = match candidate.short_channel_id() { + Some(short_channel_id) => short_channel_id, + None => return 0, + }; + 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 + 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) } } } @@ -1837,7 +1846,7 @@ where L::Target: Logger { effective_capacity, }; let channel_penalty_msat = scid_opt.map_or(0, - |scid| scorer.channel_penalty_msat(scid, &$src_node_id, &$dest_node_id, + |scid| scorer.channel_penalty_msat($candidate, channel_usage, score_params)); let path_penalty_msat = $next_hops_path_penalty_msat .saturating_add(channel_penalty_msat); @@ -1951,7 +1960,7 @@ where L::Target: Logger { if let Some(first_channels) = first_hop_targets.get(&$node_id) { for details in first_channels { let candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id }; - add_entry!(candidate, our_node_id, $node_id, $fee_to_target_msat, + 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); @@ -1975,7 +1984,7 @@ where L::Target: Logger { info: directed_channel, short_channel_id: *chan_id, }; - add_entry!(candidate, *source, $node_id, + add_entry!(&candidate, *source, $node_id, $fee_to_target_msat, $next_hops_value_contribution, $next_hops_path_htlc_minimum_msat, @@ -2006,7 +2015,7 @@ 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, node_id: our_node_id }; - let added = add_entry!(candidate, our_node_id, payee, 0, path_value_msat, + let added = add_entry!(&candidate, our_node_id, payee, 0, path_value_msat, 0, 0u64, 0, 0).is_some(); log_trace!(logger, "{} direct route to payee via {}", if added { "Added" } else { "Skipped" }, LoggedCandidateHop(&candidate)); @@ -2043,7 +2052,7 @@ where L::Target: Logger { CandidateRouteHop::OneHopBlinded { hint, hint_idx } } 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, + 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) { path_contribution_msat = hop_used_msat; @@ -2057,7 +2066,7 @@ where L::Target: Logger { Some(fee) => fee, None => continue }; - add_entry!(first_hop_candidate, our_node_id, intro_node_id, blinded_path_fee, + add_entry!(&first_hop_candidate, our_node_id, intro_node_id, blinded_path_fee, path_contribution_msat, candidate.htlc_minimum_msat(), 0_u64, candidate.cltv_expiry_delta(), candidate.blinded_path().map_or(1, |bp| bp.blinded_hops.len() as u8)); @@ -2100,7 +2109,7 @@ where L::Target: Logger { }) .unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop, target_node_id: target }); - if let Some(hop_used_msat) = add_entry!(candidate, source, target, + 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) @@ -2122,7 +2131,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); @@ -2139,7 +2148,7 @@ where L::Target: Logger { recommended_value_msat, our_node_pubkey); for details in first_channels { let first_hop_candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id}; - add_entry!(first_hop_candidate, our_node_id, NodeId::from_pubkey(&prev_hop_id), + 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); @@ -2180,7 +2189,7 @@ where L::Target: Logger { recommended_value_msat, our_node_pubkey); for details in first_channels { let first_hop_candidate = CandidateRouteHop::FirstHop { details, node_id: our_node_id}; - add_entry!(first_hop_candidate, our_node_id, + add_entry!(&first_hop_candidate, our_node_id, NodeId::from_pubkey(&hop.src_node_id), aggregate_next_hops_fee_msat, aggregate_path_contribution_msat, @@ -2638,13 +2647,18 @@ 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 target = match candidate.target() { + Some(target) => target, + None => return 0, + }; + let source = candidate.source(); 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 == source && next_id == target { return 0; } cur_id = next_id; @@ -2721,6 +2735,8 @@ mod tests { use core::convert::TryInto; + use super::CandidateRouteHop; + fn get_channel_details(short_channel_id: Option, node_id: PublicKey, features: InitFeatures, outbound_capacity_msat: u64) -> channelmanager::ChannelDetails { channelmanager::ChannelDetails { @@ -5737,7 +5753,11 @@ 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 { + fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { + let short_channel_id = match candidate.short_channel_id() { + Some(id) => id, + None => return 0, + }; if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 } } } @@ -5753,8 +5773,12 @@ 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 { + let target = match candidate.target() { + Some(target) => target, + None => return 0, + }; + if target == self.node_id { u64::max_value() } else { 0 } } } @@ -6218,21 +6242,29 @@ 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 = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes); + let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 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, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes); + let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 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, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes); + let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 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 aaafbc35b61..ab5b8552e1c 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 $(: $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, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams ) -> u64; } @@ -125,9 +125,9 @@ pub trait ScoreUpdate $(: $supertrait)* { impl, T: Deref $(+ $supertrait)*> ScoreLookUp for T { type ScoreParams = SP; 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) } } @@ -352,7 +352,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 } } @@ -1188,9 +1188,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; } @@ -1221,9 +1230,9 @@ impl>, L: Deref, T: Time> ScoreLookUp for Prob let capacity_msat = usage.effective_capacity.as_msat(); let inflight_htlc_msat = usage.inflight_htlc_msat; self.channel_liquidities - .get(&short_channel_id) + .get(&scid) .unwrap_or(&ChannelLiquidity::new()) - .as_directed(source, target, inflight_htlc_msat, capacity_msat, self.decay_params) + .as_directed(&source, &target, inflight_htlc_msat, capacity_msat, self.decay_params) .penalty_msat(amount_msat, score_params) .saturating_add(anti_probing_penalty_msat) .saturating_add(base_penalty_msat) @@ -1868,7 +1877,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}; @@ -2234,39 +2243,44 @@ 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 channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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] @@ -2290,19 +2304,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 = 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] @@ -2314,7 +2333,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, @@ -2322,15 +2340,21 @@ mod tests { effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, }; 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); + let successful_path: 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 = CandidateRouteHop::PublicHop { + info, + short_channel_id: 41, + }; + + 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] @@ -2343,7 +2367,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 { @@ -2351,20 +2374,27 @@ 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 scid_42 = 42; + let channel = network_graph.read_only().channel(scid_42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info, + short_channel_id: scid_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] @@ -2378,7 +2408,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 { @@ -2386,20 +2415,27 @@ 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 scid_42 = 42; + let channel = network_graph.read_only().channel(scid_42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info, + short_channel_id: scid_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] @@ -2447,17 +2483,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 = 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 = 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 = 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 = 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 = 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 = CandidateRouteHop::PublicHop { + info, + short_channel_id: 44, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); } #[test] @@ -2469,25 +2541,58 @@ 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 channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info, + short_channel_id: 41, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, 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 = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); + let channel = network_graph.read_only().channel(43).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&target).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info, + short_channel_id: 43, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info, + short_channel_id: 41, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, 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 = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); + let channel = network_graph.read_only().channel(43).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&target).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info, + short_channel_id: 43, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); } #[test] @@ -2505,86 +2610,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 }, + 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, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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), 916); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&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] @@ -2601,24 +2711,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, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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] @@ -2635,37 +2750,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 = 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] @@ -2683,7 +2803,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, @@ -2691,13 +2810,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 = 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(); @@ -2705,7 +2830,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] @@ -2723,7 +2848,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, @@ -2731,7 +2855,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 = 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(); @@ -2741,13 +2871,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), 365); + assert_eq!(deserialized_scorer.channel_penalty_msat(&candidate, usage, ¶ms), 365); } #[test] @@ -2759,54 +2889,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), 4375); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info, + short_channel_id: 42, + }; + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 1355); } #[test] @@ -2814,7 +2949,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, @@ -2826,14 +2960,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 = 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, @@ -2842,7 +2982,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] @@ -2850,7 +2990,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, @@ -2858,12 +2997,18 @@ mod tests { }; let params = ProbabilisticScoringFeeParameters { - liquidity_penalty_multiplier_msat: 1_000, - liquidity_penalty_amount_multiplier_msat: 0, - ..ProbabilisticScoringFeeParameters::zero_penalty() + liquidity_penalty_multiplier_msat: 1_000, + liquidity_penalty_amount_multiplier_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), 300); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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, @@ -2871,7 +3016,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] @@ -2879,7 +3024,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: u64::max_value(), inflight_htlc_msat: 0, @@ -2891,8 +3035,14 @@ mod tests { ..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 = 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] @@ -2905,17 +3055,22 @@ 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 channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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] @@ -2925,7 +3080,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 { @@ -2933,13 +3087,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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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] @@ -2964,15 +3124,21 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, }; + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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), 47); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 47); assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42), 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(&candidate, usage, ¶ms), 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), @@ -2985,7 +3151,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), 198); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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]))); @@ -3004,7 +3170,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), 47); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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), @@ -3017,16 +3183,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), 2048); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2048); usage.inflight_htlc_msat = 0; - assert_eq!(scorer.channel_penalty_msat(42, &source, &target, usage, ¶ms), 409); + assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 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(&candidate, usage, ¶ms), 2048); // Advance to decay all liquidity offsets to zero. SinceEpoch::advance(Duration::from_secs(60 * 60 * 10)); @@ -3046,7 +3212,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() @@ -3059,7 +3224,13 @@ 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 channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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 { @@ -3067,7 +3238,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 { @@ -3075,7 +3246,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 { @@ -3083,7 +3254,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] @@ -3104,7 +3275,13 @@ 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); + let channel = network_graph.read_only().channel(42).unwrap().to_owned(); + let (info, _) = channel.as_directed_from(&source).unwrap(); + let candidate: CandidateRouteHop = 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(); diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 7a9ce06910b..d4597448bd1 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -17,6 +17,8 @@ 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::routing::router::{CandidateRouteHop, RouteHintHop}; use crate::sign; use crate::events; use crate::events::bump_transaction::{WalletSource, Utxo}; @@ -139,10 +141,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, &()); + 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 = 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, &()); + 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 => continue, + }; + let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop { + info: channel.0, + short_channel_id: hop.short_channel_id, + }; + scorer.channel_penalty_msat(&candidate, usage, &()); } } } @@ -1165,8 +1191,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)) => { @@ -1266,4 +1296,4 @@ impl WalletSource for TestWalletSource { } Ok(tx) } -} +} \ No newline at end of file