From b5be4c210c804488c18a0f5fe912728fdede6984 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Wed, 20 Oct 2021 09:15:31 -0500 Subject: [PATCH] Define Payee abstraction for use in get_route A payee can be identified by a pubkey and optionally have an associated set of invoice features and route hints. Use this in get_route instead of three separate parameters. This may be included in PaymentPathFailed later to use when finding a new route. --- fuzz/src/full_stack.rs | 8 +- fuzz/src/router.rs | 6 +- lightning-invoice/src/lib.rs | 4 +- lightning-invoice/src/utils.rs | 8 +- lightning/src/ln/channelmanager.rs | 16 +- lightning/src/ln/functional_test_utils.rs | 22 +- lightning/src/ln/functional_tests.rs | 17 +- lightning/src/ln/shutdown_tests.rs | 8 +- lightning/src/routing/router.rs | 316 +++++++++++++--------- lightning/src/routing/scorer.rs | 6 +- 10 files changed, 247 insertions(+), 164 deletions(-) diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 84ba7bab5..b2feaa695 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -38,7 +38,7 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig use lightning::ln::msgs::DecodeError; use lightning::ln::script::ShutdownScript; use lightning::routing::network_graph::{NetGraphMsgHandler, NetworkGraph}; -use lightning::routing::router::get_route; +use lightning::routing::router::{get_route, Payee}; use lightning::routing::scorer::Scorer; use lightning::util::config::UserConfig; use lightning::util::errors::APIError; @@ -438,7 +438,8 @@ pub fn do_test(data: &[u8], logger: &Arc) { }, 4 => { let value = slice_to_be24(get_slice!(3)) as u64; - let route = match get_route(&our_id, &net_graph_msg_handler.network_graph, &get_pubkey!(), None, None, &Vec::new(), value, 42, Arc::clone(&logger), &scorer) { + let payee = Payee::new(get_pubkey!()); + let route = match get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, value, 42, Arc::clone(&logger), &scorer) { Ok(route) => route, Err(_) => return, }; @@ -455,7 +456,8 @@ pub fn do_test(data: &[u8], logger: &Arc) { }, 15 => { let value = slice_to_be24(get_slice!(3)) as u64; - let mut route = match get_route(&our_id, &net_graph_msg_handler.network_graph, &get_pubkey!(), None, None, &Vec::new(), value, 42, Arc::clone(&logger), &scorer) { + let payee = Payee::new(get_pubkey!()); + let mut route = match get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, value, 42, Arc::clone(&logger), &scorer) { Ok(route) => route, Err(_) => return, }; diff --git a/fuzz/src/router.rs b/fuzz/src/router.rs index 6a207254a..6f54aa02d 100644 --- a/fuzz/src/router.rs +++ b/fuzz/src/router.rs @@ -16,7 +16,7 @@ use lightning::chain::transaction::OutPoint; use lightning::ln::channelmanager::{ChannelDetails, ChannelCounterparty}; use lightning::ln::features::InitFeatures; use lightning::ln::msgs; -use lightning::routing::router::{get_route, RouteHint, RouteHintHop}; +use lightning::routing::router::{get_route, Payee, RouteHint, RouteHintHop}; use lightning::routing::scorer::Scorer; use lightning::util::logger::Logger; use lightning::util::ser::Readable; @@ -250,9 +250,9 @@ pub fn do_test(data: &[u8], out: Out) { } let scorer = Scorer::new(0); for target in node_pks.iter() { - let _ = get_route(&our_pubkey, &net_graph, target, None, + let payee = Payee::new(*target).with_route_hints(last_hops.clone()); + let _ = get_route(&our_pubkey, &payee, &net_graph, first_hops.map(|c| c.iter().collect::>()).as_ref().map(|a| a.as_slice()), - &last_hops.iter().collect::>(), slice_to_be64(get_slice!(8)), slice_to_be32(get_slice!(4)), Arc::clone(&logger), &scorer); } }, diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 61e394da6..0f125362c 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -1208,10 +1208,10 @@ impl Invoice { } /// Returns a list of all routes included in the invoice as the underlying hints - pub fn route_hints(&self) -> Vec<&RouteHint> { + pub fn route_hints(&self) -> Vec { find_all_extract!( self.signed_invoice.known_tagged_fields(), TaggedField::PrivateRoute(ref x), x - ).map(|route| &**route).collect() + ).map(|route| (**route).clone()).collect() } /// Returns the currency for which the invoice was issued diff --git a/lightning-invoice/src/utils.rs b/lightning-invoice/src/utils.rs index 31c1ab255..c9046abc0 100644 --- a/lightning-invoice/src/utils.rs +++ b/lightning-invoice/src/utils.rs @@ -113,19 +113,19 @@ mod test { assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64); assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string()))); + let payee = router::Payee::new(invoice.recover_payee_pub_key()) + .with_features(invoice.features().unwrap().clone()) + .with_route_hints(invoice.route_hints()); let amt_msat = invoice.amount_pico_btc().unwrap() / 10; let first_hops = nodes[0].node.list_usable_channels(); - let last_hops = invoice.route_hints(); let network_graph = &nodes[0].net_graph_msg_handler.network_graph; let logger = test_utils::TestLogger::new(); let scorer = Scorer::new(0); let route = router::get_route( &nodes[0].node.get_our_node_id(), + &payee, network_graph, - &invoice.recover_payee_pub_key(), - Some(invoice.features().unwrap().clone()), Some(&first_hops.iter().collect::>()), - &last_hops, amt_msat, invoice.min_final_cltv_expiry() as u32, &logger, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index f3085fe20..418ef5f9b 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -5827,7 +5827,7 @@ mod tests { use ln::functional_test_utils::*; use ln::msgs; use ln::msgs::ChannelMessageHandler; - use routing::router::{get_keysend_route, get_route}; + use routing::router::{Payee, get_keysend_route, get_route}; use routing::scorer::Scorer; use util::errors::APIError; use util::events::{Event, MessageSendEvent, MessageSendEventsProvider}; @@ -6074,7 +6074,9 @@ mod tests { let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &expected_route, 100_000); // Next, attempt a keysend payment and make sure it fails. - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let payee = Payee::new(expected_route.last().unwrap().node.get_our_node_id()) + .with_features(InvoiceFeatures::known()); + let route = get_route(&nodes[0].node.get_our_node_id(), &payee, &nodes[0].net_graph_msg_handler.network_graph, None, 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -6102,7 +6104,7 @@ mod tests { // To start (2), send a keysend payment but don't claim it. let payment_preimage = PaymentPreimage([42; 32]); - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let route = get_route(&nodes[0].node.get_our_node_id(), &payee, &nodes[0].net_graph_msg_handler.network_graph, None, 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -6256,7 +6258,7 @@ pub mod bench { use ln::functional_test_utils::*; use ln::msgs::{ChannelMessageHandler, Init}; use routing::network_graph::NetworkGraph; - use routing::router::get_route; + use routing::router::{Payee, get_route}; use routing::scorer::Scorer; use util::test_utils; use util::config::UserConfig; @@ -6365,9 +6367,11 @@ pub mod bench { macro_rules! send_payment { ($node_a: expr, $node_b: expr) => { let usable_channels = $node_a.list_usable_channels(); + let payee = Payee::new($node_b.get_our_node_id()) + .with_features(InvoiceFeatures::known()); let scorer = Scorer::new(0); - let route = get_route(&$node_a.get_our_node_id(), &dummy_graph, &$node_b.get_our_node_id(), Some(InvoiceFeatures::known()), - Some(&usable_channels.iter().map(|r| r).collect::>()), &[], 10_000, TEST_FINAL_CLTV, &logger_a, &scorer).unwrap(); + let route = get_route(&$node_a.get_our_node_id(), &payee, &dummy_graph, + Some(&usable_channels.iter().map(|r| r).collect::>()), 10_000, TEST_FINAL_CLTV, &logger_a, &scorer).unwrap(); let mut payment_preimage = PaymentPreimage([0; 32]); payment_preimage.0[0..8].copy_from_slice(&payment_count.to_le_bytes()); diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 0f188ac38..b45fbd318 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -16,7 +16,7 @@ use chain::transaction::OutPoint; use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure}; use routing::network_graph::{NetGraphMsgHandler, NetworkGraph}; -use routing::router::{Route, get_route}; +use routing::router::{Payee, Route, get_route}; use routing::scorer::Scorer; use ln::features::{InitFeatures, InvoiceFeatures}; use ln::msgs; @@ -1011,13 +1011,15 @@ macro_rules! get_route_and_payment_hash { }}; ($send_node: expr, $recv_node: expr, $last_hops: expr, $recv_value: expr, $cltv: expr) => {{ let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!($recv_node, Some($recv_value)); + let payee = $crate::routing::router::Payee::new($recv_node.node.get_our_node_id()) + .with_features($crate::ln::features::InvoiceFeatures::known()) + .with_route_hints($last_hops); let net_graph_msg_handler = &$send_node.net_graph_msg_handler; let scorer = ::routing::scorer::Scorer::new(0); let route = ::routing::router::get_route( - &$send_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph, - &$recv_node.node.get_our_node_id(), Some(::ln::features::InvoiceFeatures::known()), + &$send_node.node.get_our_node_id(), &payee, &net_graph_msg_handler.network_graph, Some(&$send_node.node.list_usable_channels().iter().collect::>()), - &$last_hops, $recv_value, $cltv, $send_node.logger, &scorer + $recv_value, $cltv, $send_node.logger, &scorer ).unwrap(); (route, payment_hash, payment_preimage, payment_secret) }} @@ -1327,11 +1329,13 @@ pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: pub const TEST_FINAL_CLTV: u32 = 70; pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) { + let payee = Payee::new(expected_route.last().unwrap().node.get_our_node_id()) + .with_features(InvoiceFeatures::known()); let net_graph_msg_handler = &origin_node.net_graph_msg_handler; let scorer = Scorer::new(0); - let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph, - &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), - Some(&origin_node.node.list_usable_channels().iter().collect::>()), &[], + let route = get_route( + &origin_node.node.get_our_node_id(), &payee, &net_graph_msg_handler.network_graph, + Some(&origin_node.node.list_usable_channels().iter().collect::>()), recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), expected_route.len()); @@ -1343,9 +1347,11 @@ pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: } pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) { + let payee = Payee::new(expected_route.last().unwrap().node.get_our_node_id()) + .with_features(InvoiceFeatures::known()); let net_graph_msg_handler = &origin_node.net_graph_msg_handler; let scorer = Scorer::new(0); - let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer).unwrap(); + let route = get_route(&origin_node.node.get_our_node_id(), &payee, &net_graph_msg_handler.network_graph, None, recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), expected_route.len()); for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) { diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index eb7d868a9..aeca6e85b 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -24,7 +24,7 @@ use ln::channel::{Channel, ChannelError}; use ln::{chan_utils, onion_utils}; use ln::chan_utils::HTLC_SUCCESS_TX_WEIGHT; use routing::network_graph::{NetworkUpdate, RoutingFees}; -use routing::router::{Route, RouteHop, RouteHint, RouteHintHop, get_route, get_keysend_route}; +use routing::router::{Payee, Route, RouteHop, RouteHint, RouteHintHop, get_route, get_keysend_route}; use routing::scorer::Scorer; use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures}; use ln::msgs; @@ -7299,7 +7299,8 @@ fn test_check_htlc_underpaying() { create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); let scorer = Scorer::new(0); - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer).unwrap(); + let payee = Payee::new(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known()); + let route = get_route(&nodes[0].node.get_our_node_id(), &payee, &nodes[0].net_graph_msg_handler.network_graph, None, 10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer).unwrap(); let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]); let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, 0).unwrap(); nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap(); @@ -7487,7 +7488,7 @@ fn test_priv_forwarding_rejection() { htlc_minimum_msat: None, htlc_maximum_msat: None, }]); - let last_hops = vec![&route_hint]; + let last_hops = vec![route_hint]; let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], last_hops, 10_000, TEST_FINAL_CLTV); nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap(); @@ -7696,12 +7697,14 @@ fn test_bump_penalty_txn_on_revoked_htlcs() { let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, InitFeatures::known(), InitFeatures::known()); // Lock HTLC in both directions (using a slightly lower CLTV delay to provide timely RBF bumps) + let payee = Payee::new(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known()); let scorer = Scorer::new(0); - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, - &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 3_000_000, 50, nodes[0].logger, &scorer).unwrap(); + let route = get_route(&nodes[0].node.get_our_node_id(), &payee, &nodes[0].net_graph_msg_handler.network_graph, + None, 3_000_000, 50, nodes[0].logger, &scorer).unwrap(); let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0; - let route = get_route(&nodes[1].node.get_our_node_id(), &nodes[1].net_graph_msg_handler.network_graph, - &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 3_000_000, 50, nodes[0].logger, &scorer).unwrap(); + let payee = Payee::new(nodes[0].node.get_our_node_id()).with_features(InvoiceFeatures::known()); + let route = get_route(&nodes[1].node.get_our_node_id(), &payee, &nodes[1].net_graph_msg_handler.network_graph, + None, 3_000_000, 50, nodes[0].logger, &scorer).unwrap(); send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000); let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2); diff --git a/lightning/src/ln/shutdown_tests.rs b/lightning/src/ln/shutdown_tests.rs index e82cdae60..cbf288962 100644 --- a/lightning/src/ln/shutdown_tests.rs +++ b/lightning/src/ln/shutdown_tests.rs @@ -13,7 +13,7 @@ use chain::keysinterface::KeysInterface; use chain::transaction::OutPoint; use ln::{PaymentPreimage, PaymentHash}; use ln::channelmanager::PaymentSendFailure; -use routing::router::get_route; +use routing::router::{Payee, get_route}; use routing::network_graph::NetworkUpdate; use routing::scorer::Scorer; use ln::features::{InitFeatures, InvoiceFeatures}; @@ -99,8 +99,10 @@ fn updates_shutdown_wait() { let net_graph_msg_handler0 = &nodes[0].net_graph_msg_handler; let net_graph_msg_handler1 = &nodes[1].net_graph_msg_handler; - let route_1 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler0.network_graph, &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); - let route_2 = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler1.network_graph, &nodes[0].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 100000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let payee_1 = Payee::new(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known()); + let route_1 = get_route(&nodes[0].node.get_our_node_id(), &payee_1, &net_graph_msg_handler0.network_graph, None, 100000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let payee_2 = Payee::new(nodes[0].node.get_our_node_id()).with_features(InvoiceFeatures::known()); + let route_2 = get_route(&nodes[1].node.get_our_node_id(), &payee_2, &net_graph_msg_handler1.network_graph, None, 100000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); unwrap_send_err!(nodes[0].node.send_payment(&route_1, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable {..}, {}); unwrap_send_err!(nodes[1].node.send_payment(&route_2, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable {..}, {}); diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index b617eebd4..9f48d4cb8 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -129,6 +129,53 @@ impl Readable for Route { } } +/// The recipient of a payment. +pub struct Payee { + /// The node id of the payee. + pubkey: PublicKey, + + /// 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, + + /// Hints for routing to the payee, containing channels connecting the payee to public nodes. + pub route_hints: Vec, +} + +impl Payee { + /// Creates a payee with the node id of the given `pubkey`. + pub fn new(pubkey: PublicKey) -> Self { + Self { + pubkey, + features: None, + route_hints: vec![], + } + } + + /// Creates a payee with the node id of the given `pubkey` to use for keysend payments. + pub fn for_keysend(pubkey: PublicKey) -> Self { + Self::new(pubkey).with_features(InvoiceFeatures::for_keysend()) + } + + /// Includes the payee's features. + /// + /// (C-not exported) since bindings don't support move semantics + pub fn with_features(self, features: InvoiceFeatures) -> Self { + Self { features: Some(features), ..self } + } + + /// Includes hints for routing to the payee. + /// + /// (C-not exported) since bindings don't support move semantics + pub fn with_route_hints(self, route_hints: Vec) -> Self { + Self { route_hints, ..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); @@ -362,26 +409,26 @@ 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_features` parameter of `get_route`. +/// 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 ) -> Result where L::Target: Logger { - let invoice_features = InvoiceFeatures::for_keysend(); + 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, network, payee, Some(invoice_features), first_hops, last_hops, - final_value_msat, final_cltv, logger, scorer + our_node_pubkey, &payee, network, first_hops, final_value_msat, final_cltv, 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_features. -/// Without this, MPP will only be used if the payee's features are available in the network graph. +/// 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 `last_hops`. +/// 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 @@ -396,12 +443,12 @@ where L::Target: Logger { /// 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( - our_node_pubkey: &PublicKey, network: &NetworkGraph, payee: &PublicKey, - payee_features: Option, first_hops: Option<&[&ChannelDetails]>, - last_hops: &[&RouteHint], final_value_msat: u64, final_cltv: u32, logger: L, scorer: &S + our_node_pubkey: &PublicKey, payee: &Payee, network: &NetworkGraph, + first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv: u32, logger: L, + scorer: &S ) -> Result where L::Target: Logger { - let payee_node_id = NodeId::from_pubkey(&payee); + let payee_node_id = NodeId::from_pubkey(&payee.pubkey); let our_node_id = NodeId::from_pubkey(&our_node_pubkey); if payee_node_id == our_node_id { @@ -416,10 +463,10 @@ where L::Target: Logger { return Err(LightningError{err: "Cannot send a payment of 0 msat".to_owned(), action: ErrorAction::IgnoreError}); } - for route in last_hops.iter() { + for route in payee.route_hints.iter() { for hop in &route.0 { - if hop.src_node_id == *payee { - return Err(LightningError{err: "Last hop cannot have a payee as a source.".to_owned(), action: ErrorAction::IgnoreError}); + if hop.src_node_id == payee.pubkey { + return Err(LightningError{err: "Route hint cannot have the payee as the source.".to_owned(), action: ErrorAction::IgnoreError}); } } } @@ -500,15 +547,15 @@ where L::Target: Logger { // Allow MPP only if we have a features set from somewhere that indicates the payee supports // it. If the payee supports it they're supposed to include it in the invoice, so that should // work reliably. - let allow_mpp = if let Some(features) = &payee_features { + let allow_mpp = if let Some(features) = &payee.features { features.supports_basic_mpp() } else if let Some(node) = network_nodes.get(&payee_node_id) { if let Some(node_info) = node.announcement_info.as_ref() { node_info.features.supports_basic_mpp() } else { false } } else { false }; - log_trace!(logger, "Searching for a route from payer {} to payee {} {} MPP", our_node_pubkey, payee, - if allow_mpp { "with" } else { "without" }); + log_trace!(logger, "Searching for a route from payer {} to payee {} {} MPP", our_node_pubkey, + payee.pubkey, if allow_mpp { "with" } else { "without" }); // Step (1). // Prepare the data we'll use for payee-to-payer search by @@ -567,7 +614,7 @@ where L::Target: Logger { // - when we want to stop looking for new paths. let mut already_collected_value_msat = 0; - log_trace!(logger, "Building path from {} (payee) to {} (us/payer) for value {} msat.", payee, our_node_pubkey, final_value_msat); + log_trace!(logger, "Building path from {} (payee) to {} (us/payer) for value {} msat.", payee.pubkey, our_node_pubkey, final_value_msat); macro_rules! add_entry { // Adds entry which goes from $src_node_id to $dest_node_id @@ -937,7 +984,7 @@ where L::Target: Logger { // If a caller provided us with last hops, add them to routing targets. Since this happens // earlier than general path finding, they will be somewhat prioritized, although currently // it matters only if the fees are exactly the same. - for route in last_hops.iter().filter(|route| !route.0.is_empty()) { + for route in payee.route_hints.iter().filter(|route| !route.0.is_empty()) { let first_hop_in_route = &(route.0)[0]; let have_hop_src_in_graph = // Only add the hops in this route to our candidate set if either @@ -949,7 +996,7 @@ where L::Target: Logger { // We start building the path from reverse, i.e., from payee // to the first RouteHintHop in the path. let hop_iter = route.0.iter().rev(); - let prev_hop_iter = core::iter::once(payee).chain( + let prev_hop_iter = core::iter::once(&payee.pubkey).chain( route.0.iter().skip(1).rev().map(|hop| &hop.src_node_id)); let mut hop_used = true; let mut aggregate_next_hops_fee_msat: u64 = 0; @@ -1309,7 +1356,7 @@ where L::Target: Logger { }).collect()); } - if let Some(features) = &payee_features { + if let Some(features) = &payee.features { for path in selected_paths.iter_mut() { if let Ok(route_hop) = path.last_mut().unwrap() { route_hop.node_features = features.to_context(); @@ -1318,7 +1365,7 @@ where L::Target: Logger { } let route = Route { paths: selected_paths.into_iter().map(|path| path.into_iter().collect()).collect::, _>>()? }; - log_info!(logger, "Got route to {}: {}", payee, log_route!(route)); + log_info!(logger, "Got route to {}: {}", payee.pubkey, log_route!(route)); Ok(route) } @@ -1326,7 +1373,7 @@ where L::Target: Logger { mod tests { use routing; use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId}; - use routing::router::{get_route, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees}; + 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}; @@ -1790,15 +1837,16 @@ mod tests { fn simple_route_test() { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); + let payee = Payee::new(nodes[2]); let scorer = Scorer::new(0); // Simple route to 2 via 1 - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 0, 42, Arc::clone(&logger), &scorer) { + 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) { assert_eq!(err, "Cannot send a payment of 0 msat"); } else { panic!(); } - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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]); @@ -1820,17 +1868,18 @@ mod tests { fn invalid_first_hop_test() { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); + let payee = Payee::new(nodes[2]); let scorer = Scorer::new(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, &net_graph_msg_handler.network_graph, &nodes[2], None, Some(&our_chans.iter().collect::>()), &Vec::new(), 100, 42, Arc::clone(&logger), &scorer) { + 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) { assert_eq!(err, "First hop cannot have our_node_pubkey as a destination."); } else { panic!(); } - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); } @@ -1838,6 +1887,7 @@ mod tests { fn htlc_minimum_test() { let (secp_ctx, 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); // Simple route to 2 via 1 @@ -1935,7 +1985,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, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 199_999_999, 42, Arc::clone(&logger), &scorer) { + 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) { assert_eq!(err, "Failed to find a path to the given destination"); } else { panic!(); } @@ -1954,7 +2004,7 @@ mod tests { }); // A payment above the minimum should pass - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 199_999_999, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 199_999_999, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths[0].len(), 2); } @@ -1962,6 +2012,7 @@ mod tests { fn htlc_minimum_overpay_test() { let (secp_ctx, 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); // A route to node#2 via two paths. @@ -2032,8 +2083,7 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 60_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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. @@ -2078,16 +2128,14 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 60_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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); @@ -2100,6 +2148,7 @@ mod tests { fn disable_channels_test() { let (secp_ctx, 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); // // Disable channels 4 and 12 by flags=2 @@ -2129,13 +2178,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, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 100, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[2], None, Some(&our_chans.iter().collect::>()), &Vec::new(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[7]); @@ -2157,6 +2206,7 @@ mod tests { fn disable_node_test() { let (secp_ctx, 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); // Disable nodes 1, 2, and 8 by requiring unknown feature bits @@ -2166,13 +2216,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, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 100, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[2], None, Some(&our_chans.iter().collect::>()), &Vec::new(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[7]); @@ -2201,7 +2251,8 @@ mod tests { let scorer = Scorer::new(0); // Route to 1 via 2 and 3 because our channel to 1 is disabled - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[0], None, None, &Vec::new(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths[0].len(), 3); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2226,8 +2277,9 @@ mod tests { assert_eq!(route.paths[0][2].channel_features.le_flags(), &id_to_feature_flags(3)); // 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, &net_graph_msg_handler.network_graph, &nodes[2], None, Some(&our_chans.iter().collect::>()), &Vec::new(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[7]); @@ -2347,12 +2399,14 @@ mod tests { let mut invalid_last_hops = last_hops_multi_private_channels(&nodes); invalid_last_hops.push(invalid_last_hop); { - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &invalid_last_hops.iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer) { - assert_eq!(err, "Last hop cannot have a payee as a source."); + 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) { + assert_eq!(err, "Route hint cannot have the payee as the source."); } else { panic!(); } } - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &last_hops_multi_private_channels(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths[0].len(), 5); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2421,11 +2475,12 @@ mod tests { fn ignores_empty_last_hops_test() { let (secp_ctx, net_graph_msg_handler, _, 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); // Test handling of an empty RouteHint passed in Invoice. - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &empty_last_hop(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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]); @@ -2502,6 +2557,7 @@ mod tests { fn multi_hint_last_hops_test() { let (secp_ctx, 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); // Test through channels 2, 3, 5, 8. // Test shows that multiple hop hints are considered. @@ -2532,7 +2588,7 @@ mod tests { excess_data: Vec::new() }); - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &multi_hint_last_hops(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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]); @@ -2607,11 +2663,12 @@ mod tests { fn last_hops_with_public_channel_test() { let (secp_ctx, net_graph_msg_handler, _, 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); // 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, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &last_hops_with_public_channel(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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]); @@ -2661,7 +2718,8 @@ mod tests { // 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 route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, Some(&our_chans.iter().collect::>()), &last_hops.iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths[0].len(), 2); assert_eq!(route.paths[0][0].pubkey, nodes[3]); @@ -2681,7 +2739,8 @@ mod tests { last_hops[0].0[0].fees.base_msat = 1000; // Revert to via 6 as the fee on 8 goes up - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &last_hops.iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths[0].len(), 4); assert_eq!(route.paths[0][0].pubkey, nodes[1]); @@ -2715,7 +2774,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, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &last_hops.iter().collect::>(), 2000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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]); @@ -2773,9 +2832,10 @@ mod tests { htlc_minimum_msat: None, htlc_maximum_msat: last_hop_htlc_max, }]); + 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); - get_route(&source_node_id, &NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()), &target_node_id, None, Some(&our_chans.iter().collect::>()), &vec![&last_hops], route_val, 42, &test_utils::TestLogger::new(), &scorer) + 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) } #[test] @@ -2829,6 +2889,7 @@ mod tests { let (secp_ctx, 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 payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); // We will use a simple single-path route from // our node to node2 via node0: channels {1, 3}. @@ -2891,16 +2952,15 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 250_000_001, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 250_000_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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); @@ -2928,16 +2988,15 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), Some(&our_chans.iter().collect::>()), &Vec::new(), 200_000_001, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), Some(&our_chans.iter().collect::>()), &Vec::new(), 200_000_000, 42, Arc::clone(&logger), &scorer).unwrap(); + 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(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.len(), 2); @@ -2976,16 +3035,15 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 15_001, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 15_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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); @@ -3047,16 +3105,15 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 15_001, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 15_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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); @@ -3080,16 +3137,15 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 10_001, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 10_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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); @@ -3105,6 +3161,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(0); + let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known()); // 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. @@ -3189,16 +3246,15 @@ mod tests { }); { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 60_000, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 49_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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 { @@ -3211,8 +3267,7 @@ mod tests { { // Attempt to route an exact amount is also fine - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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 { @@ -3229,6 +3284,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(0); + let payee = Payee::new(nodes[2]); // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50). update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate { @@ -3257,7 +3313,7 @@ mod tests { }); { - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 50_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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 { @@ -3274,6 +3330,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(0); + let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); // We need a route consisting of 3 paths: // From our node to node2 via node0, node7, node1 (three paths one hop each). @@ -3365,8 +3422,8 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, - &nodes[2], Some(InvoiceFeatures::known()), None, &Vec::new(), 300_000, 42, Arc::clone(&logger), &scorer) { + 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) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -3374,8 +3431,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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 250_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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 { @@ -3388,8 +3444,7 @@ mod tests { { // Attempt to route an exact amount is also fine - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 290_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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 { @@ -3406,6 +3461,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(0); + let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known()); // We need a route consisting of 3 paths: // From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}. @@ -3540,8 +3596,8 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 350_000, 42, Arc::clone(&logger), &scorer) { + 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) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -3549,8 +3605,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, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 300_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 300_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; @@ -3568,6 +3623,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(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, // so that liquidity-wise any 2 of 3 combination is sufficient, @@ -3707,8 +3763,7 @@ mod tests { { // Now, attempt to route 180 sats. // Our algorithm should provide us with these 2 paths. - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 180_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 180_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_value_transferred_msat = 0; @@ -3735,6 +3790,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(0); + let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known()); // We need a route consisting of 2 paths: // From our node to node3 via {node0, node2} and {node7, node2, node4}. @@ -3874,16 +3930,15 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 210_000, 42, Arc::clone(&logger), &scorer) { + 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) { 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, &net_graph_msg_handler.network_graph, &nodes[3], - Some(InvoiceFeatures::known()), None, &Vec::new(), 200_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 200_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; @@ -3904,6 +3959,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(0); + let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known()); // We need a route consisting of 3 paths: // From our node to node2 via node0, node7, node1 (three paths one hop each). @@ -3994,8 +4050,8 @@ mod tests { { // Attempt to route more than available results in a failure. - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 150_000, 42, Arc::clone(&logger), &scorer) { + 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) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } @@ -4003,8 +4059,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, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 125_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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 { @@ -4017,8 +4072,7 @@ mod tests { { // Attempt to route without the last small cheap channel - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[2], - Some(InvoiceFeatures::known()), None, &Vec::new(), 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.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 { @@ -4062,6 +4116,7 @@ mod tests { let net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, None, Arc::clone(&logger)); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(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); update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate { @@ -4154,7 +4209,7 @@ mod tests { { // Now ensure the route flows simply over nodes 1 and 4 to 6. - let route = get_route(&our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, &Vec::new(), 10_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 10_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), 3); @@ -4190,6 +4245,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, _, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(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 // send. @@ -4222,7 +4278,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, &net_graph_msg_handler.network_graph, &nodes[2], None, None, &Vec::new(), 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), 2); @@ -4251,6 +4307,7 @@ mod tests { let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let scorer = Scorer::new(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 // gets an htlc_maximum_msat of 80_000 and channel 4 an htlc_minimum_msat of 90_000. We @@ -4284,7 +4341,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, &net_graph_msg_handler.network_graph, &nodes[2], Some(InvoiceFeatures::known()), None, &Vec::new(), 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); + let route = get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), 2); @@ -4317,12 +4374,13 @@ mod tests { 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 payee = Payee::new(nodes[0]).with_features(InvoiceFeatures::known()); { - let route = get_route(&our_id, &network_graph, &nodes[0], Some(InvoiceFeatures::known()), Some(&[ + let route = get_route(&our_id, &payee, &network_graph, Some(&[ &get_channel_details(Some(3), nodes[0], InitFeatures::known(), 200_000), &get_channel_details(Some(2), nodes[0], InitFeatures::known(), 10_000), - ]), &[], 100_000, 42, Arc::clone(&logger), &scorer).unwrap(); + ]), 100_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), 1); @@ -4331,10 +4389,10 @@ mod tests { assert_eq!(route.paths[0][0].fee_msat, 100_000); } { - let route = get_route(&our_id, &network_graph, &nodes[0], Some(InvoiceFeatures::known()), Some(&[ + let route = get_route(&our_id, &payee, &network_graph, Some(&[ &get_channel_details(Some(3), nodes[0], InitFeatures::known(), 50_000), &get_channel_details(Some(2), nodes[0], InitFeatures::known(), 50_000), - ]), &[], 100_000, 42, Arc::clone(&logger), &scorer).unwrap(); + ]), 100_000, 42, Arc::clone(&logger), &scorer).unwrap(); assert_eq!(route.paths.len(), 2); assert_eq!(route.paths[0].len(), 1); assert_eq!(route.paths[1].len(), 1); @@ -4353,12 +4411,13 @@ mod tests { fn prefers_shorter_route_with_higher_fees() { let (secp_ctx, net_graph_msg_handler, _, 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 route = get_route( - &our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, - &last_hops(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer + &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4370,8 +4429,8 @@ mod tests { // from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper. let scorer = Scorer::new(100); let route = get_route( - &our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, - &last_hops(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer + &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4404,12 +4463,13 @@ mod tests { fn avoids_routing_through_bad_channels_and_nodes() { let (secp_ctx, net_graph_msg_handler, _, 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 route = get_route( - &our_id, &net_graph_msg_handler.network_graph, &nodes[6], None, None, - &last_hops(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer + &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4420,8 +4480,8 @@ 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, &net_graph_msg_handler.network_graph, &nodes[6], None, None, - &last_hops(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer + &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + Arc::clone(&logger), &scorer ).unwrap(); let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::>(); @@ -4432,8 +4492,8 @@ 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, &net_graph_msg_handler.network_graph, &nodes[6], None, None, - &last_hops(&nodes).iter().collect::>(), 100, 42, Arc::clone(&logger), &scorer + &our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42, + Arc::clone(&logger), &scorer ) { Err(LightningError { err, .. } ) => { assert_eq!(err, "Failed to find a path to the given destination"); @@ -4543,9 +4603,10 @@ mod tests { seed = seed.overflowing_mul(0xdeadbeef).0; let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); seed = seed.overflowing_mul(0xdeadbeef).0; - let dst = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); + let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); + let payee = Payee::new(dst); let amt = seed as u64 % 200_000_000; - if get_route(src, &graph, dst, None, None, &[], amt, 42, &test_utils::TestLogger::new(), &scorer).is_ok() { + if get_route(src, &payee, &graph, None, amt, 42, &test_utils::TestLogger::new(), &scorer).is_ok() { continue 'load_endpoints; } } @@ -4573,9 +4634,10 @@ mod tests { seed = seed.overflowing_mul(0xdeadbeef).0; let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); seed = seed.overflowing_mul(0xdeadbeef).0; - let dst = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); + let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); + let payee = Payee::new(dst).with_features(InvoiceFeatures::known()); let amt = seed as u64 % 200_000_000; - if get_route(src, &graph, dst, Some(InvoiceFeatures::known()), None, &[], amt, 42, &test_utils::TestLogger::new(), &scorer).is_ok() { + if get_route(src, &payee, &graph, None, amt, 42, &test_utils::TestLogger::new(), &scorer).is_ok() { continue 'load_endpoints; } } @@ -4639,8 +4701,9 @@ mod benches { let src = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); seed *= 0xdeadbeef; let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); + let payee = Payee::new(dst); let amt = seed as u64 % 1_000_000; - if get_route(&src, &graph, &dst, None, None, &[], amt, 42, &DummyLogger{}, &scorer).is_ok() { + if get_route(&src, &payee, &graph, None, amt, 42, &DummyLogger{}, &scorer).is_ok() { path_endpoints.push((src, dst, amt)); continue 'load_endpoints; } @@ -4651,7 +4714,8 @@ mod benches { let mut idx = 0; bench.iter(|| { let (src, dst, amt) = path_endpoints[idx % path_endpoints.len()]; - assert!(get_route(&src, &graph, &dst, None, None, &[], amt, 42, &DummyLogger{}, &scorer).is_ok()); + let payee = Payee::new(dst); + assert!(get_route(&src, &payee, &graph, None, amt, 42, &DummyLogger{}, &scorer).is_ok()); idx += 1; }); } @@ -4672,8 +4736,9 @@ mod benches { let src = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); seed *= 0xdeadbeef; let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); + let payee = Payee::new(dst).with_features(InvoiceFeatures::known()); let amt = seed as u64 % 1_000_000; - if get_route(&src, &graph, &dst, Some(InvoiceFeatures::known()), None, &[], amt, 42, &DummyLogger{}, &scorer).is_ok() { + if get_route(&src, &payee, &graph, None, amt, 42, &DummyLogger{}, &scorer).is_ok() { path_endpoints.push((src, dst, amt)); continue 'load_endpoints; } @@ -4684,7 +4749,8 @@ mod benches { let mut idx = 0; bench.iter(|| { let (src, dst, amt) = path_endpoints[idx % path_endpoints.len()]; - assert!(get_route(&src, &graph, &dst, Some(InvoiceFeatures::known()), None, &[], amt, 42, &DummyLogger{}, &scorer).is_ok()); + let payee = Payee::new(dst).with_features(InvoiceFeatures::known()); + assert!(get_route(&src, &payee, &graph, None, amt, 42, &DummyLogger{}, &scorer).is_ok()); idx += 1; }); } diff --git a/lightning/src/routing/scorer.rs b/lightning/src/routing/scorer.rs index 0f43c3d79..841d4bdba 100644 --- a/lightning/src/routing/scorer.rs +++ b/lightning/src/routing/scorer.rs @@ -18,7 +18,7 @@ //! # extern crate secp256k1; //! # //! # use lightning::routing::network_graph::NetworkGraph; -//! # use lightning::routing::router::get_route; +//! # use lightning::routing::router::{Payee, get_route}; //! # use lightning::routing::scorer::Scorer; //! # use lightning::util::logger::{Logger, Record}; //! # use secp256k1::key::PublicKey; @@ -27,7 +27,7 @@ //! # impl Logger for FakeLogger { //! # fn log(&self, record: &Record) { unimplemented!() } //! # } -//! # fn find_scored_route(payer: PublicKey, payee: PublicKey, network_graph: NetworkGraph) { +//! # fn find_scored_route(payer: PublicKey, payee: Payee, network_graph: NetworkGraph) { //! # let logger = FakeLogger {}; //! # //! // Use the default channel penalty. @@ -36,7 +36,7 @@ //! // Or use a custom channel penalty. //! let scorer = Scorer::new(1_000); //! -//! let route = get_route(&payer, &network_graph, &payee, None, None, &vec![], 1_000, 42, &logger, &scorer); +//! let route = get_route(&payer, &payee, &network_graph, None, 1_000, 42, &logger, &scorer); //! # } //! ``` //! -- 2.39.5