@@ -203,7 +203,7 @@ where
203
203
for PhantomRouteHints { channels, phantom_scid, real_node_pubkey } in phantom_route_hints {
204
204
log_trace ! ( logger, "Generating phantom route hints for node {}" ,
205
205
log_pubkey!( real_node_pubkey) ) ;
206
- let mut route_hints = filter_channels ( channels, amt_msat, & logger) ;
206
+ let mut route_hints = sort_and_filter_channels ( channels, amt_msat, & logger) ;
207
207
208
208
// If we have any public channel, the route hints from `filter_channels` will be empty.
209
209
// In that case we create a RouteHint on which we will push a single hop with the phantom
@@ -485,7 +485,7 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has
485
485
invoice = invoice. amount_milli_satoshis ( amt) ;
486
486
}
487
487
488
- let route_hints = filter_channels ( channels, amt_msat, & logger) ;
488
+ let route_hints = sort_and_filter_channels ( channels, amt_msat, & logger) ;
489
489
for hint in route_hints {
490
490
invoice = invoice. private_route ( hint) ;
491
491
}
@@ -504,8 +504,8 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has
504
504
}
505
505
}
506
506
507
- /// Filters the `channels` for an invoice, and returns the corresponding `RouteHint`s to include
508
- /// in the invoice.
507
+ /// Filters the `channels` for an invoice, and returns the three corresponding `RouteHint`s
508
+ /// with the most inbound capacity to include in the invoice.
509
509
///
510
510
/// The filtering is based on the following criteria:
511
511
/// * Only one channel per counterparty node
@@ -514,7 +514,7 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has
514
514
/// `is_usable` (i.e. the peer is connected).
515
515
/// * If any public channel exists, the returned `RouteHint`s will be empty, and the sender will
516
516
/// need to find the path by looking at the public channels instead
517
- fn filter_channels < L : Deref > (
517
+ fn sort_and_filter_channels < L : Deref > (
518
518
channels : Vec < ChannelDetails > , min_inbound_capacity_msat : Option < u64 > , logger : & L
519
519
) -> Vec < RouteHint > where L :: Target : Logger {
520
520
let mut filtered_channels: HashMap < PublicKey , ChannelDetails > = HashMap :: new ( ) ;
@@ -597,7 +597,7 @@ fn filter_channels<L: Deref>(
597
597
// the payment value and where we're currently connected to the channel counterparty.
598
598
// Even if we cannot satisfy both goals, always ensure we include *some* hints, preferring
599
599
// those which meet at least one criteria.
600
- filtered_channels
600
+ let mut eligible_channels = filtered_channels
601
601
. into_iter ( )
602
602
. map ( |( _, channel) | channel)
603
603
. filter ( |channel| {
@@ -610,7 +610,7 @@ fn filter_channels<L: Deref>(
610
610
// online-ness.
611
611
has_enough_capacity
612
612
} else if min_capacity_channel_exists {
613
- has_enough_capacity
613
+ has_enough_capacity
614
614
} else if online_channel_exists {
615
615
channel. is_usable
616
616
} else { true } ;
@@ -629,8 +629,11 @@ fn filter_channels<L: Deref>(
629
629
630
630
include_channel
631
631
} )
632
- . map ( route_hint_from_channel)
633
- . collect :: < Vec < RouteHint > > ( )
632
+ . collect :: < Vec < ChannelDetails > > ( ) ;
633
+
634
+ // Sort eligible channels by inbound capacity and return the top 3.
635
+ eligible_channels. sort_unstable_by ( |a, b| b. inbound_capacity_msat . cmp ( & a. inbound_capacity_msat ) ) ;
636
+ eligible_channels. into_iter ( ) . take ( 3 ) . map ( route_hint_from_channel) . collect :: < Vec < RouteHint > > ( )
634
637
}
635
638
636
639
#[ cfg( test) ]
@@ -852,6 +855,26 @@ mod test {
852
855
match_invoice_routes ( Some ( 1_000_000_000 ) , & nodes[ 0 ] , scid_aliases) ;
853
856
}
854
857
858
+ #[ test]
859
+ fn test_hints_limited_to_3 ( ) {
860
+ let chanmon_cfgs = create_chanmon_cfgs ( 5 ) ;
861
+ let node_cfgs = create_node_cfgs ( 5 , & chanmon_cfgs) ;
862
+ let node_chanmgrs = create_node_chanmgrs ( 5 , & node_cfgs, & [ None , None , None , None , None ] ) ;
863
+ let nodes = create_network ( 5 , & node_cfgs, & node_chanmgrs) ;
864
+
865
+ let chan_1_0 = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100_004 , 0 ) ;
866
+ let chan_2_0 = create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 100_003 , 0 ) ;
867
+ let chan_3_0 = create_unannounced_chan_between_nodes_with_value ( & nodes, 3 , 0 , 100_002 , 0 ) ;
868
+ let _chan_4_0 = create_unannounced_chan_between_nodes_with_value ( & nodes, 4 , 0 , 100_001 , 0 ) ;
869
+
870
+ let mut scid_aliases = HashSet :: new ( ) ;
871
+ scid_aliases. insert ( chan_1_0. 0 . short_channel_id_alias . unwrap ( ) ) ;
872
+ scid_aliases. insert ( chan_2_0. 0 . short_channel_id_alias . unwrap ( ) ) ;
873
+ scid_aliases. insert ( chan_3_0. 0 . short_channel_id_alias . unwrap ( ) ) ;
874
+
875
+ match_invoice_routes ( Some ( 500_000 ) , & nodes[ 0 ] , scid_aliases) ;
876
+ }
877
+
855
878
#[ test]
856
879
fn test_forwarding_info_not_assigned_channel_excluded_from_hints ( ) {
857
880
let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
0 commit comments