@@ -118,11 +118,11 @@ use io::KVStore;
118
118
use payment_store:: PaymentStore ;
119
119
pub use payment_store:: { PaymentDetails , PaymentDirection , PaymentStatus } ;
120
120
use peer_store:: { PeerInfo , PeerStore } ;
121
- use types:: { ChainMonitor , ChannelManager , KeysManager , NetworkGraph , PeerManager , Scorer } ;
121
+ use types:: { ChainMonitor , ChannelManager , KeysManager , NetworkGraph , PeerManager , Router , Scorer } ;
122
122
pub use types:: { ChannelDetails , ChannelId , PeerDetails , UserChannelId } ;
123
123
use wallet:: Wallet ;
124
124
125
- use logger:: { log_error, log_info, log_trace, FilesystemLogger , Logger } ;
125
+ use logger:: { log_debug , log_error, log_info, log_trace, FilesystemLogger , Logger } ;
126
126
127
127
use lightning:: chain:: keysinterface:: EntropySource ;
128
128
use lightning:: chain:: Confirm ;
@@ -136,7 +136,7 @@ use lightning_background_processor::process_events_async;
136
136
137
137
use lightning_transaction_sync:: EsploraSyncClient ;
138
138
139
- use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
139
+ use lightning:: routing:: router:: { PaymentParameters , RouteParameters , Router as LdkRouter } ;
140
140
use lightning_invoice:: { payment, Currency , Invoice } ;
141
141
142
142
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
@@ -284,6 +284,7 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
284
284
gossip_source : Arc < GossipSource > ,
285
285
kv_store : Arc < K > ,
286
286
logger : Arc < FilesystemLogger > ,
287
+ router : Arc < Router > ,
287
288
scorer : Arc < Mutex < Scorer > > ,
288
289
peer_store : Arc < PeerStore < K , Arc < FilesystemLogger > > > ,
289
290
payment_store : Arc < PaymentStore < K , Arc < FilesystemLogger > > > ,
@@ -1035,7 +1036,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1035
1036
. map_err ( |_| Error :: ChannelConfigUpdateFailed )
1036
1037
}
1037
1038
1038
- /// Send a payement given an invoice.
1039
+ /// Send a payment given an invoice.
1039
1040
pub fn send_payment ( & self , invoice : & Invoice ) -> Result < PaymentHash , Error > {
1040
1041
let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1041
1042
if rt_lock. is_none ( ) {
@@ -1287,6 +1288,99 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1287
1288
}
1288
1289
}
1289
1290
1291
+ /// Sends payment probes over all paths of a route that would be used to pay the given invoice.
1292
+ ///
1293
+ /// This may be used to send "pre-flight" probes, i.e., to train our scorer before conducting
1294
+ /// the actual payment. Note this is only useful if there likely is sufficient time for the
1295
+ /// probe to settle before sending out the actual payment, e.g., when waiting for user
1296
+ /// confirmation in a wallet UI.
1297
+ pub fn send_payment_probe ( & self , invoice : & Invoice ) -> Result < ( ) , Error > {
1298
+ let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1299
+ if rt_lock. is_none ( ) {
1300
+ return Err ( Error :: NotRunning ) ;
1301
+ }
1302
+
1303
+ let amount_msat = if let Some ( invoice_amount_msat) = invoice. amount_milli_satoshis ( ) {
1304
+ invoice_amount_msat
1305
+ } else {
1306
+ log_error ! ( self . logger, "Failed to send probe as no amount was given in the invoice." ) ;
1307
+ return Err ( Error :: InvalidAmount ) ;
1308
+ } ;
1309
+
1310
+ let expiry_time = invoice. duration_since_epoch ( ) . saturating_add ( invoice. expiry_time ( ) ) ;
1311
+ let mut payment_params = PaymentParameters :: from_node_id (
1312
+ invoice. recover_payee_pub_key ( ) ,
1313
+ invoice. min_final_cltv_expiry_delta ( ) as u32 ,
1314
+ )
1315
+ . with_expiry_time ( expiry_time. as_secs ( ) )
1316
+ . with_route_hints ( invoice. route_hints ( ) ) ;
1317
+ if let Some ( features) = invoice. features ( ) {
1318
+ payment_params = payment_params. with_features ( features. clone ( ) ) ;
1319
+ }
1320
+ let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
1321
+
1322
+ self . send_payment_probe_internal ( route_params)
1323
+ }
1324
+
1325
+ /// Sends payment probes over all paths of a route that would be used to pay the given
1326
+ /// amount to the given `node_id`.
1327
+ ///
1328
+ /// This may be used to send "pre-flight" probes, i.e., to train our scorer before conducting
1329
+ /// the actual payment. Note this is only useful if there likely is sufficient time for the
1330
+ /// probe to settle before sending out the actual payment, e.g., when waiting for user
1331
+ /// confirmation in a wallet UI.
1332
+ pub fn send_spontaneous_payment_probe (
1333
+ & self , amount_msat : u64 , node_id : PublicKey ,
1334
+ ) -> Result < ( ) , Error > {
1335
+ let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1336
+ if rt_lock. is_none ( ) {
1337
+ return Err ( Error :: NotRunning ) ;
1338
+ }
1339
+
1340
+ let payment_params =
1341
+ PaymentParameters :: from_node_id ( node_id, self . config . default_cltv_expiry_delta ) ;
1342
+
1343
+ let route_params = RouteParameters { payment_params, final_value_msat : amount_msat } ;
1344
+
1345
+ self . send_payment_probe_internal ( route_params)
1346
+ }
1347
+
1348
+ fn send_payment_probe_internal ( & self , route_params : RouteParameters ) -> Result < ( ) , Error > {
1349
+ let payer = self . channel_manager . get_our_node_id ( ) ;
1350
+ let first_hops = self . channel_manager . list_usable_channels ( ) ;
1351
+ let inflight_htlcs = self . channel_manager . compute_inflight_htlcs ( ) ;
1352
+
1353
+ let route = self
1354
+ . router
1355
+ . find_route (
1356
+ & payer,
1357
+ & route_params,
1358
+ Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) ,
1359
+ & inflight_htlcs,
1360
+ )
1361
+ . map_err ( |e| {
1362
+ log_error ! ( self . logger, "Failed to find path for payment probe: {:?}" , e) ;
1363
+ Error :: ProbeSendingFailed
1364
+ } ) ?;
1365
+
1366
+ for path in route. paths {
1367
+ if path. hops . len ( ) + path. blinded_tail . as_ref ( ) . map_or ( 0 , |t| t. hops . len ( ) ) < 2 {
1368
+ log_debug ! (
1369
+ self . logger,
1370
+ "Skipped sending payment probe over path with less than two hops."
1371
+ ) ;
1372
+ continue ;
1373
+ }
1374
+
1375
+ self . channel_manager . send_probe ( path) . map_err ( |e| {
1376
+ log_error ! ( self . logger, "Failed to send payment probe: {:?}" , e) ;
1377
+ Error :: ProbeSendingFailed
1378
+ } ) ?;
1379
+ }
1380
+
1381
+ Ok ( ( ) )
1382
+ }
1383
+
1290
1384
/// Returns a payable invoice that can be used to request and receive a payment of the amount
1291
1385
/// given.
1292
1386
pub fn receive_payment (
0 commit comments