@@ -326,7 +326,7 @@ where
326326 F :: Target : FeeEstimator ,
327327 L :: Target : Logger ,
328328{
329- let route_hints = filter_channels ( channelmanager. list_usable_channels ( ) , amt_msat) ;
329+ let route_hints = filter_channels ( channelmanager. list_channels ( ) , amt_msat) ;
330330
331331 // `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin
332332 // supply.
@@ -377,16 +377,18 @@ where
377377/// The filtering is based on the following criteria:
378378/// * Only one channel per counterparty node
379379/// * Always select the channel with the highest inbound capacity per counterparty node
380- /// * Filter out channels with a lower inbound capacity than `min_inbound_capacity_msat`, if any
381- /// channel with a higher or equal inbound capacity than `min_inbound_capacity_msat` exists
380+ /// * Prefer channels with capacity at least `min_inbound_capacity_msat` and where the channel
381+ /// `is_usable` (i.e. the peer is connected).
382382/// * If any public channel exists, the returned `RouteHint`s will be empty, and the sender will
383- /// need to find the path by looking at the public channels instead
383+ /// need to find the path by looking at the public channels instead
384384fn filter_channels ( channels : Vec < ChannelDetails > , min_inbound_capacity_msat : Option < u64 > ) -> Vec < RouteHint > {
385- let mut filtered_channels: HashMap < PublicKey , & ChannelDetails > = HashMap :: new ( ) ;
385+ let mut filtered_channels: HashMap < PublicKey , ChannelDetails > = HashMap :: new ( ) ;
386386 let min_inbound_capacity = min_inbound_capacity_msat. unwrap_or ( 0 ) ;
387387 let mut min_capacity_channel_exists = false ;
388+ let mut online_channel_exists = false ;
389+ let mut online_min_capacity_channel_exists = false ;
388390
389- for channel in channels. iter ( ) {
391+ for channel in channels. into_iter ( ) . filter ( |chan| chan . is_channel_ready ) {
390392 if channel. get_inbound_payment_scid ( ) . is_none ( ) || channel. counterparty . forwarding_info . is_none ( ) {
391393 continue ;
392394 }
@@ -399,7 +401,13 @@ fn filter_channels(channels: Vec<ChannelDetails>, min_inbound_capacity_msat: Opt
399401
400402 if channel. inbound_capacity_msat >= min_inbound_capacity {
401403 min_capacity_channel_exists = true ;
402- } ;
404+ if channel. is_usable {
405+ online_min_capacity_channel_exists = true ;
406+ }
407+ }
408+ if channel. is_usable {
409+ online_channel_exists = true ;
410+ }
403411 match filtered_channels. entry ( channel. counterparty . node_id ) {
404412 hash_map:: Entry :: Occupied ( mut entry) => {
405413 let current_max_capacity = entry. get ( ) . inbound_capacity_msat ;
@@ -414,7 +422,7 @@ fn filter_channels(channels: Vec<ChannelDetails>, min_inbound_capacity_msat: Opt
414422 }
415423 }
416424
417- let route_hint_from_channel = |channel : & ChannelDetails | {
425+ let route_hint_from_channel = |channel : ChannelDetails | {
418426 let forwarding_info = channel. counterparty . forwarding_info . as_ref ( ) . unwrap ( ) ;
419427 RouteHint ( vec ! [ RouteHintHop {
420428 src_node_id: channel. counterparty. node_id,
@@ -427,15 +435,26 @@ fn filter_channels(channels: Vec<ChannelDetails>, min_inbound_capacity_msat: Opt
427435 htlc_minimum_msat: channel. inbound_htlc_minimum_msat,
428436 htlc_maximum_msat: channel. inbound_htlc_maximum_msat, } ] )
429437 } ;
430- // If all channels are private, return the route hint for the highest inbound capacity channel
431- // per counterparty node. If channels with an higher inbound capacity than the
432- // min_inbound_capacity exists, filter out the channels with a lower capacity than that.
438+ // If all channels are private, prefer to return route hints which have a higher capacity than
439+ // the payment value and where we're currently connected to the channel counterparty.
440+ // Even if we cannot satisfy both goals, always ensure we include *some* hints, preferring
441+ // those which meet at least one criteria.
433442 filtered_channels. into_iter ( )
434443 . filter ( |( _counterparty_id, channel) | {
435- min_capacity_channel_exists && channel. inbound_capacity_msat >= min_inbound_capacity ||
436- !min_capacity_channel_exists
444+ if online_min_capacity_channel_exists {
445+ channel. inbound_capacity_msat >= min_inbound_capacity && channel. is_usable
446+ } else if min_capacity_channel_exists && online_channel_exists {
447+ // If there are some online channels and some min_capacity channels, but no
448+ // online-and-min_capacity channels, just include the min capacity ones and ignore
449+ // online-ness.
450+ channel. inbound_capacity_msat >= min_inbound_capacity
451+ } else if min_capacity_channel_exists {
452+ channel. inbound_capacity_msat >= min_inbound_capacity
453+ } else if online_channel_exists {
454+ channel. is_usable
455+ } else { true }
437456 } )
438- . map ( |( _counterparty_id, channel) | route_hint_from_channel ( & channel) )
457+ . map ( |( _counterparty_id, channel) | route_hint_from_channel ( channel) )
439458 . collect :: < Vec < RouteHint > > ( )
440459}
441460
@@ -723,6 +742,35 @@ mod test {
723742 match_invoice_routes ( Some ( 5000 ) , & nodes[ 0 ] , scid_aliases) ;
724743 }
725744
745+ #[ test]
746+ fn test_hints_has_only_online_channels ( ) {
747+ let chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
748+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
749+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
750+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
751+ let chan_a = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 10_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) ;
752+ let chan_b = create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 10_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) ;
753+ let _chan_c = create_unannounced_chan_between_nodes_with_value ( & nodes, 3 , 0 , 1_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) ;
754+
755+ // With all peers connected we should get all hints that have sufficient value
756+ let mut scid_aliases = HashSet :: new ( ) ;
757+ scid_aliases. insert ( chan_a. 0 . short_channel_id_alias . unwrap ( ) ) ;
758+ scid_aliases. insert ( chan_b. 0 . short_channel_id_alias . unwrap ( ) ) ;
759+
760+ match_invoice_routes ( Some ( 1_000_000_000 ) , & nodes[ 0 ] , scid_aliases. clone ( ) ) ;
761+
762+ // With only one sufficient-value peer connected we should only get its hint
763+ scid_aliases. remove ( & chan_b. 0 . short_channel_id_alias . unwrap ( ) ) ;
764+ nodes[ 0 ] . node . peer_disconnected ( & nodes[ 2 ] . node . get_our_node_id ( ) , false ) ;
765+ match_invoice_routes ( Some ( 1_000_000_000 ) , & nodes[ 0 ] , scid_aliases. clone ( ) ) ;
766+
767+ // If we don't have any sufficient-value peers connected we should get all hints with
768+ // sufficient value, even though there is a connected insufficient-value peer.
769+ scid_aliases. insert ( chan_b. 0 . short_channel_id_alias . unwrap ( ) ) ;
770+ nodes[ 0 ] . node . peer_disconnected ( & nodes[ 1 ] . node . get_our_node_id ( ) , false ) ;
771+ match_invoice_routes ( Some ( 1_000_000_000 ) , & nodes[ 0 ] , scid_aliases) ;
772+ }
773+
726774 #[ test]
727775 fn test_forwarding_info_not_assigned_channel_excluded_from_hints ( ) {
728776 let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
0 commit comments