@@ -118,11 +118,11 @@ use io::KVStore;
118118use payment_store:: PaymentStore ;
119119pub use payment_store:: { PaymentDetails , PaymentDirection , PaymentStatus } ;
120120use peer_store:: { PeerInfo , PeerStore } ;
121- use types:: { ChainMonitor , ChannelManager , KeysManager , NetworkGraph , PeerManager , Scorer } ;
121+ use types:: { ChainMonitor , ChannelManager , KeysManager , NetworkGraph , PeerManager , Router , Scorer } ;
122122pub use types:: { ChannelDetails , ChannelId , PeerDetails , UserChannelId } ;
123123use wallet:: Wallet ;
124124
125- use logger:: { log_error, log_info, log_trace, FilesystemLogger , Logger } ;
125+ use logger:: { log_debug , log_error, log_info, log_trace, FilesystemLogger , Logger } ;
126126
127127use lightning:: chain:: keysinterface:: EntropySource ;
128128use lightning:: chain:: Confirm ;
@@ -136,7 +136,7 @@ use lightning_background_processor::process_events_async;
136136
137137use lightning_transaction_sync:: EsploraSyncClient ;
138138
139- use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
139+ use lightning:: routing:: router:: { PaymentParameters , RouteParameters , Router as LdkRouter } ;
140140use lightning_invoice:: { payment, Currency , Invoice } ;
141141
142142use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
@@ -284,6 +284,7 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
284284 gossip_source : Arc < GossipSource > ,
285285 kv_store : Arc < K > ,
286286 logger : Arc < FilesystemLogger > ,
287+ router : Arc < Router > ,
287288 scorer : Arc < Mutex < Scorer > > ,
288289 peer_store : Arc < PeerStore < K , Arc < FilesystemLogger > > > ,
289290 payment_store : Arc < PaymentStore < K , Arc < FilesystemLogger > > > ,
@@ -1035,7 +1036,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
10351036 . map_err ( |_| Error :: ChannelConfigUpdateFailed )
10361037 }
10371038
1038- /// Send a payement given an invoice.
1039+ /// Send a payment given an invoice.
10391040 pub fn send_payment ( & self , invoice : & Invoice ) -> Result < PaymentHash , Error > {
10401041 let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
10411042 if rt_lock. is_none ( ) {
@@ -1287,6 +1288,99 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
12871288 }
12881289 }
12891290
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+
12901384 /// Returns a payable invoice that can be used to request and receive a payment of the amount
12911385 /// given.
12921386 pub fn receive_payment (
0 commit comments