X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=b33e021ab4fc30357a1124885c45b076419aed61;hb=5c89d019050a4b2dd68610d2e59d45acbfee5775;hp=5c92871007cf28a89b55fc1505105b56bbd3e85a;hpb=7f49f6bf4d838196ff7b20e78207b4bfdad264c6;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 5c928710..b33e021a 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256; use crate::blinded_path::{BlindedHop, BlindedPath}; use crate::ln::PaymentHash; use crate::ln::channelmanager::{ChannelDetails, PaymentId}; -use crate::ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures}; +use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, InvoiceFeatures, NodeFeatures}; use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT}; use crate::offers::invoice::BlindedPayInfo; use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees}; @@ -27,39 +27,43 @@ use crate::util::chacha20::ChaCha20; use crate::io; use crate::prelude::*; -use crate::sync::Mutex; +use crate::sync::{Mutex, MutexGuard}; use alloc::collections::BinaryHeap; use core::{cmp, fmt}; use core::ops::Deref; /// A [`Router`] implemented using [`find_route`]. -pub struct DefaultRouter>, L: Deref, S: Deref> where +pub struct DefaultRouter>, L: Deref, S: Deref, SP: Sized, Sc: Score> where L::Target: Logger, - S::Target: for <'a> LockableScore<'a>, + S::Target: for <'a> LockableScore<'a, Locked = MutexGuard<'a, Sc>>, { network_graph: G, logger: L, random_seed_bytes: Mutex<[u8; 32]>, - scorer: S + scorer: S, + score_params: SP } -impl>, L: Deref, S: Deref> DefaultRouter where +impl>, L: Deref, S: Deref, SP: Sized, Sc: Score> DefaultRouter where L::Target: Logger, - S::Target: for <'a> LockableScore<'a>, + S::Target: for <'a> LockableScore<'a, Locked = MutexGuard<'a, Sc>>, { /// Creates a new router. - pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S) -> Self { + pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: SP) -> Self { let random_seed_bytes = Mutex::new(random_seed_bytes); - Self { network_graph, logger, random_seed_bytes, scorer } + Self { network_graph, logger, random_seed_bytes, scorer, score_params } } } -impl>, L: Deref, S: Deref> Router for DefaultRouter where +impl< G: Deref>, L: Deref, S: Deref, SP: Sized, Sc: Score> Router for DefaultRouter where L::Target: Logger, - S::Target: for <'a> LockableScore<'a>, + S::Target: for <'a> LockableScore<'a, Locked = MutexGuard<'a, Sc>>, { fn find_route( - &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, + &self, + payer: &PublicKey, + params: &RouteParameters, + first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: &InFlightHtlcs ) -> Result { let random_seed_bytes = { @@ -67,10 +71,10 @@ impl>, L: Deref, S: Deref> Router for DefaultR *locked_random_seed_bytes = Sha256::hash(&*locked_random_seed_bytes).into_inner(); *locked_random_seed_bytes }; - find_route( payer, params, &self.network_graph, first_hops, &*self.logger, &ScorerAccountingForInFlightHtlcs::new(self.scorer.lock(), inflight_htlcs), + &self.score_params, &random_seed_bytes ) } @@ -122,7 +126,8 @@ impl<'a, S: Score> Writeable for ScorerAccountingForInFlightHtlcs<'a, S> { } impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> { - fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage) -> u64 { + type ScoreParams = S::ScoreParams; + fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 { if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( source, target, short_channel_id ) { @@ -131,9 +136,9 @@ impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> { ..usage }; - self.scorer.channel_penalty_msat(short_channel_id, source, target, usage) + self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params) } else { - self.scorer.channel_penalty_msat(short_channel_id, source, target, usage) + self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params) } } @@ -442,7 +447,7 @@ impl Writeable for RouteParameters { (2, self.final_value_msat, required), // LDK versions prior to 0.0.114 had the `final_cltv_expiry_delta` parameter in // `RouteParameters` directly. For compatibility, we write it here. - (4, self.payment_params.final_cltv_expiry_delta, required), + (4, self.payment_params.payee.final_cltv_expiry_delta(), option), }); Ok(()) } @@ -453,11 +458,13 @@ impl Readable for RouteParameters { _init_and_read_tlv_fields!(reader, { (0, payment_params, (required: ReadableArgs, 0)), (2, final_value_msat, required), - (4, final_cltv_expiry_delta, required), + (4, final_cltv_delta, option), }); let mut payment_params: PaymentParameters = payment_params.0.unwrap(); - if payment_params.final_cltv_expiry_delta == 0 { - payment_params.final_cltv_expiry_delta = final_cltv_expiry_delta.0.unwrap(); + if let Payee::Clear { ref mut final_cltv_expiry_delta, .. } = payment_params.payee { + if final_cltv_expiry_delta == &0 { + *final_cltv_expiry_delta = final_cltv_delta.ok_or(DecodeError::InvalidValue)?; + } } Ok(Self { payment_params, @@ -493,14 +500,6 @@ const MAX_PATH_LENGTH_ESTIMATE: u8 = 19; /// Information used to route a payment. #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct PaymentParameters { - /// Features supported by the payee. - /// - /// May be set from the payee's invoice or via [`for_keysend`]. May be `None` if the invoice - /// does not contain any features. - /// - /// [`for_keysend`]: Self::for_keysend - pub features: Option, - /// Information about the payee, such as their features and route hints for their channels. pub payee: Payee, @@ -534,9 +533,6 @@ pub struct PaymentParameters { /// payment to fail. Future attempts for the same payment shouldn't be relayed through any of /// these SCIDs. pub previously_failed_channels: Vec, - - /// The minimum CLTV delta at the end of the route. This value must not be zero. - pub final_cltv_expiry_delta: u32, } impl Writeable for PaymentParameters { @@ -545,19 +541,19 @@ impl Writeable for PaymentParameters { let mut blinded_hints = &vec![]; match &self.payee { Payee::Clear { route_hints, .. } => clear_hints = route_hints, - Payee::Blinded { route_hints } => blinded_hints = route_hints, + Payee::Blinded { route_hints, .. } => blinded_hints = route_hints, } write_tlv_fields!(writer, { (0, self.payee.node_id(), option), (1, self.max_total_cltv_expiry_delta, required), - (2, self.features, option), + (2, self.payee.features(), option), (3, self.max_path_count, required), (4, *clear_hints, vec_type), (5, self.max_channel_saturation_power_of_half, required), (6, self.expiry_time, option), (7, self.previously_failed_channels, vec_type), (8, *blinded_hints, optional_vec), - (9, self.final_cltv_expiry_delta, required), + (9, self.payee.final_cltv_expiry_delta(), option), }); Ok(()) } @@ -568,7 +564,7 @@ impl ReadableArgs for PaymentParameters { _init_and_read_tlv_fields!(reader, { (0, payee_pubkey, option), (1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)), - (2, features, option), + (2, features, (option: ReadableArgs, payee_pubkey.is_some())), (3, max_path_count, (default_value, DEFAULT_MAX_PATH_COUNT)), (4, route_hints, vec_type), (5, max_channel_saturation_power_of_half, (default_value, 2)), @@ -581,22 +577,25 @@ impl ReadableArgs for PaymentParameters { let blinded_route_hints = blinded_route_hints.unwrap_or(vec![]); let payee = if blinded_route_hints.len() != 0 { if clear_route_hints.len() != 0 || payee_pubkey.is_some() { return Err(DecodeError::InvalidValue) } - Payee::Blinded { route_hints: blinded_route_hints } + Payee::Blinded { + route_hints: blinded_route_hints, + features: features.and_then(|f: Features| f.bolt12()), + } } else { Payee::Clear { route_hints: clear_route_hints, node_id: payee_pubkey.ok_or(DecodeError::InvalidValue)?, + features: features.and_then(|f| f.bolt11()), + final_cltv_expiry_delta: final_cltv_expiry_delta.0.unwrap(), } }; Ok(Self { max_total_cltv_expiry_delta: _init_tlv_based_struct_field!(max_total_cltv_expiry_delta, (default_value, unused)), - features, max_path_count: _init_tlv_based_struct_field!(max_path_count, (default_value, unused)), payee, max_channel_saturation_power_of_half: _init_tlv_based_struct_field!(max_channel_saturation_power_of_half, (default_value, unused)), expiry_time, previously_failed_channels: previously_failed_channels.unwrap_or(Vec::new()), - final_cltv_expiry_delta: _init_tlv_based_struct_field!(final_cltv_expiry_delta, (default_value, unused)), }) } } @@ -609,14 +608,12 @@ impl PaymentParameters { /// provided. pub fn from_node_id(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32) -> Self { Self { - features: None, - payee: Payee::Clear { node_id: payee_pubkey, route_hints: vec![] }, + payee: Payee::Clear { node_id: payee_pubkey, route_hints: vec![], features: None, final_cltv_expiry_delta }, expiry_time: None, max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, max_path_count: DEFAULT_MAX_PATH_COUNT, max_channel_saturation_power_of_half: 2, previously_failed_channels: Vec::new(), - final_cltv_expiry_delta, } } @@ -625,14 +622,23 @@ impl PaymentParameters { /// The `final_cltv_expiry_delta` should match the expected final CLTV delta the recipient has /// provided. pub fn for_keysend(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32) -> Self { - Self::from_node_id(payee_pubkey, final_cltv_expiry_delta).with_features(InvoiceFeatures::for_keysend()) + Self::from_node_id(payee_pubkey, final_cltv_expiry_delta).with_bolt11_features(InvoiceFeatures::for_keysend()).expect("PaymentParameters::from_node_id should always initialize the payee as unblinded") } - /// Includes the payee's features. + /// Includes the payee's features. Errors if the parameters were initialized with blinded payment + /// paths. /// /// This is not exported to bindings users since bindings don't support move semantics - pub fn with_features(self, features: InvoiceFeatures) -> Self { - Self { features: Some(features), ..self } + pub fn with_bolt11_features(self, features: InvoiceFeatures) -> Result { + match self.payee { + Payee::Blinded { .. } => Err(()), + Payee::Clear { route_hints, node_id, final_cltv_expiry_delta, .. } => + Ok(Self { + payee: Payee::Clear { + route_hints, node_id, features: Some(features), final_cltv_expiry_delta + }, ..self + }) + } } /// Includes hints for routing to the payee. Errors if the parameters were initialized with @@ -642,8 +648,12 @@ impl PaymentParameters { pub fn with_route_hints(self, route_hints: Vec) -> Result { match self.payee { Payee::Blinded { .. } => Err(()), - Payee::Clear { node_id, .. } => - Ok(Self { payee: Payee::Clear { route_hints, node_id }, ..self }) + Payee::Clear { node_id, features, final_cltv_expiry_delta, .. } => + Ok(Self { + payee: Payee::Clear { + route_hints, node_id, features, final_cltv_expiry_delta, + }, ..self + }) } } @@ -686,6 +696,11 @@ pub enum Payee { /// Aggregated routing info and blinded paths, for routing to the payee without knowing their /// node id. route_hints: Vec<(BlindedPayInfo, BlindedPath)>, + /// Features supported by the payee. + /// + /// May be set from the payee's invoice. May be `None` if the invoice does not contain any + /// features. + features: Option, }, /// The recipient included these route hints in their BOLT11 invoice. Clear { @@ -693,6 +708,15 @@ pub enum Payee { node_id: PublicKey, /// Hints for routing to the payee, containing channels connecting the payee to public nodes. route_hints: Vec, + /// Features supported by the payee. + /// + /// May be set from the payee's invoice or via [`for_keysend`]. May be `None` if the invoice + /// does not contain any features. + /// + /// [`for_keysend`]: PaymentParameters::for_keysend + features: Option, + /// The minimum CLTV delta at the end of the route. This value must not be zero. + final_cltv_expiry_delta: u32, }, } @@ -703,10 +727,74 @@ impl Payee { _ => None, } } + fn node_features(&self) -> Option { + match self { + Self::Clear { features, .. } => features.as_ref().map(|f| f.to_context()), + Self::Blinded { features, .. } => features.as_ref().map(|f| f.to_context()), + } + } + fn supports_basic_mpp(&self) -> bool { + match self { + Self::Clear { features, .. } => features.as_ref().map_or(false, |f| f.supports_basic_mpp()), + Self::Blinded { features, .. } => features.as_ref().map_or(false, |f| f.supports_basic_mpp()), + } + } + fn features(&self) -> Option { + match self { + Self::Clear { features, .. } => features.as_ref().map(|f| FeaturesRef::Bolt11(f)), + Self::Blinded { features, .. } => features.as_ref().map(|f| FeaturesRef::Bolt12(f)), + } + } + fn final_cltv_expiry_delta(&self) -> Option { + match self { + Self::Clear { final_cltv_expiry_delta, .. } => Some(*final_cltv_expiry_delta), + _ => None, + } + } +} + +enum FeaturesRef<'a> { + Bolt11(&'a InvoiceFeatures), + Bolt12(&'a Bolt12InvoiceFeatures), +} +enum Features { + Bolt11(InvoiceFeatures), + Bolt12(Bolt12InvoiceFeatures), +} + +impl Features { + fn bolt12(self) -> Option { + match self { + Self::Bolt12(f) => Some(f), + _ => None, + } + } + fn bolt11(self) -> Option { + match self { + Self::Bolt11(f) => Some(f), + _ => None, + } + } +} + +impl<'a> Writeable for FeaturesRef<'a> { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + match self { + Self::Bolt11(f) => Ok(f.write(w)?), + Self::Bolt12(f) => Ok(f.write(w)?), + } + } +} + +impl ReadableArgs for Features { + fn read(reader: &mut R, bolt11: bool) -> Result { + if bolt11 { return Ok(Self::Bolt11(Readable::read(reader)?)) } + Ok(Self::Bolt12(Readable::read(reader)?)) + } } /// A list of hops along a payment path terminating with a channel to the recipient. -#[derive(Clone, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] pub struct RouteHint(pub Vec); impl Writeable for RouteHint { @@ -731,7 +819,7 @@ impl Readable for RouteHint { } /// A channel descriptor for a hop along a payment path. -#[derive(Clone, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] pub struct RouteHintHop { /// The node_id of the non-target end of the route pub src_node_id: PublicKey, @@ -1136,12 +1224,12 @@ impl fmt::Display for LoggedPayeePubkey { pub fn find_route( our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &NetworkGraph, first_hops: Option<&[&ChannelDetails]>, logger: L, - scorer: &S, random_seed_bytes: &[u8; 32] + scorer: &S, score_params: &S::ScoreParams, random_seed_bytes: &[u8; 32] ) -> Result where L::Target: Logger, GL::Target: Logger { let graph_lock = network_graph.read_only(); let mut route = get_route(our_node_pubkey, &route_params.payment_params, &graph_lock, first_hops, - route_params.final_value_msat, logger, scorer, + route_params.final_value_msat, logger, scorer, score_params, random_seed_bytes)?; add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes); Ok(route) @@ -1149,7 +1237,7 @@ where L::Target: Logger, GL::Target: Logger { pub(crate) fn get_route( our_node_pubkey: &PublicKey, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph, - first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, logger: L, scorer: &S, + first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, logger: L, scorer: &S, score_params: &S::ScoreParams, _random_seed_bytes: &[u8; 32] ) -> Result where L::Target: Logger { @@ -1175,7 +1263,7 @@ where L::Target: Logger { } match &payment_params.payee { - Payee::Clear { route_hints, node_id } => { + Payee::Clear { route_hints, node_id, .. } => { for route in route_hints.iter() { for hop in &route.0 { if hop.src_node_id == *node_id { @@ -1187,7 +1275,8 @@ where L::Target: Logger { _ => return Err(LightningError{err: "Routing to blinded paths isn't supported yet".to_owned(), action: ErrorAction::IgnoreError}), } - if payment_params.max_total_cltv_expiry_delta <= payment_params.final_cltv_expiry_delta { + let final_cltv_expiry_delta = payment_params.payee.final_cltv_expiry_delta().unwrap_or(0); + if payment_params.max_total_cltv_expiry_delta <= final_cltv_expiry_delta { return Err(LightningError{err: "Can't find a route where the maximum total CLTV expiry delta is below the final CLTV expiry.".to_owned(), action: ErrorAction::IgnoreError}); } @@ -1259,8 +1348,8 @@ where L::Target: Logger { // work reliably. let allow_mpp = if payment_params.max_path_count == 1 { false - } else if let Some(features) = &payment_params.features { - features.supports_basic_mpp() + } else if payment_params.payee.supports_basic_mpp() { + true } else if let Some(payee) = payee_node_id_opt { network_nodes.get(&payee).map_or(false, |node| node.announcement_info.as_ref().map_or(false, |info| info.features.supports_basic_mpp())) @@ -1418,9 +1507,9 @@ where L::Target: Logger { // In order to already account for some of the privacy enhancing random CLTV // expiry delta offset we add on top later, we subtract a rough estimate // (2*MEDIAN_HOP_CLTV_EXPIRY_DELTA) here. - let max_total_cltv_expiry_delta = (payment_params.max_total_cltv_expiry_delta - payment_params.final_cltv_expiry_delta) + let max_total_cltv_expiry_delta = (payment_params.max_total_cltv_expiry_delta - final_cltv_expiry_delta) .checked_sub(2*MEDIAN_HOP_CLTV_EXPIRY_DELTA) - .unwrap_or(payment_params.max_total_cltv_expiry_delta - payment_params.final_cltv_expiry_delta); + .unwrap_or(payment_params.max_total_cltv_expiry_delta - final_cltv_expiry_delta); let hop_total_cltv_delta = ($next_hops_cltv_delta as u32) .saturating_add($candidate.cltv_expiry_delta()); let exceeds_cltv_delta_limit = hop_total_cltv_delta > max_total_cltv_expiry_delta; @@ -1514,7 +1603,7 @@ where L::Target: Logger { effective_capacity, }; let channel_penalty_msat = scorer.channel_penalty_msat( - short_channel_id, &$src_node_id, &$dest_node_id, channel_usage + short_channel_id, &$src_node_id, &$dest_node_id, channel_usage, score_params ); let path_penalty_msat = $next_hops_path_penalty_msat .saturating_add(channel_penalty_msat); @@ -1762,7 +1851,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 + hop.short_channel_id, &source, &target, channel_usage, score_params ); aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat .saturating_add(channel_penalty_msat); @@ -2110,7 +2199,7 @@ where L::Target: Logger { }).collect::>(); // Propagate the cltv_expiry_delta one hop backwards since the delta from the current hop is // applicable for the previous hop. - path.iter_mut().rev().fold(payment_params.final_cltv_expiry_delta, |prev_cltv_expiry_delta, hop| { + path.iter_mut().rev().fold(final_cltv_expiry_delta, |prev_cltv_expiry_delta, hop| { core::mem::replace(&mut hop.as_mut().unwrap().cltv_expiry_delta, prev_cltv_expiry_delta) }); selected_paths.push(path); @@ -2118,10 +2207,10 @@ where L::Target: Logger { // Make sure we would never create a route with more paths than we allow. debug_assert!(selected_paths.len() <= payment_params.max_path_count.into()); - if let Some(features) = &payment_params.features { + if let Some(node_features) = payment_params.payee.node_features() { for path in selected_paths.iter_mut() { if let Ok(route_hop) = path.last_mut().unwrap() { - route_hop.node_features = features.to_context(); + route_hop.node_features = node_features.clone(); } } } @@ -2259,8 +2348,9 @@ fn build_route_from_hops_internal( } impl Score for HopScorer { + type ScoreParams = (); fn channel_penalty_msat(&self, _short_channel_id: u64, source: &NodeId, target: &NodeId, - _usage: ChannelUsage) -> u64 + _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 { let mut cur_id = self.our_node_id; for i in 0..self.hop_ids.len() { @@ -2305,7 +2395,7 @@ fn build_route_from_hops_internal( let scorer = HopScorer { our_node_id, hop_ids }; get_route(our_node_pubkey, payment_params, network_graph, None, final_value_msat, - logger, &scorer, random_seed_bytes) + logger, &scorer, &(), random_seed_bytes) } #[cfg(test)] @@ -2316,10 +2406,10 @@ mod tests { 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}; - use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters}; + use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, 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; - use crate::chain::keysinterface::EntropySource; + use crate::sign::EntropySource; use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT}; use crate::ln::channelmanager; @@ -2395,11 +2485,11 @@ mod tests { // Simple route to 2 via 1 - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 0, Arc::clone(&logger), &scorer, &random_seed_bytes) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 0, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Cannot send a payment of 0 msat"); } else { panic!(); } - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -2431,11 +2521,11 @@ mod tests { let our_chans = vec![get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)]; if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = - get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { + get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "First hop cannot have our_node_pubkey as a destination."); } else { panic!(); } - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); } @@ -2543,7 +2633,7 @@ mod tests { }); // Not possible to send 199_999_999, because the minimum on channel=2 is 200_000_000. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &random_seed_bytes) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a path to the given destination"); } else { panic!(); } @@ -2562,7 +2652,7 @@ mod tests { }); // A payment above the minimum should pass - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); } @@ -2571,7 +2661,7 @@ mod tests { let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); let scorer = ln_test_utils::TestScorer::new(); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); @@ -2644,7 +2734,7 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); // Overpay fees to hit htlc_minimum_msat. let overpaid_fees = route.paths[0].hops[0].fee_msat + route.paths[1].hops[0].fee_msat; // TODO: this could be better balanced to overpay 10k and not 15k. @@ -2689,14 +2779,14 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); // Fine to overpay for htlc_minimum_msat if it allows us to save fee. assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops[0].short_channel_id, 12); let fees = route.paths[0].hops[0].fee_msat; assert_eq!(fees, 5_000); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); // Not fine to overpay for htlc_minimum_msat if it requires paying more than fee on // the other channel. assert_eq!(route.paths.len(), 1); @@ -2741,13 +2831,13 @@ mod tests { }); // If all the channels require some features we don't understand, route should fail - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a path to the given destination"); } else { panic!(); } // If we specify a channel to node7, that overrides our local channel view and that gets used let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); @@ -2782,13 +2872,13 @@ mod tests { add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], unknown_features.clone(), 1); // If all nodes require some features we don't understand, route should fail - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a path to the given destination"); } else { panic!(); } // If we specify a channel to node7, that overrides our local channel view and that gets used let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); @@ -2820,7 +2910,7 @@ mod tests { // Route to 1 via 2 and 3 because our channel to 1 is disabled let payment_params = PaymentParameters::from_node_id(nodes[0], 42); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 3); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -2847,7 +2937,7 @@ mod tests { // If we specify a channel to node7, that overrides our local channel view and that gets used let payment_params = PaymentParameters::from_node_id(nodes[2], 42); let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); @@ -2970,13 +3060,13 @@ mod tests { invalid_last_hops.push(invalid_last_hop); { let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(invalid_last_hops).unwrap(); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Route hint cannot have the payee as the source."); } else { panic!(); } } let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap(); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3052,7 +3142,7 @@ mod tests { // Test handling of an empty RouteHint passed in Invoice. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3158,7 +3248,7 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3230,7 +3320,7 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &[42u8; 32]).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &[42u8; 32]).unwrap(); assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3312,7 +3402,7 @@ mod tests { // This test shows that public routes can be present in the invoice // which would be handled in the same manner. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3365,7 +3455,7 @@ mod tests { let our_chans = vec![get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; let mut last_hops = last_hops(&nodes); let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap(); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[3]); @@ -3386,7 +3476,7 @@ mod tests { // Revert to via 6 as the fee on 8 goes up let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops).unwrap(); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3420,7 +3510,7 @@ mod tests { assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly // ...but still use 8 for larger payments as 6 has a variable feerate - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 2000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 2000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3486,7 +3576,7 @@ mod tests { let logger = ln_test_utils::TestLogger::new(); let network_graph = NetworkGraph::new(Network::Testnet, &logger); let route = get_route(&source_node_id, &payment_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), route_val, &logger, &scorer, &random_seed_bytes); + Some(&our_chans.iter().collect::>()), route_val, &logger, &scorer, &(), &random_seed_bytes); route } @@ -3544,7 +3634,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); // We will use a simple single-path route from // our node to node2 via node0: channels {1, 3}. @@ -3608,14 +3698,14 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 250_000_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 250_000_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route an exact amount we have should be fine. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 250_000_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 250_000_000, Arc::clone(&logger), &scorer, &(),&random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -3644,14 +3734,14 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 200_000_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 200_000_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route an exact amount we have should be fine. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 200_000_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), 200_000_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -3691,14 +3781,14 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route an exact amount we have should be fine. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -3762,14 +3852,14 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route an exact amount we have should be fine. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -3794,14 +3884,14 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 10_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 10_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route an exact amount we have should be fine. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -3820,7 +3910,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. // {12, 13, 11} have the capacities of 100, {6} has a capacity of 50. @@ -3906,14 +3996,14 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route 49 sats (just a bit below the capacity). - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 49_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 49_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3926,7 +4016,7 @@ mod tests { { // Attempt to route an exact amount is also fine - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3974,7 +4064,7 @@ mod tests { }); { - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3995,7 +4085,7 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); let payment_params = PaymentParameters::from_node_id(nodes[2], 42) - .with_features(channelmanager::provided_invoice_features(&config)); + .with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); // We need a route consisting of 3 paths: // From our node to node2 via node0, node7, node1 (three paths one hop each). @@ -4089,7 +4179,7 @@ mod tests { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( &our_id, &payment_params, &network_graph.read_only(), None, 300_000, - Arc::clone(&logger), &scorer, &random_seed_bytes) { + Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -4099,7 +4189,7 @@ mod tests { let zero_payment_params = payment_params.clone().with_max_path_count(0); if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( &our_id, &zero_payment_params, &network_graph.read_only(), None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes) { + Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Can't find a route with no paths allowed."); } else { panic!(); } } @@ -4111,7 +4201,7 @@ mod tests { let fail_payment_params = payment_params.clone().with_max_path_count(3); if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( &our_id, &fail_payment_params, &network_graph.read_only(), None, 250_000, - Arc::clone(&logger), &scorer, &random_seed_bytes) { + Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -4120,7 +4210,7 @@ mod tests { // Now, attempt to route 250 sats (just a bit below the capacity). // Our algorithm should provide us with these 3 paths. let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, - 250_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + 250_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -4134,7 +4224,7 @@ mod tests { { // Attempt to route an exact amount is also fine let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, - 290_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + 290_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -4154,7 +4244,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); // We need a route consisting of 3 paths: // From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}. @@ -4290,7 +4380,7 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 350_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 350_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -4298,7 +4388,7 @@ mod tests { { // Now, attempt to route 300 sats (exact amount we can route). // Our algorithm should provide us with these 3 paths, 100 sats each. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 300_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 300_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; @@ -4319,7 +4409,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); // This test checks that if we have two cheaper paths and one more expensive path, // so that liquidity-wise any 2 of 3 combination is sufficient, @@ -4459,7 +4549,7 @@ mod tests { { // Now, attempt to route 180 sats. // Our algorithm should provide us with these 2 paths. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 180_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 180_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_value_transferred_msat = 0; @@ -4489,7 +4579,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); // We need a route consisting of 2 paths: // From our node to node3 via {node0, node2} and {node7, node2, node4}. @@ -4630,14 +4720,14 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 210_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 210_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route 200 sats (exact amount we can route). - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 200_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 200_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; @@ -4671,7 +4761,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap(), 42).with_features(channelmanager::provided_invoice_features(&config)) + let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap(), 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap() .with_route_hints(vec![RouteHint(vec![RouteHintHop { src_node_id: nodes[2], short_channel_id: 42, @@ -4737,7 +4827,7 @@ mod tests { // Get a route for 100 sats and check that we found the MPP route no problem and didn't // overpay at all. - let mut route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let mut route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); route.paths.sort_by_key(|path| path.hops[0].short_channel_id); // Paths are manually ordered ordered by SCID, so: @@ -4763,7 +4853,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config)) + let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap() .with_max_channel_saturation_power_of_half(0); // We need a route consisting of 3 paths: @@ -4856,7 +4946,7 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 150_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { + &our_id, &payment_params, &network_graph.read_only(), None, 150_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -4864,7 +4954,7 @@ mod tests { { // Now, attempt to route 125 sats (just a bit below the capacity of 3 channels). // Our algorithm should provide us with these 3 paths. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 125_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 125_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -4877,7 +4967,7 @@ mod tests { { // Attempt to route without the last small cheap channel - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -5016,7 +5106,7 @@ mod tests { { // Now ensure the route flows simply over nodes 1 and 4 to 6. - let route = get_route(&our_id, &payment_params, &network.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 3); @@ -5087,7 +5177,7 @@ mod tests { { // Now, attempt to route 90 sats, which is exactly 90 sats at the last hop, plus the // 200% fee charged channel 13 in the 1-to-2 direction. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 2); @@ -5119,7 +5209,7 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); // We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2 // gets an htlc_maximum_msat of 80_000 and channel 4 an htlc_minimum_msat of 90_000. We @@ -5153,7 +5243,7 @@ mod tests { // Now, attempt to route 90 sats, hitting the htlc_minimum on channel 4, but // overshooting the htlc_maximum on channel 2. Thus, we should pick the (absurdly // expensive) channels 12-13 path. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 2); @@ -5187,7 +5277,7 @@ mod tests { let network_graph = NetworkGraph::new(Network::Testnet, Arc::clone(&logger)); let scorer = ln_test_utils::TestScorer::new(); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[0], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[0], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); @@ -5195,7 +5285,7 @@ mod tests { let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[ &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000), &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000), - ]), 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 1); @@ -5207,7 +5297,7 @@ mod tests { let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[ &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000), - ]), 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); assert_eq!(route.paths[0].hops.len(), 1); assert_eq!(route.paths[1].hops.len(), 1); @@ -5239,7 +5329,7 @@ mod tests { &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000), - ]), 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 1); @@ -5261,7 +5351,7 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); let route = get_route( &our_id, &payment_params, &network_graph.read_only(), None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes + Arc::clone(&logger), &scorer, &(), &random_seed_bytes ).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -5274,7 +5364,7 @@ mod tests { let scorer = FixedPenaltyScorer::with_penalty(100); let route = get_route( &our_id, &payment_params, &network_graph.read_only(), None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes + Arc::clone(&logger), &scorer, &(), &random_seed_bytes ).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -5292,7 +5382,8 @@ mod tests { fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } } impl Score for BadChannelScorer { - fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage) -> u64 { + 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 } } @@ -5312,7 +5403,8 @@ mod tests { } impl Score for BadNodeScorer { - fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage) -> u64 { + 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 } } @@ -5335,7 +5427,7 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); let route = get_route( &our_id, &payment_params, &network_graph, None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes + Arc::clone(&logger), &scorer, &(), &random_seed_bytes ).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -5347,7 +5439,7 @@ mod tests { let scorer = BadChannelScorer { short_channel_id: 6 }; let route = get_route( &our_id, &payment_params, &network_graph, None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes + Arc::clone(&logger), &scorer, &(), &random_seed_bytes ).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); @@ -5359,7 +5451,7 @@ mod tests { let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) }; match get_route( &our_id, &payment_params, &network_graph, None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes + Arc::clone(&logger), &scorer, &(), &random_seed_bytes ) { Err(LightningError { err, .. } ) => { assert_eq!(err, "Failed to find a path to the given destination"); @@ -5453,7 +5545,7 @@ mod tests { .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert_ne!(path.len(), 0); @@ -5461,7 +5553,7 @@ mod tests { let fail_max_total_cltv_delta = 23; let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap() .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta); - match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) + match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { Err(LightningError { err, .. } ) => { assert_eq!(err, "Failed to find a path to the given destination"); @@ -5486,9 +5578,9 @@ mod tests { // We should be able to find a route initially, and then after we fail a few random // channels eventually we won't be able to any longer. - assert!(get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).is_ok()); + assert!(get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).is_ok()); loop { - if let Ok(route) = get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { + if let Ok(route) = get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { for chan in route.paths[0].hops.iter() { assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id)); } @@ -5512,14 +5604,14 @@ mod tests { // First check we can actually create a long route on this graph. let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0); let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into()); // But we can't create a path surpassing the MAX_PATH_LENGTH_ESTIMATE limit. let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0); match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes) + Arc::clone(&logger), &scorer, &(), &random_seed_bytes) { Err(LightningError { err, .. } ) => { assert_eq!(err, "Failed to find a path to the given destination"); @@ -5538,7 +5630,7 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap(); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); let cltv_expiry_deltas_before = route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::>(); @@ -5573,7 +5665,7 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); let mut route = get_route(&our_id, &payment_params, &network_graph, None, 100, - Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap(); add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes); let mut path_plausibility = vec![]; @@ -5650,8 +5742,8 @@ mod tests { fn avoids_saturating_channels() { let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph(); let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - - let scorer = ProbabilisticScorer::new(Default::default(), &*network_graph, Arc::clone(&logger)); + let decay_params = ProbabilisticScoringDecayParameters::default(); + let scorer = ProbabilisticScorer::new(decay_params, &*network_graph, Arc::clone(&logger)); // Set the fee on channel 13 to 100% to match channel 4 giving us two equivalent paths (us // -> node 7 -> node2 and us -> node 1 -> node 2) which we should balance over. @@ -5681,11 +5773,11 @@ mod tests { }); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); // 100,000 sats is less than the available liquidity on each channel, set above. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000_000, Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 2); assert!((route.paths[0].hops[1].short_channel_id == 4 && route.paths[1].hops[1].short_channel_id == 13) || (route.paths[1].hops[1].short_channel_id == 4 && route.paths[0].hops[1].short_channel_id == 13)); @@ -5705,7 +5797,7 @@ mod tests { #[test] #[cfg(not(feature = "no-std"))] fn generate_routes() { - use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters}; + use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters}; let mut d = match super::bench_utils::get_route_file() { Ok(f) => f, @@ -5730,9 +5822,9 @@ mod tests { let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); let payment_params = PaymentParameters::from_node_id(dst, 42); let amt = seed as u64 % 200_000_000; - let params = ProbabilisticScoringParameters::default(); - let scorer = ProbabilisticScorer::new(params, &graph, &logger); - if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &random_seed_bytes).is_ok() { + let params = ProbabilisticScoringFeeParameters::default(); + let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger); + if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, ¶ms, &random_seed_bytes).is_ok() { continue 'load_endpoints; } } @@ -5742,7 +5834,7 @@ mod tests { #[test] #[cfg(not(feature = "no-std"))] fn generate_routes_mpp() { - use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters}; + use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters}; let mut d = match super::bench_utils::get_route_file() { Ok(f) => f, @@ -5766,11 +5858,11 @@ mod tests { let src = &PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); seed = seed.overflowing_mul(0xdeadbeef).0; let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); - let payment_params = PaymentParameters::from_node_id(dst, 42).with_features(channelmanager::provided_invoice_features(&config)); + let payment_params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); let amt = seed as u64 % 200_000_000; - let params = ProbabilisticScoringParameters::default(); - let scorer = ProbabilisticScorer::new(params, &graph, &logger); - if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &random_seed_bytes).is_ok() { + let params = ProbabilisticScoringFeeParameters::default(); + let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger); + if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, ¶ms, &random_seed_bytes).is_ok() { continue 'load_endpoints; } } @@ -5785,8 +5877,8 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let scorer_params = ProbabilisticScoringParameters::default(); - let mut scorer = ProbabilisticScorer::new(scorer_params, Arc::clone(&network_graph), Arc::clone(&logger)); + let mut scorer_params = ProbabilisticScoringFeeParameters::default(); + let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger)); // First check set manual penalties are returned by the scorer. let usage = ChannelUsage { @@ -5794,23 +5886,23 @@ mod tests { inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, }; - scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123); - scorer.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), 456); + 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); // 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, &random_seed_bytes); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), 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.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, &random_seed_bytes); + 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); assert!(route.is_err()); // Finally make sure we can route again, when we remove the ban. - scorer.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, &random_seed_bytes); + 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); assert!(route.is_ok()); } @@ -5993,11 +6085,11 @@ mod benches { use bitcoin::hashes::Hash; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use crate::chain::transaction::OutPoint; - use crate::chain::keysinterface::{EntropySource, KeysManager}; + use crate::sign::{EntropySource, KeysManager}; use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails}; use crate::ln::features::InvoiceFeatures; use crate::routing::gossip::NetworkGraph; - use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters}; + use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters}; use crate::util::config::UserConfig; use crate::util::logger::{Logger, Record}; use crate::util::ser::ReadableArgs; @@ -6064,7 +6156,7 @@ mod benches { let logger = DummyLogger {}; let network_graph = read_network_graph(&logger); let scorer = FixedPenaltyScorer::with_penalty(0); - generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty()); + generate_routes(bench, &network_graph, scorer, &(), InvoiceFeatures::empty()); } #[bench] @@ -6072,29 +6164,29 @@ mod benches { let logger = DummyLogger {}; let network_graph = read_network_graph(&logger); let scorer = FixedPenaltyScorer::with_penalty(0); - generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default())); + generate_routes(bench, &network_graph, scorer, &(), channelmanager::provided_invoice_features(&UserConfig::default())); } #[bench] fn generate_routes_with_probabilistic_scorer(bench: &mut Bencher) { let logger = DummyLogger {}; let network_graph = read_network_graph(&logger); - let params = ProbabilisticScoringParameters::default(); - let scorer = ProbabilisticScorer::new(params, &network_graph, &logger); - generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty()); + let params = ProbabilisticScoringFeeParameters::default(); + let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + generate_routes(bench, &network_graph, scorer, ¶ms, InvoiceFeatures::empty()); } #[bench] fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) { let logger = DummyLogger {}; let network_graph = read_network_graph(&logger); - let params = ProbabilisticScoringParameters::default(); - let scorer = ProbabilisticScorer::new(params, &network_graph, &logger); - generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default())); + let params = ProbabilisticScoringFeeParameters::default(); + let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + generate_routes(bench, &network_graph, scorer, ¶ms, channelmanager::provided_invoice_features(&UserConfig::default())); } fn generate_routes( - bench: &mut Bencher, graph: &NetworkGraph<&DummyLogger>, mut scorer: S, + bench: &mut Bencher, graph: &NetworkGraph<&DummyLogger>, mut scorer: S, score_params: &S::ScoreParams, features: InvoiceFeatures ) { let nodes = graph.read_only().nodes().clone(); @@ -6112,10 +6204,10 @@ mod benches { let src = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); seed *= 0xdeadbeef; let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); - let params = PaymentParameters::from_node_id(dst, 42).with_features(features.clone()); + let params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(features.clone()).unwrap(); let first_hop = first_hop(src); let amt = seed as u64 % 1_000_000; - if let Ok(route) = get_route(&payer, ¶ms, &graph.read_only(), Some(&[&first_hop]), amt, &DummyLogger{}, &scorer, &random_seed_bytes) { + if let Ok(route) = get_route(&payer, ¶ms, &graph.read_only(), Some(&[&first_hop]), amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes) { routes.push(route); route_endpoints.push((first_hop, params, amt)); continue 'load_endpoints; @@ -6142,7 +6234,7 @@ mod benches { // selected destinations, possibly causing us to fail because, eg, the newly-selected path // requires a too-high CLTV delta. route_endpoints.retain(|(first_hop, params, amt)| { - get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, &random_seed_bytes).is_ok() + get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok() }); route_endpoints.truncate(100); assert_eq!(route_endpoints.len(), 100); @@ -6151,7 +6243,7 @@ mod benches { let mut idx = 0; bench.iter(|| { let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()]; - assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, &random_seed_bytes).is_ok()); + assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok()); idx += 1; }); }