Skip to content

Commit 5f7054d

Browse files
committed
Distinguish Between Sender and User Custom TLVs
- This update introduces a clear separation between two types of custom TLVs: those sent by the sender for the user, and those added by the user to the reply path, which are expected to return with the response. - This commit establishes this distinction in the codebase at relevant points. - The next commit will build on this by providing an interface for users to add their own custom TLVs to the reply path, allowing them to receive specific data back in the response.
1 parent e8ac014 commit 5f7054d

9 files changed

+146
-99
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,11 +1336,11 @@ fn custom_tlvs_to_blinded_path() {
13361336
let path = &[&nodes[1]];
13371337
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, ev)
13381338
.with_payment_secret(payment_secret)
1339-
.with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone());
1339+
.with_custom_tlvs(recipient_onion_fields.sender_custom_tlvs.clone());
13401340
do_pass_along_path(args);
13411341
claim_payment_along_route(
13421342
ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
1343-
.with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone())
1343+
.with_custom_tlvs(recipient_onion_fields.sender_custom_tlvs.clone())
13441344
);
13451345
}
13461346

lightning/src/ln/channelmanager.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ pub enum PendingHTLCRouting {
187187
/// For HTLCs received by LDK, this will ultimately be exposed in
188188
/// [`Event::PaymentClaimable::onion_fields`] as
189189
/// [`RecipientOnionFields::custom_tlvs`].
190-
custom_tlvs: Vec<(u64, Vec<u8>)>,
190+
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
191+
/// Custom TLVs which were set by us through the reply path
192+
user_custom_tlvs: Vec<u8>,
191193
/// Set if this HTLC is the final hop in a multi-hop blinded path.
192194
requires_blinded_error: bool,
193195
},
@@ -217,7 +219,9 @@ pub enum PendingHTLCRouting {
217219
///
218220
/// For HTLCs received by LDK, these will ultimately bubble back up as
219221
/// [`RecipientOnionFields::custom_tlvs`].
220-
custom_tlvs: Vec<(u64, Vec<u8>)>,
222+
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
223+
/// Custom TLVs which were set by us through the reply path
224+
user_custom_tlvs: Vec<u8>,
221225
/// Set if this HTLC is the final hop in a multi-hop blinded path.
222226
requires_blinded_error: bool,
223227
},
@@ -5712,23 +5716,24 @@ where
57125716
let (cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret, mut onion_fields) = match routing {
57135717
PendingHTLCRouting::Receive {
57145718
payment_data, payment_metadata, payment_context,
5715-
incoming_cltv_expiry, phantom_shared_secret, custom_tlvs,
5719+
incoming_cltv_expiry, phantom_shared_secret, sender_custom_tlvs, user_custom_tlvs,
57165720
requires_blinded_error: _
57175721
} => {
57185722
let _legacy_hop_data = Some(payment_data.clone());
57195723
let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
5720-
payment_metadata, custom_tlvs };
5724+
payment_metadata, sender_custom_tlvs, user_custom_tlvs };
57215725
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
57225726
Some(payment_data), payment_context, phantom_shared_secret, onion_fields)
57235727
},
57245728
PendingHTLCRouting::ReceiveKeysend {
57255729
payment_data, payment_preimage, payment_metadata,
5726-
incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _
5730+
incoming_cltv_expiry, sender_custom_tlvs, user_custom_tlvs, requires_blinded_error: _
57275731
} => {
57285732
let onion_fields = RecipientOnionFields {
57295733
payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
57305734
payment_metadata,
5731-
custom_tlvs,
5735+
sender_custom_tlvs,
5736+
user_custom_tlvs,
57325737
};
57335738
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
57345739
payment_data, None, None, onion_fields)
@@ -6700,10 +6705,10 @@ where
67006705
}
67016706
});
67026707

