mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 06:57:53 +01:00
Unify route finding methods
An upcoming Router interface will be used for finding a Route both when initially sending a payment and also when retrying failed payment paths. Unify the three varieties of get_route so the interface can consist of a single method implemented by the new `find_route` method. Give get_route pub(crate) visibility so it can still be used in tests.
This commit is contained in:
parent
5feb4dc9c4
commit
2d102a3065
9 changed files with 135 additions and 108 deletions
|
@ -38,7 +38,7 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig
|
||||||
use lightning::ln::msgs::DecodeError;
|
use lightning::ln::msgs::DecodeError;
|
||||||
use lightning::ln::script::ShutdownScript;
|
use lightning::ln::script::ShutdownScript;
|
||||||
use lightning::routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
|
use lightning::routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
|
||||||
use lightning::routing::router::{get_route, Payee};
|
use lightning::routing::router::{find_route, Payee, RouteParameters};
|
||||||
use lightning::routing::scorer::Scorer;
|
use lightning::routing::scorer::Scorer;
|
||||||
use lightning::util::config::UserConfig;
|
use lightning::util::config::UserConfig;
|
||||||
use lightning::util::errors::APIError;
|
use lightning::util::errors::APIError;
|
||||||
|
@ -437,9 +437,14 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
4 => {
|
4 => {
|
||||||
let value = slice_to_be24(get_slice!(3)) as u64;
|
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
|
||||||
let payee = Payee::new(get_pubkey!());
|
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) {
|
let params = RouteParameters {
|
||||||
|
payee,
|
||||||
|
final_value_msat,
|
||||||
|
final_cltv_expiry_delta: 42,
|
||||||
|
};
|
||||||
|
let route = match find_route(&our_id, ¶ms, &net_graph_msg_handler.network_graph, None, Arc::clone(&logger), &scorer) {
|
||||||
Ok(route) => route,
|
Ok(route) => route,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
@ -455,9 +460,14 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
15 => {
|
15 => {
|
||||||
let value = slice_to_be24(get_slice!(3)) as u64;
|
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
|
||||||
let payee = Payee::new(get_pubkey!());
|
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) {
|
let params = RouteParameters {
|
||||||
|
payee,
|
||||||
|
final_value_msat,
|
||||||
|
final_cltv_expiry_delta: 42,
|
||||||
|
};
|
||||||
|
let mut route = match find_route(&our_id, ¶ms, &net_graph_msg_handler.network_graph, None, Arc::clone(&logger), &scorer) {
|
||||||
Ok(route) => route,
|
Ok(route) => route,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ use lightning::chain::transaction::OutPoint;
|
||||||
use lightning::ln::channelmanager::{ChannelDetails, ChannelCounterparty};
|
use lightning::ln::channelmanager::{ChannelDetails, ChannelCounterparty};
|
||||||
use lightning::ln::features::InitFeatures;
|
use lightning::ln::features::InitFeatures;
|
||||||
use lightning::ln::msgs;
|
use lightning::ln::msgs;
|
||||||
use lightning::routing::router::{get_route, Payee, RouteHint, RouteHintHop};
|
use lightning::routing::router::{find_route, Payee, RouteHint, RouteHintHop, RouteParameters};
|
||||||
use lightning::routing::scorer::Scorer;
|
use lightning::routing::scorer::Scorer;
|
||||||
use lightning::util::logger::Logger;
|
use lightning::util::logger::Logger;
|
||||||
use lightning::util::ser::Readable;
|
use lightning::util::ser::Readable;
|
||||||
|
@ -250,10 +250,14 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
|
||||||
}
|
}
|
||||||
let scorer = Scorer::new(0);
|
let scorer = Scorer::new(0);
|
||||||
for target in node_pks.iter() {
|
for target in node_pks.iter() {
|
||||||
let payee = Payee::new(*target).with_route_hints(last_hops.clone());
|
let params = RouteParameters {
|
||||||
let _ = get_route(&our_pubkey, &payee, &net_graph,
|
payee: Payee::new(*target).with_route_hints(last_hops.clone()),
|
||||||
|
final_value_msat: slice_to_be64(get_slice!(8)),
|
||||||
|
final_cltv_expiry_delta: slice_to_be32(get_slice!(4)),
|
||||||
|
};
|
||||||
|
let _ = find_route(&our_pubkey, ¶ms, &net_graph,
|
||||||
first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
|
first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
|
||||||
slice_to_be64(get_slice!(8)), slice_to_be32(get_slice!(4)), Arc::clone(&logger), &scorer);
|
Arc::clone(&logger), &scorer);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ mod test {
|
||||||
use lightning::ln::functional_test_utils::*;
|
use lightning::ln::functional_test_utils::*;
|
||||||
use lightning::ln::features::InitFeatures;
|
use lightning::ln::features::InitFeatures;
|
||||||
use lightning::ln::msgs::ChannelMessageHandler;
|
use lightning::ln::msgs::ChannelMessageHandler;
|
||||||
use lightning::routing::router;
|
use lightning::routing::router::{Payee, RouteParameters, find_route};
|
||||||
use lightning::routing::scorer::Scorer;
|
use lightning::routing::scorer::Scorer;
|
||||||
use lightning::util::events::MessageSendEventsProvider;
|
use lightning::util::events::MessageSendEventsProvider;
|
||||||
use lightning::util::test_utils;
|
use lightning::util::test_utils;
|
||||||
|
@ -113,23 +113,21 @@ mod test {
|
||||||
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
|
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
|
||||||
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
|
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
|
||||||
|
|
||||||
let payee = router::Payee::new(invoice.recover_payee_pub_key())
|
let payee = Payee::new(invoice.recover_payee_pub_key())
|
||||||
.with_features(invoice.features().unwrap().clone())
|
.with_features(invoice.features().unwrap().clone())
|
||||||
.with_route_hints(invoice.route_hints());
|
.with_route_hints(invoice.route_hints());
|
||||||
let amt_msat = invoice.amount_pico_btc().unwrap() / 10;
|
let params = RouteParameters {
|
||||||
|
payee,
|
||||||
|
final_value_msat: invoice.amount_milli_satoshis().unwrap(),
|
||||||
|
final_cltv_expiry_delta: invoice.min_final_cltv_expiry() as u32,
|
||||||
|
};
|
||||||
let first_hops = nodes[0].node.list_usable_channels();
|
let first_hops = nodes[0].node.list_usable_channels();
|
||||||
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
||||||
let logger = test_utils::TestLogger::new();
|
let logger = test_utils::TestLogger::new();
|
||||||
let scorer = Scorer::new(0);
|
let scorer = Scorer::new(0);
|
||||||
let route = router::get_route(
|
let route = find_route(
|
||||||
&nodes[0].node.get_our_node_id(),
|
&nodes[0].node.get_our_node_id(), ¶ms, network_graph,
|
||||||
&payee,
|
Some(&first_hops.iter().collect::<Vec<_>>()), &logger, &scorer,
|
||||||
network_graph,
|
|
||||||
Some(&first_hops.iter().collect::<Vec<_>>()),
|
|
||||||
amt_msat,
|
|
||||||
invoice.min_final_cltv_expiry() as u32,
|
|
||||||
&logger,
|
|
||||||
&scorer,
|
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let payment_event = {
|
let payment_event = {
|
||||||
|
|
|
@ -45,7 +45,7 @@ use chain::transaction::{OutPoint, TransactionData};
|
||||||
use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
|
use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
|
||||||
use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
|
use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
|
||||||
use ln::features::{InitFeatures, NodeFeatures};
|
use ln::features::{InitFeatures, NodeFeatures};
|
||||||
use routing::router::{Payee, PaymentPathRetry, Route, RouteHop};
|
use routing::router::{Payee, Route, RouteHop, RouteParameters};
|
||||||
use ln::msgs;
|
use ln::msgs;
|
||||||
use ln::msgs::NetAddress;
|
use ln::msgs::NetAddress;
|
||||||
use ln::onion_utils;
|
use ln::onion_utils;
|
||||||
|
@ -3112,7 +3112,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
||||||
!payment.get().is_fulfilled()
|
!payment.get().is_fulfilled()
|
||||||
{
|
{
|
||||||
let retry = if let Some(payee_data) = payee {
|
let retry = if let Some(payee_data) = payee {
|
||||||
Some(PaymentPathRetry {
|
Some(RouteParameters {
|
||||||
payee: payee_data,
|
payee: payee_data,
|
||||||
final_value_msat: path_last_hop.fee_msat,
|
final_value_msat: path_last_hop.fee_msat,
|
||||||
final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta,
|
final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta,
|
||||||
|
@ -3183,7 +3183,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
||||||
}
|
}
|
||||||
mem::drop(channel_state_lock);
|
mem::drop(channel_state_lock);
|
||||||
let retry = if let Some(payee_data) = payee {
|
let retry = if let Some(payee_data) = payee {
|
||||||
Some(PaymentPathRetry {
|
Some(RouteParameters {
|
||||||
payee: payee_data.clone(),
|
payee: payee_data.clone(),
|
||||||
final_value_msat: path_last_hop.fee_msat,
|
final_value_msat: path_last_hop.fee_msat,
|
||||||
final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta,
|
final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta,
|
||||||
|
@ -6036,15 +6036,14 @@ mod tests {
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
|
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
|
||||||
use ln::channelmanager::{PaymentId, PaymentSendFailure};
|
use ln::channelmanager::{PaymentId, PaymentSendFailure};
|
||||||
use ln::features::{InitFeatures, InvoiceFeatures};
|
use ln::features::InitFeatures;
|
||||||
use ln::functional_test_utils::*;
|
use ln::functional_test_utils::*;
|
||||||
use ln::msgs;
|
use ln::msgs;
|
||||||
use ln::msgs::ChannelMessageHandler;
|
use ln::msgs::ChannelMessageHandler;
|
||||||
use routing::router::{Payee, get_keysend_route, get_route};
|
use routing::router::{Payee, RouteParameters, find_route};
|
||||||
use routing::scorer::Scorer;
|
use routing::scorer::Scorer;
|
||||||
use util::errors::APIError;
|
use util::errors::APIError;
|
||||||
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
|
use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
|
||||||
use util::test_utils;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -6280,7 +6279,6 @@ mod tests {
|
||||||
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
|
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
|
||||||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
||||||
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
|
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
|
||||||
let logger = test_utils::TestLogger::new();
|
|
||||||
let scorer = Scorer::new(0);
|
let scorer = Scorer::new(0);
|
||||||
|
|
||||||
// To start (1), send a regular payment but don't claim it.
|
// To start (1), send a regular payment but don't claim it.
|
||||||
|
@ -6288,9 +6286,15 @@ mod tests {
|
||||||
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &expected_route, 100_000);
|
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &expected_route, 100_000);
|
||||||
|
|
||||||
// Next, attempt a keysend payment and make sure it fails.
|
// Next, attempt a keysend payment and make sure it fails.
|
||||||
let payee = Payee::new(expected_route.last().unwrap().node.get_our_node_id())
|
let params = RouteParameters {
|
||||||
.with_features(InvoiceFeatures::known());
|
payee: Payee::for_keysend(expected_route.last().unwrap().node.get_our_node_id()),
|
||||||
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();
|
final_value_msat: 100_000,
|
||||||
|
final_cltv_expiry_delta: TEST_FINAL_CLTV,
|
||||||
|
};
|
||||||
|
let route = find_route(
|
||||||
|
&nodes[0].node.get_our_node_id(), ¶ms,
|
||||||
|
&nodes[0].net_graph_msg_handler.network_graph, None, nodes[0].logger, &scorer
|
||||||
|
).unwrap();
|
||||||
nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
|
nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
|
||||||
check_added_monitors!(nodes[0], 1);
|
check_added_monitors!(nodes[0], 1);
|
||||||
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
|
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
|
||||||
|
@ -6318,7 +6322,10 @@ mod tests {
|
||||||
|
|
||||||
// To start (2), send a keysend payment but don't claim it.
|
// To start (2), send a keysend payment but don't claim it.
|
||||||
let payment_preimage = PaymentPreimage([42; 32]);
|
let payment_preimage = PaymentPreimage([42; 32]);
|
||||||
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 route = find_route(
|
||||||
|
&nodes[0].node.get_our_node_id(), ¶ms,
|
||||||
|
&nodes[0].net_graph_msg_handler.network_graph, None, nodes[0].logger, &scorer
|
||||||
|
).unwrap();
|
||||||
let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
|
let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
|
||||||
check_added_monitors!(nodes[0], 1);
|
check_added_monitors!(nodes[0], 1);
|
||||||
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
|
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
|
||||||
|
@ -6370,12 +6377,18 @@ mod tests {
|
||||||
nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() });
|
nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() });
|
||||||
|
|
||||||
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
|
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
|
||||||
|
let params = RouteParameters {
|
||||||
|
payee: Payee::for_keysend(payee_pubkey),
|
||||||
|
final_value_msat: 10000,
|
||||||
|
final_cltv_expiry_delta: 40,
|
||||||
|
};
|
||||||
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
||||||
let first_hops = nodes[0].node.list_usable_channels();
|
let first_hops = nodes[0].node.list_usable_channels();
|
||||||
let scorer = Scorer::new(0);
|
let scorer = Scorer::new(0);
|
||||||
let route = get_keysend_route(&payer_pubkey, network_graph, &payee_pubkey,
|
let route = find_route(
|
||||||
Some(&first_hops.iter().collect::<Vec<_>>()), &vec![], 10000, 40,
|
&payer_pubkey, ¶ms, network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
|
||||||
nodes[0].logger, &scorer).unwrap();
|
nodes[0].logger, &scorer
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
let test_preimage = PaymentPreimage([42; 32]);
|
let test_preimage = PaymentPreimage([42; 32]);
|
||||||
let mismatch_payment_hash = PaymentHash([43; 32]);
|
let mismatch_payment_hash = PaymentHash([43; 32]);
|
||||||
|
@ -6407,12 +6420,18 @@ mod tests {
|
||||||
nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() });
|
nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() });
|
||||||
|
|
||||||
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
|
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
|
||||||
|
let params = RouteParameters {
|
||||||
|
payee: Payee::for_keysend(payee_pubkey),
|
||||||
|
final_value_msat: 10000,
|
||||||
|
final_cltv_expiry_delta: 40,
|
||||||
|
};
|
||||||
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
||||||
let first_hops = nodes[0].node.list_usable_channels();
|
let first_hops = nodes[0].node.list_usable_channels();
|
||||||
let scorer = Scorer::new(0);
|
let scorer = Scorer::new(0);
|
||||||
let route = get_keysend_route(&payer_pubkey, network_graph, &payee_pubkey,
|
let route = find_route(
|
||||||
Some(&first_hops.iter().collect::<Vec<_>>()), &vec![], 10000, 40,
|
&payer_pubkey, ¶ms, network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
|
||||||
nodes[0].logger, &scorer).unwrap();
|
nodes[0].logger, &scorer
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
let test_preimage = PaymentPreimage([42; 32]);
|
let test_preimage = PaymentPreimage([42; 32]);
|
||||||
let test_secret = PaymentSecret([43; 32]);
|
let test_secret = PaymentSecret([43; 32]);
|
||||||
|
|
|
@ -432,11 +432,11 @@ impl InvoiceFeatures {
|
||||||
/// Getting a route for a keysend payment to a private node requires providing the payee's
|
/// Getting a route for a keysend payment to a private node requires providing the payee's
|
||||||
/// features (since they were not announced in a node announcement). However, keysend payments
|
/// features (since they were not announced in a node announcement). However, keysend payments
|
||||||
/// don't have an invoice to pull the payee's features from, so this method is provided for use in
|
/// don't have an invoice to pull the payee's features from, so this method is provided for use in
|
||||||
/// [`get_keysend_route`], thus omitting the need for payers to manually construct an
|
/// [`Payee::for_keysend`], thus omitting the need for payers to manually construct an
|
||||||
/// `InvoiceFeatures` for [`get_route`].
|
/// `InvoiceFeatures` for [`find_route`].
|
||||||
///
|
///
|
||||||
/// [`get_keysend_route`]: crate::routing::router::get_keysend_route
|
/// [`Payee::for_keysend`]: crate::routing::router::Payee::for_keysend
|
||||||
/// [`get_route`]: crate::routing::router::get_route
|
/// [`find_route`]: crate::routing::router::find_route
|
||||||
pub(crate) fn for_keysend() -> InvoiceFeatures {
|
pub(crate) fn for_keysend() -> InvoiceFeatures {
|
||||||
InvoiceFeatures::empty().set_variable_length_onion_optional()
|
InvoiceFeatures::empty().set_variable_length_onion_optional()
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ use ln::channel::{Channel, ChannelError};
|
||||||
use ln::{chan_utils, onion_utils};
|
use ln::{chan_utils, onion_utils};
|
||||||
use ln::chan_utils::HTLC_SUCCESS_TX_WEIGHT;
|
use ln::chan_utils::HTLC_SUCCESS_TX_WEIGHT;
|
||||||
use routing::network_graph::{NetworkUpdate, RoutingFees};
|
use routing::network_graph::{NetworkUpdate, RoutingFees};
|
||||||
use routing::router::{Payee, Route, RouteHop, RouteHint, RouteHintHop, get_route, get_keysend_route};
|
use routing::router::{Payee, Route, RouteHop, RouteHint, RouteHintHop, RouteParameters, find_route, get_route};
|
||||||
use routing::scorer::Scorer;
|
use routing::scorer::Scorer;
|
||||||
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
|
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
|
||||||
use ln::msgs;
|
use ln::msgs;
|
||||||
|
@ -9056,10 +9056,13 @@ fn test_keysend_payments_to_public_node() {
|
||||||
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
||||||
let payer_pubkey = nodes[0].node.get_our_node_id();
|
let payer_pubkey = nodes[0].node.get_our_node_id();
|
||||||
let payee_pubkey = nodes[1].node.get_our_node_id();
|
let payee_pubkey = nodes[1].node.get_our_node_id();
|
||||||
|
let params = RouteParameters {
|
||||||
|
payee: Payee::for_keysend(payee_pubkey),
|
||||||
|
final_value_msat: 10000,
|
||||||
|
final_cltv_expiry_delta: 40,
|
||||||
|
};
|
||||||
let scorer = Scorer::new(0);
|
let scorer = Scorer::new(0);
|
||||||
let route = get_keysend_route(
|
let route = find_route(&payer_pubkey, ¶ms, &network_graph, None, nodes[0].logger, &scorer).unwrap();
|
||||||
&payer_pubkey, &network_graph, &payee_pubkey, None, &vec![], 10000, 40, nodes[0].logger, &scorer
|
|
||||||
).unwrap();
|
|
||||||
|
|
||||||
let test_preimage = PaymentPreimage([42; 32]);
|
let test_preimage = PaymentPreimage([42; 32]);
|
||||||
let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
|
let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
|
||||||
|
@ -9085,12 +9088,17 @@ fn test_keysend_payments_to_private_node() {
|
||||||
nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() });
|
nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() });
|
||||||
|
|
||||||
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
|
let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
|
||||||
|
let params = RouteParameters {
|
||||||
|
payee: Payee::for_keysend(payee_pubkey),
|
||||||
|
final_value_msat: 10000,
|
||||||
|
final_cltv_expiry_delta: 40,
|
||||||
|
};
|
||||||
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
let network_graph = &nodes[0].net_graph_msg_handler.network_graph;
|
||||||
let first_hops = nodes[0].node.list_usable_channels();
|
let first_hops = nodes[0].node.list_usable_channels();
|
||||||
let scorer = Scorer::new(0);
|
let scorer = Scorer::new(0);
|
||||||
let route = get_keysend_route(
|
let route = find_route(
|
||||||
&payer_pubkey, &network_graph, &payee_pubkey, Some(&first_hops.iter().collect::<Vec<_>>()),
|
&payer_pubkey, ¶ms, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
|
||||||
&vec![], 10000, 40, nodes[0].logger, &scorer
|
nodes[0].logger, &scorer
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let test_preimage = PaymentPreimage([42; 32]);
|
let test_preimage = PaymentPreimage([42; 32]);
|
||||||
|
|
|
@ -70,7 +70,7 @@ pub struct Route {
|
||||||
/// given path is variable, keeping the length of any path to less than 20 should currently
|
/// given path is variable, keeping the length of any path to less than 20 should currently
|
||||||
/// ensure it is viable.
|
/// ensure it is viable.
|
||||||
pub paths: Vec<Vec<RouteHop>>,
|
pub paths: Vec<Vec<RouteHop>>,
|
||||||
/// The `payee` parameter passed to [`get_route`].
|
/// The `payee` parameter passed to [`find_route`].
|
||||||
/// This is used by `ChannelManager` to track information which may be required for retries,
|
/// This is used by `ChannelManager` to track information which may be required for retries,
|
||||||
/// provided back to you via [`Event::PaymentPathFailed`].
|
/// provided back to you via [`Event::PaymentPathFailed`].
|
||||||
///
|
///
|
||||||
|
@ -82,7 +82,7 @@ impl Route {
|
||||||
/// Returns the total amount of fees paid on this [`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
|
/// 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 {
|
pub fn get_total_fees(&self) -> u64 {
|
||||||
// Do not count last hop of each path since that's the full value of the payment
|
// Do not count last hop of each path since that's the full value of the payment
|
||||||
return self.paths.iter()
|
return self.paths.iter()
|
||||||
|
@ -140,13 +140,14 @@ impl Readable for Route {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parameters needed to re-compute a [`Route`] for retrying a failed payment path.
|
/// Parameters needed to find a [`Route`] for paying a [`Payee`].
|
||||||
///
|
///
|
||||||
/// Provided in [`Event::PaymentPathFailed`] and passed to [`get_retry_route`].
|
/// Passed to [`find_route`] and also provided in [`Event::PaymentPathFailed`] for retrying a failed
|
||||||
|
/// payment path.
|
||||||
///
|
///
|
||||||
/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
|
/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PaymentPathRetry {
|
pub struct RouteParameters {
|
||||||
/// The recipient of the failed payment path.
|
/// The recipient of the failed payment path.
|
||||||
pub payee: Payee,
|
pub payee: Payee,
|
||||||
|
|
||||||
|
@ -157,7 +158,7 @@ pub struct PaymentPathRetry {
|
||||||
pub final_cltv_expiry_delta: u32,
|
pub final_cltv_expiry_delta: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_writeable_tlv_based!(PaymentPathRetry, {
|
impl_writeable_tlv_based!(RouteParameters, {
|
||||||
(0, payee, required),
|
(0, payee, required),
|
||||||
(2, final_value_msat, required),
|
(2, final_value_msat, required),
|
||||||
(4, final_cltv_expiry_delta, required),
|
(4, final_cltv_expiry_delta, required),
|
||||||
|
@ -479,59 +480,46 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a keysend route from us (payer) to the given target node (payee). This is needed because
|
/// Finds a route from us (payer) to the given target node (payee).
|
||||||
/// 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<L: Deref, S: routing::Score>(
|
|
||||||
our_node_pubkey: &PublicKey, network: &NetworkGraph, payee: &PublicKey,
|
|
||||||
first_hops: Option<&[&ChannelDetails]>, last_hops: &[&RouteHint], final_value_msat: u64,
|
|
||||||
final_cltv_expiry_delta: u32, logger: L, scorer: &S
|
|
||||||
) -> Result<Route, LightningError>
|
|
||||||
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_expiry_delta,
|
|
||||||
logger, scorer
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a route suitable for retrying a failed payment path.
|
|
||||||
///
|
///
|
||||||
/// Used to re-compute a [`Route`] when handling a [`Event::PaymentPathFailed`]. Any adjustments to
|
/// If the payee provided features in their invoice, they should be provided via `params.payee`.
|
||||||
/// the [`NetworkGraph`] and channel scores should be made prior to calling this function.
|
/// 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
|
/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
|
||||||
pub fn get_retry_route<L: Deref, S: routing::Score>(
|
pub fn find_route<L: Deref, S: routing::Score>(
|
||||||
our_node_pubkey: &PublicKey, retry: &PaymentPathRetry, network: &NetworkGraph,
|
our_node_pubkey: &PublicKey, params: &RouteParameters, network: &NetworkGraph,
|
||||||
first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S
|
first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S
|
||||||
) -> Result<Route, LightningError>
|
) -> Result<Route, LightningError>
|
||||||
where L::Target: Logger {
|
where L::Target: Logger {
|
||||||
get_route(
|
get_route(
|
||||||
our_node_pubkey, &retry.payee, network, first_hops, retry.final_value_msat,
|
our_node_pubkey, ¶ms.payee, network, first_hops, params.final_value_msat,
|
||||||
retry.final_cltv_expiry_delta, logger, scorer
|
params.final_cltv_expiry_delta, logger, scorer
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a route from us (payer) to the given target node (payee).
|
pub(crate) fn get_route<L: Deref, S: routing::Score>(
|
||||||
///
|
|
||||||
/// 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`.
|
|
||||||
///
|
|
||||||
/// 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<L: Deref, S: routing::Score>(
|
|
||||||
our_node_pubkey: &PublicKey, payee: &Payee, network: &NetworkGraph,
|
our_node_pubkey: &PublicKey, payee: &Payee, network: &NetworkGraph,
|
||||||
first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv_expiry_delta: u32,
|
first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv_expiry_delta: u32,
|
||||||
logger: L, scorer: &S
|
logger: L, scorer: &S
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
//! Utilities for scoring payment channels.
|
//! Utilities for scoring payment channels.
|
||||||
//!
|
//!
|
||||||
//! [`Scorer`] may be given to [`get_route`] to score payment channels during path finding when a
|
//! [`Scorer`] may be given to [`find_route`] to score payment channels during path finding when a
|
||||||
//! custom [`routing::Score`] implementation is not needed.
|
//! custom [`routing::Score`] implementation is not needed.
|
||||||
//!
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
//! # extern crate secp256k1;
|
//! # extern crate secp256k1;
|
||||||
//! #
|
//! #
|
||||||
//! # use lightning::routing::network_graph::NetworkGraph;
|
//! # use lightning::routing::network_graph::NetworkGraph;
|
||||||
//! # use lightning::routing::router::{Payee, get_route};
|
//! # use lightning::routing::router::{RouteParameters, find_route};
|
||||||
//! # use lightning::routing::scorer::Scorer;
|
//! # use lightning::routing::scorer::Scorer;
|
||||||
//! # use lightning::util::logger::{Logger, Record};
|
//! # use lightning::util::logger::{Logger, Record};
|
||||||
//! # use secp256k1::key::PublicKey;
|
//! # use secp256k1::key::PublicKey;
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
//! # impl Logger for FakeLogger {
|
//! # impl Logger for FakeLogger {
|
||||||
//! # fn log(&self, record: &Record) { unimplemented!() }
|
//! # fn log(&self, record: &Record) { unimplemented!() }
|
||||||
//! # }
|
//! # }
|
||||||
//! # fn find_scored_route(payer: PublicKey, payee: Payee, network_graph: NetworkGraph) {
|
//! # fn find_scored_route(payer: PublicKey, params: RouteParameters, network_graph: NetworkGraph) {
|
||||||
//! # let logger = FakeLogger {};
|
//! # let logger = FakeLogger {};
|
||||||
//! #
|
//! #
|
||||||
//! // Use the default channel penalty.
|
//! // Use the default channel penalty.
|
||||||
|
@ -36,11 +36,11 @@
|
||||||
//! // Or use a custom channel penalty.
|
//! // Or use a custom channel penalty.
|
||||||
//! let scorer = Scorer::new(1_000);
|
//! let scorer = Scorer::new(1_000);
|
||||||
//!
|
//!
|
||||||
//! let route = get_route(&payer, &payee, &network_graph, None, 1_000, 42, &logger, &scorer);
|
//! let route = find_route(&payer, ¶ms, &network_graph, None, &logger, &scorer);
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! [`get_route`]: crate::routing::router::get_route
|
//! [`find_route`]: crate::routing::router::find_route
|
||||||
|
|
||||||
use routing;
|
use routing;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ use ln::msgs::DecodeError;
|
||||||
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
|
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
|
||||||
use routing::network_graph::NetworkUpdate;
|
use routing::network_graph::NetworkUpdate;
|
||||||
use util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
|
use util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
|
||||||
use routing::router::{PaymentPathRetry, RouteHop};
|
use routing::router::{RouteHop, RouteParameters};
|
||||||
|
|
||||||
use bitcoin::blockdata::script::Script;
|
use bitcoin::blockdata::script::Script;
|
||||||
use bitcoin::hashes::Hash;
|
use bitcoin::hashes::Hash;
|
||||||
|
@ -229,13 +229,13 @@ pub enum Event {
|
||||||
/// If this is `Some`, then the corresponding channel should be avoided when the payment is
|
/// If this is `Some`, then the corresponding channel should be avoided when the payment is
|
||||||
/// retried. May be `None` for older [`Event`] serializations.
|
/// retried. May be `None` for older [`Event`] serializations.
|
||||||
short_channel_id: Option<u64>,
|
short_channel_id: Option<u64>,
|
||||||
/// Parameters needed to re-compute a [`Route`] for retrying the failed path.
|
/// Parameters needed to compute a new [`Route`] when retrying the failed payment path.
|
||||||
///
|
///
|
||||||
/// See [`get_retry_route`] for details.
|
/// See [`find_route`] for details.
|
||||||
///
|
///
|
||||||
/// [`Route`]: crate::routing::router::Route
|
/// [`Route`]: crate::routing::router::Route
|
||||||
/// [`get_retry_route`]: crate::routing::router::get_retry_route
|
/// [`find_route`]: crate::routing::router::find_route
|
||||||
retry: Option<PaymentPathRetry>,
|
retry: Option<RouteParameters>,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
error_code: Option<u16>,
|
error_code: Option<u16>,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Add table
Reference in a new issue