99
1010//! Data structures and methods for constructing [`BlindedPaymentPath`]s to send a payment over.
1111
12+ use alloc:: collections:: BTreeMap ;
13+
1214use bitcoin:: secp256k1:: ecdh:: SharedSecret ;
1315use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 , SecretKey } ;
1416
@@ -29,8 +31,8 @@ use crate::types::features::BlindedHopFeatures;
2931use crate :: types:: payment:: PaymentSecret ;
3032use crate :: types:: routing:: RoutingFees ;
3133use crate :: util:: ser:: {
32- FixedLengthReader , HighZeroBytesDroppedBigSize , LengthReadableArgs , Readable , WithoutLength ,
33- Writeable , Writer ,
34+ BigSizeKeyedMap , FixedLengthReader , HighZeroBytesDroppedBigSize , LengthReadableArgs , Readable ,
35+ WithoutLength , Writeable , Writer ,
3436} ;
3537
3638#[ allow( unused_imports) ]
@@ -572,6 +574,20 @@ pub enum PaymentContext {
572574 /// [`Refund`]: crate::offers::refund::Refund
573575 Bolt12Refund ( Bolt12RefundContext ) ,
574576}
577+ impl PaymentContext {
578+ /// Returns the additional payment metadata stored alongside this payment context, if any.
579+ ///
580+ /// Payment metadata is stored as a map from a numeric key to an arbitrary byte array value.
581+ /// This allows for several types of metadata to be stored attached to a single payment. In the
582+ /// future some optional features of LDK may use some keys.
583+ pub fn payment_metadata ( & self ) -> Option < & BTreeMap < u64 , Vec < u8 > > > {
584+ match self {
585+ Self :: Bolt12Offer ( Bolt12OfferContext { payment_metadata, .. } )
586+ | Self :: AsyncBolt12Offer ( AsyncBolt12OfferContext { payment_metadata, .. } )
587+ | Self :: Bolt12Refund ( Bolt12RefundContext { payment_metadata, .. } ) => payment_metadata. as_ref ( ) ,
588+ }
589+ }
590+ }
575591
576592// Used when writing PaymentContext in Event::PaymentClaimable to avoid cloning.
577593pub ( crate ) enum PaymentContextRef < ' a > {
@@ -594,6 +610,27 @@ pub struct Bolt12OfferContext {
594610 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
595611 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
596612 pub invoice_request : InvoiceRequestFields ,
613+
614+ /// Additional data about this payment which is not used in LDK and can be used for any
615+ /// purpose.
616+ ///
617+ /// This is analogous to the BOLT 11 [`RecipientOnionFields::payment_metadata`] (which is
618+ /// provided to payers via [`Bolt11Invoice::payment_metadata`]) and can be used any time data
619+ /// needs to be "stored" by a payment recipient for their own internal use, provided back to
620+ /// them with the payment.
621+ ///
622+ /// Payment metadata is stored as a map from a numeric key to an arbitrary byte array value.
623+ /// This allows for several types of metadata to be stored attached to a single payment. In the
624+ /// future some optional features of LDK may use some keys. For the sake of conflict
625+ /// reduction, those features will attempt to use keys in the range 128-256.
626+ ///
627+ /// Note that because this is included in the payment onion, its size must be tightly
628+ /// constrained. More than a few hundred bytes and the payment will be entirely unpayable (with
629+ /// limited routing options as size increases).
630+ ///
631+ /// [`RecipientOnionFields::payment_metadata`]: crate::ln::outbound_payment::RecipientOnionFields::payment_metadata
632+ /// [`Bolt11Invoice::payment_metadata`]: lightning_invoice::Bolt11Invoice::payment_metadata
633+ pub payment_metadata : Option < BTreeMap < u64 , Vec < u8 > > > ,
597634}
598635
599636/// The context of a payment made for a static invoice requested from a BOLT 12 [`Offer`].
@@ -606,13 +643,55 @@ pub struct AsyncBolt12OfferContext {
606643 ///
607644 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
608645 pub offer_nonce : Nonce ,
646+
647+ /// Additional data about this payment which is not used in LDK and can be used for any
648+ /// purpose.
649+ ///
650+ /// This is analogous to the BOLT 11 [`RecipientOnionFields::payment_metadata`] (which is
651+ /// provided to payers via [`Bolt11Invoice::payment_metadata`]) and can be used any time data
652+ /// needs to be "stored" by a payment recipient for their own internal use, provided back to
653+ /// them with the payment.
654+ ///
655+ /// Payment metadata is stored as a map from a numeric key to an arbitrary byte array value.
656+ /// This allows for several types of metadata to be stored attached to a single payment. In the
657+ /// future some optional features of LDK may use some keys. For the sake of conflict
658+ /// reduction, those features will attempt to use keys in the range 128-256.
659+ ///
660+ /// Note that because this is included in the payment onion, its size must be tightly
661+ /// constrained. More than a few hundred bytes and the payment will be entirely unpayable (with
662+ /// limited routing options as size increases).
663+ ///
664+ /// [`RecipientOnionFields::payment_metadata`]: crate::ln::outbound_payment::RecipientOnionFields::payment_metadata
665+ /// [`Bolt11Invoice::payment_metadata`]: lightning_invoice::Bolt11Invoice::payment_metadata
666+ pub payment_metadata : Option < BTreeMap < u64 , Vec < u8 > > > ,
609667}
610668
611669/// The context of a payment made for an invoice sent for a BOLT 12 [`Refund`].
612670///
613671/// [`Refund`]: crate::offers::refund::Refund
614672#[ derive( Clone , Debug , Eq , PartialEq ) ]
615- pub struct Bolt12RefundContext { }
673+ pub struct Bolt12RefundContext {
674+ /// Additional data about this payment which is not used in LDK and can be used for any
675+ /// purpose.
676+ ///
677+ /// This is analogous to the BOLT 11 [`RecipientOnionFields::payment_metadata`] (which is
678+ /// provided to payers via [`Bolt11Invoice::payment_metadata`]) and can be used any time data
679+ /// needs to be "stored" by a payment recipient for their own internal use, provided back to
680+ /// them with the payment.
681+ ///
682+ /// Payment metadata is stored as a map from a numeric key to an arbitrary byte array value.
683+ /// This allows for several types of metadata to be stored attached to a single payment. In the
684+ /// future some optional features of LDK may use some keys. For the sake of conflict
685+ /// reduction, those features will attempt to use keys in the range 128-256.
686+ ///
687+ /// Note that because this is included in the payment onion, its size must be tightly
688+ /// constrained. More than a few hundred bytes and the payment will be entirely unpayable (with
689+ /// limited routing options as size increases).
690+ ///
691+ /// [`RecipientOnionFields::payment_metadata`]: crate::ln::outbound_payment::RecipientOnionFields::payment_metadata
692+ /// [`Bolt11Invoice::payment_metadata`]: lightning_invoice::Bolt11Invoice::payment_metadata
693+ pub payment_metadata : Option < BTreeMap < u64 , Vec < u8 > > > ,
694+ }
616695
617696impl TryFrom < CounterpartyForwardingInfo > for PaymentRelay {
618697 type Error = ( ) ;
@@ -1031,14 +1110,18 @@ impl<'a> Writeable for PaymentContextRef<'a> {
10311110
10321111impl_writeable_tlv_based ! ( Bolt12OfferContext , {
10331112 ( 0 , offer_id, required) ,
1113+ ( 1 , payment_metadata, ( option, encoding: ( BTreeMap <u64 , Vec <u8 >>, BigSizeKeyedMap ) ) ) ,
10341114 ( 2 , invoice_request, required) ,
10351115} ) ;
10361116
10371117impl_writeable_tlv_based ! ( AsyncBolt12OfferContext , {
10381118 ( 0 , offer_nonce, required) ,
1119+ ( 1 , payment_metadata, ( option, encoding: ( BTreeMap <u64 , Vec <u8 >>, BigSizeKeyedMap ) ) ) ,
10391120} ) ;
10401121
1041- impl_writeable_tlv_based ! ( Bolt12RefundContext , { } ) ;
1122+ impl_writeable_tlv_based ! ( Bolt12RefundContext , {
1123+ ( 1 , payment_metadata, ( option, encoding: ( BTreeMap <u64 , Vec <u8 >>, BigSizeKeyedMap ) ) ) ,
1124+ } ) ;
10421125
10431126#[ cfg( test) ]
10441127mod tests {
@@ -1097,7 +1180,9 @@ mod tests {
10971180 let recv_tlvs = ReceiveTlvs {
10981181 payment_secret : PaymentSecret ( [ 0 ; 32 ] ) ,
10991182 payment_constraints : PaymentConstraints { max_cltv_expiry : 0 , htlc_minimum_msat : 1 } ,
1100- payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
1183+ payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext {
1184+ payment_metadata : None ,
1185+ } ) ,
11011186 } ;
11021187 let htlc_maximum_msat = 100_000 ;
11031188 let blinded_payinfo =
@@ -1115,7 +1200,9 @@ mod tests {
11151200 let recv_tlvs = ReceiveTlvs {
11161201 payment_secret : PaymentSecret ( [ 0 ; 32 ] ) ,
11171202 payment_constraints : PaymentConstraints { max_cltv_expiry : 0 , htlc_minimum_msat : 1 } ,
1118- payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
1203+ payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext {
1204+ payment_metadata : None ,
1205+ } ) ,
11191206 } ;
11201207 let blinded_payinfo = super :: compute_payinfo :: < ForwardTlvs > (
11211208 & [ ] ,
@@ -1178,7 +1265,9 @@ mod tests {
11781265 let recv_tlvs = ReceiveTlvs {
11791266 payment_secret : PaymentSecret ( [ 0 ; 32 ] ) ,
11801267 payment_constraints : PaymentConstraints { max_cltv_expiry : 0 , htlc_minimum_msat : 3 } ,
1181- payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
1268+ payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext {
1269+ payment_metadata : None ,
1270+ } ) ,
11821271 } ;
11831272 let htlc_maximum_msat = 100_000 ;
11841273 let blinded_payinfo = super :: compute_payinfo (
@@ -1238,7 +1327,9 @@ mod tests {
12381327 let recv_tlvs = ReceiveTlvs {
12391328 payment_secret : PaymentSecret ( [ 0 ; 32 ] ) ,
12401329 payment_constraints : PaymentConstraints { max_cltv_expiry : 0 , htlc_minimum_msat : 1 } ,
1241- payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
1330+ payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext {
1331+ payment_metadata : None ,
1332+ } ) ,
12421333 } ;
12431334 let htlc_minimum_msat = 3798 ;
12441335 assert ! ( super :: compute_payinfo(
@@ -1309,7 +1400,9 @@ mod tests {
13091400 let recv_tlvs = ReceiveTlvs {
13101401 payment_secret : PaymentSecret ( [ 0 ; 32 ] ) ,
13111402 payment_constraints : PaymentConstraints { max_cltv_expiry : 0 , htlc_minimum_msat : 1 } ,
1312- payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext { } ) ,
1403+ payment_context : PaymentContext :: Bolt12Refund ( Bolt12RefundContext {
1404+ payment_metadata : None ,
1405+ } ) ,
13131406 } ;
13141407
13151408 let blinded_payinfo = super :: compute_payinfo (
0 commit comments