Merge pull request #2237 from henghonglee/issue-2189-score-params

[#2189] Score Fee Params as a passed in parameter
This commit is contained in:
Matt Corallo 2023-05-11 05:27:14 +00:00 committed by GitHub
commit e61b128967
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 638 additions and 567 deletions

View file

@ -48,7 +48,7 @@ use lightning::util::config::UserConfig;
use lightning::util::errors::APIError; use lightning::util::errors::APIError;
use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
use lightning::util::logger::Logger; use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, ReadableArgs, Writeable}; use lightning::util::ser::{ReadableArgs, Writeable};
use crate::utils::test_logger; use crate::utils::test_logger;
use crate::utils::test_persister::TestPersister; use crate::utils::test_persister::TestPersister;

View file

@ -17,7 +17,7 @@ use lightning::ln::msgs;
use lightning::routing::gossip::{NetworkGraph, RoutingFees}; use lightning::routing::gossip::{NetworkGraph, RoutingFees};
use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResult}; use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResult};
use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters}; use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
use lightning::routing::scoring::ProbabilisticScorer; use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters};
use lightning::util::config::UserConfig; use lightning::util::config::UserConfig;
use lightning::util::ser::Readable; use lightning::util::ser::Readable;
@ -293,7 +293,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
}])); }]));
} }
} }
let scorer = ProbabilisticScorer::new(Default::default(), &net_graph, &logger); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &net_graph, &logger);
let random_seed_bytes: [u8; 32] = [get_slice!(1)[0]; 32]; let random_seed_bytes: [u8; 32] = [get_slice!(1)[0]; 32];
for target in node_pks.iter() { for target in node_pks.iter() {
let final_value_msat = slice_to_be64(get_slice!(8)); let final_value_msat = slice_to_be64(get_slice!(8));
@ -305,7 +305,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
}; };
let _ = find_route(&our_pubkey, &route_params, &net_graph, let _ = find_route(&our_pubkey, &route_params, &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()),
&logger, &scorer, &random_seed_bytes); &logger, &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes);
} }
}, },
} }

View file

