Skip to content

Commit 2ea54b8

Browse files
committed
Introduce custom TLVs in pay_for_bolt11_invoice
Custom TLVs let the payer attach arbitrary data to the onion packet, enabling everything from richer metadata to custom authentication on the payee's side. Until now, this flexibility existed only through `send_payment`. The simpler `pay_for_bolt11_invoice` API offered no way to pass custom TLVs, limiting its usefulness in flows that rely on additional context. This commit adds custom TLV support to `pay_for_bolt11_invoice`, bringing it to feature parity.
1 parent de384ff commit 2ea54b8

File tree

6 files changed

+34
-5
lines changed

6 files changed

+34
-5
lines changed

lightning-liquidity/tests/lsps2_integration_tests.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,7 @@ fn client_trusts_lsp_end_to_end_test() {
12211221
&invoice,
12221222
PaymentId(invoice.payment_hash().to_byte_array()),
12231223
None,
1224+
vec![],
12241225
Default::default(),
12251226
Retry::Attempts(3),
12261227
)
@@ -1694,6 +1695,7 @@ fn late_payment_forwarded_and_safe_after_force_close_does_not_broadcast() {
16941695
&invoice,
16951696
PaymentId(invoice.payment_hash().to_byte_array()),
16961697
None,
1698+
vec![],
16971699
Default::default(),
16981700
Retry::Attempts(3),
16991701
)
@@ -1885,6 +1887,7 @@ fn htlc_timeout_before_client_claim_results_in_handling_failed() {
18851887
&invoice,
18861888
PaymentId(invoice.payment_hash().to_byte_array()),
18871889
None,
1890+
vec![],
18881891
Default::default(),
18891892
Retry::Attempts(3),
18901893
)
@@ -2222,6 +2225,7 @@ fn client_trusts_lsp_partial_fee_does_not_trigger_broadcast() {
22222225
&invoice,
22232226
PaymentId(invoice.payment_hash().to_byte_array()),
22242227
None,
2228+
vec![],
22252229
Default::default(),
22262230
Retry::Attempts(3),
22272231
)

