Skip to content

Commit ab4527b

Browse files
committed
Add Custom TLVs for payment::ReceiveTlvs
- Building on the previous commit, this update allows users to include their own custom TLVs within the reply path of a sent onion message. - With this, users can attach custom data to the message, which will be returned in the response, providing more flexibility for custom use cases.
1 parent a267555 commit ab4527b

File tree

7 files changed

+37
-6
lines changed

7 files changed

+37
-6
lines changed

fuzz/src/invoice_request_deser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
103103
htlc_minimum_msat: 1,
104104
},
105105
payment_context,
106+
custom_data: None,
106107
};
107108
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
108109
let intermediate_nodes = [PaymentForwardNode {

fuzz/src/refund_deser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
8080
htlc_minimum_msat: 1,
8181
},
8282
payment_context,
83+
custom_data: None,
8384
};
8485
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
8586
let intermediate_nodes = [PaymentForwardNode {

lightning/src/blinded_path/payment.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@ pub struct UnauthenticatedReceiveTlvs {
283283
pub payment_constraints: PaymentConstraints,
284284
/// Context for the receiver of this payment.
285285
pub payment_context: PaymentContext,
286+
/// Custom data set by the user. And is returned back when the blinded path is used.
287+
///
288+
/// ## Note on Forward Compatibility:
289+
/// Users can encode any kind of data into the `Vec<u8>` bytes here. However, they should ensure
290+
/// that the data is structured in a forward-compatible manner. This is especially important as
291+
/// `ReceiveTlvs` created in one version of the software may still appear in payments received
292+
/// shortly after a software upgrade. Proper forward compatibility helps prevent data loss or
293+
/// misinterpretation in future versions.
294+
pub custom_data: Option<Vec<u8>>,
286295
}
287296

288297
impl UnauthenticatedReceiveTlvs {
@@ -444,6 +453,7 @@ impl Writeable for ReceiveTlvs {
444453
(65536, self.tlvs.payment_secret, required),
445454
(65537, self.tlvs.payment_context, required),
446455
(65539, self.authentication, required),
456+
(65541, self.tlvs.custom_data, required)
447457
});
448458
Ok(())
449459
}
@@ -455,6 +465,7 @@ impl Writeable for UnauthenticatedReceiveTlvs {
455465
(12, self.payment_constraints, required),
456466
(65536, self.payment_secret, required),
457467
(65537, self.payment_context, required),
468+
(65541, self.custom_data, (default_value, Vec::new())),
458469
});
459470
Ok(())
460471
}
@@ -483,6 +494,7 @@ impl Readable for BlindedPaymentTlvs {
483494
(65536, payment_secret, option),
484495
(65537, payment_context, option),
485496
(65539, authentication, option),
497+
(65541, custom_data, option)
486498
});
487499
let _padding: Option<utils::Padding> = _padding;
488500

@@ -504,6 +516,7 @@ impl Readable for BlindedPaymentTlvs {
504516
payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?,
505517
payment_constraints: payment_constraints.0.unwrap(),
506518
payment_context: payment_context.ok_or(DecodeError::InvalidValue)?,
519+
custom_data: custom_data.ok_or(DecodeError::InvalidValue)?,
507520
},
508521
authentication: authentication.ok_or(DecodeError::InvalidValue)?,
509522
}))
@@ -730,6 +743,7 @@ mod tests {
730743
htlc_minimum_msat: 1,
731744
},
732745
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
746+
custom_data: None,
733747
};
734748
let htlc_maximum_msat = 100_000;
735749
let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat, 12).unwrap();
@@ -749,6 +763,7 @@ mod tests {
749763
htlc_minimum_msat: 1,
750764
},
751765
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
766+
custom_data: None,
752767
};
753768
let blinded_payinfo = super::compute_payinfo(&[], &recv_tlvs, 4242, TEST_FINAL_CLTV as u16).unwrap();
754769
assert_eq!(blinded_payinfo.fee_base_msat, 0);
@@ -805,6 +820,7 @@ mod tests {
805820
htlc_minimum_msat: 3,
806821
},
807822
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
823+
custom_data: None,
808824
};
809825
let htlc_maximum_msat = 100_000;
810826
let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat, TEST_FINAL_CLTV as u16).unwrap();
@@ -858,6 +874,7 @@ mod tests {
858874
htlc_minimum_msat: 1,
859875
},
860876
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
877+
custom_data: None,
861878
};
862879
let htlc_minimum_msat = 3798;
863880
assert!(super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_minimum_msat - 1, TEST_FINAL_CLTV as u16).is_err());
@@ -915,6 +932,7 @@ mod tests {
915932
htlc_minimum_msat: 1,
916933
},
917934
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
935+
custom_data: None,
918936
};
919937

920938
let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, 10_000, TEST_FINAL_CLTV as u16).unwrap();

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub fn blinded_payment_path(
7676
intro_node_min_htlc_opt.unwrap_or_else(|| channel_upds.last().unwrap().htlc_minimum_msat),
7777
},
7878
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
79+
custom_data: None,
7980
};
8081

8182
let nonce = Nonce([42u8; 16]);
@@ -127,6 +128,7 @@ fn do_one_hop_blinded_path(success: bool) {
127128
htlc_minimum_msat: chan_upd.htlc_minimum_msat,
128129
},
129130
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
131+
custom_data: None,
130132
};
131133
let nonce = Nonce([42u8; 16]);
132134
let expanded_key = chanmon_cfgs[1].keys_manager.get_inbound_payment_key();
@@ -175,6 +177,7 @@ fn mpp_to_one_hop_blinded_path() {
175177
htlc_minimum_msat: chan_upd_1_3.htlc_minimum_msat,
176178
},
177179
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
180+
custom_data: None,
178181
};
179182
let nonce = Nonce([42u8; 16]);
180183
let expanded_key = chanmon_cfgs[3].keys_manager.get_inbound_payment_key();
@@ -837,6 +840,8 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
837840
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2],
838841
&chanmon_cfgs[2].keys_manager);
839842

