@@ -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 " } ) ;
@@ -917,12 +940,10 @@ where L::Target: Logger {
917940 // Taking too many smaller paths also increases the chance of payment failure.
918941 // Thus to avoid this effect, we require from our collected links to provide
919942 // at least a minimal contribution to the recommended value yet-to-be-fulfilled.
920- // This requirement is currently 10% of the value.
921-
922- // Derive the minimal liquidity contribution with a ratio of 10 (10%, rounded up)
923- // 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.
924945 let minimal_value_contribution_msat: u64 = if allow_mpp {
925- ( final_value_msat + 9 ) / 10
946+ ( final_value_msat + ( payment_params . max_mpp_path_count as u64 - 1 ) ) / payment_params . max_mpp_path_count as u64
926947 } else {
927948 final_value_msat
928949 } ;
@@ -1669,6 +1690,8 @@ where L::Target: Logger {
16691690 } ) ;
16701691 selected_paths. push ( path) ;
16711692 }
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( ) ) ;
16721695
16731696 if let Some ( features) = & payment_params. features {
16741697 for path in selected_paths. iter_mut ( ) {
0 commit comments