9
9
10
10
//! Convenient utilities for paying Lightning invoices.
11
11
12
- use crate :: Bolt11Invoice ;
12
+ use crate :: { Bolt11Invoice , Vec } ;
13
13
14
14
use bitcoin_hashes:: Hash ;
15
15
16
16
use lightning:: chain;
17
17
use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
18
18
use lightning:: sign:: { NodeSigner , SignerProvider , EntropySource } ;
19
19
use lightning:: ln:: PaymentHash ;
20
- use lightning:: ln:: channelmanager:: { ChannelManager , PaymentId , Retry , RetryableSendFailure , RecipientOnionFields } ;
20
+ use lightning:: ln:: channelmanager:: { ChannelManager , PaymentId , Retry , RetryableSendFailure , RecipientOnionFields , ProbeSendFailure } ;
21
21
use lightning:: routing:: router:: { PaymentParameters , RouteParameters , Router } ;
22
22
use lightning:: util:: logger:: Logger ;
23
23
@@ -163,6 +163,85 @@ fn pay_invoice_using_amount<P: Deref>(
163
163
payer. send_payment ( payment_hash, recipient_onion, payment_id, route_params, retry_strategy)
164
164
}
165
165
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
+
166
245
fn expiry_time_from_unix_epoch ( invoice : & Bolt11Invoice ) -> Duration {
167
246
invoice. signed_invoice . raw_invoice . data . timestamp . 0 + invoice. expiry_time ( )
168
247
}
@@ -176,6 +255,15 @@ pub enum PaymentError {
176
255
Sending ( RetryableSendFailure ) ,
177
256
}
178
257
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
+
179
267
/// A trait defining behavior of a [`Bolt11Invoice`] payer.
180
268
///
181
269
/// Useful for unit testing internal methods.
0 commit comments