Skip to content

Commit

Permalink
sim-all: logs aliases and pks if both are known
Browse files Browse the repository at this point in the history
This commit redefines what data about a node is passed along to the simulator on
activities. Previously, we used to pass only the src/dst `PublicKey`. However, by doing
this we had no way of logging (nor accessing) any other information about them. This is
mainly because all this mapping is only available on `sim-cli::main.rs`, and also because
the data is mostly logged by the producers/consumers functions, which are not even part
or the `Simulator` class.

Therefore, the alternative we are left with are passing the information to the simulator.
This can be done in several ways, I've gone with the one that has a better balance between
codediff and usefulness, which is passing `NodeInfo` along. This, however, means having to
obtain the destination node features on `main` instead of on `validation`.
  • Loading branch information
sr-gi committed Oct 5, 2023
1 parent b502082 commit e884245
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 130 deletions.
79 changes: 54 additions & 25 deletions sim-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,10 @@ async fn main() -> anyhow::Result<()> {
.unwrap();

let config_str = std::fs::read_to_string(cli.config)?;
let Config {
nodes,
mut activity,
} = serde_json::from_str(&config_str)?;
let Config { nodes, activity } = serde_json::from_str(&config_str)?;

let mut clients: HashMap<PublicKey, Arc<Mutex<dyn LightningNode + Send>>> = HashMap::new();
let mut pk_node_map = HashMap::new();
let mut alias_node_map = HashMap::new();

for connection in nodes {
Expand Down Expand Up @@ -77,36 +75,67 @@ async fn main() -> anyhow::Result<()> {
)));
}

alias_node_map.insert(node_info.alias.clone(), node_info.pubkey);
clients.insert(node_info.pubkey, node);
pk_node_map.insert(node_info.pubkey, node_info.clone());
alias_node_map.insert(node_info.alias.clone(), node_info);
}

let mut validated_activities = vec![];
// Make all the activities identifiable by PK internally
for act in activity.iter_mut() {
for act in activity.into_iter() {
// We can only map aliases to nodes we control, so if either the source or destination alias
// is not in alias_node_map, we fail
if let NodeId::Alias(a) = &act.source {
if let Some(pk) = alias_node_map.get(a) {
act.source = NodeId::PublicKey(*pk);
} else {
anyhow::bail!(LightningError::ValidationError(format!(
"activity source alias {} not found in nodes.",
act.source
)));
let source = if let Some(source) = match &act.source {
NodeId::PublicKey(pk) => pk_node_map.get(pk),
NodeId::Alias(a) => alias_node_map.get(a),
} {
source.clone()
} else {
anyhow::bail!(LightningError::ValidationError(format!(
"activity source {} not found in nodes.",
act.source
)));
};

let destination = match &act.destination {
NodeId::Alias(a) => {
if let Some(info) = alias_node_map.get(a) {
info.clone()
} else {
anyhow::bail!(LightningError::ValidationError(format!(
"unknown activity destination: {}.",
act.destination
)));
}
}
}
if let NodeId::Alias(a) = &act.destination {
if let Some(pk) = alias_node_map.get(a) {
act.destination = NodeId::PublicKey(*pk);
} else {
anyhow::bail!(LightningError::ValidationError(format!(
"unknown activity destination: {}.",
act.destination
)));
NodeId::PublicKey(pk) => {
if let Some(info) = pk_node_map.get(pk) {
info.clone()
} else {
clients
.get(&source.pubkey)
.unwrap()
.lock()
.await
.get_node_info(pk)
.await
.map_err(|e| {
log::debug!("{}", e);
LightningError::ValidationError(format!(
"Destination node unknown or invalid: {}.",
pk,
))
})?
}
}
}
validated_activities.push(ActivityDefinition::try_from(act)?);
};

validated_activities.push(ActivityDefinition {
source,
destination,
interval_secs: act.interval_secs,
amount_msat: act.amount_msat,
});
}

let sim = Simulation::new(
Expand Down
29 changes: 16 additions & 13 deletions sim-lib/src/cln.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,28 +230,31 @@ impl LightningNode for ClnNode {
}
}

async fn get_node_features(&mut self, node: PublicKey) -> Result<NodeFeatures, LightningError> {
let node_id = node.serialize().to_vec();
let nodes: Vec<cln_grpc::pb::ListnodesNodes> = self
async fn get_node_info(&mut self, node_id: &PublicKey) -> Result<NodeInfo, LightningError> {
let mut nodes: Vec<cln_grpc::pb::ListnodesNodes> = self
.client
.list_nodes(ListnodesRequest {
id: Some(node_id.clone()),
id: Some(node_id.serialize().to_vec()),
})
.await
.map_err(|err| LightningError::GetNodeInfoError(err.to_string()))?
.into_inner()
.nodes;

// We are filtering `list_nodes` to a single node, so we should get either an empty vector or one with a single element
if let Some(node) = nodes.first() {
Ok(node
.features
.clone()
.map_or(NodeFeatures::empty(), |mut f| {
// We need to reverse this given it has the CLN wire encoding which is BE
f.reverse();
NodeFeatures::from_le_bytes(f)
}))
if let Some(node) = nodes.pop() {
Ok(NodeInfo {
pubkey: *node_id,
alias: node.alias.unwrap_or(String::new()),
features: node
.features
.clone()
.map_or(NodeFeatures::empty(), |mut f| {
// We need to reverse this given it has the CLN wire encoding which is BE
f.reverse();
NodeFeatures::from_le_bytes(f)
}),
})
} else {
Err(LightningError::GetNodeInfoError(
"Node not found".to_string(),
Expand Down
Loading

0 comments on commit e884245

Please sign in to comment.