@@ -18,7 +18,7 @@ use lightning::ln::msgs::{
1818use lightning:: ln:: { PaymentHash , PaymentPreimage } ;
1919use lightning:: routing:: gossip:: { NetworkGraph , NodeId } ;
2020use lightning:: routing:: router:: { find_route, Path , PaymentParameters , Route , RouteParameters } ;
21- use lightning:: routing:: scoring:: ProbabilisticScorer ;
21+ use lightning:: routing:: scoring:: { ProbabilisticScorer , ProbabilisticScoringDecayParameters } ;
2222use lightning:: routing:: utxo:: { UtxoLookup , UtxoResult } ;
2323use lightning:: util:: logger:: { Level , Logger , Record } ;
2424use thiserror:: Error ;
@@ -455,6 +455,9 @@ struct SimNode<'a, T: SimNetwork> {
455455 in_flight : HashMap < PaymentHash , Receiver < Result < PaymentResult , LightningError > > > ,
456456 /// A read-only graph used for pathfinding.
457457 pathfinding_graph : Arc < NetworkGraph < & ' a WrappedLog > > ,
458+ /// Probabilistic scorer used to rank paths through the network for routing. This is reused across
459+ /// multiple payments to maintain scoring state.
460+ scorer : ProbabilisticScorer < Arc < NetworkGraph < & ' a WrappedLog > > , & ' a WrappedLog > ,
458461}
459462
460463impl < ' a , T : SimNetwork > SimNode < ' a , T > {
@@ -465,11 +468,21 @@ impl<'a, T: SimNetwork> SimNode<'a, T> {
465468 payment_network : Arc < Mutex < T > > ,
466469 pathfinding_graph : Arc < NetworkGraph < & ' a WrappedLog > > ,
467470 ) -> Self {
471+ // Initialize the probabilistic scorer with default parameters for learning from payment
472+ // history. These parameters control how much successful/failed payments affect routing
473+ // scores and how quickly these scores decay over time.
474+ let scorer = ProbabilisticScorer :: new (
475+ ProbabilisticScoringDecayParameters :: default ( ) ,
476+ pathfinding_graph. clone ( ) ,
477+ & WrappedLog { } ,
478+ ) ;
479+
468480 SimNode {
469481 info : node_info ( pubkey) ,
470482 network : payment_network,
471483 in_flight : HashMap :: new ( ) ,
472484 pathfinding_graph,
485+ scorer,
473486 }
474487 }
475488}
@@ -489,14 +502,13 @@ fn node_info(pubkey: PublicKey) -> NodeInfo {
489502
490503/// Uses LDK's pathfinding algorithm with default parameters to find a path from source to destination, with no
491504/// restrictions on fee budget.
492- fn find_payment_route (
505+ fn find_payment_route < ' a > (
493506 source : & PublicKey ,
494507 dest : PublicKey ,
495508 amount_msat : u64 ,
496- pathfinding_graph : & NetworkGraph < & WrappedLog > ,
509+ pathfinding_graph : & NetworkGraph < & ' a WrappedLog > ,
510+ scorer : & ProbabilisticScorer < Arc < NetworkGraph < & ' a WrappedLog > > , & ' a WrappedLog > ,
497511) -> Result < Route , SimulationError > {
498- let scorer = ProbabilisticScorer :: new ( Default :: default ( ) , pathfinding_graph, & WrappedLog { } ) ;
499-
500512 find_route (
501513 source,
502514 & RouteParameters {
@@ -512,7 +524,7 @@ fn find_payment_route(
512524 pathfinding_graph,
513525 None ,
514526 & WrappedLog { } ,
515- & scorer,
527+ scorer,
516528 & Default :: default ( ) ,
517529 & [ 0 ; 32 ] ,
518530 )
@@ -554,11 +566,13 @@ impl<T: SimNetwork> LightningNode for SimNode<'_, T> {
554566 } ,
555567 }
556568
569+ // Use the stored scorer when finding a route
557570 let route = match find_payment_route (
558571 & self . info . pubkey ,
559572 dest,
560573 amount_msat,
561574 & self . pathfinding_graph ,
575+ & self . scorer ,
562576 ) {
563577 Ok ( path) => path,
564578 // In the case that we can't find a route for the payment, we still report a successful payment *api call*
@@ -1543,7 +1557,8 @@ mod tests {
15431557 struct DispatchPaymentTestKit < ' a > {
15441558 graph : SimGraph ,
15451559 nodes : Vec < PublicKey > ,
1546- routing_graph : NetworkGraph < & ' a WrappedLog > ,
1560+ routing_graph : Arc < NetworkGraph < & ' a WrappedLog > > ,
1561+ scorer : ProbabilisticScorer < Arc < NetworkGraph < & ' a WrappedLog > > , & ' a WrappedLog > ,
15471562 shutdown : triggered:: Trigger ,
15481563 }
15491564
@@ -1557,6 +1572,13 @@ mod tests {
15571572 async fn new ( capacity : u64 ) -> Self {
15581573 let ( shutdown, _listener) = triggered:: trigger ( ) ;
15591574 let channels = create_simulated_channels ( 3 , capacity) ;
1575+ let routing_graph = Arc :: new ( populate_network_graph ( channels. clone ( ) ) . unwrap ( ) ) ;
1576+
1577+ let scorer = ProbabilisticScorer :: new (
1578+ ProbabilisticScoringDecayParameters :: default ( ) ,
1579+ routing_graph. clone ( ) ,
1580+ & WrappedLog { } ,
1581+ ) ;
15601582
15611583 // Collect pubkeys in-order, pushing the last node on separately because they don't have an outgoing
15621584 // channel (they are not node_1 in any channel, only node_2).
@@ -1570,7 +1592,8 @@ mod tests {
15701592 graph : SimGraph :: new ( channels. clone ( ) , TaskTracker :: new ( ) , shutdown. clone ( ) )
15711593 . expect ( "could not create test graph" ) ,
15721594 nodes,
1573- routing_graph : populate_network_graph ( channels) . unwrap ( ) ,
1595+ routing_graph,
1596+ scorer,
15741597 shutdown,
15751598 } ;
15761599
@@ -1614,7 +1637,8 @@ mod tests {
16141637 dest : PublicKey ,
16151638 amt : u64 ,
16161639 ) -> Route {
1617- let route = find_payment_route ( & source, dest, amt, & self . routing_graph ) . unwrap ( ) ;
1640+ let route =
1641+ find_payment_route ( & source, dest, amt, & self . routing_graph , & self . scorer ) . unwrap ( ) ;
16181642
16191643 let ( sender, receiver) = oneshot:: channel ( ) ;
16201644 self . graph
0 commit comments