Skip to content

Commit

Permalink
Merge pull request #120 from sr-gi/20231003-validate-network
Browse files Browse the repository at this point in the history
sim-lib: Adds LightningNode::get_network
  • Loading branch information
sr-gi authored Oct 4, 2023
2 parents 843d797 + def8dd1 commit f376643
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 31 deletions.
15 changes: 13 additions & 2 deletions sim-lib/src/cln.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use async_trait::async_trait;
use bitcoin::secp256k1::PublicKey;
use bitcoin::Network;
use cln_grpc::pb::{
listpays_pays::ListpaysPaysStatus, node_client::NodeClient, Amount, GetinfoRequest,
GetinfoResponse, KeysendRequest, KeysendResponse, ListchannelsRequest, ListnodesRequest,
Expand Down Expand Up @@ -59,7 +60,6 @@ impl ClnNode {
id,
alias,
our_features,
network,
..
} = client
.getinfo(GetinfoRequest {})
Expand All @@ -81,7 +81,6 @@ impl ClnNode {
.map_err(|err| LightningError::GetInfoError(err.to_string()))?,
features,
alias: alias.unwrap_or("".to_string()),
network,
},
})
}
Expand Down Expand Up @@ -123,6 +122,18 @@ impl LightningNode for ClnNode {
&self.info
}

async fn get_network(&mut self) -> Result<Network, LightningError> {
let info = self
.client
.getinfo(GetinfoRequest {})
.await
.map_err(|err| LightningError::GetInfoError(err.to_string()))?
.into_inner();

Ok(Network::from_core_arg(&info.network)
.map_err(|err| LightningError::ValidationError(err.to_string()))?)
}

async fn send_payment(
&mut self,
dest: PublicKey,
Expand Down
41 changes: 20 additions & 21 deletions sim-lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use async_trait::async_trait;
use bitcoin::secp256k1::PublicKey;
use bitcoin::Network;
use csv::WriterBuilder;
use lightning::ln::features::NodeFeatures;
use lightning::ln::PaymentHash;
Expand Down Expand Up @@ -120,14 +121,15 @@ pub struct NodeInfo {
pub pubkey: PublicKey,
pub alias: String,
pub features: NodeFeatures,
pub network: String,
}

/// LightningNode represents the functionality that is required to execute events on a lightning node.
#[async_trait]
pub trait LightningNode {
/// Get information about the node.
fn get_info(&self) -> &NodeInfo;
/// Get the network this node is running at
async fn get_network(&mut self) -> Result<Network, LightningError>;
/// Keysend payment worth `amount_msat` from a source node to the destination node.
async fn send_payment(
&mut self,
Expand Down Expand Up @@ -348,37 +350,34 @@ impl Simulation {
Ok(())
}

// it validates that the nodes are all on the same network and ensures that we're not running on mainnet.
// validates that the nodes are all on the same network and ensures that we're not running on mainnet.
async fn validate_node_network(&self) -> Result<(), LightningError> {
let mut valid_network = Option::None;
let unsupported_networks: HashSet<String> = vec!["mainnet", "bitcoin"]
.into_iter()
.map(|s| s.to_string())
.collect();
if self.nodes.is_empty() {
return Err(LightningError::ValidationError(
"we don't control any nodes. Specify at least one node in your config file"
.to_string(),
));
}
let mut running_network = Option::None;

for node in self.nodes.values() {
let network = node.lock().await.get_info().network.clone();
if unsupported_networks.contains(&network) {
let network = node.lock().await.get_network().await?;
if network == Network::Bitcoin {
return Err(LightningError::ValidationError(
"mainnet is not supported".to_string(),
));
}

valid_network = valid_network.take().or_else(|| Some(network.clone()));
if let Some(valid) = &valid_network {
if valid != &network {
return Err(LightningError::ValidationError(format!(
"nodes are not on the same network {}.",
network,
)));
}
running_network = running_network.take().or(Some(network));
if running_network != Some(network) {
return Err(LightningError::ValidationError(format!(
"nodes are not on the same network {}.",
network,
)));
}
}

log::info!(
"Simulation is running on the network: {}.",
valid_network.as_ref().unwrap()
);
log::info!("Simulation is running on {}.", running_network.unwrap());

Ok(())
}
Expand Down
41 changes: 33 additions & 8 deletions sim-lib/src/lnd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
use async_trait::async_trait;
use bitcoin::hashes::{sha256, Hash};
use bitcoin::secp256k1::PublicKey;
use bitcoin::Network;
use lightning::ln::features::NodeFeatures;
use lightning::ln::{PaymentHash, PaymentPreimage};
use tonic_lnd::lnrpc::{payment::PaymentStatus, GetInfoRequest, GetInfoResponse};
Expand Down Expand Up @@ -53,7 +54,6 @@ impl LndNode {
identity_pubkey,
features,
alias,
chains,
..
} = client
.lightning()
Expand All @@ -62,20 +62,13 @@ impl LndNode {
.map_err(|err| LightningError::GetInfoError(err.to_string()))?
.into_inner();

if chains.len() != 1 {
return Err(LightningError::GetInfoError(
"LND node is not connected to a single chain".to_string(),
));
}

Ok(Self {
client,
info: NodeInfo {
pubkey: PublicKey::from_str(&identity_pubkey)
.map_err(|err| LightningError::GetInfoError(err.to_string()))?,
features: parse_node_features(features.keys().cloned().collect()),
alias,
network: chains[0].network.clone(),
},
})
}
Expand All @@ -90,6 +83,38 @@ impl LightningNode for LndNode {
&self.info
}

async fn get_network(&mut self) -> Result<Network, LightningError> {
let info = self
.client
.lightning()
.get_info(GetInfoRequest {})
.await
.map_err(|err| LightningError::GetInfoError(err.to_string()))?
.into_inner();

if info.chains.is_empty() {
return Err(LightningError::ValidationError(
"LND node is not connected any chain".to_string(),
));
} else if info.chains.len() > 1 {
return Err(LightningError::ValidationError(format!(
"LND node is connected to more than one chain: {:?}",
info.chains.iter().map(|c| c.chain.to_string())
)));
}

Ok(Network::from_str(match info.chains[0].network.as_str() {
"mainnet" => "bitcoin",
"simnet" => {
return Err(LightningError::ValidationError(
"simnet is not supported".to_string(),
))
}
x => x,
})
.map_err(|err| LightningError::ValidationError(err.to_string()))?)
}

async fn send_payment(
&mut self,
dest: PublicKey,
Expand Down

0 comments on commit f376643

Please sign in to comment.