use crate::dbs::UsedSpace;
use crate::node::logging::log_ctx::LogCtx;
use crate::node::logging::run_system_logger;
use crate::node::{
network::Network,
state_db::{get_reward_pk, store_new_reward_keypair},
Config, Error, Result,
};
use crate::routing::{
EventStream, {Prefix, XorName},
};
use crate::types::PublicKey;
use rand::rngs::OsRng;
use std::{net::SocketAddr, path::PathBuf};
use tokio::time::Duration;
#[derive(Clone, Debug)]
struct NodeInfo {
root_dir: PathBuf,
reward_key: PublicKey,
}
#[derive(custom_debug::Debug)]
pub struct Node {
#[debug(skip)]
network_api: Network,
node_info: NodeInfo,
used_space: UsedSpace,
}
impl Node {
pub async fn new(config: &Config, joining_timeout: Duration) -> Result<(Self, EventStream)> {
let root_dir_buf = config.root_dir()?;
let root_dir = root_dir_buf.as_path();
tokio::fs::create_dir_all(root_dir).await?;
let reward_key = match get_reward_pk(root_dir).await? {
Some(public_key) => PublicKey::Ed25519(public_key),
None => {
let mut rng = OsRng;
let keypair = ed25519_dalek::Keypair::generate(&mut rng);
store_new_reward_keypair(root_dir, &keypair).await?;
PublicKey::Ed25519(keypair.public)
}
};
let node_info = NodeInfo {
root_dir: root_dir_buf.clone(),
reward_key,
};
let used_space = UsedSpace::new(config.max_capacity());
let joining_timeout = if cfg!(feature = "always-joinable") {
debug!(
">>>Feature \"always-joinable\" is set. Running with join timeout: {:?}",
joining_timeout * 10
);
joining_timeout * 10
} else {
joining_timeout
};
let (network_api, network_events) = tokio::time::timeout(
joining_timeout,
Network::new(root_dir_buf.as_path(), config, used_space.clone()),
)
.await
.map_err(|_| Error::JoinTimeout)??;
let node = Self {
node_info,
used_space,
network_api: network_api.clone(),
};
let our_pid = std::process::id();
let node_prefix = node.our_prefix().await;
let node_name = node.our_name().await;
let node_age = node.our_age().await;
let our_conn_info = node.our_connection_info().await;
let our_conn_info_json = serde_json::to_string(&our_conn_info)
.unwrap_or_else(|_| "Failed to serialize connection info".into());
println!(
"Node PID: {:?}, prefix: {:?}, name: {:?}, age: {}, connection info:\n{}",
our_pid, node_prefix, node_name, node_age, our_conn_info_json,
);
info!(
"Node PID: {:?}, prefix: {:?}, name: {:?}, age: {}, connection info: {}",
our_pid, node_prefix, node_name, node_age, our_conn_info_json,
);
run_system_logger(LogCtx::new(network_api), config.resource_logs).await;
Ok((node, network_events))
}
pub async fn our_connection_info(&self) -> SocketAddr {
self.network_api.our_connection_info().await
}
pub async fn our_name(&self) -> XorName {
self.network_api.our_name().await
}
pub async fn our_age(&self) -> u8 {
self.network_api.age().await
}
pub async fn our_prefix(&self) -> Prefix {
self.network_api.our_prefix().await
}
pub async fn genesis_key(&self) -> bls::PublicKey {
self.network_api.genesis_key().await
}
}