@@ -50,6 +50,7 @@ use crate::config::{
5050 default_user_config, may_announce_channel, AnnounceError , AsyncPaymentsRole ,
5151 BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig , HRNResolverConfig ,
5252 TorConfig , DEFAULT_ESPLORA_SERVER_URL , DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL ,
53+ DEFAULT_MAX_PROBE_AMOUNT_MSAT , DEFAULT_MIN_PROBE_AMOUNT_MSAT ,
5354} ;
5455use crate :: connection:: ConnectionManager ;
5556use crate :: entropy:: NodeEntropy ;
@@ -74,6 +75,10 @@ use crate::logger::{log_error, LdkLogger, LogLevel, LogWriter, Logger};
7475use crate :: message_handler:: NodeCustomMessageHandler ;
7576use crate :: payment:: asynchronous:: om_mailbox:: OnionMessageMailbox ;
7677use crate :: peer_store:: PeerStore ;
78+ use crate :: probing:: {
79+ HighDegreeStrategy , Prober , ProbingConfig , ProbingStrategy , ProbingStrategyKind ,
80+ RandomWalkStrategy ,
81+ } ;
7782use crate :: runtime:: { Runtime , RuntimeSpawner } ;
7883use crate :: tx_broadcaster:: TransactionBroadcaster ;
7984use crate :: types:: {
@@ -306,6 +311,7 @@ pub struct NodeBuilder {
306311 async_payments_role : Option < AsyncPaymentsRole > ,
307312 runtime_handle : Option < tokio:: runtime:: Handle > ,
308313 pathfinding_scores_sync_config : Option < PathfindingScoresSyncConfig > ,
314+ probing_config : Option < ProbingConfig > ,
309315}
310316
311317impl NodeBuilder {
@@ -323,6 +329,7 @@ impl NodeBuilder {
323329 let log_writer_config = None ;
324330 let runtime_handle = None ;
325331 let pathfinding_scores_sync_config = None ;
332+ let probing_config = None ;
326333 Self {
327334 config,
328335 chain_data_source_config,
@@ -332,6 +339,7 @@ impl NodeBuilder {
332339 runtime_handle,
333340 async_payments_role : None ,
334341 pathfinding_scores_sync_config,
342+ probing_config,
335343 }
336344 }
337345
@@ -629,6 +637,31 @@ impl NodeBuilder {
629637 Ok ( self )
630638 }
631639
640+ /// Sets background probing config.
641+ ///
642+ /// Use [`ProbingConfigBuilder`] to build the configuration:
643+ /// ```no_run
644+ /// # #[cfg(not(feature = "uniffi"))]
645+ /// # {
646+ /// use std::time::Duration;
647+ /// use ldk_node::Builder;
648+ /// use ldk_node::probing::ProbingConfigBuilder;
649+ ///
650+ /// let mut builder = Builder::new();
651+ /// builder.set_probing_config(
652+ /// ProbingConfigBuilder::high_degree(100)
653+ /// .interval(Duration::from_secs(30))
654+ /// .build()
655+ /// );
656+ /// # }
657+ /// ```
658+ ///
659+ /// [`ProbingConfigBuilder`]: crate::probing::ProbingConfigBuilder
660+ pub fn set_probing_config ( & mut self , config : ProbingConfig ) -> & mut Self {
661+ self . probing_config = Some ( config) ;
662+ self
663+ }
664+
632665 /// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
633666 /// previously configured.
634667 pub fn build ( & self , node_entropy : NodeEntropy ) -> Result < Node , BuildError > {
@@ -868,6 +901,7 @@ impl NodeBuilder {
868901 self . gossip_source_config . as_ref ( ) ,
869902 self . liquidity_source_config . as_ref ( ) ,
870903 self . pathfinding_scores_sync_config . as_ref ( ) ,
904+ self . probing_config . as_ref ( ) ,
871905 self . async_payments_role ,
872906 seed_bytes,
873907 runtime,
@@ -1166,6 +1200,15 @@ impl ArcedNodeBuilder {
11661200 self . inner . write ( ) . expect ( "lock" ) . set_async_payments_role ( role) . map ( |_| ( ) )
11671201 }
11681202
1203+ /// Configures background probing.
1204+ ///
1205+ /// Use [`ProbingConfigBuilder`] to build the configuration.
1206+ ///
1207+ /// [`ProbingConfigBuilder`]: crate::probing::ProbingConfigBuilder
1208+ pub fn set_probing_config ( & self , config : Arc < ProbingConfig > ) {
1209+ self . inner . write ( ) . expect ( "lock" ) . set_probing_config ( ( * config) . clone ( ) ) ;
1210+ }
1211+
11691212 /// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
11701213 /// previously configured.
11711214 pub fn build ( & self , node_entropy : Arc < NodeEntropy > ) -> Result < Arc < Node > , BuildError > {
@@ -1361,8 +1404,8 @@ fn build_with_store_internal(
13611404 gossip_source_config : Option < & GossipSourceConfig > ,
13621405 liquidity_source_config : Option < & LiquiditySourceConfig > ,
13631406 pathfinding_scores_sync_config : Option < & PathfindingScoresSyncConfig > ,
1364- async_payments_role : Option < AsyncPaymentsRole > , seed_bytes : [ u8 ; 64 ] , runtime : Arc < Runtime > ,
1365- logger : Arc < Logger > , kv_store : Arc < DynStore > ,
1407+ probing_config : Option < & ProbingConfig > , async_payments_role : Option < AsyncPaymentsRole > ,
1408+ seed_bytes : [ u8 ; 64 ] , runtime : Arc < Runtime > , logger : Arc < Logger > , kv_store : Arc < DynStore > ,
13661409) -> Result < Node , BuildError > {
13671410 optionally_install_rustls_cryptoprovider ( ) ;
13681411
@@ -2219,6 +2262,51 @@ fn build_with_store_internal(
22192262 _leak_checker. 0 . push ( Arc :: downgrade ( & wallet) as Weak < dyn Any + Send + Sync > ) ;
22202263 }
22212264
2265+ let prober = probing_config. map ( |probing_cfg| {
2266+ let strategy: Arc < dyn ProbingStrategy > = match & probing_cfg. kind {
2267+ ProbingStrategyKind :: HighDegree { top_node_count } => {
2268+ // Dedicated router for probing so the diversity penalty doesn't interfere
2269+ // with real payments; shares the scorer so probe results still train it.
2270+ let mut probing_fee_params = ProbabilisticScoringFeeParameters :: default ( ) ;
2271+ if let Some ( penalty) = probing_cfg. diversity_penalty_msat {
2272+ probing_fee_params. probing_diversity_penalty_msat = penalty;
2273+ }
2274+ let probing_router = Arc :: new ( DefaultRouter :: new (
2275+ Arc :: clone ( & network_graph) ,
2276+ Arc :: clone ( & logger) ,
2277+ Arc :: clone ( & keys_manager) ,
2278+ Arc :: clone ( & scorer) ,
2279+ probing_fee_params,
2280+ ) ) ;
2281+ Arc :: new ( HighDegreeStrategy :: new (
2282+ Arc :: clone ( & network_graph) ,
2283+ Arc :: clone ( & channel_manager) ,
2284+ probing_router,
2285+ * top_node_count,
2286+ DEFAULT_MIN_PROBE_AMOUNT_MSAT ,
2287+ DEFAULT_MAX_PROBE_AMOUNT_MSAT ,
2288+ probing_cfg. cooldown ,
2289+ config. probing_liquidity_limit_multiplier ,
2290+ ) )
2291+ } ,
2292+ ProbingStrategyKind :: RandomWalk { max_hops } => Arc :: new ( RandomWalkStrategy :: new (
2293+ Arc :: clone ( & network_graph) ,
2294+ Arc :: clone ( & channel_manager) ,
2295+ * max_hops,
2296+ DEFAULT_MIN_PROBE_AMOUNT_MSAT ,
2297+ DEFAULT_MAX_PROBE_AMOUNT_MSAT ,
2298+ ) ) ,
2299+ ProbingStrategyKind :: Custom ( s) => Arc :: clone ( s) ,
2300+ } ;
2301+ Arc :: new ( Prober {
2302+ channel_manager : Arc :: clone ( & channel_manager) ,
2303+ logger : Arc :: clone ( & logger) ,
2304+ strategy,
2305+ interval : probing_cfg. interval ,
2306+ max_locked_msat : probing_cfg. max_locked_msat ,
2307+ } )
2308+ } ) ;
2309+
22222310 Ok ( Node {
22232311 runtime,
22242312 stop_sender,
@@ -2252,6 +2340,7 @@ fn build_with_store_internal(
22522340 om_mailbox,
22532341 async_payments_role,
22542342 hrn_resolver,
2343+ prober,
22552344 #[ cfg( cycle_tests) ]
22562345 _leak_checker,
22572346 } )
0 commit comments