Disable MPP routing when the payee does not support it
authorMatt Corallo <git@bluematt.me>
Fri, 5 Mar 2021 03:36:34 +0000 (22:36 -0500)
committerMatt Corallo <git@bluematt.me>
Mon, 8 Mar 2021 22:19:23 +0000 (17:19 -0500)
lightning/src/ln/features.rs
lightning/src/routing/router.rs

index efed0b10ed2ae72935f9742b1f4594ed0e90100b..488d6d70f5768ffde2d0af6afd80707a595625c9 100644 (file)
@@ -574,7 +574,6 @@ impl<T: sealed::BasicMPP> Features<T> {
                <T as sealed::BasicMPP>::requires_feature(&self.flags)
        }
        // We currently never test for this since we don't actually *generate* multipath routes.
-       #[allow(dead_code)]
        pub(crate) fn supports_basic_mpp(&self) -> bool {
                <T as sealed::BasicMPP>::supports_feature(&self.flags)
        }
index faf8c46142383ff679f075f4b5d33304dec992b6..fc856b5ea58da3afd4fa2166685a7c5c95e9b2b9 100644 (file)
@@ -15,7 +15,7 @@
 use bitcoin::secp256k1::key::PublicKey;
 
 use ln::channelmanager::ChannelDetails;
-use ln::features::{ChannelFeatures, NodeFeatures, InvoiceFeatures};
+use ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures};
 use ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
 use routing::network_graph::{NetworkGraph, RoutingFees};
 use util::ser::{Writeable, Readable};
@@ -314,6 +314,9 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
 
 /// Gets a route from us (payer) to the given target node (payee).
 ///
+/// If the payee provided features in their invoice, they should be provided via payee_features.
+/// Without this, MPP will only be used if the payee's features are available in the network graph.
+///
 /// Extra routing hops between known nodes and the target will be used if they are included in
 /// last_hops.
 ///
@@ -396,6 +399,17 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
        const ROUTE_CAPACITY_PROVISION_FACTOR: u64 = 3;
        let recommended_value_msat = final_value_msat * ROUTE_CAPACITY_PROVISION_FACTOR as u64;
 
+       // Allow MPP only if we have a features set from somewhere that indicates the payee supports
+       // it. If the payee supports it they're supposed to include it in the invoice, so that should
+       // work reliably.
+       let allow_mpp = if let Some(features) = &payee_features {
+               features.supports_basic_mpp()
+       } else if let Some(node) = network.get_nodes().get(&payee) {
+               if let Some(node_info) = node.announcement_info.as_ref() {
+                       node_info.features.supports_basic_mpp()
+               } else { false }
+       } else { false };
+
        // Step (1).
        // Prepare the data we'll use for payee-to-payer search by
        // inserting first hops suggested by the caller as targets.
@@ -484,8 +498,13 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
                                        // the absolute liquidity contribution is lowered,
                                        // thus increasing the number of potential channels to be selected.
 
-                                       // Derive the minimal liquidity contribution with a ratio of 20 (5%, rounded up).
-                                       let minimal_value_contribution_msat: u64 = (recommended_value_msat - already_collected_value_msat + 19) / 20;
+                                       // Derive the minimal liquidity contribution with a ratio of 20 (5%, rounded up)
+                                       // or 100% if we're not allowed to do multipath payments.
+                                       let minimal_value_contribution_msat: u64 = if allow_mpp {
+                                               (recommended_value_msat - already_collected_value_msat + 19) / 20
+                                       } else {
+                                               final_value_msat
+                                       };
                                        // Verify the liquidity offered by this channel complies to the minimal contribution.
                                        let contributes_sufficient_value = available_value_contribution_msat >= minimal_value_contribution_msat;
 
@@ -866,6 +885,11 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
                        }
                }
 
+               if !allow_mpp {
+                       // If we don't support MPP, no use trying to gather more value ever.
+                       break 'paths_collection;
+               }
+
                // Step (3).
                // Stop either when recommended value is reached,
                // or if during last iteration no new path was found.