Skip to content

Commit c45669a

Browse files
committed
Use temporary_node_failure for a phantom HTLC with bogus CLTV
When we receive a phantom HTLC with a bogus/modified CLTV, we should fail back with `incorrect_cltv_expiry`, but that requires a `channel_update`, which we cannot generate for a phantom HTLC which has no corresponding channel. Thus, instead, we have to fall back to `incorrect_cltv_expiry`. Fixes #1879
1 parent 33919ee commit c45669a

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2278,10 +2278,13 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
22782278
}
22792279
chan_update_opt
22802280
} else {
2281-
if (msg.cltv_expiry as u64) < (*outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 { // incorrect_cltv_expiry
2281+
if (msg.cltv_expiry as u64) < (*outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 {
2282+
// We really should set `incorrect_cltv_expiry` here but as we're not
2283+
// forwarding over a real channel we can't generate a channel_update
2284+
// for it. Instead we just return a generic temporary_node_failure.
22822285
break Some((
22832286
"Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
2284-
0x1000 | 13, None,
2287+
0x2000 | 2, None,
22852288
));
22862289
}
22872290
None

lightning/src/ln/onion_route_tests.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,47 @@ fn test_phantom_failure_too_low_cltv() {
11091109
expect_payment_failed_conditions(&nodes[0], payment_hash, true, fail_conditions);
11101110
}
11111111

1112+
#[test]
1113+
fn test_phantom_failure_modified_cltv() {
1114+
// Test that we fail back phantoms if the upstream node fiddled with the CLTV too much with the
1115+
// correct error code.
1116+
let chanmon_cfgs = create_chanmon_cfgs(2);
1117+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1118+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
1119+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1120+
1121+
let channel = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features());
1122+
1123+
// Get the route.
1124+
let recv_value_msat = 10_000;
1125+
let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_value_msat));
1126+
let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel);
1127+
1128+
// Route the HTLC through to the destination.
1129+
nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap();
1130+
check_added_monitors!(nodes[0], 1);
1131+
let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
1132+
let mut update_add = update_0.update_add_htlcs[0].clone();
1133+
1134+
// Modify the route to have a too-low cltv.
1135+
update_add.cltv_expiry -= 10;
1136+
1137+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add);
1138+
commitment_signed_dance!(nodes[1], nodes[0], &update_0.commitment_signed, false, true);
1139+
1140+
let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1141+
assert!(update_1.update_fail_htlcs.len() == 1);
1142+
let fail_msg = update_1.update_fail_htlcs[0].clone();
1143+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_msg);
1144+
commitment_signed_dance!(nodes[0], nodes[1], update_1.commitment_signed, false);
1145+
1146+
// Ensure the payment fails with the expected error.
1147+
let mut fail_conditions = PaymentFailedConditions::new()
1148+
.blamed_scid(phantom_scid)
1149+
.expected_htlc_error_data(0x2000 | 2, &[]);
1150+
expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions);
1151+
}
1152+
11121153
#[test]
11131154
fn test_phantom_failure_too_low_recv_amt() {
11141155
let chanmon_cfgs = create_chanmon_cfgs(2);

0 commit comments

Comments
 (0)