X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=633775bfe630032338a551f4bfd64ce9388f3af0;hb=094ddb264bbb2d71d84822033f2a5e83a5f7f60b;hp=9f48d4cb8cd7dce1b90c0c5417df29c86a9fa8b1;hpb=b5be4c210c804488c18a0f5fe912728fdede6984;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 9f48d4cb..633775bf 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -70,19 +70,34 @@ pub struct Route { /// given path is variable, keeping the length of any path to less than 20 should currently /// ensure it is viable. pub paths: Vec>, + /// The `payee` parameter passed to [`find_route`]. + /// This is used by `ChannelManager` to track information which may be required for retries, + /// provided back to you via [`Event::PaymentPathFailed`]. + /// + /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed + pub payee: Option, +} + +pub(crate) trait RoutePath { + /// Gets the fees for a given path, excluding any excess paid to the recipient. + fn get_path_fees(&self) -> u64; +} +impl RoutePath for Vec { + fn get_path_fees(&self) -> u64 { + // Do not count last hop of each path since that's the full value of the payment + self.split_last().map(|(_, path_prefix)| path_prefix).unwrap_or(&[]) + .iter().map(|hop| &hop.fee_msat) + .sum() + } } impl Route { /// Returns the total amount of fees paid on this [`Route`]. /// /// This doesn't include any extra payment made to the recipient, which can happen in excess of - /// the amount passed to [`get_route`]'s `final_value_msat`. + /// the amount passed to [`find_route`]'s `params.final_value_msat`. pub fn get_total_fees(&self) -> u64 { - // Do not count last hop of each path since that's the full value of the payment - return self.paths.iter() - .flat_map(|path| path.split_last().map(|(_, path_prefix)| path_prefix).unwrap_or(&[])) - .map(|hop| &hop.fee_msat) - .sum(); + self.paths.iter().map(|path| path.get_path_fees()).sum() } /// Returns the total amount paid on this [`Route`], excluding the fees. @@ -106,7 +121,9 @@ impl Writeable for Route { hop.write(writer)?; } } - write_tlv_fields!(writer, {}); + write_tlv_fields!(writer, { + (1, self.payee, option), + }); Ok(()) } } @@ -124,15 +141,43 @@ impl Readable for Route { } paths.push(hops); } - read_tlv_fields!(reader, {}); - Ok(Route { paths }) + let mut payee = None; + read_tlv_fields!(reader, { + (1, payee, option), + }); + Ok(Route { paths, payee }) } } +/// Parameters needed to find a [`Route`] for paying a [`Payee`]. +/// +/// Passed to [`find_route`] and also provided in [`Event::PaymentPathFailed`] for retrying a failed +/// payment path. +/// +/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed +#[derive(Clone, Debug)] +pub struct RouteParameters { + /// The recipient of the failed payment path. + pub payee: Payee, + + /// The amount in msats sent on the failed payment path. + pub final_value_msat: u64, + + /// The CLTV on the final hop of the failed payment path. + pub final_cltv_expiry_delta: u32, +} + +impl_writeable_tlv_based!(RouteParameters, { + (0, payee, required), + (2, final_value_msat, required), + (4, final_cltv_expiry_delta, required), +}); + /// The recipient of a payment. +#[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct Payee { /// The node id of the payee. - pubkey: PublicKey, + pub pubkey: PublicKey, /// Features supported by the payee. /// @@ -144,8 +189,18 @@ pub struct Payee { /// Hints for routing to the payee, containing channels connecting the payee to public nodes. pub route_hints: Vec, + + /// Expiration of a payment to the payee, in seconds relative to the UNIX epoch. + pub expiry_time: Option, } +impl_writeable_tlv_based!(Payee, { + (0, pubkey, required), + (2, features, option), + (4, route_hints, vec_type), + (6, expiry_time, option), +}); + impl Payee { /// Creates a payee with the node id of the given `pubkey`. pub fn new(pubkey: PublicKey) -> Self { @@ -153,6 +208,7 @@ impl Payee { pubkey, features: None, route_hints: vec![], + expiry_time: None, } } @@ -174,12 +230,39 @@ impl Payee { pub fn with_route_hints(self, route_hints: Vec) -> Self { Self { route_hints, ..self } } + + /// Includes a payment expiration in seconds relative to the UNIX epoch. + pub fn with_expiry_time(self, expiry_time: u64) -> Self { + Self { expiry_time: Some(expiry_time), ..self } + } } /// A list of hops along a payment path terminating with a channel to the recipient. #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct RouteHint(pub Vec); + +impl Writeable for RouteHint { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + (self.0.len() as u64).write(writer)?; + for hop in self.0.iter() { + hop.write(writer)?; + } + Ok(()) + } +} + +impl Readable for RouteHint { + fn read(reader: &mut R) -> Result { + let hop_count: u64 = Readable::read(reader)?; + let mut hops = Vec::with_capacity(cmp::min(hop_count, 16) as usize); + for _ in 0..hop_count { + hops.push(Readable::read(reader)?); + } + Ok(Self(hops)) + } +} + /// A channel descriptor for a hop along a payment path. #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct RouteHintHop { @@ -197,6 +280,15 @@ pub struct RouteHintHop { pub htlc_maximum_msat: Option, } +impl_writeable_tlv_based!(RouteHintHop, { + (0, src_node_id, required), + (1, htlc_minimum_msat, option), + (2, short_channel_id, required), + (3, htlc_maximum_msat, option), + (4, fees, required), + (6, cltv_expiry_delta, required), +}); + #[derive(Eq, PartialEq)] struct RouteGraphNode { node_id: NodeId, @@ -407,45 +499,49 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option { } } -/// Gets a keysend route from us (payer) to the given target node (payee). This is needed because -/// keysend payments do not have an invoice from which to pull the payee's supported features, which -/// makes it tricky to otherwise supply the `payee` parameter of `get_route`. -pub fn get_keysend_route( - our_node_pubkey: &PublicKey, network: &NetworkGraph, payee: &PublicKey, - first_hops: Option<&[&ChannelDetails]>, last_hops: &[&RouteHint], final_value_msat: u64, - final_cltv: u32, logger: L, scorer: &S +/// Finds a route from us (payer) to the given target node (payee). +/// +/// If the payee provided features in their invoice, they should be provided via `params.payee`. +/// Without this, MPP will only be used if the payee's features are available in the network graph. +/// +/// Private routing paths between a public node and the target may be included in `params.payee`. +/// +/// If some channels aren't announced, it may be useful to fill in `first_hops` with the results +/// from [`ChannelManager::list_usable_channels`]. If it is filled in, the view of our local +/// channels from [`NetworkGraph`] will be ignored, and only those in `first_hops` will be used. +/// +/// The fees on channels from us to the next hop are ignored as they are assumed to all be equal. +/// However, the enabled/disabled bit on such channels as well as the `htlc_minimum_msat` / +/// `htlc_maximum_msat` *are* checked as they may change based on the receiving node. +/// +/// # Note +/// +/// May be used to re-compute a [`Route`] when handling a [`Event::PaymentPathFailed`]. Any +/// adjustments to the [`NetworkGraph`] and channel scores should be made prior to calling this +/// function. +/// +/// # Panics +/// +/// Panics if first_hops contains channels without short_channel_ids; +/// [`ChannelManager::list_usable_channels`] will never include such channels. +/// +/// [`ChannelManager::list_usable_channels`]: crate::ln::channelmanager::ChannelManager::list_usable_channels +/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed +pub fn find_route( + our_node_pubkey: &PublicKey, params: &RouteParameters, network: &NetworkGraph, + first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S ) -> Result where L::Target: Logger { - let route_hints = last_hops.iter().map(|hint| (*hint).clone()).collect(); - let payee = Payee::for_keysend(*payee).with_route_hints(route_hints); get_route( - our_node_pubkey, &payee, network, first_hops, final_value_msat, final_cltv, logger, scorer + our_node_pubkey, ¶ms.payee, network, first_hops, params.final_value_msat, + params.final_cltv_expiry_delta, logger, scorer ) } -/// Gets a route from us (payer) to the given target node (payee). -/// -/// If the payee provided features in their invoice, they should be provided via `payee`. Without -/// this, MPP will only be used if the payee's features are available in the network graph. -/// -/// Private routing paths between a public node and the target may be included in `payee`. -/// Currently, only the last hop in each path is considered. -/// -/// If some channels aren't announced, it may be useful to fill in a first_hops with the -/// results from a local ChannelManager::list_usable_channels() call. If it is filled in, our -/// view of our local channels (from net_graph_msg_handler) will be ignored, and only those -/// in first_hops will be used. -/// -/// Panics if first_hops contains channels without short_channel_ids -/// (ChannelManager::list_usable_channels will never include such channels). -/// -/// The fees on channels from us to next-hops are ignored (as they are assumed to all be -/// equal), however the enabled/disabled bit on such channels as well as the -/// htlc_minimum_msat/htlc_maximum_msat *are* checked as they may change based on the receiving node. -pub fn get_route( +pub(crate) fn get_route( our_node_pubkey: &PublicKey, payee: &Payee, network: &NetworkGraph, - first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv: u32, logger: L, - scorer: &S + first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv_expiry_delta: u32, + logger: L, scorer: &S ) -> Result where L::Target: Logger { let payee_node_id = NodeId::from_pubkey(&payee.pubkey); @@ -1155,7 +1251,7 @@ where L::Target: Logger { } ordered_hops.last_mut().unwrap().0.fee_msat = value_contribution_msat; ordered_hops.last_mut().unwrap().0.hop_use_fee_msat = 0; - ordered_hops.last_mut().unwrap().0.cltv_expiry_delta = final_cltv; + ordered_hops.last_mut().unwrap().0.cltv_expiry_delta = final_cltv_expiry_delta; log_trace!(logger, "Found a path back to us from the target with {} hops contributing up to {} msat: {:?}", ordered_hops.len(), value_contribution_msat, ordered_hops); @@ -1364,7 +1460,10 @@ where L::Target: Logger { } } - let route = Route { paths: selected_paths.into_iter().map(|path| path.into_iter().collect()).collect::, _>>()? }; + let route = Route { + paths: selected_paths.into_iter().map(|path| path.into_iter().collect()).collect::, _>>()?, + payee: Some(payee.clone()), + }; log_info!(logger, "Got route to {}: {}", payee.pubkey, log_route!(route)); Ok(route) } @@ -1374,7 +1473,6 @@ mod tests { use routing; use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId}; use routing::router::{get_route, Payee, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees}; - use routing::scorer::Scorer; use chain::transaction::OutPoint; use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures}; use ln::msgs::{ErrorAction, LightningError, OptionalField, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler, @@ -1425,7 +1523,7 @@ mod tests { // Using the same keys for LN and BTC ids fn add_channel( - net_graph_msg_handler: &NetGraphMsgHandler, Arc>, + net_graph_msg_handler: &NetGraphMsgHandler, Arc, Arc>, secp_ctx: &Secp256k1, node_1_privkey: &SecretKey, node_2_privkey: &SecretKey, features: ChannelFeatures, short_channel_id: u64 ) { let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey); @@ -1457,7 +1555,7 @@ mod tests { } fn update_channel( - net_graph_msg_handler: &NetGraphMsgHandler, Arc>, + net_graph_msg_handler: &NetGraphMsgHandler, Arc, Arc>, secp_ctx: &Secp256k1, node_privkey: &SecretKey, update: UnsignedChannelUpdate ) { let msghash = hash_to_message!(&Sha256dHash::hash(&update.encode()[..])[..]); @@ -1473,7 +1571,7 @@ mod tests { } fn add_or_update_node( - net_graph_msg_handler: &NetGraphMsgHandler, Arc>, + net_graph_msg_handler: &NetGraphMsgHandler, Arc, Arc>, secp_ctx: &Secp256k1, node_privkey: &SecretKey, features: NodeFeatures, timestamp: u32 ) { let node_id = PublicKey::from_secret_key(&secp_ctx, node_privkey); @@ -1527,12 +1625,18 @@ mod tests { } } - fn build_graph() -> (Secp256k1, NetGraphMsgHandler, sync::Arc>, sync::Arc, sync::Arc) { + fn build_graph() -> ( + Secp256k1, + sync::Arc, + NetGraphMsgHandler, sync::Arc, sync::Arc>, + sync::Arc, + sync::Arc, + ) { let secp_ctx = Secp256k1::new(); let logger = Arc::new(test_utils::TestLogger::new()); let chain_monitor = Arc::new(test_utils::TestChainSource::new(Network::Testnet)); - let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()); - let net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, None, Arc::clone(&logger)); + let network_graph = Arc::new(NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash())); + let net_graph_msg_handler = NetGraphMsgHandler::new(Arc::clone(&network_graph), None, Arc::clone(&logger)); // Build network from our_id to node6: // // -1(1)2- node0 -1(3)2- @@ -1830,23 +1934,23 @@ mod tests { add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[5], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0); - (secp_ctx, net_graph_msg_handler, chain_monitor, logger) + (secp_ctx, network_graph, net_graph_msg_handler, chain_monitor, logger) } #[test] fn simple_route_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[2]); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Simple route to 2 via 1 - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 0, 42, Arc::clone(&logger), &scorer) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &network_graph, None, 0, 42, Arc::clone(&logger), &scorer) { assert_eq!(err, "Cannot send a payment of 0 msat"); } else { panic!(); } - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -1866,29 +1970,29 @@ mod tests { #[test] fn invalid_first_hop_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[2]); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Simple route to 2 via 1 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, &payee, &net_graph_msg_handler.network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer) { assert_eq!(err, "First hop cannot have our_node_pubkey as a destination."); } else { panic!(); } - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); } #[test] fn htlc_minimum_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[2]); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Simple route to 2 via 1 @@ -1985,7 +2089,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, &payee, &net_graph_msg_handler.network_graph, None, 199_999_999, 42, Arc::clone(&logger), &scorer) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &network_graph, None, 199_999_999, 42, Arc::clone(&logger), &scorer) { assert_eq!(err, "Failed to find a path to the given destination"); } else { panic!(); } @@ -2004,16 +2108,16 @@ mod tests { }); // A payment above the minimum should pass - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 199_999_999, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 199_999_999, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); } #[test] fn htlc_minimum_overpay_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // A route to node#2 via two paths. // One path allows transferring 35-40 sats, another one also allows 35-40 sats. @@ -2083,7 +2187,7 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer).unwrap(); // Overpay fees to hit htlc_minimum_msat. let overpaid_fees = route.paths[0][0].fee_msat + route.paths[1][0].fee_msat; // TODO: this could be better balanced to overpay 10k and not 15k. @@ -2128,14 +2232,14 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer).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][0].short_channel_id, 12); let fees = route.paths[0][0].fee_msat; assert_eq!(fees, 5_000); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).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); @@ -2146,10 +2250,10 @@ mod tests { #[test] fn disable_channels_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[2]); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // // Disable channels 4 and 12 by flags=2 update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { @@ -2178,13 +2282,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, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[7]); @@ -2204,10 +2308,10 @@ mod tests { #[test] fn disable_node_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[2]); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Disable nodes 1, 2, and 8 by requiring unknown feature bits let unknown_features = NodeFeatures::known().set_unknown_feature_required(); @@ -2216,13 +2320,13 @@ mod tests { add_or_update_node(&net_graph_msg_handler, &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, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[7]); @@ -2246,13 +2350,13 @@ mod tests { #[test] fn our_chans_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Route to 1 via 2 and 3 because our channel to 1 is disabled let payee = Payee::new(nodes[0]); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 3); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2279,7 +2383,7 @@ mod tests { // If we specify a channel to node7, that overrides our local channel view and that gets used let payee = Payee::new(nodes[2]); 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, &payee, &net_graph_msg_handler.network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[7]); @@ -2375,9 +2479,9 @@ mod tests { #[test] fn partial_route_hint_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Simple test across 2, 3, 5, and 4 via a last_hop channel // Tests the behaviour when the RouteHint contains a suboptimal hop. @@ -2400,13 +2504,13 @@ mod tests { invalid_last_hops.push(invalid_last_hop); { let payee = Payee::new(nodes[6]).with_route_hints(invalid_last_hops); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer) { + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer) { assert_eq!(err, "Route hint cannot have the payee as the source."); } else { panic!(); } } let payee = Payee::new(nodes[6]).with_route_hints(last_hops_multi_private_channels(&nodes)); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 5); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2473,14 +2577,14 @@ mod tests { #[test] fn ignores_empty_last_hops_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[6]).with_route_hints(empty_last_hop(&nodes)); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Test handling of an empty RouteHint passed in Invoice. - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 5); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2555,10 +2659,10 @@ mod tests { #[test] fn multi_hint_last_hops_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[6]).with_route_hints(multi_hint_last_hops(&nodes)); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Test through channels 2, 3, 5, 8. // Test shows that multiple hop hints are considered. @@ -2588,7 +2692,7 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 4); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2661,14 +2765,14 @@ mod tests { #[test] fn last_hops_with_public_channel_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[6]).with_route_hints(last_hops_with_public_channel(&nodes)); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // 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, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 5); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2711,15 +2815,15 @@ mod tests { #[test] fn our_chans_last_hop_connect_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // Simple test with outbound channel to 4 to test that last_hops and first_hops connect 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 payee = Payee::new(nodes[6]).with_route_hints(last_hops.clone()); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, Some(&our_chans.iter().collect::>()), 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[3]); @@ -2740,7 +2844,7 @@ mod tests { // Revert to via 6 as the fee on 8 goes up let payee = Payee::new(nodes[6]).with_route_hints(last_hops); - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 4); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2774,7 +2878,7 @@ mod tests { assert_eq!(route.paths[0][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, &payee, &net_graph_msg_handler.network_graph, None, 2000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 2000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 5); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2834,7 +2938,7 @@ mod tests { }]); let payee = Payee::new(target_node_id).with_route_hints(vec![last_hops]); let our_chans = vec![get_channel_details(Some(42), middle_node_id, InitFeatures::from_le_bytes(vec![0b11]), outbound_capacity_msat)]; - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); get_route(&source_node_id, &payee, &NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()), Some(&our_chans.iter().collect::>()), route_val, 42, &test_utils::TestLogger::new(), &scorer) } @@ -2886,9 +2990,9 @@ mod tests { fn available_amount_while_routing_test() { // Tests whether we choose the correct available channel amount while routing. - let (secp_ctx, mut net_graph_msg_handler, chain_monitor, logger) = build_graph(); + let (secp_ctx, network_graph, mut net_graph_msg_handler, chain_monitor, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); // We will use a simple single-path route from @@ -2953,14 +3057,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, &payee, &net_graph_msg_handler.network_graph, None, 250_000_001, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 250_000_001, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, None, 250_000_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 250_000_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.len(), 2); @@ -2989,14 +3093,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, &payee, &net_graph_msg_handler.network_graph, Some(&our_chans.iter().collect::>()), 200_000_001, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, Some(&our_chans.iter().collect::>()), 200_000_001, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, Some(&our_chans.iter().collect::>()), 200_000_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, Some(&our_chans.iter().collect::>()), 200_000_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.len(), 2); @@ -3036,14 +3140,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, &payee, &net_graph_msg_handler.network_graph, None, 15_001, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 15_001, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, None, 15_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 15_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.len(), 2); @@ -3106,14 +3210,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, &payee, &net_graph_msg_handler.network_graph, None, 15_001, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 15_001, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, None, 15_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 15_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.len(), 2); @@ -3138,14 +3242,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, &payee, &net_graph_msg_handler.network_graph, None, 10_001, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 10_001, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, None, 10_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 10_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.len(), 2); @@ -3158,9 +3262,9 @@ mod tests { fn available_liquidity_last_hop_test() { // Check that available liquidity properly limits the path even when only // one of the latter hops is limited. - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known()); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. @@ -3247,14 +3351,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, &payee, &net_graph_msg_handler.network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, None, 49_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 49_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3267,7 +3371,7 @@ mod tests { { // Attempt to route an exact amount is also fine - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3281,9 +3385,9 @@ mod tests { #[test] fn ignore_fee_first_hop_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[2]); // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50). @@ -3313,7 +3417,7 @@ mod tests { }); { - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3327,9 +3431,9 @@ mod tests { #[test] fn simple_mpp_route_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); // We need a route consisting of 3 paths: @@ -3423,7 +3527,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, &payee, &net_graph_msg_handler.network_graph, None, 300_000, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 300_000, 42, Arc::clone(&logger), &scorer) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -3431,7 +3535,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, &payee, &net_graph_msg_handler.network_graph, None, 250_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 250_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3444,7 +3548,7 @@ mod tests { { // Attempt to route an exact amount is also fine - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 290_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 290_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -3458,9 +3562,9 @@ mod tests { #[test] fn long_mpp_route_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known()); // We need a route consisting of 3 paths: @@ -3597,7 +3701,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, &payee, &net_graph_msg_handler.network_graph, None, 350_000, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 350_000, 42, Arc::clone(&logger), &scorer) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -3605,7 +3709,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, &payee, &net_graph_msg_handler.network_graph, None, 300_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 300_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; @@ -3620,9 +3724,9 @@ mod tests { #[test] fn mpp_cheaper_route_test() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known()); // This test checks that if we have two cheaper paths and one more expensive path, @@ -3763,7 +3867,7 @@ mod tests { { // Now, attempt to route 180 sats. // Our algorithm should provide us with these 2 paths. - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 180_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 180_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_value_transferred_msat = 0; @@ -3787,9 +3891,9 @@ mod tests { // This test makes sure that MPP algorithm properly takes into account // fees charged on the channels, by making the fees impactful: // if the fee is not properly accounted for, the behavior is different. - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known()); // We need a route consisting of 2 paths: @@ -3931,14 +4035,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, &payee, &net_graph_msg_handler.network_graph, None, 210_000, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 210_000, 42, Arc::clone(&logger), &scorer) { 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, &payee, &net_graph_msg_handler.network_graph, None, 200_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 200_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; @@ -3956,9 +4060,9 @@ mod tests { fn drop_lowest_channel_mpp_route_test() { // This test checks that low-capacity channel is dropped when after // path finding we realize that we found more capacity than we need. - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); // We need a route consisting of 3 paths: @@ -4051,7 +4155,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, &payee, &net_graph_msg_handler.network_graph, None, 150_000, 42, Arc::clone(&logger), &scorer) { + &our_id, &payee, &network_graph, None, 150_000, 42, Arc::clone(&logger), &scorer) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -4059,7 +4163,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, &payee, &net_graph_msg_handler.network_graph, None, 125_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 125_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -4072,7 +4176,7 @@ mod tests { { // Attempt to route without the last small cheap channel - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -4112,10 +4216,10 @@ mod tests { // "previous hop" being set to node 3, creating a loop in the path. let secp_ctx = Secp256k1::new(); let logger = Arc::new(test_utils::TestLogger::new()); - let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()); - let net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, None, Arc::clone(&logger)); + let network_graph = Arc::new(NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash())); + let net_graph_msg_handler = NetGraphMsgHandler::new(Arc::clone(&network_graph), None, Arc::clone(&logger)); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[6]); add_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6); @@ -4209,7 +4313,7 @@ mod tests { { // Now ensure the route flows simply over nodes 1 and 4 to 6. - let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 10_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 10_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), 3); @@ -4242,9 +4346,9 @@ mod tests { // Test that if, while walking the graph, we find a hop that has exactly enough liquidity // for us, including later hop fees, we take it. In the first version of our MPP algorithm // we calculated fees on a higher value, resulting in us ignoring such paths. - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, _, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[2]); // We modify the graph to set the htlc_maximum of channel 2 to below the value we wish to @@ -4278,7 +4382,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, &payee, &net_graph_msg_handler.network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), 2); @@ -4304,9 +4408,9 @@ mod tests { // htlc_maximum_msat, we don't end up undershooting a later htlc_minimum_msat. In the // initial version of MPP we'd accept such routes but reject them while recalculating fees, // resulting in us thinking there is no possible path, even if other paths exist. - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); // We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2 @@ -4341,7 +4445,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, &payee, &net_graph_msg_handler.network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), 2); @@ -4373,7 +4477,7 @@ mod tests { let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let logger = Arc::new(test_utils::TestLogger::new()); let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let payee = Payee::new(nodes[0]).with_features(InvoiceFeatures::known()); { @@ -4409,14 +4513,14 @@ mod tests { #[test] fn prefers_shorter_route_with_higher_fees() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[6]).with_route_hints(last_hops(&nodes)); // Without penalizing each hop 100 msats, a longer path with lower fees is chosen. - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let route = get_route( - &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + &our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4427,9 +4531,9 @@ mod tests { // Applying a 100 msat penalty to each hop results in taking channels 7 and 10 to nodes[6] // from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper. - let scorer = Scorer::new(100); + let scorer = test_utils::TestScorer::with_fixed_penalty(100); let route = get_route( - &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + &our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4447,6 +4551,8 @@ mod tests { fn channel_penalty_msat(&self, short_channel_id: u64, _source: &NodeId, _target: &NodeId) -> u64 { if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 } } + + fn payment_path_failed(&mut self, _path: &Vec, _short_channel_id: u64) {} } struct BadNodeScorer { @@ -4457,18 +4563,20 @@ mod tests { fn channel_penalty_msat(&self, _short_channel_id: u64, _source: &NodeId, target: &NodeId) -> u64 { if *target == self.node_id { u64::max_value() } else { 0 } } + + fn payment_path_failed(&mut self, _path: &Vec, _short_channel_id: u64) {} } #[test] fn avoids_routing_through_bad_channels_and_nodes() { - let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); + let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let payee = Payee::new(nodes[6]).with_route_hints(last_hops(&nodes)); // A path to nodes[6] exists when no penalties are applied to any channel. - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); let route = get_route( - &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + &our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4480,7 +4588,7 @@ mod tests { // A different path to nodes[6] exists if channel 6 cannot be routed over. let scorer = BadChannelScorer { short_channel_id: 6 }; let route = get_route( - &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + &our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4492,7 +4600,7 @@ mod tests { // A path to nodes[6] does not exist if nodes[2] cannot be routed through. let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) }; match get_route( - &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + &our_id, &payee, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer ) { Err(LightningError { err, .. } ) => { @@ -4522,6 +4630,7 @@ mod tests { short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0 }, ]], + payee: None, }; assert_eq!(route.get_total_fees(), 250); @@ -4554,6 +4663,7 @@ mod tests { short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0 }, ]], + payee: None, }; assert_eq!(route.get_total_fees(), 200); @@ -4565,7 +4675,7 @@ mod tests { // In an earlier version of `Route::get_total_fees` and `Route::get_total_amount`, they // would both panic if the route was completely empty. We test to ensure they return 0 // here, even though its somewhat nonsensical as a route. - let route = Route { paths: Vec::new() }; + let route = Route { paths: Vec::new(), payee: None }; assert_eq!(route.get_total_fees(), 0); assert_eq!(route.get_total_amount(), 0); @@ -4593,7 +4703,7 @@ mod tests { }, }; let graph = NetworkGraph::read(&mut d).unwrap(); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // First, get 100 (source, destination) pairs for which route-getting actually succeeds... let mut seed = random_init_seed() as usize; @@ -4624,7 +4734,7 @@ mod tests { }, }; let graph = NetworkGraph::read(&mut d).unwrap(); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // First, get 100 (source, destination) pairs for which route-getting actually succeeds... let mut seed = random_init_seed() as usize; @@ -4690,7 +4800,7 @@ mod benches { let mut d = test_utils::get_route_file().unwrap(); let graph = NetworkGraph::read(&mut d).unwrap(); let nodes = graph.read_only().nodes().clone(); - let scorer = Scorer::new(0); + let scorer = Scorer::with_fixed_penalty(0); // First, get 100 (source, destination) pairs for which route-getting actually succeeds... let mut path_endpoints = Vec::new(); @@ -4725,7 +4835,7 @@ mod benches { let mut d = test_utils::get_route_file().unwrap(); let graph = NetworkGraph::read(&mut d).unwrap(); let nodes = graph.read_only().nodes().clone(); - let scorer = Scorer::new(0); + let scorer = Scorer::with_fixed_penalty(0); // First, get 100 (source, destination) pairs for which route-getting actually succeeds... let mut path_endpoints = Vec::new();