diff --git a/node/src/api/server.rs b/node/src/api/server.rs index b997505..c76bb24 100644 --- a/node/src/api/server.rs +++ b/node/src/api/server.rs @@ -3,12 +3,14 @@ use thiserror::Error; use crate::{ log, PROJECT_PATH }; use vlogger::*; +use std::io::Cursor; + use std::fs; #[derive(Error, Debug)] pub enum HttpServerError { #[error("Socket Error: {0}")] - SockerError(#[from] std::io::Error) + SocketError(#[from] std::io::Error), } const INTERNAL_SERVER_ERROR: &'static str = r#" @@ -30,7 +32,6 @@ const INTERNAL_SERVER_ERROR: &'static str = r#" fn derive_content_type(endpoint: &str) -> &'static str { match endpoint.rsplit(".").next() { Some(ext) => { - log(msg!(DEBUG, "{:?}", ext)); match ext { "html" => "text/html", "js" => "text/javascript", @@ -44,6 +45,7 @@ fn derive_content_type(endpoint: &str) -> &'static str { } } + fn serve_static(status: u16, file_path: &'static str) -> Result, HttpServerError> { let path: std::path::PathBuf = {PROJECT_PATH.to_string() + "/static" + file_path}.into(); let file = std::fs::File::open(path)?; @@ -57,6 +59,28 @@ fn internal_server_error(e: String) -> Response>> { .with_header(Header::from_bytes(b"Content-Type", b"text/html").unwrap()) } +type JSON = std::io::Cursor>; + +fn handle_api(endpoint: &str) -> Result, HttpServerError>{ + Ok(Response::from_string("Hello World".to_string())) +} + +fn respond_api(req: &tiny_http::Request, url: Vec<&str>) -> Result, HttpServerError> { + match (req.method(), url.as_slice()) { + (&Method::Get, ["get_table_content"]) => handle_api("get_table_content"), + (_, _) => handle_api(""), + } +} + +fn respond_file(req: &tiny_http::Request, url: Vec<&str>) -> Result, HttpServerError> { + match (req.method(), url.as_slice()) { + (&Method::Get, [""]) => serve_static(200, "/index.html"), + (&Method::Get, ["app.js"]) => serve_static(200, "/app.js"), + (&Method::Get, ["style.css"]) => serve_static(200, "/style.css"), + (_, _) => serve_static(404, "/404.html"), + } +} + pub async fn start_server() -> Result<(), HttpServerError>{ let address = "127.0.0.1:6080"; let server = tiny_http::Server::http(address).unwrap(); @@ -66,20 +90,24 @@ pub async fn start_server() -> Result<(), HttpServerError>{ match req { Some(req) => { let url = req.url().split('?').next().unwrap(); - log(msg!(DEBUG, "{:?}", req.url())); - - let response = match (req.method(), url) { - (&Method::Get, "/") => serve_static(200, "/index.html"), - (&Method::Get, "/app.js") => serve_static(200, "/app.js"), - (&Method::Get, "/style.css") => serve_static(200, "/style.css"), - (_, _) => serve_static(404, "/404.html"), - }; - - match response { - Ok(r) => { let _ = req.respond(r); }, - Err(e) => { internal_server_error(e.to_string()); }, - }; - }, + let mut url = url.split("/").skip(1).collect::>(); + log(msg!(DEBUG, "{:?}", url)); + match url[0] { + "api" => { + url.remove(0); + let response = respond_api(&req, url)?; + if let Err(e) = req.respond(response) { + log(msg!(ERROR, "{}", e)); + } + } + _ => { + let response = respond_file(&req, url)?; + if let Err(e) = req.respond(response) { + log(msg!(ERROR, "{}", e)); + } + } + } + } None => {} } tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; diff --git a/node/src/db/database.rs b/node/src/db/database.rs index 93ada1e..221e502 100644 --- a/node/src/db/database.rs +++ b/node/src/db/database.rs @@ -16,23 +16,18 @@ static BINCODE_CONFIG: Configuration = bincode::config::standard(); const DB_TREE: &str = "blocks"; -const BLOCK_PREFIX: [u8; 7] = *b"blocks:"; -const CHAIN_DATA_PREFIX: [u8; 11] = *b"chain_data:"; -const DATA_TO_BLOCK_PREFIX: [u8; 14] = *b"data_to_block:"; -const METADATA_PREFIX: [u8; 9] = *b"metadata:"; -const BALANCE_PREFIX: [u8; 8] = *b"balance:"; -const NONCE_PREFIX: [u8; 6] = *b"nonce:"; +const BLOCK_PREFIX: &[u8] = b"blocks:"; +const CHAIN_DATA_PREFIX: &[u8] = b"chain_data:"; +const DATA_TO_BLOCK_PREFIX: &[u8] = b"data_to_block:"; +const METADATA_PREFIX: &[u8] = b"metadata:"; +const BALANCE_PREFIX: &[u8] = b"balance:"; +const NONCE_PREFIX: &[u8] = b"nonce:"; -const MEMPOOL_PREFIX: [u8; 8] = *b"mempool:"; +const MEMPOOL_PREFIX: &[u8] = b"mempool:"; -const TIP_KEY: [u8; 10] = *b"chain_tip:"; -const HEIGHT_KEY: [u8; 13] = *b"chain_height:"; -const HEIGHT_TO_HASH_PREFIX: [u8; 15] = *b"height_to_hash:"; - -#[derive(Debug)] -pub struct ChainDb { - db: sled::Tree, -} +const TIP_KEY: &[u8] = b"chain_tip:"; +const HEIGHT_KEY: &[u8] = b"chain_height:"; +const HEIGHT_TO_HASH_PREFIX: &[u8] = b"height_to_hash:"; fn prefix(prefix: &[u8], key: &[u8]) -> Vec { let mut bytes = Vec::with_capacity(prefix.len() + key.len()); @@ -41,6 +36,11 @@ fn prefix(prefix: &[u8], key: &[u8]) -> Vec { bytes } +#[derive(Debug)] +pub struct ChainDb { + db: sled::Tree, +} + impl ChainDb { pub fn new(path: Option, db_temp: bool) -> Result { let path = if path.is_some() { @@ -111,14 +111,14 @@ impl ChainDb { Ok(()) } - fn set_nonce(&self, address: &Address, nonce: u64) -> Result<(), DatabaseError> { + pub fn set_nonce(&self, address: &Address, nonce: u64) -> Result<(), DatabaseError> { let bin_nonce = bincode::encode_to_vec(&nonce, BINCODE_CONFIG)?; let address = prefix(&NONCE_PREFIX, address); self.db.insert(address, bin_nonce)?; Ok(()) } - fn get_nonce(&self, address: &Address) -> Result, DatabaseError> { + pub fn get_nonce(&self, address: &Address) -> Result, DatabaseError> { match self.db.get(prefix(&NONCE_PREFIX, address))? { Some(n) => { let (nonce, _) = bincode::decode_from_slice::(&n, BINCODE_CONFIG)?; @@ -149,10 +149,11 @@ impl ChainDb { } } - pub fn get_block_by_key(&self, block_hash: &str) -> Result>, DatabaseError> { - let block_hash = prefix(&BLOCK_PREFIX, block_hash.as_bytes()); + pub fn get_block_by_key(&self, block_hash: &[u8]) -> Result>, DatabaseError> { + let block_hash = prefix(&BLOCK_PREFIX, block_hash); + log(msg!(DEBUG, "{:?}", hex::encode(&block_hash))); if let Some(bin_block) = self.db.get(block_hash)? { - let (block, _size) = bincode::decode_from_slice::(&bin_block, BINCODE_CONFIG) + let (block, _) = bincode::decode_from_slice::(&bin_block, BINCODE_CONFIG) .map_err(|e| DatabaseError::Decode(e))?; Ok(Some(block.into())) } else { @@ -165,7 +166,7 @@ impl ChainDb { height: u64, ) -> Result>, DatabaseError> { if let Some(hash) = self.db.get(prefix(&HEIGHT_TO_HASH_PREFIX, &height.to_be_bytes()))? { - let (hash_str, _) = bincode::decode_from_slice::(&hash, BINCODE_CONFIG)?; + let (hash_str, _) = bincode::decode_from_slice::<[u8; 32], _>(&hash, BINCODE_CONFIG)?; Ok(self.get_block_by_key(&hash_str)?) } else { Ok(None) @@ -211,7 +212,9 @@ impl ChainDb { pub fn add_block(&self, block: &core::Block) -> Result<(), DatabaseError> { let mut db_batch = Batch::default(); let bin_block = bincode::encode_to_vec(block, BINCODE_CONFIG)?; - db_batch.insert(prefix(&BLOCK_PREFIX, block.head().block_hash()), bin_block); + let block_prefix = prefix(&BLOCK_PREFIX, block.head().block_hash()); + log(msg!(DEBUG, "{:?}", hex::encode(&block_prefix))); + db_batch.insert(block_prefix, bin_block); db_batch.insert( prefix(&HEIGHT_TO_HASH_PREFIX, &block.head().height.to_be_bytes()), block.head().block_hash(), diff --git a/node/src/node/blockchain.rs b/node/src/node/blockchain.rs index ae6288c..0bbe757 100644 --- a/node/src/node/blockchain.rs +++ b/node/src/node/blockchain.rs @@ -2,8 +2,10 @@ use std::sync::Arc; use std::time::UNIX_EPOCH; use shared::core::Address; +use shared::print_error_chain; use thiserror::*; +use vlogger::*; use shared::core; use shared::core::ChainData; use crate::db; @@ -178,9 +180,12 @@ impl Blockchain { } } - pub fn display_block_by_key(&self, key: String) { - if let Ok(Some(b)) = self.db.get_block_by_key(&key) { - log(format!("{:#?}", b)) + pub fn display_block_by_key(&self, key: &[u8]) { + log(msg!(DEBUG, "BLOCK_KEY = {:?}", key)); + match self.db.get_block_by_key(key) { + Ok(Some(b)) => log(format!("{}", *b)), + Ok(None) => log(msg!(ERROR, "{} Not found", hex::encode(key))), + Err(e) => print_error_chain(&e.into()), } } @@ -225,6 +230,14 @@ impl Blockchain { Ok(()) } + pub fn recover_mempool(&mut self) { + self.mempool = if let Ok(m) = self.db.recover_mempool() { + m + } else { + vec![] + } + } + pub async fn shutdown(&self) -> Result<(), BlockchainError> { self.db.dump_mempool(&self.mempool)?; self.db.shutdown().await?; diff --git a/node/src/node/node.rs b/node/src/node/node.rs index 929e752..7d14e6b 100644 --- a/node/src/node/node.rs +++ b/node/src/node/node.rs @@ -436,7 +436,11 @@ impl Node { }); publish_watcher_event(wat_cmd); } - NodeCommand::DisplayBlockByKey(key) => self.chain.display_block_by_key(key), + NodeCommand::DisplayBlockByKey(key) => { + if let Ok(block_hash) = hex::decode(key) { + self.chain.display_block_by_key(&block_hash) + } + }, NodeCommand::DisplayBlockByHeight(height) => self.chain.display_block_by_height(height), NodeCommand::ListBlocks => { log(msg!(DEBUG, "Received DebugListBlocks command")); @@ -480,6 +484,8 @@ impl Node { let mut system_rx = subscribe_system_event(); publish_system_event(SystemEvent::NodeStarted); + self.chain.recover_mempool(); + loop { select! { _ = self.accept_command() => { diff --git a/node/src/watcher/watcher.rs b/node/src/watcher/watcher.rs index 39e994a..a2893b8 100644 --- a/node/src/watcher/watcher.rs +++ b/node/src/watcher/watcher.rs @@ -184,6 +184,7 @@ impl Watcher { match nd_cmd { NodeCommand::DisplayBlockByKey(_) => { let key = (*content)[*index].clone().to_string(); + log(msg!(DEBUG, "KEY IN ENTER: {key}")); let resp = ExecutorCommand::Node(NodeCommand::DisplayBlockByKey(key)); let _ = self.exec_tx.send(resp).await; } diff --git a/node/static/app.js b/node/static/app.js index 60ef851..7341332 100644 --- a/node/static/app.js +++ b/node/static/app.js @@ -21,3 +21,7 @@ async function getTableContent() { console.log(content); } + +(async () => { + await getTableContent() +})(); diff --git a/node/static/index.html b/node/static/index.html index a7bacad..41bc0a7 100644 --- a/node/static/index.html +++ b/node/static/index.html @@ -22,6 +22,4 @@ - diff --git a/shared/src/core/block.rs b/shared/src/core/block.rs index d4b1ba4..4fc5160 100644 --- a/shared/src/core/block.rs +++ b/shared/src/core/block.rs @@ -36,6 +36,19 @@ impl BlockHeader { } } +impl std::fmt::Display for Block { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let hash = hex::encode(self.head().block_hash()); + write!(f, "Block:\n hash: 0x{hash}\n data:\n")?; + for (i, t) in self.data().iter().enumerate() { + let data = hex::encode(t); + write!(f, " #{i}: {data}")?; + } + Ok(()) + } +} + + impl Block { pub fn new(head: BlockHeader, data: Vec<[u8; 32]>) -> Self { Self { head, data }