@@ -176,6 +176,12 @@ impl_writeable_tlv_based!(RouteParameters, {
176
176
/// Maximum total CTLV difference we allow for a full payment path.
177
177
pub const DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA : u32 = 1008 ;
178
178
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
+
179
185
// The median hop CLTV expiry delta currently seen in the network.
180
186
const MEDIAN_HOP_CLTV_EXPIRY_DELTA : u32 = 40 ;
181
187
@@ -215,12 +221,16 @@ pub struct PaymentParameters {
215
221
216
222
/// The maximum total CLTV delta we accept for the route.
217
223
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 ,
218
227
}
219
228
220
229
impl_writeable_tlv_based ! ( PaymentParameters , {
221
230
( 0 , payee_pubkey, required) ,
222
231
( 1 , max_total_cltv_expiry_delta, ( default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ) ) ,
223
232
( 2 , features, option) ,
233
+ ( 3 , max_mpp_path_count, ( default_value, DEFAULT_MAX_MPP_PATH_COUNT ) ) ,
224
234
( 4 , route_hints, vec_type) ,
225
235
( 6 , expiry_time, option) ,
226
236
} ) ;
@@ -234,6 +244,7 @@ impl PaymentParameters {
234
244
route_hints : vec ! [ ] ,
235
245
expiry_time : None ,
236
246
max_total_cltv_expiry_delta : DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ,
247
+ max_mpp_path_count : DEFAULT_MAX_MPP_PATH_COUNT ,
237
248
}
238
249
}
239
250
@@ -269,6 +280,13 @@ impl PaymentParameters {
269
280
pub fn with_max_total_cltv_expiry_delta ( self , max_total_cltv_expiry_delta : u32 ) -> Self {
270
281
Self { max_total_cltv_expiry_delta, ..self }
271
282
}
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
+ }
272
290
}
273
291
274
292
/// A list of hops along a payment path terminating with a channel to the recipient.
@@ -790,6 +808,11 @@ where L::Target: Logger {
790
808
node_info. features . supports_basic_mpp ( )
791
809
} else { false }
792
810
} 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
+
793
816
log_trace ! ( logger, "Searching for a route from payer {} to payee {} {} MPP and {} first hops {}overriding the network graph" , our_node_pubkey,
794
817
payment_params. payee_pubkey, if allow_mpp { "with" } else { "without" } ,
795
818
first_hops. map( |hops| hops. len( ) ) . unwrap_or( 0 ) , if first_hops. is_some( ) { "" } else { "not " } ) ;
@@ -847,11 +870,8 @@ where L::Target: Logger {
847
870
let mut used_channel_liquidities: HashMap < ( u64 , bool ) , u64 > =
848
871
HashMap :: with_capacity ( network_nodes. len ( ) ) ;
849
872
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.
855
875
let mut already_collected_value_msat = 0 ;
856
876
857
877
for ( _, channels) in first_hop_targets. iter_mut ( ) {
@@ -920,16 +940,10 @@ where L::Target: Logger {
920
940
// Taking too many smaller paths also increases the chance of payment failure.
921
941
// Thus to avoid this effect, we require from our collected links to provide
922
942
// 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.
931
945
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
933
947
} else {
934
948
final_value_msat
935
949
} ;
@@ -1504,10 +1518,8 @@ where L::Target: Logger {
1504
1518
* used_channel_liquidities. entry ( ( victim_scid, true ) ) . or_default ( ) = exhausted;
1505
1519
}
1506
1520
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
1511
1523
already_collected_value_msat += value_contribution_msat;
1512
1524
1513
1525
payment_paths. push ( payment_path) ;
@@ -1678,6 +1690,8 @@ where L::Target: Logger {
1678
1690
} ) ;
1679
1691
selected_paths. push ( path) ;
1680
1692
}
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( ) ) ;
1681
1695
1682
1696
if let Some ( features) = & payment_params. features {
1683
1697
for path in selected_paths. iter_mut ( ) {
0 commit comments