diff --git a/bindings/ldk_node.udl b/bindings/ldk_node.udl index 326de194da..14f65811de 100644 --- a/bindings/ldk_node.udl +++ b/bindings/ldk_node.udl @@ -42,6 +42,8 @@ interface ProbingConfigBuilder { void set_max_locked_msat(u64 max_msat); void set_diversity_penalty_msat(u64 penalty_msat); void set_cooldown(u64 secs); + [Throws=ProbingConfigError] + void set_amount_range_msat(u64 min_msat, u64 max_msat); ProbingConfig build(); }; @@ -219,6 +221,8 @@ typedef dictionary NodeStatus; typedef enum BuildError; +typedef enum ProbingConfigError; + [Trait, WithForeign] interface VssHeaderProvider { [Async, Throws=VssHeaderProviderError] diff --git a/src/builder.rs b/src/builder.rs index 54e79f4b3a..acb72ad890 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -59,8 +59,7 @@ use crate::config::{ default_user_config, may_announce_channel, AnnounceError, AsyncPaymentsRole, Config, ElectrumSyncConfig, EsploraSyncConfig, HRNResolverConfig, TorConfig, CHANNEL_TX_FACTS_CACHE_CAPACITY, CHANNEL_TX_FACTS_CACHE_WARMUP_COUNT, - DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL, - DEFAULT_MAX_PROBE_AMOUNT_MSAT, DEFAULT_MIN_PROBE_AMOUNT_MSAT, PAYMENT_CACHE_CAPACITY, + DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL, PAYMENT_CACHE_CAPACITY, PAYMENT_CACHE_WARMUP_COUNT, }; use crate::connection::ConnectionManager; @@ -2526,8 +2525,8 @@ fn build_with_store_internal( Arc::clone(&channel_manager), probing_router, *top_node_count, - DEFAULT_MIN_PROBE_AMOUNT_MSAT, - DEFAULT_MAX_PROBE_AMOUNT_MSAT, + probing_cfg.min_amount_msat, + probing_cfg.max_amount_msat, probing_cfg.cooldown, config.probing_liquidity_limit_multiplier, )) @@ -2536,8 +2535,8 @@ fn build_with_store_internal( Arc::clone(&network_graph), Arc::clone(&channel_manager), *max_hops, - DEFAULT_MIN_PROBE_AMOUNT_MSAT, - DEFAULT_MAX_PROBE_AMOUNT_MSAT, + probing_cfg.min_amount_msat, + probing_cfg.max_amount_msat, )), ProbingStrategyKind::Custom(s) => Arc::clone(s), }; diff --git a/src/lib.rs b/src/lib.rs index a5f2a72e18..6fcd257bd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -186,6 +186,7 @@ use payment::{HRNResolver, UnifiedPayment}; use peer_store::{PeerInfo, PeerStore}; #[cfg(feature = "uniffi")] pub use probing::ArcedProbingConfigBuilder as ProbingConfigBuilder; +pub use probing::ProbingConfigError; use probing::{run_prober, Prober}; use runtime::Runtime; pub use tokio; diff --git a/src/probing.rs b/src/probing.rs index 7a17cd2fad..42beda5301 100644 --- a/src/probing.rs +++ b/src/probing.rs @@ -79,8 +79,8 @@ use lightning_invoice::DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA; use lightning_types::features::{ChannelFeatures, NodeFeatures}; use crate::config::{ - DEFAULT_MAX_PROBE_LOCKED_MSAT, DEFAULT_PROBED_NODE_COOLDOWN_SECS, - DEFAULT_PROBING_INTERVAL_SECS, MIN_PROBING_INTERVAL, + DEFAULT_MAX_PROBE_AMOUNT_MSAT, DEFAULT_MAX_PROBE_LOCKED_MSAT, DEFAULT_MIN_PROBE_AMOUNT_MSAT, + DEFAULT_PROBED_NODE_COOLDOWN_SECS, DEFAULT_PROBING_INTERVAL_SECS, MIN_PROBING_INTERVAL, }; use crate::logger::{log_debug, LdkLogger, Logger}; use crate::types::{ChannelManager, Graph, Router}; @@ -165,8 +165,28 @@ pub struct ProbingConfig { pub(crate) max_locked_msat: u64, pub(crate) diversity_penalty_msat: Option, pub(crate) cooldown: Duration, + pub(crate) min_amount_msat: u64, + pub(crate) max_amount_msat: u64, } +/// An error that could arise when configuring a [`ProbingConfig`]. +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Error))] +pub enum ProbingConfigError { + /// The given probe amount range is invalid, i.e., its minimum exceeds its maximum. + InvalidAmountRange, +} + +impl fmt::Display for ProbingConfigError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::InvalidAmountRange => write!(f, "Given probe amount range is invalid."), + } + } +} + +impl std::error::Error for ProbingConfigError {} + /// Builder for [`ProbingConfig`]. /// /// A new instance starts from one of three strategy constructors — [`high_degree`], @@ -183,6 +203,8 @@ pub struct ProbingConfigBuilder { max_locked_msat: u64, diversity_penalty_msat: Option, cooldown: Duration, + min_amount_msat: u64, + max_amount_msat: u64, } impl ProbingConfigBuilder { @@ -193,6 +215,8 @@ impl ProbingConfigBuilder { max_locked_msat: DEFAULT_MAX_PROBE_LOCKED_MSAT, diversity_penalty_msat: None, cooldown: Duration::from_secs(DEFAULT_PROBED_NODE_COOLDOWN_SECS), + min_amount_msat: DEFAULT_MIN_PROBE_AMOUNT_MSAT, + max_amount_msat: DEFAULT_MAX_PROBE_AMOUNT_MSAT, } } @@ -256,6 +280,28 @@ impl ProbingConfigBuilder { self } + /// Overrides the bounds each probe's amount is uniformly drawn from. + /// + /// Only applies to the built-in strategies; custom strategies choose their + /// own probe amounts when building paths. Larger amounts teach the scorer + /// about liquidity in the range of larger payments, at the cost of locking + /// more liquidity per in-flight probe — size `max_locked_msat` accordingly. + /// + /// Defaults to 1 000 000 - 10 000 000 msat (1k - 10k sats). + /// + /// Returns [`ProbingConfigError::InvalidAmountRange`] if `min_msat` exceeds `max_msat`. + pub fn amount_range_msat( + &mut self, min_msat: u64, max_msat: u64, + ) -> Result<&mut Self, ProbingConfigError> { + if min_msat > max_msat { + return Err(ProbingConfigError::InvalidAmountRange); + } + + self.min_amount_msat = min_msat; + self.max_amount_msat = max_msat; + Ok(self) + } + /// Builds the [`ProbingConfig`]. pub fn build(&self) -> ProbingConfig { ProbingConfig { @@ -264,6 +310,8 @@ impl ProbingConfigBuilder { max_locked_msat: self.max_locked_msat, diversity_penalty_msat: self.diversity_penalty_msat, cooldown: self.cooldown, + min_amount_msat: self.min_amount_msat, + max_amount_msat: self.max_amount_msat, } } } @@ -335,6 +383,20 @@ impl ArcedProbingConfigBuilder { self.inner.write().expect("lock").cooldown(Duration::from_secs(secs)); } + /// Overrides the bounds each probe's amount is uniformly drawn from. + /// + /// Only applies to the built-in strategies; custom strategies choose their + /// own probe amounts when building paths. + /// + /// Defaults to 1 000 000 - 10 000 000 msat (1k - 10k sats). + /// + /// Returns [`ProbingConfigError::InvalidAmountRange`] if `min_msat` exceeds `max_msat`. + pub fn set_amount_range_msat( + &self, min_msat: u64, max_msat: u64, + ) -> Result<(), ProbingConfigError> { + self.inner.write().expect("lock").amount_range_msat(min_msat, max_msat).map(|_| ()) + } + /// Builds the [`ProbingConfig`]. pub fn build(&self) -> Arc { Arc::new(self.inner.read().expect("lock").build())