Compare commits
No commits in common. "da9daa9359616b55a70694982e46f9db54b1bf84" and "d8fd0dfb73c6a4b6deab94919241614194e03a73" have entirely different histories.
da9daa9359
...
d8fd0dfb73
1
TODO
@ -5,4 +5,3 @@ Non Exaustive list of ideas:
|
|||||||
- Mouse Input []
|
- Mouse Input []
|
||||||
- Http server []
|
- Http server []
|
||||||
- RCI []
|
- RCI []
|
||||||
- gemini
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
crossterm = "0.29.0"
|
crossterm = "0.29.0"
|
||||||
ratatui = "0.29.0"
|
ratatui = "0.29.0"
|
||||||
vlogger = { path = "../vlogger" }
|
ws = "0.9.2"
|
||||||
|
vlogger = { path = "../lib/logger-rs" }
|
||||||
clap = { version = "4.5.47", features = ["derive"] }
|
clap = { version = "4.5.47", features = ["derive"] }
|
||||||
textwrap = "0.16.2"
|
textwrap = "0.16.2"
|
||||||
|
|||||||
1
lib/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
5112
native_client/Cargo.lock
generated
@ -2,27 +2,7 @@
|
|||||||
name = "native_client"
|
name = "native_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
egui = "0.32.2"
|
tauri = "=2.0.0-alpha.4"
|
||||||
eframe = { version = "0.32.2", default-features = false, features = [
|
tauri-egui = "0.3.0"
|
||||||
"default_fonts", # Embed the default egui fonts.
|
|
||||||
"glow", # Use the glow rendering backend. Alternative: "wgpu".
|
|
||||||
"persistence", # Enable restoring app state when restarting the app.
|
|
||||||
"wayland", # To support Linux (and CI)
|
|
||||||
"x11", # To support older Linux distributions (restores one of the default features)
|
|
||||||
] }
|
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
|
||||||
watchlet = { path = "../watchlet" }
|
|
||||||
hex = "0.4.3"
|
|
||||||
vlogger = { path = "../vlogger" }
|
|
||||||
bincode = { version = "2.0.1", features = ["serde"] }
|
|
||||||
shared = { path = "../shared" }
|
|
||||||
tokio = { version = "1.47.1", features = ["full", "rt-multi-thread"] }
|
|
||||||
tokio-tungstenite = "0.27.0"
|
|
||||||
thiserror = "2.0.16"
|
|
||||||
futures-util = "0.3.31"
|
|
||||||
uuid = { version = "1.18.1", features = ["v4"] }
|
|
||||||
crossbeam = "0.8.4"
|
|
||||||
once_cell = "1.21.3"
|
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
let dir = env!("CARGO_MANIFEST_DIR");
|
|
||||||
let data_path = format!("{dir}/data");
|
|
||||||
|
|
||||||
println!("cargo:rustc-env=DATA_DIR_PATH={}", data_path);
|
|
||||||
}
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
use crossbeam::channel::Sender;
|
|
||||||
use vlogger::*;
|
|
||||||
use watchlet::{FileStorage, Wallet, WalletManager};
|
|
||||||
|
|
||||||
use crate::bus::event::{subscribe_system_event, SystemEvent};
|
|
||||||
use crate::messages::client::ClientMessage;
|
|
||||||
use crate::messages::error::SystemError;
|
|
||||||
use crate::messages::frontend::FrontendMessage;
|
|
||||||
use crate::messages::backend::BackendMessage;
|
|
||||||
use crate::constants::DATA_DIR_PATH;
|
|
||||||
|
|
||||||
use std::path;
|
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
||||||
pub struct WalletState {
|
|
||||||
pub address: String,
|
|
||||||
pub balance: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WalletService {
|
|
||||||
exit: bool,
|
|
||||||
receiver: crossbeam::channel::Receiver<BackendMessage>,
|
|
||||||
fr_sender: Sender<FrontendMessage>,
|
|
||||||
ws_sender: Sender<ClientMessage>,
|
|
||||||
wallet_manager: WalletManager<FileStorage>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WalletService {
|
|
||||||
pub fn new(
|
|
||||||
receiver: crossbeam::channel::Receiver<BackendMessage>,
|
|
||||||
fr_sender: Sender<FrontendMessage>,
|
|
||||||
ws_sender: Sender<ClientMessage>,
|
|
||||||
) -> Self {
|
|
||||||
let wallet_path = path::PathBuf::from(format!("{}/wallet/wallet.age", DATA_DIR_PATH));
|
|
||||||
let storage = FileStorage::new(wallet_path.into());
|
|
||||||
let mut wallet_manager = WalletManager::new(storage);
|
|
||||||
wallet_manager.load_wallet("password".into()).unwrap();
|
|
||||||
Self {
|
|
||||||
exit: false,
|
|
||||||
receiver,
|
|
||||||
fr_sender,
|
|
||||||
ws_sender,
|
|
||||||
wallet_manager
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wallet(&self) -> Option<&Wallet> {
|
|
||||||
self.wallet_manager.wallet()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exit(&mut self) {
|
|
||||||
log!(INFO, "Shutting down WalletService",);
|
|
||||||
self.exit = true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
|
||||||
log!(DEBUG, "Dummy Update");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_state(&self) -> Option<WalletState> {
|
|
||||||
if let Some(wallet) = self.wallet() {
|
|
||||||
let address = hex::encode(wallet.address());
|
|
||||||
let balance = wallet.balance();
|
|
||||||
Some(WalletState { address, balance })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn handle_cmd(&mut self, cmd: BackendMessage) {
|
|
||||||
log!(DEBUG, "Received cmd");
|
|
||||||
match cmd {
|
|
||||||
BackendMessage::StateRequest => {
|
|
||||||
let msg = match self.get_state() {
|
|
||||||
Some(state) => FrontendMessage::StateResponse(state),
|
|
||||||
None => FrontendMessage::Error(SystemError::WalletNotLoaded),
|
|
||||||
};
|
|
||||||
if let Err(e) = self.fr_sender.send(msg) {
|
|
||||||
log!(ERROR, "Failed to send FrontendMessage: {e}");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
BackendMessage::Transaction(_transaction) => {
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub async fn handle_system_event(&mut self, event: SystemEvent) {
|
|
||||||
match event {
|
|
||||||
SystemEvent::Shutdown => self.exit(),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run(&mut self) {
|
|
||||||
let mut event_bus = subscribe_system_event();
|
|
||||||
while !self.exit {
|
|
||||||
tokio::select! {
|
|
||||||
result = tokio::task::spawn_blocking({
|
|
||||||
let rx = self.receiver.clone();
|
|
||||||
move || rx.recv()
|
|
||||||
}) => {
|
|
||||||
if let Ok(Ok(cmd)) = result {
|
|
||||||
self.handle_cmd(cmd).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = event_bus.recv() => {
|
|
||||||
if let Ok(event) = result {
|
|
||||||
self.handle_system_event(event).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use shared::WsClientResponse;
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
use crossbeam::channel::{Receiver, Sender};
|
|
||||||
use futures_util::{SinkExt, StreamExt};
|
|
||||||
use tokio_tungstenite::WebSocketStream;
|
|
||||||
use tokio_tungstenite::{tungstenite::{self, Message }, MaybeTlsStream};
|
|
||||||
use thiserror::Error;
|
|
||||||
use uuid::Uuid;
|
|
||||||
use vlogger::*;
|
|
||||||
|
|
||||||
use crate::bus::event::{publish_system_event, subscribe_system_event, SystemEvent};
|
|
||||||
use crate::messages::{backend::BackendMessage, client::ClientMessage };
|
|
||||||
|
|
||||||
static BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard();
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum WsClientError {
|
|
||||||
#[error("WS Error: {0}")]
|
|
||||||
WsError(#[from] tokio_tungstenite::tungstenite::Error),
|
|
||||||
#[error("Decode Error: {0}")]
|
|
||||||
Decode(#[from] bincode::error::DecodeError),
|
|
||||||
#[error("Encode Error: {0}")]
|
|
||||||
Encode(#[from] bincode::error::EncodeError),
|
|
||||||
|
|
||||||
#[error("Network Error: Not Connected")]
|
|
||||||
NoConnection
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WsClient {
|
|
||||||
back_tx: Sender<BackendMessage>,
|
|
||||||
rx: Receiver<ClientMessage>,
|
|
||||||
nodes: HashMap<Uuid, SocketAddr>,
|
|
||||||
socket: Option<WebSocketStream<MaybeTlsStream<TcpStream>>>,
|
|
||||||
exit: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WsClient {
|
|
||||||
pub async fn new(
|
|
||||||
back_tx: Sender<BackendMessage>,
|
|
||||||
rx: Receiver<ClientMessage>,
|
|
||||||
) -> Result<Self, WsClientError> {
|
|
||||||
publish_system_event(SystemEvent::WsClientConnect);
|
|
||||||
Ok(Self {
|
|
||||||
back_tx,
|
|
||||||
rx,
|
|
||||||
nodes: HashMap::new(),
|
|
||||||
socket: None,
|
|
||||||
exit: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn connect_to_nodes(&mut self) -> Result<(), WsClientError> {
|
|
||||||
let (socket, _response) = tokio_tungstenite::connect_async("ws://localhost:9001").await?;
|
|
||||||
|
|
||||||
self.socket = Some(socket);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn handle_cmd(&mut self, cmd: ClientMessage) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn exit(&mut self) {
|
|
||||||
log!(INFO, "Shutting down Websocket Client");
|
|
||||||
self.exit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn handle_system_event(&mut self, event: SystemEvent) {
|
|
||||||
match event {
|
|
||||||
SystemEvent::Shutdown => self.exit(),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run(&mut self) -> Result<(), WsClientError> {
|
|
||||||
let mut event_bus = subscribe_system_event();
|
|
||||||
|
|
||||||
while !self.exit {
|
|
||||||
tokio::select! {
|
|
||||||
event_res = event_bus.recv() => {
|
|
||||||
if let Ok(event) = event_res {
|
|
||||||
self.handle_system_event(event).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ = tokio::time::sleep(tokio::time::Duration::from_millis(1)) => {
|
|
||||||
while let Ok(cmd) = self.rx.try_recv() {
|
|
||||||
self.execute_command(cmd).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ws_msg_res = async {
|
|
||||||
if let Some(socket) = self.socket.as_mut() {
|
|
||||||
Ok(socket.next().await)
|
|
||||||
} else {
|
|
||||||
Err(WsClientError::NoConnection)
|
|
||||||
}
|
|
||||||
} => {
|
|
||||||
if let Ok(Some(cmd)) = ws_msg_res {
|
|
||||||
match cmd {
|
|
||||||
Ok(msg) => self.handle_ws_message(msg).await?,
|
|
||||||
Err(e) => self.handle_ws_error(e).await?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(self.socket.as_mut().unwrap().close(None).await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_ws_error(&mut self, e: tungstenite::Error) -> Result<(), WsClientError> {
|
|
||||||
if self.socket.is_some() {
|
|
||||||
match e {
|
|
||||||
tungstenite::Error::ConnectionClosed => {
|
|
||||||
self.socket.as_mut().unwrap().close(None).await?;
|
|
||||||
publish_system_event(SystemEvent::WsClientDisconnect)
|
|
||||||
},
|
|
||||||
tungstenite::Error::AlreadyClosed => {},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(WsClientError::NoConnection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_ws_message(&mut self, msg: Message) -> Result<(), WsClientError> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn execute_command(&mut self, cmd: ClientMessage) -> Result<(), WsClientError> {
|
|
||||||
if self.socket.is_some() {
|
|
||||||
match cmd {
|
|
||||||
ClientMessage::BroadcastTransaction(tx) => {
|
|
||||||
let bin_tx = bincode::encode_to_vec(tx, BINCODE_CONFIG)?;
|
|
||||||
self.socket.as_mut().unwrap().send(bin_tx.into()).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
ClientMessage::ConnectToNetwork => {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(WsClientError::NoConnection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
use tokio::sync::broadcast::{self, Sender, Receiver};
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum SystemEvent {
|
|
||||||
WsClientConnect,
|
|
||||||
WsClientDisconnect,
|
|
||||||
Shutdown,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EventBus {
|
|
||||||
sender: Sender<SystemEvent>,
|
|
||||||
_receiver: Receiver<SystemEvent>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventBus {
|
|
||||||
pub fn new() -> Self{
|
|
||||||
let (tx, rx) = broadcast::channel::<SystemEvent>(100);
|
|
||||||
Self {
|
|
||||||
sender: tx,
|
|
||||||
_receiver: rx,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn publish(&self, msg: SystemEvent) {
|
|
||||||
if let Err(e) = self.sender.send(msg) {
|
|
||||||
eprintln!("{e}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subscribe(&self) -> broadcast::Receiver<SystemEvent> {
|
|
||||||
self.sender.subscribe()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static SYSTEM_EVENT_BUS: Lazy<Arc<EventBus>> = Lazy::new(|| Arc::new(EventBus::new()));
|
|
||||||
|
|
||||||
pub fn publish_system_event(event: SystemEvent) {
|
|
||||||
SYSTEM_EVENT_BUS.publish(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subscribe_system_event() -> broadcast::Receiver<SystemEvent> {
|
|
||||||
SYSTEM_EVENT_BUS.subscribe()
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
pub const DATA_DIR_PATH: &str = env!("DATA_DIR_PATH");
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
use crate::messages::backend::BackendMessage;
|
|
||||||
|
|
||||||
pub trait DisplayPage {
|
|
||||||
fn show(&mut self, ctx: &egui::Context) -> Option<BackendMessage>;
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
use crossbeam::channel::Sender;
|
|
||||||
|
|
||||||
use crate::{frontend::DisplayPage, messages::backend::BackendMessage};
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
|
||||||
pub struct HomePage {
|
|
||||||
label: String,
|
|
||||||
|
|
||||||
value: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HomePage {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
label: Default::default(),
|
|
||||||
value: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DisplayPage for HomePage {
|
|
||||||
fn show(&mut self, ctx: &egui::Context) -> Option<BackendMessage> {
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
|
||||||
ui.heading("eframe template");
|
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label("Write something: ");
|
|
||||||
ui.text_edit_singleline(&mut self.label).request_focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.add(egui::Slider::new(&mut self.value, 0.0..=10.0).text("value"));
|
|
||||||
if ui.button("Increment").clicked() {
|
|
||||||
self.value += 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
ui.add(egui::github_link_file!(
|
|
||||||
"https://github.com/emilk/eframe_template/blob/main/",
|
|
||||||
"Source code."
|
|
||||||
));
|
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
|
||||||
egui::warn_if_debug_build(ui);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
use crossbeam::channel::Sender;
|
|
||||||
|
|
||||||
use egui::{Align, Layout, RichText};
|
|
||||||
|
|
||||||
use crate::{frontend::DisplayPage, messages::backend::BackendMessage};
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct TransactionPage {
|
|
||||||
from_to_amount: [String; 3],
|
|
||||||
focused: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TransactionPage {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
from_to_amount: Default::default(),
|
|
||||||
focused: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct TransactionRequest {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const TX_FIELDS: &[&str] = &[
|
|
||||||
"From:",
|
|
||||||
"To:",
|
|
||||||
"Amount:",
|
|
||||||
];
|
|
||||||
|
|
||||||
impl DisplayPage for TransactionPage {
|
|
||||||
fn show(&mut self, ctx: &egui::Context) -> Option<BackendMessage> {
|
|
||||||
let mut msg = None;
|
|
||||||
|
|
||||||
ctx.input(|input| {
|
|
||||||
if input.key_pressed(egui::Key::Tab) {
|
|
||||||
self.focused = (self.focused + 1) % TX_FIELDS.len()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
|
||||||
ui.heading("Transaction Page");
|
|
||||||
ui.separator();
|
|
||||||
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
|
|
||||||
for (i, f) in TX_FIELDS.iter().enumerate() {
|
|
||||||
ui.add_space(8.0);
|
|
||||||
ui.label(RichText::new(*f).size(14.0));
|
|
||||||
if i == self.focused {
|
|
||||||
ui.text_edit_singleline(&mut self.from_to_amount[i]).request_focus();
|
|
||||||
} else {
|
|
||||||
ui.text_edit_singleline(&mut self.from_to_amount[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if ui.button("GetState").clicked() {
|
|
||||||
msg = Some(BackendMessage::StateRequest);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
use crate::{backend::wallet::WalletState, frontend::DisplayPage, messages::backend::BackendMessage};
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct WalletInterface {
|
|
||||||
wallet: Option<WalletState>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WalletInterface {
|
|
||||||
pub fn new(wallet: Option<WalletState>) -> Self{
|
|
||||||
Self {
|
|
||||||
wallet,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn set_wallet(&mut self, wallet: WalletState) {
|
|
||||||
self.wallet = Some(wallet);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wallet(&self) -> &Option<WalletState> {
|
|
||||||
&self.wallet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DisplayPage for WalletInterface {
|
|
||||||
fn show(&mut self, ctx: &egui::Context) -> Option<BackendMessage> {
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
|
||||||
ui.heading("Wallet Interface");
|
|
||||||
ui.separator();
|
|
||||||
ui.add_space(20.0);
|
|
||||||
ui.vertical_centered(|ui| {
|
|
||||||
egui::Grid::new("wallet_grid")
|
|
||||||
.num_columns(2)
|
|
||||||
.spacing([20.0, 10.0])
|
|
||||||
.striped(true)
|
|
||||||
.show(ui, |ui| {
|
|
||||||
if let Some(wallet) = &self.wallet {
|
|
||||||
ui.strong("Address:");
|
|
||||||
ui.label(format!("0x{}", &wallet.address));
|
|
||||||
ui.end_row();
|
|
||||||
|
|
||||||
ui.strong("Balance:");
|
|
||||||
ui.label(wallet.balance.to_string());
|
|
||||||
ui.end_row();
|
|
||||||
} else {
|
|
||||||
ui.spinner();
|
|
||||||
ui.label("Loading Wallet...");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,279 +0,0 @@
|
|||||||
use std::{process::exit, thread::sleep, time::Duration};
|
|
||||||
|
|
||||||
use egui::{Button, Color32, Key, RichText, Stroke};
|
|
||||||
use watchlet::WalletError;
|
|
||||||
use crate::{backend::{wallet::WalletState, ws_client::WsClientError}, bus::event::{publish_system_event, subscribe_system_event, SystemEvent}, messages::{backend::BackendMessage, client::ClientMessage, frontend::FrontendMessage}};
|
|
||||||
use vlogger::*;
|
|
||||||
|
|
||||||
use super::{pages::HomePage, DisplayPage, TransactionPage, wallet_interface::WalletInterface};
|
|
||||||
use crossbeam::channel::{Receiver, Sender};
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct State {
|
|
||||||
pages: Vec<Page>,
|
|
||||||
current_page_index: usize,
|
|
||||||
side_panel: bool,
|
|
||||||
connected: bool,
|
|
||||||
wallet: Option<WalletState>,
|
|
||||||
|
|
||||||
#[serde(skip)]
|
|
||||||
receiver: Receiver<FrontendMessage>,
|
|
||||||
#[serde(skip)]
|
|
||||||
be_sender: crossbeam::channel::Sender<BackendMessage>,
|
|
||||||
#[serde(skip)]
|
|
||||||
ws_sender: crossbeam::channel::Sender<ClientMessage>,
|
|
||||||
#[serde(skip)]
|
|
||||||
event_bus: tokio::sync::broadcast::Receiver<SystemEvent>,
|
|
||||||
#[serde(skip)]
|
|
||||||
callback: Option<PageCallback>,
|
|
||||||
#[serde(skip)]
|
|
||||||
be_msg: Option<BackendMessage>,
|
|
||||||
#[serde(skip)]
|
|
||||||
ws_msg: Option<ClientMessage>,
|
|
||||||
#[serde(skip)]
|
|
||||||
ws_errors: Vec<WsClientError>,
|
|
||||||
#[serde(skip)]
|
|
||||||
wallet_errors: Vec<WalletError>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
|
||||||
pub enum Page {
|
|
||||||
Home(HomePage),
|
|
||||||
Transaction(TransactionPage),
|
|
||||||
Wallet(WalletInterface),
|
|
||||||
}
|
|
||||||
|
|
||||||
const HOME_PAGE_INDEX: usize = 0;
|
|
||||||
const TRANSACTION_PAGE_INDEX: usize = 1;
|
|
||||||
const WALLET_INTERFACE_INDEX: usize = 2;
|
|
||||||
|
|
||||||
type PageCallback = fn(&mut State);
|
|
||||||
|
|
||||||
static PAGE_CALLBACKS: &[PageCallback] = &[
|
|
||||||
|_| {},
|
|
||||||
|_| {},
|
|
||||||
|s| {
|
|
||||||
if let Page::Wallet(w) = &mut s.pages[s.current_page_index] {
|
|
||||||
if w.wallet().is_none() {
|
|
||||||
if let Some(wallet) = &s.wallet {
|
|
||||||
w.set_wallet(wallet.clone());
|
|
||||||
s.callback = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const PAGE_INDEXES: &[(usize, &str, Option<PageCallback>)] = &[
|
|
||||||
(HOME_PAGE_INDEX, "Home", None),
|
|
||||||
(TRANSACTION_PAGE_INDEX, "Transaction", None),
|
|
||||||
(WALLET_INTERFACE_INDEX, "Wallet", Some(PAGE_CALLBACKS[WALLET_INTERFACE_INDEX]))
|
|
||||||
];
|
|
||||||
|
|
||||||
impl DisplayPage for Page {
|
|
||||||
fn show(&mut self, ctx: &egui::Context) -> Option<BackendMessage> {
|
|
||||||
match self {
|
|
||||||
Page::Home(home) => home.show(ctx),
|
|
||||||
Page::Transaction(tx) => tx.show(ctx),
|
|
||||||
Page::Wallet(wallet) => wallet.show(ctx),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for State {
|
|
||||||
fn default() -> Self {
|
|
||||||
let (_, front_rx) = crossbeam::channel::unbounded::<FrontendMessage>();
|
|
||||||
let (back_tx, _) = crossbeam::channel::unbounded::<BackendMessage>();
|
|
||||||
let (ws_tx, _) = crossbeam::channel::unbounded::<ClientMessage>();
|
|
||||||
Self {
|
|
||||||
pages: vec![
|
|
||||||
Page::Home(HomePage::new()),
|
|
||||||
Page::Transaction(TransactionPage::new()),
|
|
||||||
Page::Wallet(WalletInterface::new(None)),
|
|
||||||
],
|
|
||||||
current_page_index: HOME_PAGE_INDEX,
|
|
||||||
receiver: front_rx,
|
|
||||||
be_sender: back_tx,
|
|
||||||
ws_sender: ws_tx,
|
|
||||||
event_bus: subscribe_system_event(),
|
|
||||||
wallet: None,
|
|
||||||
callback: None,
|
|
||||||
be_msg: None,
|
|
||||||
ws_msg: None,
|
|
||||||
side_panel: true,
|
|
||||||
connected: false,
|
|
||||||
ws_errors: vec![],
|
|
||||||
wallet_errors: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State {
|
|
||||||
pub fn new(
|
|
||||||
cc: &eframe::CreationContext<'_>,
|
|
||||||
receiver: Receiver<FrontendMessage>,
|
|
||||||
sender: Sender<BackendMessage>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(storage) = cc.storage {
|
|
||||||
let mut ret = eframe::get_value::<Self>(storage, eframe::APP_KEY).unwrap_or_default();
|
|
||||||
ret.receiver = receiver;
|
|
||||||
ret.be_sender = sender;
|
|
||||||
ret
|
|
||||||
} else {
|
|
||||||
Self {
|
|
||||||
receiver,
|
|
||||||
be_sender: sender,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_callback(&mut self) {
|
|
||||||
if let Some(c) = self.callback {
|
|
||||||
c(self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_command(&mut self) {
|
|
||||||
if let Some(cmd) = &self.ws_msg {
|
|
||||||
if let Err(e) = self.ws_sender.send((*cmd).clone()) {
|
|
||||||
log!(ERROR, "{e}");
|
|
||||||
} else {
|
|
||||||
self.ws_msg = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(cmd) = &self.be_msg {
|
|
||||||
if let Err(e) = self.be_sender.send((*cmd).clone()) {
|
|
||||||
log!(ERROR, "{e}");
|
|
||||||
} else {
|
|
||||||
self.be_msg = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_key_input(&self, ctx: &egui::Context) {
|
|
||||||
ctx.input(|input| {
|
|
||||||
if input.key_pressed(Key::Escape) {
|
|
||||||
publish_system_event(SystemEvent::Shutdown);
|
|
||||||
sleep(Duration::from_millis(100));
|
|
||||||
exit(1);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn home(&mut self) -> &mut Page {
|
|
||||||
&mut self.pages[HOME_PAGE_INDEX]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wallet(&mut self) -> &mut Page {
|
|
||||||
&mut self.pages[WALLET_INTERFACE_INDEX]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transaction(&mut self) -> &mut Page {
|
|
||||||
&mut self.pages[TRANSACTION_PAGE_INDEX]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_page(&mut self) -> &mut Page {
|
|
||||||
&mut self.pages[self.current_page_index]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn listen(&mut self) {
|
|
||||||
if let Ok(msg) = self.event_bus.try_recv() {
|
|
||||||
match msg {
|
|
||||||
SystemEvent::Shutdown => {
|
|
||||||
log!(DEBUG, "Received Wallet State Response");
|
|
||||||
}
|
|
||||||
SystemEvent::WsClientConnect => {
|
|
||||||
self.connected = true;
|
|
||||||
}
|
|
||||||
SystemEvent::WsClientDisconnect => {
|
|
||||||
self.connected = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Ok(msg) = self.receiver.try_recv() {
|
|
||||||
match msg {
|
|
||||||
FrontendMessage::StateResponse(state) => {
|
|
||||||
log!(DEBUG, "Received Wallet State Response");
|
|
||||||
self.wallet = Some(state)
|
|
||||||
}
|
|
||||||
FrontendMessage::Error(e) => {
|
|
||||||
log!(ERROR, "Received Error {e:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl eframe::App for State {
|
|
||||||
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
|
||||||
eframe::set_value(storage, eframe::APP_KEY, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
|
||||||
self.handle_key_input(ctx);
|
|
||||||
self.run_command();
|
|
||||||
self.listen();
|
|
||||||
self.run_callback();
|
|
||||||
egui::TopBottomPanel::top("Menu").show(ctx, |ui| {
|
|
||||||
ui.set_height(30.);
|
|
||||||
ui.horizontal_centered(|ui| {
|
|
||||||
if ui.button("☰").clicked() {
|
|
||||||
self.side_panel = !self.side_panel;
|
|
||||||
}
|
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
|
||||||
if self.connected {
|
|
||||||
ui.label(RichText::new("Connected").color(Color32::GREEN));
|
|
||||||
} else {
|
|
||||||
if ui.button(RichText::new("Disconnected").color(Color32::RED)).clicked() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if self.side_panel {
|
|
||||||
egui::SidePanel::left("menu panel").show(ctx, |ui| {
|
|
||||||
ui.set_width(150.0);
|
|
||||||
ui.heading("Navigation");
|
|
||||||
let available_width = ui.available_width();
|
|
||||||
|
|
||||||
for (i, s, c) in PAGE_INDEXES {
|
|
||||||
if ui.add_sized(
|
|
||||||
[available_width, 24.0],
|
|
||||||
Button::new(RichText::new(*s).size(14.0))
|
|
||||||
.right_text("")
|
|
||||||
.fill(Color32::TRANSPARENT)
|
|
||||||
).clicked() {
|
|
||||||
self.current_page_index = *i;
|
|
||||||
self.callback = *c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
self.current_page().show(ctx);
|
|
||||||
if !self.ws_errors.is_empty() || !self.wallet_errors.is_empty() {
|
|
||||||
egui::TopBottomPanel::bottom("Errors")
|
|
||||||
.frame(egui::Frame::new()
|
|
||||||
.fill(Color32::from_rgba_unmultiplied(200, 50, 50, 100))
|
|
||||||
.stroke(Stroke::new(1.0, Color32::from_rgb(255, 150, 150)))
|
|
||||||
)
|
|
||||||
.show(ctx, |ui| {
|
|
||||||
if !self.ws_errors.is_empty() {
|
|
||||||
ui.label("Network Errors:");
|
|
||||||
ui.separator();
|
|
||||||
for (i, e) in self.ws_errors.iter().enumerate() {
|
|
||||||
ui.label(format!(" {i}: {e}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !self.wallet_errors.is_empty() {
|
|
||||||
ui.label("Wallet Errors:");
|
|
||||||
ui.separator();
|
|
||||||
for (i, e) in self.wallet_errors.iter().enumerate() {
|
|
||||||
ui.label(format!(" {i}: {e}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
pub mod constants;
|
|
||||||
|
|
||||||
pub mod frontend {
|
|
||||||
pub mod state;
|
|
||||||
pub use state::*;
|
|
||||||
|
|
||||||
pub mod display;
|
|
||||||
pub use display::*;
|
|
||||||
|
|
||||||
pub use pages::*;
|
|
||||||
pub mod pages {
|
|
||||||
|
|
||||||
pub mod wallet_interface;
|
|
||||||
|
|
||||||
pub mod tx_page;
|
|
||||||
pub use tx_page::*;
|
|
||||||
|
|
||||||
pub mod home;
|
|
||||||
pub use home::*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod messages {
|
|
||||||
pub mod frontend;
|
|
||||||
pub mod backend;
|
|
||||||
pub mod error;
|
|
||||||
pub mod client;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod bus {
|
|
||||||
pub mod event;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod backend {
|
|
||||||
pub mod wallet;
|
|
||||||
pub mod ws_client;
|
|
||||||
}
|
|
||||||
@ -1,72 +1,5 @@
|
|||||||
#![warn(clippy::all, rust_2018_idioms)]
|
use tauri_egui;
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
|
||||||
|
|
||||||
use native_client::{backend::{wallet::WalletService, ws_client}, frontend, messages::{backend::BackendMessage, client::ClientMessage, frontend::FrontendMessage}};
|
fn main() {
|
||||||
use crossbeam::channel::{Sender, Receiver};
|
println!("Hello, world!");
|
||||||
|
|
||||||
fn dispatch_frontend(
|
|
||||||
receiver: Receiver<FrontendMessage>,
|
|
||||||
sender: Sender<BackendMessage>,
|
|
||||||
) -> eframe::Result {
|
|
||||||
let native_options = eframe::NativeOptions {
|
|
||||||
viewport: egui::ViewportBuilder::default()
|
|
||||||
.with_inner_size([400.0, 300.0])
|
|
||||||
.with_min_inner_size([300.0, 220.0]),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
eframe::run_native(
|
|
||||||
"eframe template",
|
|
||||||
native_options,
|
|
||||||
Box::new(|cc|
|
|
||||||
{
|
|
||||||
let mut style = (*cc.egui_ctx.style()).clone();
|
|
||||||
style.text_styles = [
|
|
||||||
(egui::TextStyle::Heading, egui::FontId::new(24.0, egui::FontFamily::Proportional)),
|
|
||||||
(egui::TextStyle::Body, egui::FontId::new(18.0, egui::FontFamily::Proportional)),
|
|
||||||
(egui::TextStyle::Button, egui::FontId::new(16.0, egui::FontFamily::Proportional)),
|
|
||||||
(egui::TextStyle::Small, egui::FontId::new(12.0, egui::FontFamily::Proportional)),
|
|
||||||
].into();
|
|
||||||
cc.egui_ctx.set_style(style);
|
|
||||||
cc.egui_ctx.set_request_repaint_callback(|info| {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(16)); // ~60 FPS max
|
|
||||||
});
|
|
||||||
Ok(Box::new(frontend::State::new(cc, receiver, sender)))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
|
||||||
let (front_tx, front_rx) = crossbeam::channel::unbounded::<FrontendMessage>();
|
|
||||||
let (back_tx, back_rx) = crossbeam::channel::unbounded::<BackendMessage>();
|
|
||||||
let (client_tx, client_rx) = crossbeam::channel::unbounded::<ClientMessage>();
|
|
||||||
|
|
||||||
let backend_handle = std::thread::spawn({
|
|
||||||
let back_tx = back_tx.clone();
|
|
||||||
move || {
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
rt.block_on({
|
|
||||||
let back_tx = back_tx.clone();
|
|
||||||
let front_tx = front_tx.clone();
|
|
||||||
async {
|
|
||||||
tokio::join!(
|
|
||||||
async {
|
|
||||||
let mut wallet_service = WalletService::new(back_rx, front_tx, client_tx);
|
|
||||||
wallet_service.run().await;
|
|
||||||
},
|
|
||||||
async {
|
|
||||||
let mut ws_client = ws_client::WsClient::new(back_tx, client_rx).await.unwrap();
|
|
||||||
ws_client.run().await.unwrap();
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let _res = dispatch_frontend(front_rx, back_tx);
|
|
||||||
|
|
||||||
backend_handle.join().unwrap();
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
use crate::frontend::TransactionRequest;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum BackendMessage {
|
|
||||||
StateRequest,
|
|
||||||
Transaction(TransactionRequest),
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
use shared::blockchain_core::Transaction;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum ClientMessage {
|
|
||||||
BroadcastTransaction(Transaction),
|
|
||||||
ConnectToNetwork,
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum SystemError {
|
|
||||||
WalletNotLoaded
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
use crate::backend::wallet::WalletState;
|
|
||||||
|
|
||||||
use super::error::SystemError;
|
|
||||||
|
|
||||||
pub enum FrontendMessage {
|
|
||||||
StateResponse(WalletState),
|
|
||||||
Error(SystemError)
|
|
||||||
}
|
|
||||||
3270
node/Cargo.lock
generated
@ -8,12 +8,13 @@ chrono = "0.4.41"
|
|||||||
clap = { version = "4.5.45", features = ["derive"] }
|
clap = { version = "4.5.45", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
serde_json = "1.0.143"
|
||||||
sha2 = "0.10.9"
|
sha2 = "0.10.9"
|
||||||
thiserror = "2.0.16"
|
thiserror = "2.0.16"
|
||||||
tokio = { version = "1.47.1", features = ["rt-multi-thread", "net", "sync", "time", "macros"] }
|
tokio = { version = "1.47.1", features = ["rt-multi-thread", "net", "sync", "time", "macros"] }
|
||||||
tokio-tungstenite = { version = "0.27.0", features = ["handshake", "rustls-tls-webpki-roots"] }
|
tokio-tungstenite = "0.27.0"
|
||||||
uuid = { version = "1.18.0", features = ["v4", "serde"] }
|
uuid = { version = "1.18.0", features = ["v4", "serde"] }
|
||||||
vlogger = { path = "../vlogger" }
|
vlogger = { path = "../lib/logger-rs" }
|
||||||
ratatui = "0.29.0"
|
ratatui = "0.29.0"
|
||||||
crossterm = { version = "0.29.0", features = ["event-stream"] }
|
crossterm = { version = "0.29.0", features = ["event-stream"] }
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
@ -29,9 +30,6 @@ futures = "0.3.31"
|
|||||||
secp256k1 = { version = "0.31.1", features = ["hashes", "rand", "recovery", "serde"] }
|
secp256k1 = { version = "0.31.1", features = ["hashes", "rand", "recovery", "serde"] }
|
||||||
ring = "0.17.14"
|
ring = "0.17.14"
|
||||||
shared = { path = "../shared", features = ["node"] }
|
shared = { path = "../shared", features = ["node"] }
|
||||||
watchlet = { path = "../watchlet" }
|
wallet = { path = "../wallet" }
|
||||||
cli-renderer = { path = "../cli-renderer" }
|
cli-renderer = { path = "../cli-renderer" }
|
||||||
tiny_http = "0.12.0"
|
tiny_http = "0.12.0"
|
||||||
serde-big-array = "0.5.1"
|
|
||||||
rust-ipfs = "0.14.1"
|
|
||||||
libp2p = "0.56.0"
|
|
||||||
|
|||||||
4
node/proc/09:09:13_6977
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[INFO ] [watcher.rs :60 ] 09:09:43: Physical memory usage: 9 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:09:43: Virtual memory usage: 1066 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:10:13: Physical memory usage: 9 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:10:13: Virtual memory usage: 1066 MB
|
||||||
30
node/proc/09:12:45_7340
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
[INFO ] [watcher.rs :60 ] 09:12:55: Physical memory usage: 5 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:12:55: Virtual memory usage: 1062 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:13:05: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:13:05: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:13:15: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:13:15: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:13:25: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:13:25: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:13:35: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:13:35: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:13:45: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:13:45: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:13:55: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:13:55: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:14:05: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:14:05: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:14:15: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:14:15: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:14:25: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:14:25: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:14:35: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:14:35: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:14:45: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:14:45: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:14:55: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:14:55: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:15:05: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:15:05: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:15:15: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:15:15: Virtual memory usage: 1063 MB
|
||||||
410
node/proc/09:15:49_17386
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
[INFO ] [watcher.rs :60 ] 09:15:59: Physical memory usage: 5 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:15:59: Virtual memory usage: 1062 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:16:09: Physical memory usage: 5 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:16:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:16:19: Physical memory usage: 5 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:16:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:16:29: Physical memory usage: 5 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:16:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:16:39: Physical memory usage: 5 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:16:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:16:49: Physical memory usage: 5 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:16:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:16:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:16:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:17:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:17:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:17:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:17:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:17:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:17:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:17:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:17:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:17:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:17:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:17:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:17:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:18:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:18:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:18:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:18:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:18:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:18:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:18:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:18:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:18:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:18:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:18:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:18:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:19:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:19:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:19:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:19:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:19:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:19:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:19:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:19:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:19:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:19:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:19:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:19:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:20:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:20:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:20:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:20:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:20:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:20:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:20:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:20:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:20:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:20:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:20:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:20:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:21:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:21:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:21:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:21:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:21:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:21:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:21:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:21:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:21:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:21:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:21:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:21:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:22:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:22:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:22:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:22:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:22:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:22:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:22:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:22:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:22:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:22:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:22:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:22:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:23:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:23:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:23:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:23:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:23:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:23:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:23:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:23:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:23:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:23:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:23:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:23:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:24:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:24:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:24:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:24:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:24:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:24:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:24:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:24:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:24:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:24:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:24:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:24:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:25:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:25:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:25:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:25:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:25:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:25:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:25:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:25:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:25:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:25:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:25:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:25:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:26:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:26:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:26:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:26:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:26:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:26:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:26:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:26:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:26:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:26:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:26:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:26:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:27:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:27:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:27:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:27:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:27:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:27:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:27:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:27:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:27:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:27:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:27:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:27:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:28:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:28:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:28:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:28:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:28:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:28:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:28:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:28:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:28:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:28:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:28:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:28:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:29:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:29:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:29:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:29:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:29:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:29:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:29:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:29:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:29:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:29:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:29:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:29:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:30:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:30:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:30:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:30:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:30:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:30:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:30:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:30:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:30:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:30:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:30:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:30:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:31:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:31:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:31:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:31:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:31:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:31:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:31:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:31:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:31:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:31:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:31:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:31:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:32:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:32:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:32:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:32:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:32:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:32:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:32:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:32:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:32:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:32:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:32:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:32:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:33:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:33:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:33:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:33:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:33:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:33:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:33:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:33:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:33:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:33:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:33:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:33:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:34:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:34:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:34:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:34:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:34:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:34:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:34:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:34:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:34:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:34:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:34:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:34:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:35:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:35:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:35:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:35:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:35:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:35:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:35:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:35:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:35:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:35:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:35:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:35:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:36:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:36:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:36:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:36:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:36:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:36:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:36:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:36:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:36:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:36:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:36:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:36:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:37:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:37:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:37:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:37:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:37:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:37:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:37:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:37:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:37:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:37:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:37:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:37:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:38:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:38:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:38:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:38:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:38:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:38:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:38:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:38:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:38:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:38:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:38:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:38:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:39:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:39:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:39:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:39:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:39:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:39:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:39:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:39:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:39:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:39:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:39:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:39:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:40:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:40:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:40:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:40:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:40:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:40:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:40:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:40:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:40:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:40:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:40:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:40:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:41:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:41:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:41:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:41:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:41:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:41:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:41:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:41:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:41:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:41:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:41:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:41:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:42:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:42:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:42:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:42:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:42:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:42:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:42:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:42:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:42:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:42:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:42:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:42:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:43:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:43:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:43:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:43:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:43:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:43:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:43:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:43:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:43:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:43:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:43:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:43:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:44:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:44:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:44:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:44:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:44:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:44:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:44:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:44:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:44:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:44:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:44:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:44:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:45:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:45:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:45:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:45:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:45:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:45:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:45:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:45:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:45:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:45:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:45:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:45:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:46:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:46:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:46:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:46:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:46:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:46:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:46:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:46:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:46:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:46:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:46:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:46:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:47:09: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:47:09: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:47:19: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:47:19: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:47:29: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:47:29: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:47:39: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:47:39: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:47:49: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:47:49: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:47:59: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:47:59: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:48:10: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:48:10: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:48:20: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:48:20: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:48:30: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:48:30: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:48:40: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:48:40: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:48:50: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:48:50: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:49:00: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:49:00: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:49:10: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:49:10: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:49:20: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:49:20: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:49:30: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:49:30: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:49:40: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:49:40: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:49:50: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:49:50: Virtual memory usage: 1063 MB
|
||||||
|
[INFO ] [watcher.rs :60 ] 09:50:00: Physical memory usage: 6 MB
|
||||||
|
[INFO ] [watcher.rs :61 ] 09:50:00: Virtual memory usage: 1063 MB
|
||||||
6
node/proc/15:16:35_93227
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[INFO ] [watcher.rs :145 ] 15:16:45: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:16:45: Virtual memory usage: 1691 MB
|
||||||
|
[INFO ] [watcher.rs :145 ] 15:16:55: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:16:55: Virtual memory usage: 1691 MB
|
||||||
|
[INFO ] [watcher.rs :145 ] 15:17:05: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:17:05: Virtual memory usage: 1691 MB
|
||||||
4
node/proc/15:17:19_93429
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[INFO ] [watcher.rs :145 ] 15:17:29: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:17:29: Virtual memory usage: 1691 MB
|
||||||
|
[INFO ] [watcher.rs :145 ] 15:17:39: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:17:39: Virtual memory usage: 1691 MB
|
||||||
6
node/proc/15:40:52_98073
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[INFO ] [watcher.rs :145 ] 15:41:02: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:41:02: Virtual memory usage: 1691 MB
|
||||||
|
[INFO ] [watcher.rs :145 ] 15:41:12: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:41:12: Virtual memory usage: 1691 MB
|
||||||
|
[INFO ] [watcher.rs :145 ] 15:41:22: Physical memory usage: 32 MB
|
||||||
|
[INFO ] [watcher.rs :154 ] 15:41:22: Virtual memory usage: 1691 MB
|
||||||
@ -1,10 +1,10 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use tiny_http::{ Method, Response, Header };
|
use tiny_http::{ Method, Response, Header };
|
||||||
use thiserror::Error;
|
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)]
|
||||||
@ -61,7 +61,7 @@ fn internal_server_error(e: String) -> Response<std::io::Cursor<Vec<u8>>> {
|
|||||||
|
|
||||||
type JSON = std::io::Cursor<Vec<u8>>;
|
type JSON = std::io::Cursor<Vec<u8>>;
|
||||||
|
|
||||||
fn handle_api(_endpoint: &str) -> Result<Response<JSON>, HttpServerError>{
|
fn handle_api(endpoint: &str) -> Result<Response<JSON>, HttpServerError>{
|
||||||
Ok(Response::from_string("Hello World".to_string()))
|
Ok(Response::from_string("Hello World".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use shared::blockchain_core;
|
use shared::core;
|
||||||
use cli_renderer::RenderLayoutKind;
|
use cli_renderer::RenderLayoutKind;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ pub enum CliCommand {
|
|||||||
|
|
||||||
/// Make a Transaction
|
/// Make a Transaction
|
||||||
#[command(name = "tx")]
|
#[command(name = "tx")]
|
||||||
Transaction(blockchain_core::Transaction),
|
Transaction(core::Transaction),
|
||||||
|
|
||||||
/// Start new TcpListner on Addr
|
/// Start new TcpListner on Addr
|
||||||
#[command(name = "listen")]
|
#[command(name = "listen")]
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
use crate::args::*;
|
use crate::args::*;
|
||||||
use crate::network::NodeId;
|
use shared::core::ChainData;
|
||||||
use shared::blockchain_core::ChainData;
|
|
||||||
use vlogger::*;
|
use vlogger::*;
|
||||||
use crate::executor::ExecutorCommand;
|
use crate::executor::ExecutorCommand;
|
||||||
use crate::node::*;
|
use crate::node::*;
|
||||||
@ -12,7 +11,7 @@ pub fn handle_peer_command(cmd: CliPeerCommand) -> NodeCommand {
|
|||||||
match cmd {
|
match cmd {
|
||||||
CliPeerCommand::List => NodeCommand::ListPeers,
|
CliPeerCommand::List => NodeCommand::ListPeers,
|
||||||
CliPeerCommand::Remove { id } => NodeCommand::RemovePeer {
|
CliPeerCommand::Remove { id } => NodeCommand::RemovePeer {
|
||||||
peer_id: NodeId(*id.parse::<uuid::Uuid>().unwrap().as_bytes()),
|
peer_id: id.parse::<uuid::Uuid>().unwrap(),
|
||||||
},
|
},
|
||||||
CliPeerCommand::Connect { addr } => NodeCommand::ConnectTcpPeer(addr),
|
CliPeerCommand::Connect { addr } => NodeCommand::ConnectTcpPeer(addr),
|
||||||
}
|
}
|
||||||
@ -38,10 +37,7 @@ fn handle_seed_command(cmd: CliSeedCommand) -> NodeCommand {
|
|||||||
|
|
||||||
fn handle_ping(cmd: CliPingCommand) -> NodeCommand {
|
fn handle_ping(cmd: CliPingCommand) -> NodeCommand {
|
||||||
match cmd {
|
match cmd {
|
||||||
CliPingCommand::Id { id } => {
|
CliPingCommand::Id { id } => NodeCommand::PingId(id),
|
||||||
let id = NodeId(*id.parse::<uuid::Uuid>().unwrap().as_bytes());
|
|
||||||
NodeCommand::PingId(id)
|
|
||||||
},
|
|
||||||
CliPingCommand::Addr { addr } => NodeCommand::PingAddr(addr),
|
CliPingCommand::Addr { addr } => NodeCommand::PingAddr(addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,7 +53,7 @@ pub fn cli(input: &str) -> ExecutorCommand {
|
|||||||
CliCommand::Peer { peer_cmd } => ExecutorCommand::Node(handle_peer_command(peer_cmd)),
|
CliCommand::Peer { peer_cmd } => ExecutorCommand::Node(handle_peer_command(peer_cmd)),
|
||||||
CliCommand::Block { block_cmd } => ExecutorCommand::Node(handle_block_command(block_cmd)),
|
CliCommand::Block { block_cmd } => ExecutorCommand::Node(handle_block_command(block_cmd)),
|
||||||
CliCommand::Transaction(tx) => {
|
CliCommand::Transaction(tx) => {
|
||||||
ExecutorCommand::Node(NodeCommand::ProcessChainData(ChainData::NodeTransaction(tx)))
|
ExecutorCommand::Node(NodeCommand::ProcessChainData(ChainData::Transaction(tx)))
|
||||||
}
|
}
|
||||||
CliCommand::Award { address, amount } => {
|
CliCommand::Award { address, amount } => {
|
||||||
let mut bytes = [0u8; 20];
|
let mut bytes = [0u8; 20];
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use bincode::{self, config::Configuration};
|
|||||||
use sled::{self, Batch};
|
use sled::{self, Batch};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vlogger::*;
|
use vlogger::*;
|
||||||
use shared::blockchain_core::{self, Address, Block, ChainData, Hasher};
|
use shared::core::{self, Block, ChainData, Hasher, Address};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::error::DatabaseError,
|
db::error::DatabaseError,
|
||||||
@ -12,7 +12,7 @@ use crate::{
|
|||||||
use shared::print_error_chain;
|
use shared::print_error_chain;
|
||||||
|
|
||||||
use crate::PROJECT_PATH;
|
use crate::PROJECT_PATH;
|
||||||
pub static BINCODE_CONFIG: Configuration = bincode::config::standard();
|
static BINCODE_CONFIG: Configuration = bincode::config::standard();
|
||||||
|
|
||||||
const DB_TREE: &str = "blocks";
|
const DB_TREE: &str = "blocks";
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ pub struct ChainDb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ChainDb {
|
impl ChainDb {
|
||||||
pub fn open(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() {
|
||||||
&path.unwrap()
|
&path.unwrap()
|
||||||
} else {
|
} else {
|
||||||
@ -75,28 +75,6 @@ impl ChainDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_chain(&mut self, blocks: &Vec<Block>, tx: &Vec<ChainData>) -> Result<(), DatabaseError> {
|
|
||||||
self.db.clear()?;
|
|
||||||
let mut batch = Batch::default();
|
|
||||||
for b in blocks {
|
|
||||||
self.add_block_batch(&mut batch, &b)?;
|
|
||||||
let block_txs = tx.iter().filter(|t| b.data.contains(&t.hash())).collect::<Vec<&ChainData>>();
|
|
||||||
for b_data in block_txs {
|
|
||||||
self.add_data_batch(&mut batch, b_data, b.head().block_hash())?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.db.apply_batch(batch)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_from(&mut self, blocks: &Vec<Block>, tx: &Vec<ChainData>) -> Result<(), DatabaseError> {
|
|
||||||
let chain_height = self.get_height()?;
|
|
||||||
if blocks.len() > chain_height as usize {
|
|
||||||
return self.replace_chain(blocks, tx);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recover_mempool(&self) -> Result<Vec<ChainData>, DatabaseError> {
|
pub fn recover_mempool(&self) -> Result<Vec<ChainData>, DatabaseError> {
|
||||||
let mem_tree = self.db.scan_prefix(MEMPOOL_PREFIX);
|
let mem_tree = self.db.scan_prefix(MEMPOOL_PREFIX);
|
||||||
let mut mem_vec = vec![];
|
let mut mem_vec = vec![];
|
||||||
@ -171,11 +149,11 @@ impl ChainDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block_by_key(&self, block_hash: &[u8]) -> Result<Option<Arc<blockchain_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);
|
let block_hash = prefix(&BLOCK_PREFIX, block_hash);
|
||||||
log(msg!(DEBUG, "{:?}", hex::encode(&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, _) = bincode::decode_from_slice::<blockchain_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 {
|
||||||
@ -186,7 +164,7 @@ impl ChainDb {
|
|||||||
pub fn get_block_by_height(
|
pub fn get_block_by_height(
|
||||||
&self,
|
&self,
|
||||||
height: u64,
|
height: u64,
|
||||||
) -> Result<Option<Arc<blockchain_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::<[u8; 32], _>(&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)?)
|
||||||
@ -211,49 +189,28 @@ impl ChainDb {
|
|||||||
Ok(Arc::new(chain_data))
|
Ok(Arc::new(chain_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_height(&self) -> Result<u64, DatabaseError> {
|
pub fn get_all_blocks(&self) -> Result<Vec<Arc<core::Block>>, DatabaseError> {
|
||||||
if let Some(bin_height) = self.db.get(prefix(&METADATA_PREFIX, &HEIGHT_KEY))? {
|
|
||||||
let (height, _) = bincode::decode_from_slice(&bin_height, BINCODE_CONFIG)?;
|
|
||||||
Ok(height)
|
|
||||||
} else {
|
|
||||||
Err(DatabaseError::MissingData(format!("Height")))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_all_blocks(&self) -> Result<Vec<Arc<blockchain_core::Block>>, DatabaseError> {
|
|
||||||
self
|
self
|
||||||
.db
|
.db
|
||||||
.scan_prefix(BLOCK_PREFIX)
|
.scan_prefix(BLOCK_PREFIX)
|
||||||
.map(|res| -> Result<Arc<blockchain_core::Block>, DatabaseError> {
|
.map(|res| -> Result<Arc<core::Block>, DatabaseError> {
|
||||||
let (_key, value) = res?;
|
let (_key, value) = res?;
|
||||||
let (block, _size) = bincode::decode_from_slice::<blockchain_core::Block, _>(&value, BINCODE_CONFIG)
|
let (block, _size) = bincode::decode_from_slice::<core::Block, _>(&value, BINCODE_CONFIG)
|
||||||
.map_err(|e| DatabaseError::Decode(e))?;
|
.map_err(|e| DatabaseError::Decode(e))?;
|
||||||
Ok(Arc::new(block))
|
Ok(Arc::new(block))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_data_batch(&self, batch: &mut Batch, data: &blockchain_core::ChainData, block: &[u8]) -> Result<(), DatabaseError> {
|
pub fn add_data(&self, data: &core::ChainData) -> Result<(), DatabaseError> {
|
||||||
let bin_data = bincode::encode_to_vec(data, BINCODE_CONFIG)?;
|
let bin_data = bincode::encode_to_vec(data, BINCODE_CONFIG)?;
|
||||||
let data_hash = prefix(&CHAIN_DATA_PREFIX, &Hasher::hash_chain_data(data));
|
let data_hash = prefix(&CHAIN_DATA_PREFIX, &Hasher::hash_chain_data(data));
|
||||||
batch.insert(data_hash, bin_data);
|
self.db.insert(data_hash, bin_data)?;
|
||||||
let data_to_block_hash = prefix(DATA_TO_BLOCK_PREFIX, block);
|
|
||||||
batch.insert(data_to_block_hash, block);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_data(&self, data: &blockchain_core::ChainData, block: &[u8]) -> Result<(), DatabaseError> {
|
pub fn add_block(&self, block: &core::Block) -> Result<(), DatabaseError> {
|
||||||
let mut batch = Batch::default();
|
let mut db_batch = Batch::default();
|
||||||
let bin_data = bincode::encode_to_vec(data, BINCODE_CONFIG)?;
|
|
||||||
let data_hash = prefix(&CHAIN_DATA_PREFIX, &Hasher::hash_chain_data(data));
|
|
||||||
batch.insert(data_hash, bin_data);
|
|
||||||
let data_to_block_hash = prefix(DATA_TO_BLOCK_PREFIX, block);
|
|
||||||
batch.insert(data_to_block_hash, block);
|
|
||||||
self.db.apply_batch(batch)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_block_batch(&self, db_batch: &mut Batch, block: &blockchain_core::Block) -> Result<(), DatabaseError> {
|
|
||||||
let bin_block = bincode::encode_to_vec(block, BINCODE_CONFIG)?;
|
let bin_block = bincode::encode_to_vec(block, BINCODE_CONFIG)?;
|
||||||
let block_prefix = prefix(&BLOCK_PREFIX, block.head().block_hash());
|
let block_prefix = prefix(&BLOCK_PREFIX, block.head().block_hash());
|
||||||
log(msg!(DEBUG, "{:?}", hex::encode(&block_prefix)));
|
log(msg!(DEBUG, "{:?}", hex::encode(&block_prefix)));
|
||||||
@ -269,33 +226,10 @@ impl ChainDb {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
db_batch.insert(prefix(&METADATA_PREFIX, &TIP_KEY), block.head().block_hash());
|
db_batch.insert(prefix(&METADATA_PREFIX, &TIP_KEY), block.head().block_hash());
|
||||||
|
let bin_head = bincode::encode_to_vec(&block.head().height, BINCODE_CONFIG)?;
|
||||||
db_batch.insert(
|
db_batch.insert(
|
||||||
prefix(&METADATA_PREFIX, &HEIGHT_KEY),
|
prefix(&METADATA_PREFIX, &HEIGHT_KEY),
|
||||||
&block.head().height.to_be_bytes()
|
bin_head
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_block(&self, block: &blockchain_core::Block) -> Result<(), DatabaseError> {
|
|
||||||
let mut db_batch = Batch::default();
|
|
||||||
let bin_block = bincode::encode_to_vec(block, BINCODE_CONFIG)?;
|
|
||||||
let block_prefix = prefix(&BLOCK_PREFIX, block.head().block_hash());
|
|
||||||
|
|
||||||
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(),
|
|
||||||
);
|
|
||||||
for data in block.data() {
|
|
||||||
db_batch.insert(
|
|
||||||
prefix(&DATA_TO_BLOCK_PREFIX, data),
|
|
||||||
block.head().block_hash(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
db_batch.insert(prefix(&METADATA_PREFIX, &TIP_KEY), block.head().block_hash());
|
|
||||||
db_batch.insert(
|
|
||||||
prefix(&METADATA_PREFIX, &HEIGHT_KEY),
|
|
||||||
&block.head().height.to_be_bytes()
|
|
||||||
);
|
);
|
||||||
self.db.apply_batch(db_batch)?;
|
self.db.apply_batch(db_batch)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -6,9 +6,9 @@ pub enum DatabaseError {
|
|||||||
Init(#[from] std::io::Error),
|
Init(#[from] std::io::Error),
|
||||||
#[error("Database operation failed: {0}")]
|
#[error("Database operation failed: {0}")]
|
||||||
Operation(#[from] sled::Error),
|
Operation(#[from] sled::Error),
|
||||||
#[error("Failed to encode data: {0}")]
|
#[error("Failed to serialize data: {0}")]
|
||||||
Encode(#[from] bincode::error::EncodeError),
|
Encode(#[from] bincode::error::EncodeError),
|
||||||
#[error("Failed to decode data: {0}")]
|
#[error("Failed to deserialize data: {0}")]
|
||||||
Decode(#[from] bincode::error::DecodeError),
|
Decode(#[from] bincode::error::DecodeError),
|
||||||
#[error("Chain data not found for hash: {0}")]
|
#[error("Chain data not found for hash: {0}")]
|
||||||
MissingData(String),
|
MissingData(String),
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::log;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|||||||
@ -7,7 +7,6 @@ pub mod node {
|
|||||||
|
|
||||||
pub mod blockchain;
|
pub mod blockchain;
|
||||||
pub use blockchain::*;
|
pub use blockchain::*;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
@ -29,8 +28,6 @@ pub mod db {
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
pub use database::*;
|
pub use database::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
|
|
||||||
pub mod ipfs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod bus {
|
pub mod bus {
|
||||||
@ -66,7 +63,7 @@ pub mod watcher {
|
|||||||
pub use command::*;
|
pub use command::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod network {
|
pub mod protocol {
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub use message::*;
|
pub use message::*;
|
||||||
|
|
||||||
@ -75,29 +72,12 @@ pub mod network {
|
|||||||
|
|
||||||
pub mod connector;
|
pub mod connector;
|
||||||
pub use connector::*;
|
pub use connector::*;
|
||||||
|
|
||||||
pub mod ws_server;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod seeds_constants;
|
pub mod seeds_constants;
|
||||||
|
|
||||||
use cli_renderer::{RenderCommand, RenderTarget};
|
use cli_renderer::{RenderCommand, RenderTarget};
|
||||||
|
|
||||||
pub fn print_error_chain(err: &anyhow::Error) {
|
|
||||||
let mut err_string = String::from(format!("Error: {}\n", err));
|
|
||||||
|
|
||||||
let mut source = err.source();
|
|
||||||
let mut level = 1;
|
|
||||||
|
|
||||||
while let Some(err) = source {
|
|
||||||
err_string.push_str(format!(" {}: {}\n", level, err).as_str());
|
|
||||||
source = err.source();
|
|
||||||
level += 1;
|
|
||||||
}
|
|
||||||
log(err_string)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn log(msg: String) {
|
pub fn log(msg: String) {
|
||||||
crate::bus::publish_watcher_event(watcher::WatcherCommand::Render(RenderCommand::StringToPaneId {
|
crate::bus::publish_watcher_event(watcher::WatcherCommand::Render(RenderCommand::StringToPaneId {
|
||||||
pane: RenderTarget::CliOutput,
|
pane: RenderTarget::CliOutput,
|
||||||
|
|||||||
@ -19,7 +19,6 @@ async fn main() -> Result<(), std::io::Error> {
|
|||||||
.render(args.render)
|
.render(args.render)
|
||||||
.bootstrap(args.bootstrap)
|
.bootstrap(args.bootstrap)
|
||||||
.temporary(args.temporary)
|
.temporary(args.temporary)
|
||||||
.database(args.database)
|
|
||||||
.start()
|
.start()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
segment_size: 1048576
|
|
||||||
use_compression: false
|
|
||||||
version: 0.34
|
|
||||||
l–ø
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
segment_size: 1048576
|
|
||||||
use_compression: false
|
|
||||||
version: 0.34
|
|
||||||
l–ø
|
|
||||||
@ -1,161 +0,0 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
use shared::blockchain_core::validator::{ValidationError, Validator};
|
|
||||||
use tokio::io::AsyncWriteExt;
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
use futures::{SinkExt, StreamExt};
|
|
||||||
use tokio::sync::mpsc::{self, Receiver, Sender};
|
|
||||||
use thiserror::Error;
|
|
||||||
use vlogger::*;
|
|
||||||
use shared::ws_protocol::{ WsClientRequest, WsClientResponse };
|
|
||||||
use watchlet::WalletError;
|
|
||||||
|
|
||||||
use crate::db::BINCODE_CONFIG;
|
|
||||||
use crate::executor::ExecutorCommand;
|
|
||||||
use crate::log;
|
|
||||||
use crate::node::NodeCommand;
|
|
||||||
use crate::seeds_constants::WS_LISTEN_ADDRESS;
|
|
||||||
|
|
||||||
#[derive(Debug, bincode::Encode, bincode::Decode)]
|
|
||||||
pub enum WsCommand {
|
|
||||||
Respond{
|
|
||||||
msg: WsClientResponse,
|
|
||||||
addr: SocketAddr,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum WsServerError {
|
|
||||||
#[error("Socker Error: {0}")]
|
|
||||||
Socket(#[from] std::io::Error),
|
|
||||||
#[error("Tungstenite Error: {0}")]
|
|
||||||
Connection(#[from] tokio_tungstenite::tungstenite::Error),
|
|
||||||
#[error("Encoding Error: {0}")]
|
|
||||||
Encode(#[from] bincode::error::EncodeError),
|
|
||||||
#[error("Decoding Error: {0}")]
|
|
||||||
Decode(#[from] bincode::error::DecodeError),
|
|
||||||
#[error("Crypto Error: {0}")]
|
|
||||||
Crypto(#[from] WalletError),
|
|
||||||
#[error("MPSC Send Error: {0}")]
|
|
||||||
MpscSend(#[from] mpsc::error::SendError<WsClientResponse>),
|
|
||||||
#[error("Validation Error: {0}")]
|
|
||||||
Validation(#[from] ValidationError),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WsServer {
|
|
||||||
rx: Receiver<WsCommand>,
|
|
||||||
tx: Sender<ExecutorCommand>,
|
|
||||||
clients: HashMap<SocketAddr, Sender<WsClientResponse>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_ws_client_request(
|
|
||||||
req: WsClientRequest,
|
|
||||||
_tx: Sender<ExecutorCommand>,
|
|
||||||
) -> Result<(), WsServerError> {
|
|
||||||
match req {
|
|
||||||
WsClientRequest::Ping => {
|
|
||||||
log(msg!(DEBUG, "Received Ping from client"));
|
|
||||||
let _response = bincode::encode_to_vec(WsClientResponse::Pong, BINCODE_CONFIG)?;
|
|
||||||
}
|
|
||||||
WsClientRequest::BroadcastTransaction(sign_tx) => {
|
|
||||||
Validator::verify_signature(&sign_tx)?;
|
|
||||||
let _cmd = ExecutorCommand::Node(NodeCommand::BroadcastTransaction(sign_tx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn ws_connection(
|
|
||||||
stream: TcpStream,
|
|
||||||
mut rx: Receiver<WsClientResponse>,
|
|
||||||
_tx: Sender<ExecutorCommand>,
|
|
||||||
) -> Result<(), WsServerError> {
|
|
||||||
let ws_server = tokio_tungstenite::accept_async(stream).await.unwrap();
|
|
||||||
let (mut write, mut read) = ws_server.split();
|
|
||||||
|
|
||||||
tokio::select! {
|
|
||||||
ws_res = read.next() => {
|
|
||||||
match ws_res {
|
|
||||||
Some(Ok(msg)) => {
|
|
||||||
log(msg!(DEBUG, "msg: {:#?}", msg));
|
|
||||||
if msg.is_text() || msg.is_binary() {
|
|
||||||
let (_message, _size): (WsClientRequest, usize) = bincode::decode_from_slice(msg.to_string().as_bytes(), BINCODE_CONFIG)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ws_cmd = rx.recv() => {
|
|
||||||
match ws_cmd {
|
|
||||||
Some(cmd) => {
|
|
||||||
let bin_cmd = bincode::encode_to_vec(&cmd, BINCODE_CONFIG)?;
|
|
||||||
write.send(bin_cmd.into()).await?;
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WsServer {
|
|
||||||
pub fn new(rx: Receiver<WsCommand>, tx: Sender<ExecutorCommand>) -> Self {
|
|
||||||
Self {
|
|
||||||
rx,
|
|
||||||
tx,
|
|
||||||
clients: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run(&mut self) -> Result<(), WsServerError> {
|
|
||||||
let listener = tokio::net::TcpListener::bind(*WS_LISTEN_ADDRESS).await?;
|
|
||||||
let mut tasks = Vec::new();
|
|
||||||
|
|
||||||
log(msg!(DEBUG, "Starting WsServer at {}", *WS_LISTEN_ADDRESS));
|
|
||||||
|
|
||||||
loop {
|
|
||||||
tokio::select! {
|
|
||||||
ws_cmd = self.rx.recv() => {
|
|
||||||
match ws_cmd {
|
|
||||||
Some(cmd) => {
|
|
||||||
match cmd {
|
|
||||||
WsCommand::Respond { msg, addr } => {
|
|
||||||
if let Some(sender) = self.clients.get(&addr) {
|
|
||||||
sender.send(msg).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
con_res = listener.accept() => {
|
|
||||||
match con_res {
|
|
||||||
Ok((mut stream, addr)) => {
|
|
||||||
log(msg!(DEBUG, "Received Connection Attempt from {}", addr));
|
|
||||||
if self.clients.len() < 5 {
|
|
||||||
let (tx, rx) = mpsc::channel::<WsClientResponse>(100);
|
|
||||||
self.clients.insert(addr, tx);
|
|
||||||
let tx = self.tx.clone();
|
|
||||||
let task_handle = tokio::spawn(async move {
|
|
||||||
if let Err(e) = ws_connection(stream, rx, tx).await {
|
|
||||||
log(msg!(ERROR, "{e}"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tasks.push(task_handle);
|
|
||||||
} else {
|
|
||||||
stream.shutdown().await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log(msg!(ERROR, "{e}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +1,19 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::UNIX_EPOCH;
|
use std::time::UNIX_EPOCH;
|
||||||
|
|
||||||
use shared::blockchain_core::validator::ValidationError;
|
use shared::core::Address;
|
||||||
use shared::blockchain_core::{self, Address};
|
|
||||||
use shared::print_error_chain;
|
use shared::print_error_chain;
|
||||||
use thiserror::*;
|
use thiserror::*;
|
||||||
|
|
||||||
use vlogger::*;
|
use vlogger::*;
|
||||||
use shared::blockchain_core::Block;
|
use shared::core;
|
||||||
use shared::blockchain_core::ChainData;
|
use shared::core::ChainData;
|
||||||
use crate::db;
|
use crate::db;
|
||||||
use crate::db::DatabaseError;
|
use crate::db::DatabaseError;
|
||||||
use crate::db::database;
|
use crate::db::database;
|
||||||
use crate::db::BINCODE_CONFIG;
|
|
||||||
use crate::log;
|
use crate::log;
|
||||||
|
|
||||||
use shared::blockchain_core::Hasher;
|
use shared::core::Hasher;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Blockchain {
|
pub struct Blockchain {
|
||||||
@ -24,33 +22,40 @@ pub struct Blockchain {
|
|||||||
db: database::ChainDb,
|
db: database::ChainDb,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, bincode::Encode, bincode::Decode)]
|
|
||||||
pub struct ChainBootStrap {
|
|
||||||
blocks: Vec<Block>,
|
|
||||||
mempool: Vec<ChainData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum BlockchainError {
|
pub enum BlockchainError {
|
||||||
#[error("Failed to serialize data: {0}")]
|
|
||||||
Encode(#[from] bincode::error::EncodeError),
|
|
||||||
#[error("Failed to deserialize data: {0}")]
|
|
||||||
Decode(#[from] bincode::error::DecodeError),
|
|
||||||
#[error("Database operation failed")]
|
#[error("Database operation failed")]
|
||||||
Database(#[from] DatabaseError),
|
Database(#[from] DatabaseError),
|
||||||
|
|
||||||
#[error("invalid account creation")]
|
#[error("invalid account creation")]
|
||||||
InvalidAccountCreation,
|
InvalidAccountCreation,
|
||||||
|
|
||||||
#[error("Transactional error")]
|
#[error("Transactional error")]
|
||||||
Transaction(#[from] shared::blockchain_core::TransactionError),
|
Transaction(#[from] shared::core::TransactionError),
|
||||||
|
|
||||||
#[error("Validation Error")]
|
#[error("Validation Error")]
|
||||||
Validation(#[from] ValidationError),
|
Validation(#[from] ValidationError),
|
||||||
|
|
||||||
#[error("Insufficient fonds on address {0}")]
|
#[error("Insufficient fonds on address {0}")]
|
||||||
InsufficientFunds(String),
|
InsufficientFunds(String),
|
||||||
|
|
||||||
|
#[error("Block Creation Error")]
|
||||||
|
BlockCreation,
|
||||||
}
|
}
|
||||||
|
|
||||||
const BLOCKCHAIN_ID: &str = "watch-chain";
|
const BLOCKCHAIN_ID: &str = "watch-chain";
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum ValidationError {
|
||||||
|
#[error("Invalid Block Hash Detected at height {0}")]
|
||||||
|
InvalidBlockHash(u64),
|
||||||
|
#[error("Previous Block Hash doesn't match at height {0}")]
|
||||||
|
InvalidPreviousBlockHash(u64),
|
||||||
|
#[error("Invalid Block JSON: {0}")]
|
||||||
|
InvalidBlockJson(#[from] serde_json::Error),
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl Blockchain {
|
impl Blockchain {
|
||||||
fn hash_transaction_pool(&self) -> Vec<[u8; 32]> {
|
fn hash_transaction_pool(&self) -> Vec<[u8; 32]> {
|
||||||
@ -71,8 +76,9 @@ impl Blockchain {
|
|||||||
Ok(self.db.set_balance(&address, new_balance)?)
|
Ok(self.db.set_balance(&address, new_balance)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_block(&mut self) -> Result<Arc<blockchain_core::Block>, BlockchainError> {
|
pub fn create_block(&mut self) -> Result<Arc<core::Block>, BlockchainError> {
|
||||||
let blocks = self.db.get_all_blocks()?;
|
match self.blocks() {
|
||||||
|
Ok(blocks) => {
|
||||||
let previous_hash = if blocks.len() > 0 {
|
let previous_hash = if blocks.len() > 0 {
|
||||||
<[u8; 32]>::try_from(blocks.last().unwrap().head().block_hash()).unwrap()
|
<[u8; 32]>::try_from(blocks.last().unwrap().head().block_hash()).unwrap()
|
||||||
} else {
|
} else {
|
||||||
@ -87,7 +93,7 @@ impl Blockchain {
|
|||||||
.as_secs();
|
.as_secs();
|
||||||
let nonce = 0;
|
let nonce = 0;
|
||||||
|
|
||||||
let mut new_head = blockchain_core::BlockHeader {
|
let mut new_head = core::BlockHeader {
|
||||||
previous_hash: <[u8; 32]>::from(previous_hash),
|
previous_hash: <[u8; 32]>::from(previous_hash),
|
||||||
merkle_root,
|
merkle_root,
|
||||||
timestamp,
|
timestamp,
|
||||||
@ -104,12 +110,15 @@ impl Blockchain {
|
|||||||
|
|
||||||
new_head.block_hash = block_hash;
|
new_head.block_hash = block_hash;
|
||||||
|
|
||||||
let new_block = Arc::new(blockchain_core::Block::new(new_head, tx_hashes));
|
let new_block = Arc::new(core::Block::new(new_head, tx_hashes));
|
||||||
self.add_block(new_block.clone())?;
|
self.add_block(new_block.clone())?;
|
||||||
Ok(new_block)
|
Ok(new_block)
|
||||||
}
|
}
|
||||||
|
Err(_) => Err(BlockchainError::BlockCreation),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn apply_transaction(&mut self, tx: &blockchain_core::Transaction) -> Result<(), BlockchainError> {
|
fn apply_transaction(&mut self, tx: &core::Transaction) -> Result<(), BlockchainError> {
|
||||||
tx.validate()?;
|
tx.validate()?;
|
||||||
let from = tx.from();
|
let from = tx.from();
|
||||||
let to = tx.to();
|
let to = tx.to();
|
||||||
@ -137,10 +146,6 @@ impl Blockchain {
|
|||||||
pub fn apply_chain_data(&mut self, data: ChainData) -> Result<(), BlockchainError> {
|
pub fn apply_chain_data(&mut self, data: ChainData) -> Result<(), BlockchainError> {
|
||||||
match &data {
|
match &data {
|
||||||
ChainData::Transaction(tx) => {
|
ChainData::Transaction(tx) => {
|
||||||
self.apply_transaction(tx.data())?;
|
|
||||||
self.mempool.push(data);
|
|
||||||
}
|
|
||||||
ChainData::NodeTransaction(tx) => {
|
|
||||||
self.apply_transaction(tx)?;
|
self.apply_transaction(tx)?;
|
||||||
self.mempool.push(data);
|
self.mempool.push(data);
|
||||||
}
|
}
|
||||||
@ -159,16 +164,16 @@ impl Blockchain {
|
|||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blocks(&self) -> Result<Vec<std::sync::Arc<blockchain_core::Block>>, BlockchainError> {
|
pub fn blocks(&self) -> Result<Vec<std::sync::Arc<core::Block>>, BlockchainError> {
|
||||||
Ok(self.db.get_all_blocks()?)
|
Ok(self.db.get_all_blocks()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_block(&self, block: &blockchain_core::Block) -> Result<(), BlockchainError> {
|
fn insert_block(&self, block: &core::Block) -> Result<(), BlockchainError> {
|
||||||
self.db.add_block(block)?;
|
self.db.add_block(block)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_block(&mut self, block: Arc<blockchain_core::Block>) -> Result<(), BlockchainError> {
|
pub fn add_block(&mut self, block: Arc<core::Block>) -> Result<(), BlockchainError> {
|
||||||
match self.validate_block(&block) {
|
match self.validate_block(&block) {
|
||||||
Ok(()) => Ok(self.insert_block(&block)?),
|
Ok(()) => Ok(self.insert_block(&block)?),
|
||||||
Err(e) => Err(BlockchainError::Validation(e)),
|
Err(e) => Err(BlockchainError::Validation(e)),
|
||||||
@ -190,7 +195,7 @@ impl Blockchain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_block(&self, block: &blockchain_core::Block) -> Result<(), ValidationError> {
|
fn validate_block(&self, block: &core::Block) -> Result<(), ValidationError> {
|
||||||
let head = block.head();
|
let head = block.head();
|
||||||
let hash = Hasher::calculate_block_hash(block.head());
|
let hash = Hasher::calculate_block_hash(block.head());
|
||||||
if hash != head.block_hash() {
|
if hash != head.block_hash() {
|
||||||
@ -233,26 +238,14 @@ impl Blockchain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bootstrap(&self) -> Result<Vec<u8>, BlockchainError> {
|
|
||||||
let blocks = self.blocks()?;
|
|
||||||
let mempool = self.mempool.clone();
|
|
||||||
|
|
||||||
let bs = ChainBootStrap {
|
|
||||||
blocks: blocks.iter().map(|b| (**b).clone()).collect::<Vec<Block>>(),
|
|
||||||
mempool
|
|
||||||
};
|
|
||||||
let bin_bs = bincode::encode_to_vec(&bs, BINCODE_CONFIG)?;
|
|
||||||
Ok(bin_bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
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?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(path: Option<String>, db_temp: bool) -> Result<Blockchain, BlockchainError> {
|
pub fn build(path: Option<String>, db_temp: bool) -> Result<Blockchain, BlockchainError> {
|
||||||
let db = db::ChainDb::open(path, db_temp).or_else(|e| Err(BlockchainError::Database(e)))?;
|
let db = db::ChainDb::new(path, db_temp).or_else(|e| Err(BlockchainError::Database(e)))?;
|
||||||
let mempool = db.recover_mempool()?;
|
let mempool = db.recover_mempool()?;
|
||||||
|
|
||||||
let chain = Blockchain {
|
let chain = Blockchain {
|
||||||
@ -265,15 +258,4 @@ impl Blockchain {
|
|||||||
.or_else(|e| return Err(BlockchainError::Validation(e)))?;
|
.or_else(|e| return Err(BlockchainError::Validation(e)))?;
|
||||||
Ok(chain)
|
Ok(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(&mut self, bin_data: Vec<u8>) -> Result<(), BlockchainError> {
|
|
||||||
let (data, _) = bincode::decode_from_slice::<ChainBootStrap, _>(&bin_data, BINCODE_CONFIG)?;
|
|
||||||
self.db.build_from(&data.blocks, &data.mempool)?;
|
|
||||||
|
|
||||||
self.mempool = data.mempool;
|
|
||||||
self
|
|
||||||
.validate_chain()
|
|
||||||
.or_else(|e| return Err(BlockchainError::Validation(e)))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Clone, Error)]
|
||||||
pub enum NetworkError {
|
pub enum NetworkError {
|
||||||
#[error("Implement NetworkError Enum: ({})", file!())]
|
#[error("Implement NetworkError Enum: ({})", file!())]
|
||||||
TODO,
|
TODO,
|
||||||
#[error("Decode Error: {0}")]
|
|
||||||
Decode(#[from] bincode::error::DecodeError),
|
|
||||||
#[error("Encode Error: {0}")]
|
|
||||||
Encode(#[from] bincode::error::EncodeError),
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
use crate::bus::{publish_system_event, publish_watcher_event, subscribe_system_event, SystemEvent};
|
use crate::bus::{publish_system_event, publish_watcher_event, subscribe_system_event, SystemEvent};
|
||||||
use shared::blockchain_core::{self, ChainData, SignedTransaction, validator::ValidationError};
|
use shared::core::{self, ChainData};
|
||||||
use crate::print_error_chain;
|
use shared::print_error_chain;
|
||||||
use crate::executor::ExecutorCommand;
|
use crate::executor::ExecutorCommand;
|
||||||
use crate::log;
|
use crate::log;
|
||||||
use crate::network::{NodeId, ProtocolMessage};
|
use crate::protocol::ProtocolMessage;
|
||||||
use crate::network::{Connector, ConnectorCommand};
|
use crate::protocol::{Connector, ConnectorCommand};
|
||||||
use crate::seeds_constants::SEED_NODES;
|
use crate::seeds_constants::SEED_NODES;
|
||||||
use crate::watcher::{WatcherCommand, WatcherMode};
|
use crate::watcher::{WatcherCommand, WatcherMode};
|
||||||
use crate::network::ws_server::{WsCommand, WsServer};
|
use super::{ Blockchain, BlockchainError, ValidationError };
|
||||||
use super::{ Blockchain, BlockchainError };
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
@ -22,14 +21,14 @@ use vlogger::*;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TcpPeer {
|
pub struct TcpPeer {
|
||||||
pub id: NodeId,
|
pub id: Uuid,
|
||||||
pub addr: SocketAddr,
|
pub addr: SocketAddr,
|
||||||
pub sender: tokio::sync::mpsc::Sender<ProtocolMessage>,
|
pub sender: tokio::sync::mpsc::Sender<ProtocolMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpPeer {
|
impl TcpPeer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
id: NodeId,
|
id: Uuid,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
sender: tokio::sync::mpsc::Sender<ProtocolMessage>,
|
sender: tokio::sync::mpsc::Sender<ProtocolMessage>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -40,9 +39,9 @@ impl TcpPeer {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Node {
|
pub struct Node {
|
||||||
pub tcp_connector: Option<mpsc::Sender<ConnectorCommand>>,
|
pub tcp_connector: Option<mpsc::Sender<ConnectorCommand>>,
|
||||||
pub id: NodeId,
|
pub id: Uuid,
|
||||||
pub addr: Option<SocketAddr>,
|
pub addr: Option<SocketAddr>,
|
||||||
pub tcp_peers: HashMap<NodeId, TcpPeer>,
|
pub tcp_peers: HashMap<Uuid, TcpPeer>,
|
||||||
chain: Blockchain,
|
chain: Blockchain,
|
||||||
listner_handle: Option<tokio::task::JoinHandle<()>>,
|
listner_handle: Option<tokio::task::JoinHandle<()>>,
|
||||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||||
@ -58,19 +57,18 @@ pub enum NodeError {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum NodeCommand {
|
pub enum NodeCommand {
|
||||||
BroadcastTransaction(SignedTransaction),
|
|
||||||
AddPeer(TcpPeer),
|
AddPeer(TcpPeer),
|
||||||
RemovePeer {
|
RemovePeer {
|
||||||
peer_id: NodeId,
|
peer_id: Uuid,
|
||||||
},
|
},
|
||||||
ProcessMessage {
|
ProcessMessage {
|
||||||
peer_id: NodeId,
|
peer_id: Uuid,
|
||||||
message: ProtocolMessage,
|
message: ProtocolMessage,
|
||||||
},
|
},
|
||||||
ProcessChainData(ChainData),
|
ProcessChainData(ChainData),
|
||||||
StartListner(SocketAddr),
|
StartListner(SocketAddr),
|
||||||
PingAddr(String),
|
PingAddr(String),
|
||||||
PingId(NodeId),
|
PingId(String),
|
||||||
CreateBlock,
|
CreateBlock,
|
||||||
DisplayBlockInteractive,
|
DisplayBlockInteractive,
|
||||||
DisplayBlockByKey(String),
|
DisplayBlockByKey(String),
|
||||||
@ -85,7 +83,6 @@ pub enum NodeCommand {
|
|||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl Node {
|
impl Node {
|
||||||
pub fn peer_addresses(&self) -> Vec<SocketAddr> {
|
pub fn peer_addresses(&self) -> Vec<SocketAddr> {
|
||||||
let mut addr: Vec<SocketAddr> = self
|
let mut addr: Vec<SocketAddr> = self
|
||||||
@ -111,18 +108,18 @@ impl Node {
|
|||||||
log(msg!(DEBUG, "Node Id: {}", self.id))
|
log(msg!(DEBUG, "Node Id: {}", self.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_tcp_peer(&mut self, peer_id: NodeId) {
|
async fn remove_tcp_peer(&mut self, peer_id: Uuid) {
|
||||||
log(msg!(DEBUG, "Removing Peer {peer_id}"));
|
log(msg!(DEBUG, "Removing Peer {peer_id}"));
|
||||||
self.tcp_peers.remove_entry(&peer_id);
|
self.tcp_peers.remove_entry(&peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_tcp_peer(&mut self, peer: TcpPeer) {
|
async fn add_tcp_peer(&mut self, peer: TcpPeer) {
|
||||||
log(msg!(DEBUG, "Added Peer from address: {}", peer.addr));
|
log(msg!(DEBUG, "Added Peer from address: {}", peer.addr));
|
||||||
self.tcp_peers.insert(peer.id.clone(), peer);
|
self.tcp_peers.insert(peer.id, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new_with_id(
|
pub async fn new_with_id(
|
||||||
id: NodeId,
|
id: uuid::Uuid,
|
||||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||||
addr: Option<SocketAddr>,
|
addr: Option<SocketAddr>,
|
||||||
chain: Blockchain,
|
chain: Blockchain,
|
||||||
@ -148,7 +145,7 @@ impl Node {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let (tx, rx) = mpsc::channel::<NodeCommand>(100);
|
let (tx, rx) = mpsc::channel::<NodeCommand>(100);
|
||||||
Self {
|
Self {
|
||||||
id: NodeId(*Uuid::new_v4().as_bytes()),
|
id: Uuid::new_v4(),
|
||||||
tcp_peers: HashMap::new(),
|
tcp_peers: HashMap::new(),
|
||||||
addr,
|
addr,
|
||||||
exec_tx,
|
exec_tx,
|
||||||
@ -170,23 +167,43 @@ impl Node {
|
|||||||
let _ = self.chain.shutdown().await;
|
let _ = self.chain.shutdown().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_blocks(&self) -> Result<Vec<Arc<blockchain_core::Block>>, NodeError> {
|
fn get_blocks(&self) -> Result<Vec<Arc<core::Block>>, NodeError> {
|
||||||
Ok(self.chain.blocks()?)
|
Ok(self.chain.blocks()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn process_message(&mut self, peer_id: NodeId, message: ProtocolMessage) -> Result<(), NodeError> {
|
pub async fn process_message(&mut self, peer_id: uuid::Uuid, message: ProtocolMessage) {
|
||||||
match message {
|
match message {
|
||||||
ProtocolMessage::BootstrapRequest { .. } => {
|
ProtocolMessage::BootstrapRequest { .. } => {
|
||||||
log(msg!(DEBUG, "Received BootstrapRequest from {peer_id}"));
|
log(msg!(DEBUG, "Received BootstrapRequest from {peer_id}"));
|
||||||
let peer = &self.tcp_peers[&peer_id];
|
let peer = &self.tcp_peers[&peer_id];
|
||||||
let blocks = self.chain.bootstrap()?;
|
let resp = ProtocolMessage::BootstrapResponse {
|
||||||
let resp = ProtocolMessage::BootstrapResponse { blocks };
|
blocks: {
|
||||||
|
if let Ok(blocks) = self.get_blocks() {
|
||||||
|
serde_json::to_string(
|
||||||
|
&blocks
|
||||||
|
.iter()
|
||||||
|
.map(|f| (**f).clone())
|
||||||
|
.collect::<Vec<core::Block>>(),
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
log(msg!(
|
||||||
|
ERROR,
|
||||||
|
"Failed to serde Chain for BootstrapResponse: {e}"
|
||||||
|
));
|
||||||
|
e
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
peer.sender.send(resp).await.unwrap();
|
peer.sender.send(resp).await.unwrap();
|
||||||
log(msg!(DEBUG, "Send BootstrapResponse to {peer_id}"));
|
log(msg!(DEBUG, "Send BootstrapResponse to {peer_id}"));
|
||||||
}
|
}
|
||||||
ProtocolMessage::BootstrapResponse { blocks } => {
|
ProtocolMessage::BootstrapResponse { blocks } => {
|
||||||
log(msg!(DEBUG, "Received BootstrapResponse from seed"));
|
log(msg!(DEBUG, "Received BootstrapResponse from seed"));
|
||||||
self.chain.build(blocks).unwrap();
|
self.chain = Blockchain::build(blocks, true).unwrap();
|
||||||
}
|
}
|
||||||
ProtocolMessage::Pong { peer_id } => {
|
ProtocolMessage::Pong { peer_id } => {
|
||||||
log(msg!(DEBUG, "Received Pong from {peer_id}"));
|
log(msg!(DEBUG, "Received Pong from {peer_id}"));
|
||||||
@ -227,7 +244,6 @@ impl Node {
|
|||||||
log(msg!(DEBUG, "TODO: implement this message type"));
|
log(msg!(DEBUG, "TODO: implement this message type"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_message_to_peer_addr(&self, addr: SocketAddr, msg: ProtocolMessage) {
|
pub async fn send_message_to_peer_addr(&self, addr: SocketAddr, msg: ProtocolMessage) {
|
||||||
@ -244,7 +260,7 @@ impl Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_message_to_peer_id(&self, id: NodeId, msg: ProtocolMessage) {
|
pub async fn send_message_to_peer_id(&self, id: Uuid, msg: ProtocolMessage) {
|
||||||
if let Some(peer) = self.tcp_peers.get(&id) {
|
if let Some(peer) = self.tcp_peers.get(&id) {
|
||||||
if let Err(e) = peer.sender.send(msg).await {
|
if let Err(e) = peer.sender.send(msg).await {
|
||||||
log(msg!(ERROR, "Error Sending message to peer: {e}"));
|
log(msg!(ERROR, "Error Sending message to peer: {e}"));
|
||||||
@ -269,7 +285,7 @@ impl Node {
|
|||||||
log(msg!(DEBUG, "Bootstrapping"));
|
log(msg!(DEBUG, "Bootstrapping"));
|
||||||
|
|
||||||
let message = ProtocolMessage::BootstrapRequest {
|
let message = ProtocolMessage::BootstrapRequest {
|
||||||
peer_id: self.id.clone(),
|
peer_id: self.id,
|
||||||
version: "".to_string(),
|
version: "".to_string(),
|
||||||
};
|
};
|
||||||
self.send_message_to_seed(message).await;
|
self.send_message_to_seed(message).await;
|
||||||
@ -280,7 +296,7 @@ impl Node {
|
|||||||
async fn broadcast_network_data(&self, data: ChainData) {
|
async fn broadcast_network_data(&self, data: ChainData) {
|
||||||
for (id, peer) in &self.tcp_peers {
|
for (id, peer) in &self.tcp_peers {
|
||||||
let message = ProtocolMessage::ChainData {
|
let message = ProtocolMessage::ChainData {
|
||||||
peer_id: self.id.clone(),
|
peer_id: self.id,
|
||||||
data: data.clone(),
|
data: data.clone(),
|
||||||
};
|
};
|
||||||
peer.sender.send(message).await.unwrap();
|
peer.sender.send(message).await.unwrap();
|
||||||
@ -288,10 +304,10 @@ impl Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn broadcast_block(&self, block: &blockchain_core::Block) {
|
async fn broadcast_block(&self, block: &core::Block) {
|
||||||
for (id, peer) in &self.tcp_peers {
|
for (id, peer) in &self.tcp_peers {
|
||||||
let message = ProtocolMessage::Block {
|
let message = ProtocolMessage::Block {
|
||||||
peer_id: self.id.clone(),
|
peer_id: self.id,
|
||||||
height: block.head().height as u64,
|
height: block.head().height as u64,
|
||||||
block: block.clone(),
|
block: block.clone(),
|
||||||
};
|
};
|
||||||
@ -325,7 +341,7 @@ impl Node {
|
|||||||
self.tcp_connector = Some(con_tx);
|
self.tcp_connector = Some(con_tx);
|
||||||
|
|
||||||
self.listner_handle = Some(tokio::spawn({
|
self.listner_handle = Some(tokio::spawn({
|
||||||
let mut connector = Connector::new(self.id.clone(), addr, self.exec_tx(), con_rx);
|
let mut connector = Connector::new(self.id, addr, self.exec_tx(), con_rx);
|
||||||
log(msg!(DEBUG, "Connector Build"));
|
log(msg!(DEBUG, "Connector Build"));
|
||||||
async move { connector.start().await }
|
async move { connector.start().await }
|
||||||
}));
|
}));
|
||||||
@ -344,9 +360,6 @@ impl Node {
|
|||||||
log(msg!(DEBUG, "Received NodeCommand::BootStrap"));
|
log(msg!(DEBUG, "Received NodeCommand::BootStrap"));
|
||||||
let _ = self.bootstrap().await;
|
let _ = self.bootstrap().await;
|
||||||
}
|
}
|
||||||
NodeCommand::BroadcastTransaction(sign_tx) => {
|
|
||||||
self.broadcast_network_data(ChainData::Transaction(sign_tx)).await;
|
|
||||||
}
|
|
||||||
NodeCommand::StartListner(addr) => {
|
NodeCommand::StartListner(addr) => {
|
||||||
self.start_connection_listner(addr).await;
|
self.start_connection_listner(addr).await;
|
||||||
}
|
}
|
||||||
@ -364,15 +377,19 @@ impl Node {
|
|||||||
}
|
}
|
||||||
NodeCommand::PingAddr(addr) => {
|
NodeCommand::PingAddr(addr) => {
|
||||||
if let Ok(addr_sock) = addr.parse::<SocketAddr>() {
|
if let Ok(addr_sock) = addr.parse::<SocketAddr>() {
|
||||||
let mes = ProtocolMessage::Ping { peer_id: self.id.clone() };
|
let mes = ProtocolMessage::Ping { peer_id: self.id };
|
||||||
self.send_message_to_peer_addr(addr_sock, mes).await;
|
self.send_message_to_peer_addr(addr_sock, mes).await;
|
||||||
} else {
|
} else {
|
||||||
log(msg!(ERROR, "Failed to Parse to sock_addr: {addr}"));
|
log(msg!(ERROR, "Failed to Parse to sock_addr: {addr}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NodeCommand::PingId(id) => {
|
NodeCommand::PingId(id) => {
|
||||||
let mes = ProtocolMessage::Ping { peer_id: self.id.clone() };
|
if let Ok(id) = id.parse::<Uuid>() {
|
||||||
|
let mes = ProtocolMessage::Ping { peer_id: self.id };
|
||||||
self.send_message_to_peer_id(id, mes).await;
|
self.send_message_to_peer_id(id, mes).await;
|
||||||
|
} else {
|
||||||
|
log(msg!(ERROR, "Failed to Parse to sock_addr: {id}"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
NodeCommand::AddPeer(peer) => {
|
NodeCommand::AddPeer(peer) => {
|
||||||
self.add_tcp_peer(peer).await;
|
self.add_tcp_peer(peer).await;
|
||||||
@ -382,7 +399,7 @@ impl Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NodeCommand::ProcessMessage { peer_id, message } => {
|
NodeCommand::ProcessMessage { peer_id, message } => {
|
||||||
self.process_message(peer_id, message).await.unwrap();
|
self.process_message(peer_id, message).await;
|
||||||
}
|
}
|
||||||
NodeCommand::AwardCurrency { address, amount } => {
|
NodeCommand::AwardCurrency { address, amount } => {
|
||||||
if let Err(e) = self.chain.award_currency(address, amount) {
|
if let Err(e) = self.chain.award_currency(address, amount) {
|
||||||
@ -397,8 +414,7 @@ impl Node {
|
|||||||
}
|
}
|
||||||
NodeCommand::CreateBlock => {
|
NodeCommand::CreateBlock => {
|
||||||
log(msg!(DEBUG, "Received CreateBlock Command"));
|
log(msg!(DEBUG, "Received CreateBlock Command"));
|
||||||
match self.chain.create_block() {
|
if let Ok(block) = self.chain.create_block() {
|
||||||
Ok(block) => {
|
|
||||||
log(msg!(
|
log(msg!(
|
||||||
INFO,
|
INFO,
|
||||||
"Created Block with hash {}",
|
"Created Block with hash {}",
|
||||||
@ -406,8 +422,6 @@ impl Node {
|
|||||||
));
|
));
|
||||||
self.broadcast_block(&block).await;
|
self.broadcast_block(&block).await;
|
||||||
}
|
}
|
||||||
Err(e) => print_error_chain(&e.into()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
NodeCommand::DisplayBlockInteractive => {
|
NodeCommand::DisplayBlockInteractive => {
|
||||||
let blocks = match self.chain.list_blocks() {
|
let blocks = match self.chain.list_blocks() {
|
||||||
@ -463,20 +477,10 @@ impl Node {
|
|||||||
.await;
|
.await;
|
||||||
};
|
};
|
||||||
|
|
||||||
let http_handle = tokio::spawn(async move {
|
let handle = tokio::spawn(async move {
|
||||||
let _ = crate::api::server::start_server().await;
|
let _ = crate::api::server::start_server().await;
|
||||||
});
|
});
|
||||||
|
|
||||||
let (_tx, rx) = mpsc::channel::<WsCommand>(100);
|
|
||||||
|
|
||||||
let mut ws_server = WsServer::new(rx, self.exec_tx());
|
|
||||||
|
|
||||||
let _ws_handle = tokio::spawn(async move {
|
|
||||||
if let Err(e) = ws_server.run().await {
|
|
||||||
print_error_chain(&e.into());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut system_rx = subscribe_system_event();
|
let mut system_rx = subscribe_system_event();
|
||||||
publish_system_event(SystemEvent::NodeStarted);
|
publish_system_event(SystemEvent::NodeStarted);
|
||||||
|
|
||||||
@ -502,7 +506,7 @@ impl Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
http_handle.abort_handle().abort();
|
handle.abort_handle().abort();
|
||||||
self.shutdown().await;
|
self.shutdown().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
use crate::executor::ExecutorCommand;
|
use crate::executor::ExecutorCommand;
|
||||||
use crate::log;
|
use crate::log;
|
||||||
use crate::network::NodeId;
|
|
||||||
use crate::node::node;
|
use crate::node::node;
|
||||||
use super::ProtocolMessage;
|
use crate::protocol::ProtocolMessage;
|
||||||
use tokio::net;
|
use tokio::net;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
@ -13,8 +12,8 @@ use vlogger::*;
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
node_id: NodeId,
|
node_id: uuid::Uuid,
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
stream: net::TcpStream,
|
stream: net::TcpStream,
|
||||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||||
rx: mpsc::Receiver<ProtocolMessage>,
|
rx: mpsc::Receiver<ProtocolMessage>,
|
||||||
@ -22,8 +21,8 @@ pub struct Connection {
|
|||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
node_id: NodeId,
|
node_id: uuid::Uuid,
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
stream: net::TcpStream,
|
stream: net::TcpStream,
|
||||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||||
rx: mpsc::Receiver<ProtocolMessage>,
|
rx: mpsc::Receiver<ProtocolMessage>,
|
||||||
@ -47,7 +46,7 @@ impl Connection {
|
|||||||
match response_result {
|
match response_result {
|
||||||
Some(response) => {
|
Some(response) => {
|
||||||
if let Err(e) = Connector::send_message(&mut self.stream, &response).await {
|
if let Err(e) = Connector::send_message(&mut self.stream, &response).await {
|
||||||
log(msg!(ERROR, "Failed to send response to {}: {}", self.peer_id.clone(), e));
|
log(msg!(ERROR, "Failed to send response to {}: {}", self.peer_id, e));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -64,7 +63,7 @@ impl Connection {
|
|||||||
log(msg!(DEBUG, "Received Message from {}", self.peer_id));
|
log(msg!(DEBUG, "Received Message from {}", self.peer_id));
|
||||||
|
|
||||||
let command = ExecutorCommand::Node(node::NodeCommand::ProcessMessage {
|
let command = ExecutorCommand::Node(node::NodeCommand::ProcessMessage {
|
||||||
peer_id: self.peer_id.clone(),
|
peer_id: self.peer_id,
|
||||||
message: message.clone()
|
message: message.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -7,15 +7,13 @@ use vlogger::*;
|
|||||||
use shared::print_error_chain;
|
use shared::print_error_chain;
|
||||||
use thiserror::*;
|
use thiserror::*;
|
||||||
|
|
||||||
use crate::db::BINCODE_CONFIG;
|
|
||||||
use crate::log;
|
use crate::log;
|
||||||
use crate::network::NodeId;
|
|
||||||
use super::Connection;
|
use super::Connection;
|
||||||
use crate::bus::*;
|
use crate::bus::*;
|
||||||
use crate::executor::ExecutorCommand;
|
use crate::executor::ExecutorCommand;
|
||||||
use crate::node::node;
|
use crate::node::node;
|
||||||
use crate::node::{NetworkError, error};
|
use crate::node::{NetworkError, error};
|
||||||
use super::ProtocolMessage;
|
use crate::protocol::ProtocolMessage;
|
||||||
|
|
||||||
pub enum ConnectorCommand {
|
pub enum ConnectorCommand {
|
||||||
ConnectToTcpPeer(SocketAddr),
|
ConnectToTcpPeer(SocketAddr),
|
||||||
@ -24,7 +22,7 @@ pub enum ConnectorCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Connector {
|
pub struct Connector {
|
||||||
node_id: NodeId,
|
node_id: uuid::Uuid,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||||
rx: mpsc::Receiver<ConnectorCommand>,
|
rx: mpsc::Receiver<ConnectorCommand>,
|
||||||
@ -41,7 +39,7 @@ const MAX_LISTNER_TRIES: usize = 5;
|
|||||||
|
|
||||||
impl Connector {
|
impl Connector {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
node_id: NodeId,
|
node_id: uuid::Uuid,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
exec_tx: mpsc::Sender<ExecutorCommand>,
|
exec_tx: mpsc::Sender<ExecutorCommand>,
|
||||||
rx: mpsc::Receiver<ConnectorCommand>,
|
rx: mpsc::Receiver<ConnectorCommand>,
|
||||||
@ -148,7 +146,7 @@ impl Connector {
|
|||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
) {
|
) {
|
||||||
let handshake = ProtocolMessage::Handshake {
|
let handshake = ProtocolMessage::Handshake {
|
||||||
peer_id: self.node_id.clone(),
|
peer_id: self.node_id,
|
||||||
version: "".to_string(),
|
version: "".to_string(),
|
||||||
};
|
};
|
||||||
match Connector::send_message(&mut stream, &handshake).await {
|
match Connector::send_message(&mut stream, &handshake).await {
|
||||||
@ -170,7 +168,7 @@ impl Connector {
|
|||||||
let cmd = ExecutorCommand::Node(node::NodeCommand::AddPeer(peer.clone()));
|
let cmd = ExecutorCommand::Node(node::NodeCommand::AddPeer(peer.clone()));
|
||||||
publish_network_event(NetworkEvent::SeedConnected(addr.to_string()));
|
publish_network_event(NetworkEvent::SeedConnected(addr.to_string()));
|
||||||
let _ = self.exec_tx.send(cmd).await;
|
let _ = self.exec_tx.send(cmd).await;
|
||||||
Connection::new(self.node_id.clone(), peer.id, stream, self.exec_tx.clone(), ch_rx)
|
Connection::new(self.node_id, peer.id, stream, self.exec_tx.clone(), ch_rx)
|
||||||
.start()
|
.start()
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -185,7 +183,7 @@ impl Connector {
|
|||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
) {
|
) {
|
||||||
let handshake = ProtocolMessage::Handshake {
|
let handshake = ProtocolMessage::Handshake {
|
||||||
peer_id: self.node_id.clone(),
|
peer_id: self.node_id,
|
||||||
version: "".to_string(),
|
version: "".to_string(),
|
||||||
};
|
};
|
||||||
match Connector::send_message(&mut stream, &handshake).await {
|
match Connector::send_message(&mut stream, &handshake).await {
|
||||||
@ -206,7 +204,7 @@ impl Connector {
|
|||||||
};
|
};
|
||||||
let cmd = ExecutorCommand::Node(node::NodeCommand::AddPeer(peer.clone()));
|
let cmd = ExecutorCommand::Node(node::NodeCommand::AddPeer(peer.clone()));
|
||||||
let _ = self.exec_tx.send(cmd).await;
|
let _ = self.exec_tx.send(cmd).await;
|
||||||
Connection::new(self.node_id.clone(), peer.id, stream, self.exec_tx.clone(), ch_rx)
|
Connection::new(self.node_id, peer.id, stream, self.exec_tx.clone(), ch_rx)
|
||||||
.start()
|
.start()
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -225,7 +223,7 @@ impl Connector {
|
|||||||
let peer = match mes {
|
let peer = match mes {
|
||||||
ProtocolMessage::Handshake { peer_id, .. } => {
|
ProtocolMessage::Handshake { peer_id, .. } => {
|
||||||
let ack = ProtocolMessage::HandshakeAck {
|
let ack = ProtocolMessage::HandshakeAck {
|
||||||
peer_id: self.node_id.clone(),
|
peer_id: self.node_id,
|
||||||
version: "".to_string(),
|
version: "".to_string(),
|
||||||
};
|
};
|
||||||
match Connector::send_message(&mut stream, &ack).await {
|
match Connector::send_message(&mut stream, &ack).await {
|
||||||
@ -243,7 +241,7 @@ impl Connector {
|
|||||||
};
|
};
|
||||||
let cmd = ExecutorCommand::Node(node::NodeCommand::AddPeer(peer.clone()));
|
let cmd = ExecutorCommand::Node(node::NodeCommand::AddPeer(peer.clone()));
|
||||||
let _ = self.exec_tx.send(cmd).await;
|
let _ = self.exec_tx.send(cmd).await;
|
||||||
Connection::new(self.node_id.clone(), peer.id, stream, self.exec_tx.clone(), ch_rx)
|
Connection::new(self.node_id, peer.id, stream, self.exec_tx.clone(), ch_rx)
|
||||||
.start()
|
.start()
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -253,7 +251,8 @@ impl Connector {
|
|||||||
stream: &mut net::TcpStream,
|
stream: &mut net::TcpStream,
|
||||||
message: &ProtocolMessage,
|
message: &ProtocolMessage,
|
||||||
) -> Result<(), NetworkError> {
|
) -> Result<(), NetworkError> {
|
||||||
let data = bincode::encode_to_vec(message, BINCODE_CONFIG)?;
|
let json = serde_json::to_string(message).map_err(|_e| NetworkError::TODO)?;
|
||||||
|
let data = json.as_bytes();
|
||||||
|
|
||||||
let len = data.len() as u32;
|
let len = data.len() as u32;
|
||||||
stream
|
stream
|
||||||
@ -262,7 +261,7 @@ impl Connector {
|
|||||||
.map_err(|_e| NetworkError::TODO)?;
|
.map_err(|_e| NetworkError::TODO)?;
|
||||||
|
|
||||||
stream
|
stream
|
||||||
.write_all(&data)
|
.write_all(data)
|
||||||
.await
|
.await
|
||||||
.map_err(|_e| NetworkError::TODO)?;
|
.map_err(|_e| NetworkError::TODO)?;
|
||||||
stream.flush().await.map_err(|_e| NetworkError::TODO)?;
|
stream.flush().await.map_err(|_e| NetworkError::TODO)?;
|
||||||
@ -290,7 +289,9 @@ impl Connector {
|
|||||||
.await
|
.await
|
||||||
.map_err(|_e| NetworkError::TODO)?;
|
.map_err(|_e| NetworkError::TODO)?;
|
||||||
|
|
||||||
let (message, _): (ProtocolMessage, usize) = bincode::decode_from_slice(&data, BINCODE_CONFIG)?;
|
let json = String::from_utf8(data).map_err(|_e| NetworkError::TODO)?;
|
||||||
|
|
||||||
|
let message: ProtocolMessage = serde_json::from_str(&json).map_err(|_e| NetworkError::TODO)?;
|
||||||
|
|
||||||
Ok(message)
|
Ok(message)
|
||||||
}
|
}
|
||||||
@ -1,62 +1,52 @@
|
|||||||
use shared::blockchain_core::{self, ChainData};
|
use shared::core::{self, ChainData};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
pub const MAX_MESSAGE_SIZE: usize = 1_000_000;
|
pub const MAX_MESSAGE_SIZE: usize = 1_000_000;
|
||||||
|
|
||||||
#[derive(Debug, Clone, bincode::Encode, bincode::Decode, Hash, PartialEq, Eq)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
pub struct NodeId(pub [u8; 16]);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, bincode::Encode, bincode::Decode)]
|
|
||||||
pub enum ProtocolMessage {
|
pub enum ProtocolMessage {
|
||||||
BootstrapRequest {
|
BootstrapRequest {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
version: String,
|
version: String,
|
||||||
},
|
},
|
||||||
BootstrapResponse {
|
BootstrapResponse {
|
||||||
blocks: Vec<u8>,
|
blocks: Option<String>,
|
||||||
},
|
},
|
||||||
GetPeersRequest {
|
GetPeersRequest {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
},
|
},
|
||||||
GetPeersResponse {
|
GetPeersResponse {
|
||||||
peer_addresses: Vec<SocketAddr>,
|
peer_addresses: Vec<SocketAddr>,
|
||||||
},
|
},
|
||||||
Handshake {
|
Handshake {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
version: String,
|
version: String,
|
||||||
},
|
},
|
||||||
HandshakeAck {
|
HandshakeAck {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
version: String,
|
version: String,
|
||||||
},
|
},
|
||||||
Block {
|
Block {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
height: u64,
|
height: u64,
|
||||||
block: blockchain_core::Block,
|
block: core::Block,
|
||||||
},
|
},
|
||||||
ChainData {
|
ChainData {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
data: ChainData,
|
data: ChainData,
|
||||||
},
|
},
|
||||||
Ping {
|
Ping {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
},
|
},
|
||||||
Pong {
|
Pong {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
},
|
},
|
||||||
Disconnect {
|
Disconnect {
|
||||||
peer_id: NodeId,
|
peer_id: uuid::Uuid,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for NodeId {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let msg = self.to_string();
|
|
||||||
write!(f, "{}", msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for ProtocolMessage {
|
impl fmt::Display for ProtocolMessage {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -67,7 +57,7 @@ impl fmt::Display for ProtocolMessage {
|
|||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"BootstrapResponse with {:?} blocks",
|
"BootstrapResponse with {:?} blocks",
|
||||||
blocks.len()
|
blocks.clone().unwrap_or_default().len()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ProtocolMessage::GetPeersRequest { peer_id } => {
|
ProtocolMessage::GetPeersRequest { peer_id } => {
|
||||||
@ -1,10 +1,6 @@
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
|
||||||
pub static WS_LISTEN_ADDRESS: Lazy<SocketAddr> = Lazy::new(|| {
|
|
||||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 9001)
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static SEED_NODES: Lazy<[SocketAddr; 3]> = Lazy::new(|| {
|
pub static SEED_NODES: Lazy<[SocketAddr; 3]> = Lazy::new(|| {
|
||||||
[
|
[
|
||||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8333),
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8333),
|
||||||
|
|||||||
@ -76,7 +76,7 @@ impl WatcherBuilder {
|
|||||||
self.addr = Some(crate::seeds_constants::SEED_NODES[0]);
|
self.addr = Some(crate::seeds_constants::SEED_NODES[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let chain = node::Blockchain::new(self.database, self.temporary).unwrap();
|
let chain = node::Blockchain::build(None, self.temporary).unwrap();
|
||||||
let mut node = Node::new(self.addr.clone(), exec_tx.clone(), chain);
|
let mut node = Node::new(self.addr.clone(), exec_tx.clone(), chain);
|
||||||
log(msg!(INFO, "Built Node"));
|
log(msg!(INFO, "Built Node"));
|
||||||
|
|
||||||
|
|||||||
@ -227,9 +227,8 @@ impl Watcher {
|
|||||||
pub async fn log_memory() {
|
pub async fn log_memory() {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let id = format!("{}_{}", current_timestamp(), std::process::id());
|
let id = format!("{}_{}", current_timestamp(), std::process::id());
|
||||||
let id = id.replace(":", "_");
|
|
||||||
let mut path = std::path::PathBuf::new();
|
let mut path = std::path::PathBuf::new();
|
||||||
path.push("proc");
|
path.push("./proc/");
|
||||||
path.push(id);
|
path.push(id);
|
||||||
let mut mem_map = std::fs::OpenOptions::new()
|
let mut mem_map = std::fs::OpenOptions::new()
|
||||||
.create(true)
|
.create(true)
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
segment_size: 1048576
|
|
||||||
use_compression: false
|
|
||||||
version: 0.34
|
|
||||||
l–ø
|
|
||||||
BIN
node/temp/db
219
shared/Cargo.lock
generated
@ -58,18 +58,6 @@ version = "1.0.99"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base16ct"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64ct"
|
|
||||||
version = "1.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bincode"
|
name = "bincode"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@ -151,12 +139,6 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-oid"
|
|
||||||
version = "0.9.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@ -166,18 +148,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crypto-bigint"
|
|
||||||
version = "0.5.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
|
||||||
dependencies = [
|
|
||||||
"generic-array",
|
|
||||||
"rand_core",
|
|
||||||
"subtle",
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@ -188,16 +158,6 @@ dependencies = [
|
|||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "der"
|
|
||||||
version = "0.7.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
|
||||||
dependencies = [
|
|
||||||
"const-oid",
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.10.7"
|
||||||
@ -205,52 +165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"const-oid",
|
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
"subtle",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ecdsa"
|
|
||||||
version = "0.16.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
|
|
||||||
dependencies = [
|
|
||||||
"der",
|
|
||||||
"digest",
|
|
||||||
"elliptic-curve",
|
|
||||||
"rfc6979",
|
|
||||||
"signature",
|
|
||||||
"spki",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "elliptic-curve"
|
|
||||||
version = "0.13.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
|
||||||
dependencies = [
|
|
||||||
"base16ct",
|
|
||||||
"crypto-bigint",
|
|
||||||
"digest",
|
|
||||||
"ff",
|
|
||||||
"generic-array",
|
|
||||||
"group",
|
|
||||||
"pkcs8",
|
|
||||||
"rand_core",
|
|
||||||
"sec1",
|
|
||||||
"subtle",
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ff"
|
|
||||||
version = "0.13.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core",
|
|
||||||
"subtle",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -261,29 +176,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "group"
|
|
||||||
version = "0.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
|
||||||
dependencies = [
|
|
||||||
"ff",
|
|
||||||
"rand_core",
|
|
||||||
"subtle",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -298,15 +190,6 @@ version = "0.4.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hmac"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
|
||||||
dependencies = [
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@ -319,20 +202,6 @@ version = "1.0.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "k256"
|
|
||||||
version = "0.13.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"ecdsa",
|
|
||||||
"elliptic-curve",
|
|
||||||
"once_cell",
|
|
||||||
"sha2",
|
|
||||||
"signature",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "keccak"
|
name = "keccak"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@ -354,28 +223,12 @@ version = "2.7.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.21.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell_polyfill"
|
name = "once_cell_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pkcs8"
|
|
||||||
version = "0.10.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
|
||||||
dependencies = [
|
|
||||||
"der",
|
|
||||||
"spki",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.101"
|
version = "1.0.101"
|
||||||
@ -394,45 +247,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.6.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rfc6979"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
|
||||||
dependencies = [
|
|
||||||
"hmac",
|
|
||||||
"subtle",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.20"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sec1"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
|
||||||
dependencies = [
|
|
||||||
"base16ct",
|
|
||||||
"der",
|
|
||||||
"generic-array",
|
|
||||||
"pkcs8",
|
|
||||||
"subtle",
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.219"
|
||||||
@ -494,7 +314,6 @@ dependencies = [
|
|||||||
"bincode",
|
"bincode",
|
||||||
"clap",
|
"clap",
|
||||||
"hex",
|
"hex",
|
||||||
"k256",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
@ -502,38 +321,12 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signature"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
|
||||||
dependencies = [
|
|
||||||
"digest",
|
|
||||||
"rand_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spki"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
|
|
||||||
dependencies = [
|
|
||||||
"base64ct",
|
|
||||||
"der",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subtle"
|
|
||||||
version = "2.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.106"
|
version = "2.0.106"
|
||||||
@ -601,12 +394,6 @@ version = "0.0.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
|
checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.11.1+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-link"
|
name = "windows-link"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
@ -686,9 +473,3 @@ name = "windows_x86_64_msvc"
|
|||||||
version = "0.53.0"
|
version = "0.53.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zeroize"
|
|
||||||
version = "1.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
|
||||||
|
|||||||
@ -15,7 +15,6 @@ bincode = "2.0.1"
|
|||||||
clap = { version = "4.5.47", features = ["derive"] }
|
clap = { version = "4.5.47", features = ["derive"] }
|
||||||
# getrandom = { version = "0.3.3", features = ["wasm_js"] }
|
# getrandom = { version = "0.3.3", features = ["wasm_js"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
k256 = { version = "0.13.4", features = ["ecdsa-core"] }
|
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.143"
|
serde_json = "1.0.143"
|
||||||
sha2 = "0.10.9"
|
sha2 = "0.10.9"
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
use bincode::{Decode, Encode};
|
|
||||||
|
|
||||||
use crate::blockchain_core::{SignedTransaction, Transaction};
|
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, Clone)]
|
|
||||||
pub enum ChainData {
|
|
||||||
Transaction(SignedTransaction),
|
|
||||||
NodeTransaction(Transaction),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChainData {
|
|
||||||
pub fn hash(&self) -> [u8; 32] {
|
|
||||||
match self {
|
|
||||||
Self::Transaction(tx) => tx.hash(),
|
|
||||||
Self::NodeTransaction(tx) => tx.hash(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
use k256::ecdsa::{
|
|
||||||
VerifyingKey,
|
|
||||||
RecoveryId,
|
|
||||||
Signature,
|
|
||||||
signature::Verifier,
|
|
||||||
};
|
|
||||||
use crate::blockchain_core::{Hasher, SignedTransaction};
|
|
||||||
use crate::blockchain_core::{ Block, ChainData };
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum ValidationError {
|
|
||||||
#[error("Invalid Block Hash Detected at height {0}")]
|
|
||||||
InvalidBlockHash(u64),
|
|
||||||
#[error("Invalid Block Hash Difficulty Detected at height {0}")]
|
|
||||||
InvalidBlockHashDifficulty(u64),
|
|
||||||
#[error("Previous Block Hash doesn't match at height {0}")]
|
|
||||||
InvalidPreviousBlockHash(u64),
|
|
||||||
#[error("Invalid Block Data Hash Count at height: {0}!\nexpected: {1}\nfound: {2}\n")]
|
|
||||||
BlockDataCount(u64, usize, usize),
|
|
||||||
#[error("Ecdsa Error: {0}")]
|
|
||||||
K256(#[from] k256::ecdsa::Error),
|
|
||||||
#[error("Invalid Recovery ID: {0}")]
|
|
||||||
InvalidRecoveryId(u8),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Validator {}
|
|
||||||
|
|
||||||
impl Validator {
|
|
||||||
pub fn validate_chain(blocks: &[Block], data: &[ChainData]) -> Result<(), ValidationError> {
|
|
||||||
let data_hashes = data.iter().map(|d| d.hash()).collect::<Vec<[u8; 32]>>();
|
|
||||||
for block in blocks {
|
|
||||||
let block_data_hashes = data_hashes.iter().filter(|d| block.data().contains(d)).collect::<Vec<_>>();
|
|
||||||
Self::validate_block(block, &block_data_hashes)?
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify_signature(sign_tx: &SignedTransaction) -> Result<(), ValidationError>{
|
|
||||||
if let Some(rec_id) = RecoveryId::from_byte(sign_tx.recovery_id()) {
|
|
||||||
let sig = Signature::from_slice(sign_tx.signature())?;
|
|
||||||
let hash = sign_tx.hash();
|
|
||||||
let pub_key = VerifyingKey::recover_from_msg(&hash, &sig, rec_id).unwrap();
|
|
||||||
|
|
||||||
Ok(pub_key.verify(&hash, &sig).unwrap())
|
|
||||||
} else {
|
|
||||||
Err(ValidationError::InvalidRecoveryId(sign_tx.recovery_id()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn validate_block(block: &Block, data: &[&[u8; 32]]) -> Result<(), ValidationError> {
|
|
||||||
let block_hash = Hasher::calculate_block_hash(block.head());
|
|
||||||
|
|
||||||
if !block_hash.starts_with(b"0") {
|
|
||||||
return Err(ValidationError::InvalidBlockHashDifficulty(block.head().height));
|
|
||||||
}
|
|
||||||
|
|
||||||
if block_hash != block.head().block_hash() {
|
|
||||||
return Err(ValidationError::InvalidBlockHash(block.head().height))
|
|
||||||
}
|
|
||||||
if data.len() != block.data().len() {
|
|
||||||
return Err(ValidationError::BlockDataCount(block.head().height, block.data().len(), data.len()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
shared/src/core/data.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use bincode::{Decode, Encode};
|
||||||
|
|
||||||
|
use super::Transaction;
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize, Encode, Decode, Debug, Clone)]
|
||||||
|
pub enum ChainData {
|
||||||
|
Transaction(Transaction),
|
||||||
|
}
|
||||||
@ -2,35 +2,25 @@ use sha2::Digest;
|
|||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
use sha3::Keccak256;
|
use sha3::Keccak256;
|
||||||
|
|
||||||
use crate::blockchain_core::Transaction;
|
|
||||||
|
|
||||||
use super::{BlockHeader, ChainData};
|
use super::{BlockHeader, ChainData};
|
||||||
|
|
||||||
pub struct Hasher {}
|
pub struct Hasher {}
|
||||||
|
|
||||||
impl Hasher {
|
impl Hasher {
|
||||||
|
pub fn hash_chain_data(data: &ChainData) -> [u8; 32] {
|
||||||
pub fn hash_transaction_data(data: &Transaction) -> [u8; 32] {
|
|
||||||
let mut hasher = Keccak256::new();
|
let mut hasher = Keccak256::new();
|
||||||
hasher.update(data.to());
|
match data {
|
||||||
hasher.update(data.from());
|
ChainData::Transaction(tx) => {
|
||||||
hasher.update(data.value().to_be_bytes());
|
hasher.update(tx.to());
|
||||||
hasher.update(data.data());
|
hasher.update(tx.from());
|
||||||
|
hasher.update(tx.value().to_be_bytes());
|
||||||
|
hasher.update(tx.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
let res = hasher.finalize();
|
let res = hasher.finalize();
|
||||||
res.into()
|
res.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_chain_data(data: &ChainData) -> [u8; 32] {
|
|
||||||
match data {
|
|
||||||
ChainData::Transaction(signed_transaction) => {
|
|
||||||
signed_transaction.hash()
|
|
||||||
}
|
|
||||||
ChainData::NodeTransaction(tx) => {
|
|
||||||
tx.hash()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn calculate_next_level(level: &[[u8; 32]]) -> Vec<[u8; 32]> {
|
pub fn calculate_next_level(level: &[[u8; 32]]) -> Vec<[u8; 32]> {
|
||||||
let mut next_level = Vec::new();
|
let mut next_level = Vec::new();
|
||||||
|
|
||||||
@ -1,5 +1,3 @@
|
|||||||
use std::time::UNIX_EPOCH;
|
|
||||||
|
|
||||||
use super::Address;
|
use super::Address;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@ -57,11 +55,10 @@ pub struct Transaction {
|
|||||||
to: Address,
|
to: Address,
|
||||||
value: u64,
|
value: u64,
|
||||||
data: String,
|
data: String,
|
||||||
timestamp: u64,
|
|
||||||
nonce: u64,
|
nonce: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, bincode::Decode, bincode::Encode)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SignedTransaction {
|
pub struct SignedTransaction {
|
||||||
tx: Transaction,
|
tx: Transaction,
|
||||||
signature: [u8; 64],
|
signature: [u8; 64],
|
||||||
@ -82,15 +79,11 @@ impl SignedTransaction {
|
|||||||
&self.signature
|
&self.signature
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(&self) -> [u8; 32] {
|
|
||||||
self.data().hash()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recovery_id(&self) -> u8 {
|
pub fn recovery_id(&self) -> u8 {
|
||||||
self.recovery_id
|
self.recovery_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data(&self) -> &Transaction {
|
pub fn tx(&self) -> &Transaction {
|
||||||
&self.tx
|
&self.tx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +96,6 @@ impl Transaction {
|
|||||||
value,
|
value,
|
||||||
data,
|
data,
|
||||||
nonce,
|
nonce,
|
||||||
timestamp: std::time::SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +111,7 @@ impl Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(&self) -> [u8; 32] {
|
pub fn hash(&self) -> [u8; 32] {
|
||||||
super::Hasher::hash_transaction_data(self)
|
super::Hasher::hash_chain_data(&super::ChainData::Transaction(self.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(&self) -> &Address {
|
pub fn from(&self) -> &Address {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
pub mod blockchain_core {
|
pub mod core {
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub use block::*;
|
pub use block::*;
|
||||||
|
|
||||||
@ -13,13 +13,8 @@ pub mod blockchain_core {
|
|||||||
|
|
||||||
pub mod address;
|
pub mod address;
|
||||||
pub use address::*;
|
pub use address::*;
|
||||||
|
|
||||||
pub mod validator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod ws_protocol;
|
|
||||||
pub use ws_protocol::*;
|
|
||||||
|
|
||||||
pub fn print_error_chain(err: &anyhow::Error) {
|
pub fn print_error_chain(err: &anyhow::Error) {
|
||||||
let mut err_string = String::from(format!("Error: {}\n", err));
|
let mut err_string = String::from(format!("Error: {}\n", err));
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
use crate::blockchain_core::SignedTransaction;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, bincode::Encode, bincode::Decode)]
|
|
||||||
pub enum WsClientRequest {
|
|
||||||
Ping,
|
|
||||||
BroadcastTransaction(SignedTransaction),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, bincode::Encode, bincode::Decode)]
|
|
||||||
pub enum WsClientResponse {
|
|
||||||
Pong
|
|
||||||
}
|
|
||||||
10
testing/tauri/test/.gitignore
vendored
@ -1,10 +0,0 @@
|
|||||||
.DS_Store
|
|
||||||
node_modules
|
|
||||||
/build
|
|
||||||
/.svelte-kit
|
|
||||||
/package
|
|
||||||
.env
|
|
||||||
.env.*
|
|
||||||
!.env.example
|
|
||||||
vite.config.js.timestamp-*
|
|
||||||
vite.config.ts.timestamp-*
|
|
||||||
7
testing/tauri/test/.vscode/extensions.json
vendored
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"svelte.svelte-vscode",
|
|
||||||
"tauri-apps.tauri-vscode",
|
|
||||||
"rust-lang.rust-analyzer"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
3
testing/tauri/test/.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"svelte.enable-ts-plugin": true
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
# Tauri + SvelteKit + TypeScript
|
|
||||||
|
|
||||||
This template should help get you started developing with Tauri, SvelteKit and TypeScript in Vite.
|
|
||||||
|
|
||||||
## Recommended IDE Setup
|
|
||||||
|
|
||||||
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://shadcn-svelte.com/schema.json",
|
|
||||||
"tailwind": {
|
|
||||||
"css": "src/app.css",
|
|
||||||
"baseColor": "zinc"
|
|
||||||
},
|
|
||||||
"aliases": {
|
|
||||||
"components": "$lib/components",
|
|
||||||
"utils": "$lib/utils",
|
|
||||||
"ui": "$lib/components/ui",
|
|
||||||
"hooks": "$lib/hooks",
|
|
||||||
"lib": "$lib"
|
|
||||||
},
|
|
||||||
"typescript": true,
|
|
||||||
"registry": "https://shadcn-svelte.com/registry"
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "test",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite dev",
|
|
||||||
"build": "vite build",
|
|
||||||
"preview": "vite preview",
|
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
||||||
"tauri": "export WEBKIT_DISABLE_COMPOSITING_MODE=1; tauri"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@tailwindcss/vite": "^4.1.13",
|
|
||||||
"@tauri-apps/api": "^2",
|
|
||||||
"@tauri-apps/plugin-opener": "^2",
|
|
||||||
"tailwindcss": "^4.1.13"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@lucide/svelte": "^0.544.0",
|
|
||||||
"@sveltejs/adapter-static": "^3.0.6",
|
|
||||||
"@sveltejs/kit": "^2.9.0",
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
|
||||||
"@tauri-apps/cli": "^2",
|
|
||||||
"clsx": "^2.1.1",
|
|
||||||
"svelte": "^5.0.0",
|
|
||||||
"svelte-check": "^4.0.0",
|
|
||||||
"tailwind-merge": "^3.3.1",
|
|
||||||
"tailwind-variants": "^3.1.1",
|
|
||||||
"tw-animate-css": "^1.3.8",
|
|
||||||
"typescript": "~5.6.2",
|
|
||||||
"vite": "^6.0.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1545
testing/tauri/test/pnpm-lock.yaml
generated
7
testing/tauri/test/src-tauri/.gitignore
vendored
@ -1,7 +0,0 @@
|
|||||||
# Generated by Cargo
|
|
||||||
# will have compiled files and executables
|
|
||||||
/target/
|
|
||||||
|
|
||||||
# Generated by Tauri
|
|
||||||
# will have schema files for capabilities auto-completion
|
|
||||||
/gen/schemas
|
|
||||||
5286
testing/tauri/test/src-tauri/Cargo.lock
generated
@ -1,25 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "test"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "A Tauri App"
|
|
||||||
authors = ["you"]
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
# The `_lib` suffix may seem redundant but it is necessary
|
|
||||||
# to make the lib name unique and wouldn't conflict with the bin name.
|
|
||||||
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
|
|
||||||
name = "test_lib"
|
|
||||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
tauri-build = { version = "2", features = [] }
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
tauri = { version = "2", features = [] }
|
|
||||||
tauri-plugin-opener = "2"
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
|
||||||
serde_json = "1"
|
|
||||||
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
tauri_build::build()
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../gen/schemas/desktop-schema.json",
|
|
||||||
"identifier": "default",
|
|
||||||
"description": "Capability for the main window",
|
|
||||||
"windows": ["main"],
|
|
||||||
"permissions": [
|
|
||||||
"core:default",
|
|
||||||
"opener:default"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 974 B |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 903 B |
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 14 KiB |
@ -1,14 +0,0 @@
|
|||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
|
||||||
#[tauri::command]
|
|
||||||
fn greet(name: &str) -> String {
|
|
||||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
||||||
pub fn run() {
|
|
||||||
tauri::Builder::default()
|
|
||||||
.plugin(tauri_plugin_opener::init())
|
|
||||||
.invoke_handler(tauri::generate_handler![greet])
|
|
||||||
.run(tauri::generate_context!())
|
|
||||||
.expect("error while running tauri application");
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
test_lib::run()
|
|
||||||
}
|
|
||||||