bless
This commit is contained in:
parent
7dd25c1580
commit
d8fd0dfb73
@ -3,12 +3,14 @@ use thiserror::Error;
|
|||||||
use crate::{ log, PROJECT_PATH };
|
use crate::{ log, PROJECT_PATH };
|
||||||
use vlogger::*;
|
use vlogger::*;
|
||||||
|
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum HttpServerError {
|
pub enum HttpServerError {
|
||||||
#[error("Socket Error: {0}")]
|
#[error("Socket Error: {0}")]
|
||||||
SockerError(#[from] std::io::Error)
|
SocketError(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
const INTERNAL_SERVER_ERROR: &'static str = r#"
|
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 {
|
fn derive_content_type(endpoint: &str) -> &'static str {
|
||||||
match endpoint.rsplit(".").next() {
|
match endpoint.rsplit(".").next() {
|
||||||
Some(ext) => {
|
Some(ext) => {
|
||||||
log(msg!(DEBUG, "{:?}", ext));
|
|
||||||
match ext {
|
match ext {
|
||||||
"html" => "text/html",
|
"html" => "text/html",
|
||||||
"js" => "text/javascript",
|
"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> {
|
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 path: std::path::PathBuf = {PROJECT_PATH.to_string() + "/static" + file_path}.into();
|
||||||
let file = std::fs::File::open(path)?;
|
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())
|
.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>{
|
pub async fn start_server() -> Result<(), HttpServerError>{
|
||||||
let address = "127.0.0.1:6080";
|
let address = "127.0.0.1:6080";
|
||||||
let server = tiny_http::Server::http(address).unwrap();
|
let server = tiny_http::Server::http(address).unwrap();
|
||||||
@ -66,20 +90,24 @@ pub async fn start_server() -> Result<(), HttpServerError>{
|
|||||||
match req {
|
match req {
|
||||||
Some(req) => {
|
Some(req) => {
|
||||||
let url = req.url().split('?').next().unwrap();
|
let url = req.url().split('?').next().unwrap();
|
||||||
log(msg!(DEBUG, "{:?}", req.url()));
|
let mut url = url.split("/").skip(1).collect::<Vec<&str>>();
|
||||||
|
log(msg!(DEBUG, "{:?}", url));
|
||||||
let response = match (req.method(), url) {
|
match url[0] {
|
||||||
(&Method::Get, "/") => serve_static(200, "/index.html"),
|
"api" => {
|
||||||
(&Method::Get, "/app.js") => serve_static(200, "/app.js"),
|
url.remove(0);
|
||||||
(&Method::Get, "/style.css") => serve_static(200, "/style.css"),
|
let response = respond_api(&req, url)?;
|
||||||
(_, _) => serve_static(404, "/404.html"),
|
if let Err(e) = req.respond(response) {
|
||||||
};
|
log(msg!(ERROR, "{}", e));
|
||||||
|
}
|
||||||
match response {
|
}
|
||||||
Ok(r) => { let _ = req.respond(r); },
|
_ => {
|
||||||
Err(e) => { internal_server_error(e.to_string()); },
|
let response = respond_file(&req, url)?;
|
||||||
};
|
if let Err(e) = req.respond(response) {
|
||||||
},
|
log(msg!(ERROR, "{}", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
|
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 DB_TREE: &str = "blocks";
|
||||||
|
|
||||||
const BLOCK_PREFIX: [u8; 7] = *b"blocks:";
|
const BLOCK_PREFIX: &[u8] = b"blocks:";
|
||||||
const CHAIN_DATA_PREFIX: [u8; 11] = *b"chain_data:";
|
const CHAIN_DATA_PREFIX: &[u8] = b"chain_data:";
|
||||||
const DATA_TO_BLOCK_PREFIX: [u8; 14] = *b"data_to_block:";
|
const DATA_TO_BLOCK_PREFIX: &[u8] = b"data_to_block:";
|
||||||
const METADATA_PREFIX: [u8; 9] = *b"metadata:";
|
const METADATA_PREFIX: &[u8] = b"metadata:";
|
||||||
const BALANCE_PREFIX: [u8; 8] = *b"balance:";
|
const BALANCE_PREFIX: &[u8] = b"balance:";
|
||||||
const NONCE_PREFIX: [u8; 6] = *b"nonce:";
|
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 TIP_KEY: &[u8] = b"chain_tip:";
|
||||||
const HEIGHT_KEY: [u8; 13] = *b"chain_height:";
|
const HEIGHT_KEY: &[u8] = b"chain_height:";
|
||||||
const HEIGHT_TO_HASH_PREFIX: [u8; 15] = *b"height_to_hash:";
|
const HEIGHT_TO_HASH_PREFIX: &[u8] = b"height_to_hash:";
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ChainDb {
|
|
||||||
db: sled::Tree,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prefix(prefix: &[u8], key: &[u8]) -> Vec<u8> {
|
fn prefix(prefix: &[u8], key: &[u8]) -> Vec<u8> {
|
||||||
let mut bytes = Vec::with_capacity(prefix.len() + key.len());
|
let mut bytes = Vec::with_capacity(prefix.len() + key.len());
|
||||||
@ -41,6 +36,11 @@ fn prefix(prefix: &[u8], key: &[u8]) -> Vec<u8> {
|
|||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ChainDb {
|
||||||
|
db: sled::Tree,
|
||||||
|
}
|
||||||
|
|
||||||
impl ChainDb {
|
impl ChainDb {
|
||||||
pub fn new(path: Option<String>, db_temp: bool) -> Result<ChainDb, DatabaseError> {
|
pub fn new(path: Option<String>, db_temp: bool) -> Result<ChainDb, DatabaseError> {
|
||||||
let path = if path.is_some() {
|
let path = if path.is_some() {
|
||||||
@ -111,14 +111,14 @@ impl ChainDb {
|
|||||||
Ok(())
|
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 bin_nonce = bincode::encode_to_vec(&nonce, BINCODE_CONFIG)?;
|
||||||
let address = prefix(&NONCE_PREFIX, address);
|
let address = prefix(&NONCE_PREFIX, address);
|
||||||
self.db.insert(address, bin_nonce)?;
|
self.db.insert(address, bin_nonce)?;
|
||||||
Ok(())
|
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))? {
|
match self.db.get(prefix(&NONCE_PREFIX, address))? {
|
||||||
Some(n) => {
|
Some(n) => {
|
||||||
let (nonce, _) = bincode::decode_from_slice::<u64, _>(&n, BINCODE_CONFIG)?;
|
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> {
|
pub fn get_block_by_key(&self, block_hash: &[u8]) -> Result<Option<Arc<core::Block>>, DatabaseError> {
|
||||||
let block_hash = prefix(&BLOCK_PREFIX, block_hash.as_bytes());
|
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)? {
|
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))?;
|
.map_err(|e| DatabaseError::Decode(e))?;
|
||||||
Ok(Some(block.into()))
|
Ok(Some(block.into()))
|
||||||
} else {
|
} else {
|
||||||
@ -165,7 +166,7 @@ impl ChainDb {
|
|||||||
height: u64,
|
height: u64,
|
||||||
) -> Result<Option<Arc<core::Block>>, DatabaseError> {
|
) -> Result<Option<Arc<core::Block>>, DatabaseError> {
|
||||||
if let Some(hash) = self.db.get(prefix(&HEIGHT_TO_HASH_PREFIX, &height.to_be_bytes()))? {
|
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)?)
|
Ok(self.get_block_by_key(&hash_str)?)
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -211,7 +212,9 @@ impl ChainDb {
|
|||||||
pub fn add_block(&self, block: &core::Block) -> Result<(), DatabaseError> {
|
pub fn add_block(&self, block: &core::Block) -> Result<(), DatabaseError> {
|
||||||
let mut db_batch = Batch::default();
|
let mut db_batch = Batch::default();
|
||||||
let bin_block = bincode::encode_to_vec(block, BINCODE_CONFIG)?;
|
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(
|
db_batch.insert(
|
||||||
prefix(&HEIGHT_TO_HASH_PREFIX, &block.head().height.to_be_bytes()),
|
prefix(&HEIGHT_TO_HASH_PREFIX, &block.head().height.to_be_bytes()),
|
||||||
block.head().block_hash(),
|
block.head().block_hash(),
|
||||||
|
|||||||
@ -2,8 +2,10 @@ use std::sync::Arc;
|
|||||||
use std::time::UNIX_EPOCH;
|
use std::time::UNIX_EPOCH;
|
||||||
|
|
||||||
use shared::core::Address;
|
use shared::core::Address;
|
||||||
|
use shared::print_error_chain;
|
||||||
use thiserror::*;
|
use thiserror::*;
|
||||||
|
|
||||||
|
use vlogger::*;
|
||||||
use shared::core;
|
use shared::core;
|
||||||
use shared::core::ChainData;
|
use shared::core::ChainData;
|
||||||
use crate::db;
|
use crate::db;
|
||||||
@ -178,9 +180,12 @@ impl Blockchain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_block_by_key(&self, key: String) {
|
pub fn display_block_by_key(&self, key: &[u8]) {
|
||||||
if let Ok(Some(b)) = self.db.get_block_by_key(&key) {
|
log(msg!(DEBUG, "BLOCK_KEY = {:?}", key));
|
||||||
log(format!("{:#?}", b))
|
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(())
|
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> {
|
pub async fn shutdown(&self) -> Result<(), BlockchainError> {
|
||||||
self.db.dump_mempool(&self.mempool)?;
|
self.db.dump_mempool(&self.mempool)?;
|
||||||
self.db.shutdown().await?;
|
self.db.shutdown().await?;
|
||||||
|
|||||||
@ -436,7 +436,11 @@ impl Node {
|
|||||||
});
|
});
|
||||||
publish_watcher_event(wat_cmd);
|
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::DisplayBlockByHeight(height) => self.chain.display_block_by_height(height),
|
||||||
NodeCommand::ListBlocks => {
|
NodeCommand::ListBlocks => {
|
||||||
log(msg!(DEBUG, "Received DebugListBlocks command"));
|
log(msg!(DEBUG, "Received DebugListBlocks command"));
|
||||||
@ -480,6 +484,8 @@ impl Node {
|
|||||||
let mut system_rx = subscribe_system_event();
|
let mut system_rx = subscribe_system_event();
|
||||||
publish_system_event(SystemEvent::NodeStarted);
|
publish_system_event(SystemEvent::NodeStarted);
|
||||||
|
|
||||||
|
self.chain.recover_mempool();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
select! {
|
select! {
|
||||||
_ = self.accept_command() => {
|
_ = self.accept_command() => {
|
||||||
|
|||||||
@ -184,6 +184,7 @@ impl Watcher {
|
|||||||
match nd_cmd {
|
match nd_cmd {
|
||||||
NodeCommand::DisplayBlockByKey(_) => {
|
NodeCommand::DisplayBlockByKey(_) => {
|
||||||
let key = (*content)[*index].clone().to_string();
|
let key = (*content)[*index].clone().to_string();
|
||||||
|
log(msg!(DEBUG, "KEY IN ENTER: {key}"));
|
||||||
let resp = ExecutorCommand::Node(NodeCommand::DisplayBlockByKey(key));
|
let resp = ExecutorCommand::Node(NodeCommand::DisplayBlockByKey(key));
|
||||||
let _ = self.exec_tx.send(resp).await;
|
let _ = self.exec_tx.send(resp).await;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,3 +21,7 @@ async function getTableContent() {
|
|||||||
|
|
||||||
console.log(content);
|
console.log(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await getTableContent()
|
||||||
|
})();
|
||||||
|
|||||||
@ -22,6 +22,4 @@
|
|||||||
</div>
|
</div>
|
||||||
<script src="/app.js" ></script>
|
<script src="/app.js" ></script>
|
||||||
</body>
|
</body>
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
</html>
|
</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 {
|
impl Block {
|
||||||
pub fn new(head: BlockHeader, data: Vec<[u8; 32]>) -> Self {
|
pub fn new(head: BlockHeader, data: Vec<[u8; 32]>) -> Self {
|
||||||
Self { head, data }
|
Self { head, data }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user