Skip to content

Commit 090068f

Browse files
Correctly fail back phantom node payments that don't match inbound payment data
Previously, we failed back these payments without encrypting with the second-to-last-hop's failure onion layer.
1 parent edba328 commit 090068f

File tree

2 files changed

+67
-9
lines changed

2 files changed

+67
-9
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ pub(super) enum PendingHTLCRouting {
366366
Receive {
367367
payment_data: msgs::FinalOnionHopData,
368368
incoming_cltv_expiry: u32, // Used to track when we should expire pending HTLCs that go unclaimed
369+
phantom_shared_secret: Option<[u8; 32]>,
369370
},
370371
ReceiveKeysend {
371372
payment_preimage: PaymentPreimage,
@@ -2072,7 +2073,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
20722073
}
20732074

20742075
fn construct_recv_pending_htlc_info(&self, hop_data: msgs::OnionHopData, shared_secret: [u8; 32],
2075-
payment_hash: PaymentHash, amt_msat: u64, cltv_expiry: u32) -> Result<PendingHTLCInfo, ReceiveError>
2076+
payment_hash: PaymentHash, amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>) -> Result<PendingHTLCInfo, ReceiveError>
20762077
{
20772078
// final_incorrect_cltv_expiry
20782079
if hop_data.outgoing_cltv_value != cltv_expiry {
@@ -2129,6 +2130,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
21292130
PendingHTLCRouting::Receive {
21302131
payment_data: data,
21312132
incoming_cltv_expiry: hop_data.outgoing_cltv_value,
2133+
phantom_shared_secret,
21322134
}
21332135
} else if let Some(payment_preimage) = keysend_preimage {
21342136
// We need to check that the sender knows the keysend preimage before processing this
@@ -2232,7 +2234,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
22322234
let pending_forward_info = match next_hop {
22332235
onion_utils::Hop::Receive(next_hop_data) => {
22342236
// OUR PAYMENT!
2235-
match self.construct_recv_pending_htlc_info(next_hop_data, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry) {
2237+
match self.construct_recv_pending_htlc_info(next_hop_data, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry, None) {
22362238
Ok(info) => {
22372239
// Note that we could obviously respond immediately with an update_fulfill_htlc
22382240
// message, however that would leak that we are the recipient of this payment, so
@@ -3061,7 +3063,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30613063
};
30623064
match next_hop {
30633065
onion_utils::Hop::Receive(hop_data) => {
3064-
match self.construct_recv_pending_htlc_info(hop_data, phantom_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value) {
3066+
match self.construct_recv_pending_htlc_info(hop_data, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value, Some(phantom_shared_secret)) {
30653067
Ok(info) => phantom_receives.push((prev_short_channel_id, prev_funding_outpoint, vec![(info, prev_htlc_id)])),
30663068
Err(ReceiveError { err_code, err_data, msg }) => fail_phantom_forward!(msg, err_code, err_data, phantom_shared_secret)
30673069
}
@@ -3221,11 +3223,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32213223
HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info: PendingHTLCInfo {
32223224
routing, incoming_shared_secret, payment_hash, amt_to_forward, .. },
32233225
prev_funding_outpoint } => {
3224-
let (cltv_expiry, onion_payload) = match routing {
3225-
PendingHTLCRouting::Receive { payment_data, incoming_cltv_expiry } =>
3226-
(incoming_cltv_expiry, OnionPayload::Invoice(payment_data)),
3226+
let (cltv_expiry, onion_payload, phantom_shared_secret) = match routing {
3227+
PendingHTLCRouting::Receive { payment_data, incoming_cltv_expiry, phantom_shared_secret } =>
3228+
(incoming_cltv_expiry, OnionPayload::Invoice(payment_data), phantom_shared_secret),
32273229
PendingHTLCRouting::ReceiveKeysend { payment_preimage, incoming_cltv_expiry } =>
3228-
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage)),
3230+
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage), None),
32293231
_ => {
32303232
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
32313233
}
@@ -3248,13 +3250,20 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32483250
htlc_msat_height_data.extend_from_slice(
32493251
&byte_utils::be32_to_array(self.best_block.read().unwrap().height()),
32503252
);
3253+
let failure_code = 0x4000 | 15;
3254+
let failure_reason = if let Some(phantom_ss) = phantom_shared_secret {
3255+
let packet = onion_utils::build_failure_packet(&phantom_ss, failure_code, &htlc_msat_height_data[..]).encode();
3256+
let error_data = onion_utils::encrypt_failure_packet(&phantom_ss, &packet);
3257+
HTLCFailReason::LightningError { err: error_data }
3258+
} else {
3259+
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: htlc_msat_height_data }
3260+
};
32513261
failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData {
32523262
short_channel_id: $htlc.prev_hop.short_channel_id,
32533263
outpoint: prev_funding_outpoint,
32543264
htlc_id: $htlc.prev_hop.htlc_id,
32553265
incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
3256-
}), payment_hash,
3257-
HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: htlc_msat_height_data }
3266+
}), payment_hash, failure_reason
32583267
));
32593268
}
32603269
}
@@ -5993,6 +6002,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
59936002
},
59946003
(1, Receive) => {
59956004
(0, payment_data, required),
6005+
(1, phantom_shared_secret, option),
59966006
(2, incoming_cltv_expiry, required),
59976007
},
59986008
(2, ReceiveKeysend) => {

lightning/src/ln/onion_route_tests.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,3 +850,51 @@ fn test_phantom_failure_too_low_cltv() {
850850
.expected_htlc_error_data(17, &error_data);
851851
expect_payment_failed_conditions!(nodes[0], payment_hash, false, fail_conditions);
852852
}
853+
854+
#[test]
855+
fn test_phantom_failure_too_low_recv_amt() {
856+
let chanmon_cfgs = create_chanmon_cfgs(2);
857+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
858+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
859+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
860+
861+
let channel = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
862+
863+
// Get the route with a too-low amount.
864+
let recv_amt_msat = 10_000;
865+
let bad_recv_amt_msat = recv_amt_msat - 10;
866+
let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_amt_msat));
867+
let (mut route, phantom_scid) = get_phantom_route!(nodes, bad_recv_amt_msat, channel);
868+
869+
// Route the HTLC through to the destination.
870+
nodes[0].node.send_payment(&route, payment_hash.clone(), &Some(payment_secret)).unwrap();
871+
check_added_monitors!(nodes[0], 1);
872+
let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
873+
let mut update_add = update_0.update_add_htlcs[0].clone();
874+
875+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add);
876+
commitment_signed_dance!(nodes[1], nodes[0], &update_0.commitment_signed, false, true);
877+
878+
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
879+
nodes[1].node.process_pending_htlc_forwards();
880+
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
881+
nodes[1].node.process_pending_htlc_forwards();
882+
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
883+
nodes[1].node.process_pending_htlc_forwards();
884+
let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
885+
check_added_monitors!(&nodes[1], 1);
886+
assert!(update_1.update_fail_htlcs.len() == 1);
887+
let fail_msg = update_1.update_fail_htlcs[0].clone();
888+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &fail_msg);
889+
commitment_signed_dance!(nodes[0], nodes[1], update_1.commitment_signed, false);
890+
891+
// Ensure the payment fails with the expected error.
892+
let mut error_data = byte_utils::be64_to_array(bad_recv_amt_msat).to_vec();
893+
error_data.extend_from_slice(
894+
&byte_utils::be32_to_array(nodes[1].node.best_block.read().unwrap().height()),
895+
);
896+
let mut fail_conditions = PaymentFailedConditions::new()
897+
.blamed_scid(phantom_scid)
898+
.expected_htlc_error_data(0x4000 | 15, &error_data);
899+
expect_payment_failed_conditions!(nodes[0], payment_hash, true, fail_conditions);
900+
}

0 commit comments

Comments
 (0)