@ -866,7 +866,7 @@ mod tests {
fn disconnect_socket(&mut self) {} fn disconnect_socket(&mut self) {}
} }
type ChannelManager = channelmanager::ChannelManager<Arc<ChainMonitor>, Arc<test_utils::TestBroadcaster>, Arc<KeysManager>, Arc<KeysManager>, Arc<KeysManager>, Arc<test_utils::TestFeeEstimator>, Arc<DefaultRouter< Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>, Arc<Mutex<TestScorer>>>>, Arc<test_utils::TestLogger>>; type ChannelManager = channelmanager::ChannelManager<Arc<ChainMonitor>, Arc<test_utils::TestBroadcaster>, Arc<KeysManager>, Arc<KeysManager>, Arc<KeysManager>, Arc<test_utils::TestFeeEstimator>, Arc<DefaultRouter<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>, Arc<Mutex<TestScorer>>, (), TestScorer>>, Arc<test_utils::TestLogger>>;
type ChainMonitor = chainmonitor::ChainMonitor<InMemorySigner, Arc<test_utils::TestChainSource>, Arc<test_utils::TestBroadcaster>, Arc<test_utils::TestFeeEstimator>, Arc<test_utils::TestLogger>, Arc<FilesystemPersister>>; type ChainMonitor = chainmonitor::ChainMonitor<InMemorySigner, Arc<test_utils::TestChainSource>, Arc<test_utils::TestBroadcaster>, Arc<test_utils::TestFeeEstimator>, Arc<test_utils::TestLogger>, Arc<FilesystemPersister>>;
@ -1000,8 +1000,9 @@ mod tests {
} }
impl Score for TestScorer { impl Score for TestScorer {
type ScoreParams = ();
fn channel_penalty_msat( fn channel_penalty_msat(
&self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage, _score_params: &Self::ScoreParams
) -> u64 { unimplemented!(); } ) -> u64 { unimplemented!(); }
fn payment_path_failed(&mut self, actual_path: &Path, actual_short_channel_id: u64) { fn payment_path_failed(&mut self, actual_path: &Path, actual_short_channel_id: u64) {
@ -1114,7 +1115,7 @@ mod tests {
let network_graph = Arc::new(NetworkGraph::new(network, logger.clone())); let network_graph = Arc::new(NetworkGraph::new(network, logger.clone()));
let scorer = Arc::new(Mutex::new(TestScorer::new())); let scorer = Arc::new(Mutex::new(TestScorer::new()));
let seed = [i as u8; 32]; let seed = [i as u8; 32];
let router = Arc::new(DefaultRouter::new(network_graph.clone(), logger.clone(), seed, scorer.clone())); let router = Arc::new(DefaultRouter::new(network_graph.clone(), logger.clone(), seed, scorer.clone(), ()));
let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet)); let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
let persister = Arc::new(FilesystemPersister::new(format!("{}_persister_{}", &persist_dir, i))); let persister = Arc::new(FilesystemPersister::new(format!("{}_persister_{}", &persist_dir, i)));
let now = Duration::from_secs(genesis_block.header.time as u64); let now = Duration::from_secs(genesis_block.header.time as u64);

View file

@ -46,7 +46,7 @@ use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, No
use crate::ln::features::InvoiceFeatures; use crate::ln::features::InvoiceFeatures;
use crate::routing::gossip::NetworkGraph; use crate::routing::gossip::NetworkGraph;
use crate::routing::router::{BlindedTail, DefaultRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteHop, RouteParameters, Router}; use crate::routing::router::{BlindedTail, DefaultRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteHop, RouteParameters, Router};
use crate::routing::scoring::ProbabilisticScorer; use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters};
use crate::ln::msgs; use crate::ln::msgs;
use crate::ln::onion_utils; use crate::ln::onion_utils;
use crate::ln::onion_utils::HTLCFailReason; use crate::ln::onion_utils::HTLCFailReason;
@ -625,7 +625,9 @@ pub type SimpleArcChannelManager<M, T, F, L> = ChannelManager<
Arc<DefaultRouter< Arc<DefaultRouter<
Arc<NetworkGraph<Arc<L>>>, Arc<NetworkGraph<Arc<L>>>,
Arc<L>, Arc<L>,
Arc<Mutex<ProbabilisticScorer<Arc<NetworkGraph<Arc<L>>>, Arc<L>>>> Arc<Mutex<ProbabilisticScorer<Arc<NetworkGraph<Arc<L>>>, Arc<L>>>>,
ProbabilisticScoringFeeParameters,
ProbabilisticScorer<Arc<NetworkGraph<Arc<L>>>, Arc<L>>,
>>, >>,
Arc<L> Arc<L>
>; >;
@ -641,7 +643,7 @@ pub type SimpleArcChannelManager<M, T, F, L> = ChannelManager<
/// of [`KeysManager`] and [`DefaultRouter`]. /// of [`KeysManager`] and [`DefaultRouter`].
/// ///
/// This is not exported to bindings users as Arcs don't make sense in bindings /// This is not exported to bindings users as Arcs don't make sense in bindings
pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> = ChannelManager<&'a M, &'b T, &'c KeysManager, &'c KeysManager, &'c KeysManager, &'d F, &'e DefaultRouter<&'f NetworkGraph<&'g L>, &'g L, &'h Mutex<ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>>>, &'g L>; pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> = ChannelManager<&'a M, &'b T, &'c KeysManager, &'c KeysManager, &'c KeysManager, &'d F, &'e DefaultRouter<&'f NetworkGraph<&'g L>, &'g L, &'h Mutex<ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>>, ProbabilisticScoringFeeParameters, ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>>, &'g L>;
/// A trivial trait which describes any [`ChannelManager`] used in testing. /// A trivial trait which describes any [`ChannelManager`] used in testing.
#[cfg(any(test, feature = "_test_utils"))] #[cfg(any(test, feature = "_test_utils"))]
@ -8584,7 +8586,7 @@ mod tests {
}; };
let route = find_route( let route = find_route(
&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph,
None, nodes[0].logger, &scorer, &random_seed_bytes None, nodes[0].logger, &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage),
RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.0)).unwrap(); RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.0)).unwrap();
@ -8618,7 +8620,7 @@ mod tests {
let payment_preimage = PaymentPreimage([42; 32]); let payment_preimage = PaymentPreimage([42; 32]);
let route = find_route( let route = find_route(
&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph,
None, nodes[0].logger, &scorer, &random_seed_bytes None, nodes[0].logger, &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage),
RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.0)).unwrap(); RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.0)).unwrap();
@ -8681,7 +8683,7 @@ mod tests {
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let route = find_route( let route = find_route(
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()), &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
nodes[0].logger, &scorer, &random_seed_bytes nodes[0].logger, &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let test_preimage = PaymentPreimage([42; 32]); let test_preimage = PaymentPreimage([42; 32]);
@ -8725,7 +8727,7 @@ mod tests {
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let route = find_route( let route = find_route(
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()), &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
nodes[0].logger, &scorer, &random_seed_bytes nodes[0].logger, &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let test_preimage = PaymentPreimage([42; 32]); let test_preimage = PaymentPreimage([42; 32]);

View file

@ -1738,7 +1738,7 @@ pub fn get_route(send_node: &Node, payment_params: &PaymentParameters, recv_valu
router::get_route( router::get_route(
&send_node.node.get_our_node_id(), payment_params, &send_node.network_graph.read_only(), &send_node.node.get_our_node_id(), payment_params, &send_node.network_graph.read_only(),
Some(&send_node.node.list_usable_channels().iter().collect::<Vec<_>>()), Some(&send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
recv_value, send_node.logger, &scorer, &random_seed_bytes recv_value, send_node.logger, &scorer, &(), &random_seed_bytes
) )
} }
@ -2328,7 +2328,7 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
let route = router::get_route( let route = router::get_route(
&origin_node.node.get_our_node_id(), &payment_params, &network_graph, &origin_node.node.get_our_node_id(), &payment_params, &network_graph,
None, recv_value, origin_node.logger, &scorer, &random_seed_bytes).unwrap(); None, recv_value, origin_node.logger, &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops.len(), expected_route.len()); assert_eq!(route.paths[0].hops.len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) { for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) {

View file

@ -7044,7 +7044,7 @@ fn test_check_htlc_underpaying() {
let scorer = test_utils::TestScorer::new(); let scorer = test_utils::TestScorer::new();
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[1].node.invoice_features()).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None, 10_000, nodes[0].logger, &scorer, &random_seed_bytes).unwrap(); let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None, 10_000, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]); 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, None).unwrap(); let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, None).unwrap();
nodes[0].node.send_payment_with_route(&route, our_payment_hash, nodes[0].node.send_payment_with_route(&route, our_payment_hash,
@ -7298,11 +7298,11 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
let scorer = test_utils::TestScorer::new(); let scorer = test_utils::TestScorer::new();
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None, let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None,
3_000_000, nodes[0].logger, &scorer, &random_seed_bytes).unwrap(); 3_000_000, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0; let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0;
let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), 50).with_bolt11_features(nodes[0].node.invoice_features()).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), 50).with_bolt11_features(nodes[0].node.invoice_features()).unwrap();
let route = get_route(&nodes[1].node.get_our_node_id(), &payment_params, &nodes[1].network_graph.read_only(), None, let route = get_route(&nodes[1].node.get_our_node_id(), &payment_params, &nodes[1].network_graph.read_only(), None,
3_000_000, nodes[0].logger, &scorer, &random_seed_bytes).unwrap(); 3_000_000, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000); send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000);
let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2); let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2);
@ -9520,7 +9520,7 @@ fn test_keysend_payments_to_public_node() {
}; };
let scorer = test_utils::TestScorer::new(); let scorer = test_utils::TestScorer::new();
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger, &scorer, &random_seed_bytes).unwrap(); let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger, &scorer, &(), &random_seed_bytes).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), let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage),
@ -9555,7 +9555,7 @@ fn test_keysend_payments_to_private_node() {
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
let route = find_route( let route = find_route(
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()), &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
nodes[0].logger, &scorer, &random_seed_bytes nodes[0].logger, &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let test_preimage = PaymentPreimage([42; 32]); let test_preimage = PaymentPreimage([42; 32]);

View file

@ -993,7 +993,7 @@ macro_rules! get_phantom_route {
(get_route( (get_route(
&$nodes[0].node.get_our_node_id(), &payment_params, &network_graph, &$nodes[0].node.get_our_node_id(), &payment_params, &network_graph,
Some(&$nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()), Some(&$nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
$amt, $nodes[0].logger, &scorer, &[0u8; 32] $amt, $nodes[0].logger, &scorer, &(), &[0u8; 32]
).unwrap(), phantom_route_hint.phantom_scid) ).unwrap(), phantom_route_hint.phantom_scid)
} }
}} }}

View file

