Skip to content

Commit e446031

Browse files
committed
Introduce user_custom_data
1 parent 17e3756 commit e446031

7 files changed

+92
-29
lines changed

lightning/src/ln/channelmanager.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ pub enum PendingHTLCRouting {
222222
/// [`Event::PaymentClaimable::onion_fields`] as
223223
/// [`RecipientOnionFields::sender_custom_tlvs`].
224224
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
225+
/// Custom TLVs set by the receiver in the blinded path used to reach them.
226+
///
227+
/// For HTLCs received by LDK, this will be exposed in
228+
/// [`Event::PaymentClaimable::onion_fields`] as
229+
/// [`RecipientOnionFields::user_custom_data`].
230+
user_custom_data: Option<Vec<u8>>,
225231
/// Set if this HTLC is the final hop in a multi-hop blinded path.
226232
requires_blinded_error: bool,
227233
},
@@ -252,6 +258,11 @@ pub enum PendingHTLCRouting {
252258
/// For HTLCs received by LDK, these will ultimately bubble back up as
253259
/// [`RecipientOnionFields::sender_custom_tlvs`].
254260
sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
261+
/// Custom TLVs set by the receiver in the blinded path used to reach them.
262+
///
263+
/// For HTLCs received by LDK, these will ultimately bubble back up as
264+
/// [`RecipientOnionFields::user_custom_data`].
265+
user_custom_data: Option<Vec<u8>>,
255266
/// Set if this HTLC is the final hop in a multi-hop blinded path.
256267
requires_blinded_error: bool,
257268
/// Set if we are receiving a keysend to a blinded path, meaning we created the
@@ -6119,24 +6130,25 @@ where
61196130
PendingHTLCRouting::Receive {
61206131
payment_data, payment_metadata, payment_context,
61216132
incoming_cltv_expiry, phantom_shared_secret, sender_custom_tlvs,
6122-
requires_blinded_error: _
6133+
user_custom_data, requires_blinded_error: _
61236134
} => {
61246135
let _legacy_hop_data = Some(payment_data.clone());
61256136
let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
6126-
payment_metadata, sender_custom_tlvs };
6137+
payment_metadata, sender_custom_tlvs, user_custom_data };
61276138
(incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
61286139
Some(payment_data), payment_context, phantom_shared_secret, onion_fields,
61296140
true, None)
61306141
},
61316142
PendingHTLCRouting::ReceiveKeysend {
61326143
payment_data, payment_preimage, payment_metadata,
6133-
incoming_cltv_expiry, sender_custom_tlvs, requires_blinded_error: _,
6134-
has_recipient_created_payment_secret, payment_context, invoice_request,
6144+
incoming_cltv_expiry, sender_custom_tlvs, user_custom_data,
6145+
requires_blinded_error: _, has_recipient_created_payment_secret, payment_context, invoice_request,
61356146
} => {
61366147
let onion_fields = RecipientOnionFields {
61376148
payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
61386149
payment_metadata,
61396150
sender_custom_tlvs,
6151+
user_custom_data
61406152
};
61416153
(incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
61426154
payment_data, payment_context, None, onion_fields,
@@ -10645,7 +10657,7 @@ where
1064510657
/// [`Router::create_blinded_payment_paths`].
1064610658
fn create_blinded_payment_paths(
1064710659
&self, amount_msats: Option<u64>, payment_secret: PaymentSecret, payment_context: PaymentContext,
10648-
relative_expiry_seconds: u32
10660+
relative_expiry_seconds: u32,
1064910661
) -> Result<Vec<BlindedPaymentPath>, ()> {
1065010662
let expanded_key = &self.inbound_payment_key;
1065110663
let entropy = &*self.entropy_source;
@@ -12603,6 +12615,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1260312615
(5, sender_custom_tlvs, optional_vec),
1260412616
(7, requires_blinded_error, (default_value, false)),
1260512617
(9, payment_context, option),
12618+
(11, user_custom_data, option),
1260612619
},
1260712620
(2, ReceiveKeysend) => {
1260812621
(0, payment_preimage, required),
@@ -12612,6 +12625,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1261212625
(4, payment_data, option), // Added in 0.0.116
1261312626
(5, sender_custom_tlvs, optional_vec),
1261412627
(7, has_recipient_created_payment_secret, (default_value, false)),
12628+
(9, user_custom_data, option),
1261512629
(9, payment_context, option),
1261612630
(11, invoice_request, option),
1261712631
},

lightning/src/ln/functional_test_utils.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -2659,6 +2659,7 @@ pub struct PassAlongPathArgs<'a, 'b, 'c, 'd> {
26592659
pub expected_preimage: Option<PaymentPreimage>,
26602660
pub is_probe: bool,
26612661
pub sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
2662+
pub user_custom_data: Option<Vec<u8>>,
26622663
pub payment_metadata: Option<Vec<u8>>,
26632664
pub expected_failure: Option<HTLCDestination>,
26642665
}
@@ -2671,7 +2672,7 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
26712672
Self {
26722673
origin_node, expected_path, recv_value, payment_hash, payment_secret: None, event,
26732674
payment_claimable_expected: true, clear_recipient_events: true, expected_preimage: None,
2674-
is_probe: false, sender_custom_tlvs: Vec::new(), payment_metadata: None, expected_failure: None,
2675+
is_probe: false, sender_custom_tlvs: Vec::new(), user_custom_data: None, payment_metadata: None, expected_failure: None,
26752676
}
26762677
}
26772678
pub fn without_clearing_recipient_events(mut self) -> Self {
@@ -2714,7 +2715,7 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
27142715
let PassAlongPathArgs {
27152716
origin_node, expected_path, recv_value, payment_hash: our_payment_hash,
27162717
payment_secret: our_payment_secret, event: ev, payment_claimable_expected,
2717-
clear_recipient_events, expected_preimage, is_probe, sender_custom_tlvs, payment_metadata,
2718+
clear_recipient_events, expected_preimage, is_probe, sender_custom_tlvs, user_custom_data, payment_metadata,
27182719
expected_failure
27192720
} = args;
27202721

@@ -2751,6 +2752,7 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
27512752
assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
27522753
assert!(onion_fields.is_some());
27532754
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2755+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_data, user_custom_data);
27542756
assert_eq!(onion_fields.as_ref().unwrap().payment_metadata, payment_metadata);
27552757
match &purpose {
27562758
PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => {
@@ -2882,6 +2884,7 @@ pub struct ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
28822884
pub skip_last: bool,
28832885
pub payment_preimage: PaymentPreimage,
28842886
pub sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
2887+
pub user_custom_data: Option<Vec<u8>>,
28852888
// Allow forwarding nodes to have taken 1 msat more fee than expected based on the downstream
28862889
// fulfill amount.
28872890
//
@@ -2900,7 +2903,7 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
29002903
Self {
29012904
origin_node, expected_paths, expected_extra_fees: vec![0; expected_paths.len()],
29022905
expected_min_htlc_overpay: vec![0; expected_paths.len()], skip_last: false, payment_preimage,
2903-
allow_1_msat_fee_overpay: false, sender_custom_tlvs: vec![],
2906+
allow_1_msat_fee_overpay: false, sender_custom_tlvs: vec![], user_custom_data: None,
29042907
}
29052908
}
29062909
pub fn skip_last(mut self, skip_last: bool) -> Self {
@@ -2923,12 +2926,17 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> {
29232926
self.sender_custom_tlvs = sender_custom_tlvs;
29242927
self
29252928
}
2929+
pub fn with_user_custom_data(mut self, user_custom_data: Vec<u8>) -> Self {
2930+
self.user_custom_data = Some(user_custom_data);
2931+
self
2932+
}
29262933
}
29272934

29282935
pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
29292936
let ClaimAlongRouteArgs {
29302937
origin_node, expected_paths, expected_extra_fees, expected_min_htlc_overpay, skip_last,
29312938
payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay, sender_custom_tlvs,
2939+
user_custom_data
29322940
} = args;
29332941
let claim_event = expected_paths[0].last().unwrap().node.get_and_clear_pending_events();
29342942
assert_eq!(claim_event.len(), 1);
@@ -2966,6 +2974,7 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
29662974
assert_eq!(htlcs.len(), expected_paths.len()); // One per path.
29672975
assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::<u64>(), amount_msat);
29682976
assert_eq!(onion_fields.as_ref().unwrap().sender_custom_tlvs, sender_custom_tlvs);
2977+
assert_eq!(onion_fields.as_ref().unwrap().user_custom_data, user_custom_data);
29692978
check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs);
29702979
fwd_amt_msat = amount_msat;
29712980
}

