Skip to content

Commit 6e9cda4

Browse files
committed
simln-lib/bugfix: return all nodes from ln_node_from_graph
39257da introduced bug where we would not return all `SimNode`s from ln_node_from_graph because we were using the `SimGraph` which does not have the excluded nodes, if any. Here we use the pathfinding graph for the nodes list which would include all the nodes.
1 parent 09fb1ba commit 6e9cda4

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

sim-cli/src/parsing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ pub async fn create_simulation_with_network(
301301
));
302302

303303
// Copy all simulated channels into a read-only routing graph, allowing to pathfind for
304-
// individual payments without locking th simulation graph (this is a duplication of the channels,
304+
// individual payments without locking the simulation graph (this is a duplication of the channels,
305305
// but the performance tradeoff is worthwhile for concurrent pathfinding).
306306
let routing_graph = Arc::new(
307307
populate_network_graph(channels, clock.clone())
@@ -312,7 +312,7 @@ pub async fn create_simulation_with_network(
312312
// custom actions on the simulated network. For the nodes we'll pass our simulation, cast them
313313
// to a dyn trait and exclude any nodes that shouldn't be included in random activity
314314
// generation.
315-
let nodes = ln_node_from_graph(simulation_graph.clone(), routing_graph, clock.clone()).await?;
315+
let nodes = ln_node_from_graph(simulation_graph, routing_graph, clock.clone()).await?;
316316
let mut nodes_dyn: HashMap<_, Arc<Mutex<dyn LightningNode>>> = nodes
317317
.iter()
318318
.map(|(pk, node)| (*pk, Arc::clone(node) as Arc<Mutex<dyn LightningNode>>))

simln-lib/src/sim_node.rs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,16 @@ impl<T: SimNetwork, C: Clock> LightningNode for SimNode<T, C> {
798798
}
799799

800800
async fn channel_capacities(&self) -> Result<u64, LightningError> {
801-
let channels = self.network.lock().await.lookup_node(&self.info.pubkey)?;
801+
let channels = match self.network.lock().await.lookup_node(&self.info.pubkey) {
802+
Ok(channels) => channels,
803+
Err(e) => match e {
804+
// This is a bit weird in that a user could have a SimNode but if it was excluded
805+
// from sending payments, it won't be returned from the lookup_node call. In that
806+
// case, we return a capacity of 0 instead of returning a node not found error.
807+
LightningError::GetNodeInfoError(_) => return Ok(0),
808+
_ => return Err(e),
809+
},
810+
};
802811
Ok(channels.1.iter().sum())
803812
}
804813

@@ -1102,13 +1111,46 @@ pub async fn ln_node_from_graph<C: Clock>(
11021111
routing_graph: Arc<LdkNetworkGraph>,
11031112
clock: Arc<C>,
11041113
) -> Result<HashMap<PublicKey, Arc<Mutex<SimNode<SimGraph, C>>>>, LightningError> {
1105-
let mut nodes: HashMap<PublicKey, Arc<Mutex<SimNode<SimGraph, C>>>> = HashMap::new();
1114+
let network_graph = routing_graph.read_only();
1115+
let mut nodes: HashMap<PublicKey, Arc<Mutex<SimNode<SimGraph, C>>>> =
1116+
HashMap::with_capacity(network_graph.nodes().len());
1117+
1118+
// We want to return all the nodes even if they were excluded in the SimGraph. So we iterate
1119+
// over the routing_graph that should include all nodes.
1120+
for node in network_graph.nodes().unordered_iter() {
1121+
let node_pubkey = node
1122+
.0
1123+
.as_pubkey()
1124+
.map_err(|e| LightningError::GetInfoError(e.to_string()))?;
1125+
1126+
let current_node_info = network_graph.node(node.0);
1127+
debug_assert!(current_node_info.is_some());
1128+
debug_assert!(current_node_info.unwrap().channels.len() > 0);
1129+
let node_channel = current_node_info.unwrap().channels[0];
1130+
1131+
let channel_info = graph
1132+
.lock()
1133+
.await
1134+
.channels
1135+
.lock()
1136+
.await
1137+
.get(&node_channel.into())
1138+
.cloned();
11061139

1107-
for node in graph.lock().await.nodes.iter() {
1140+
debug_assert!(channel_info.is_some());
1141+
let channel_info = channel_info.unwrap();
1142+
1143+
let node_alias = if channel_info.node_1.policy.pubkey == node_pubkey {
1144+
channel_info.node_1.policy.alias.clone()
1145+
} else {
1146+
channel_info.node_2.policy.alias.clone()
1147+
};
1148+
1149+
let info = node_info(node_pubkey, node_alias);
11081150
nodes.insert(
1109-
*node.0,
1151+
node_pubkey,
11101152
Arc::new(Mutex::new(SimNode::new(
1111-
node.1 .0.clone(),
1153+
info,
11121154
graph.clone(),
11131155
routing_graph.clone(),
11141156
clock.clone(),
@@ -1966,19 +2008,25 @@ mod tests {
19662008
.await
19672009
.unwrap();
19682010

2011+
assert!(nodes.len() == 3);
2012+
19692013
let node_1 = nodes.get(&pk1).unwrap().lock().await;
19702014
let node_1_capacity = node_1.channel_capacities().await.unwrap();
19712015

1972-
// Node 1 has 2 channels but one was excluded so here we should only have the one that was
1973-
// not excluded.
2016+
// Node 1 has 2 channels but one was excluded so here we should only have the capacity of
2017+
// the channel that was not excluded.
19742018
assert!(node_1_capacity == capacity_1);
19752019

19762020
let node_2 = nodes.get(&pk2).unwrap().lock().await;
19772021
let node_2_capacity = node_2.channel_capacities().await.unwrap();
19782022
assert!(node_2_capacity == capacity_1);
19792023

1980-
// Node 3's only channel was excluded so it won't be present here.
1981-
assert!(!nodes.contains_key(&pk3));
2024+
// Node 3 should be returned from ln_node_from_graph but it won't have any channel capacity
2025+
// present because its only channel was excluded.
2026+
let node_3 = nodes.get(&pk3);
2027+
assert!(node_3.is_some());
2028+
let node_3 = node_3.unwrap().lock().await;
2029+
assert!(node_3.channel_capacities().await.unwrap() == 0);
19822030
}
19832031

19842032
/// Tests basic functionality of a `SimulatedChannel` but does no endeavor to test the underlying

0 commit comments

Comments
 (0)