@@ -24,10 +24,12 @@ use lightning::io::Cursor;
2424use lightning:: ln:: channelmanager:: { self , ChainParameters , ChannelManagerReadArgs } ;
2525use lightning:: ln:: msgs:: { RoutingMessageHandler , SocketAddress } ;
2626use lightning:: ln:: peer_handler:: { IgnoringMessageHandler , MessageHandler } ;
27+ use lightning:: log_trace;
2728use lightning:: routing:: gossip:: NodeAlias ;
2829use lightning:: routing:: router:: DefaultRouter ;
2930use lightning:: routing:: scoring:: {
30- ProbabilisticScorer , ProbabilisticScoringDecayParameters , ProbabilisticScoringFeeParameters ,
31+ CombinedScorer , ProbabilisticScorer , ProbabilisticScoringDecayParameters ,
32+ ProbabilisticScoringFeeParameters ,
3133} ;
3234use lightning:: sign:: { EntropySource , NodeSigner } ;
3335use lightning:: util:: persist:: {
@@ -50,7 +52,9 @@ use crate::event::EventQueue;
5052use crate :: fee_estimator:: OnchainFeeEstimator ;
5153use crate :: gossip:: GossipSource ;
5254use crate :: io:: sqlite_store:: SqliteStore ;
53- use crate :: io:: utils:: { read_node_metrics, write_node_metrics} ;
55+ use crate :: io:: utils:: {
56+ read_external_pathfinding_scores_from_cache, read_node_metrics, write_node_metrics,
57+ } ;
5458use crate :: io:: vss_store:: VssStore ;
5559use crate :: io:: {
5660 self , PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE , PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE ,
@@ -110,6 +114,11 @@ enum GossipSourceConfig {
110114 RapidGossipSync ( String ) ,
111115}
112116
117+ #[ derive( Debug , Clone ) ]
118+ struct PathfindingScoresSyncConfig {
119+ url : String ,
120+ }
121+
113122#[ derive( Debug , Clone , Default ) ]
114123struct LiquiditySourceConfig {
115124 // Act as an LSPS1 client connecting to the given service.
@@ -243,6 +252,7 @@ pub struct NodeBuilder {
243252 log_writer_config : Option < LogWriterConfig > ,
244253 async_payments_role : Option < AsyncPaymentsRole > ,
245254 runtime_handle : Option < tokio:: runtime:: Handle > ,
255+ pathfinding_scores_sync_config : Option < PathfindingScoresSyncConfig > ,
246256}
247257
248258impl NodeBuilder {
@@ -260,6 +270,7 @@ impl NodeBuilder {
260270 let liquidity_source_config = None ;
261271 let log_writer_config = None ;
262272 let runtime_handle = None ;
273+ let pathfinding_scores_sync_config = None ;
263274 Self {
264275 config,
265276 entropy_source_config,
@@ -269,6 +280,7 @@ impl NodeBuilder {
269280 log_writer_config,
270281 runtime_handle,
271282 async_payments_role : None ,
283+ pathfinding_scores_sync_config,
272284 }
273285 }
274286
@@ -411,6 +423,14 @@ impl NodeBuilder {
411423 self
412424 }
413425
426+ /// Configures the [`Node`] instance to source its external scores from the given URL.
427+ ///
428+ /// The external scores are merged into the local scoring system to improve routing.
429+ pub fn set_pathfinding_scores_source ( & mut self , url : String ) -> & mut Self {
430+ self . pathfinding_scores_sync_config = Some ( PathfindingScoresSyncConfig { url } ) ;
431+ self
432+ }
433+
414434 /// Configures the [`Node`] instance to source inbound liquidity from the given
415435 /// [bLIP-51 / LSPS1] service.
416436 ///
@@ -718,6 +738,7 @@ impl NodeBuilder {
718738 self . chain_data_source_config . as_ref ( ) ,
719739 self . gossip_source_config . as_ref ( ) ,
720740 self . liquidity_source_config . as_ref ( ) ,
741+ self . pathfinding_scores_sync_config . as_ref ( ) ,
721742 self . async_payments_role ,
722743 seed_bytes,
723744 runtime,
@@ -751,6 +772,7 @@ impl NodeBuilder {
751772 self . chain_data_source_config . as_ref ( ) ,
752773 self . gossip_source_config . as_ref ( ) ,
753774 self . liquidity_source_config . as_ref ( ) ,
775+ self . pathfinding_scores_sync_config . as_ref ( ) ,
754776 self . async_payments_role ,
755777 seed_bytes,
756778 runtime,
@@ -910,6 +932,13 @@ impl ArcedNodeBuilder {
910932 self . inner . write ( ) . unwrap ( ) . set_gossip_source_rgs ( rgs_server_url) ;
911933 }
912934
935+ /// Configures the [`Node`] instance to source its external scores from the given URL.
936+ ///
937+ /// The external scores are merged into the local scoring system to improve routing.
938+ pub fn set_pathfinding_scores_source ( & self , url : String ) {
939+ self . inner . write ( ) . unwrap ( ) . set_pathfinding_scores_source ( url) ;
940+ }
941+
913942 /// Configures the [`Node`] instance to source inbound liquidity from the given
914943 /// [bLIP-51 / LSPS1] service.
915944 ///
@@ -1110,6 +1139,7 @@ fn build_with_store_internal(
11101139 config : Arc < Config > , chain_data_source_config : Option < & ChainDataSourceConfig > ,
11111140 gossip_source_config : Option < & GossipSourceConfig > ,
11121141 liquidity_source_config : Option < & LiquiditySourceConfig > ,
1142+ pathfinding_scores_sync_config : Option < & PathfindingScoresSyncConfig > ,
11131143 async_payments_role : Option < AsyncPaymentsRole > , seed_bytes : [ u8 ; 64 ] , runtime : Arc < Runtime > ,
11141144 logger : Arc < Logger > , kv_store : Arc < DynStore > ,
11151145) -> Result < Node , BuildError > {
@@ -1365,26 +1395,38 @@ fn build_with_store_internal(
13651395 } ,
13661396 } ;
13671397
1368- let scorer = match io:: utils:: read_scorer (
1398+ let local_scorer = match io:: utils:: read_scorer (
13691399 Arc :: clone ( & kv_store) ,
13701400 Arc :: clone ( & network_graph) ,
13711401 Arc :: clone ( & logger) ,
13721402 ) {
1373- Ok ( scorer) => Arc :: new ( Mutex :: new ( scorer) ) ,
1403+ Ok ( scorer) => scorer,
13741404 Err ( e) => {
13751405 if e. kind ( ) == std:: io:: ErrorKind :: NotFound {
13761406 let params = ProbabilisticScoringDecayParameters :: default ( ) ;
1377- Arc :: new ( Mutex :: new ( ProbabilisticScorer :: new (
1378- params,
1379- Arc :: clone ( & network_graph) ,
1380- Arc :: clone ( & logger) ,
1381- ) ) )
1407+ ProbabilisticScorer :: new ( params, Arc :: clone ( & network_graph) , Arc :: clone ( & logger) )
13821408 } else {
13831409 return Err ( BuildError :: ReadFailed ) ;
13841410 }
13851411 } ,
13861412 } ;
13871413
1414+ let scorer = Arc :: new ( Mutex :: new ( CombinedScorer :: new ( local_scorer) ) ) ;
1415+
1416+ // Restore external pathfinding scores from cache if possible.
1417+ match read_external_pathfinding_scores_from_cache ( Arc :: clone ( & kv_store) , Arc :: clone ( & logger) ) {
1418+ Ok ( external_scores) => {
1419+ scorer. lock ( ) . unwrap ( ) . merge ( external_scores, cur_time) ;
1420+ log_trace ! ( logger, "External scores from cache merged successfully" ) ;
1421+ } ,
1422+ Err ( e) => {
1423+ if e. kind ( ) != std:: io:: ErrorKind :: NotFound {
1424+ log_error ! ( logger, "Error while reading external scores from cache: {}" , e) ;
1425+ return Err ( BuildError :: ReadFailed ) ;
1426+ }
1427+ } ,
1428+ }
1429+
13881430 let scoring_fee_params = ProbabilisticScoringFeeParameters :: default ( ) ;
13891431 let router = Arc :: new ( DefaultRouter :: new (
13901432 Arc :: clone ( & network_graph) ,
@@ -1716,6 +1758,8 @@ fn build_with_store_internal(
17161758 let ( background_processor_stop_sender, _) = tokio:: sync:: watch:: channel ( ( ) ) ;
17171759 let is_running = Arc :: new ( RwLock :: new ( false ) ) ;
17181760
1761+ let pathfinding_scores_sync_url = pathfinding_scores_sync_config. map ( |c| c. url . clone ( ) ) ;
1762+
17191763 Ok ( Node {
17201764 runtime,
17211765 stop_sender,
@@ -1734,6 +1778,7 @@ fn build_with_store_internal(
17341778 keys_manager,
17351779 network_graph,
17361780 gossip_source,
1781+ pathfinding_scores_sync_url,
17371782 liquidity_source,
17381783 kv_store,
17391784 logger,
0 commit comments