Skip to content

Commit 932c382

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 54783b1 commit 932c382

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
@@ -5679,7 +5679,7 @@ mod tests {
56795679
let mut scorer = ProbabilisticScorer::new(params, &graph, &logger);
56805680
let features = super::InvoiceFeatures::empty();
56815681

5682-
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed() as usize, 2);
5682+
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed(), 0, 2);
56835683
}
56845684

56855685
#[test]
@@ -5701,7 +5701,29 @@ mod tests {
57015701
let mut scorer = ProbabilisticScorer::new(params, &graph, &logger);
57025702
let features = channelmanager::provided_invoice_features(&UserConfig::default());
57035703

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

57075729
#[test]
@@ -5955,11 +5977,11 @@ pub(crate) mod bench_utils {
59555977
short_channel_id: Some(1),
59565978
inbound_scid_alias: None,
59575979
outbound_scid_alias: None,
5958-
channel_value_satoshis: 10_000_000,
5980+
channel_value_satoshis: 10_000_000_000,
59595981
user_channel_id: 0,
5960-
balance_msat: 10_000_000,
5961-
outbound_capacity_msat: 10_000_000,
5962-
next_outbound_htlc_limit_msat: 10_000_000,
5982+
balance_msat: 10_000_000_000,
5983+
outbound_capacity_msat: 10_000_000_000,
5984+
next_outbound_htlc_limit_msat: 10_000_000_000,
59635985
inbound_capacity_msat: 0,
59645986
unspendable_punishment_reserve: None,
59655987
confirmations_required: None,
@@ -5977,44 +5999,60 @@ pub(crate) mod bench_utils {
59775999
}
59786000

59796001
pub(crate) fn generate_test_routes<S: Score>(graph: &NetworkGraph<&TestLogger>, scorer: &mut S,
5980-
features: InvoiceFeatures, mut seed: usize, route_count: usize,
6002+
features: InvoiceFeatures, mut seed: u64, starting_amount: u64, route_count: usize,
59816003
) -> Vec<(ChannelDetails, PaymentParameters, u64)> {
59826004
let payer = payer_pubkey();
59836005
let keys_manager = KeysManager::new(&[0u8; 32], 42, 42);
59846006
let random_seed_bytes = keys_manager.get_secure_random_bytes();
59856007

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

6007-
// ...and seed the scorer with success and failure data...
6008-
for route in routes {
6009-
let amount = route.get_total_amount();
6010-
if amount < 250_000 {
6011-
for path in route.paths {
6012-
scorer.payment_path_successful(&path);
6013-
}
6014-
} else if amount > 750_000 {
6015-
for path in route.paths {
6016-
let short_channel_id = path.hops[path.hops.len() / 2].short_channel_id;
6017-
scorer.payment_path_failed(&path, short_channel_id);
6054+
route_endpoints.push((first_hop, params, amt));
6055+
break;
60186056
}
60196057
}
60206058
}
@@ -6056,15 +6094,15 @@ mod benches {
60566094
let logger = TestLogger::new();
60576095
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60586096
let scorer = FixedPenaltyScorer::with_penalty(0);
6059-
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
6097+
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty(), 0);
60606098
}
60616099

60626100
#[bench]
60636101
fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
60646102
let logger = TestLogger::new();
60656103
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60666104
let scorer = FixedPenaltyScorer::with_penalty(0);
6067-
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()));
6105+
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()), 0);
60686106
}
60696107

60706108
#[bench]
@@ -6073,7 +6111,7 @@ mod benches {
60736111
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60746112
let params = ProbabilisticScoringParameters::default();
60756113
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
6076-
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
6114+
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty(), 0);
60776115
}
60786116

60796117
#[bench]
@@ -6082,20 +6120,28 @@ mod benches {
60826120
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60836121
let params = ProbabilisticScoringParameters::default();
60846122
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
6085-
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()));
6123+
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()), 0);
60866124
}
60876125

6126+
#[bench]
6127+
fn generate_large_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) {
6128+
let logger = TestLogger::new();
6129+
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
6130+
let params = ProbabilisticScoringParameters::default();
6131+
let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
6132+
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()), 100_000_000);
6133+
}
60886134

60896135
fn generate_routes<S: Score>(
60906136
bench: &mut Bencher, graph: &NetworkGraph<&TestLogger>, mut scorer: S,
6091-
features: InvoiceFeatures,
6137+
features: InvoiceFeatures, starting_amount: u64,
60926138
) {
60936139
let payer = bench_utils::payer_pubkey();
60946140
let keys_manager = KeysManager::new(&[0u8; 32], 42, 42);
60956141
let random_seed_bytes = keys_manager.get_secure_random_bytes();
60966142

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

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

0 commit comments

Comments
 (0)