Skip to content

Commit e4a6e4f

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 21af334 commit e4a6e4f

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

37513836
#[cfg(all(test, feature = "unstable"))]
@@ -3763,7 +3848,8 @@ mod benches {
37633848

37643849
#[bench]
37653850
fn generate_routes(bench: &mut Bencher) {
3766-
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");
3851+
let mut d = tests::get_route_file()
3852+
.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");
37673853
let graph = NetworkGraph::read(&mut d).unwrap();
37683854

37693855
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
@@ -3794,7 +3880,8 @@ mod benches {
37943880

37953881
#[bench]
37963882
fn generate_mpp_routes(bench: &mut Bencher) {
3797-
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");
3883+
let mut d = tests::get_route_file()
3884+
.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");
37983885
let graph = NetworkGraph::read(&mut d).unwrap();
37993886

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

0 commit comments

Comments
 (0)