Skip to content

Commit 88d5459

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. Note: 1. Similar to keysend, for serialization purposes, user_custom_tlv are assigned a specific TLV number. 2. For uniformity, user_custom_tlv are assigned the lowest possible odd number after (1 << 16), which is 65537.
1 parent e8ac014 commit 88d5459

9 files changed

+200
-126
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,7 @@ fn custom_tlvs_to_blinded_path() {
13231323
);
13241324

13251325
let recipient_onion_fields = RecipientOnionFields::spontaneous_empty()
1326-
.with_custom_tlvs(vec![((1 << 16) + 1, vec![42, 42])])
1326+
.with_sender_custom_tlvs(vec![((1 << 16) + 3, vec![42, 42])])
13271327
.unwrap();
13281328
nodes[0].node.send_payment(payment_hash, recipient_onion_fields.clone(),
13291329
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
@@ -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_sender_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_sender_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: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,7 +2585,8 @@ pub struct PassAlongPathArgs<'a, 'b, 'c, 'd> {
25852585
pub clear_recipient_events: bool,
25862586
pub expected_preimage: Option<PaymentPreimage>,
25872587
pub is_probe: bool,
2588-
pub custom_tlvs: Vec<(u64, Vec<u8>)>,
2588+
pub sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
2589+
pub user_custom_tlvs: Vec<u8>,
25892590
pub payment_metadata: Option<Vec<u8>>,
25902591
}
25912592

@@ -2597,7 +2598,7 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
25972598
Self {
25982599
origin_node, expected_path, recv_value, payment_hash, payment_secret: None, event,
25992600
payment_claimable_expected: true, clear_recipient_events: true, expected_preimage: None,
2600-
is_probe: false, custom_tlvs: Vec::new(), payment_metadata: None,
2601+
is_probe: false, sender_custom_tlvs: Vec::new(), user_custom_tlvs: Vec::new(), payment_metadata: None,
26012602
}
26022603
}
26032604
pub fn without_clearing_recipient_events(mut self) -> Self {
@@ -2621,8 +2622,12 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
26212622
self.expected_preimage = Some(payment_preimage);
26222623
self
26232624
}
2624-
pub fn with_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2625-
self.custom_tlvs = custom_tlvs;
2625+
pub fn with_sender_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2626+
self.sender_custom_tlvs = custom_tlvs;
2627+
self
2628+
}
2629+
pub fn with_user_custom_tlvs(mut self, custom_tlvs: Vec<u8>) -> Self {
2630+
self.user_custom_tlvs = custom_tlvs;
26262631
self
26272632
}
26282633
pub fn with_payment_metadata(mut self, payment_metadata: Vec<u8>) -> Self {
@@ -2635,7 +2640,8 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
26352640
let PassAlongPathArgs {
26362641
origin_node, expected_path, recv_value, payment_hash: our_payment_hash,
26372642
payment_secret: our_payment_secret, event: ev, payment_claimable_expected,
2638-
clear_recipient_events, expected_preimage, is_probe, custom_tlvs, payment_metadata,
2643+
clear_recipient_events, expected_preimage, is_probe, sender_custom_tlvs, user_custom_tlvs,
2644+
payment_metadata,
26392645
} = args;
26402646

26412647
let mut payment_event = SendEvent::from_event(ev);
@@ -2668,7 +2674,8 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
26682674
assert_eq!(our_payment_hash, *payment_hash);
26692675
assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
26702676
assert!(onion_fields.is_some());
2671-
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
2677+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2678+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_tlvs, user_custom_tlvs);
26722679
assert_eq!(onion_fields.as_ref().unwrap().payment_metadata, payment_metadata);
26732680
match &purpose {
26742681
PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => {
@@ -2782,7 +2789,8 @@ pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
27822789
pub expected_min_htlc_overpay: Vec<u32>,
27832790
pub skip_last: bool,
27842791
pub payment_preimage: PaymentPreimage,
2785-
pub custom_tlvs: Vec<(u64, Vec<u8>)>,
2792+
pub sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
2793+
pub user_custom_tlvs: Vec<u8>,
27862794
// Allow forwarding nodes to have taken 1 msat more fee than expected based on the downstream
27872795
// fulfill amount.
27882796
//
@@ -2801,7 +2809,7 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
28012809
Self {
28022810
origin_node, expected_paths, expected_extra_fees: vec![0; expected_paths.len()],
28032811
expected_min_htlc_overpay: vec![0; expected_paths.len()], skip_last: false, payment_preimage,
2804-
allow_1_msat_fee_overpay: false, custom_tlvs: vec![],
2812+
allow_1_msat_fee_overpay: false, sender_custom_tlvs: vec![], user_custom_tlvs: vec![],
28052813
}
28062814
}
28072815
pub fn skip_last(mut self, skip_last: bool) -> Self {
@@ -2820,16 +2828,16 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
28202828
self.allow_1_msat_fee_overpay = true;
28212829
self
28222830
}
2823-
pub fn with_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2824-
self.custom_tlvs = custom_tlvs;
2831+
pub fn with_sender_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2832+
self.sender_custom_tlvs = custom_tlvs;
28252833
self
28262834
}
28272835
}
28282836

28292837
pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
28302838
let ClaimAlongRouteArgs {
28312839
origin_node, expected_paths, expected_extra_fees, expected_min_htlc_overpay, skip_last,
2832-
payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay, custom_tlvs,
2840+
payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay, sender_custom_tlvs, user_custom_tlvs,
28332841
} = args;
28342842
let claim_event = expected_paths[0].last().unwrap().node.get_and_clear_pending_events();
28352843
assert_eq!(claim_event.len(), 1);
@@ -2849,7 +2857,8 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
28492857
assert_eq!(preimage, our_payment_preimage);
28502858
assert_eq!(htlcs.len(), expected_paths.len()); // One per path.
28512859
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);
2860+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2861+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_tlvs, user_custom_tlvs);
28532862
check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs);
28542863
fwd_amt_msat = amount_msat;
28552864
},
@@ -2866,7 +2875,8 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
28662875
assert_eq!(&payment_hash.0, &Sha256::hash(&our_payment_preimage.0)[..]);
28672876
assert_eq!(htlcs.len(), expected_paths.len()); // One per path.
28682877
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);
2878+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2879+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_tlvs, user_custom_tlvs);
28702880
check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs);
28712881
fwd_amt_msat = amount_msat;
28722882
}

0 commit comments

Comments
 (0)