bless
This commit is contained in:
parent
7ac62bdc00
commit
d6f7c758c0
@ -118,6 +118,14 @@ pub struct CliArgs {
|
||||
/// Provide File with current chain
|
||||
#[arg(short = 'f', long)]
|
||||
pub seed_file: Option<String>,
|
||||
|
||||
/// Enable debug mode (alternative syntax)
|
||||
#[arg(short = 'b', long = "bootstrap", action = clap::ArgAction::SetTrue)]
|
||||
pub bootstrap: bool,
|
||||
|
||||
/// Enable debug mode (alternative syntax)
|
||||
#[arg(short = 's', long = "seed", action = clap::ArgAction::SetTrue)]
|
||||
pub seed: bool,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
|
||||
@ -19,6 +19,7 @@ pub enum ValidationError {
|
||||
InvalidPreviousBlockHash
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Blockchain {
|
||||
id: String,
|
||||
@ -139,7 +140,6 @@ impl Blockchain {
|
||||
new_head.block_hash = block_hash;
|
||||
|
||||
let new_block = core::Block::new(new_head, self.tx_mempool.clone());
|
||||
log!(DEBUG, "Created new Block {:#?}", new_block);
|
||||
self.blocks.push(new_block);
|
||||
self.blocks.last().unwrap().clone()
|
||||
}
|
||||
@ -198,11 +198,12 @@ pub fn calculate_block_hash(head: &core::BlockHeader) -> String {
|
||||
}
|
||||
|
||||
impl Blockchain {
|
||||
pub fn print_blocks(&self) {
|
||||
println!("Blocks List\n--------------");
|
||||
pub fn list_blocks(&self) -> String {
|
||||
let mut ret = String::from("Blocks List\n-------------------");
|
||||
for (i, b) in self.blocks.iter().enumerate() {
|
||||
println!("Block #{i}\n{:#?}", b.head().block_hash);
|
||||
ret.push_str(format!("Block Hash #{i}: {}\n", b.head.block_hash()).as_str())
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn get_balances(&self) -> &std::collections::HashMap<String, u32> {
|
||||
@ -238,7 +239,6 @@ impl Blockchain {
|
||||
}
|
||||
|
||||
fn validate_chain(&self) -> Result<(), ValidationError>{
|
||||
log!(INFO, "Validating Chain");
|
||||
let blocks = self.blocks();
|
||||
for block in blocks {
|
||||
let head = block.head();
|
||||
@ -252,7 +252,6 @@ impl Blockchain {
|
||||
}
|
||||
|
||||
pub fn build(blocks: Vec<core::Block>) -> Result<Blockchain, ValidationError> {
|
||||
log!(INFO, "Starting Chain Build from Genesis");
|
||||
let chain = Blockchain {
|
||||
blocks,
|
||||
balances: HashMap::new(),
|
||||
|
||||
22
src/error.rs
22
src/error.rs
@ -24,20 +24,22 @@ pub enum TxError {
|
||||
UnknownAccount(String)
|
||||
}
|
||||
|
||||
pub fn print_error_chain(err: &dyn std::error::Error) {
|
||||
eprintln!("Error: {}", err);
|
||||
pub fn print_error_chain(err: &dyn std::error::Error) -> String {
|
||||
|
||||
let mut source = err.source();
|
||||
let mut level = 1;
|
||||
let mut err_string = String::from(format!("Error: {}", err));
|
||||
|
||||
while let Some(err) = source {
|
||||
eprintln!(" {}: {}", level, err);
|
||||
source = err.source();
|
||||
level += 1;
|
||||
}
|
||||
let mut source = err.source();
|
||||
let mut level = 1;
|
||||
|
||||
while let Some(err) = source {
|
||||
err_string.push_str(format!(" {}: {}", level, err).as_str());
|
||||
source = err.source();
|
||||
level += 1;
|
||||
}
|
||||
err_string
|
||||
}
|
||||
|
||||
pub fn handle_error(err: BlockchainError) {
|
||||
pub fn handle_error(err: BlockchainError) -> String {
|
||||
match &err {
|
||||
BlockchainError::Tx(tx) => {
|
||||
match tx {
|
||||
|
||||
16
src/main.rs
16
src/main.rs
@ -6,14 +6,24 @@ pub mod seeds_constants;
|
||||
pub mod watcher;
|
||||
pub mod cli;
|
||||
|
||||
use crate::{args::get_args, watcher::watcher::Watcher};
|
||||
use crate::watcher::watcher::Watcher;
|
||||
use clap::Parser;
|
||||
|
||||
pub async fn log(exec_tx: &tokio::sync::mpsc::Sender<watcher::ExecutorCommand>, msg: String) {
|
||||
let cmd = watcher::ExecutorCommand::Print(msg);
|
||||
let _ = exec_tx.send(cmd).await;
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
||||
let args = get_args();
|
||||
let args = args::CliArgs::parse();
|
||||
|
||||
let mut watcher = Watcher::build().file(args.seed_file).addr(args.addr).start().await;
|
||||
let mut watcher = Watcher::build()
|
||||
.file(args.seed_file)
|
||||
.addr(args.addr)
|
||||
.bootstrap(args.bootstrap)
|
||||
.start().await;
|
||||
|
||||
loop {
|
||||
if !watcher.poll().await.is_ok_and(|b| b) {
|
||||
|
||||
@ -45,7 +45,6 @@ pub enum NodeCommand {
|
||||
Exit,
|
||||
}
|
||||
|
||||
|
||||
impl NativeNode {
|
||||
|
||||
pub fn peer_addresses(&self) -> Vec<SocketAddr> {
|
||||
@ -84,7 +83,7 @@ impl NativeNode {
|
||||
self.tcp_peers.insert(id, peer);
|
||||
}
|
||||
|
||||
pub fn new_with_id(
|
||||
pub async fn new_with_id(
|
||||
id: uuid::Uuid,
|
||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||
addr: Option<SocketAddr>,
|
||||
@ -96,6 +95,7 @@ impl NativeNode {
|
||||
tcp_peers: HashMap::new(),
|
||||
chain: {
|
||||
if blocks.is_some() {
|
||||
crate::log(&exec_tx, msg!(INFO, "Building Chain")).await;
|
||||
Blockchain::build(blocks.unwrap()).unwrap_or(Default::default())
|
||||
} else {
|
||||
Default::default()
|
||||
@ -109,7 +109,7 @@ impl NativeNode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
pub async fn new(
|
||||
addr: Option<SocketAddr>,
|
||||
blocks: Option<Vec<core::Block>>,
|
||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||
@ -120,6 +120,7 @@ impl NativeNode {
|
||||
tcp_peers: HashMap::new(),
|
||||
chain: {
|
||||
if blocks.is_some() {
|
||||
crate::log(&exec_tx, msg!(INFO, "Building Chain")).await;
|
||||
Blockchain::build(blocks.unwrap()).unwrap_or(Default::default())
|
||||
} else {
|
||||
Default::default()
|
||||
@ -223,10 +224,17 @@ impl NativeNode {
|
||||
}
|
||||
|
||||
async fn log(&self, msg: String) {
|
||||
let _ = self.exec_tx.send(ExecutorCommand::Print(msg));
|
||||
let _ = self.exec_tx.send(ExecutorCommand::Print(msg)).await;
|
||||
}
|
||||
|
||||
pub async fn run_native(&mut self) {
|
||||
pub async fn transaction(&mut self, tx: &core::Tx) {
|
||||
match self.chain.apply(tx) {
|
||||
Ok(_) => self.log(msg!(INFO, "Transaction applied")).await,
|
||||
Err(e) => self.log(crate::error::print_error_chain(&e)).await
|
||||
};
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
|
||||
if let Some(a) = self.addr {
|
||||
self.start_connection_listner(a.clone()).await;
|
||||
@ -255,7 +263,7 @@ impl NativeNode {
|
||||
self.process_message(peer_id, &message).await;
|
||||
},
|
||||
NodeCommand::Transaction { tx } => {
|
||||
self.chain.apply(&tx).unwrap();
|
||||
self.transaction(&tx).await;
|
||||
self.broadcast_transaction(&tx).await;
|
||||
},
|
||||
NodeCommand::CreateBlock => {
|
||||
@ -265,7 +273,7 @@ impl NativeNode {
|
||||
},
|
||||
NodeCommand::ListBlocks => {
|
||||
self.log(msg!(INFO, "Received DebugListBlocks command")).await;
|
||||
self.chain.print_blocks();
|
||||
self.log(self.chain.list_blocks()).await;
|
||||
},
|
||||
NodeCommand::ListPeers => {
|
||||
self.log(msg!(INFO, "Received DebugListPeers command")).await;
|
||||
|
||||
@ -61,12 +61,12 @@ impl Executor {
|
||||
// }
|
||||
}
|
||||
|
||||
async fn render_string(&self, str: String) {
|
||||
pub async fn render_string(&self, str: String) {
|
||||
let rd_cmd = RenderCommand::RenderStringToPane{
|
||||
str,
|
||||
pane: RenderPane::CliOutput
|
||||
};
|
||||
let _ = self.render_tx.send(rd_cmd);
|
||||
let _ = self.render_tx.send(rd_cmd).await;
|
||||
}
|
||||
|
||||
async fn echo(&self, s: Vec<String>) {
|
||||
|
||||
@ -6,8 +6,6 @@ use tokio::time::{timeout, Duration};
|
||||
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::watcher::renderer::RenderPane;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Parser {
|
||||
rx: mpsc::Receiver<ParserCommand>,
|
||||
@ -20,10 +18,6 @@ pub enum ParserCommand {
|
||||
Exit
|
||||
}
|
||||
|
||||
const CMD_ECHO: &str = "echo";
|
||||
const CMD_CLEAR: &str = "clear";
|
||||
const CMD_NODE: &str = "node";
|
||||
|
||||
impl Parser {
|
||||
pub fn new(
|
||||
rx: mpsc::Receiver<ParserCommand>,
|
||||
@ -64,30 +58,6 @@ impl Parser {
|
||||
let cmd = cli(&argv);
|
||||
let _ = self.exec_tx.send(cmd).await;
|
||||
},
|
||||
//match *cmd {
|
||||
// CMD_NODE => { cli(&s_split) }
|
||||
// CMD_ECHO => {
|
||||
// if args.is_empty() {
|
||||
// ExecutorCommand::InvalidCommand(msg!(ERROR, "print expects args"))
|
||||
// } else {
|
||||
// ExecutorCommand::Echo(args.iter().map(|a| a.to_string()).collect())
|
||||
// }
|
||||
// }
|
||||
// CMD_CLEAR => {
|
||||
// if args.is_empty() {
|
||||
// ExecutorCommand::Clear(RenderPane::All)
|
||||
// } else if args[0] == "in" {
|
||||
// ExecutorCommand::Clear(RenderPane::CliInput)
|
||||
// } else if args[0] == "out" {
|
||||
// ExecutorCommand::Clear(RenderPane::CliOutput)
|
||||
// } else {
|
||||
// ExecutorCommand::InvalidCommand(msg!(ERROR, "clear: Unknown arg {}", args[0]))
|
||||
// }
|
||||
// }
|
||||
// _ => {
|
||||
// ExecutorCommand::InvalidCommand(msg!(ERROR, "Unknown Command {cmd}"))
|
||||
// }
|
||||
// };
|
||||
ParserCommand::Exit => {
|
||||
self.exit().await;
|
||||
}
|
||||
|
||||
@ -20,7 +20,8 @@ pub struct Watcher {
|
||||
#[derive(Default)]
|
||||
pub struct WatcherBuilder {
|
||||
addr: Option<SocketAddr>,
|
||||
seed_file: Option<String>
|
||||
seed_file: Option<String>,
|
||||
bootstrap: bool
|
||||
}
|
||||
|
||||
impl Watcher {
|
||||
@ -28,6 +29,18 @@ impl Watcher {
|
||||
WatcherBuilder::new()
|
||||
}
|
||||
|
||||
pub fn render_tx(&self) -> mpsc::Sender<RenderCommand> {
|
||||
self.render_tx.clone()
|
||||
}
|
||||
|
||||
pub fn parser_tx(&self) -> mpsc::Sender<ParserCommand> {
|
||||
self.parser_tx.clone()
|
||||
}
|
||||
|
||||
pub fn exec_tx(&self) -> mpsc::Sender<ExecutorCommand> {
|
||||
self.exec_tx.clone()
|
||||
}
|
||||
|
||||
pub async fn log(render_tx: &mpsc::Sender<RenderCommand>, msg: String) {
|
||||
let rendermsg = RenderCommand::RenderStringToPane { str: msg, pane: RenderPane::CliOutput };
|
||||
if let Err(e) = render_tx.send(rendermsg).await {
|
||||
@ -99,6 +112,11 @@ impl WatcherBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn bootstrap(mut self, bootstrap: bool) -> Self {
|
||||
self.bootstrap = bootstrap;
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn log(render_tx: &mpsc::Sender<RenderCommand>, msg: String) {
|
||||
let rendermsg = RenderCommand::RenderStringToPane { str: msg, pane: RenderPane::CliOutput };
|
||||
let _ = render_tx.send(rendermsg).await;
|
||||
@ -122,7 +140,11 @@ impl WatcherBuilder {
|
||||
.as_ref()
|
||||
.and_then(|path| std::fs::read_to_string(path).ok())
|
||||
.and_then(|content| serde_json::from_str(&content).ok());
|
||||
let mut node = NativeNode::new(self.addr.clone(), blocks, exec_tx.clone());
|
||||
|
||||
let mut node = NativeNode::new(self.addr.clone(), blocks, exec_tx.clone()).await;
|
||||
if self.bootstrap {
|
||||
let _ = node.bootstrap().await;
|
||||
}
|
||||
let _ = Self::log(&render_tx, msg!(INFO, "Build Node"));
|
||||
|
||||
let parser_handle = tokio::spawn({
|
||||
@ -148,7 +170,7 @@ impl WatcherBuilder {
|
||||
|
||||
let node_handle = tokio::spawn({
|
||||
async move {
|
||||
node.run_native().await;
|
||||
node.run().await;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user