@@ -12,6 +12,8 @@ use crate::ln::channelmanager::CounterpartyForwardingInfo;
12
12
use crate :: ln:: features:: BlindedHopFeatures ;
13
13
use crate :: ln:: msgs:: DecodeError ;
14
14
use crate :: offers:: invoice:: BlindedPayInfo ;
15
+ use crate :: offers:: invoice_request:: InvoiceRequestFields ;
16
+ use crate :: offers:: offer:: OfferId ;
15
17
use crate :: util:: ser:: { HighZeroBytesDroppedBigSize , Readable , Writeable , Writer } ;
16
18
17
19
#[ allow( unused_imports) ]
@@ -53,6 +55,8 @@ pub struct ReceiveTlvs {
53
55
pub payment_secret : PaymentSecret ,
54
56
/// Constraints for the receiver of this payment.
55
57
pub payment_constraints : PaymentConstraints ,
58
+ /// Context for the receiver of this payment.
59
+ pub payment_context : PaymentContext ,
56
60
}
57
61
58
62
/// Data to construct a [`BlindedHop`] for sending a payment over.
@@ -97,6 +101,66 @@ pub struct PaymentConstraints {
97
101
pub htlc_minimum_msat : u64 ,
98
102
}
99
103
104
+ /// The context of an inbound payment, which is included in a [`BlindedPath`] via [`ReceiveTlvs`]
105
+ /// and surfaced in [`PaymentPurpose`].
106
+ ///
107
+ /// [`BlindedPath`]: crate::blinded_path::BlindedPath
108
+ /// [`PaymentPurpose`]: crate::events::PaymentPurpose
109
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
110
+ pub enum PaymentContext {
111
+ /// The payment context was unknown.
112
+ Unknown ( UnknownPaymentContext ) ,
113
+
114
+ /// The payment was made for an invoice requested from a BOLT 12 [`Offer`].
115
+ ///
116
+ /// [`Offer`]: crate::offers::offer::Offer
117
+ Bolt12Offer ( Bolt12OfferContext ) ,
118
+
119
+ /// The payment was made for an invoice sent for a BOLT 12 [`Refund`].
120
+ ///
121
+ /// [`Refund`]: crate::offers::refund::Refund
122
+ Bolt12Refund ( Bolt12RefundContext ) ,
123
+ }
124
+
125
+ // Used when writing PaymentContext in Event::PaymentClaimable to avoid cloning.
126
+ pub ( crate ) enum PaymentContextRef < ' a > {
127
+ Bolt12Offer ( & ' a Bolt12OfferContext ) ,
128
+ Bolt12Refund ( & ' a Bolt12RefundContext ) ,
129
+ }
130
+
131
+ /// An unknown payment context.
132
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
133
+ pub struct UnknownPaymentContext ( ( ) ) ;
134
+
135
+ /// The context of a payment made for an invoice requested from a BOLT 12 [`Offer`].
136
+ ///
137
+ /// [`Offer`]: crate::offers::offer::Offer
138
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
139
+ pub struct Bolt12OfferContext {
140
+ /// The identifier of the [`Offer`].
141
+ ///
142
+ /// [`Offer`]: crate::offers::offer::Offer
143
+ pub offer_id : OfferId ,
144
+
145
+ /// Fields from an [`InvoiceRequest`] sent for a [`Bolt12Invoice`].
146
+ ///
147
+ /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
148
+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
149
+ pub invoice_request : InvoiceRequestFields ,
150
+ }
151
+
152
+ /// The context of a payment made for an invoice sent for a BOLT 12 [`Refund`].
153
+ ///
154
+ /// [`Refund`]: crate::offers::refund::Refund
155
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
156
+ pub struct Bolt12RefundContext { }
157
+
158
+ impl PaymentContext {
159
+ pub ( crate ) fn unknown ( ) -> Self {
160
+ PaymentContext :: Unknown ( UnknownPaymentContext ( ( ) ) )
161
+ }
162
+ }
163
+
100
164
impl TryFrom < CounterpartyForwardingInfo > for PaymentRelay {
101
165
type Error = ( ) ;
102
166
@@ -137,7 +201,8 @@ impl Writeable for ReceiveTlvs {
137
201
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
138
202
encode_tlv_stream ! ( w, {
139
203
( 12 , self . payment_constraints, required) ,
140
- ( 65536 , self . payment_secret, required)
204
+ ( 65536 , self . payment_secret, required) ,
205
+ ( 65537 , self . payment_context, required)
141
206
} ) ;
142
207
Ok ( ( ) )
143
208
}
@@ -163,11 +228,14 @@ impl Readable for BlindedPaymentTlvs {
163
228
( 12 , payment_constraints, required) ,
164
229
( 14 , features, option) ,
165
230
( 65536 , payment_secret, option) ,
231
+ ( 65537 , payment_context, ( default_value, PaymentContext :: unknown( ) ) ) ,
166
232
} ) ;
167
233
let _padding: Option < utils:: Padding > = _padding;
168
234
169
235
if let Some ( short_channel_id) = scid {
170
- if payment_secret. is_some ( ) { return Err ( DecodeError :: InvalidValue ) }
236
+ if payment_secret. is_some ( ) {
237
+ return Err ( DecodeError :: InvalidValue )
238
+ }
171
239
Ok ( BlindedPaymentTlvs :: Forward ( ForwardTlvs {
172
240
short_channel_id,
173
241
payment_relay : payment_relay. ok_or ( DecodeError :: InvalidValue ) ?,
@@ -179,6 +247,7 @@ impl Readable for BlindedPaymentTlvs {
179
247
Ok ( BlindedPaymentTlvs :: Receive ( ReceiveTlvs {
180
248
payment_secret : payment_secret. ok_or ( DecodeError :: InvalidValue ) ?,
181
249
payment_constraints : payment_constraints. 0 . unwrap ( ) ,
250
+ payment_context : payment_context. 0 . unwrap ( ) ,
182
251
} ) )
183
252
}
184
253
}
@@ -309,10 +378,53 @@ impl Readable for PaymentConstraints {
309
378
}
310
379
}
311
380
381
+ impl_writeable_tlv_based_enum ! ( PaymentContext ,
382
+ ;
383
+ ( 0 , Unknown ) ,
384
+ ( 1 , Bolt12Offer ) ,
385
+ ( 2 , Bolt12Refund ) ,
386
+ ) ;
387
+
388
+ impl < ' a > Writeable for PaymentContextRef < ' a > {
389
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
390
+ match self {
391
+ PaymentContextRef :: Bolt12Offer ( context) => {
392
+ 1u8 . write ( w) ?;
393
+ context. write ( w) ?;
394
+ } ,
395
+ PaymentContextRef :: Bolt12Refund ( context) => {
396
+ 2u8 . write ( w) ?;
397
+ context. write ( w) ?;
398
+ } ,
399
+ }
400
+
401
+ Ok ( ( ) )
402
+ }
403
+ }
404
+
405
+ impl Writeable for UnknownPaymentContext {
406
+ fn write < W : Writer > ( & self , _w : & mut W ) -> Result < ( ) , io:: Error > {
407
+ Ok ( ( ) )
408
+ }
409
+ }
410
+
411
+ impl Readable for UnknownPaymentContext {
412
+ fn read < R : io:: Read > ( _r : & mut R ) -> Result < Self , DecodeError > {
413
+ Ok ( UnknownPaymentContext ( ( ) ) )
414
+ }
415
+ }
416
+
417
+ impl_writeable_tlv_based ! ( Bolt12OfferContext , {
418
+ ( 0 , offer_id, required) ,
419
+ ( 2 , invoice_request, required) ,
420
+ } ) ;
421
+
422
+ impl_writeable_tlv_based ! ( Bolt12RefundContext , { } ) ;
423
+
312
424
#[ cfg( test) ]
313
425
mod tests {
314
426
use bitcoin:: secp256k1:: PublicKey ;
315
- use crate :: blinded_path:: payment:: { ForwardNode , ForwardTlvs , ReceiveTlvs , PaymentConstraints , PaymentRelay } ;
427
+ use crate :: blinded_path:: payment:: { ForwardNode , ForwardTlvs , ReceiveTlvs , PaymentConstraints , PaymentContext , PaymentRelay } ;
316
428
use crate :: ln:: PaymentSecret ;
317
429
use crate :: ln:: features:: BlindedHopFeatures ;
318
430
use crate :: ln:: functional_test_utils:: TEST_FINAL_CLTV ;
@@ -361,6 +473,7 @@ mod tests {
361
473
max_cltv_expiry : 0 ,
362
474
htlc_minimum_msat : 1 ,
363
475
} ,
476
+ payment_context : PaymentContext :: unknown ( ) ,
364
477
} ;
365
478
let htlc_maximum_msat = 100_000 ;
366
479
let blinded_payinfo = super :: compute_payinfo ( & intermediate_nodes[ ..] , & recv_tlvs, htlc_maximum_msat, 12 ) . unwrap ( ) ;
@@ -379,6 +492,7 @@ mod tests {
379
492
max_cltv_expiry : 0 ,
380
493
htlc_minimum_msat : 1 ,
381
494
} ,
495
+ payment_context : PaymentContext :: unknown ( ) ,
382
496
} ;
383
497
let blinded_payinfo = super :: compute_payinfo ( & [ ] , & recv_tlvs, 4242 , TEST_FINAL_CLTV as u16 ) . unwrap ( ) ;
384
498
assert_eq ! ( blinded_payinfo. fee_base_msat, 0 ) ;
@@ -432,6 +546,7 @@ mod tests {
432
546
max_cltv_expiry : 0 ,
433
547
htlc_minimum_msat : 3 ,
434
548
} ,
549
+ payment_context : PaymentContext :: unknown ( ) ,
435
550
} ;
436
551
let htlc_maximum_msat = 100_000 ;
437
552
let blinded_payinfo = super :: compute_payinfo ( & intermediate_nodes[ ..] , & recv_tlvs, htlc_maximum_msat, TEST_FINAL_CLTV as u16 ) . unwrap ( ) ;
@@ -482,6 +597,7 @@ mod tests {
482
597
max_cltv_expiry : 0 ,
483
598
htlc_minimum_msat : 1 ,
484
599
} ,
600
+ payment_context : PaymentContext :: unknown ( ) ,
485
601
} ;
486
602
let htlc_minimum_msat = 3798 ;
487
603
assert ! ( super :: compute_payinfo( & intermediate_nodes[ ..] , & recv_tlvs, htlc_minimum_msat - 1 , TEST_FINAL_CLTV as u16 ) . is_err( ) ) ;
@@ -536,6 +652,7 @@ mod tests {
536
652
max_cltv_expiry : 0 ,
537
653
htlc_minimum_msat : 1 ,
538
654
} ,
655
+ payment_context : PaymentContext :: unknown ( ) ,
539
656
} ;
540
657
541
658
let blinded_payinfo = super :: compute_payinfo ( & intermediate_nodes[ ..] , & recv_tlvs, 10_000 , TEST_FINAL_CLTV as u16 ) . unwrap ( ) ;
0 commit comments