lightning/src/ln/max_payment_path_len_tests.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ fn large_payment_metadata() {
7878
payment_secret: Some(payment_secret),
7979
payment_metadata: Some(payment_metadata.clone()),
8080
sender_custom_tlvs: Vec::new(),
81+
user_custom_data: None,
8182
};
8283
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();
8384
check_added_monitors!(nodes[0], 1);
@@ -126,6 +127,7 @@ fn large_payment_metadata() {
126127
payment_secret: Some(payment_secret_2),
127128
payment_metadata: Some(vec![42; max_metadata_len - INTERMED_PAYLOAD_LEN_ESTIMATE]),
128129
sender_custom_tlvs: Vec::new(),
130+
user_custom_data: None,
129131
};
130132
let mut route_params_0_2 = route_0_2.route_params.clone().unwrap();
131133
route_params_0_2.payment_params.max_path_length = 2;
@@ -190,7 +192,7 @@ fn one_hop_blinded_path_with_custom_tlv() {
190192
intro_node_blinding_point: Some(blinded_path.blinding_point()),
191193
keysend_preimage: None,
192194
invoice_request: None,
193-
sender_custom_tlvs: &Vec::new()
195+
sender_custom_tlvs: &Vec::new(),
194196
}.serialized_length();
195197
let max_custom_tlv_len = 1300
196198
- crate::util::ser::BigSize(CUSTOM_TLV_TYPE).serialized_length() // custom TLV type

