99
1010//! Convenient utilities for paying Lightning invoices.
1111
12- use crate :: Bolt11Invoice ;
12+ use crate :: { Bolt11Invoice , Vec } ;
1313
1414use bitcoin_hashes:: Hash ;
1515
1616use lightning:: chain;
1717use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
1818use lightning:: sign:: { NodeSigner , SignerProvider , EntropySource } ;
1919use lightning:: ln:: PaymentHash ;
20- use lightning:: ln:: channelmanager:: { ChannelManager , PaymentId , Retry , RetryableSendFailure , RecipientOnionFields } ;
20+ use lightning:: ln:: channelmanager:: { ChannelManager , PaymentId , Retry , RetryableSendFailure , RecipientOnionFields , ProbeSendFailure } ;
2121use lightning:: routing:: router:: { PaymentParameters , RouteParameters , Router } ;
2222use lightning:: util:: logger:: Logger ;
2323
@@ -163,6 +163,85 @@ fn pay_invoice_using_amount<P: Deref>(
163163 payer. send_payment ( payment_hash, recipient_onion, payment_id, route_params, retry_strategy)
164164}
165165
166+ /// Sends payment probes over all paths of a route that would be used to pay the given invoice.
167+ ///
168+ /// See [`ChannelManager::send_preflight_probes`] for more information.
169+ pub fn preflight_probe_invoice < M : Deref , T : Deref , ES : Deref , NS : Deref , SP : Deref , F : Deref , R : Deref , L : Deref > (
170+ invoice : & Bolt11Invoice , channelmanager : & ChannelManager < M , T , ES , NS , SP , F , R , L > ,
171+ liquidity_limit_multiplier : Option < u64 > ,
172+ ) -> Result < Vec < ( PaymentHash , PaymentId ) > , ProbingError >
173+ where
174+ M :: Target : chain:: Watch < <SP :: Target as SignerProvider >:: Signer > ,
175+ T :: Target : BroadcasterInterface ,
176+ ES :: Target : EntropySource ,
177+ NS :: Target : NodeSigner ,
178+ SP :: Target : SignerProvider ,
179+ F :: Target : FeeEstimator ,
180+ R :: Target : Router ,
181+ L :: Target : Logger ,
182+ {
183+ let amount_msat = if let Some ( invoice_amount_msat) = invoice. amount_milli_satoshis ( ) {
184+ invoice_amount_msat
185+ } else {
186+ return Err ( ProbingError :: Invoice ( "Failed to send probe as no amount was given in the invoice." ) ) ;
187+ } ;
188+
189+ let mut payment_params = PaymentParameters :: from_node_id (
190+ invoice. recover_payee_pub_key ( ) ,
191+ invoice. min_final_cltv_expiry_delta ( ) as u32 ,
192+ )
193+ . with_expiry_time ( expiry_time_from_unix_epoch ( invoice) . as_secs ( ) )
194+ . with_route_hints ( invoice. route_hints ( ) )
195+ . unwrap ( ) ;
196+
197+ if let Some ( features) = invoice. features ( ) {
198+ payment_params = payment_params. with_bolt11_features ( features. clone ( ) ) . unwrap ( ) ;
199+ }
200+ let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
201+
202+ channelmanager. send_preflight_probes ( route_params, liquidity_limit_multiplier)
203+ . map_err ( ProbingError :: Sending )
204+ }
205+
206+ /// Sends payment probes over all paths of a route that would be used to pay the given zero-value
207+ /// invoice using the given amount.
208+ ///
209+ /// See [`ChannelManager::send_preflight_probes`] for more information.
210+ pub fn preflight_probe_zero_value_invoice < M : Deref , T : Deref , ES : Deref , NS : Deref , SP : Deref , F : Deref , R : Deref , L : Deref > (
211+ invoice : & Bolt11Invoice , amount_msat : u64 , channelmanager : & ChannelManager < M , T , ES , NS , SP , F , R , L > ,
212+ liquidity_limit_multiplier : Option < u64 > ,
213+ ) -> Result < Vec < ( PaymentHash , PaymentId ) > , ProbingError >
214+ where
215+ M :: Target : chain:: Watch < <SP :: Target as SignerProvider >:: Signer > ,
216+ T :: Target : BroadcasterInterface ,
217+ ES :: Target : EntropySource ,
218+ NS :: Target : NodeSigner ,
219+ SP :: Target : SignerProvider ,
220+ F :: Target : FeeEstimator ,
221+ R :: Target : Router ,
222+ L :: Target : Logger ,
223+ {
224+ if invoice. amount_milli_satoshis ( ) . is_some ( ) {
225+ return Err ( ProbingError :: Invoice ( "amount unexpected" ) ) ;
226+ }
227+
228+ let mut payment_params = PaymentParameters :: from_node_id (
229+ invoice. recover_payee_pub_key ( ) ,
230+ invoice. min_final_cltv_expiry_delta ( ) as u32 ,
231+ )
232+ . with_expiry_time ( expiry_time_from_unix_epoch ( invoice) . as_secs ( ) )
233+ . with_route_hints ( invoice. route_hints ( ) )
234+ . unwrap ( ) ;
235+
236+ if let Some ( features) = invoice. features ( ) {
237+ payment_params = payment_params. with_bolt11_features ( features. clone ( ) ) . unwrap ( ) ;
238+ }
239+ let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
240+
241+ channelmanager. send_preflight_probes ( route_params, liquidity_limit_multiplier)
242+ . map_err ( ProbingError :: Sending )
243+ }
244+
166245fn expiry_time_from_unix_epoch ( invoice : & Bolt11Invoice ) -> Duration {
167246 invoice. signed_invoice . raw_invoice . data . timestamp . 0 + invoice. expiry_time ( )
168247}
@@ -176,6 +255,15 @@ pub enum PaymentError {
176255 Sending ( RetryableSendFailure ) ,
177256}
178257
258+ /// An error that may occur when sending a payment probe.
259+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
260+ pub enum ProbingError {
261+ /// An error resulting from the provided [`Bolt11Invoice`].
262+ Invoice ( & ' static str ) ,
263+ /// An error occurring when sending a payment probe.
264+ Sending ( ProbeSendFailure ) ,
265+ }
266+
179267/// A trait defining behavior of a [`Bolt11Invoice`] payer.
180268///
181269/// Useful for unit testing internal methods.
0 commit comments