bless
This commit is contained in:
parent
7dd25c1580
commit
d8fd0dfb73
@ -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<Response<fs::File>, 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<std::io::Cursor<Vec<u8>>> {
|
||||
.with_header(Header::from_bytes(b"Content-Type", b"text/html").unwrap())
|
||||
}
|
||||
|
||||
type JSON = std::io::Cursor<Vec<u8>>;
|
||||
|
||||
fn handle_api(endpoint: &str) -> Result<Response<JSON>, HttpServerError>{
|
||||
Ok(Response::from_string("Hello World".to_string()))
|
||||
}
|
||||
|
||||
fn respond_api(req: &tiny_http::Request, url: Vec<&str>) -> Result<Response<JSON>, 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<Response<fs::File>, 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::<Vec<&str>>();
|
||||
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;
|
||||
|
||||
@ -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<u8> {
|
||||
let mut bytes = Vec::with_capacity(prefix.len() + key.len());
|
||||
@ -41,6 +36,11 @@ fn prefix(prefix: &[u8], key: &[u8]) -> Vec<u8> {
|
||||
bytes
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChainDb {
|
||||
db: sled::Tree,
|
||||
}
|
||||
|
||||
impl ChainDb {
|
||||
pub fn new(path: Option<String>, db_temp: bool) -> Result<ChainDb, DatabaseError> {
|
||||
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<Option<u64>, DatabaseError> {
|
||||
pub fn get_nonce(&self, address: &Address) -> Result<Option<u64>, DatabaseError> {
|
||||
match self.db.get(prefix(&NONCE_PREFIX, address))? {
|
||||
Some(n) => {
|
||||
let (nonce, _) = bincode::decode_from_slice::<u64, _>(&n, BINCODE_CONFIG)?;
|
||||
@ -149,10 +149,11 @@ impl ChainDb {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_block_by_key(&self, block_hash: &str) -> Result<Option<Arc<core::Block>>, DatabaseError> {
|
||||
let block_hash = prefix(&BLOCK_PREFIX, block_hash.as_bytes());
|
||||
pub fn get_block_by_key(&self, block_hash: &[u8]) -> Result<Option<Arc<core::Block>>, 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::<core::Block, _>(&bin_block, BINCODE_CONFIG)
|
||||
let (block, _) = bincode::decode_from_slice::<core::Block, _>(&bin_block, BINCODE_CONFIG)
|
||||
.map_err(|e| DatabaseError::Decode(e))?;
|
||||
Ok(Some(block.into()))
|
||||
} else {
|
||||
@ -165,7 +166,7 @@ impl ChainDb {
|
||||
height: u64,
|
||||
) -> Result<Option<Arc<core::Block>>, DatabaseError> {
|
||||
if let Some(hash) = self.db.get(prefix(&HEIGHT_TO_HASH_PREFIX, &height.to_be_bytes()))? {
|
||||
let (hash_str, _) = bincode::decode_from_slice::<String, _>(&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(),
|
||||
|
||||
@ -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?;
|
||||
|
||||
@ -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() => {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -21,3 +21,7 @@ async function getTableContent() {
|
||||
|
||||
console.log(content);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await getTableContent()
|
||||
})();
|
||||
|
||||
@ -22,6 +22,4 @@
|
||||
</div>
|
||||
<script src="/app.js" ></script>
|
||||
</body>
|
||||
<style>
|
||||
</style>
|
||||
</html>
|
||||
|
||||
@ -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 }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user