Skip to content

Commit c947de3

Browse files
WIP: 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 212ee86 commit c947de3

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

lightning/src/ln/channelmanager.rs

+22-7
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

@@ -5698,7 +5702,10 @@ where
56985702
}
56995703
}) => {
57005704
let blinded_failure = routing.blinded_failure();
5701-
let (cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret, mut onion_fields) = match routing {
5705+
let (
5706+
cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret,
5707+
mut onion_fields, has_recipient_created_payment_secret
5708+
) = match routing {
57025709
PendingHTLCRouting::Receive {
57035710
payment_data, payment_metadata, payment_context,
57045711
incoming_cltv_expiry, phantom_shared_secret, custom_tlvs,
@@ -5708,19 +5715,21 @@ where
57085715
let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
57095716
payment_metadata, custom_tlvs };
57105717
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
5711-
Some(payment_data), payment_context, phantom_shared_secret, onion_fields)
5718+
Some(payment_data), payment_context, phantom_shared_secret, onion_fields,
5719+
true)
57125720
},
57135721
PendingHTLCRouting::ReceiveKeysend {
57145722
payment_data, payment_preimage, payment_metadata,
5715-
incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _
5723+
incoming_cltv_expiry, custom_tlvs, has_recipient_created_payment_secret,
5724+
requires_blinded_error: _,
57165725
} => {
57175726
let onion_fields = RecipientOnionFields {
57185727
payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
57195728
payment_metadata,
57205729
custom_tlvs,
57215730
};
57225731
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
5723-
payment_data, None, None, onion_fields)
5732+
payment_data, None, None, onion_fields, has_recipient_created_payment_secret)
57245733
},
57255734
_ => {
57265735
panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -5885,9 +5894,8 @@ where
58855894
// that we are the ultimate recipient of the given payment hash.
58865895
// Further, we must not expose whether we have any other HTLCs
58875896
// associated with the same payment_hash pending or not.
5888-
match claimable_htlc.onion_payload {
5889-
OnionPayload::Invoice { .. } => {
5890-
let payment_data = payment_data.unwrap();
5897+
let payment_preimage = if has_recipient_created_payment_secret {
5898+
if let Some(ref payment_data) = payment_data {
58915899
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) {
58925900
Ok(result) => result,
58935901
Err(()) => {
@@ -5903,6 +5911,12 @@ where
59035911
fail_htlc!(claimable_htlc, payment_hash);
59045912
}
59055913
}
5914+
payment_preimage
5915+
} else { debug_assert!(false); None }
5916+
} else { None };
5917+
match claimable_htlc.onion_payload {
5918+
OnionPayload::Invoice { .. } => {
5919+
let payment_data = payment_data.unwrap();
59065920
let purpose = events::PaymentPurpose::from_parts(
59075921
payment_preimage,
59085922
payment_data.payment_secret,
@@ -11421,6 +11435,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1142111435
(3, payment_metadata, option),
1142211436
(4, payment_data, option), // Added in 0.0.116
1142311437
(5, custom_tlvs, optional_vec),
11438+
(7, has_recipient_created_payment_secret, (default_value, false)),
1142411439
},
1142511440
);
1142611441

lightning/src/ln/onion_payment.rs

+4-3
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)