55// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
66// accordance with one or both of these licenses.
77
8- //! Holds a payment handler allowing to create [BIP 21] URIs with on-chain, [BOLT 11], and [BOLT 12] payment
9- //! options.
8+ //! Holds a payment handler that supports creating and paying to [BIP 21] URIs with on-chain, [BOLT 11],
9+ //! and [BOLT 12] payment options.
1010//!
11- //! It also supports sending payments to these URIs as well as to [BIP 353] Human-Readable Names.
11+ //! Also supports sending payments to [BIP 353] Human-Readable Names.
1212//!
1313//! [BIP 21]: https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki
1414//! [BIP 353]: https://github.com/bitcoin/bips/blob/master/bip-0353.mediawiki
1515//! [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
1616//! [BOLT 12]: https://github.com/lightning/bolts/blob/master/12-offer-encoding.md
1717use std:: sync:: Arc ;
18+ use std:: time:: Duration ;
1819use std:: vec:: IntoIter ;
1920
2021use bip21:: de:: ParamKind ;
@@ -29,6 +30,7 @@ use lightning::onion_message::dns_resolution::HumanReadableName;
2930use lightning:: routing:: router:: RouteParametersConfig ;
3031use lightning_invoice:: { Bolt11Invoice , Bolt11InvoiceDescription , Description } ;
3132
33+ use crate :: config:: HRN_RESOLUTION_TIMEOUT_SECS ;
3234use crate :: error:: Error ;
3335use crate :: ffi:: maybe_wrap;
3436use crate :: logger:: { log_error, LdkLogger , Logger } ;
@@ -44,12 +46,12 @@ struct Extras {
4446 bolt12_offer : Option < Offer > ,
4547}
4648
47- /// A payment handler allowing to create [BIP 21] URIs with an on-chain, [BOLT 11], and [BOLT 12] payment
48- /// option .
49+ /// A payment handler that supports creating and paying to [BIP 21] URIs with on-chain, [BOLT 11],
50+ /// and [BOLT 12] payment options .
4951///
50- /// Should be retrieved by calling [`Node::unified_payment`]
52+ /// Also supports sending payments to [BIP 353] Human-Readable Names.
5153///
52- /// It also supports sending payments to these URIs as well as to [BIP 353] Human-Readable Names.
54+ /// Should be retrieved by calling [`Node::unified_payment`]
5355///
5456/// [BIP 21]: https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki
5557/// [BIP 353]: https://github.com/bitcoin/bips/blob/master/bip-0353.mediawiki
@@ -147,7 +149,7 @@ impl UnifiedPayment {
147149 /// has an offer and or invoice, it will try to pay the offer first followed by the invoice.
148150 /// If they both fail, the on-chain payment will be paid.
149151 ///
150- /// Returns a `UnifiedPaymentResult` indicating the outcome of the payment. If an error
152+ /// Returns a [ `UnifiedPaymentResult`] indicating the outcome of the payment. If an error
151153 /// occurs, an `Error` is returned detailing the issue encountered.
152154 ///
153155 /// If `route_parameters` are provided they will override the default as well as the
@@ -159,38 +161,57 @@ impl UnifiedPayment {
159161 & self , uri_str : & str , amount_msat : Option < u64 > ,
160162 route_parameters : Option < RouteParametersConfig > ,
161163 ) -> Result < UnifiedPaymentResult , Error > {
162- let instructions = PaymentInstructions :: parse (
164+ let parse_fut = PaymentInstructions :: parse (
163165 uri_str,
164166 self . config . network ,
165167 self . hrn_resolver . as_ref ( ) ,
166168 false ,
167- )
168- . await
169- . map_err ( |e| {
170- log_error ! ( self . logger, "Failed to parse payment instructions: {:?}" , e) ;
171- Error :: UriParameterParsingFailed
172- } ) ?;
169+ ) ;
170+
171+ let instructions =
172+ tokio:: time:: timeout ( Duration :: from_secs ( HRN_RESOLUTION_TIMEOUT_SECS ) , parse_fut)
173+ . await
174+ . map_err ( |e| {
175+ log_error ! ( self . logger, "Payment instructions resolution timed out: {:?}" , e) ;
176+ Error :: UriParameterParsingFailed
177+ } ) ?
178+ . map_err ( |e| {
179+ log_error ! ( self . logger, "Failed to parse payment instructions: {:?}" , e) ;
180+ Error :: UriParameterParsingFailed
181+ } ) ?;
173182
174183 let resolved = match instructions {
175184 PaymentInstructions :: ConfigurableAmount ( instr) => {
176- let amount = amount_msat. ok_or_else ( || {
185+ let amount_msat = amount_msat. ok_or_else ( || {
177186 log_error ! ( self . logger, "No amount specified. Aborting the payment." ) ;
178187 Error :: InvalidAmount
179188 } ) ?;
180189
181- let amt = BPIAmount :: from_milli_sats ( amount ) . map_err ( |e| {
190+ let amt = BPIAmount :: from_milli_sats ( amount_msat ) . map_err ( |e| {
182191 log_error ! ( self . logger, "Error while converting amount : {:?}" , e) ;
183192 Error :: InvalidAmount
184193 } ) ?;
185194
186- instr. set_amount ( amt, self . hrn_resolver . as_ref ( ) ) . await . map_err ( |e| {
187- log_error ! ( self . logger, "Failed to set amount: {:?}" , e) ;
188- Error :: InvalidAmount
189- } ) ?
195+ let fut = instr. set_amount ( amt, self . hrn_resolver . as_ref ( ) ) ;
196+
197+ tokio:: time:: timeout ( Duration :: from_secs ( HRN_RESOLUTION_TIMEOUT_SECS ) , fut)
198+ . await
199+ . map_err ( |e| {
200+ log_error ! (
201+ self . logger,
202+ "Payment instructions resolution timed out: {:?}" ,
203+ e
204+ ) ;
205+ Error :: UriParameterParsingFailed
206+ } ) ?
207+ . map_err ( |e| {
208+ log_error ! ( self . logger, "Failed to set amount: {:?}" , e) ;
209+ Error :: InvalidAmount
210+ } ) ?
190211 } ,
191212 PaymentInstructions :: FixedAmount ( instr) => {
192- if let Some ( user_amount ) = amount_msat {
193- if instr. max_amount ( ) . map_or ( false , |amt| user_amount < amt. milli_sats ( ) ) {
213+ if let Some ( user_amount_msat ) = amount_msat {
214+ if instr. max_amount ( ) . map_or ( false , |amt| user_amount_msat < amt. milli_sats ( ) ) {
194215 log_error ! ( self . logger, "Amount specified is less than the amount in the parsed URI. Aborting the payment." ) ;
195216 return Err ( Error :: InvalidAmount ) ;
196217 }
0 commit comments