@@ -18,7 +18,7 @@ use lightning::ln::msgs::{
18
18
use lightning:: ln:: { PaymentHash , PaymentPreimage } ;
19
19
use lightning:: routing:: gossip:: { NetworkGraph , NodeId } ;
20
20
use lightning:: routing:: router:: { find_route, Path , PaymentParameters , Route , RouteParameters } ;
21
- use lightning:: routing:: scoring:: ProbabilisticScorer ;
21
+ use lightning:: routing:: scoring:: { ProbabilisticScorer , ProbabilisticScoringDecayParameters } ;
22
22
use lightning:: routing:: utxo:: { UtxoLookup , UtxoResult } ;
23
23
use lightning:: util:: logger:: { Level , Logger , Record } ;
24
24
use thiserror:: Error ;
@@ -455,6 +455,9 @@ struct SimNode<'a, T: SimNetwork> {
455
455
in_flight : HashMap < PaymentHash , Receiver < Result < PaymentResult , LightningError > > > ,
456
456
/// A read-only graph used for pathfinding.
457
457
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 > ,
458
461
}
459
462
460
463
impl < ' a , T : SimNetwork > SimNode < ' a , T > {
@@ -465,11 +468,21 @@ impl<'a, T: SimNetwork> SimNode<'a, T> {
465
468
payment_network : Arc < Mutex < T > > ,
466
469
pathfinding_graph : Arc < NetworkGraph < & ' a WrappedLog > > ,
467
470
) -> 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
+
468
480
SimNode {
469
481
info : node_info ( pubkey) ,
470
482
network : payment_network,
471
483
in_flight : HashMap :: new ( ) ,
472
484
pathfinding_graph,
485
+ scorer,
473
486
}
474
487
}
475
488
}
@@ -489,14 +502,13 @@ fn node_info(pubkey: PublicKey) -> NodeInfo {
489
502
490
503
/// Uses LDK's pathfinding algorithm with default parameters to find a path from source to destination, with no
491
504
/// restrictions on fee budget.
492
- fn find_payment_route (
505
+ fn find_payment_route < ' a > (
493
506
source : & PublicKey ,
494
507
dest : PublicKey ,
495
508
amount_msat : u64 ,
496
- pathfinding_graph : & NetworkGraph < & WrappedLog > ,
509
+ pathfinding_graph : & NetworkGraph < & ' a WrappedLog > ,
510
+ scorer : & ProbabilisticScorer < Arc < NetworkGraph < & ' a WrappedLog > > , & ' a WrappedLog > ,
497
511
) -> Result < Route , SimulationError > {
498
- let scorer = ProbabilisticScorer :: new ( Default :: default ( ) , pathfinding_graph, & WrappedLog { } ) ;
499
-
500
512
find_route (
501
513
source,
502
514
& RouteParameters {
@@ -512,7 +524,7 @@ fn find_payment_route(
512
524
pathfinding_graph,
513
525
None ,
514
526
& WrappedLog { } ,
515
- & scorer,
527
+ scorer,
516
528
& Default :: default ( ) ,
517
529
& [ 0 ; 32 ] ,
518
530
)
@@ -554,11 +566,13 @@ impl<T: SimNetwork> LightningNode for SimNode<'_, T> {
554
566
} ,
555
567
}
556
568
569
+ // Use the stored scorer when finding a route
557
570
let route = match find_payment_route (
558
571
& self . info . pubkey ,
559
572
dest,
560
573
amount_msat,
561
574
& self . pathfinding_graph ,
575
+ & self . scorer ,
562
576
) {
563
577
Ok ( path) => path,
564
578
// 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 {
1543
1557
struct DispatchPaymentTestKit < ' a > {
1544
1558
graph : SimGraph ,
1545
1559
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 > ,
1547
1562
shutdown : triggered:: Trigger ,
1548
1563
}
1549
1564
@@ -1557,6 +1572,13 @@ mod tests {
1557
1572
async fn new ( capacity : u64 ) -> Self {
1558
1573
let ( shutdown, _listener) = triggered:: trigger ( ) ;
1559
1574
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
+ ) ;
1560
1582
1561
1583
// Collect pubkeys in-order, pushing the last node on separately because they don't have an outgoing
1562
1584
// channel (they are not node_1 in any channel, only node_2).
@@ -1570,7 +1592,8 @@ mod tests {
1570
1592
graph : SimGraph :: new ( channels. clone ( ) , TaskTracker :: new ( ) , shutdown. clone ( ) )
1571
1593
. expect ( "could not create test graph" ) ,
1572
1594
nodes,
1573
- routing_graph : populate_network_graph ( channels) . unwrap ( ) ,
1595
+ routing_graph,
1596
+ scorer,
1574
1597
shutdown,
1575
1598
} ;
1576
1599
@@ -1614,7 +1637,8 @@ mod tests {
1614
1637
dest : PublicKey ,
1615
1638
amt : u64 ,
1616
1639
) -> 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 ( ) ;
1618
1642
1619
1643
let ( sender, receiver) = oneshot:: channel ( ) ;
1620
1644
self . graph
0 commit comments