Skip to content

Commit fd4d33a

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 070475e commit fd4d33a

9 files changed

+260
-146
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,7 +1395,7 @@ fn custom_tlvs_to_blinded_path() {
13951395
);
13961396

13971397
let recipient_onion_fields = RecipientOnionFields::spontaneous_empty()
1398-
.with_custom_tlvs(vec![((1 << 16) + 1, vec![42, 42])])
1398+
.with_sender_custom_tlvs(vec![((1 << 16) + 3, vec![42, 42])])
13991399
.unwrap();
14001400
nodes[0].node.send_payment(payment_hash, recipient_onion_fields.clone(),
14011401
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
@@ -1408,11 +1408,11 @@ fn custom_tlvs_to_blinded_path() {
14081408
let path = &[&nodes[1]];
14091409
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, ev)
14101410
.with_payment_secret(payment_secret)
1411-
.with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone());
1411+
.with_sender_custom_tlvs(recipient_onion_fields.sender_custom_tlvs.clone());
14121412
do_pass_along_path(args);
14131413
claim_payment_along_route(
14141414
ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
1415-
.with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone())
1415+
.with_sender_custom_tlvs(recipient_onion_fields.sender_custom_tlvs.clone())
14161416
);
14171417
}
14181418

lightning/src/ln/channelmanager.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,14 @@ pub enum PendingHTLCRouting {
194194
///
195195
/// For HTLCs received by LDK, this will ultimately be exposed in
196196
/// [`Event::PaymentClaimable::onion_fields`] as
197-
/// [`RecipientOnionFields::custom_tlvs`].
198-
custom_tlvs: Vec<(u64, Vec<u8>)>,
197+
/// [`RecipientOnionFields::sender_custom_tlvs`].
198+
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
199+
/// Custom TLVs set by the receiver in the blinded path used to reach them.
200+
///
201+
/// For HTLCs received by LDK, this will be exposed in
202+
/// [`Event::PaymentClaimable::onion_fields`] as
203+
/// [`RecipientOnionFields::user_custom_tlvs`].
204+
user_custom_tlvs: Vec<u8>,
199205
/// Set if this HTLC is the final hop in a multi-hop blinded path.
200206
requires_blinded_error: bool,
201207
},
@@ -224,8 +230,13 @@ pub enum PendingHTLCRouting {
224230
/// Custom TLVs which were set by the sender.
225231
///
226232
/// For HTLCs received by LDK, these will ultimately bubble back up as
227-
/// [`RecipientOnionFields::custom_tlvs`].
228-
custom_tlvs: Vec<(u64, Vec<u8>)>,
233+
/// [`RecipientOnionFields::sender_custom_tlvs`].
234+
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
235+
/// Custom TLVs set by the receiver in the blinded path used to reach them.
236+
///
237+
/// For HTLCs received by LDK, these will ultimately bubble back up as
238+
/// [`RecipientOnionFields::user_custom_tlvs`].
239+
user_custom_tlvs: Vec<u8>,
229240
/// Set if this HTLC is the final hop in a multi-hop blinded path.
230241
requires_blinded_error: bool,
231242
/// Set if we are receiving a keysend to a blinded path, meaning we created the
@@ -941,10 +952,10 @@ impl ClaimablePayments {
941952
}
942953
}
943954

