Skip to content

Commit 1c96c22

Browse files
Verify blinded keysend payment secrets
If we're receiving a keysend to a blinded path, then we created the payment secret within. Using our inbound_payment_key, we can decrypt the payment secret bytes to get the payment's min_cltv_expiry_delta and min amount, to verify the payment is valid. However, if we're receiving an MPP keysend *not* to a blinded path, then we did not create the payment secret and shouldn't verify it since it's only used to correlate MPP parts. Therefore, store whether the payment secret is recipient-generated in our pending inbound payment data so we know whether to verify it or not.
1 parent cf8d07c commit 1c96c22

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ pub enum PendingHTLCRouting {
220220
custom_tlvs: Vec<(u64, Vec<u8>)>,
221221
/// Set if this HTLC is the final hop in a multi-hop blinded path.
222222
requires_blinded_error: bool,
223+
/// Set if we are receiving a keysend to a blinded path, meaning we created the
224+
/// [`PaymentSecret`] and should verify it using our
225+
/// [`NodeSigner::get_inbound_payment_key_material`].
226+
has_recipient_created_payment_secret: bool,
223227
},
224228
}
225229

@@ -5699,7 +5703,10 @@ where
56995703
}
57005704
}) => {
57015705
let blinded_failure = routing.blinded_failure();
5702-
let (cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret, mut onion_fields) = match routing {
5706+
let (
5707+
cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret,
5708+
mut onion_fields, has_recipient_created_payment_secret
5709+
) = match routing {
57035710
PendingHTLCRouting::Receive {
57045711
payment_data, payment_metadata, payment_context,
57055712
incoming_cltv_expiry, phantom_shared_secret, custom_tlvs,
@@ -5709,19 +5716,21 @@ where
57095716
let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
57105717
payment_metadata, custom_tlvs };
57115718
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
5712-
Some(payment_data), payment_context, phantom_shared_secret, onion_fields)
5719+
Some(payment_data), payment_context, phantom_shared_secret, onion_fields,
5720+
true)
57135721
},
57145722
PendingHTLCRouting::ReceiveKeysend {
57155723
payment_data, payment_preimage, payment_metadata,
5716-
incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _
5724+
incoming_cltv_expiry, custom_tlvs, has_recipient_created_payment_secret,
5725+
requires_blinded_error: _,
57175726
} => {
57185727
let onion_fields = RecipientOnionFields {
57195728
payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
57205729
payment_metadata,
57215730
custom_tlvs,
57225731
};
57235732
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
5724-
payment_data, None, None, onion_fields)
5733+
payment_data, None, None, onion_fields, has_recipient_created_payment_secret)
57255734
},
57265735
_ => {
57275736
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -5886,9 +5895,8 @@ where
58865895
// that we are the ultimate recipient of the given payment hash.
58875896
// Further, we must not expose whether we have any other HTLCs
58885897
// associated with the same payment_hash pending or not.
5889-
match claimable_htlc.onion_payload {
5890-
OnionPayload::Invoice { .. } => {
5891-
let payment_data = payment_data.unwrap();
5898+
let payment_preimage = if has_recipient_created_payment_secret {
5899+
if let Some(ref payment_data) = payment_data {
58925900
let (payment_preimage, min_final_cltv_expiry_delta) = match inbound_payment::verify(payment_hash, &payment_data, self.highest_seen_timestamp.load(Ordering::Acquire) as u64, &self.inbound_payment_key, &self.logger) {
58935901
Ok(result) => result,
58945902
Err(()) => {
@@ -5904,6 +5912,12 @@ where
59045912
fail_htlc!(claimable_htlc, payment_hash);
59055913
}
59065914
}
5915+
payment_preimage
5916+
} else { debug_assert!(false); None }
5917+
} else { None };
5918+
match claimable_htlc.onion_payload {
5919+
OnionPayload::Invoice { .. } => {
5920+
let payment_data = payment_data.unwrap();
59075921
let purpose = events::PaymentPurpose::from_parts(
59085922
payment_preimage,
59095923
payment_data.payment_secret,
@@ -11422,6 +11436,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1142211436
(3, payment_metadata, option),
1142311437
(4, payment_data, option), // Added in 0.0.116
1142411438
(5, custom_tlvs, optional_vec),
11439+
(7, has_recipient_created_payment_secret, (default_value, false)),
1142511440
},
1142611441
);
1142711442

lightning/src/ln/onion_payment.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,14 @@ pub(super) fn create_recv_pending_htlc_info(
135135
) -> Result<PendingHTLCInfo, InboundHTLCErr> {
136136
let (
137137
payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, onion_cltv_expiry,
138-
payment_metadata, payment_context, requires_blinded_error
138+
payment_metadata, payment_context, requires_blinded_error, has_recipient_created_payment_secret
139139
) = match hop_data {
140140
msgs::InboundOnionPayload::Receive {
141141
payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
142142
cltv_expiry_height, payment_metadata, ..
143143
} =>
144144
(payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
145-
cltv_expiry_height, payment_metadata, None, false),
145+
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none()),
146146
msgs::InboundOnionPayload::BlindedReceive {
147147
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
148148
intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage,
@@ -161,7 +161,7 @@ pub(super) fn create_recv_pending_htlc_info(
161161
let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
162162
(Some(payment_data), keysend_preimage, custom_tlvs,
163163
sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
164-
intro_node_blinding_point.is_none())
164+
intro_node_blinding_point.is_none(), true)
165165
}
166166
msgs::InboundOnionPayload::Forward { .. } => {
167167
return Err(InboundHTLCErr {
@@ -241,6 +241,7 @@ pub(super) fn create_recv_pending_htlc_info(
241241
incoming_cltv_expiry: onion_cltv_expiry,
242242
custom_tlvs,
243243
requires_blinded_error,
244+
has_recipient_created_payment_secret,
244245
}
245246
} else if let Some(data) = payment_data {
246247
PendingHTLCRouting::Receive {

0 commit comments

Comments
 (0)