@@ -122,7 +122,7 @@ use types::{ChainMonitor, ChannelManager, KeysManager, NetworkGraph, PeerManager
122
122
pub use types:: { ChannelDetails , PeerDetails , UserChannelId } ;
123
123
use wallet:: Wallet ;
124
124
125
- use logger:: { log_debug , log_error, log_info, log_trace, FilesystemLogger , Logger } ;
125
+ use logger:: { log_error, log_info, log_trace, FilesystemLogger , Logger } ;
126
126
127
127
use lightning:: chain:: Confirm ;
128
128
use lightning:: ln:: channelmanager:: { self , PaymentId , RecipientOnionFields , Retry } ;
@@ -138,7 +138,7 @@ use lightning_background_processor::process_events_async;
138
138
139
139
use lightning_transaction_sync:: EsploraSyncClient ;
140
140
141
- use lightning:: routing:: router:: { PaymentParameters , RouteParameters , Router as LdkRouter } ;
141
+ use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
142
142
use lightning_invoice:: { payment, Bolt11Invoice , Currency } ;
143
143
144
144
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
@@ -150,7 +150,6 @@ use bitcoin::{Address, Txid};
150
150
151
151
use rand:: Rng ;
152
152
153
- use std:: collections:: HashMap ;
154
153
use std:: default:: Default ;
155
154
use std:: net:: ToSocketAddrs ;
156
155
use std:: sync:: { Arc , Mutex , RwLock } ;
@@ -295,7 +294,7 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
295
294
gossip_source : Arc < GossipSource > ,
296
295
kv_store : Arc < K > ,
297
296
logger : Arc < FilesystemLogger > ,
298
- router : Arc < Router > ,
297
+ _router : Arc < Router > ,
299
298
scorer : Arc < Mutex < Scorer > > ,
300
299
peer_store : Arc < PeerStore < K , Arc < FilesystemLogger > > > ,
301
300
payment_store : Arc < PaymentStore < K , Arc < FilesystemLogger > > > ,
@@ -1320,116 +1319,93 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1320
1319
/// payment. To mitigate this issue, channels with available liquidity less than the required
1321
1320
/// amount times [`Config::probing_liquidity_limit_multiplier`] won't be used to send
1322
1321
/// pre-flight probes.
1323
- pub fn send_payment_probe ( & self , invoice : & Bolt11Invoice ) -> Result < ( ) , Error > {
1322
+ pub fn send_payment_probes ( & self , invoice : & Bolt11Invoice ) -> Result < ( ) , Error > {
1324
1323
let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1325
1324
if rt_lock. is_none ( ) {
1326
1325
return Err ( Error :: NotRunning ) ;
1327
1326
}
1328
1327
1329
- let amount_msat = if let Some ( invoice_amount_msat) = invoice. amount_milli_satoshis ( ) {
1330
- invoice_amount_msat
1331
- } else {
1332
- log_error ! ( self . logger, "Failed to send probe as no amount was given in the invoice." ) ;
1333
- return Err ( Error :: InvalidAmount ) ;
1334
- } ;
1328
+ let liquidity_limit_multiplier = Some ( self . config . probing_liquidity_limit_multiplier ) ;
1335
1329
1336
- let expiry_time = invoice . duration_since_epoch ( ) . saturating_add ( invoice . expiry_time ( ) ) ;
1337
- let mut payment_params = PaymentParameters :: from_node_id (
1338
- invoice . recover_payee_pub_key ( ) ,
1339
- invoice . min_final_cltv_expiry_delta ( ) as u32 ,
1330
+ payment :: preflight_probe_invoice (
1331
+ invoice ,
1332
+ & * self . channel_manager ,
1333
+ liquidity_limit_multiplier ,
1340
1334
)
1341
- . with_expiry_time ( expiry_time. as_secs ( ) )
1342
- . with_route_hints ( invoice. route_hints ( ) )
1343
- . map_err ( |_| Error :: InvalidInvoice ) ?;
1344
- if let Some ( features) = invoice. features ( ) {
1345
- payment_params = payment_params
1346
- . with_bolt11_features ( features. clone ( ) )
1347
- . map_err ( |_| Error :: InvalidInvoice ) ?;
1348
- }
1349
- let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
1335
+ . map_err ( |e| {
1336
+ log_error ! ( self . logger, "Failed to send payment probes: {:?}" , e) ;
1337
+ Error :: ProbeSendingFailed
1338
+ } ) ?;
1350
1339
1351
- self . send_payment_probe_internal ( route_params )
1340
+ Ok ( ( ) )
1352
1341
}
1353
1342
1354
1343
/// Sends payment probes over all paths of a route that would be used to pay the given
1355
1344
/// amount to the given `node_id`.
1356
1345
///
1357
- /// This may be used to send "pre-flight" probes, i.e., to train our scorer before conducting
1358
- /// the actual payment. Note this is only useful if there likely is sufficient time for the
1359
- /// probe to settle before sending out the actual payment, e.g., when waiting for user
1360
- /// confirmation in a wallet UI.
1361
- ///
1362
- /// Otherwise, there is a chance the probe could take up some liquidity needed to complete the
1363
- /// actual payment. Users should therefore be cautious and might avoid sending probes if
1364
- /// liquidity is scarce and/or they don't expect the probe to return before they send the
1365
- /// payment. To mitigate this issue, channels with available liquidity less than the required
1366
- /// amount times [`Config::probing_liquidity_limit_multiplier`] won't be used to send
1367
- /// pre-flight probes.
1368
- pub fn send_spontaneous_payment_probe (
1346
+ /// See [`Self::send_payment_probes`] for more information.
1347
+ pub fn send_spontaneous_payment_probes (
1369
1348
& self , amount_msat : u64 , node_id : PublicKey ,
1370
1349
) -> Result < ( ) , Error > {
1371
1350
let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1372
1351
if rt_lock. is_none ( ) {
1373
1352
return Err ( Error :: NotRunning ) ;
1374
1353
}
1375
1354
1376
- let payment_params =
1377
- PaymentParameters :: from_node_id ( node_id, self . config . default_cltv_expiry_delta ) ;
1378
-
1379
- let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
1380
-
1381
- self . send_payment_probe_internal ( route_params)
1382
- }
1383
-
1384
- fn send_payment_probe_internal ( & self , route_params : RouteParameters ) -> Result < ( ) , Error > {
1385
- let payer = self . channel_manager . get_our_node_id ( ) ;
1386
- let usable_channels = self . channel_manager . list_usable_channels ( ) ;
1387
- let first_hops = usable_channels. iter ( ) . collect :: < Vec < _ > > ( ) ;
1388
- let inflight_htlcs = self . channel_manager . compute_inflight_htlcs ( ) ;
1355
+ let liquidity_limit_multiplier = Some ( self . config . probing_liquidity_limit_multiplier ) ;
1356
+ let cltv_expiry_delta = self . config . default_cltv_expiry_delta ;
1389
1357
1390
- let route = self
1391
- . router
1392
- . find_route ( & payer, & route_params, Some ( & first_hops) , inflight_htlcs)
1358
+ self . channel_manager
1359
+ . send_spontaneous_preflight_probes (
1360
+ node_id,
1361
+ amount_msat,
1362
+ cltv_expiry_delta,
1363
+ liquidity_limit_multiplier,
1364
+ )
1393
1365
. map_err ( |e| {
1394
- log_error ! ( self . logger, "Failed to find path for payment probe : {:?}" , e) ;
1366
+ log_error ! ( self . logger, "Failed to send payment probes : {:?}" , e) ;
1395
1367
Error :: ProbeSendingFailed
1396
1368
} ) ?;
1397
1369
1398
- let mut used_liquidity_map = HashMap :: with_capacity ( first_hops. len ( ) ) ;
1399
- for path in route. paths {
1400
- if path. hops . len ( ) + path. blinded_tail . as_ref ( ) . map_or ( 0 , |t| t. hops . len ( ) ) < 2 {
1401
- log_debug ! (
1370
+ Ok ( ( ) )
1371
+ }
1372
+
1373
+ /// Sends payment probes over all paths of a route that would be used to pay the given
1374
+ /// zero-value invoice using the given amount.
1375
+ ///
1376
+ /// This can be used to send pre-flight probes for a so-called "zero-amount" invoice, i.e., an
1377
+ /// invoice that leaves the amount paid to be determined by the user.
1378
+ ///
1379
+ /// See [`Self::send_payment_probes`] for more information.
1380
+ pub fn send_payment_probes_using_amount (
1381
+ & self , invoice : & Bolt11Invoice , amount_msat : u64 ,
1382
+ ) -> Result < ( ) , Error > {
1383
+ let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1384
+ if rt_lock. is_none ( ) {
1385
+ return Err ( Error :: NotRunning ) ;
1386
+ }
1387
+
1388
+ if let Some ( invoice_amount_msat) = invoice. amount_milli_satoshis ( ) {
1389
+ if amount_msat < invoice_amount_msat {
1390
+ log_error ! (
1402
1391
self . logger,
1403
- "Skipped sending payment probe over path with less than two hops."
1404
- ) ;
1405
- continue ;
1392
+ "Failed to send probes as the given amount needs to be at least the invoice amount: required {}msat, gave {}msat." , invoice_amount_msat, amount_msat) ;
1393
+ return Err ( Error :: InvalidAmount ) ;
1406
1394
}
1395
+ }
1407
1396
1408
- if let Some ( first_path_hop) = path. hops . first ( ) {
1409
- if let Some ( first_hop) = first_hops. iter ( ) . find ( |h| {
1410
- h. get_outbound_payment_scid ( ) == Some ( first_path_hop. short_channel_id )
1411
- } ) {
1412
- let path_value = path. final_value_msat ( ) + path. fee_msat ( ) ;
1413
- let used_liquidity =
1414
- used_liquidity_map. entry ( first_path_hop. short_channel_id ) . or_insert ( 0 ) ;
1415
-
1416
- if first_hop. next_outbound_htlc_limit_msat
1417
- < ( * used_liquidity + path_value)
1418
- * self . config . probing_liquidity_limit_multiplier
1419
- {
1420
- log_debug ! ( self . logger, "Skipped sending payment probe to avoid putting channel {} under the liquidity limit." , first_path_hop. short_channel_id) ;
1421
- continue ;
1422
- } else {
1423
- * used_liquidity += path_value;
1424
- }
1425
- }
1426
- }
1397
+ let liquidity_limit_multiplier = Some ( self . config . probing_liquidity_limit_multiplier ) ;
1427
1398
1428
- self . channel_manager . send_probe ( path) . map_err ( |e| {
1429
- log_error ! ( self . logger, "Failed to send payment probe: {:?}" , e) ;
1430
- Error :: ProbeSendingFailed
1431
- } ) ?;
1432
- }
1399
+ payment:: preflight_probe_zero_value_invoice (
1400
+ invoice,
1401
+ amount_msat,
1402
+ & * self . channel_manager ,
1403
+ liquidity_limit_multiplier,
1404
+ )
1405
+ . map_err ( |e| {
1406
+ log_error ! ( self . logger, "Failed to send payment probes: {:?}" , e) ;
1407
+ Error :: ProbeSendingFailed
1408
+ } ) ?;
1433
1409
1434
1410
Ok ( ( ) )
1435
1411
}
0 commit comments