Skip to content

Commit 9ff748c

Browse files
committed
Add offset plausibility test.
1 parent fce86c9 commit 9ff748c

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

lightning/src/routing/router.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,7 @@ mod tests {
16391639
NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate};
16401640
use ln::channelmanager;
16411641
use util::test_utils;
1642+
use util::chacha20::ChaCha20;
16421643
use util::ser::Writeable;
16431644
#[cfg(c_bindings)]
16441645
use util::ser::Writer;
@@ -5071,6 +5072,74 @@ mod tests {
50715072
assert_eq!(cltv_expiry_deltas_before, cltv_expiry_deltas_limited);
50725073
}
50735074

5075+
#[test]
5076+
fn adds_plausible_cltv_offset() {
5077+
let (secp_ctx, network, _, _, logger) = build_graph();
5078+
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
5079+
let network_graph = network.read_only();
5080+
let network_nodes = network_graph.nodes();
5081+
let network_channels = network_graph.channels();
5082+
let scorer = test_utils::TestScorer::with_penalty(0);
5083+
let payment_params = PaymentParameters::from_node_id(nodes[3]);
5084+
let keys_manager = test_utils::TestKeysInterface::new(&[4u8; 32], Network::Testnet);
5085+
let random_seed_bytes = keys_manager.get_secure_random_bytes();
5086+
5087+
let mut route = get_route(&our_id, &payment_params, &network, None, 100, 0,
5088+
Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
5089+
add_random_cltv_offset(&mut route, &payment_params, &network, &random_seed_bytes);
5090+
5091+
let mut path_plausibility = vec![];
5092+
5093+
for p in route.paths {
5094+
// 1. Select random observation point
5095+
let mut prng = ChaCha20::new(&random_seed_bytes, &[0u8; 12]);
5096+
let mut random_bytes = [0u8; ::core::mem::size_of::<usize>()];
5097+
5098+
prng.process_in_place(&mut random_bytes);
5099+
let random_path_index = usize::from_be_bytes(random_bytes).wrapping_rem(p.len());
5100+
let observation_point = NodeId::from_pubkey(&p.get(random_path_index).unwrap().pubkey);
5101+
5102+
// 2. Calculate what CLTV expiry delta we would observe there
5103+
let observed_cltv_expiry_delta: u32 = p[random_path_index..].iter().map(|h| h.cltv_expiry_delta).sum();
5104+
5105+
// 3. Starting from the observation point, find candidate paths
5106+
let mut candidates: VecDeque<(NodeId, Vec<u32>)> = VecDeque::new();
5107+
candidates.push_back((observation_point, vec![]));
5108+
5109+
let mut found_plausible_candidate = false;
5110+
5111+
'candidate_loop: while let Some((cur_node_id, cur_path_cltv_deltas)) = candidates.pop_front() {
5112+
if let Some(remaining) = observed_cltv_expiry_delta.checked_sub(cur_path_cltv_deltas.iter().sum::<u32>()) {
5113+
if remaining == 0 || remaining.wrapping_rem(40) == 0 || remaining.wrapping_rem(144) == 0 {
5114+
found_plausible_candidate = true;
5115+
break 'candidate_loop;
5116+
}
5117+
}
5118+
5119+
if let Some(cur_node) = network_nodes.get(&cur_node_id) {
5120+
for channel_id in &cur_node.channels {
5121+
if let Some(channel_info) = network_channels.get(&channel_id) {
5122+
if let Some((dir_info, next_id)) = channel_info.as_directed_from(&cur_node_id) {
5123+
if let Some(channel_update_info) = dir_info.direction() {
5124+
let next_cltv_expiry_delta = channel_update_info.cltv_expiry_delta as u32;
5125+
if cur_path_cltv_deltas.iter().sum::<u32>()
5126+
.saturating_add(next_cltv_expiry_delta) <= observed_cltv_expiry_delta {
5127+
let mut new_path_cltv_deltas = cur_path_cltv_deltas.clone();
5128+
new_path_cltv_deltas.push(next_cltv_expiry_delta);
5129+
candidates.push_back((*next_id, new_path_cltv_deltas));
5130+
}
5131+
}
5132+
}
5133+
}
5134+
}
5135+
}
5136+
}
5137+
5138+
path_plausibility.push(found_plausible_candidate);
5139+
}
5140+
assert!(path_plausibility.iter().all(|x| *x));
5141+
}
5142+
50745143
#[cfg(not(feature = "no-std"))]
50755144
pub(super) fn random_init_seed() -> u64 {
50765145
// Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG.

0 commit comments

Comments
 (0)