@@ -149,6 +149,7 @@ use bitcoin::{Address, Txid};
149
149
150
150
use rand:: Rng ;
151
151
152
+ use std:: collections:: HashMap ;
152
153
use std:: default:: Default ;
153
154
use std:: net:: ToSocketAddrs ;
154
155
use std:: sync:: { Arc , Mutex , RwLock } ;
@@ -164,6 +165,7 @@ const DEFAULT_CLTV_EXPIRY_DELTA: u32 = 144;
164
165
const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS : u64 = 80 ;
165
166
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS : u64 = 30 ;
166
167
const DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS : u64 = 60 * 10 ;
168
+ const DEFAULT_PROBING_LIQUIDITY_LIMIT_MULTIPLIER : u64 = 3 ;
167
169
const DEFAULT_LOG_LEVEL : LogLevel = LogLevel :: Debug ;
168
170
169
171
// The 'stop gap' parameter used by BDK's wallet sync. This seems to configure the threshold
@@ -210,6 +212,7 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
210
212
/// | `wallet_sync_interval_secs` | 30 |
211
213
/// | `fee_rate_cache_update_interval_secs` | 600 |
212
214
/// | `trusted_peers_0conf` | [] |
215
+ /// | `probing_liquidity_limit_multiplier` | 3 |
213
216
/// | `log_level` | Debug |
214
217
///
215
218
pub struct Config {
@@ -243,6 +246,11 @@ pub struct Config {
243
246
/// funding transaction ends up never being confirmed on-chain. Zero-confirmation channels
244
247
/// should therefore only be accepted from trusted peers.
245
248
pub trusted_peers_0conf : Vec < PublicKey > ,
249
+ /// The liquidity factor by which we filter the outgoing channels used for sending probes.
250
+ ///
251
+ /// Channels with available liquidity less than the required amount times this value won't be
252
+ /// used to send pre-flight probes.
253
+ pub probing_liquidity_limit_multiplier : u64 ,
246
254
/// The level at which we log messages.
247
255
///
248
256
/// Any messages below this level will be excluded from the logs.
@@ -261,6 +269,7 @@ impl Default for Config {
261
269
wallet_sync_interval_secs : DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS ,
262
270
fee_rate_cache_update_interval_secs : DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS ,
263
271
trusted_peers_0conf : Vec :: new ( ) ,
272
+ probing_liquidity_limit_multiplier : DEFAULT_PROBING_LIQUIDITY_LIMIT_MULTIPLIER ,
264
273
log_level : DEFAULT_LOG_LEVEL ,
265
274
}
266
275
}
@@ -1302,10 +1311,14 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1302
1311
/// This may be used to send "pre-flight" probes, i.e., to train our scorer before conducting
1303
1312
/// the actual payment. Note this is only useful if there likely is sufficient time for the
1304
1313
/// probe to settle before sending out the actual payment, e.g., when waiting for user
1305
- /// confirmation in a wallet UI. Otherwise, there is a chance the probe could take up some
1306
- /// liquidity needed to complete the actual payment. Users should therefore be cautious and
1307
- /// might avoid sending probes if liquidity is scarce and/or they don't expect the probe to
1308
- /// return before they send the payment.
1314
+ /// confirmation in a wallet UI.
1315
+ ///
1316
+ /// Otherwise, there is a chance the probe could take up some liquidity needed to complete the
1317
+ /// actual payment. Users should therefore be cautious and might avoid sending probes if
1318
+ /// liquidity is scarce and/or they don't expect the probe to return before they send the
1319
+ /// payment. To mitigate this issue, channels with available liquidity less than the required
1320
+ /// amount times [`Config::probing_liquidity_limit_multiplier`] won't be used to send
1321
+ /// pre-flight probes.
1309
1322
pub fn send_payment_probe ( & self , invoice : & Bolt11Invoice ) -> Result < ( ) , Error > {
1310
1323
let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
1311
1324
if rt_lock. is_none ( ) {
@@ -1343,10 +1356,14 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1343
1356
/// This may be used to send "pre-flight" probes, i.e., to train our scorer before conducting
1344
1357
/// the actual payment. Note this is only useful if there likely is sufficient time for the
1345
1358
/// probe to settle before sending out the actual payment, e.g., when waiting for user
1346
- /// confirmation in a wallet UI. Otherwise, there is a chance the probe could take up some
1347
- /// liquidity needed to complete the actual payment. Users should therefore be cautious and
1348
- /// might avoid sending probes if liquidity is scarce and/or they don't expect the probe to
1349
- /// return before they send the payment.
1359
+ /// confirmation in a wallet UI.
1360
+ ///
1361
+ /// Otherwise, there is a chance the probe could take up some liquidity needed to complete the
1362
+ /// actual payment. Users should therefore be cautious and might avoid sending probes if
1363
+ /// liquidity is scarce and/or they don't expect the probe to return before they send the
1364
+ /// payment. To mitigate this issue, channels with available liquidity less than the required
1365
+ /// amount times [`Config::probing_liquidity_limit_multiplier`] won't be used to send
1366
+ /// pre-flight probes.
1350
1367
pub fn send_spontaneous_payment_probe (
1351
1368
& self , amount_msat : u64 , node_id : PublicKey ,
1352
1369
) -> Result < ( ) , Error > {
@@ -1365,22 +1382,19 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1365
1382
1366
1383
fn send_payment_probe_internal ( & self , route_params : RouteParameters ) -> Result < ( ) , Error > {
1367
1384
let payer = self . channel_manager . get_our_node_id ( ) ;
1368
- let first_hops = self . channel_manager . list_usable_channels ( ) ;
1385
+ let usable_channels = self . channel_manager . list_usable_channels ( ) ;
1386
+ let first_hops = usable_channels. iter ( ) . collect :: < Vec < _ > > ( ) ;
1369
1387
let inflight_htlcs = self . channel_manager . compute_inflight_htlcs ( ) ;
1370
1388
1371
1389
let route = self
1372
1390
. router
1373
- . find_route (
1374
- & payer,
1375
- & route_params,
1376
- Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) ,
1377
- inflight_htlcs,
1378
- )
1391
+ . find_route ( & payer, & route_params, Some ( & first_hops) , inflight_htlcs)
1379
1392
. map_err ( |e| {
1380
1393
log_error ! ( self . logger, "Failed to find path for payment probe: {:?}" , e) ;
1381
1394
Error :: ProbeSendingFailed
1382
1395
} ) ?;
1383
1396
1397
+ let mut used_liquidity_map = HashMap :: with_capacity ( first_hops. len ( ) ) ;
1384
1398
for path in route. paths {
1385
1399
if path. hops . len ( ) + path. blinded_tail . as_ref ( ) . map_or ( 0 , |t| t. hops . len ( ) ) < 2 {
1386
1400
log_debug ! (
@@ -1390,6 +1404,26 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
1390
1404
continue ;
1391
1405
}
1392
1406
1407
+ if let Some ( first_path_hop) = path. hops . first ( ) {
1408
+ if let Some ( first_hop) = first_hops. iter ( ) . find ( |h| {
1409
+ h. get_outbound_payment_scid ( ) == Some ( first_path_hop. short_channel_id )
1410
+ } ) {
1411
+ let path_value = path. final_value_msat ( ) + path. fee_msat ( ) ;
1412
+ let used_liquidity =
1413
+ used_liquidity_map. entry ( first_path_hop. short_channel_id ) . or_insert ( 0 ) ;
1414
+
1415
+ if first_hop. next_outbound_htlc_limit_msat
1416
+ < ( * used_liquidity + path_value)
1417
+ * self . config . probing_liquidity_limit_multiplier
1418
+ {
1419
+ log_debug ! ( self . logger, "Skipped sending payment probe to avoid putting channel {} under the liquidity limit." , first_path_hop. short_channel_id) ;
1420
+ continue ;
1421
+ } else {
1422
+ * used_liquidity += path_value;
1423
+ }
1424
+ }
1425
+ }
1426
+
1393
1427
self . channel_manager . send_probe ( path) . map_err ( |e| {
1394
1428
log_error ! ( self . logger, "Failed to send payment probe: {:?}" , e) ;
1395
1429
Error :: ProbeSendingFailed
0 commit comments