Skip to content

Commit 136a558

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 865210e commit 136a558

9 files changed

+196
-125
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: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,9 @@ pub enum PendingHTLCRouting {
195195
/// For HTLCs received by LDK, this will ultimately be exposed in
196196
/// [`Event::PaymentClaimable::onion_fields`] as
197197
/// [`RecipientOnionFields::custom_tlvs`].
198-
custom_tlvs: Vec<(u64, Vec<u8>)>,
198+
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
199+
/// Custom TLVs which were set by us through the reply path
200+
user_custom_tlvs: Vec<u8>,
199201
/// Set if this HTLC is the final hop in a multi-hop blinded path.
200202
requires_blinded_error: bool,
201203
},
@@ -225,7 +227,9 @@ pub enum PendingHTLCRouting {
225227
///
226228
/// For HTLCs received by LDK, these will ultimately bubble back up as
227229
/// [`RecipientOnionFields::custom_tlvs`].
228-
custom_tlvs: Vec<(u64, Vec<u8>)>,
230+
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
231+
/// Custom TLVs which were set by us through the reply path
232+
user_custom_tlvs: Vec<u8>,
229233
/// Set if this HTLC is the final hop in a multi-hop blinded path.
230234
requires_blinded_error: bool,
231235
/// Set if we are receiving a keysend to a blinded path, meaning we created the
@@ -941,10 +945,10 @@ impl ClaimablePayments {
941945
}
942946
}
943947

944-
if let Some(RecipientOnionFields { custom_tlvs, .. }) = &payment.onion_fields {
945-
if !custom_tlvs_known && custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) {
948+
if let Some(RecipientOnionFields { sender_custom_tlvs, .. }) = &payment.onion_fields {
949+
if !custom_tlvs_known && sender_custom_tlvs.iter().any(|(typ, _)| typ % 2 == 0) {
946950
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)));
951+
&payment_hash, log_iter!(sender_custom_tlvs.iter().map(|(typ, _)| typ).filter(|typ| *typ % 2 == 0)));
948952
return Err(payment.htlcs);
949953
}
950954
}
@@ -5985,25 +5989,26 @@ where
59855989
) = match routing {
59865990
PendingHTLCRouting::Receive {
59875991
payment_data, payment_metadata, payment_context,
5988-
incoming_cltv_expiry, phantom_shared_secret, custom_tlvs,
5992+
incoming_cltv_expiry, phantom_shared_secret, sender_custom_tlvs, user_custom_tlvs,
59895993
requires_blinded_error: _
59905994
} => {
59915995
let _legacy_hop_data = Some(payment_data.clone());
59925996
let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
5993-
payment_metadata, custom_tlvs };
5997+
payment_metadata, sender_custom_tlvs, user_custom_tlvs };
59945998
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
59955999
Some(payment_data), payment_context, phantom_shared_secret, onion_fields,
59966000
true)
59976001
},
59986002
PendingHTLCRouting::ReceiveKeysend {
59996003
payment_data, payment_preimage, payment_metadata,
6000-
incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _,
6004+
incoming_cltv_expiry, sender_custom_tlvs, user_custom_tlvs, requires_blinded_error: _,
60016005
has_recipient_created_payment_secret,
60026006
} => {
60036007
let onion_fields = RecipientOnionFields {
60046008
payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
60056009
payment_metadata,
6006-
custom_tlvs,
6010+
sender_custom_tlvs,
6011+
user_custom_tlvs,
60076012
};
60086013
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
60096014
payment_data, None, None, onion_fields, has_recipient_created_payment_secret)
@@ -12348,18 +12353,20 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1234812353
(1, phantom_shared_secret, option),
1234912354
(2, incoming_cltv_expiry, required),
1235012355
(3, payment_metadata, option),
12351-
(5, custom_tlvs, optional_vec),
12356+
(5, sender_custom_tlvs, optional_vec),
1235212357
(7, requires_blinded_error, (default_value, false)),
1235312358
(9, payment_context, option),
12359+
(11, user_custom_tlvs, optional_vec),
1235412360
},
1235512361
(2, ReceiveKeysend) => {
1235612362
(0, payment_preimage, required),
1235712363
(1, requires_blinded_error, (default_value, false)),
1235812364
(2, incoming_cltv_expiry, required),
1235912365
(3, payment_metadata, option),
1236012366
(4, payment_data, option), // Added in 0.0.116
12361-
(5, custom_tlvs, optional_vec),
12367+
(5, sender_custom_tlvs, optional_vec),
1236212368
(7, has_recipient_created_payment_secret, (default_value, false)),
12369+
(9, user_custom_tlvs, optional_vec),
1236312370
},
1236412371
);
1236512372

@@ -15354,7 +15361,8 @@ mod tests {
1535415361
payment_data: Some(msgs::FinalOnionHopData {
1535515362
payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
1535615363
}),
15357-
custom_tlvs: Vec::new(),
15364+
sender_custom_tlvs: Vec::new(),
15365+
user_custom_tlvs: Vec::new(),
1535815366
};
1535915367
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
1536015368
// intended amount, we fail the payment.
@@ -15376,7 +15384,8 @@ mod tests {
1537615384
payment_data: Some(msgs::FinalOnionHopData {
1537715385
payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat,
1537815386
}),
15379-
custom_tlvs: Vec::new(),
15387+
sender_custom_tlvs: Vec::new(),
15388+
user_custom_tlvs: Vec::new(),
1538015389
};
1538115390
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
1538215391
assert!(create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
@@ -15400,7 +15409,8 @@ mod tests {
1540015409
payment_data: Some(msgs::FinalOnionHopData {
1540115410
payment_secret: PaymentSecret([0; 32]), total_msat: 100,
1540215411
}),
15403-
custom_tlvs: Vec::new(),
15412+
sender_custom_tlvs: Vec::new(),
15413+
user_custom_tlvs: Vec::new(),
1540415414
}, [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height,
1540515415
node[0].node.default_configuration.accept_mpp_keysend);
1540615416

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)