@@ -124,7 +124,9 @@ pub struct RouteHint {
124
124
/// The difference in CLTV values between this node and the next node.
125
125
pub cltv_expiry_delta : u16 ,
126
126
/// The minimum value, in msat, which must be relayed to the next hop.
127
- pub htlc_minimum_msat : u64 ,
127
+ pub htlc_minimum_msat : Option < u64 > ,
128
+ /// The maximum value in msat available for routing with a single HTLC.
129
+ pub htlc_maximum_msat : Option < u64 > ,
128
130
}
129
131
130
132
#[ derive( Eq , PartialEq ) ]
@@ -150,6 +152,7 @@ impl cmp::PartialOrd for RouteGraphNode {
150
152
struct DummyDirectionalChannelInfo {
151
153
cltv_expiry_delta : u32 ,
152
154
htlc_minimum_msat : u64 ,
155
+ htlc_maximum_msat : Option < u64 > ,
153
156
fees : RoutingFees ,
154
157
}
155
158
@@ -191,6 +194,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
191
194
let dummy_directional_info = DummyDirectionalChannelInfo { // used for first_hops routes
192
195
cltv_expiry_delta : 0 ,
193
196
htlc_minimum_msat : 0 ,
197
+ htlc_maximum_msat : None ,
194
198
fees : RoutingFees {
195
199
base_msat : 0 ,
196
200
proportional_millionths : 0 ,
@@ -227,14 +231,24 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
227
231
// Adds entry which goes from $src_node_id to $dest_node_id
228
232
// over the channel with id $chan_id with fees described in
229
233
// $directional_info.
230
- ( $chan_id: expr, $src_node_id: expr, $dest_node_id: expr, $directional_info: expr, $chan_features: expr, $starting_fee_msat: expr ) => {
234
+ ( $chan_id: expr, $src_node_id: expr, $dest_node_id: expr, $directional_info: expr, $capacity_sats : expr , $ chan_features: expr, $starting_fee_msat: expr ) => {
231
235
//TODO: Explore simply adding fee to hit htlc_minimum_msat
232
236
if $starting_fee_msat as u64 + final_value_msat >= $directional_info. htlc_minimum_msat {
233
237
let proportional_fee_millions = ( $starting_fee_msat + final_value_msat) . checked_mul( $directional_info. fees. proportional_millionths as u64 ) ;
234
238
if let Some ( new_fee) = proportional_fee_millions. and_then( |part| {
235
239
( $directional_info. fees. base_msat as u64 ) . checked_add( part / 1000000 ) } )
236
240
{
237
241
let mut total_fee = $starting_fee_msat as u64 ;
242
+
243
+ let mut available_msat = $capacity_sats;
244
+ if let Some ( htlc_maximum_msat) = $directional_info. htlc_maximum_msat {
245
+ if let Some ( capacity_sats) = $capacity_sats {
246
+ available_msat = Some ( cmp:: min( capacity_sats * 1000 , htlc_maximum_msat) ) ;
247
+ } else {
248
+ available_msat = Some ( htlc_maximum_msat) ;
249
+ }
250
+ }
251
+
238
252
let hm_entry = dist. entry( & $src_node_id) ;
239
253
let old_entry = hm_entry. or_insert_with( || {
240
254
let mut fee_base_msat = u32 :: max_value( ) ;
@@ -254,6 +268,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
254
268
fee_msat: 0 ,
255
269
cltv_expiry_delta: 0 ,
256
270
} ,
271
+ None ,
257
272
)
258
273
} ) ;
259
274
if $src_node_id != * our_node_id {
@@ -282,7 +297,8 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
282
297
channel_features: $chan_features. clone( ) ,
283
298
fee_msat: new_fee, // This field is ignored on the last-hop anyway
284
299
cltv_expiry_delta: $directional_info. cltv_expiry_delta as u32 ,
285
- }
300
+ } ;
301
+ old_entry. 4 = available_msat;
286
302
}
287
303
}
288
304
}
@@ -293,7 +309,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
293
309
( $node: expr, $node_id: expr, $fee_to_target_msat: expr ) => {
294
310
if first_hops. is_some( ) {
295
311
if let Some ( & ( ref first_hop, ref features) ) = first_hop_targets. get( & $node_id) {
296
- add_entry!( first_hop, * our_node_id, $node_id, dummy_directional_info, features. to_context( ) , $fee_to_target_msat) ;
312
+ add_entry!( first_hop, * our_node_id, $node_id, dummy_directional_info, None :: < u64 > , features. to_context( ) , $fee_to_target_msat) ;
297
313
}
298
314
}
299
315
@@ -313,15 +329,15 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
313
329
if first_hops. is_none( ) || chan. node_two != * our_node_id {
314
330
if let Some ( two_to_one) = chan. two_to_one. as_ref( ) {
315
331
if two_to_one. enabled {
316
- add_entry!( chan_id, chan. node_two, chan. node_one, two_to_one, chan. features, $fee_to_target_msat) ;
332
+ add_entry!( chan_id, chan. node_two, chan. node_one, two_to_one, chan. capacity_sats , chan . features, $fee_to_target_msat) ;
317
333
}
318
334
}
319
335
}
320
336
} else {
321
337
if first_hops. is_none( ) || chan. node_one != * our_node_id {
322
338
if let Some ( one_to_two) = chan. one_to_two. as_ref( ) {
323
339
if one_to_two. enabled {
324
- add_entry!( chan_id, chan. node_one, chan. node_two, one_to_two, chan. features, $fee_to_target_msat) ;
340
+ add_entry!( chan_id, chan. node_one, chan. node_two, one_to_two, chan. capacity_sats , chan . features, $fee_to_target_msat) ;
325
341
}
326
342
}
327
343
@@ -350,7 +366,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
350
366
// bit lazy here. In the future, we should pull them out via our
351
367
// ChannelManager, but there's no reason to waste the space until we
352
368
// need them.
353
- add_entry ! ( first_hop, * our_node_id , hop. src_node_id, dummy_directional_info, features. to_context( ) , 0 ) ;
369
+ add_entry ! ( first_hop, * our_node_id , hop. src_node_id, dummy_directional_info, None :: < u64 > , features. to_context( ) , 0 ) ;
354
370
true
355
371
} else {
356
372
// In any other case, only add the hop if the source is in the regular network
@@ -360,7 +376,17 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
360
376
if have_hop_src_in_graph {
361
377
// BOLT 11 doesn't allow inclusion of features for the last hop hints, which
362
378
// really sucks, cause we're gonna need that eventually.
363
- add_entry ! ( hop. short_channel_id, hop. src_node_id, target, hop, ChannelFeatures :: empty( ) , 0 ) ;
379
+ let last_hop_htlc_minimum_msat: u64 = match hop. htlc_minimum_msat {
380
+ Some ( htlc_minimum_msat) => htlc_minimum_msat,
381
+ None => 0
382
+ } ;
383
+ let directional_info = DummyDirectionalChannelInfo {
384
+ cltv_expiry_delta : hop. cltv_expiry_delta as u32 ,
385
+ htlc_minimum_msat : last_hop_htlc_minimum_msat,
386
+ htlc_maximum_msat : hop. htlc_maximum_msat ,
387
+ fees : hop. fees ,
388
+ } ;
389
+ add_entry ! ( hop. short_channel_id, hop. src_node_id, target, directional_info, None :: <u64 >, ChannelFeatures :: empty( ) , 0 ) ;
364
390
}
365
391
}
366
392
@@ -1048,7 +1074,8 @@ mod tests {
1048
1074
short_channel_id: 8 ,
1049
1075
fees: zero_fees,
1050
1076
cltv_expiry_delta: ( 8 << 8 ) | 1 ,
1051
- htlc_minimum_msat: 0 ,
1077
+ htlc_minimum_msat: None ,
1078
+ htlc_maximum_msat: None ,
1052
1079
} , RouteHint {
1053
1080
src_node_id: nodes[ 4 ] . clone( ) ,
1054
1081
short_channel_id: 9 ,
@@ -1057,13 +1084,15 @@ mod tests {
1057
1084
proportional_millionths: 0 ,
1058
1085
} ,
1059
1086
cltv_expiry_delta: ( 9 << 8 ) | 1 ,
1060
- htlc_minimum_msat: 0 ,
1087
+ htlc_minimum_msat: None ,
1088
+ htlc_maximum_msat: None ,
1061
1089
} , RouteHint {
1062
1090
src_node_id: nodes[ 5 ] . clone( ) ,
1063
1091
short_channel_id: 10 ,
1064
1092
fees: zero_fees,
1065
1093
cltv_expiry_delta: ( 10 << 8 ) | 1 ,
1066
- htlc_minimum_msat: 0 ,
1094
+ htlc_minimum_msat: None ,
1095
+ htlc_maximum_msat: None ,
1067
1096
} )
1068
1097
}
1069
1098
@@ -1245,7 +1274,8 @@ mod tests {
1245
1274
proportional_millionths: 0 ,
1246
1275
} ,
1247
1276
cltv_expiry_delta: ( 8 << 8 ) | 1 ,
1248
- htlc_minimum_msat: 0 ,
1277
+ htlc_minimum_msat: None ,
1278
+ htlc_maximum_msat: None ,
1249
1279
} ] ;
1250
1280
let our_chans = vec ! [ channelmanager:: ChannelDetails {
1251
1281
channel_id: [ 0 ; 32 ] ,
0 commit comments