Skip to content

Commit 7eb7a84

Browse files
committed
Add an additional test/bench for routing larger amounts, score more
When benchmarking our router, we previously only ever tested with amounts under 1,000 sats, which is an incredibly small amount. While this ensures we have the maximal number of available channels to consider, it prevents our scorer from getting exercise across its range. Further, we only score the immediate path we are expecting to to send over, and not randomly but rather based on the amount sent. Here we try to make the benchmarks a bit more realistic by adding a new benchmark which attempts to send around 100K sats, which is a reasonable amount to send over a channel today. We also convert the scoring data to be randomized based on the seed as well as attempt to (possibly) find a new route for a much larger value and score based on that. This potentially allows us to score multiple potential paths between the source and destination as the large route-find may return an MPP result.
1 parent 4116620 commit 7eb7a84

File tree

1 file changed

+85
-39
lines changed

1 file changed

+85
-39
lines changed

lightning/src/routing/router.rs

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5684,7 +5684,7 @@ mod tests {
56845684
let mut scorer = ProbabilisticScorer::new(params, &graph, &logger);
56855685
let features = super::InvoiceFeatures::empty();
56865686

5687-
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed() as usize, 2);
5687+
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed(), 0, 2);
56885688
}
56895689

56905690
#[test]
@@ -5706,7 +5706,29 @@ mod tests {
57065706
let mut scorer = ProbabilisticScorer::new(params, &graph, &logger);
57075707
let features = channelmanager::provided_invoice_features(&UserConfig::default());
57085708

5709-
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed() as usize, 2);
5709+
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed(), 0, 2);
5710+
}
5711+
5712+
#[test]
5713+
#[cfg(not(feature = "no-std"))]
5714+
fn generate_large_mpp_routes() {
5715+
use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters};
5716+
5717+
let mut d = match super::bench_utils::get_route_file() {
5718+
Ok(f) => f,
5719+
Err(e) => {
5720+
eprintln!("{}", e);
5721+
return;
5722+
},
5723+
};
5724+
let logger = ln_test_utils::TestLogger::new();
5725+
let graph = NetworkGraph::read(&mut d, &logger).unwrap();
5726+
5727+
let params = ProbabilisticScoringParameters::default();
5728+
let mut scorer = ProbabilisticScorer::new(params, &graph, &logger);
5729+
let features = channelmanager::provided_invoice_features(&UserConfig::default());
5730+
5731+
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed(), 1_000_000, 2);
57105732
}
57115733

