Skip to content

Commit 5a18e5c

Browse files
committed
Add a random real-world-network-graph test for the router
This is the same code as was recently failing in our benchmarks, adapted to use a random starting seed instead of a fixed one and a smaller iteration to reduce runtime.
1 parent aadddaf commit 5a18e5c

File tree

2 files changed

+94
-2
lines changed

2 files changed

+94
-2
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ jobs:
153153
echo "Bad hash"
154154
exit 1
155155
fi
156+
- name: Test with Network Graph on Rust ${{ matrix.toolchain }}
157+
run: |
158+
cd lightning
159+
RUSTFLAGS="--cfg=require_route_graph_test" cargo test
160+
cd ..
156161
- name: Run benchmarks on Rust ${{ matrix.toolchain }}
157162
run: |
158163
cd lightning

lightning/src/routing/router.rs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3748,6 +3748,91 @@ mod tests {
37483748
assert_eq!(route.paths[0][1].channel_features.le_flags(), &id_to_feature_flags(13));
37493749
}
37503750
}
3751+
3752+
use std::fs::File;
3753+
use util::ser::Readable;
3754+
/// Tries to open a network graph file, or panics with a URL to fetch it.
3755+
pub(super) fn get_route_file() -> Result<std::fs::File, std::io::Error> {
3756+
let res = File::open("net_graph-2021-02-12.bin") // By default we're run in RL/lightning
3757+
.or_else(|_| File::open("lightning/net_graph-2021-02-12.bin")) // We may be run manually in RL/
3758+
.or_else(|_| { // Fall back to guessing based on the binary location
3759+
// path is likely something like .../rust-lightning/target/debug/deps/lightning-...
3760+
let mut path = std::env::current_exe().unwrap();
3761+
path.pop(); // lightning-...
3762+
path.pop(); // deps
3763+
path.pop(); // debug
3764+
path.pop(); // target
3765+
path.push("lightning");
3766+
path.push("net_graph-2021-02-12.bin");
3767+
eprintln!("{}", path.to_str().unwrap());
3768+
File::open(path)
3769+
});
3770+
#[cfg(require_route_graph_test)]
3771+
return Ok(res.expect("Didn't have route graph and was configured to require it"));
3772+
res
3773+
}
3774+
3775+
pub(super) fn random_init_seed() -> u64 {
3776+
// Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG.
3777+
use std::hash::{BuildHasher, Hasher};
3778+
let seed = std::collections::hash_map::RandomState::new().build_hasher().finish();
3779+
println!("Using seed of {}", seed);
3780+
seed
3781+
}
3782+
3783+
#[test]
3784+
fn generate_routes() {
3785+
let mut d = match get_route_file() {
3786+
Ok(f) => f,
3787+
Err(_) => {
3788+
eprintln!("Please fetch https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin and place it at lightning/net_graph-2021-02-12.bin");
3789+
return;
3790+
},
3791+
};
3792+
let graph = NetworkGraph::read(&mut d).unwrap();
3793+
3794+
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
3795+
let mut seed = random_init_seed() as usize;
3796+
'load_endpoints: for _ in 0..10 {
3797+
loop {
3798+
seed = seed.overflowing_mul(0xdeadbeef).0;
3799+
let src = graph.get_nodes().keys().skip(seed % graph.get_nodes().len()).next().unwrap();
3800+
seed = seed.overflowing_mul(0xdeadbeef).0;
3801+
let dst = graph.get_nodes().keys().skip(seed % graph.get_nodes().len()).next().unwrap();
3802+
let amt = seed as u64 % 200_000_000;
3803+
if get_route(src, &graph, dst, None, None, &[], amt, 42, &test_utils::TestLogger::new()).is_ok() {
3804+
continue 'load_endpoints;
3805+
}
3806+
}
3807+
}
3808+
}
3809+
3810+
#[test]
3811+
fn generate_routes_mpp() {
3812+
let mut d = match get_route_file() {
3813+
Ok(f) => f,
3814+
Err(_) => {
3815+
eprintln!("Please fetch https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin and place it at lightning/net_graph-2021-02-12.bin");
3816+
return;
3817+
},
3818+
};
3819+
let graph = NetworkGraph::read(&mut d).unwrap();
3820+
3821+
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
3822+
let mut seed = random_init_seed() as usize;
3823+
'load_endpoints: for _ in 0..10 {
3824+
loop {
3825+
seed = seed.overflowing_mul(0xdeadbeef).0;
3826+
let src = graph.get_nodes().keys().skip(seed % graph.get_nodes().len()).next().unwrap();
3827+
seed = seed.overflowing_mul(0xdeadbeef).0;
3828+
let dst = graph.get_nodes().keys().skip(seed % graph.get_nodes().len()).next().unwrap();
3829+
let amt = seed as u64 % 200_000_000;
3830+
if get_route(src, &graph, dst, Some(InvoiceFeatures::known()), None, &[], amt, 42, &test_utils::TestLogger::new()).is_ok() {
3831+
continue 'load_endpoints;
3832+
}
3833+
}
3834+
}
3835+
}
37513836
}
37523837

37533838
#[cfg(all(test, feature = "unstable"))]
@@ -3765,7 +3850,8 @@ mod benches {
37653850

37663851
#[bench]
37673852
fn generate_routes(bench: &mut Bencher) {
3768-
let mut d = File::open("net_graph-2021-02-12.bin").expect("Please fetch https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin and place it at lightning/net_graph-2021-02-12.bin");
3853+
let mut d = tests::get_route_file()
3854+
.expect("Please fetch https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin and place it at lightning/net_graph-2021-02-12.bin");
37693855
let graph = NetworkGraph::read(&mut d).unwrap();
37703856

37713857
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
@@ -3796,7 +3882,8 @@ mod benches {
37963882

37973883
#[bench]
37983884
fn generate_mpp_routes(bench: &mut Bencher) {
3799-
let mut d = File::open("net_graph-2021-02-12.bin").expect("Please fetch https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin and place it at lightning/net_graph-2021-02-12.bin");
3885+
let mut d = tests::get_route_file()
3886+
.expect("Please fetch https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin and place it at lightning/net_graph-2021-02-12.bin");
38003887
let graph = NetworkGraph::read(&mut d).unwrap();
38013888

38023889
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...

0 commit comments

Comments
 (0)