@@ -176,6 +176,12 @@ impl_writeable_tlv_based!(RouteParameters, {
176176/// Maximum total CTLV difference we allow for a full payment path.
177177pub const DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA : u32 = 1008 ;
178178
179+ /// Maximum number of paths we allow an MPP payment to have.
180+ // The default limit is currently set rather arbitrary - there aren't any real fundamental path-count
181+ // limits. After we support retrying individual paths we should likely bump this, but
182+ // for now more than 10 paths likely carries too much one-path failure.
183+ pub const DEFAULT_MAX_MPP_PATH_COUNT : u8 = 10 ;
184+
179185// The median hop CLTV expiry delta currently seen in the network.
180186const MEDIAN_HOP_CLTV_EXPIRY_DELTA : u32 = 40 ;
181187
@@ -215,12 +221,16 @@ pub struct PaymentParameters {
215221
216222 /// The maximum total CLTV delta we accept for the route.
217223 pub max_total_cltv_expiry_delta : u32 ,
224+
225+ /// The maximum number of paths that may be used by MPP payments.
226+ pub max_mpp_path_count : u8 ,
218227}
219228
220229impl_writeable_tlv_based ! ( PaymentParameters , {
221230 ( 0 , payee_pubkey, required) ,
222231 ( 1 , max_total_cltv_expiry_delta, ( default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ) ) ,
223232 ( 2 , features, option) ,
233+ ( 3 , max_mpp_path_count, ( default_value, DEFAULT_MAX_MPP_PATH_COUNT ) ) ,
224234 ( 4 , route_hints, vec_type) ,
225235 ( 6 , expiry_time, option) ,
226236} ) ;
@@ -234,6 +244,7 @@ impl PaymentParameters {
234244 route_hints : vec ! [ ] ,
235245 expiry_time : None ,
236246 max_total_cltv_expiry_delta : DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ,
247+ max_mpp_path_count : DEFAULT_MAX_MPP_PATH_COUNT ,
237248 }
238249 }
239250
@@ -269,6 +280,13 @@ impl PaymentParameters {
269280 pub fn with_max_total_cltv_expiry_delta ( self , max_total_cltv_expiry_delta : u32 ) -> Self {
270281 Self { max_total_cltv_expiry_delta, ..self }
271282 }
283+
284+ /// Includes a limit for the maximum number of payment paths that may be used by MPP.
285+ ///
286+ /// (C-not exported) since bindings don't support move semantics
287+ pub fn with_max_mpp_path_count ( self , max_mpp_path_count : u8 ) -> Self {
288+ Self { max_mpp_path_count, ..self }
289+ }
272290}
273291
274292/// A list of hops along a payment path terminating with a channel to the recipient.
@@ -790,6 +808,11 @@ where L::Target: Logger {
790808 node_info. features . supports_basic_mpp ( )
791809 } else { false }
792810 } else { false } ;
811+
812+ if allow_mpp && payment_params. max_mpp_path_count == 0 {
813+ return Err ( LightningError { err : "Can't find an MPP route with no paths allowed." . to_owned ( ) , action : ErrorAction :: IgnoreError } ) ;
814+ }
815+
793816 log_trace ! ( logger, "Searching for a route from payer {} to payee {} {} MPP and {} first hops {}overriding the network graph" , our_node_pubkey,
794817 payment_params. payee_pubkey, if allow_mpp { "with" } else { "without" } ,
795818 first_hops. map( |hops| hops. len( ) ) . unwrap_or( 0 ) , if first_hops. is_some( ) { "" } else { "not " } ) ;
@@ -847,11 +870,8 @@ where L::Target: Logger {
847870 let mut used_channel_liquidities: HashMap < ( u64 , bool ) , u64 > =
848871 HashMap :: with_capacity ( network_nodes. len ( ) ) ;
849872
850- // Keeping track of how much value we already collected across other paths. Helps to decide:
851- // - how much a new path should be transferring (upper bound);
852- // - whether a channel should be disregarded because
853- // it's available liquidity is too small comparing to how much more we need to collect;
854- // - when we want to stop looking for new paths.
873+ // Keeping track of how much value we already collected across other paths. Helps to decide
874+ // when we want to stop looking for new paths.
855875 let mut already_collected_value_msat = 0 ;
856876
857877 for ( _, channels) in first_hop_targets. iter_mut ( ) {
@@ -920,16 +940,10 @@ where L::Target: Logger {
920940 // Taking too many smaller paths also increases the chance of payment failure.
921941 // Thus to avoid this effect, we require from our collected links to provide
922942 // at least a minimal contribution to the recommended value yet-to-be-fulfilled.
923- //
924- // This requirement is currently 5% of the remaining-to-be-collected value.
925- // This means as we successfully advance in our collection,
926- // the absolute liquidity contribution is lowered,
927- // thus increasing the number of potential channels to be selected.
928-
929- // Derive the minimal liquidity contribution with a ratio of 20 (5%, rounded up)
930- // or 100% if we're not allowed to do multipath payments.
943+ // This requirement is currently set to be 1/max_mpp_path_count of the payment
944+ // value to ensure we only ever return routes that do not violate this limit.
931945 let minimal_value_contribution_msat: u64 = if allow_mpp {
932- ( recommended_value_msat - already_collected_value_msat + 19 ) / 20
946+ ( final_value_msat + ( payment_params . max_mpp_path_count as u64 - 1 ) ) / payment_params . max_mpp_path_count as u64
933947 } else {
934948 final_value_msat
935949 } ;
@@ -1504,10 +1518,8 @@ where L::Target: Logger {
15041518 * used_channel_liquidities. entry ( ( victim_scid, true ) ) . or_default ( ) = exhausted;
15051519 }
15061520
1507- // Track the total amount all our collected paths allow to send so that we:
1508- // - know when to stop looking for more paths
1509- // - know which of the hops are useless considering how much more sats we need
1510- // (contributes_sufficient_value)
1521+ // Track the total amount all our collected paths allow to send so that we know
1522+ // when to stop looking for more paths
15111523 already_collected_value_msat += value_contribution_msat;
15121524
15131525 payment_paths. push ( payment_path) ;
@@ -1678,6 +1690,8 @@ where L::Target: Logger {
16781690 } ) ;
16791691 selected_paths. push ( path) ;
16801692 }
1693+ // Make sure we would never create a route with more paths than we allow.
1694+ assert ! ( selected_paths. len( ) <= payment_params. max_mpp_path_count. into( ) ) ;
16811695
16821696 if let Some ( features) = & payment_params. features {
16831697 for path in selected_paths. iter_mut ( ) {
0 commit comments