57125734
#[test]
@@ -5960,11 +5982,11 @@ pub(crate) mod bench_utils {
59605982
short_channel_id: Some(1),
59615983
inbound_scid_alias: None,
59625984
outbound_scid_alias: None,
5963-
channel_value_satoshis: 10_000_000,
5985+
channel_value_satoshis: 10_000_000_000,
59645986
user_channel_id: 0,
5965-
balance_msat: 10_000_000,
5966-
outbound_capacity_msat: 10_000_000,
5967-
next_outbound_htlc_limit_msat: 10_000_000,
5987+
balance_msat: 10_000_000_000,
5988+
outbound_capacity_msat: 10_000_000_000,
5989+
next_outbound_htlc_limit_msat: 10_000_000_000,
59685990
inbound_capacity_msat: 0,
59695991
unspendable_punishment_reserve: None,
59705992
confirmations_required: None,
@@ -5982,44 +6004,60 @@ pub(crate) mod bench_utils {
59826004
}
59836005

59846006
pub(crate) fn generate_test_routes<S: Score>(graph: &NetworkGraph<&TestLogger>, scorer: &mut S,
5985-
features: InvoiceFeatures, mut seed: usize, route_count: usize,
6007+
features: InvoiceFeatures, mut seed: u64, starting_amount: u64, route_count: usize,
59866008
) -> Vec<(ChannelDetails, PaymentParameters, u64)> {
59876009
let payer = payer_pubkey();
59886010
let keys_manager = KeysManager::new(&[0u8; 32], 42, 42);
59896011
let random_seed_bytes = keys_manager.get_secure_random_bytes();
59906012

59916013
let nodes = graph.read_only().nodes().clone();
59926014
let mut route_endpoints = Vec::new();
5993-
let mut routes = Vec::new();
5994-
5995-
'load_endpoints: for _ in 0..route_count * 3 /2 {
6015+
for _ in 0..route_count * 3 / 2 {
59966016
loop {
5997-
seed = seed.overflowing_mul(0xdeadbeef).0;
5998-
let src = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
5999-
seed = seed.overflowing_mul(0xdeadbeef).0;
6000-
let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
6017+
seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
6018+
let src = PublicKey::from_slice(nodes.unordered_keys()
6019+
.skip((seed as usize) % nodes.len()).next().unwrap().as_slice()).unwrap();
6020+
seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
6021+
let dst = PublicKey::from_slice(nodes.unordered_keys()
6022+
.skip((seed as usize) % nodes.len()).next().unwrap().as_slice()).unwrap();
60016023
let params = PaymentParameters::from_node_id(dst, 42).with_features(features.clone());
60026024
let first_hop = first_hop(src);
6003-
let amt = seed as u64 % 1_000_000;
6004-
if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]), amt, 42, &TestLogger::new(), &scorer, &random_seed_bytes) {
6005-
routes.push(route);
6006-
route_endpoints.push((first_hop, params, amt));
6007-
continue 'load_endpoints;
6008-
}
6009-
}
6010-
}
6025+
let amt = starting_amount + seed % 1_000_000;
6026+
let path_exists =
6027+
get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]),
6028+
amt, 42, &TestLogger::new(), &scorer, &random_seed_bytes).is_ok();
6029+
if path_exists {
6030+
// ...and seed the scorer with success and failure data...
6031+
seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
6032+
let mut score_amt = seed % 1_000_000_000;
6033+
loop {
6034+
// Generate fail/success paths for a wider range of potential amounts with
6035+
// MPP enabled to give us a chance to apply penalties for more potential
6036+
// routes.
6037+
let mpp_features = channelmanager::provided_invoice_features(&UserConfig::default());
6038+
let params = PaymentParameters::from_node_id(dst, 42).with_features(mpp_features);
6039+
6040+
let route_res = get_route(&payer, &params, &graph.read_only(),
6041+
Some(&[&first_hop]), score_amt, 42, &TestLogger::new(), &scorer,
6042+
&random_seed_bytes);
6043+
if let Ok(route) = route_res {
6044+
for path in route.paths {
6045+
if seed & 0x80 == 0 {
6046+
scorer.payment_path_successful(&path);
6047+
} else {
6048+
let short_channel_id = path.hops[path.hops.len() / 2].short_channel_id;
6049+
scorer.payment_path_failed(&path, short_channel_id);
6050+
}
6051+
seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
6052+
}
6053+
break;
6054+
}
6055+
// If we couldn't find a path with a higer amount, reduce and try again.
6056+
score_amt /= 100;
6057+
}
60116058

6012-
// ...and seed the scorer with success and failure data...
6013-
for route in routes {
6014-
let amount = route.get_total_amount();
6015-
if amount < 250_000 {
6016-
for path in route.paths {
6017-
scorer.payment_path_successful(&path);
6018-
}
6019-
} else if amount > 750_000 {
6020-
for path in route.paths {
6021-
let short_channel_id = path.hops[path.hops.len() / 2].short_channel_id;
6022-
scorer.payment_path_failed(&path, short_channel_id);
6059+
route_endpoints.push((first_hop, params, amt));
6060+
break;
60236061
}
60246062
}
60256063
}
@@ -6061,15 +6099,15 @@ mod benches {
60616099
let logger = TestLogger::new();
60626100
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60636101
let scorer = FixedPenaltyScorer::with_penalty(0);
6064-
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
6102+
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty(), 0);
60656103
}
60666104

60676105
#[bench]
60686106
fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
60696107
let logger = TestLogger::new();
60706108
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60716109
let scorer = FixedPenaltyScorer::with_penalty(0);
6072-
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()));
6110+
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()), 0);
60736111
}
60746112

60756113
#[bench]
@@ -6078,7 +6116,7 @@ mod benches {
60786116
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60796117
let params = ProbabilisticScoringParameters::default();
60806118
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
6081-
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
6119+
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty(), 0);
60826120
}
60836121

60846122
#[bench]
@@ -6087,20 +6125,28 @@ mod benches {
60876125
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60886126
let params = ProbabilisticScoringParameters::default();
60896127
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
6090-
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()));
6128+
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()), 0);
60916129
}
60926130

6131+
#[bench]
6132+
fn generate_large_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) {
6133+
let logger = TestLogger::new();
6134+
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
6135+
let params = ProbabilisticScoringParameters::default();
6136+
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
6137+
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()), 100_000_000);
6138+
}
60936139

60946140
fn generate_routes<S: Score>(
60956141
bench: &mut Bencher, graph: &NetworkGraph<&TestLogger>, mut scorer: S,
6096-
features: InvoiceFeatures,
6142+
features: InvoiceFeatures, starting_amount: u64,
60976143
) {
60986144
let payer = bench_utils::payer_pubkey();
60996145
let keys_manager = KeysManager::new(&[0u8; 32], 42, 42);
61006146
let random_seed_bytes = keys_manager.get_secure_random_bytes();
61016147

61026148
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
6103-
let route_endpoints = bench_utils::generate_test_routes(graph, &mut scorer, features, 0xdeadbeef, 100);
6149+
let route_endpoints = bench_utils::generate_test_routes(graph, &mut scorer, features, 0xdeadbeef, starting_amount, 50);
61046150

61056151
// ...then benchmark finding paths between the nodes we learned.
61066152
let mut idx = 0;

0 commit comments

Comments
 (0)