944-
if let Some(RecipientOnionFields { custom_tlvs, .. }) = &payment.onion_fields {
945-
if !custom_tlvs_known && custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) {
955+
if let Some(RecipientOnionFields { sender_custom_tlvs, .. }) = &payment.onion_fields {
956+
if !custom_tlvs_known && sender_custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) {
946957
log_info!(logger, "Rejecting payment with payment hash {} as we cannot accept payment with unknown even TLVs: {}",
947-
&payment_hash, log_iter!(custom_tlvs.iter().map(|(typ, _)| typ).filter(|typ| *typ % 2 == 0)));
958+
&payment_hash, log_iter!(sender_custom_tlvs.iter().map(|(typ, _)| typ).filter(|typ| *typ % 2 == 0)));
948959
return Err(payment.htlcs);
949960
}
950961
}
@@ -5985,25 +5996,26 @@ where
59855996
) = match routing {
59865997
PendingHTLCRouting::Receive {
59875998
payment_data, payment_metadata, payment_context,
5988-
incoming_cltv_expiry, phantom_shared_secret, custom_tlvs,
5999+
incoming_cltv_expiry, phantom_shared_secret, sender_custom_tlvs, user_custom_tlvs,
59896000
requires_blinded_error: _
59906001
} => {
59916002
let _legacy_hop_data = Some(payment_data.clone());
59926003
let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
5993-
payment_metadata, custom_tlvs };
6004+
payment_metadata, sender_custom_tlvs, user_custom_tlvs };
59946005
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
59956006
Some(payment_data), payment_context, phantom_shared_secret, onion_fields,
59966007
true)
59976008
},
59986009
PendingHTLCRouting::ReceiveKeysend {
59996010
payment_data, payment_preimage, payment_metadata,
6000-
incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _,
6011+
incoming_cltv_expiry, sender_custom_tlvs, user_custom_tlvs, requires_blinded_error: _,
60016012
has_recipient_created_payment_secret,
60026013
} => {
60036014
let onion_fields = RecipientOnionFields {
60046015
payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
60056016
payment_metadata,
6006-
custom_tlvs,
6017+
sender_custom_tlvs,
6018+
user_custom_tlvs,
60076019
};
60086020
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
60096021
payment_data, None, None, onion_fields, has_recipient_created_payment_secret)
@@ -12348,18 +12360,20 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1234812360
(1, phantom_shared_secret, option),
1234912361
(2, incoming_cltv_expiry, required),
1235012362
(3, payment_metadata, option),
12351-
(5, custom_tlvs, optional_vec),
12363+
(5, sender_custom_tlvs, optional_vec),
1235212364
(7, requires_blinded_error, (default_value, false)),
1235312365
(9, payment_context, option),
12366+
(11, user_custom_tlvs, optional_vec),
1235412367
},
1235512368
(2, ReceiveKeysend) => {
1235612369
(0, payment_preimage, required),
1235712370
(1, requires_blinded_error, (default_value, false)),
1235812371
(2, incoming_cltv_expiry, required),
1235912372
(3, payment_metadata, option),
1236012373
(4, payment_data, option), // Added in 0.0.116
12361-
(5, custom_tlvs, optional_vec),
12374+
(5, sender_custom_tlvs, optional_vec),
1236212375
(7, has_recipient_created_payment_secret, (default_value, false)),
12376+
(9, user_custom_tlvs, optional_vec),
1236312377
},
1236412378
);
1236512379

