Skip to content

Commit 0901c19

Browse files
committed
Switch to upstreamed preflight probing methods
1 parent e5650db commit 0901c19

File tree

3 files changed

+66
-88
lines changed

3 files changed

+66
-88
lines changed

bindings/ldk_node.udl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,11 @@ interface LDKNode {
7373
[Throws=NodeError]
7474
PaymentHash send_spontaneous_payment(u64 amount_msat, PublicKey node_id);
7575
[Throws=NodeError]
76-
void send_payment_probe([ByRef]Bolt11Invoice invoice);
76+
void send_payment_probes([ByRef]Bolt11Invoice invoice);
7777
[Throws=NodeError]
78-
void send_spontaneous_payment_probe(u64 amount_msat, PublicKey node_id);
78+
void send_spontaneous_payment_probes(u64 amount_msat, PublicKey node_id);
79+
[Throws=NodeError]
80+
void send_payment_probes_using_amount([ByRef]Bolt11Invoice invoice, u64 amount_msat);
7981
[Throws=NodeError]
8082
Bolt11Invoice receive_payment(u64 amount_msat, [ByRef]string description, u32 expiry_secs);
8183
[Throws=NodeError]

src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
753753
gossip_source,
754754
kv_store,
755755
logger,
756-
router,
756+
_router: router,
757757
scorer,
758758
peer_store,
759759
payment_store,

src/lib.rs

Lines changed: 61 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ use types::{ChainMonitor, ChannelManager, KeysManager, NetworkGraph, PeerManager
122122
pub use types::{ChannelDetails, PeerDetails, UserChannelId};
123123
use wallet::Wallet;
124124

125-
use logger::{log_debug, log_error, log_info, log_trace, FilesystemLogger, Logger};
125+
use logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};
126126

127127
use lightning::chain::Confirm;
128128
use lightning::ln::channelmanager::{self, PaymentId, RecipientOnionFields, Retry};
@@ -138,7 +138,7 @@ use lightning_background_processor::process_events_async;
138138

139139
use lightning_transaction_sync::EsploraSyncClient;
140140

141-
use lightning::routing::router::{PaymentParameters, RouteParameters, Router as LdkRouter};
141+
use lightning::routing::router::{PaymentParameters, RouteParameters};
142142
use lightning_invoice::{payment, Bolt11Invoice, Currency};
143143

144144
use bitcoin::hashes::sha256::Hash as Sha256;
@@ -150,7 +150,6 @@ use bitcoin::{Address, Txid};
150150

151151
use rand::Rng;
152152

153-
use std::collections::HashMap;
154153
use std::default::Default;
155154
use std::net::ToSocketAddrs;
156155
use std::sync::{Arc, Mutex, RwLock};
@@ -295,7 +294,7 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
295294
gossip_source: Arc<GossipSource>,
296295
kv_store: Arc<K>,
297296
logger: Arc<FilesystemLogger>,
298-
router: Arc<Router>,
297+
_router: Arc<Router>,
299298
scorer: Arc<Mutex<Scorer>>,
300299
peer_store: Arc<PeerStore<K, Arc<FilesystemLogger>>>,
301300
payment_store: Arc<PaymentStore<K, Arc<FilesystemLogger>>>,
@@ -1320,116 +1319,93 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
13201319
/// payment. To mitigate this issue, channels with available liquidity less than the required
13211320
/// amount times [`Config::probing_liquidity_limit_multiplier`] won't be used to send
13221321
/// 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> {
13241323
let rt_lock = self.runtime.read().unwrap();
13251324
if rt_lock.is_none() {
13261325
return Err(Error::NotRunning);
13271326
}
13281327

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);
13351329

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,
13401334
)
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+
})?;
13501339

1351-
self.send_payment_probe_internal(route_params)
1340+
Ok(())
13521341
}
13531342

13541343
/// Sends payment probes over all paths of a route that would be used to pay the given
13551344
/// amount to the given `node_id`.
13561345
///
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(
13691348
&self, amount_msat: u64, node_id: PublicKey,
13701349
) -> Result<(), Error> {
13711350
let rt_lock = self.runtime.read().unwrap();
13721351
if rt_lock.is_none() {
13731352
return Err(Error::NotRunning);
13741353
}
13751354

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;
13891357

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+
)
13931365
.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);
13951367
Error::ProbeSendingFailed
13961368
})?;
13971369

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!(
14021391
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);
14061394
}
1395+
}
14071396

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);
14271398

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+
})?;
14331409

14341410
Ok(())
14351411
}

0 commit comments

Comments
 (0)