From 50e7bda56b50d3f8a0909f804192b543d1fcbd02 Mon Sep 17 00:00:00 2001 From: Herr Seppia Date: Thu, 26 Oct 2023 15:46:54 +0200 Subject: [PATCH] Add HTTP Info --- node/src/lib.rs | 4 ++++ node/src/network.rs | 4 ++++ rusk/src/lib/chain.rs | 6 ++++++ rusk/src/lib/http/chain.rs | 25 ++++++++++++++++++++++--- rusk/src/lib/http/event.rs | 36 ++++++++++++++++++++++++++---------- rusk/src/lib/http/rusk.rs | 8 +++++--- 6 files changed, 67 insertions(+), 16 deletions(-) diff --git a/node/src/lib.rs b/node/src/lib.rs index 438995b475..d54f0396a7 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -159,6 +159,10 @@ impl Node { self.network.clone() } + pub fn vm(&self) -> Arc> { + self.vm_handler.clone() + } + /// Sets up and runs a list of services. pub async fn spawn_all( &self, diff --git a/node/src/network.rs b/node/src/network.rs index 8e3e500b4c..e80d791c2c 100644 --- a/node/src/network.rs +++ b/node/src/network.rs @@ -148,6 +148,10 @@ impl Kadcast { pub async fn alive_nodes(&self, amount: usize) -> Vec { self.peer.alive_nodes(amount).await } + + pub fn conf(&self) -> &Config { + &self.conf + } } #[async_trait] diff --git a/rusk/src/lib/chain.rs b/rusk/src/lib/chain.rs index 5aedaccd25..661bf3f1d2 100644 --- a/rusk/src/lib/chain.rs +++ b/rusk/src/lib/chain.rs @@ -17,4 +17,10 @@ impl RuskNode { pub fn db(&self) -> Arc> { self.0.database() as Arc> } + pub fn network(&self) -> Arc>> { + self.0.network() as Arc>> + } + pub fn vm(&self) -> Arc> { + self.0.vm() as Arc> + } } diff --git a/rusk/src/lib/http/chain.rs b/rusk/src/lib/http/chain.rs index cd6c3aa171..13a30f43b9 100644 --- a/rusk/src/lib/http/chain.rs +++ b/rusk/src/lib/http/chain.rs @@ -25,7 +25,7 @@ use serde_json::json; use super::event::{ Event, MessageRequest, MessageResponse, RequestData, ResponseData, Target, }; -use crate::http::RuskNode; +use crate::{http::RuskNode, VERSION, VERSION_BUILD}; const GQL_VAR_PREFIX: &str = "rusk-gqlvar-"; @@ -61,6 +61,7 @@ impl RuskNode { let amount = request.event.data.as_string().trim().parse()?; self.alive_nodes(amount).await } + (Target::Host(_), "Chain", "info") => self.get_info().await, _ => anyhow::bail!("Unsupported"), } } @@ -90,7 +91,8 @@ impl RuskNode { } let data = serde_json::to_string(&data) .map_err(|e| anyhow::anyhow!("Cannot parse response {e}"))?; - Ok(data.into()) + + Ok(ResponseData::Json(data)) } async fn propagate_tx(&self, tx: &[u8]) -> anyhow::Result { @@ -108,6 +110,23 @@ impl RuskNode { async fn alive_nodes(&self, amount: usize) -> anyhow::Result { let nodes = self.0.network().read().await.alive_nodes(amount).await; let nodes: Vec<_> = nodes.iter().map(|n| n.to_string()).collect(); - Ok(serde_json::to_string(&nodes)?.into()) + let response = serde_json::to_string(&nodes)?; + + Ok(ResponseData::Json(response)) + } + + async fn get_info(&self) -> anyhow::Result { + let mut info: HashMap<&str, serde_json::Value> = HashMap::new(); + info.insert("version", VERSION.as_str().into()); + info.insert("version_build", VERSION_BUILD.as_str().into()); + + let n_conf = self.network().read().await.conf().clone(); + info.insert("bootstrapping_nodes", n_conf.bootstrapping_nodes.into()); + info.insert("chain_id", n_conf.kadcast_id.into()); + info.insert("kadcast_address", n_conf.public_address.into()); + + let response = serde_json::to_string(&info)?; + + Ok(ResponseData::Json(response)) } } diff --git a/rusk/src/lib/http/event.rs b/rusk/src/lib/http/event.rs index d326457391..acc7e72e79 100644 --- a/rusk/src/lib/http/event.rs +++ b/rusk/src/lib/http/event.rs @@ -15,6 +15,7 @@ use std::collections::HashMap; use std::fmt::{Display, Formatter}; use std::str::FromStr; use std::sync::mpsc; +use tungstenite::http::{response, HeaderValue}; /// A request sent by the websocket client. #[derive(Debug, Serialize, Deserialize)] @@ -194,6 +195,8 @@ impl MessageResponse { .body(hyper::Body::from(error.to_string()))?); } + let mut headers = HashMap::new(); + let body = { match self.data { ResponseData::Binary(wrapper) => { @@ -204,19 +207,30 @@ impl MessageResponse { Body::from(data) } ResponseData::Text(text) => Body::from(text), - ResponseData::Channel(channel) => Body::wrap_stream( - stream::iter(channel).map(move |e| match is_binary { - true => Ok::<_, anyhow::Error>(e), - false => Ok::<_, anyhow::Error>( - hex::encode(e).as_bytes().to_vec(), - ), - }), // Ok::<_, anyhow::Error>), - ), + ResponseData::Json(text) => { + headers.insert(CONTENT_TYPE, CONTENT_TYPE_JSON); + Body::from(text) + } + ResponseData::Channel(channel) => { + Body::wrap_stream(stream::iter(channel).map(move |e| { + match is_binary { + true => Ok::<_, anyhow::Error>(e), + false => Ok::<_, anyhow::Error>( + hex::encode(e).as_bytes().to_vec(), + ), + } + })) + } ResponseData::None => Body::empty(), } }; - - Ok(hyper::Response::new(body)) + let mut response = hyper::Response::new(body); + for (k, v) in headers { + response + .headers_mut() + .insert(k, HeaderValue::from_str(v).unwrap()); + } + Ok(response) } pub fn set_header(&mut self, key: &str, value: serde_json::Value) { @@ -276,6 +290,7 @@ impl From> for RequestData { pub enum ResponseData { Binary(BinaryWrapper), Text(String), + Json(String), #[serde(skip)] Channel(mpsc::Receiver>), #[default] @@ -348,6 +363,7 @@ impl Event { } const CONTENT_TYPE: &str = "Content-Type"; const CONTENT_TYPE_BINARY: &str = "application/octet-stream"; +const CONTENT_TYPE_JSON: &str = "application/json"; fn parse_len(bytes: &[u8]) -> anyhow::Result<(usize, &[u8])> { if bytes.len() < 4 { diff --git a/rusk/src/lib/http/rusk.rs b/rusk/src/lib/http/rusk.rs index 09f2daaf8c..d70023a676 100644 --- a/rusk/src/lib/http/rusk.rs +++ b/rusk/src/lib/http/rusk.rs @@ -8,13 +8,15 @@ use dusk_bytes::Serializable; use node::vm::VMExecution; use rusk_prover::{LocalProver, Prover}; use serde::Serialize; +use std::collections::HashMap; use std::sync::{mpsc, Arc}; use std::thread; use tokio::task; +use tungstenite::http::response; use rusk_abi::ContractId; -use crate::Rusk; +use crate::{Rusk, VERSION, VERSION_BUILD}; use super::event::{ Event, MessageRequest, MessageResponse, RequestData, ResponseData, Target, @@ -50,7 +52,6 @@ impl Rusk { (Target::Host(_), "rusk", "prove_wfco") => { Ok(LocalProver.prove_wfco(request.event_data())?.into()) } - (Target::Host(_), "rusk", "provisioners") => { self.get_provisioners() } @@ -121,7 +122,8 @@ impl Rusk { }) .collect::>(); - Ok(serde_json::to_string(&prov)?.into()) + let response = serde_json::to_string(&prov)?; + Ok(ResponseData::Json(response)) } }