lightning/src/ln/bolt11_payment_tests.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ fn payment_metadata_end_to_end_for_invoice_with_amount() {
5555
&invoice,
5656
PaymentId(payment_hash.0),
5757
Some(100),
58+
vec![],
5859
RouteParametersConfig::default(),
5960
Retry::Attempts(0),
6061
) {
@@ -68,6 +69,7 @@ fn payment_metadata_end_to_end_for_invoice_with_amount() {
6869
&invoice,
6970
PaymentId(payment_hash.0),
7071
None,
72+
vec![],
7173
RouteParametersConfig::default(),
7274
Retry::Attempts(0),
7375
)
@@ -123,6 +125,7 @@ fn payment_metadata_end_to_end_for_invoice_with_no_amount() {
123125
&invoice,
124126
PaymentId(payment_hash.0),
125127
None,
128+
vec![],
126129
RouteParametersConfig::default(),
127130
Retry::Attempts(0),
128131
) {
@@ -136,6 +139,7 @@ fn payment_metadata_end_to_end_for_invoice_with_no_amount() {
136139
&invoice,
137140
PaymentId(payment_hash.0),
138141
Some(50_000),
142+
vec![],
139143
RouteParametersConfig::default(),
140144
Retry::Attempts(0),
141145
)

lightning/src/ln/channelmanager.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,8 +2272,11 @@ where
22722272
/// # let channel_manager = channel_manager.get_cm();
22732273
/// # let payment_id = PaymentId([42; 32]);
22742274
/// # let payment_hash = PaymentHash((*invoice.payment_hash()).to_byte_array());
2275+
/// # let custom_tlvs = vec![
2276+
/// # (343493u64, b"hello".to_vec()),
2277+
/// # ];
22752278
/// match channel_manager.pay_for_bolt11_invoice(
2276-
/// invoice, payment_id, None, route_params_config, retry
2279+
/// invoice, payment_id, None, custom_tlvs, route_params_config, retry
22772280
/// ) {
22782281
/// Ok(()) => println!("Sending payment with hash {}", payment_hash),
22792282
/// Err(e) => println!("Failed sending payment with hash {}: {:?}", payment_hash, e),
@@ -5542,14 +5545,16 @@ where
55425545
/// To use default settings, call the function with [`RouteParametersConfig::default`].
55435546
pub fn pay_for_bolt11_invoice(
55445547
&self, invoice: &Bolt11Invoice, payment_id: PaymentId, amount_msats: Option<u64>,
5545-
route_params_config: RouteParametersConfig, retry_strategy: Retry,
5548+
custom_tlvs: Vec<(u64, Vec<u8>)>, route_params_config: RouteParametersConfig,
5549+
retry_strategy: Retry,
55465550
) -> Result<(), Bolt11PaymentError> {
55475551
let best_block_height = self.best_block.read().unwrap().height;
55485552
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
55495553
self.pending_outbound_payments.pay_for_bolt11_invoice(
55505554
invoice,
55515555
payment_id,
55525556
amount_msats,
5557+
custom_tlvs,
55535558
route_params_config,
55545559
retry_strategy,
55555560
&self.router,

lightning/src/ln/invoice_utils.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,14 @@ mod test {
710710
let retry = Retry::Attempts(0);
711711
nodes[0]
712712
.node
713-
.pay_for_bolt11_invoice(&invoice, PaymentId([42; 32]), None, Default::default(), retry)
713+
.pay_for_bolt11_invoice(
714+
&invoice,
715+
PaymentId([42; 32]),
716+
None,
717+
vec![],
718+
Default::default(),
719+
retry,
720+
)
714721
.unwrap();
715722
check_added_monitors(&nodes[0], 1);
716723

lightning/src/ln/outbound_payment.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,8 @@ pub enum RetryableSendFailure {
543543
///
544544
/// [`BlindedPaymentPath`]: crate::blinded_path::payment::BlindedPaymentPath
545545
OnionPacketSizeExceeded,
546+
/// The provided [`RecipientOnionFields::custom_tlvs`] are of invalid range
547+
InvalidCustomTlvs,
546548
}
547549

548550
/// If a payment fails to send to a route, it can be in one of several states. This enum is returned
@@ -919,6 +921,7 @@ where
919921
pub(super) fn pay_for_bolt11_invoice<R: Deref, ES: Deref, NS: Deref, IH, SP>(
920922
&self, invoice: &Bolt11Invoice, payment_id: PaymentId,
921923
amount_msats: Option<u64>,
924+
custom_tlvs: Vec<(u64, Vec<u8>)>,
922925
route_params_config: RouteParametersConfig,
923926
retry_strategy: Retry,
924927
router: &R,
@@ -942,7 +945,9 @@ where
942945
(None, None) => return Err(Bolt11PaymentError::InvalidAmount),
943946
};
944947

945-
let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret());
948+
let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret())
949+
.with_custom_tlvs(custom_tlvs)
950+
.map_err(|_| Bolt11PaymentError::SendingFailed(RetryableSendFailure::InvalidCustomTlvs))?;
946951
recipient_onion.payment_metadata = invoice.payment_metadata().map(|v| v.clone());
947952

948953
let payment_params = PaymentParameters::from_bolt11_invoice(invoice)
@@ -1061,6 +1066,7 @@ where
10611066
RetryableSendFailure::RouteNotFound => PaymentFailureReason::RouteNotFound,
10621067
RetryableSendFailure::DuplicatePayment => PaymentFailureReason::UnexpectedError,
10631068
RetryableSendFailure::OnionPacketSizeExceeded => PaymentFailureReason::UnexpectedError,
1069+
RetryableSendFailure::InvalidCustomTlvs => PaymentFailureReason::UnexpectedError,
10641070
};
10651071
self.abandon_payment(payment_id, reason, pending_events);
10661072
return Err(Bolt12PaymentError::SendingFailed(e));

lightning/src/ln/payment_tests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5400,7 +5400,10 @@ fn max_out_mpp_path() {
54005400

54015401
let id = PaymentId([42; 32]);
54025402
let retry = Retry::Attempts(0);
5403-
nodes[0].node.pay_for_bolt11_invoice(&invoice, id, None, route_params_cfg, retry).unwrap();
5403+
nodes[0]
5404+
.node
5405+
.pay_for_bolt11_invoice(&invoice, id, None, vec![], route_params_cfg, retry)
5406+
.unwrap();
54045407

54055408
assert!(nodes[0].node.list_recent_payments().len() == 1);
54065409
check_added_monitors(&nodes[0], 2); // one monitor update per MPP part

0 commit comments

Comments
 (0)