843+
route_params.payment_params.max_path_length = 18;
844+
840845
let route = if check == ReceiveCheckFail::ProcessPendingHTLCsCheck {
841846
let mut route = get_route(&nodes[0], &route_params).unwrap();
842847
// Set the final CLTV expiry too low to trigger the failure in process_pending_htlc_forwards.
@@ -1240,6 +1245,7 @@ fn sender_custom_tlvs_to_blinded_path() {
12401245
htlc_minimum_msat: chan_upd.htlc_minimum_msat,
12411246
},
12421247
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
1248+
custom_data: None,
12431249
};
12441250
let nonce = Nonce([42u8; 16]);
12451251
let expanded_key = chanmon_cfgs[1].keys_manager.get_inbound_payment_key();
@@ -1294,6 +1300,7 @@ fn fails_receive_tlvs_authentication() {
12941300
htlc_minimum_msat: chan_upd.htlc_minimum_msat,
12951301
},
12961302
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
1303+
custom_data: None,
12971304
};
12981305
let nonce = Nonce([42u8; 16]);
12991306
let expanded_key = chanmon_cfgs[1].keys_manager.get_inbound_payment_key();
@@ -1325,6 +1332,7 @@ fn fails_receive_tlvs_authentication() {
13251332
htlc_minimum_msat: chan_upd.htlc_minimum_msat,
13261333
},
13271334
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
1335+
custom_data: None,
13281336
};
13291337
let nonce = Nonce([43u8; 16]);
13301338
let mut payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);

lightning/src/ln/channelmanager.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10027,7 +10027,7 @@ where
1002710027
).map_err(|()| Bolt12SemanticError::InvalidAmount)?;
1002810028

1002910029
let payment_paths = self.create_blinded_payment_paths(
10030-
amount_msat, payment_secret, payment_context, relative_expiry_secs
10030+
amount_msat, payment_secret, payment_context, None, relative_expiry_secs
1003110031
).map_err(|()| Bolt12SemanticError::MissingPaths)?;
1003210032

1003310033
let nonce = Nonce::from_entropy_source(entropy);
@@ -10243,7 +10243,7 @@ where
1024310243
Ok((payment_hash, payment_secret)) => {
1024410244
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
1024510245
let payment_paths = self.create_blinded_payment_paths(
10246-
Some(amount_msats), payment_secret, payment_context, relative_expiry,
10246+
Some(amount_msats), payment_secret, payment_context, None, relative_expiry,
1024710247
)
1024810248
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
1024910249

@@ -10560,7 +10560,7 @@ where
1056010560
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
1056110561
/// [`Router::create_blinded_payment_paths`].
1056210562
fn create_blinded_payment_paths(
10563-
&self, amount_msats: Option<u64>, payment_secret: PaymentSecret, payment_context: PaymentContext,
10563+
&self, amount_msats: Option<u64>, payment_secret: PaymentSecret, payment_context: PaymentContext, custom_data: Option<Vec<u8>>,
1056410564
relative_expiry_seconds: u32,
1056510565
) -> Result<Vec<BlindedPaymentPath>, ()> {
1056610566
let expanded_key = &self.inbound_payment_key;
@@ -10584,6 +10584,7 @@ where
1058410584
htlc_minimum_msat: 1,
1058510585
},
1058610586
payment_context,
10587+
custom_data,
1058710588
};
1058810589
let nonce = Nonce::from_entropy_source(entropy);
1058910590
let payee_tlvs = payee_tlvs.authenticate(nonce, expanded_key);
@@ -12121,7 +12122,7 @@ where
1212112122
invoice_request: invoice_request.fields(),
1212212123
});
1212312124
let payment_paths = match self.create_blinded_payment_paths(
12124-
Some(amount_msats), payment_secret, payment_context, relative_expiry
12125+
Some(amount_msats), payment_secret, payment_context, None, relative_expiry
1212512126
) {
1212612127
Ok(payment_paths) => payment_paths,
1212712128
Err(()) => {

lightning/src/ln/max_payment_path_len_tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ fn one_hop_blinded_path_with_custom_tlv() {
168168
htlc_minimum_msat: chan_upd_1_2.htlc_minimum_msat,
169169
},
170170
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
171+
custom_data: None,
171172
};
172173
let nonce = Nonce([42u8; 16]);
173174
let expanded_key = chanmon_cfgs[2].keys_manager.get_inbound_payment_key();

lightning/src/ln/msgs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,6 +2909,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
29092909
next_blinding_override,
29102910
})
29112911
},
2912+
// Note: The custom data in the receive tlvs is not used here.
29122913
ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(receive_tlvs) } => {
29132914
let ReceiveTlvs { tlvs, authentication: (hmac, nonce) } = receive_tlvs;
29142915
let expanded_key = node_signer.get_inbound_payment_key();
@@ -2917,7 +2918,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
29172918
}
29182919

29192920
let UnauthenticatedReceiveTlvs {
2920-
payment_secret, payment_constraints, payment_context,
2921+
payment_secret, payment_constraints, payment_context, custom_data
29212922
} = tlvs;
29222923
if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
29232924
Ok(Self::BlindedReceive {
@@ -2930,7 +2931,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
29302931
intro_node_blinding_point,
29312932
keysend_preimage,
29322933
sender_custom_tlvs,
2933-
user_custom_data: None,
2934+
user_custom_data: custom_data,
29342935
})
29352936
},
29362937
}

0 commit comments

Comments
 (0)