Skip to content

Commit a0183d7

Browse files
authored
Merge pull request #2741 from shaavan/issue-2215
Explicitly reject routes that double-back
2 parents 8bd4a8f + a06d158 commit a0183d7

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

lightning/src/ln/functional_test_utils.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,14 @@ macro_rules! unwrap_send_err {
956956
_ => panic!(),
957957
}
958958
},
959-
_ => panic!(),
959+
&Err(PaymentSendFailure::PathParameterError(ref result)) if !$all_failed => {
960+
assert_eq!(result.len(), 1);
961+
match result[0] {
962+
Err($type) => { $check },
963+
_ => panic!(),
964+
}
965+
},
966+
_ => {panic!()},
960967
}
961968
}
962969
}

lightning/src/ln/functional_tests.rs

+24
Original file line numberDiff line numberDiff line change
@@ -6205,6 +6205,30 @@ fn test_fail_holding_cell_htlc_upon_free_multihop() {
62056205
check_added_monitors!(nodes[0], 1);
62066206
}
62076207

6208+
#[test]
6209+
fn test_payment_route_reaching_same_channel_twice() {
6210+
//A route should not go through the same channel twice
6211+
//It is enforced when constructing a route.
6212+
let chanmon_cfgs = create_chanmon_cfgs(2);
6213+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
6214+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
6215+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
6216+
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0);
6217+
6218+
let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 0)
6219+
.with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap();
6220+
let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000);
6221+
6222+
// Extend the path by itself, essentially simulating route going through same channel twice
6223+
let cloned_hops = route.paths[0].hops.clone();
6224+
route.paths[0].hops.extend_from_slice(&cloned_hops);
6225+
6226+
unwrap_send_err!(nodes[0].node.send_payment_with_route(&route, our_payment_hash,
6227+
RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)
6228+
), false, APIError::InvalidRoute { ref err },
6229+
assert_eq!(err, &"Path went through the same channel twice"));
6230+
}
6231+
62086232
// BOLT 2 Requirements for the Sender when constructing and sending an update_add_htlc message.
62096233
// BOLT 2 Requirement: MUST NOT offer amount_msat it cannot pay for in the remote commitment transaction at the current feerate_per_kw (see "Updating Fees") while maintaining its channel reserve.
62106234
//TODO: I don't believe this is explicitly enforced when sending an HTLC but as the Fee aspect of the BOLT specs is in flux leaving this as a TODO.

lightning/src/ln/outbound_payment.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,13 @@ impl OutboundPayments {
13371337
continue 'path_check;
13381338
}
13391339
}
1340+
for (i, hop) in path.hops.iter().enumerate() {
1341+
// Check for duplicate channel_id in the remaining hops of the path
1342+
if path.hops.iter().skip(i + 1).any(|other_hop| other_hop.short_channel_id == hop.short_channel_id) {
1343+
path_errs.push(Err(APIError::InvalidRoute{err: "Path went through the same channel twice".to_owned()}));
1344+
continue 'path_check;
1345+
}
1346+
}
13401347
total_value += path.final_value_msat();
13411348
path_errs.push(Ok(()));
13421349
}

0 commit comments

Comments
 (0)