@@ -893,8 +893,8 @@ where L::Target: Logger {
893893 // semi-dummy record just to compute the fees to reach the source node.
894894 // This will affect our decision on selecting short_channel_id
895895 // as a way to reach the $dest_node_id.
896- let mut fee_base_msat = u32 :: max_value ( ) ;
897- let mut fee_proportional_millionths = u32 :: max_value ( ) ;
896+ let mut fee_base_msat = 0 ;
897+ let mut fee_proportional_millionths = 0 ;
898898 if let Some ( Some ( fees) ) = network_nodes. get( & $src_node_id) . map( |node| node. lowest_inbound_channel_fees) {
899899 fee_base_msat = fees. base_msat;
900900 fee_proportional_millionths = fees. proportional_millionths;
@@ -1285,11 +1285,9 @@ where L::Target: Logger {
12851285 ordered_hops. last_mut ( ) . unwrap ( ) . 1 = NodeFeatures :: empty ( ) ;
12861286 }
12871287 } else {
1288- // We should be able to fill in features for everything except the last
1289- // hop, if the last hop was provided via a BOLT 11 invoice (though we
1290- // should be able to extend it further as BOLT 11 does have feature
1291- // flags for the last hop node itself).
1292- assert ! ( ordered_hops. last( ) . unwrap( ) . 0 . node_id == payee_node_id) ;
1288+ // We can fill in features for everything except hops which were
1289+ // provided via the invoice we're paying. We could guess based on the
1290+ // recipient's features but for now we simply avoid guessing at all.
12931291 }
12941292 }
12951293
@@ -1671,7 +1669,7 @@ mod tests {
16711669
16721670 fn get_nodes ( secp_ctx : & Secp256k1 < All > ) -> ( SecretKey , PublicKey , Vec < SecretKey > , Vec < PublicKey > ) {
16731671 let privkeys: Vec < SecretKey > = ( 2 ..10 ) . map ( |i| {
1674- SecretKey :: from_slice ( & hex:: decode ( format ! ( "{:02 }" , i) . repeat ( 32 ) ) . unwrap ( ) [ ..] ) . unwrap ( )
1672+ SecretKey :: from_slice ( & hex:: decode ( format ! ( "{:02x }" , i) . repeat ( 32 ) ) . unwrap ( ) [ ..] ) . unwrap ( )
16751673 } ) . collect ( ) ;
16761674
16771675 let pubkeys = privkeys. iter ( ) . map ( |secret| PublicKey :: from_secret_key ( & secp_ctx, secret) ) . collect ( ) ;
@@ -2697,14 +2695,16 @@ mod tests {
26972695 assert_eq ! ( route. paths[ 0 ] [ 4 ] . channel_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ; // We can't learn any flags from invoices, sadly
26982696 }
26992697
2700- fn multi_hint_last_hops ( nodes : & Vec < PublicKey > ) -> Vec < RouteHint > {
2698+ /// Builds a trivial last-hop hint that passes through the two nodes given, with channel 0xff00
2699+ /// and 0xff01.
2700+ fn multi_hop_last_hops_hint ( hint_hops : [ PublicKey ; 2 ] ) -> Vec < RouteHint > {
27012701 let zero_fees = RoutingFees {
27022702 base_msat : 0 ,
27032703 proportional_millionths : 0 ,
27042704 } ;
27052705 vec ! [ RouteHint ( vec![ RouteHintHop {
2706- src_node_id: nodes [ 2 ] ,
2707- short_channel_id: 5 ,
2706+ src_node_id: hint_hops [ 0 ] ,
2707+ short_channel_id: 0xff00 ,
27082708 fees: RoutingFees {
27092709 base_msat: 100 ,
27102710 proportional_millionths: 0 ,
@@ -2713,29 +2713,23 @@ mod tests {
27132713 htlc_minimum_msat: None ,
27142714 htlc_maximum_msat: None ,
27152715 } , RouteHintHop {
2716- src_node_id: nodes [ 3 ] ,
2717- short_channel_id: 8 ,
2716+ src_node_id: hint_hops [ 1 ] ,
2717+ short_channel_id: 0xff01 ,
27182718 fees: zero_fees,
27192719 cltv_expiry_delta: ( 8 << 4 ) | 1 ,
27202720 htlc_minimum_msat: None ,
27212721 htlc_maximum_msat: None ,
2722- } ] ) , RouteHint ( vec![ RouteHintHop {
2723- src_node_id: nodes[ 5 ] ,
2724- short_channel_id: 10 ,
2725- fees: zero_fees,
2726- cltv_expiry_delta: ( 10 << 4 ) | 1 ,
2727- htlc_minimum_msat: None ,
2728- htlc_maximum_msat: None ,
27292722 } ] ) ]
27302723 }
27312724
27322725 #[ test]
27332726 fn multi_hint_last_hops_test ( ) {
27342727 let ( secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph ( ) ;
27352728 let ( _, our_id, privkeys, nodes) = get_nodes ( & secp_ctx) ;
2736- let payment_params = PaymentParameters :: from_node_id ( nodes[ 6 ] ) . with_route_hints ( multi_hint_last_hops ( & nodes) ) ;
2729+ let last_hops = multi_hop_last_hops_hint ( [ nodes[ 2 ] , nodes[ 3 ] ] ) ;
2730+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 6 ] ) . with_route_hints ( last_hops. clone ( ) ) ;
27372731 let scorer = test_utils:: TestScorer :: with_penalty ( 0 ) ;
2738- // Test through channels 2, 3, 5, 8 .
2732+ // Test through channels 2, 3, 0xff00, 0xff01 .
27392733 // Test shows that multiple hop hints are considered.
27402734
27412735 // Disabling channels 6 & 7 by flags=2
@@ -2782,14 +2776,86 @@ mod tests {
27822776 assert_eq ! ( route. paths[ 0 ] [ 1 ] . channel_features. le_flags( ) , & id_to_feature_flags( 4 ) ) ;
27832777
27842778 assert_eq ! ( route. paths[ 0 ] [ 2 ] . pubkey, nodes[ 3 ] ) ;
2785- assert_eq ! ( route. paths[ 0 ] [ 2 ] . short_channel_id, 5 ) ;
2779+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . short_channel_id, last_hops [ 0 ] . 0 [ 0 ] . short_channel_id ) ;
27862780 assert_eq ! ( route. paths[ 0 ] [ 2 ] . fee_msat, 0 ) ;
27872781 assert_eq ! ( route. paths[ 0 ] [ 2 ] . cltv_expiry_delta, 129 ) ;
27882782 assert_eq ! ( route. paths[ 0 ] [ 2 ] . node_features. le_flags( ) , & id_to_feature_flags( 4 ) ) ;
2789- assert_eq ! ( route. paths[ 0 ] [ 2 ] . channel_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ;
2783+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . channel_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ; // We can't learn any flags from invoices, sadly
2784+
2785+ assert_eq ! ( route. paths[ 0 ] [ 3 ] . pubkey, nodes[ 6 ] ) ;
2786+ assert_eq ! ( route. paths[ 0 ] [ 3 ] . short_channel_id, last_hops[ 0 ] . 0 [ 1 ] . short_channel_id) ;
2787+ assert_eq ! ( route. paths[ 0 ] [ 3 ] . fee_msat, 100 ) ;
2788+ assert_eq ! ( route. paths[ 0 ] [ 3 ] . cltv_expiry_delta, 42 ) ;
2789+ assert_eq ! ( route. paths[ 0 ] [ 3 ] . node_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ; // We dont pass flags in from invoices yet
2790+ assert_eq ! ( route. paths[ 0 ] [ 3 ] . channel_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ; // We can't learn any flags from invoices, sadly
2791+ }
2792+
2793+ #[ test]
2794+ fn private_multi_hint_last_hops_test ( ) {
2795+ let ( secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph ( ) ;
2796+ let ( _, our_id, privkeys, nodes) = get_nodes ( & secp_ctx) ;
2797+
2798+ let non_announced_privkey = SecretKey :: from_slice ( & hex:: decode ( format ! ( "{:02x}" , 0xf0 ) . repeat ( 32 ) ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
2799+ let non_announced_pubkey = PublicKey :: from_secret_key ( & secp_ctx, & non_announced_privkey) ;
2800+
2801+ let last_hops = multi_hop_last_hops_hint ( [ nodes[ 2 ] , non_announced_pubkey] ) ;
2802+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 6 ] ) . with_route_hints ( last_hops. clone ( ) ) ;
2803+ let scorer = test_utils:: TestScorer :: with_penalty ( 0 ) ;
2804+ // Test through channels 2, 3, 0xff00, 0xff01.
2805+ // Test shows that multiple hop hints are considered.
2806+
2807+ // Disabling channels 6 & 7 by flags=2
2808+ update_channel ( & net_graph_msg_handler, & secp_ctx, & privkeys[ 2 ] , UnsignedChannelUpdate {
2809+ chain_hash : genesis_block ( Network :: Testnet ) . header . block_hash ( ) ,
2810+ short_channel_id : 6 ,
2811+ timestamp : 2 ,
2812+ flags : 2 , // to disable
2813+ cltv_expiry_delta : 0 ,
2814+ htlc_minimum_msat : 0 ,
2815+ htlc_maximum_msat : OptionalField :: Absent ,
2816+ fee_base_msat : 0 ,
2817+ fee_proportional_millionths : 0 ,
2818+ excess_data : Vec :: new ( )
2819+ } ) ;
2820+ update_channel ( & net_graph_msg_handler, & secp_ctx, & privkeys[ 2 ] , UnsignedChannelUpdate {
2821+ chain_hash : genesis_block ( Network :: Testnet ) . header . block_hash ( ) ,
2822+ short_channel_id : 7 ,
2823+ timestamp : 2 ,
2824+ flags : 2 , // to disable
2825+ cltv_expiry_delta : 0 ,
2826+ htlc_minimum_msat : 0 ,
2827+ htlc_maximum_msat : OptionalField :: Absent ,
2828+ fee_base_msat : 0 ,
2829+ fee_proportional_millionths : 0 ,
2830+ excess_data : Vec :: new ( )
2831+ } ) ;
2832+
2833+ let route = get_route ( & our_id, & payment_params, & network_graph, None , 100 , 42 , Arc :: clone ( & logger) , & scorer) . unwrap ( ) ;
2834+ assert_eq ! ( route. paths[ 0 ] . len( ) , 4 ) ;
2835+
2836+ assert_eq ! ( route. paths[ 0 ] [ 0 ] . pubkey, nodes[ 1 ] ) ;
2837+ assert_eq ! ( route. paths[ 0 ] [ 0 ] . short_channel_id, 2 ) ;
2838+ assert_eq ! ( route. paths[ 0 ] [ 0 ] . fee_msat, 200 ) ;
2839+ assert_eq ! ( route. paths[ 0 ] [ 0 ] . cltv_expiry_delta, 65 ) ;
2840+ assert_eq ! ( route. paths[ 0 ] [ 0 ] . node_features. le_flags( ) , & id_to_feature_flags( 2 ) ) ;
2841+ assert_eq ! ( route. paths[ 0 ] [ 0 ] . channel_features. le_flags( ) , & id_to_feature_flags( 2 ) ) ;
2842+
2843+ assert_eq ! ( route. paths[ 0 ] [ 1 ] . pubkey, nodes[ 2 ] ) ;
2844+ assert_eq ! ( route. paths[ 0 ] [ 1 ] . short_channel_id, 4 ) ;
2845+ assert_eq ! ( route. paths[ 0 ] [ 1 ] . fee_msat, 100 ) ;
2846+ assert_eq ! ( route. paths[ 0 ] [ 1 ] . cltv_expiry_delta, 81 ) ;
2847+ assert_eq ! ( route. paths[ 0 ] [ 1 ] . node_features. le_flags( ) , & id_to_feature_flags( 3 ) ) ;
2848+ assert_eq ! ( route. paths[ 0 ] [ 1 ] . channel_features. le_flags( ) , & id_to_feature_flags( 4 ) ) ;
2849+
2850+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . pubkey, non_announced_pubkey) ;
2851+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . short_channel_id, last_hops[ 0 ] . 0 [ 0 ] . short_channel_id) ;
2852+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . fee_msat, 0 ) ;
2853+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . cltv_expiry_delta, 129 ) ;
2854+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . node_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ; // We dont pass flags in from invoices yet
2855+ assert_eq ! ( route. paths[ 0 ] [ 2 ] . channel_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ; // We can't learn any flags from invoices, sadly
27902856
27912857 assert_eq ! ( route. paths[ 0 ] [ 3 ] . pubkey, nodes[ 6 ] ) ;
2792- assert_eq ! ( route. paths[ 0 ] [ 3 ] . short_channel_id, 8 ) ;
2858+ assert_eq ! ( route. paths[ 0 ] [ 3 ] . short_channel_id, last_hops [ 0 ] . 0 [ 1 ] . short_channel_id ) ;
27932859 assert_eq ! ( route. paths[ 0 ] [ 3 ] . fee_msat, 100 ) ;
27942860 assert_eq ! ( route. paths[ 0 ] [ 3 ] . cltv_expiry_delta, 42 ) ;
27952861 assert_eq ! ( route. paths[ 0 ] [ 3 ] . node_features. le_flags( ) , & Vec :: <u8 >:: new( ) ) ; // We dont pass flags in from invoices yet
0 commit comments