@ -864,7 +864,7 @@ fn get_ldk_payment_preimage() {
let route = get_route( let route = get_route(
&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), &nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(),
Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()), Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
amt_msat, nodes[0].logger, &scorer, &random_seed_bytes).unwrap(); amt_msat, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
nodes[0].node.send_payment_with_route(&route, payment_hash, nodes[0].node.send_payment_with_route(&route, payment_hash,
RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
check_added_monitors!(nodes[0], 1); check_added_monitors!(nodes[0], 1);
@ -1418,7 +1418,7 @@ fn do_test_intercepted_payment(test: InterceptTest) {
let route = get_route( let route = get_route(
&nodes[0].node.get_our_node_id(), &route_params.payment_params, &nodes[0].node.get_our_node_id(), &route_params.payment_params,
&nodes[0].network_graph.read_only(), None, route_params.final_value_msat, &nodes[0].network_graph.read_only(), None, route_params.final_value_msat,
nodes[0].logger, &scorer, &random_seed_bytes, nodes[0].logger, &scorer, &(), &random_seed_bytes,
).unwrap(); ).unwrap();
let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();

View file

@ -95,9 +95,9 @@ fn updates_shutdown_wait() {
let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]); let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]);
let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[1].node.invoice_features()).unwrap(); let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
let route_1 = get_route(&nodes[0].node.get_our_node_id(), &payment_params_1, &nodes[0].network_graph.read_only(), None, 100000, &logger, &scorer, &random_seed_bytes).unwrap(); let route_1 = get_route(&nodes[0].node.get_our_node_id(), &payment_params_1, &nodes[0].network_graph.read_only(), None, 100000, &logger, &scorer, &(), &random_seed_bytes).unwrap();
let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[0].node.invoice_features()).unwrap(); let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[0].node.invoice_features()).unwrap();
let route_2 = get_route(&nodes[1].node.get_our_node_id(), &payment_params_2, &nodes[1].network_graph.read_only(), None, 100000, &logger, &scorer, &random_seed_bytes).unwrap(); let route_2 = get_route(&nodes[1].node.get_our_node_id(), &payment_params_2, &nodes[1].network_graph.read_only(), None, 100000, &logger, &scorer, &(), &random_seed_bytes).unwrap();
unwrap_send_err!(nodes[0].node.send_payment_with_route(&route_1, payment_hash, unwrap_send_err!(nodes[0].node.send_payment_with_route(&route_1, payment_hash,
RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)
), true, APIError::ChannelUnavailable {..}, {}); ), true, APIError::ChannelUnavailable {..}, {});

View file