6703-
if let Some(RecipientOnionFields { ref custom_tlvs, .. }) = claiming_payment.onion_fields {
6704-
if !custom_tlvs_known && custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) {
6708+
if let Some(RecipientOnionFields { ref sender_custom_tlvs, .. }) = claiming_payment.onion_fields {
6709+
if !custom_tlvs_known && sender_custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) {
67056710
log_info!(self.logger, "Rejecting payment with payment hash {} as we cannot accept payment with unknown even TLVs: {}",
6706-
&payment_hash, log_iter!(custom_tlvs.iter().map(|(typ, _)| typ).filter(|typ| *typ % 2 == 0)));
6711+
&payment_hash, log_iter!(sender_custom_tlvs.iter().map(|(typ, _)| typ).filter(|typ| *typ % 2 == 0)));
67076712
claimable_payments.pending_claiming_payments.remove(&payment_hash);
67086713
mem::drop(claimable_payments);
67096714
for htlc in payment.htlcs {
@@ -11455,17 +11460,19 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1145511460
(1, phantom_shared_secret, option),
1145611461
(2, incoming_cltv_expiry, required),
1145711462
(3, payment_metadata, option),
11458-
(5, custom_tlvs, optional_vec),
11463+
(5, sender_custom_tlvs, optional_vec),
1145911464
(7, requires_blinded_error, (default_value, false)),
1146011465
(9, payment_context, option),
11466+
(11, user_custom_tlvs, optional_vec),
1146111467
},
1146211468
(2, ReceiveKeysend) => {
1146311469
(0, payment_preimage, required),
1146411470
(1, requires_blinded_error, (default_value, false)),
1146511471
(2, incoming_cltv_expiry, required),
1146611472
(3, payment_metadata, option),
1146711473
(4, payment_data, option), // Added in 0.0.116
11468-
(5, custom_tlvs, optional_vec),
11474+
(5, sender_custom_tlvs, optional_vec),
11475+
(7, user_custom_tlvs, optional_vec),
1146911476
},
1147011477
);
1147111478

@@ -14182,7 +14189,8 @@ mod tests {
1418214189
payment_data: Some(msgs::FinalOnionHopData {
1418314190
payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
1418414191
}),
14185-
custom_tlvs: Vec::new(),
14192+
sender_custom_tlvs: Vec::new(),
14193+
user_custom_tlvs: Vec::new(),
1418614194
};
1418714195
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
1418814196
// intended amount, we fail the payment.
@@ -14204,7 +14212,8 @@ mod tests {
1420414212
payment_data: Some(msgs::FinalOnionHopData {
1420514213
payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
1420614214
}),
14207-
custom_tlvs: Vec::new(),
14215+
sender_custom_tlvs: Vec::new(),
14216+
user_custom_tlvs: Vec::new(),
1420814217
};
1420914218
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
1421014219
assert!(create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
@@ -14228,7 +14237,8 @@ mod tests {
1422814237
payment_data: Some(msgs::FinalOnionHopData {
1422914238
payment_secret: PaymentSecret([0; 32]), total_msat: 100,
1423014239
}),
14231-
custom_tlvs: Vec::new(),
14240+
sender_custom_tlvs: Vec::new(),
14241+
user_custom_tlvs: Vec::new(),
1423214242
}, [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height,
1423314243
node[0].node.default_configuration.accept_mpp_keysend);
1423414244

lightning/src/ln/functional_test_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,7 +2668,7 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
26682668
assert_eq!(our_payment_hash, *payment_hash);
26692669
assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
26702670
assert!(onion_fields.is_some());
2671-
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
2671+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, custom_tlvs);
26722672
assert_eq!(onion_fields.as_ref().unwrap().payment_metadata, payment_metadata);
26732673
match &purpose {
26742674
PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => {
@@ -2849,7 +2849,7 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
28492849
assert_eq!(preimage, our_payment_preimage);
28502850
assert_eq!(htlcs.len(), expected_paths.len()); // One per path.
28512851
assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::<u64>(), amount_msat);
2852-
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
2852+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, custom_tlvs);
28532853
check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs);
28542854
fwd_amt_msat = amount_msat;
28552855
},
@@ -2866,7 +2866,7 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
28662866
assert_eq!(&payment_hash.0, &Sha256::hash(&our_payment_preimage.0)[..]);
28672867
assert_eq!(htlcs.len(), expected_paths.len()); // One per path.
28682868
assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::<u64>(), amount_msat);
2869-
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
2869+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, custom_tlvs);
28702870
check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs);
28712871
fwd_amt_msat = amount_msat;
28722872
}

