Feature/add node description api (#605)
* Starting to build out node descriptions * Renamed the mod to node_description instead of descriptor * Returning results loaded from file * Taking user input for node describe command * Readline without new dependencies * Adding input format hint * Making sure the node can still start even when the descriptor file isn't there yet * Adding some additional runtime checks * Removing -dev from minimum node version * Removing initial :: on serde * Fixing comment on the /description endpoint * Swapped json for toml * Being a bit more specific with my startup message. * Cleaning up path building * Nicer runtime checks * Put path building inside the file methods
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
use crate::node::node_description::NodeDescription;
|
||||
use rocket::State;
|
||||
use rocket_contrib::json::Json;
|
||||
|
||||
/// Returns a description of the node and why someone might want to delegate stake to it.
|
||||
#[get("/description")]
|
||||
pub(crate) fn description(description: State<NodeDescription>) -> Json<NodeDescription> {
|
||||
Json(description.inner().clone())
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
use rocket::Request;
|
||||
|
||||
pub(crate) mod description;
|
||||
pub(crate) mod verloc;
|
||||
|
||||
use rocket::Request;
|
||||
|
||||
#[catch(404)]
|
||||
pub(crate) fn not_found(req: &Request) -> String {
|
||||
format!("I couldn't find '{}'. Try something else?", req.uri())
|
||||
|
||||
+12
-4
@@ -3,12 +3,14 @@
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::node::http::{
|
||||
description::description,
|
||||
not_found,
|
||||
verloc::{verloc, VerlocState},
|
||||
};
|
||||
use crate::node::listener::connection_handler::packet_processing::PacketProcessor;
|
||||
use crate::node::listener::connection_handler::ConnectionHandler;
|
||||
use crate::node::listener::Listener;
|
||||
use crate::node::node_description::NodeDescription;
|
||||
use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender};
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use log::{error, info, warn};
|
||||
@@ -21,11 +23,13 @@ use version_checker::parse_version;
|
||||
pub(crate) mod http;
|
||||
mod listener;
|
||||
mod metrics;
|
||||
pub(crate) mod node_description;
|
||||
pub(crate) mod packet_delayforwarder;
|
||||
|
||||
// the MixNode will live for whole duration of this program
|
||||
pub struct MixNode {
|
||||
config: Config,
|
||||
descriptor: NodeDescription,
|
||||
identity_keypair: Arc<identity::KeyPair>,
|
||||
sphinx_keypair: Arc<encryption::KeyPair>,
|
||||
}
|
||||
@@ -33,31 +37,35 @@ pub struct MixNode {
|
||||
impl MixNode {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
descriptor: NodeDescription,
|
||||
identity_keypair: identity::KeyPair,
|
||||
sphinx_keypair: encryption::KeyPair,
|
||||
) -> Self {
|
||||
MixNode {
|
||||
config,
|
||||
descriptor,
|
||||
identity_keypair: Arc::new(identity_keypair),
|
||||
sphinx_keypair: Arc::new(sphinx_keypair),
|
||||
}
|
||||
}
|
||||
|
||||
fn start_http_api(&self, atomic_verloc_result: AtomicVerlocResult) {
|
||||
info!("Starting HTTP API on port 8000...");
|
||||
info!("Starting HTTP API on http://localhost:8000");
|
||||
|
||||
let mut config = rocket::config::Config::release_default();
|
||||
// bind to the same address as we are using for mixnodes
|
||||
config.address = self.config.get_listening_address().ip();
|
||||
|
||||
let state = VerlocState::new(atomic_verloc_result);
|
||||
let verloc_state = VerlocState::new(atomic_verloc_result);
|
||||
let descriptor = self.descriptor.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
rocket::build()
|
||||
.configure(config)
|
||||
.mount("/", routes![verloc])
|
||||
.mount("/", routes![verloc, description])
|
||||
.register("/", catchers![not_found])
|
||||
.manage(state)
|
||||
.manage(verloc_state)
|
||||
.manage(descriptor)
|
||||
.launch()
|
||||
.await
|
||||
});
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
|
||||
pub(crate) const DESCRIPTION_FILE: &str = "description.toml";
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NodeDescription {
|
||||
pub(crate) name: String,
|
||||
pub(crate) description: String,
|
||||
pub(crate) link: String,
|
||||
}
|
||||
|
||||
impl Default for NodeDescription {
|
||||
fn default() -> Self {
|
||||
NodeDescription {
|
||||
name: "This node has not yet set a name".to_string(),
|
||||
description: "This node has not yet set a description".to_string(),
|
||||
link: "https://nymtech.net".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NodeDescription {
|
||||
pub(crate) fn load_from_file(config_path: PathBuf) -> io::Result<NodeDescription> {
|
||||
let description_file_path: PathBuf = [config_path.to_str().unwrap(), DESCRIPTION_FILE]
|
||||
.iter()
|
||||
.collect();
|
||||
let toml = fs::read_to_string(description_file_path)?;
|
||||
toml::from_str(&toml).map_err(|toml_err| io::Error::new(io::ErrorKind::Other, toml_err))
|
||||
}
|
||||
|
||||
pub(crate) fn save_to_file(
|
||||
description: &NodeDescription,
|
||||
config_path: PathBuf,
|
||||
) -> io::Result<()> {
|
||||
let description_file_path: PathBuf = [config_path.to_str().unwrap(), DESCRIPTION_FILE]
|
||||
.iter()
|
||||
.collect();
|
||||
let description_toml =
|
||||
toml::to_string(description).expect("could not encode description to toml");
|
||||
fs::write(description_file_path, description_toml)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user