lightning/src/ln/msgs.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,7 @@ mod fuzzy_internal_msgs {
18381838
pub keysend_preimage: Option<PaymentPreimage>,
18391839
pub invoice_request: Option<InvoiceRequest>,
18401840
pub sender_custom_tlvs: Vec<(u64, Vec<u8>)>,
1841+
pub user_custom_data: Option<Vec<u8>>,
18411842
}
18421843

18431844
pub enum InboundOnionPayload {
@@ -2796,7 +2797,7 @@ impl<'a> Writeable for OutboundOnionPayload<'a> {
27962797
},
27972798
Self::Receive {
27982799
ref payment_data, ref payment_metadata, ref keysend_preimage, sender_intended_htlc_amt_msat,
2799-
cltv_expiry_height, ref sender_custom_tlvs,
2800+
cltv_expiry_height, ref sender_custom_tlvs
28002801
} => {
28012802
// We need to update [`ln::outbound_payment::RecipientOnionFields::with_sender_custom_tlvs`]
28022803
// to reject any reserved types in the experimental range if new ones are ever
@@ -2819,7 +2820,7 @@ impl<'a> Writeable for OutboundOnionPayload<'a> {
28192820
},
28202821
Self::BlindedReceive {
28212822
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs,
2822-
intro_node_blinding_point, keysend_preimage, ref invoice_request, ref sender_custom_tlvs,
2823+
intro_node_blinding_point, keysend_preimage, ref invoice_request, ref sender_custom_tlvs
28232824
} => {
28242825
// We need to update [`ln::outbound_payment::RecipientOnionFields::with_sender_custom_tlvs`]
28252826
// to reject any reserved types in the experimental range if new ones are ever
@@ -2909,7 +2910,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
29092910
let mut total_msat = None;
29102911
let mut keysend_preimage: Option<PaymentPreimage> = None;
29112912
let mut invoice_request: Option<InvoiceRequest> = None;
2912-
let mut custom_tlvs = Vec::new();
2913+
let mut sender_custom_tlvs = Vec::new();
29132914

29142915
let tlv_len = BigSize::read(r)?;
29152916
let mut rd = FixedLengthReader::new(r, tlv_len.0);
@@ -2929,12 +2930,10 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
29292930
if msg_type < 1 << 16 { return Ok(false) }
29302931
let mut value = Vec::new();
29312932
msg_reader.read_to_limit(&mut value, u64::MAX)?;
2932-
custom_tlvs.push((msg_type, value));
2933+
sender_custom_tlvs.push((msg_type, value));
29332934
Ok(true)
29342935
});
29352936

2936-
let sender_custom_tlvs = custom_tlvs;
2937-
29382937
if amt.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
29392938
if intro_node_blinding_point.is_some() && update_add_blinding_point.is_some() {
29402939
return Err(DecodeError::InvalidValue)
@@ -2990,6 +2989,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
29902989
keysend_preimage,
29912990
invoice_request,
29922991
sender_custom_tlvs,
2992+
user_custom_data: None,
29932993
}))
29942994
},
29952995
}