lightning/src/ln/max_payment_path_len_tests.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ fn large_payment_metadata() {
5858
}),
5959
payment_metadata: None,
6060
keysend_preimage: None,
61-
custom_tlvs: &Vec::new(),
61+
sender_custom_tlvs: &Vec::new(),
62+
user_custom_tlvs: &Vec::new(),
6263
sender_intended_htlc_amt_msat: MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY,
6364
cltv_expiry_height: nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
6465
}.serialized_length();
@@ -75,7 +76,8 @@ fn large_payment_metadata() {
7576
let mut recipient_onion_max_md_size = RecipientOnionFields {
7677
payment_secret: Some(payment_secret),
7778
payment_metadata: Some(payment_metadata.clone()),
78-
custom_tlvs: Vec::new(),
79+
sender_custom_tlvs: Vec::new(),
80+
user_custom_tlvs: Vec::new(),
7981
};
8082
nodes[0].node.send_payment(payment_hash, recipient_onion_max_md_size.clone(), PaymentId(payment_hash.0), route_0_1.route_params.clone().unwrap(), Retry::Attempts(0)).unwrap();
8183
check_added_monitors!(nodes[0], 1);
@@ -123,7 +125,8 @@ fn large_payment_metadata() {
123125
let mut recipient_onion_allows_2_hops = RecipientOnionFields {
124126
payment_secret: Some(payment_secret_2),
125127
payment_metadata: Some(vec![42; max_metadata_len - INTERMED_PAYLOAD_LEN_ESTIMATE]),
126-
custom_tlvs: Vec::new(),
128+
sender_custom_tlvs: Vec::new(),
129+
user_custom_tlvs: Vec::new(),
127130
};
128131
let mut route_params_0_2 = route_0_2.route_params.clone().unwrap();
129132
route_params_0_2.payment_params.max_path_length = 2;
@@ -184,7 +187,8 @@ fn one_hop_blinded_path_with_custom_tlv() {
184187
encrypted_tlvs: &blinded_path.blinded_hops()[0].encrypted_payload,
185188
intro_node_blinding_point: Some(blinded_path.blinding_point()),
186189
keysend_preimage: None,
187-
custom_tlvs: &Vec::new()
190+
sender_custom_tlvs: &Vec::new(),
191+
user_custom_tlvs: &Vec::new(),
188192
}.serialized_length();
189193
let max_custom_tlv_len = 1300
190194
- crate::util::ser::BigSize(CUSTOM_TLV_TYPE).serialized_length() // custom TLV type
@@ -205,16 +209,16 @@ fn one_hop_blinded_path_with_custom_tlv() {
205209
let path = &[&nodes[2]];
206210
let args = PassAlongPathArgs::new(&nodes[1], path, amt_msat, payment_hash, events.pop().unwrap())
207211
.with_payment_secret(payment_secret)
208-
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone());
212+
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.sender_custom_tlvs.clone());
209213
do_pass_along_path(args);
210214
claim_payment_along_route(
211215
ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2]]], payment_preimage)
212-
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone())
216+
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.sender_custom_tlvs.clone())
213217
);
214218

