@@ -4963,6 +4963,11 @@ pub(crate) mod test_utils {
4963
4963
#[ cfg( all( test, feature = "unstable" , not( feature = "no-std" ) ) ) ]
4964
4964
mod benches {
4965
4965
use super :: * ;
4966
+ use bitcoin:: hashes:: Hash ;
4967
+ use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
4968
+ use chain:: transaction:: OutPoint ;
4969
+ use ln:: channelmanager:: { ChannelCounterparty , ChannelDetails } ;
4970
+ use ln:: features:: { InitFeatures , InvoiceFeatures } ;
4966
4971
use routing:: scoring:: Scorer ;
4967
4972
use util:: logger:: { Logger , Record } ;
4968
4973
@@ -4973,72 +4978,129 @@ mod benches {
4973
4978
fn log ( & self , _record : & Record ) { }
4974
4979
}
4975
4980
4976
- #[ bench]
4977
- fn generate_routes ( bench : & mut Bencher ) {
4981
+ struct ZeroPenaltyScorer ;
4982
+ impl Score for ZeroPenaltyScorer {
4983
+ fn channel_penalty_msat (
4984
+ & self , _short_channel_id : u64 , _send_amt : u64 , _capacity_msat : Option < u64 > , _source : & NodeId , _target : & NodeId
4985
+ ) -> u64 { 0 }
4986
+ fn payment_path_failed ( & mut self , _path : & [ & RouteHop ] , _short_channel_id : u64 ) { }
4987
+ fn payment_path_successful ( & mut self , _path : & [ & RouteHop ] ) { }
4988
+ }
4989
+
4990
+ fn read_network_graph ( ) -> NetworkGraph {
4978
4991
let mut d = test_utils:: get_route_file ( ) . unwrap ( ) ;
4979
- let graph = NetworkGraph :: read ( & mut d) . unwrap ( ) ;
4980
- let nodes = graph. read_only ( ) . nodes ( ) . clone ( ) ;
4981
- let scorer = Scorer :: with_fixed_penalty ( 0 ) ;
4992
+ NetworkGraph :: read ( & mut d) . unwrap ( )
4993
+ }
4982
4994
4983
- // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
4984
- let mut path_endpoints = Vec :: new ( ) ;
4985
- let mut seed: usize = 0xdeadbeef ;
4986
- ' load_endpoints: for _ in 0 ..100 {
4987
- loop {
4988
- seed *= 0xdeadbeef ;
4989
- let src = PublicKey :: from_slice ( nodes. keys ( ) . skip ( seed % nodes. len ( ) ) . next ( ) . unwrap ( ) . as_slice ( ) ) . unwrap ( ) ;
4990
- seed *= 0xdeadbeef ;
4991
- let dst = PublicKey :: from_slice ( nodes. keys ( ) . skip ( seed % nodes. len ( ) ) . next ( ) . unwrap ( ) . as_slice ( ) ) . unwrap ( ) ;
4992
- let payment_params = PaymentParameters :: from_node_id ( dst) ;
4993
- let amt = seed as u64 % 1_000_000 ;
4994
- if get_route ( & src, & payment_params, & graph, None , amt, 42 , & DummyLogger { } , & scorer) . is_ok ( ) {
4995
- path_endpoints. push ( ( src, dst, amt) ) ;
4996
- continue ' load_endpoints;
4997
- }
4998
- }
4995
+ fn payer_pubkey ( ) -> PublicKey {
4996
+ let secp_ctx = Secp256k1 :: new ( ) ;
4997
+ PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) )
4998
+ }
4999
+
5000
+ #[ inline]
5001
+ fn first_hop ( node_id : PublicKey ) -> ChannelDetails {
5002
+ ChannelDetails {
5003
+ channel_id : [ 0 ; 32 ] ,
5004
+ counterparty : ChannelCounterparty {
5005
+ features : InitFeatures :: known ( ) ,
5006
+ node_id,
5007
+ unspendable_punishment_reserve : 0 ,
5008
+ forwarding_info : None ,
5009
+ } ,
5010
+ funding_txo : Some ( OutPoint {
5011
+ txid : bitcoin:: Txid :: from_slice ( & [ 0 ; 32 ] ) . unwrap ( ) , index : 0
5012
+ } ) ,
5013
+ short_channel_id : Some ( 1 ) ,
5014
+ channel_value_satoshis : 10_000_000 ,
5015
+ user_channel_id : 0 ,
5016
+ balance_msat : 10_000_000 ,
5017
+ outbound_capacity_msat : 10_000_000 ,
5018
+ inbound_capacity_msat : 0 ,
5019
+ unspendable_punishment_reserve : None ,
5020
+ confirmations_required : None ,
5021
+ force_close_spend_delay : None ,
5022
+ is_outbound : true ,
5023
+ is_funding_locked : true ,
5024
+ is_usable : true ,
5025
+ is_public : true ,
4999
5026
}
5027
+ }
5000
5028
5001
- // ...then benchmark finding paths between the nodes we learned.
5002
- let mut idx = 0 ;
5003
- bench. iter ( || {
5004
- let ( src, dst, amt) = path_endpoints[ idx % path_endpoints. len ( ) ] ;
5005
- let payment_params = PaymentParameters :: from_node_id ( dst) ;
5006
- assert ! ( get_route( & src, & payment_params, & graph, None , amt, 42 , & DummyLogger { } , & scorer) . is_ok( ) ) ;
5007
- idx += 1 ;
5008
- } ) ;
5029
+ #[ bench]
5030
+ fn generate_routes_with_zero_penalty_scorer ( bench : & mut Bencher ) {
5031
+ let network_graph = read_network_graph ( ) ;
5032
+ let scorer = ZeroPenaltyScorer ;
5033
+ generate_routes ( bench, & network_graph, scorer, InvoiceFeatures :: empty ( ) ) ;
5009
5034
}
5010
5035
5011
5036
#[ bench]
5012
- fn generate_mpp_routes ( bench : & mut Bencher ) {
5013
- let mut d = test_utils:: get_route_file ( ) . unwrap ( ) ;
5014
- let graph = NetworkGraph :: read ( & mut d) . unwrap ( ) ;
5037
+ fn generate_mpp_routes_with_zero_penalty_scorer ( bench : & mut Bencher ) {
5038
+ let network_graph = read_network_graph ( ) ;
5039
+ let scorer = ZeroPenaltyScorer ;
5040
+ generate_routes ( bench, & network_graph, scorer, InvoiceFeatures :: known ( ) ) ;
5041
+ }
5042
+
5043
+ #[ bench]
5044
+ fn generate_routes_with_default_scorer ( bench : & mut Bencher ) {
5045
+ let network_graph = read_network_graph ( ) ;
5046
+ let scorer = Scorer :: default ( ) ;
5047
+ generate_routes ( bench, & network_graph, scorer, InvoiceFeatures :: empty ( ) ) ;
5048
+ }
5049
+
5050
+ #[ bench]
5051
+ fn generate_mpp_routes_with_default_scorer ( bench : & mut Bencher ) {
5052
+ let network_graph = read_network_graph ( ) ;
5053
+ let scorer = Scorer :: default ( ) ;
5054
+ generate_routes ( bench, & network_graph, scorer, InvoiceFeatures :: known ( ) ) ;
5055
+ }
5056
+
5057
+ fn generate_routes < S : Score > (
5058
+ bench : & mut Bencher , graph : & NetworkGraph , mut scorer : S , features : InvoiceFeatures
5059
+ ) {
5015
5060
let nodes = graph. read_only ( ) . nodes ( ) . clone ( ) ;
5016
- let scorer = Scorer :: with_fixed_penalty ( 0 ) ;
5061
+ let payer = payer_pubkey ( ) ;
5017
5062
5018
5063
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
5019
- let mut path_endpoints = Vec :: new ( ) ;
5064
+ let mut routes = Vec :: new ( ) ;
5065
+ let mut route_endpoints = Vec :: new ( ) ;
5020
5066
let mut seed: usize = 0xdeadbeef ;
5021
5067
' load_endpoints: for _ in 0 ..100 {
5022
5068
loop {
5023
5069
seed *= 0xdeadbeef ;
5024
5070
let src = PublicKey :: from_slice ( nodes. keys ( ) . skip ( seed % nodes. len ( ) ) . next ( ) . unwrap ( ) . as_slice ( ) ) . unwrap ( ) ;
5025
5071
seed *= 0xdeadbeef ;
5026
5072
let dst = PublicKey :: from_slice ( nodes. keys ( ) . skip ( seed % nodes. len ( ) ) . next ( ) . unwrap ( ) . as_slice ( ) ) . unwrap ( ) ;
5027
- let payment_params = PaymentParameters :: from_node_id ( dst) . with_features ( InvoiceFeatures :: known ( ) ) ;
5073
+ let params = PaymentParameters :: from_node_id ( dst) . with_features ( features. clone ( ) ) ;
5074
+ let first_hop = first_hop ( src) ;
5028
5075
let amt = seed as u64 % 1_000_000 ;
5029
- if get_route ( & src, & payment_params, & graph, None , amt, 42 , & DummyLogger { } , & scorer) . is_ok ( ) {
5030
- path_endpoints. push ( ( src, dst, amt) ) ;
5076
+ if let Ok ( route) = get_route ( & payer, & params, & graph, Some ( & [ & first_hop] ) , amt, 42 , & DummyLogger { } , & scorer) {
5077
+ routes. push ( route) ;
5078
+ route_endpoints. push ( ( first_hop, params, amt) ) ;
5031
5079
continue ' load_endpoints;
5032
5080
}
5033
5081
}
5034
5082
}
5035
5083
5084
+ // ...and seed the scorer with success and failure data...
5085
+ for route in routes {
5086
+ let amount = route. get_total_amount ( ) ;
5087
+ if amount < 250_000 {
5088
+ for path in route. paths {
5089
+ scorer. payment_path_successful ( & path. iter ( ) . collect :: < Vec < _ > > ( ) ) ;
5090
+ }
5091
+ } else if amount > 750_000 {
5092
+ for path in route. paths {
5093
+ let short_channel_id = path[ path. len ( ) / 2 ] . short_channel_id ;
5094
+ scorer. payment_path_failed ( & path. iter ( ) . collect :: < Vec < _ > > ( ) , short_channel_id) ;
5095
+ }
5096
+ }
5097
+ }
5098
+
5036
5099
// ...then benchmark finding paths between the nodes we learned.
5037
5100
let mut idx = 0 ;
5038
5101
bench. iter ( || {
5039
- let ( src, dst, amt) = path_endpoints[ idx % path_endpoints. len ( ) ] ;
5040
- let payment_params = PaymentParameters :: from_node_id ( dst) . with_features ( InvoiceFeatures :: known ( ) ) ;
5041
- assert ! ( get_route( & src, & payment_params, & graph, None , amt, 42 , & DummyLogger { } , & scorer) . is_ok( ) ) ;
5102
+ let ( first_hop, params, amt) = & route_endpoints[ idx % route_endpoints. len ( ) ] ;
5103
+ assert ! ( get_route( & payer, params, & graph, Some ( & [ first_hop] ) , * amt, 42 , & DummyLogger { } , & scorer) . is_ok( ) ) ;
5042
5104
idx += 1 ;
5043
5105
} ) ;
5044
5106
}
0 commit comments