lightning/src/ln/onion_payment.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -135,20 +135,20 @@ pub(super) fn create_recv_pending_htlc_info(
135135
counterparty_skimmed_fee_msat: Option<u64>, current_height: u32
136136
) -> Result<PendingHTLCInfo, InboundHTLCErr> {
137137
let (
138-
payment_data, keysend_preimage, sender_custom_tlvs, onion_amt_msat, onion_cltv_expiry,
138+
payment_data, keysend_preimage, sender_custom_tlvs, user_custom_data, onion_amt_msat, onion_cltv_expiry,
139139
payment_metadata, payment_context, requires_blinded_error, has_recipient_created_payment_secret,
140140
invoice_request
141141
) = match hop_data {
142142
msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
143143
payment_data, keysend_preimage, sender_custom_tlvs, sender_intended_htlc_amt_msat,
144144
cltv_expiry_height, payment_metadata, ..
145145
}) =>
146-
(payment_data, keysend_preimage, sender_custom_tlvs, sender_intended_htlc_amt_msat,
146+
(payment_data, keysend_preimage, sender_custom_tlvs, None, sender_intended_htlc_amt_msat,
147147
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None),
148148
msgs::InboundOnionPayload::BlindedReceive(msgs::InboundOnionBlindedReceivePayload {
149149
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
150150
intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage,
151-
sender_custom_tlvs, invoice_request
151+
sender_custom_tlvs, user_custom_data, invoice_request
152152
}) => {
153153
check_blinded_payment_constraints(
154154
sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints
@@ -161,7 +161,7 @@ pub(super) fn create_recv_pending_htlc_info(
161161
}
162162
})?;
163163
let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
164-
(Some(payment_data), keysend_preimage, sender_custom_tlvs,
164+
(Some(payment_data), keysend_preimage, sender_custom_tlvs, user_custom_data,
165165
sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
166166
intro_node_blinding_point.is_none(), true, invoice_request)
167167
}
@@ -235,6 +235,7 @@ pub(super) fn create_recv_pending_htlc_info(
235235
payment_metadata,
236236
incoming_cltv_expiry: onion_cltv_expiry,
237237
sender_custom_tlvs,
238+
user_custom_data,
238239
requires_blinded_error,
239240
has_recipient_created_payment_secret,
240241
payment_context,
@@ -248,6 +249,7 @@ pub(super) fn create_recv_pending_htlc_info(
248249
incoming_cltv_expiry: onion_cltv_expiry,
249250
phantom_shared_secret,
250251
sender_custom_tlvs,
252+
user_custom_data,
251253
requires_blinded_error,
252254
}
253255
} else {

0 commit comments

Comments
 (0)