Skip to content

Conversation

@elnosh
Copy link
Collaborator

@elnosh elnosh commented Sep 23, 2025

Changes:

  • repurpose list_channels to channel_capacities in the LightningNode trait since this call was only used to determine how much the node will send per month.
  • fixes bug introduced in 39257da where it would not return all the nodes (the ones with excluded channels). Even if we are excluding channels from nodes, we still want to return SimNodes so that a user could use them.

@elnosh elnosh requested a review from carlaKC September 23, 2025 14:46
Copy link
Contributor

@carlaKC carlaKC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel like we haven't quite hit the right API for this, but stuggling to think of a better approach - let's chat about it irl.

Comment on lines 346 to 347
/// Sum of channel capacities. It will be used to determine how much the node will send per
/// month.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: only used if running with random activity generation

Comment on lines 802 to 811
Ok(channels) => channels,
Err(e) => match e {
// This is a bit weird in that a user could have a SimNode but if it was excluded
// from sending payments, it won't be returned from the lookup_node call. In that
// case, we return a capacity of 0 instead of returning a node not found error.
LightningError::GetNodeInfoError(_) => return Ok(0),
_ => return Err(e),
},
};
Ok(channels.1.iter().sum())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can inline this

match self.network.lock().await.lookup_node(&self.info.pubkey) {
    Ok(channels) => Ok(channels.1.iter().sum()),
    Err(e) => match e {
        // This is a bit weird in that a user could have a SimNode but if it was excluded
        // from sending payments, it won't be returned from the lookup_node call. In that
        // case, we return a capacity of 0 instead of returning a node not found error.
        LightningError::GetNodeInfoError(_) =>  Ok(0),
             _ => Err(e),
        },
    }

Comment on lines 1118 to 1120
// We want to return all the nodes even if they were excluded in the SimGraph. So we iterate
// over the routing_graph that should include all nodes.
for node in network_graph.nodes().unordered_iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we still use graph here? Looking at where we call ln_node_from_graph, we only filter the excluded nodes after getting the node list.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole function can probably go back to what it was.

Copy link
Contributor

@carlaKC carlaKC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tl;dr:

  • SimGraph: has all of the nodes in the network, some have channels that are marked as exclude. We filter our capacity by the exclude field.
  • RoutingGraph: has all of the nodes, that's it.
  • ln_node_from_graph: returns the full list of nodes, so we can use any one we want for misc purposes.
  • Simulation::new: delete any nodes that we want to exclude because we don't want them sending/receiving.

Removing from the list of nodes that we give the simulator stops them from being eligible for sending/receiving payments. Having the exclude field stop their peers from over estimating the amount they should send/receive, while still allowing us to forward payments over the excluded channels.

Comment on lines 801 to 802
let channels = self.network.lock().await.lookup_node(&self.info.pubkey)?;
Ok(channels.1.iter().sum())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we should throw a node not found error if one is not in the list.

We can filter the channels by exclude to get the balance, so that we get a zero balance.

Comment on lines 804 to 808
// This is a bit weird in that a user could have a SimNode but if it was excluded
// from sending payments, it won't be returned from the lookup_node call. In that
// case, we return a capacity of 0 instead of returning a node not found error.
LightningError::GetNodeInfoError(_) => return Ok(0),
_ => return Err(e),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No implicit zero, fail if we don't find the node like in the previous commit.

Comment on lines 1118 to 1120
// We want to return all the nodes even if they were excluded in the SimGraph. So we iterate
// over the routing_graph that should include all nodes.
for node in network_graph.nodes().unordered_iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole function can probably go back to what it was.

Currently, list_channels is only used for returning a list
of channel capacities and using that to determine how much
the node should send in a month. Change it to channel_capacities
that will return the sum of the capacities of the channels
that should be taken into account.
@elnosh elnosh force-pushed the fix-excluded-nodes branch 3 times, most recently from a949210 to 1851075 Compare September 24, 2025 19:58

/// SimNetwork represents a high level network coordinator that is responsible for the task of actually propagating
/// payments through the simulated network.
#[async_trait]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had to make this an async_trait because of tokio mutex :( un-yay

@elnosh
Copy link
Collaborator Author

elnosh commented Sep 24, 2025

addressed feedback - storing all nodes in SimGraph but excluding capacity based on exclude field in SimulatedChannel

Some(node) => node.clone(),
None => {
return Err(LightningError::GetNodeInfoError(
"Node not found".to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: include pubkey of node for debugging

39257da introduced bug where we
would not return all `SimNode`s from `ln_node_from_graph` because
`SimGraph` did not have the excluded nodes. Here we store all
the nodes but exclude them from the capacity based on the
exclude field in the `SimulatedChannel`.
@carlaKC carlaKC merged commit 66daf69 into bitcoin-dev-project:main Sep 26, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants