Skip to content

Commit f81aae9

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 1b0c707 commit f81aae9

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

5680-
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed() as usize, 2);
5680+
super::bench_utils::generate_test_routes(&graph, &mut scorer, features, random_init_seed(), 0, 2);
56815681
}
56825682

56835683
#[test]
@@ -5698,7 +5698,29 @@ mod tests {
56985698
let mut scorer = ProbabilisticScorer::new(params, &graph, &logger);
56995699
let features = channelmanager::provided_invoice_features(&UserConfig::default());
57005700

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

57045726
#[test]
@@ -5952,11 +5974,11 @@ pub(crate) mod bench_utils {
59525974
short_channel_id: Some(1),
59535975
inbound_scid_alias: None,
59545976
outbound_scid_alias: None,
5955-
channel_value_satoshis: 10_000_000,
5977+
channel_value_satoshis: 10_000_000_000,
59565978
user_channel_id: 0,
5957-
balance_msat: 10_000_000,
5958-
outbound_capacity_msat: 10_000_000,
5959-
next_outbound_htlc_limit_msat: 10_000_000,
5979+
balance_msat: 10_000_000_000,
5980+
outbound_capacity_msat: 10_000_000_000,
5981+
next_outbound_htlc_limit_msat: 10_000_000_000,
59605982
inbound_capacity_msat: 0,
59615983
unspendable_punishment_reserve: None,
59625984
confirmations_required: None,
@@ -5974,44 +5996,60 @@ pub(crate) mod bench_utils {
59745996
}
59755997

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

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

6004-
// ...and seed the scorer with success and failure data...
6005-
for route in routes {
6006-
let amount = route.get_total_amount();
6007-
if amount < 250_000 {
6008-
for path in route.paths {
6009-
scorer.payment_path_successful(&path);
6010-
}
6011-
} else if amount > 750_000 {
6012-
for path in route.paths {
6013-
let short_channel_id = path.hops[path.hops.len() / 2].short_channel_id;
6014-
scorer.payment_path_failed(&path, short_channel_id);
6051+
route_endpoints.push((first_hop, params, amt));
6052+
break;
60156053
}
60166054
}
60176055
}
@@ -6053,15 +6091,15 @@ mod benches {
60536091
let logger = TestLogger::new();
60546092
let network_graph = bench_utils::read_network_graph(&logger).unwrap();
60556093
let scorer = FixedPenaltyScorer::with_penalty(0);
6056-
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
6094+
generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty(), 0);
60576095
}
60586096

60596097
#[bench]
60606098
fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
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, channelmanager::provided_invoice_features(&UserConfig::default()));
6102+
generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()), 0);
60656103
}
60666104

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

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

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

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

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

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

0 commit comments

Comments
 (0)