@@ -15354,7 +15368,8 @@ mod tests {
1535415368
payment_data: Some(msgs::FinalOnionHopData {
1535515369
payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
1535615370
}),
15357-
custom_tlvs: Vec::new(),
15371+
sender_custom_tlvs: Vec::new(),
15372+
user_custom_tlvs: Vec::new(),
1535815373
};
1535915374
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
1536015375
// intended amount, we fail the payment.
@@ -15376,7 +15391,8 @@ mod tests {
1537615391
payment_data: Some(msgs::FinalOnionHopData {
1537715392
payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
1537815393
}),
15379-
custom_tlvs: Vec::new(),
15394+
sender_custom_tlvs: Vec::new(),
15395+
user_custom_tlvs: Vec::new(),
1538015396
};
1538115397
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
1538215398
assert!(create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
@@ -15400,7 +15416,8 @@ mod tests {
1540015416
payment_data: Some(msgs::FinalOnionHopData {
1540115417
payment_secret: PaymentSecret([0; 32]), total_msat: 100,
1540215418
}),
15403-
custom_tlvs: Vec::new(),
15419+
sender_custom_tlvs: Vec::new(),
15420+
user_custom_tlvs: Vec::new(),
1540415421
}, [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height,
1540515422
node[0].node.default_configuration.accept_mpp_keysend);
1540615423

lightning/src/ln/functional_test_utils.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,7 +2633,8 @@ pub struct PassAlongPathArgs<'a, 'b, 'c, 'd> {
26332633
pub clear_recipient_events: bool,
26342634
pub expected_preimage: Option<PaymentPreimage>,
26352635
pub is_probe: bool,
2636-
pub custom_tlvs: Vec<(u64, Vec<u8>)>,
2636+
pub sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
2637+
pub user_custom_tlvs: Vec<u8>,
26372638
pub payment_metadata: Option<Vec<u8>>,
26382639
pub expected_failure: Option<HTLCDestination>,
26392640
}
@@ -2646,7 +2647,7 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
26462647
Self {
26472648
origin_node, expected_path, recv_value, payment_hash, payment_secret: None, event,
26482649
payment_claimable_expected: true, clear_recipient_events: true, expected_preimage: None,
2649-
is_probe: false, custom_tlvs: Vec::new(), payment_metadata: None, expected_failure: None,
2650+
is_probe: false, sender_custom_tlvs: Vec::new(), user_custom_tlvs: Vec::new(), payment_metadata: None, expected_failure: None,
26502651
}
26512652
}
26522653
pub fn without_clearing_recipient_events(mut self) -> Self {
@@ -2670,8 +2671,12 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
26702671
self.expected_preimage = Some(payment_preimage);
26712672
self
26722673
}
2673-
pub fn with_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2674-
self.custom_tlvs = custom_tlvs;
2674+
pub fn with_sender_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2675+
self.sender_custom_tlvs = custom_tlvs;
2676+
self
2677+
}
2678+
pub fn with_user_custom_tlvs(mut self, custom_tlvs: Vec<u8>) -> Self {
2679+
self.user_custom_tlvs = custom_tlvs;
26752680
self
26762681
}
26772682
pub fn with_payment_metadata(mut self, payment_metadata: Vec<u8>) -> Self {
@@ -2689,8 +2694,8 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
26892694
let PassAlongPathArgs {
26902695
origin_node, expected_path, recv_value, payment_hash: our_payment_hash,
26912696
payment_secret: our_payment_secret, event: ev, payment_claimable_expected,
2692-
clear_recipient_events, expected_preimage, is_probe, custom_tlvs, payment_metadata,
2693-
expected_failure
2697+
clear_recipient_events, expected_preimage, is_probe, sender_custom_tlvs, user_custom_tlvs,
2698+
payment_metadata, expected_failure
26942699
} = args;
26952700

26962701
let mut payment_event = SendEvent::from_event(ev);
@@ -2723,7 +2728,8 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
27232728
assert_eq!(our_payment_hash, *payment_hash);
27242729
assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
27252730
assert!(onion_fields.is_some());
2726-
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
2731+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2732+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_tlvs, user_custom_tlvs);
27272733
assert_eq!(onion_fields.as_ref().unwrap().payment_metadata, payment_metadata);
27282734
match &purpose {
27292735
PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => {
@@ -2842,7 +2848,8 @@ pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
28422848
pub expected_min_htlc_overpay: Vec<u32>,
28432849
pub skip_last: bool,
28442850
pub payment_preimage: PaymentPreimage,
2845-
pub custom_tlvs: Vec<(u64, Vec<u8>)>,
2851+
pub sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
2852+
pub user_custom_tlvs: Vec<u8>,
28462853
// Allow forwarding nodes to have taken 1 msat more fee than expected based on the downstream
28472854
// fulfill amount.
28482855
//
@@ -2861,7 +2868,7 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
28612868
Self {
28622869
origin_node, expected_paths, expected_extra_fees: vec![0; expected_paths.len()],
28632870
expected_min_htlc_overpay: vec![0; expected_paths.len()], skip_last: false, payment_preimage,
2864-
allow_1_msat_fee_overpay: false, custom_tlvs: vec![],
2871+
allow_1_msat_fee_overpay: false, sender_custom_tlvs: vec![], user_custom_tlvs: vec![],
28652872
}
28662873
}
28672874
pub fn skip_last(mut self, skip_last: bool) -> Self {
@@ -2880,16 +2887,16 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
28802887
self.allow_1_msat_fee_overpay = true;
28812888
self
28822889
}
2883-
pub fn with_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2884-
self.custom_tlvs = custom_tlvs;
2890+
pub fn with_sender_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2891+
self.sender_custom_tlvs = custom_tlvs;
28852892
self
28862893
}
28872894
}
28882895

28892896
pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
28902897
let ClaimAlongRouteArgs {
28912898
origin_node, expected_paths, expected_extra_fees, expected_min_htlc_overpay, skip_last,
2892-
payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay, custom_tlvs,
2899+
payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay, sender_custom_tlvs, user_custom_tlvs,
28932900
} = args;
28942901
let claim_event = expected_paths[0].last().unwrap().node.get_and_clear_pending_events();
28952902
assert_eq!(claim_event.len(), 1);
@@ -2909,7 +2916,8 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
29092916
assert_eq!(preimage, our_payment_preimage);
29102917
assert_eq!(htlcs.len(), expected_paths.len()); // One per path.
29112918
assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::<u64>(), amount_msat);
2912-
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
2919+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2920+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_tlvs, user_custom_tlvs);
29132921
check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs);
29142922
fwd_amt_msat = amount_msat;
29152923
},
@@ -2926,7 +2934,8 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
29262934
assert_eq!(&payment_hash.0, &Sha256::hash(&our_payment_preimage.0)[..]);
29272935
assert_eq!(htlcs.len(), expected_paths.len()); // One per path.
29282936
assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::<u64>(), amount_msat);
2929-
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
2937+
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2938+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_tlvs, user_custom_tlvs);
29302939
check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs);
29312940
fwd_amt_msat = amount_msat;
29322941
}

0 commit comments

Comments
 (0)