215219
// If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding.
216220
let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone();
217-
recipient_onion_too_large_custom_tlv.custom_tlvs[0].1.push(42);
221+
recipient_onion_too_large_custom_tlv.sender_custom_tlvs[0].1.push(42);
218222
let err = nodes[1].node.send_payment(payment_hash, recipient_onion_too_large_custom_tlv, PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap_err();
219223
assert_eq!(err, RetryableSendFailure::OnionPacketSizeExceeded);
220224

@@ -226,7 +230,7 @@ fn one_hop_blinded_path_with_custom_tlv() {
226230
// If we remove enough custom TLV bytes to allow for 1 intermediate unblinded hop, we're now able
227231
// to send nodes[0] -> nodes[2].
228232
let mut recipient_onion_allows_2_hops = recipient_onion_max_custom_tlv_size.clone();
229-
recipient_onion_allows_2_hops.custom_tlvs[0].1.resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0);
233+
recipient_onion_allows_2_hops.sender_custom_tlvs[0].1.resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0);
230234
nodes[0].node.send_payment(payment_hash, recipient_onion_allows_2_hops.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap();
231235
check_added_monitors(&nodes[0], 1);
232236

@@ -235,11 +239,11 @@ fn one_hop_blinded_path_with_custom_tlv() {
235239
let path = &[&nodes[1], &nodes[2]];
236240
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap())
237241
.with_payment_secret(payment_secret)
238-
.with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone());
242+
.with_custom_tlvs(recipient_onion_allows_2_hops.sender_custom_tlvs.clone());
239243
do_pass_along_path(args);
240244
claim_payment_along_route(
241245
ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
242-
.with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs)
246+
.with_custom_tlvs(recipient_onion_allows_2_hops.sender_custom_tlvs)
243247
);
244248
}
245249

@@ -300,16 +304,16 @@ fn blinded_path_with_custom_tlv() {
300304
let path = &[&nodes[2], &nodes[3]];
301305
let args = PassAlongPathArgs::new(&nodes[1], path, amt_msat, payment_hash, events.pop().unwrap())
302306
.with_payment_secret(payment_secret)
303-
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone());
307+
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.sender_custom_tlvs.clone());
304308
do_pass_along_path(args);
305309
claim_payment_along_route(
306310
ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2], &nodes[3]]], payment_preimage)
307-
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone())
311+
.with_custom_tlvs(recipient_onion_max_custom_tlv_size.sender_custom_tlvs.clone())
308312
);
309313

310314
// If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding.
311315
let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone();
312-
recipient_onion_too_large_custom_tlv.custom_tlvs[0].1.push(42);
316+
recipient_onion_too_large_custom_tlv.sender_custom_tlvs[0].1.push(42);
313317
let err = nodes[1].node.send_payment(payment_hash, recipient_onion_too_large_custom_tlv.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap_err();
314318
assert_eq!(err, RetryableSendFailure::OnionPacketSizeExceeded);
315319

@@ -333,7 +337,7 @@ fn blinded_path_with_custom_tlv() {
333337
// If we remove enough custom TLV bytes to allow for 1 intermediate unblinded hop, we're now able
334338
// to send nodes[0] -> nodes[3].
335339
let mut recipient_onion_allows_2_hops = recipient_onion_max_custom_tlv_size.clone();
336-
recipient_onion_allows_2_hops.custom_tlvs[0].1.resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0);
340+
recipient_onion_allows_2_hops.sender_custom_tlvs[0].1.resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0);
337341
nodes[0].node.send_payment(payment_hash, recipient_onion_allows_2_hops.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap();
338342
check_added_monitors(&nodes[0], 1);
339343

@@ -342,11 +346,11 @@ fn blinded_path_with_custom_tlv() {
342346
let path = &[&nodes[1], &nodes[2], &nodes[3]];
343347
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap())
344348
.with_payment_secret(payment_secret)
345-
.with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone());
349+
.with_custom_tlvs(recipient_onion_allows_2_hops.sender_custom_tlvs.clone());
346350
do_pass_along_path(args);
347351
claim_payment_along_route(
348352
ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], payment_preimage)
349-
.with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs)
353+
.with_custom_tlvs(recipient_onion_allows_2_hops.sender_custom_tlvs)
350354
);
351355
}
352356

0 commit comments

Comments
 (0)