@ -27,39 +27,43 @@ use crate::util::chacha20::ChaCha20;
use crate::io; use crate::io;
use crate::prelude::*; use crate::prelude::*;
use crate::sync::Mutex; use crate::sync::{Mutex, MutexGuard};
use alloc::collections::BinaryHeap; use alloc::collections::BinaryHeap;
use core::{cmp, fmt}; use core::{cmp, fmt};
use core::ops::Deref; use core::ops::Deref;
/// A [`Router`] implemented using [`find_route`]. /// A [`Router`] implemented using [`find_route`].
pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> where pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref, SP: Sized, Sc: Score<ScoreParams = SP>> where
L::Target: Logger, L::Target: Logger,
S::Target: for <'a> LockableScore<'a>, S::Target: for <'a> LockableScore<'a, Locked = MutexGuard<'a, Sc>>,
{ {
network_graph: G, network_graph: G,
logger: L, logger: L,
random_seed_bytes: Mutex<[u8; 32]>, random_seed_bytes: Mutex<[u8; 32]>,
scorer: S scorer: S,
score_params: SP
} }
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> DefaultRouter<G, L, S> where impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref, SP: Sized, Sc: Score<ScoreParams = SP>> DefaultRouter<G, L, S, SP, Sc> where
L::Target: Logger, L::Target: Logger,
S::Target: for <'a> LockableScore<'a>, S::Target: for <'a> LockableScore<'a, Locked = MutexGuard<'a, Sc>>,
{ {
/// Creates a new router. /// Creates a new router.
pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S) -> Self { pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: SP) -> Self {
let random_seed_bytes = Mutex::new(random_seed_bytes); let random_seed_bytes = Mutex::new(random_seed_bytes);
Self { network_graph, logger, random_seed_bytes, scorer } Self { network_graph, logger, random_seed_bytes, scorer, score_params }
} }
} }
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> Router for DefaultRouter<G, L, S> where impl< G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref, SP: Sized, Sc: Score<ScoreParams = SP>> Router for DefaultRouter<G, L, S, SP, Sc> where
L::Target: Logger, L::Target: Logger,
S::Target: for <'a> LockableScore<'a>, S::Target: for <'a> LockableScore<'a, Locked = MutexGuard<'a, Sc>>,
{ {
fn find_route( fn find_route(
&self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, &self,
payer: &PublicKey,
params: &RouteParameters,
first_hops: Option<&[&ChannelDetails]>,
inflight_htlcs: &InFlightHtlcs inflight_htlcs: &InFlightHtlcs
) -> Result<Route, LightningError> { ) -> Result<Route, LightningError> {
let random_seed_bytes = { let random_seed_bytes = {
@ -67,10 +71,10 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> Router for DefaultR
*locked_random_seed_bytes = Sha256::hash(&*locked_random_seed_bytes).into_inner(); *locked_random_seed_bytes = Sha256::hash(&*locked_random_seed_bytes).into_inner();
*locked_random_seed_bytes *locked_random_seed_bytes
}; };
find_route( find_route(
payer, params, &self.network_graph, first_hops, &*self.logger, payer, params, &self.network_graph, first_hops, &*self.logger,
&ScorerAccountingForInFlightHtlcs::new(self.scorer.lock(), inflight_htlcs), &ScorerAccountingForInFlightHtlcs::new(self.scorer.lock(), inflight_htlcs),
&self.score_params,
&random_seed_bytes &random_seed_bytes
) )
} }
@ -122,7 +126,8 @@ impl<'a, S: Score> Writeable for ScorerAccountingForInFlightHtlcs<'a, S> {
} }
impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> { impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> {
fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage) -> u64 { type ScoreParams = S::ScoreParams;
fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 {
if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat(
source, target, short_channel_id source, target, short_channel_id
) { ) {
@ -131,9 +136,9 @@ impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> {
..usage ..usage
}; };
self.scorer.channel_penalty_msat(short_channel_id, source, target, usage) self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params)
} else { } else {
self.scorer.channel_penalty_msat(short_channel_id, source, target, usage) self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params)
} }
} }
@ -1219,12 +1224,12 @@ impl fmt::Display for LoggedPayeePubkey {
pub fn find_route<L: Deref, GL: Deref, S: Score>( pub fn find_route<L: Deref, GL: Deref, S: Score>(
our_node_pubkey: &PublicKey, route_params: &RouteParameters, our_node_pubkey: &PublicKey, route_params: &RouteParameters,
network_graph: &NetworkGraph<GL>, first_hops: Option<&[&ChannelDetails]>, logger: L, network_graph: &NetworkGraph<GL>, first_hops: Option<&[&ChannelDetails]>, logger: L,
scorer: &S, random_seed_bytes: &[u8; 32] scorer: &S, score_params: &S::ScoreParams, random_seed_bytes: &[u8; 32]
) -> Result<Route, LightningError> ) -> Result<Route, LightningError>
where L::Target: Logger, GL::Target: Logger { where L::Target: Logger, GL::Target: Logger {
let graph_lock = network_graph.read_only(); let graph_lock = network_graph.read_only();
let mut route = get_route(our_node_pubkey, &route_params.payment_params, &graph_lock, first_hops, let mut route = get_route(our_node_pubkey, &route_params.payment_params, &graph_lock, first_hops,
route_params.final_value_msat, logger, scorer, route_params.final_value_msat, logger, scorer, score_params,
random_seed_bytes)?; random_seed_bytes)?;
add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes); add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
Ok(route) Ok(route)
@ -1232,7 +1237,7 @@ where L::Target: Logger, GL::Target: Logger {
pub(crate) fn get_route<L: Deref, S: Score>( pub(crate) fn get_route<L: Deref, S: Score>(
our_node_pubkey: &PublicKey, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph, our_node_pubkey: &PublicKey, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph,
first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, logger: L, scorer: &S, first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, logger: L, scorer: &S, score_params: &S::ScoreParams,
_random_seed_bytes: &[u8; 32] _random_seed_bytes: &[u8; 32]
) -> Result<Route, LightningError> ) -> Result<Route, LightningError>
where L::Target: Logger { where L::Target: Logger {
@ -1598,7 +1603,7 @@ where L::Target: Logger {
effective_capacity, effective_capacity,
}; };
let channel_penalty_msat = scorer.channel_penalty_msat( let channel_penalty_msat = scorer.channel_penalty_msat(
short_channel_id, &$src_node_id, &$dest_node_id, channel_usage short_channel_id, &$src_node_id, &$dest_node_id, channel_usage, score_params
); );
let path_penalty_msat = $next_hops_path_penalty_msat let path_penalty_msat = $next_hops_path_penalty_msat
.saturating_add(channel_penalty_msat); .saturating_add(channel_penalty_msat);
@ -1846,7 +1851,7 @@ where L::Target: Logger {
effective_capacity: candidate.effective_capacity(), effective_capacity: candidate.effective_capacity(),
}; };
let channel_penalty_msat = scorer.channel_penalty_msat( let channel_penalty_msat = scorer.channel_penalty_msat(
hop.short_channel_id, &source, &target, channel_usage hop.short_channel_id, &source, &target, channel_usage, score_params
); );
aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat
.saturating_add(channel_penalty_msat); .saturating_add(channel_penalty_msat);
@ -2343,8 +2348,9 @@ fn build_route_from_hops_internal<L: Deref>(
} }
impl Score for HopScorer { impl Score for HopScorer {
type ScoreParams = ();
fn channel_penalty_msat(&self, _short_channel_id: u64, source: &NodeId, target: &NodeId, fn channel_penalty_msat(&self, _short_channel_id: u64, source: &NodeId, target: &NodeId,
_usage: ChannelUsage) -> u64 _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64
{ {
let mut cur_id = self.our_node_id; let mut cur_id = self.our_node_id;
for i in 0..self.hop_ids.len() { for i in 0..self.hop_ids.len() {
@ -2389,7 +2395,7 @@ fn build_route_from_hops_internal<L: Deref>(
let scorer = HopScorer { our_node_id, hop_ids }; let scorer = HopScorer { our_node_id, hop_ids };
get_route(our_node_pubkey, payment_params, network_graph, None, final_value_msat, get_route(our_node_pubkey, payment_params, network_graph, None, final_value_msat,
logger, &scorer, random_seed_bytes) logger, &scorer, &(), random_seed_bytes)
} }
#[cfg(test)] #[cfg(test)]
@ -2400,7 +2406,7 @@ mod tests {
use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features, use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE}; DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringParameters}; use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters};
use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel}; use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
use crate::chain::transaction::OutPoint; use crate::chain::transaction::OutPoint;
use crate::sign::EntropySource; use crate::sign::EntropySource;
@ -2479,11 +2485,11 @@ mod tests {
// Simple route to 2 via 1 // Simple route to 2 via 1
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 0, Arc::clone(&logger), &scorer, &random_seed_bytes) { if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 0, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Cannot send a payment of 0 msat"); assert_eq!(err, "Cannot send a payment of 0 msat");
} else { panic!(); } } else { panic!(); }
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -2515,11 +2521,11 @@ mod tests {
let our_chans = vec![get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)]; 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}) = if let Err(LightningError{err, action: ErrorAction::IgnoreError}) =
get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "First hop cannot have our_node_pubkey as a destination."); assert_eq!(err, "First hop cannot have our_node_pubkey as a destination.");
} else { panic!(); } } else { panic!(); }
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
} }
@ -2627,7 +2633,7 @@ mod tests {
}); });
// Not possible to send 199_999_999, because the minimum on channel=2 is 200_000_000. // Not possible to send 199_999_999, because the minimum on channel=2 is 200_000_000.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &random_seed_bytes) { if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a path to the given destination"); assert_eq!(err, "Failed to find a path to the given destination");
} else { panic!(); } } else { panic!(); }
@ -2646,7 +2652,7 @@ mod tests {
}); });
// A payment above the minimum should pass // A payment above the minimum should pass
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
} }
@ -2728,7 +2734,7 @@ mod tests {
excess_data: Vec::new() excess_data: Vec::new()
}); });
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
// Overpay fees to hit htlc_minimum_msat. // Overpay fees to hit htlc_minimum_msat.
let overpaid_fees = route.paths[0].hops[0].fee_msat + route.paths[1].hops[0].fee_msat; let overpaid_fees = route.paths[0].hops[0].fee_msat + route.paths[1].hops[0].fee_msat;
// TODO: this could be better balanced to overpay 10k and not 15k. // TODO: this could be better balanced to overpay 10k and not 15k.
@ -2773,14 +2779,14 @@ mod tests {
excess_data: Vec::new() excess_data: Vec::new()
}); });
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
// Fine to overpay for htlc_minimum_msat if it allows us to save fee. // Fine to overpay for htlc_minimum_msat if it allows us to save fee.
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops[0].short_channel_id, 12); assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
let fees = route.paths[0].hops[0].fee_msat; let fees = route.paths[0].hops[0].fee_msat;
assert_eq!(fees, 5_000); assert_eq!(fees, 5_000);
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
// Not fine to overpay for htlc_minimum_msat if it requires paying more than fee on // Not fine to overpay for htlc_minimum_msat if it requires paying more than fee on
// the other channel. // the other channel.
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
@ -2825,13 +2831,13 @@ mod tests {
}); });
// If all the channels require some features we don't understand, route should fail // If all the channels require some features we don't understand, route should fail
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a path to the given destination"); assert_eq!(err, "Failed to find a path to the given destination");
} else { panic!(); } } else { panic!(); }
// If we specify a channel to node7, that overrides our local channel view and that gets used // 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 our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
@ -2866,13 +2872,13 @@ mod tests {
add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], unknown_features.clone(), 1); add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], unknown_features.clone(), 1);
// If all nodes require some features we don't understand, route should fail // If all nodes require some features we don't understand, route should fail
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a path to the given destination"); assert_eq!(err, "Failed to find a path to the given destination");
} else { panic!(); } } else { panic!(); }
// If we specify a channel to node7, that overrides our local channel view and that gets used // 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 our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
@ -2904,7 +2910,7 @@ mod tests {
// Route to 1 via 2 and 3 because our channel to 1 is disabled // Route to 1 via 2 and 3 because our channel to 1 is disabled
let payment_params = PaymentParameters::from_node_id(nodes[0], 42); let payment_params = PaymentParameters::from_node_id(nodes[0], 42);
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 3); assert_eq!(route.paths[0].hops.len(), 3);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -2931,7 +2937,7 @@ mod tests {
// If we specify a channel to node7, that overrides our local channel view and that gets used // If we specify a channel to node7, that overrides our local channel view and that gets used
let payment_params = PaymentParameters::from_node_id(nodes[2], 42); let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
@ -3054,13 +3060,13 @@ mod tests {
invalid_last_hops.push(invalid_last_hop); invalid_last_hops.push(invalid_last_hop);
{ {
let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(invalid_last_hops).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(invalid_last_hops).unwrap();
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Route hint cannot have the payee as the source."); assert_eq!(err, "Route hint cannot have the payee as the source.");
} else { panic!(); } } else { panic!(); }
} }
let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap();
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops.len(), 5);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -3136,7 +3142,7 @@ mod tests {
// Test handling of an empty RouteHint passed in Invoice. // Test handling of an empty RouteHint passed in Invoice.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops.len(), 5);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -3242,7 +3248,7 @@ mod tests {
excess_data: Vec::new() excess_data: Vec::new()
}); });
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops.len(), 4);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -3314,7 +3320,7 @@ mod tests {
excess_data: Vec::new() excess_data: Vec::new()
}); });
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &[42u8; 32]).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &[42u8; 32]).unwrap();
assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops.len(), 4);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -3396,7 +3402,7 @@ mod tests {
// This test shows that public routes can be present in the invoice // This test shows that public routes can be present in the invoice
// which would be handled in the same manner. // which would be handled in the same manner.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops.len(), 5);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -3449,7 +3455,7 @@ mod tests {
let our_chans = vec![get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; let 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 mut last_hops = last_hops(&nodes);
let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap();
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[3]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[3]);
@ -3470,7 +3476,7 @@ mod tests {
// Revert to via 6 as the fee on 8 goes up // Revert to via 6 as the fee on 8 goes up
let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops).unwrap();
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops.len(), 4);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -3504,7 +3510,7 @@ mod tests {
assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
// ...but still use 8 for larger payments as 6 has a variable feerate // ...but still use 8 for larger payments as 6 has a variable feerate
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 2000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 2000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops.len(), 5);
assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@ -3570,7 +3576,7 @@ mod tests {
let logger = ln_test_utils::TestLogger::new(); let logger = ln_test_utils::TestLogger::new();
let network_graph = NetworkGraph::new(Network::Testnet, &logger); let network_graph = NetworkGraph::new(Network::Testnet, &logger);
let route = get_route(&source_node_id, &payment_params, &network_graph.read_only(), let route = get_route(&source_node_id, &payment_params, &network_graph.read_only(),
Some(&our_chans.iter().collect::<Vec<_>>()), route_val, &logger, &scorer, &random_seed_bytes); Some(&our_chans.iter().collect::<Vec<_>>()), route_val, &logger, &scorer, &(), &random_seed_bytes);
route route
} }
@ -3692,14 +3698,14 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 250_000_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 250_000_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
{ {
// Now, attempt to route an exact amount we have should be fine. // Now, attempt to route an exact amount we have should be fine.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 250_000_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 250_000_000, Arc::clone(&logger), &scorer, &(),&random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let path = route.paths.last().unwrap(); let path = route.paths.last().unwrap();
assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.len(), 2);
@ -3728,14 +3734,14 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
{ {
// Now, attempt to route an exact amount we have should be fine. // Now, attempt to route an exact amount we have should be fine.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let path = route.paths.last().unwrap(); let path = route.paths.last().unwrap();
assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.len(), 2);
@ -3775,14 +3781,14 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
{ {
// Now, attempt to route an exact amount we have should be fine. // Now, attempt to route an exact amount we have should be fine.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let path = route.paths.last().unwrap(); let path = route.paths.last().unwrap();
assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.len(), 2);
@ -3846,14 +3852,14 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
{ {
// Now, attempt to route an exact amount we have should be fine. // Now, attempt to route an exact amount we have should be fine.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let path = route.paths.last().unwrap(); let path = route.paths.last().unwrap();
assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.len(), 2);
@ -3878,14 +3884,14 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 10_001, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 10_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
{ {
// Now, attempt to route an exact amount we have should be fine. // Now, attempt to route an exact amount we have should be fine.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let path = route.paths.last().unwrap(); let path = route.paths.last().unwrap();
assert_eq!(path.hops.len(), 2); assert_eq!(path.hops.len(), 2);
@ -3990,14 +3996,14 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
{ {
// Now, attempt to route 49 sats (just a bit below the capacity). // Now, attempt to route 49 sats (just a bit below the capacity).
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 49_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 49_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
for path in &route.paths { for path in &route.paths {
@ -4010,7 +4016,7 @@ mod tests {
{ {
// Attempt to route an exact amount is also fine // Attempt to route an exact amount is also fine
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
for path in &route.paths { for path in &route.paths {
@ -4058,7 +4064,7 @@ mod tests {
}); });
{ {
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
for path in &route.paths { for path in &route.paths {
@ -4173,7 +4179,7 @@ mod tests {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 300_000, &our_id, &payment_params, &network_graph.read_only(), None, 300_000,
Arc::clone(&logger), &scorer, &random_seed_bytes) { Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
@ -4183,7 +4189,7 @@ mod tests {
let zero_payment_params = payment_params.clone().with_max_path_count(0); let zero_payment_params = payment_params.clone().with_max_path_count(0);
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &zero_payment_params, &network_graph.read_only(), None, 100, &our_id, &zero_payment_params, &network_graph.read_only(), None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes) { Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Can't find a route with no paths allowed."); assert_eq!(err, "Can't find a route with no paths allowed.");
} else { panic!(); } } else { panic!(); }
} }
@ -4195,7 +4201,7 @@ mod tests {
let fail_payment_params = payment_params.clone().with_max_path_count(3); let fail_payment_params = payment_params.clone().with_max_path_count(3);
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &fail_payment_params, &network_graph.read_only(), None, 250_000, &our_id, &fail_payment_params, &network_graph.read_only(), None, 250_000,
Arc::clone(&logger), &scorer, &random_seed_bytes) { Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
@ -4204,7 +4210,7 @@ mod tests {
// Now, attempt to route 250 sats (just a bit below the capacity). // Now, attempt to route 250 sats (just a bit below the capacity).
// Our algorithm should provide us with these 3 paths. // Our algorithm should provide us with these 3 paths.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None,
250_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); 250_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 3); assert_eq!(route.paths.len(), 3);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
for path in &route.paths { for path in &route.paths {
@ -4218,7 +4224,7 @@ mod tests {
{ {
// Attempt to route an exact amount is also fine // Attempt to route an exact amount is also fine
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None,
290_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); 290_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 3); assert_eq!(route.paths.len(), 3);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
for path in &route.paths { for path in &route.paths {
@ -4374,7 +4380,7 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 350_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 350_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
@ -4382,7 +4388,7 @@ mod tests {
{ {
// Now, attempt to route 300 sats (exact amount we can route). // Now, attempt to route 300 sats (exact amount we can route).
// Our algorithm should provide us with these 3 paths, 100 sats each. // Our algorithm should provide us with these 3 paths, 100 sats each.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 300_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 300_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 3); assert_eq!(route.paths.len(), 3);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
@ -4543,7 +4549,7 @@ mod tests {
{ {
// Now, attempt to route 180 sats. // Now, attempt to route 180 sats.
// Our algorithm should provide us with these 2 paths. // Our algorithm should provide us with these 2 paths.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 180_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 180_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 2); assert_eq!(route.paths.len(), 2);
let mut total_value_transferred_msat = 0; let mut total_value_transferred_msat = 0;
@ -4714,14 +4720,14 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 210_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 210_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
{ {
// Now, attempt to route 200 sats (exact amount we can route). // Now, attempt to route 200 sats (exact amount we can route).
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 200_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 200_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 2); assert_eq!(route.paths.len(), 2);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
@ -4821,7 +4827,7 @@ mod tests {
// Get a route for 100 sats and check that we found the MPP route no problem and didn't // Get a route for 100 sats and check that we found the MPP route no problem and didn't
// overpay at all. // overpay at all.
let mut route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let mut route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 2); assert_eq!(route.paths.len(), 2);
route.paths.sort_by_key(|path| path.hops[0].short_channel_id); route.paths.sort_by_key(|path| path.hops[0].short_channel_id);
// Paths are manually ordered ordered by SCID, so: // Paths are manually ordered ordered by SCID, so:
@ -4940,7 +4946,7 @@ mod tests {
{ {
// Attempt to route more than available results in a failure. // Attempt to route more than available results in a failure.
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 150_000, Arc::clone(&logger), &scorer, &random_seed_bytes) { &our_id, &payment_params, &network_graph.read_only(), None, 150_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
assert_eq!(err, "Failed to find a sufficient route to the given destination"); assert_eq!(err, "Failed to find a sufficient route to the given destination");
} else { panic!(); } } else { panic!(); }
} }
@ -4948,7 +4954,7 @@ mod tests {
{ {
// Now, attempt to route 125 sats (just a bit below the capacity of 3 channels). // Now, attempt to route 125 sats (just a bit below the capacity of 3 channels).
// Our algorithm should provide us with these 3 paths. // Our algorithm should provide us with these 3 paths.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 125_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 125_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 3); assert_eq!(route.paths.len(), 3);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
for path in &route.paths { for path in &route.paths {
@ -4961,7 +4967,7 @@ mod tests {
{ {
// Attempt to route without the last small cheap channel // Attempt to route without the last small cheap channel
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 2); assert_eq!(route.paths.len(), 2);
let mut total_amount_paid_msat = 0; let mut total_amount_paid_msat = 0;
for path in &route.paths { for path in &route.paths {
@ -5100,7 +5106,7 @@ mod tests {
{ {
// Now ensure the route flows simply over nodes 1 and 4 to 6. // Now ensure the route flows simply over nodes 1 and 4 to 6.
let route = get_route(&our_id, &payment_params, &network.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops.len(), 3); assert_eq!(route.paths[0].hops.len(), 3);
@ -5171,7 +5177,7 @@ mod tests {
{ {
// Now, attempt to route 90 sats, which is exactly 90 sats at the last hop, plus the // 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. // 200% fee charged channel 13 in the 1-to-2 direction.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
@ -5237,7 +5243,7 @@ mod tests {
// Now, attempt to route 90 sats, hitting the htlc_minimum on channel 4, but // 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 // overshooting the htlc_maximum on channel 2. Thus, we should pick the (absurdly
// expensive) channels 12-13 path. // expensive) channels 12-13 path.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops.len(), 2);
@ -5279,7 +5285,7 @@ mod tests {
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[ let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
&get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000), &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000),
&get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000), &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000),
]), 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops.len(), 1); assert_eq!(route.paths[0].hops.len(), 1);
@ -5291,7 +5297,7 @@ mod tests {
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[ let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
&get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
&get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
]), 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 2); assert_eq!(route.paths.len(), 2);
assert_eq!(route.paths[0].hops.len(), 1); assert_eq!(route.paths[0].hops.len(), 1);
assert_eq!(route.paths[1].hops.len(), 1); assert_eq!(route.paths[1].hops.len(), 1);
@ -5323,7 +5329,7 @@ mod tests {
&get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000),
&get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000), &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000),
&get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000), &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000),
]), 100_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops.len(), 1); assert_eq!(route.paths[0].hops.len(), 1);
@ -5345,7 +5351,7 @@ mod tests {
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
let route = get_route( let route = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 100, &our_id, &payment_params, &network_graph.read_only(), None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes Arc::clone(&logger), &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
@ -5358,7 +5364,7 @@ mod tests {
let scorer = FixedPenaltyScorer::with_penalty(100); let scorer = FixedPenaltyScorer::with_penalty(100);
let route = get_route( let route = get_route(
&our_id, &payment_params, &network_graph.read_only(), None, 100, &our_id, &payment_params, &network_graph.read_only(), None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes Arc::clone(&logger), &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
@ -5376,7 +5382,8 @@ mod tests {
fn write<W: Writer>(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } fn write<W: Writer>(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() }
} }
impl Score for BadChannelScorer { impl Score for BadChannelScorer {
fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage) -> u64 { type ScoreParams = ();
fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 } if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 }
} }
@ -5396,7 +5403,8 @@ mod tests {
} }
impl Score for BadNodeScorer { impl Score for BadNodeScorer {
fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage) -> u64 { type ScoreParams = ();
fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
if *target == self.node_id { u64::max_value() } else { 0 } if *target == self.node_id { u64::max_value() } else { 0 }
} }
@ -5419,7 +5427,7 @@ mod tests {
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
let route = get_route( let route = get_route(
&our_id, &payment_params, &network_graph, None, 100, &our_id, &payment_params, &network_graph, None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes Arc::clone(&logger), &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
@ -5431,7 +5439,7 @@ mod tests {
let scorer = BadChannelScorer { short_channel_id: 6 }; let scorer = BadChannelScorer { short_channel_id: 6 };
let route = get_route( let route = get_route(
&our_id, &payment_params, &network_graph, None, 100, &our_id, &payment_params, &network_graph, None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes Arc::clone(&logger), &scorer, &(), &random_seed_bytes
).unwrap(); ).unwrap();
let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
@ -5443,7 +5451,7 @@ mod tests {
let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) }; let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) };
match get_route( match get_route(
&our_id, &payment_params, &network_graph, None, 100, &our_id, &payment_params, &network_graph, None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes Arc::clone(&logger), &scorer, &(), &random_seed_bytes
) { ) {
Err(LightningError { err, .. } ) => { Err(LightningError { err, .. } ) => {
assert_eq!(err, "Failed to find a path to the given destination"); assert_eq!(err, "Failed to find a path to the given destination");
@ -5537,7 +5545,7 @@ mod tests {
.with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta); .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta);
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
assert_ne!(path.len(), 0); assert_ne!(path.len(), 0);
@ -5545,7 +5553,7 @@ mod tests {
let fail_max_total_cltv_delta = 23; let fail_max_total_cltv_delta = 23;
let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap() let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
.with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta); .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta);
match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes)
{ {
Err(LightningError { err, .. } ) => { Err(LightningError { err, .. } ) => {
assert_eq!(err, "Failed to find a path to the given destination"); assert_eq!(err, "Failed to find a path to the given destination");
@ -5570,9 +5578,9 @@ mod tests {
// We should be able to find a route initially, and then after we fail a few random // We should be able to find a route initially, and then after we fail a few random
// channels eventually we won't be able to any longer. // channels eventually we won't be able to any longer.
assert!(get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).is_ok()); assert!(get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).is_ok());
loop { loop {
if let Ok(route) = get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes) { if let Ok(route) = get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
for chan in route.paths[0].hops.iter() { for chan in route.paths[0].hops.iter() {
assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id)); assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id));
} }
@ -5596,14 +5604,14 @@ mod tests {
// First check we can actually create a long route on this graph. // First check we can actually create a long route on this graph.
let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0); let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0);
let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into()); assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into());
// But we can't create a path surpassing the MAX_PATH_LENGTH_ESTIMATE limit. // But we can't create a path surpassing the MAX_PATH_LENGTH_ESTIMATE limit.
let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0); let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0);
match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, match get_route(&our_id, &fail_payment_params, &network_graph, None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes) Arc::clone(&logger), &scorer, &(), &random_seed_bytes)
{ {
Err(LightningError { err, .. } ) => { Err(LightningError { err, .. } ) => {
assert_eq!(err, "Failed to find a path to the given destination"); assert_eq!(err, "Failed to find a path to the given destination");
@ -5622,7 +5630,7 @@ mod tests {
let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1); assert_eq!(route.paths.len(), 1);
let cltv_expiry_deltas_before = route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>(); let cltv_expiry_deltas_before = route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
@ -5657,7 +5665,7 @@ mod tests {
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
let mut route = get_route(&our_id, &payment_params, &network_graph, None, 100, let mut route = get_route(&our_id, &payment_params, &network_graph, None, 100,
Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes); add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes);
let mut path_plausibility = vec![]; let mut path_plausibility = vec![];
@ -5734,8 +5742,8 @@ mod tests {
fn avoids_saturating_channels() { fn avoids_saturating_channels() {
let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph(); let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
let decay_params = ProbabilisticScoringDecayParameters::default();
let scorer = ProbabilisticScorer::new(Default::default(), &*network_graph, Arc::clone(&logger)); let scorer = ProbabilisticScorer::new(decay_params, &*network_graph, Arc::clone(&logger));
// Set the fee on channel 13 to 100% to match channel 4 giving us two equivalent paths (us // Set the fee on channel 13 to 100% to match channel 4 giving us two equivalent paths (us
// -> node 7 -> node2 and us -> node 1 -> node 2) which we should balance over. // -> node 7 -> node2 and us -> node 1 -> node 2) which we should balance over.
@ -5769,7 +5777,7 @@ mod tests {
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
// 100,000 sats is less than the available liquidity on each channel, set above. // 100,000 sats is less than the available liquidity on each channel, set above.
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000_000, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000_000, Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 2); assert_eq!(route.paths.len(), 2);
assert!((route.paths[0].hops[1].short_channel_id == 4 && route.paths[1].hops[1].short_channel_id == 13) || assert!((route.paths[0].hops[1].short_channel_id == 4 && route.paths[1].hops[1].short_channel_id == 13) ||
(route.paths[1].hops[1].short_channel_id == 4 && route.paths[0].hops[1].short_channel_id == 13)); (route.paths[1].hops[1].short_channel_id == 4 && route.paths[0].hops[1].short_channel_id == 13));
@ -5789,7 +5797,7 @@ mod tests {
#[test] #[test]
#[cfg(not(feature = "no-std"))] #[cfg(not(feature = "no-std"))]
fn generate_routes() { fn generate_routes() {
use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters}; use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters};
let mut d = match super::bench_utils::get_route_file() { let mut d = match super::bench_utils::get_route_file() {
Ok(f) => f, Ok(f) => f,
@ -5814,9 +5822,9 @@ mod tests {
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
let payment_params = PaymentParameters::from_node_id(dst, 42); let payment_params = PaymentParameters::from_node_id(dst, 42);
let amt = seed as u64 % 200_000_000; let amt = seed as u64 % 200_000_000;
let params = ProbabilisticScoringParameters::default(); let params = ProbabilisticScoringFeeParameters::default();
let scorer = ProbabilisticScorer::new(params, &graph, &logger); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger);
if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &random_seed_bytes).is_ok() { if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &params, &random_seed_bytes).is_ok() {
continue 'load_endpoints; continue 'load_endpoints;
} }
} }
@ -5826,7 +5834,7 @@ mod tests {
#[test] #[test]
#[cfg(not(feature = "no-std"))] #[cfg(not(feature = "no-std"))]
fn generate_routes_mpp() { fn generate_routes_mpp() {
use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters}; use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters};
let mut d = match super::bench_utils::get_route_file() { let mut d = match super::bench_utils::get_route_file() {
Ok(f) => f, Ok(f) => f,
@ -5852,9 +5860,9 @@ mod tests {
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap(); let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
let payment_params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap(); let payment_params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap();
let amt = seed as u64 % 200_000_000; let amt = seed as u64 % 200_000_000;
let params = ProbabilisticScoringParameters::default(); let params = ProbabilisticScoringFeeParameters::default();
let scorer = ProbabilisticScorer::new(params, &graph, &logger); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger);
if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &random_seed_bytes).is_ok() { if get_route(src, &payment_params, &graph.read_only(), None, amt, &logger, &scorer, &params, &random_seed_bytes).is_ok() {
continue 'load_endpoints; continue 'load_endpoints;
} }
} }
@ -5869,8 +5877,8 @@ mod tests {
let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes(); let random_seed_bytes = keys_manager.get_secure_random_bytes();
let scorer_params = ProbabilisticScoringParameters::default(); let mut scorer_params = ProbabilisticScoringFeeParameters::default();
let mut scorer = ProbabilisticScorer::new(scorer_params, Arc::clone(&network_graph), Arc::clone(&logger)); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger));
// First check set manual penalties are returned by the scorer. // First check set manual penalties are returned by the scorer.
let usage = ChannelUsage { let usage = ChannelUsage {
@ -5878,23 +5886,23 @@ mod tests {
inflight_htlc_msat: 0, inflight_htlc_msat: 0,
effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 },
}; };
scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123); scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123);
scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456); scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456);
assert_eq!(scorer.channel_penalty_msat(42, &NodeId::from_pubkey(&nodes[3]), &NodeId::from_pubkey(&nodes[4]), usage), 456); assert_eq!(scorer.channel_penalty_msat(42, &NodeId::from_pubkey(&nodes[3]), &NodeId::from_pubkey(&nodes[4]), usage, &scorer_params), 456);
// Then check we can get a normal route // Then check we can get a normal route
let payment_params = PaymentParameters::from_node_id(nodes[10], 42); let payment_params = PaymentParameters::from_node_id(nodes[10], 42);
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
assert!(route.is_ok()); assert!(route.is_ok());
// Then check that we can't get a route if we ban an intermediate node. // Then check that we can't get a route if we ban an intermediate node.
scorer.add_banned(&NodeId::from_pubkey(&nodes[3])); scorer_params.add_banned(&NodeId::from_pubkey(&nodes[3]));
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
assert!(route.is_err()); assert!(route.is_err());
// Finally make sure we can route again, when we remove the ban. // Finally make sure we can route again, when we remove the ban.
scorer.remove_banned(&NodeId::from_pubkey(&nodes[3])); scorer_params.remove_banned(&NodeId::from_pubkey(&nodes[3]));
let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &random_seed_bytes); let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
assert!(route.is_ok()); assert!(route.is_ok());
} }
@ -6081,7 +6089,7 @@ mod benches {
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails}; use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
use crate::ln::features::InvoiceFeatures; use crate::ln::features::InvoiceFeatures;
use crate::routing::gossip::NetworkGraph; use crate::routing::gossip::NetworkGraph;
use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters}; use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters};
use crate::util::config::UserConfig; use crate::util::config::UserConfig;
use crate::util::logger::{Logger, Record}; use crate::util::logger::{Logger, Record};
use crate::util::ser::ReadableArgs; use crate::util::ser::ReadableArgs;
@ -6148,7 +6156,7 @@ mod benches {
let logger = DummyLogger {}; let logger = DummyLogger {};
let network_graph = read_network_graph(&logger); let network_graph = read_network_graph(&logger);
let scorer = FixedPenaltyScorer::with_penalty(0); let scorer = FixedPenaltyScorer::with_penalty(0);
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty()); generate_routes(bench, &network_graph, scorer, &(), InvoiceFeatures::empty());
} }
#[bench] #[bench]
@ -6156,29 +6164,29 @@ mod benches {
let logger = DummyLogger {}; let logger = DummyLogger {};
let network_graph = read_network_graph(&logger); let network_graph = read_network_graph(&logger);
let scorer = FixedPenaltyScorer::with_penalty(0); let scorer = FixedPenaltyScorer::with_penalty(0);
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default())); generate_routes(bench, &network_graph, scorer, &(), channelmanager::provided_invoice_features(&UserConfig::default()));
} }
#[bench] #[bench]
fn generate_routes_with_probabilistic_scorer(bench: &mut Bencher) { fn generate_routes_with_probabilistic_scorer(bench: &mut Bencher) {
let logger = DummyLogger {}; let logger = DummyLogger {};
let network_graph = read_network_graph(&logger); let network_graph = read_network_graph(&logger);
let params = ProbabilisticScoringParameters::default(); let params = ProbabilisticScoringFeeParameters::default();
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty()); generate_routes(bench, &network_graph, scorer, &params, InvoiceFeatures::empty());
} }
#[bench] #[bench]
fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) { fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) {
let logger = DummyLogger {}; let logger = DummyLogger {};
let network_graph = read_network_graph(&logger); let network_graph = read_network_graph(&logger);
let params = ProbabilisticScoringParameters::default(); let params = ProbabilisticScoringFeeParameters::default();
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger); let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default())); generate_routes(bench, &network_graph, scorer, &params, channelmanager::provided_invoice_features(&UserConfig::default()));
} }
fn generate_routes<S: Score>( fn generate_routes<S: Score>(
bench: &mut Bencher, graph: &NetworkGraph<&DummyLogger>, mut scorer: S, bench: &mut Bencher, graph: &NetworkGraph<&DummyLogger>, mut scorer: S, score_params: &S::ScoreParams,
features: InvoiceFeatures features: InvoiceFeatures
) { ) {
let nodes = graph.read_only().nodes().clone(); let nodes = graph.read_only().nodes().clone();
@ -6199,7 +6207,7 @@ mod benches {
let params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(features.clone()).unwrap(); let params = PaymentParameters::from_node_id(dst, 42).with_bolt11_features(features.clone()).unwrap();
let first_hop = first_hop(src); let first_hop = first_hop(src);
let amt = seed as u64 % 1_000_000; let amt = seed as u64 % 1_000_000;
if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]), amt, &DummyLogger{}, &scorer, &random_seed_bytes) { if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]), amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes) {
routes.push(route); routes.push(route);
route_endpoints.push((first_hop, params, amt)); route_endpoints.push((first_hop, params, amt));
continue 'load_endpoints; continue 'load_endpoints;
@ -6226,7 +6234,7 @@ mod benches {
// selected destinations, possibly causing us to fail because, eg, the newly-selected path // selected destinations, possibly causing us to fail because, eg, the newly-selected path
// requires a too-high CLTV delta. // requires a too-high CLTV delta.
route_endpoints.retain(|(first_hop, params, amt)| { route_endpoints.retain(|(first_hop, params, amt)| {
get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, &random_seed_bytes).is_ok() get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok()
}); });
route_endpoints.truncate(100); route_endpoints.truncate(100);
assert_eq!(route_endpoints.len(), 100); assert_eq!(route_endpoints.len(), 100);
@ -6235,7 +6243,7 @@ mod benches {
let mut idx = 0; let mut idx = 0;
bench.iter(|| { bench.iter(|| {
let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()]; let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()];
assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, &random_seed_bytes).is_ok()); assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok());
idx += 1; idx += 1;
}); });
} }

File diff suppressed because it is too large Load diff

View file

@ -126,10 +126,10 @@ impl<'a> Router for TestRouter<'a> {
// Since the path is reversed, the last element in our iteration is the first // Since the path is reversed, the last element in our iteration is the first
// hop. // hop.
if idx == path.hops.len() - 1 { if idx == path.hops.len() - 1 {
scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage); scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage, &());
} else { } else {
let curr_hop_path_idx = path.hops.len() - 1 - idx; let curr_hop_path_idx = path.hops.len() - 1 - idx;
scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path.hops[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage); scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(&path.hops[curr_hop_path_idx - 1].pubkey), &NodeId::from_pubkey(&hop.pubkey), usage, &());
} }
} }
} }
@ -140,7 +140,7 @@ impl<'a> Router for TestRouter<'a> {
let scorer = self.scorer.lock().unwrap(); let scorer = self.scorer.lock().unwrap();
find_route( find_route(
payer, params, &self.network_graph, first_hops, &logger, payer, params, &self.network_graph, first_hops, &logger,
&ScorerAccountingForInFlightHtlcs::new(scorer, &inflight_htlcs), &ScorerAccountingForInFlightHtlcs::new(scorer, &inflight_htlcs), &(),
&[42; 32] &[42; 32]
) )
} }
@ -1012,8 +1012,9 @@ impl crate::util::ser::Writeable for TestScorer {
} }
impl Score for TestScorer { impl Score for TestScorer {
type ScoreParams = ();
fn channel_penalty_msat( fn channel_penalty_msat(
&self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &Self::ScoreParams
) -> u64 { ) -> u64 {
if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() { if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() {
match scorer_expectations.pop_front() { match scorer_expectations.pop_front() {