@@ -115,6 +115,8 @@ pub struct RouteHint {
115
115
pub cltv_expiry_delta : u16 ,
116
116
/// The minimum value, in msat, which must be relayed to the next hop.
117
117
pub htlc_minimum_msat : u64 ,
118
+ /// The maximum value in msat available for routing with a single HTLC.
119
+ pub htlc_maximum_msat : Option < u64 > ,
118
120
}
119
121
120
122
#[ derive( Eq , PartialEq ) ]
@@ -140,6 +142,7 @@ impl cmp::PartialOrd for RouteGraphNode {
140
142
struct DummyDirectionalChannelInfo {
141
143
cltv_expiry_delta : u32 ,
142
144
htlc_minimum_msat : u64 ,
145
+ htlc_maximum_msat : Option < u64 > ,
143
146
fees : RoutingFees ,
144
147
}
145
148
@@ -181,6 +184,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
181
184
let dummy_directional_info = DummyDirectionalChannelInfo { // used for first_hops routes
182
185
cltv_expiry_delta : 0 ,
183
186
htlc_minimum_msat : 0 ,
187
+ htlc_maximum_msat : None ,
184
188
fees : RoutingFees {
185
189
base_msat : 0 ,
186
190
proportional_millionths : 0 ,
@@ -217,14 +221,24 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
217
221
// Adds entry which goes from $src_node_id to $dest_node_id
218
222
// over the channel with id $chan_id with fees described in
219
223
// $directional_info.
220
- ( $chan_id: expr, $src_node_id: expr, $dest_node_id: expr, $directional_info: expr, $chan_features: expr, $starting_fee_msat: expr ) => {
224
+ ( $chan_id: expr, $src_node_id: expr, $dest_node_id: expr, $directional_info: expr, $capacity_sats : expr , $ chan_features: expr, $starting_fee_msat: expr ) => {
221
225
//TODO: Explore simply adding fee to hit htlc_minimum_msat
222
226
if $starting_fee_msat as u64 + final_value_msat >= $directional_info. htlc_minimum_msat {
223
227
let proportional_fee_millions = ( $starting_fee_msat + final_value_msat) . checked_mul( $directional_info. fees. proportional_millionths as u64 ) ;
224
228
if let Some ( new_fee) = proportional_fee_millions. and_then( |part| {
225
229
( $directional_info. fees. base_msat as u64 ) . checked_add( part / 1000000 ) } )
226
230
{
227
231
let mut total_fee = $starting_fee_msat as u64 ;
232
+
233
+ let mut available_msat = $capacity_sats;
234
+ if let Some ( htlc_maximum_msat) = $directional_info. htlc_maximum_msat {
235
+ if let Some ( capacity_sats) = $capacity_sats {
236
+ available_msat = Some ( cmp:: min( capacity_sats * 1000 , htlc_maximum_msat) ) ;
237
+ } else {
238
+ available_msat = Some ( htlc_maximum_msat) ;
239
+ }
240
+ }
241
+
228
242
let hm_entry = dist. entry( & $src_node_id) ;
229
243
let old_entry = hm_entry. or_insert_with( || {
230
244
let node = network. get_nodes( ) . get( & $src_node_id) . unwrap( ) ;
@@ -245,6 +259,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
245
259
fee_msat: 0 ,
246
260
cltv_expiry_delta: 0 ,
247
261
} ,
262
+ None ,
248
263
)
249
264
} ) ;
250
265
if $src_node_id != * our_node_id {
@@ -273,7 +288,8 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
273
288
channel_features: $chan_features. clone( ) ,
274
289
fee_msat: new_fee, // This field is ignored on the last-hop anyway
275
290
cltv_expiry_delta: $directional_info. cltv_expiry_delta as u32 ,
276
- }
291
+ } ;
292
+ old_entry. 4 = available_msat;
277
293
}
278
294
}
279
295
}
@@ -284,7 +300,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
284
300
( $node: expr, $node_id: expr, $fee_to_target_msat: expr ) => {
285
301
if first_hops. is_some( ) {
286
302
if let Some ( & ( ref first_hop, ref features) ) = first_hop_targets. get( & $node_id) {
287
- add_entry!( first_hop, * our_node_id, $node_id, dummy_directional_info, features. to_context( ) , $fee_to_target_msat) ;
303
+ add_entry!( first_hop, * our_node_id, $node_id, dummy_directional_info, None :: < u64 > , features. to_context( ) , $fee_to_target_msat) ;
288
304
}
289
305
}
290
306
@@ -304,15 +320,15 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
304
320
if first_hops. is_none( ) || chan. node_two != * our_node_id {
305
321
if let Some ( two_to_one) = chan. two_to_one. as_ref( ) {
306
322
if two_to_one. enabled {
307
- add_entry!( chan_id, chan. node_two, chan. node_one, two_to_one, chan. features, $fee_to_target_msat) ;
323
+ add_entry!( chan_id, chan. node_two, chan. node_one, two_to_one, chan. capacity_sats , chan . features, $fee_to_target_msat) ;
308
324
}
309
325
}
310
326
}
311
327
} else {
312
328
if first_hops. is_none( ) || chan. node_one != * our_node_id {
313
329
if let Some ( one_to_two) = chan. one_to_two. as_ref( ) {
314
330
if one_to_two. enabled {
315
- add_entry!( chan_id, chan. node_one, chan. node_two, one_to_two, chan. features, $fee_to_target_msat) ;
331
+ add_entry!( chan_id, chan. node_one, chan. node_two, one_to_two, chan. capacity_sats , chan . features, $fee_to_target_msat) ;
316
332
}
317
333
}
318
334
@@ -340,12 +356,12 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
340
356
// bit lazy here. In the future, we should pull them out via our
341
357
// ChannelManager, but there's no reason to waste the space until we
342
358
// need them.
343
- add_entry ! ( first_hop, * our_node_id , hop. src_node_id, dummy_directional_info, features. to_context( ) , 0 ) ;
359
+ add_entry ! ( first_hop, * our_node_id , hop. src_node_id, dummy_directional_info, None :: < u64 > , features. to_context( ) , 0 ) ;
344
360
}
345
361
}
346
362
// BOLT 11 doesn't allow inclusion of features for the last hop hints, which
347
363
// really sucks, cause we're gonna need that eventually.
348
- add_entry ! ( hop. short_channel_id, hop. src_node_id, target, hop, ChannelFeatures :: empty( ) , 0 ) ;
364
+ add_entry ! ( hop. short_channel_id, hop. src_node_id, target, hop, None :: < u64 > , ChannelFeatures :: empty( ) , 0 ) ;
349
365
}
350
366
}
351
367
}
@@ -1049,6 +1065,7 @@ mod tests {
1049
1065
fees: zero_fees,
1050
1066
cltv_expiry_delta: ( 8 << 8 ) | 1 ,
1051
1067
htlc_minimum_msat: 0 ,
1068
+ htlc_maximum_msat: None ,
1052
1069
} , RouteHint {
1053
1070
src_node_id: node5. clone( ) ,
1054
1071
short_channel_id: 9 ,
@@ -1058,12 +1075,14 @@ mod tests {
1058
1075
} ,
1059
1076
cltv_expiry_delta: ( 9 << 8 ) | 1 ,
1060
1077
htlc_minimum_msat: 0 ,
1078
+ htlc_maximum_msat: None ,
1061
1079
} , RouteHint {
1062
1080
src_node_id: node6. clone( ) ,
1063
1081
short_channel_id: 10 ,
1064
1082
fees: zero_fees,
1065
1083
cltv_expiry_delta: ( 10 << 8 ) | 1 ,
1066
1084
htlc_minimum_msat: 0 ,
1085
+ htlc_maximum_msat: None ,
1067
1086
} ) ;
1068
1087
1069
1088
// Simple test across 2, 3, 5, and 4 via a last_hop channel
0 commit comments