@@ -26,8 +26,7 @@ use bitcoin_payment_instructions::amount::Amount as BPIAmount;
2626use bitcoin_payment_instructions:: hrn_resolution:: DummyHrnResolver ;
2727use bitcoin_payment_instructions:: { PaymentInstructions , PaymentMethod } ;
2828use lightning:: ln:: channelmanager:: PaymentId ;
29- use lightning:: offers:: offer:: Offer ;
30- use lightning:: onion_message:: dns_resolution:: HumanReadableName ;
29+ use lightning:: offers:: offer:: Offer as LdkOffer ;
3130use lightning:: routing:: router:: RouteParametersConfig ;
3231use lightning_invoice:: { Bolt11Invoice , Bolt11InvoiceDescription , Description } ;
3332
@@ -41,6 +40,16 @@ use crate::Config;
4140
4241type Uri < ' a > = bip21:: Uri < ' a , NetworkChecked , Extras > ;
4342
43+ #[ cfg( not( feature = "uniffi" ) ) ]
44+ type HumanReadableName = lightning:: onion_message:: dns_resolution:: HumanReadableName ;
45+ #[ cfg( feature = "uniffi" ) ]
46+ type HumanReadableName = crate :: ffi:: HumanReadableName ;
47+
48+ #[ cfg( not( feature = "uniffi" ) ) ]
49+ type Offer = LdkOffer ;
50+ #[ cfg( feature = "uniffi" ) ]
51+ type Offer = Arc < crate :: ffi:: Offer > ;
52+
4453#[ derive( Debug , Clone ) ]
4554struct Extras {
4655 bolt11_invoice : Option < Bolt11Invoice > ,
@@ -67,6 +76,8 @@ pub struct UnifiedPayment {
6776 config : Arc < Config > ,
6877 logger : Arc < Logger > ,
6978 hrn_resolver : Arc < HRNResolver > ,
79+ #[ cfg( hrn_tests) ]
80+ test_offer : std:: sync:: Mutex < Option < Offer > > ,
7081}
7182
7283impl UnifiedPayment {
@@ -75,7 +86,16 @@ impl UnifiedPayment {
7586 bolt12_payment : Arc < Bolt12Payment > , config : Arc < Config > , logger : Arc < Logger > ,
7687 hrn_resolver : Arc < HRNResolver > ,
7788 ) -> Self {
78- Self { onchain_payment, bolt11_invoice, bolt12_payment, config, logger, hrn_resolver }
89+ Self {
90+ onchain_payment,
91+ bolt11_invoice,
92+ bolt12_payment,
93+ config,
94+ logger,
95+ hrn_resolver,
96+ #[ cfg( hrn_tests) ]
97+ test_offer : std:: sync:: Mutex :: new ( None ) ,
98+ }
7999 }
80100}
81101
@@ -116,7 +136,7 @@ impl UnifiedPayment {
116136
117137 let bolt12_offer =
118138 match self . bolt12_payment . receive_inner ( amount_msats, description, None , None ) {
119- Ok ( offer) => Some ( offer) ,
139+ Ok ( offer) => Some ( maybe_wrap ( offer) ) ,
120140 Err ( e) => {
121141 log_error ! ( self . logger, "Failed to create offer: {}" , e) ;
122142 None
@@ -167,15 +187,26 @@ impl UnifiedPayment {
167187 route_parameters : Option < RouteParametersConfig > ,
168188 ) -> Result < UnifiedPaymentResult , Error > {
169189 let resolver;
190+ let target_network;
170191
171192 if let Ok ( _) = HumanReadableName :: from_encoded ( uri_str) {
172193 resolver = Arc :: clone ( & self . hrn_resolver ) ;
194+
195+ #[ cfg( hrn_tests) ]
196+ {
197+ target_network = bitcoin:: Network :: Bitcoin ;
198+ }
199+ #[ cfg( not( hrn_tests) ) ]
200+ {
201+ target_network = self . config . network ;
202+ }
173203 } else {
174204 resolver = Arc :: new ( HRNResolver :: Dummy ( DummyHrnResolver ) ) ;
205+ target_network = self . config . network ;
175206 }
176207
177208 let parse_fut =
178- PaymentInstructions :: parse ( uri_str, self . config . network , resolver. as_ref ( ) , false ) ;
209+ PaymentInstructions :: parse ( uri_str, target_network , resolver. as_ref ( ) , false ) ;
179210
180211 let instructions =
181212 tokio:: time:: timeout ( Duration :: from_secs ( HRN_RESOLUTION_TIMEOUT_SECS ) , parse_fut)
@@ -238,9 +269,30 @@ impl UnifiedPayment {
238269
239270 for method in sorted_payment_methods {
240271 match method {
241- PaymentMethod :: LightningBolt12 ( offer) => {
242- let offer = maybe_wrap ( offer. clone ( ) ) ;
243-
272+ PaymentMethod :: LightningBolt12 ( _offer) => {
273+ #[ cfg( not( hrn_tests) ) ]
274+ let offer = maybe_wrap ( _offer. clone ( ) ) ;
275+
276+ #[ cfg( hrn_tests) ]
277+ let offer = {
278+ let test_offer_guard = self . test_offer . lock ( ) . map_err ( |e| {
279+ log_error ! (
280+ self . logger,
281+ "Failed to lock test_offer due to poisoning: {:?}" ,
282+ e
283+ ) ;
284+ Error :: PaymentSendingFailed
285+ } ) ?;
286+
287+ match & * test_offer_guard {
288+ Some ( o) => o. clone ( ) ,
289+ None => {
290+ log_error ! ( self . logger, "test_offer was None during HRN test" ) ;
291+ return Err ( Error :: PaymentSendingFailed ) ;
292+ } ,
293+ }
294+ } ;
295+
244296 let payment_result = if let Ok ( hrn) = HumanReadableName :: from_encoded ( uri_str) {
245297 let hrn = maybe_wrap ( hrn. clone ( ) ) ;
246298 self . bolt12_payment . send_using_amount_inner ( & offer, amount_msat. unwrap_or ( 0 ) , None , None , route_parameters, Some ( hrn) )
@@ -293,6 +345,16 @@ impl UnifiedPayment {
293345 log_error ! ( self . logger, "Payable methods not found in URI" ) ;
294346 Err ( Error :: PaymentSendingFailed )
295347 }
348+
349+ /// Sets a test offer to be used in the `send` method when the `hrn_tests` config flag is enabled.
350+ /// This is necessary to test sending Bolt12 payments via the unified payment handler in HRN tests,
351+ /// as we cannot rely on the offer being present in the parsed URI.
352+ #[ cfg( hrn_tests) ]
353+ pub fn set_test_offer ( & self , _offer : Offer ) {
354+ let _ = self . test_offer . lock ( ) . map ( |mut guard| * guard = Some ( _offer) ) . map_err ( |e| {
355+ log_error ! ( self . logger, "Failed to set test offer due to poisoned lock: {:?}" , e)
356+ } ) ;
357+ }
296358}
297359
298360/// Represents the result of a payment made using a [BIP 21] URI or a [BIP 353] Human-Readable Name.
@@ -400,9 +462,10 @@ impl<'a> bip21::de::DeserializationState<'a> for DeserializationState {
400462 "lno" => {
401463 let bolt12_value =
402464 String :: try_from ( value) . map_err ( |_| Error :: UriParameterParsingFailed ) ?;
403- let offer =
404- bolt12_value. parse :: < Offer > ( ) . map_err ( |_| Error :: UriParameterParsingFailed ) ?;
405- self . bolt12_offer = Some ( offer) ;
465+ let offer = bolt12_value
466+ . parse :: < LdkOffer > ( )
467+ . map_err ( |_| Error :: UriParameterParsingFailed ) ?;
468+ self . bolt12_offer = Some ( maybe_wrap ( offer) ) ;
406469 Ok ( bip21:: de:: ParamKind :: Known )
407470 } ,
408471 _ => Ok ( bip21:: de:: ParamKind :: Unknown ) ,
@@ -425,7 +488,7 @@ mod tests {
425488 use bitcoin:: address:: NetworkUnchecked ;
426489 use bitcoin:: { Address , Network } ;
427490
428- use super :: { Amount , Bolt11Invoice , Extras , Offer } ;
491+ use super :: { maybe_wrap , Amount , Bolt11Invoice , Extras , LdkOffer } ;
429492
430493 #[ test]
431494 fn parse_uri ( ) {
@@ -479,7 +542,7 @@ mod tests {
479542 }
480543
481544 if let Some ( offer) = parsed_uri_with_offer. extras . bolt12_offer {
482- assert_eq ! ( offer, Offer :: from_str( expected_bolt12_offer_2) . unwrap( ) ) ;
545+ assert_eq ! ( offer, maybe_wrap ( LdkOffer :: from_str( expected_bolt12_offer_2) . unwrap( ) ) ) ;
483546 } else {
484547 panic ! ( "No offer found." ) ;
485548 }
0 commit comments