@@ -327,6 +327,8 @@ struct RouteGraphNode {
327
327
/// All penalties incurred from this hop on the way to the destination, as calculated using
328
328
/// channel scoring.
329
329
path_penalty_msat : u64 ,
330
+ /// The number of hops walked up to this node.
331
+ path_length_to_node : u8 ,
330
332
}
331
333
332
334
impl cmp:: Ord for RouteGraphNode {
@@ -796,11 +798,11 @@ where L::Target: Logger {
796
798
// The main heap containing all candidate next-hops sorted by their score (max(A* fee,
797
799
// htlc_minimum)). Ideally this would be a heap which allowed cheap score reduction instead of
798
800
// adding duplicate entries when we find a better path to a given node.
799
- let mut targets = BinaryHeap :: new ( ) ;
801
+ let mut targets: BinaryHeap < RouteGraphNode > = BinaryHeap :: new ( ) ;
800
802
801
803
// Map from node_id to information about the best current path to that node, including feerate
802
804
// information.
803
- let mut dist = HashMap :: with_capacity ( network_nodes. len ( ) ) ;
805
+ let mut dist: HashMap < NodeId , PathBuildingHop > = HashMap :: with_capacity ( network_nodes. len ( ) ) ;
804
806
805
807
// During routing, if we ignore a path due to an htlc_minimum_msat limit, we set this,
806
808
// indicating that we may wish to try again with a higher value, potentially paying to meet an
@@ -829,6 +831,20 @@ where L::Target: Logger {
829
831
// - when we want to stop looking for new paths.
830
832
let mut already_collected_value_msat = 0 ;
831
833
834
+ // We only consider paths shorter than our maximum length estimate.
835
+ // In the legacy onion format, the maximum number of hops used to be a fixed value of 20.
836
+ // However, in the TLV onion format, there is no fixed maximum length, but the `hop_payloads`
837
+ // field is always 1300 bytes. As the `tlv_payload` for each hop may vary in length, we have to
838
+ // estimate how many hops the route may have so that it actually fits the `hop_payloads` field.
839
+ //
840
+ // We estimate 3+32 (payload length and HMAC) + 2+8 (amt_to_forward) + 2+4 (outgoing_cltv_value) +
841
+ // 2+8 (short_channel_id) = 61 bytes for each intermediate hop and 3+32
842
+ // (payload length and HMAC) + 2+8 (amt_to_forward) + 2+4 (outgoing_cltv_value) + 2+32+8
843
+ // (payment_secret and total_msat) = 93 bytes for the final hop.
844
+ // Since the length of the potentially included `payment_metadata` is unkown to us, we round
845
+ // from (1300-93) / 61 = 19.78... just to arrive again at a conservative estimate of 20.
846
+ const MAX_PATH_LENGTH_ESTIMATE : u8 = 20 ;
847
+
832
848
for ( _, channels) in first_hop_targets. iter_mut ( ) {
833
849
// Sort the first_hops channels to the same node(s) in priority order of which channel we'd
834
850
// most like to use.
@@ -860,8 +876,8 @@ where L::Target: Logger {
860
876
// since that value has to be transferred over this channel.
861
877
// Returns whether this channel caused an update to `targets`.
862
878
( $candidate: expr, $src_node_id: expr, $dest_node_id: expr, $next_hops_fee_msat: expr,
863
- $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr,
864
- $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr ) => { {
879
+ $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr,
880
+ $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr , $next_hops_path_length : expr ) => { {
865
881
// We "return" whether we updated the path at the end, via this:
866
882
let mut did_add_update_path_to_src_node = false ;
867
883
// Channels to self should not be used. This is more of belt-and-suspenders, because in
@@ -905,6 +921,9 @@ where L::Target: Logger {
905
921
} ;
906
922
// Verify the liquidity offered by this channel complies to the minimal contribution.
907
923
let contributes_sufficient_value = available_value_contribution_msat >= minimal_value_contribution_msat;
924
+ // Do not consider candidate hops that would exceed the maximum path length.
925
+ let path_length_to_node = $next_hops_path_length + 1 ;
926
+ let doesnt_exceed_max_path_length = path_length_to_node <= MAX_PATH_LENGTH_ESTIMATE ;
908
927
909
928
// Do not consider candidates that exceed the maximum total cltv expiry limit.
910
929
// In order to already account for some of the privacy enhancing random CLTV
@@ -939,9 +958,11 @@ where L::Target: Logger {
939
958
// bother considering this channel. If retrying with recommended_value_msat may
940
959
// allow us to hit the HTLC minimum limit, set htlc_minimum_limit so that we go
941
960
// around again with a higher amount.
942
- if contributes_sufficient_value && doesnt_exceed_cltv_delta_limit && may_overpay_to_meet_path_minimum_msat {
961
+ if contributes_sufficient_value && doesnt_exceed_max_path_length &&
962
+ doesnt_exceed_cltv_delta_limit && may_overpay_to_meet_path_minimum_msat {
943
963
hit_minimum_limit = true ;
944
- } else if contributes_sufficient_value && doesnt_exceed_cltv_delta_limit && over_path_minimum_msat {
964
+ } else if contributes_sufficient_value && doesnt_exceed_max_path_length &&
965
+ doesnt_exceed_cltv_delta_limit && over_path_minimum_msat {
945
966
// Note that low contribution here (limited by available_liquidity_msat)
946
967
// might violate htlc_minimum_msat on the hops which are next along the
947
968
// payment path (upstream to the payee). To avoid that, we recompute
@@ -1038,6 +1059,7 @@ where L::Target: Logger {
1038
1059
value_contribution_msat: value_contribution_msat,
1039
1060
path_htlc_minimum_msat,
1040
1061
path_penalty_msat,
1062
+ path_length_to_node,
1041
1063
} ;
1042
1064
1043
1065
// Update the way of reaching $src_node_id with the given short_channel_id (from $dest_node_id),
@@ -1121,7 +1143,9 @@ where L::Target: Logger {
1121
1143
// meaning how much will be paid in fees after this node (to the best of our knowledge).
1122
1144
// This data can later be helpful to optimize routing (pay lower fees).
1123
1145
macro_rules! add_entries_to_cheapest_to_target_node {
1124
- ( $node: expr, $node_id: expr, $fee_to_target_msat: expr, $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr, $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr ) => {
1146
+ ( $node: expr, $node_id: expr, $fee_to_target_msat: expr, $next_hops_value_contribution: expr,
1147
+ $next_hops_path_htlc_minimum_msat: expr, $next_hops_path_penalty_msat: expr,
1148
+ $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => {
1125
1149
let skip_node = if let Some ( elem) = dist. get_mut( & $node_id) {
1126
1150
let was_processed = elem. was_processed;
1127
1151
elem. was_processed = true ;
@@ -1138,7 +1162,10 @@ where L::Target: Logger {
1138
1162
if let Some ( first_channels) = first_hop_targets. get( & $node_id) {
1139
1163
for details in first_channels {
1140
1164
let candidate = CandidateRouteHop :: FirstHop { details } ;
1141
- add_entry!( candidate, our_node_id, $node_id, $fee_to_target_msat, $next_hops_value_contribution, $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat, $next_hops_cltv_delta) ;
1165
+ add_entry!( candidate, our_node_id, $node_id, $fee_to_target_msat,
1166
+ $next_hops_value_contribution,
1167
+ $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat,
1168
+ $next_hops_cltv_delta, $next_hops_path_length) ;
1142
1169
}
1143
1170
}
1144
1171
@@ -1161,7 +1188,12 @@ where L::Target: Logger {
1161
1188
info: directed_channel. with_update( ) . unwrap( ) ,
1162
1189
short_channel_id: * chan_id,
1163
1190
} ;
1164
- add_entry!( candidate, * source, $node_id, $fee_to_target_msat, $next_hops_value_contribution, $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat, $next_hops_cltv_delta) ;
1191
+ add_entry!( candidate, * source, $node_id,
1192
+ $fee_to_target_msat,
1193
+ $next_hops_value_contribution,
1194
+ $next_hops_path_htlc_minimum_msat,
1195
+ $next_hops_path_penalty_msat,
1196
+ $next_hops_cltv_delta, $next_hops_path_length) ;
1165
1197
}
1166
1198
}
1167
1199
}
@@ -1188,8 +1220,10 @@ where L::Target: Logger {
1188
1220
if let Some ( first_channels) = first_hop_targets. get ( & payee_node_id) {
1189
1221
for details in first_channels {
1190
1222
let candidate = CandidateRouteHop :: FirstHop { details } ;
1191
- let added = add_entry ! ( candidate, our_node_id, payee_node_id, 0 , path_value_msat, 0 , 0u64 , 0 ) ;
1192
- log_trace ! ( logger, "{} direct route to payee via SCID {}" , if added { "Added" } else { "Skipped" } , candidate. short_channel_id( ) ) ;
1223
+ let added = add_entry ! ( candidate, our_node_id, payee_node_id, 0 , path_value_msat,
1224
+ 0 , 0u64 , 0 , 0 ) ;
1225
+ log_trace ! ( logger, "{} direct route to payee via SCID {}" ,
1226
+ if added { "Added" } else { "Skipped" } , candidate. short_channel_id( ) ) ;
1193
1227
}
1194
1228
}
1195
1229
@@ -1202,7 +1236,7 @@ where L::Target: Logger {
1202
1236
// If not, targets.pop() will not even let us enter the loop in step 2.
1203
1237
None => { } ,
1204
1238
Some ( node) => {
1205
- add_entries_to_cheapest_to_target_node ! ( node, payee_node_id, 0 , path_value_msat, 0 , 0u64 , 0 ) ;
1239
+ add_entries_to_cheapest_to_target_node ! ( node, payee_node_id, 0 , path_value_msat, 0 , 0u64 , 0 , 0 ) ;
1206
1240
} ,
1207
1241
}
1208
1242
@@ -1229,6 +1263,7 @@ where L::Target: Logger {
1229
1263
let mut aggregate_next_hops_path_htlc_minimum_msat: u64 = 0 ;
1230
1264
let mut aggregate_next_hops_path_penalty_msat: u64 = 0 ;
1231
1265
let mut aggregate_next_hops_cltv_delta: u32 = 0 ;
1266
+ let mut aggregate_next_hops_path_length: u8 = 0 ;
1232
1267
1233
1268
for ( idx, ( hop, prev_hop_id) ) in hop_iter. zip ( prev_hop_iter) . enumerate ( ) {
1234
1269
let source = NodeId :: from_pubkey ( & hop. src_node_id ) ;
@@ -1244,23 +1279,34 @@ where L::Target: Logger {
1244
1279
. unwrap_or_else ( || CandidateRouteHop :: PrivateHop { hint : hop } ) ;
1245
1280
let capacity_msat = candidate. effective_capacity ( ) . as_msat ( ) ;
1246
1281
aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat
1247
- . saturating_add ( scorer. channel_penalty_msat ( hop. short_channel_id , final_value_msat, capacity_msat, & source, & target) ) ;
1282
+ . saturating_add ( scorer. channel_penalty_msat ( hop. short_channel_id ,
1283
+ final_value_msat, capacity_msat, & source, & target) ) ;
1248
1284
1249
1285
aggregate_next_hops_cltv_delta = aggregate_next_hops_cltv_delta
1250
1286
. saturating_add ( hop. cltv_expiry_delta as u32 ) ;
1251
1287
1252
- if !add_entry ! ( candidate, source, target, aggregate_next_hops_fee_msat, path_value_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta) {
1253
- // If this hop was not used then there is no use checking the preceding hops
1254
- // in the RouteHint. We can break by just searching for a direct channel between
1255
- // last checked hop and first_hop_targets
1288
+ aggregate_next_hops_path_length = aggregate_next_hops_path_length
1289
+ . saturating_add ( 1 ) ;
1290
+
1291
+ if !add_entry ! ( candidate, source, target, aggregate_next_hops_fee_msat,
1292
+ path_value_msat, aggregate_next_hops_path_htlc_minimum_msat,
1293
+ aggregate_next_hops_path_penalty_msat,
1294
+ aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length) {
1295
+ // If this hop was not used then there is no use checking the preceding
1296
+ // hops in the RouteHint. We can break by just searching for a direct
1297
+ // channel between last checked hop and first_hop_targets.
1256
1298
hop_used = false ;
1257
1299
}
1258
1300
1259
1301
// Searching for a direct channel between last checked hop and first_hop_targets
1260
1302
if let Some ( first_channels) = first_hop_targets. get ( & NodeId :: from_pubkey ( & prev_hop_id) ) {
1261
1303
for details in first_channels {
1262
1304
let candidate = CandidateRouteHop :: FirstHop { details } ;
1263
- add_entry ! ( candidate, our_node_id, NodeId :: from_pubkey( & prev_hop_id) , aggregate_next_hops_fee_msat, path_value_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta) ;
1305
+ add_entry ! ( candidate, our_node_id, NodeId :: from_pubkey( & prev_hop_id) ,
1306
+ aggregate_next_hops_fee_msat, path_value_msat,
1307
+ aggregate_next_hops_path_htlc_minimum_msat,
1308
+ aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta,
1309
+ aggregate_next_hops_path_length) ;
1264
1310
}
1265
1311
}
1266
1312
@@ -1296,7 +1342,13 @@ where L::Target: Logger {
1296
1342
if let Some ( first_channels) = first_hop_targets. get ( & NodeId :: from_pubkey ( & hop. src_node_id ) ) {
1297
1343
for details in first_channels {
1298
1344
let candidate = CandidateRouteHop :: FirstHop { details } ;
1299
- add_entry ! ( candidate, our_node_id, NodeId :: from_pubkey( & hop. src_node_id) , aggregate_next_hops_fee_msat, path_value_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta) ;
1345
+ add_entry ! ( candidate, our_node_id,
1346
+ NodeId :: from_pubkey( & hop. src_node_id) ,
1347
+ aggregate_next_hops_fee_msat, path_value_msat,
1348
+ aggregate_next_hops_path_htlc_minimum_msat,
1349
+ aggregate_next_hops_path_penalty_msat,
1350
+ aggregate_next_hops_cltv_delta,
1351
+ aggregate_next_hops_path_length) ;
1300
1352
}
1301
1353
}
1302
1354
}
@@ -1319,13 +1371,13 @@ where L::Target: Logger {
1319
1371
// Both these cases (and other cases except reaching recommended_value_msat) mean that
1320
1372
// paths_collection will be stopped because found_new_path==false.
1321
1373
// This is not necessarily a routing failure.
1322
- ' path_construction: while let Some ( RouteGraphNode { node_id, lowest_fee_to_node, total_cltv_delta, value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat, .. } ) = targets. pop ( ) {
1374
+ ' path_construction: while let Some ( RouteGraphNode { node_id, lowest_fee_to_node, total_cltv_delta, value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat, path_length_to_node , .. } ) = targets. pop ( ) {
1323
1375
1324
1376
// Since we're going payee-to-payer, hitting our node as a target means we should stop
1325
1377
// traversing the graph and arrange the path out of what we found.
1326
1378
if node_id == our_node_id {
1327
1379
let mut new_entry = dist. remove ( & our_node_id) . unwrap ( ) ;
1328
- let mut ordered_hops = vec ! ( ( new_entry. clone( ) , default_node_features. clone( ) ) ) ;
1380
+ let mut ordered_hops: Vec < ( PathBuildingHop , NodeFeatures ) > = vec ! ( ( new_entry. clone( ) , default_node_features. clone( ) ) ) ;
1329
1381
1330
1382
' path_walk: loop {
1331
1383
let mut features_set = false ;
@@ -1441,7 +1493,9 @@ where L::Target: Logger {
1441
1493
match network_nodes. get ( & node_id) {
1442
1494
None => { } ,
1443
1495
Some ( node) => {
1444
- add_entries_to_cheapest_to_target_node ! ( node, node_id, lowest_fee_to_node, value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat, total_cltv_delta) ;
1496
+ add_entries_to_cheapest_to_target_node ! ( node, node_id, lowest_fee_to_node,
1497
+ value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat,
1498
+ total_cltv_delta, path_length_to_node) ;
1445
1499
} ,
1446
1500
}
1447
1501
}
@@ -1703,7 +1757,7 @@ mod tests {
1703
1757
use chain:: keysinterface:: KeysInterface ;
1704
1758
use ln:: features:: { ChannelFeatures , InitFeatures , InvoiceFeatures , NodeFeatures } ;
1705
1759
use ln:: msgs:: { ErrorAction , LightningError , OptionalField , UnsignedChannelAnnouncement , ChannelAnnouncement , RoutingMessageHandler ,
1706
- NodeAnnouncement , UnsignedNodeAnnouncement , ChannelUpdate , UnsignedChannelUpdate } ;
1760
+ NodeAnnouncement , UnsignedNodeAnnouncement , ChannelUpdate , UnsignedChannelUpdate } ;
1707
1761
use ln:: channelmanager;
1708
1762
use util:: test_utils;
1709
1763
use util:: chacha20:: ChaCha20 ;
@@ -1836,7 +1890,7 @@ mod tests {
1836
1890
}
1837
1891
1838
1892
fn get_nodes ( secp_ctx : & Secp256k1 < All > ) -> ( SecretKey , PublicKey , Vec < SecretKey > , Vec < PublicKey > ) {
1839
- let privkeys: Vec < SecretKey > = ( 2 ..10 ) . map ( |i| {
1893
+ let privkeys: Vec < SecretKey > = ( 2 ..23 ) . map ( |i| {
1840
1894
SecretKey :: from_slice ( & hex:: decode ( format ! ( "{:02x}" , i) . repeat ( 32 ) ) . unwrap ( ) [ ..] ) . unwrap ( )
1841
1895
} ) . collect ( ) ;
1842
1896
@@ -1863,6 +1917,57 @@ mod tests {
1863
1917
}
1864
1918
}
1865
1919
1920
+ fn build_line_graph ( ) -> (
1921
+ Secp256k1 < All > , sync:: Arc < NetworkGraph > , NetGraphMsgHandler < sync:: Arc < NetworkGraph > ,
1922
+ sync:: Arc < test_utils:: TestChainSource > , sync:: Arc < crate :: util:: test_utils:: TestLogger > > ,
1923
+ sync:: Arc < test_utils:: TestChainSource > , sync:: Arc < test_utils:: TestLogger > ,
1924
+ ) {
1925
+ let secp_ctx = Secp256k1 :: new ( ) ;
1926
+ let logger = Arc :: new ( test_utils:: TestLogger :: new ( ) ) ;
1927
+ let chain_monitor = Arc :: new ( test_utils:: TestChainSource :: new ( Network :: Testnet ) ) ;
1928
+ let network_graph = Arc :: new ( NetworkGraph :: new ( genesis_block ( Network :: Testnet ) . header . block_hash ( ) ) ) ;
1929
+ let net_graph_msg_handler = NetGraphMsgHandler :: new ( Arc :: clone ( & network_graph) , None , Arc :: clone ( & logger) ) ;
1930
+
1931
+ // Build network from our_id to node 20:
1932
+ // our_id -1(1)2- node0 -1(2)2- node1 - ... - node20
1933
+ let ( our_privkey, _, privkeys, _) = get_nodes ( & secp_ctx) ;
1934
+
1935
+ for ( idx, ( cur_privkey, next_privkey) ) in core:: iter:: once ( & our_privkey)
1936
+ . chain ( privkeys. iter ( ) ) . zip ( privkeys. iter ( ) ) . enumerate ( ) {
1937
+ let cur_short_channel_id = ( idx as u64 ) + 1 ;
1938
+ add_channel ( & net_graph_msg_handler, & secp_ctx, & cur_privkey, & next_privkey,
1939
+ ChannelFeatures :: from_le_bytes ( id_to_feature_flags ( 1 ) ) , cur_short_channel_id) ;
1940
+ update_channel ( & net_graph_msg_handler, & secp_ctx, & cur_privkey, UnsignedChannelUpdate {
1941
+ chain_hash : genesis_block ( Network :: Testnet ) . header . block_hash ( ) ,
1942
+ short_channel_id : cur_short_channel_id,
1943
+ timestamp : idx as u32 ,
1944
+ flags : 0 ,
1945
+ cltv_expiry_delta : 0 ,
1946
+ htlc_minimum_msat : 0 ,
1947
+ htlc_maximum_msat : OptionalField :: Absent ,
1948
+ fee_base_msat : 0 ,
1949
+ fee_proportional_millionths : 0 ,
1950
+ excess_data : Vec :: new ( )
1951
+ } ) ;
1952
+ update_channel ( & net_graph_msg_handler, & secp_ctx, & next_privkey, UnsignedChannelUpdate {
1953
+ chain_hash : genesis_block ( Network :: Testnet ) . header . block_hash ( ) ,
1954
+ short_channel_id : cur_short_channel_id,
1955
+ timestamp : ( idx as u32 ) +1 ,
1956
+ flags : 1 ,
1957
+ cltv_expiry_delta : 0 ,
1958
+ htlc_minimum_msat : 0 ,
1959
+ htlc_maximum_msat : OptionalField :: Absent ,
1960
+ fee_base_msat : 0 ,
1961
+ fee_proportional_millionths : 0 ,
1962
+ excess_data : Vec :: new ( )
1963
+ } ) ;
1964
+ add_or_update_node ( & net_graph_msg_handler, & secp_ctx, next_privkey,
1965
+ NodeFeatures :: from_le_bytes ( id_to_feature_flags ( 1 ) ) , 0 ) ;
1966
+ }
1967
+
1968
+ ( secp_ctx, network_graph, net_graph_msg_handler, chain_monitor, logger)
1969
+ }
1970
+
1866
1971
fn build_graph ( ) -> (
1867
1972
Secp256k1 < All > ,
1868
1973
sync:: Arc < NetworkGraph > ,
@@ -5213,6 +5318,35 @@ mod tests {
5213
5318
}
5214
5319
}
5215
5320
5321
+ #[ test]
5322
+ fn limits_path_length ( ) {
5323
+ let ( secp_ctx, network, _, _, logger) = build_line_graph ( ) ;
5324
+ let ( _, our_id, _, nodes) = get_nodes ( & secp_ctx) ;
5325
+ let network_graph = network. read_only ( ) ;
5326
+
5327
+ let scorer = test_utils:: TestScorer :: with_penalty ( 0 ) ;
5328
+ let keys_manager = test_utils:: TestKeysInterface :: new ( & [ 0u8 ; 32 ] , Network :: Testnet ) ;
5329
+ let random_seed_bytes = keys_manager. get_secure_random_bytes ( ) ;
5330
+
5331
+ // First check we can actually create a long route on this graph.
5332
+ let feasible_payment_params = PaymentParameters :: from_node_id ( nodes[ 19 ] ) ;
5333
+ let route = get_route ( & our_id, & feasible_payment_params, & network_graph, None , 100 , 0 ,
5334
+ Arc :: clone ( & logger) , & scorer, & random_seed_bytes) . unwrap ( ) ;
5335
+ let path = route. paths [ 0 ] . iter ( ) . map ( |hop| hop. short_channel_id ) . collect :: < Vec < _ > > ( ) ;
5336
+ assert ! ( path. len( ) == 20 ) ;
5337
+
5338
+ // But we can't create a path surpassing the 20-hop MAX_PATH_LENGTH_ESTIMATE limit.
5339
+ let fail_payment_params = PaymentParameters :: from_node_id ( nodes[ 20 ] ) ;
5340
+ match get_route ( & our_id, & fail_payment_params, & network_graph, None , 100 , 0 ,
5341
+ Arc :: clone ( & logger) , & scorer, & random_seed_bytes)
5342
+ {
5343
+ Err ( LightningError { err, .. } ) => {
5344
+ assert_eq ! ( err, "Failed to find a path to the given destination" ) ;
5345
+ } ,
5346
+ Ok ( _) => panic ! ( "Expected error" ) ,
5347
+ }
5348
+ }
5349
+
5216
5350
#[ test]
5217
5351
fn adds_and_limits_cltv_offset ( ) {
5218
5352
let ( secp_ctx, network_graph, _, _, logger) = build_graph ( ) ;
0 commit comments