X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=26e00319fbdb3b4f2e45fab8d35f51fea576773f;hb=79e2af949700281b7333f202a7292e3bf81dc674;hp=048a434508e80bd88e5f6c62060fc852f09185db;hpb=13b7cd503bd27981b249fabcaa4f2a12601f648b;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 048a4345..26e00319 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -887,7 +887,7 @@ where L::Target: Logger { HashMap::with_capacity(network_nodes.len()); // Keeping track of how much value we already collected across other paths. Helps to decide - // when we want to stop looking for new paths. + // when we want to stop looking for new paths. let mut already_collected_value_msat = 0; for (_, channels) in first_hop_targets.iter_mut() { @@ -1878,7 +1878,7 @@ mod tests { use routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE}; - use routing::scoring::{ChannelUsage, Score}; + use routing::scoring::{ChannelUsage, Score, ProbabilisticScorer, ProbabilisticScoringParameters}; use chain::transaction::OutPoint; use chain::keysinterface::KeysInterface; use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures}; @@ -1937,6 +1937,7 @@ mod tests { is_usable: true, is_public: true, inbound_htlc_minimum_msat: None, inbound_htlc_maximum_msat: None, + config: None, } } @@ -4015,7 +4016,8 @@ mod tests { let scorer = test_utils::TestScorer::with_penalty(0); let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known()); + let payment_params = PaymentParameters::from_node_id(nodes[2]) + .with_features(InvoiceFeatures::known()); // We need a route consisting of 3 paths: // From our node to node2 via node0, node7, node1 (three paths one hop each). @@ -4108,15 +4110,39 @@ mod tests { { // Attempt to route more than available results in a failure. if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( - &our_id, &payment_params, &network_graph.read_only(), None, 300_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); + &our_id, &payment_params, &network_graph.read_only(), None, 300_000, 42, + Arc::clone(&logger), &scorer, &random_seed_bytes) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { panic!(); } + } + + { + // Attempt to route while setting max_mpp_path_count to 0 results in a failure. + let zero_payment_params = payment_params.clone().with_max_mpp_path_count(0); + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( + &our_id, &zero_payment_params, &network_graph.read_only(), None, 100, 42, + Arc::clone(&logger), &scorer, &random_seed_bytes) { + assert_eq!(err, "Can't find an MPP route with no paths allowed."); + } else { panic!(); } + } + + { + // Attempt to route while setting max_mpp_path_count to 3 results in a failure. + // This is the case because the minimal_value_contribution_msat would require each path + // to account for 1/3 of the total value, which is violated by 2 out of 3 paths. + let fail_payment_params = payment_params.clone().with_max_mpp_path_count(3); + if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route( + &our_id, &fail_payment_params, &network_graph.read_only(), None, 250_000, 42, + Arc::clone(&logger), &scorer, &random_seed_bytes) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); } else { panic!(); } } { // Now, attempt to route 250 sats (just a bit below the capacity). // Our algorithm should provide us with these 3 paths. - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 250_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, + 250_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -4129,7 +4155,8 @@ mod tests { { // Attempt to route an exact amount is also fine - let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 290_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, + 290_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -5686,6 +5713,33 @@ mod tests { } } } + + #[test] + fn avoids_banned_nodes() { + let (secp_ctx, network_graph, _, _, logger) = build_line_graph(); + let (_, our_id, _, nodes) = get_nodes(&secp_ctx); + + let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); + let random_seed_bytes = keys_manager.get_secure_random_bytes(); + + let scorer_params = ProbabilisticScoringParameters::default(); + let mut scorer = ProbabilisticScorer::new(scorer_params, Arc::clone(&network_graph), Arc::clone(&logger)); + + // First check we can get a route. + let payment_params = PaymentParameters::from_node_id(nodes[10]); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes); + assert!(route.is_ok()); + + // Then check that we can't get a route if we ban an intermediate node. + scorer.add_banned(&NodeId::from_pubkey(&nodes[3])); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes); + assert!(route.is_err()); + + // Finally make sure we can route again, when we remove the ban. + scorer.remove_banned(&NodeId::from_pubkey(&nodes[3])); + let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes); + assert!(route.is_ok()); + } } #[cfg(all(test, not(feature = "no-std")))] @@ -5780,6 +5834,7 @@ mod benches { is_public: true, inbound_htlc_minimum_msat: None, inbound_htlc_maximum_msat: None, + config: None, } }