diff --git a/Cargo.toml b/Cargo.toml index d38b00e..c17fe45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alfis" -version = "0.1.5" +version = "0.1.6" authors = ["Revertron "] edition = "2018" build = "build.rs" diff --git a/src/event.rs b/src/event.rs index ea3e247..216886e 100644 --- a/src/event.rs +++ b/src/event.rs @@ -10,7 +10,7 @@ pub enum Event { NewBlockReceived, BlockchainChanged, ActionStopMining, - StatsCount { nodes: usize, blocks: u64 }, - SyncStarted { have: u64, height: u64 }, - ActionIdle, + NetworkStatus { nodes: usize, blocks: u64 }, + Syncing { have: u64, height: u64 }, + SyncFinished, } diff --git a/src/main.rs b/src/main.rs index abb6b45..65645d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -180,8 +180,9 @@ fn run_interface(context: Arc>, miner: Arc>) { debug!("Command {}", arg); match serde_json::from_str(arg).unwrap() { Loaded => { - web_view.eval("showMiningIndicator(false);").expect("Error evaluating!"); + web_view.eval("showMiningIndicator(false, false);").expect("Error evaluating!"); let handle = web_view.handle(); + let mut status = Status::new(); let mut c = context.lock().unwrap(); c.bus.register(move |_uuid, e| { debug!("Got event from bus {:?}", &e); @@ -189,18 +190,46 @@ fn run_interface(context: Arc>, miner: Arc>) { Event::KeyCreated { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) } Event::KeyLoaded { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) } Event::KeySaved { path, public } => { format!("keystoreChanged('{}', '{}');", &path, &public) } - Event::MinerStarted => { format!("showMiningIndicator({}, false);", true) } - Event::KeyGeneratorStarted => { format!("showMiningIndicator({}, false);", true) } - Event::MinerStopped => { format!("showMiningIndicator({}, false);", false) } - Event::KeyGeneratorStopped => { format!("showMiningIndicator({}, false);", false) } - Event::SyncStarted { have, height } => { - format!("setLeftStatusBarText('Synchronizing {}/{}'); showMiningIndicator(true, true);", have, height) + Event::MinerStarted => { + status.mining = true; + String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") } - Event::ActionIdle => { - format!("setLeftStatusBarText('Idle'); showMiningIndicator(false, true);") + Event::KeyGeneratorStarted => { + status.mining = true; + String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") } - Event::StatsCount { nodes, blocks } => { - format!("setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks) + Event::MinerStopped | Event::KeyGeneratorStopped => { + status.mining = false; + if status.syncing { + String::from("setLeftStatusBarText('Syncing...'); showMiningIndicator(true, true);") + } else { + String::from("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") + } + } + Event::Syncing { have, height } => { + status.syncing = true; + status.synced_blocks = have; + status.sync_height = height; + if status.mining { + String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") + } else { + format!("setLeftStatusBarText('Synchronizing {}/{}'); showMiningIndicator(true, true);", have, height) + } + } + Event::SyncFinished => { + status.syncing = false; + if status.mining { + String::from("setLeftStatusBarText('Mining...'); showMiningIndicator(true, false);") + } else { + format!("setLeftStatusBarText('Idle'); showMiningIndicator(false, false);") + } + } + Event::NetworkStatus { nodes, blocks } => { + if status.mining || status.syncing || nodes < 3 { + format!("setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks) + } else { + format!("setLeftStatusBarText('Idle'); setRightStatusBarText('Nodes: {}, Blocks: {}')", nodes, blocks) + } } _ => { String::new() } }; @@ -477,6 +506,21 @@ pub enum Cmd { StopMining, } +struct Status { + pub mining: bool, + pub syncing: bool, + pub synced_blocks: u64, + pub sync_height: u64, + pub nodes_connected: usize, + pub chain_height: u64 +} + +impl Status { + fn new() -> Self { + Status { mining: false, syncing: false, synced_blocks: 0, sync_height: 0, nodes_connected: 0, chain_height: 0 } + } +} + fn inline_style(s: &str) -> String { format!(r#""#, s) } diff --git a/src/miner.rs b/src/miner.rs index a29e7f1..fd20123 100644 --- a/src/miner.rs +++ b/src/miner.rs @@ -38,8 +38,8 @@ impl Miner { } pub fn stop(&mut self) { - self.mining.store(false, Ordering::Relaxed); - self.running.store(false, Ordering::Relaxed); + self.mining.store(false, Ordering::SeqCst); + self.running.store(false, Ordering::SeqCst); self.cond_var.notify_all(); } @@ -62,7 +62,7 @@ impl Miner { if lock.len() > 0 { info!("Got new transaction to mine"); let transaction = lock.remove(0); - mining.store(true, Ordering::Relaxed); + mining.store(true, Ordering::SeqCst); Miner::mine_internal(context.clone(), transactions.clone(), transaction, mining.clone(), cond_var.clone()); } else { let _ = cond_var.wait(lock).expect("Error in wait lock!"); @@ -72,7 +72,7 @@ impl Miner { let mining = self.mining.clone(); self.context.lock().unwrap().bus.register(move |_uuid, e| { if e == Event::ActionStopMining { - mining.store(false, Ordering::Relaxed); + mining.store(false, Ordering::SeqCst); } true }); @@ -123,17 +123,15 @@ impl Miner { let live_threads = live_threads.clone(); let cond_var = cond_var.clone(); thread::spawn(move || { - live_threads.fetch_add(1, Ordering::Relaxed); + live_threads.fetch_add(1, Ordering::SeqCst); match find_hash(&mut Sha256::new(), block, mining.clone()) { None => { - debug!("Mining did not find suitable hash or was stopped"); - let count = live_threads.fetch_sub(1, Ordering::Relaxed); + debug!("Mining was cancelled"); + let count = live_threads.fetch_sub(1, Ordering::SeqCst); // If this is the last thread, but mining was not stopped by another thread - if count == 0 && mining.load(Ordering::Relaxed) { - // If all threads came empty with mining we return transaction to the queue - transactions.lock().unwrap().push(transaction); - mining.store(false, Ordering::Relaxed); - cond_var.notify_one(); + if count == 1 { + let mut context = context.lock().unwrap(); + context.bus.post(Event::MinerStopped); } }, Some(block) => { @@ -146,7 +144,7 @@ impl Miner { } } context.bus.post(Event::MinerStopped); - mining.store(false, Ordering::Relaxed); + mining.store(false, Ordering::SeqCst); }, } }); @@ -156,21 +154,23 @@ impl Miner { fn find_hash(digest: &mut dyn Digest, mut block: Block, running: Arc) -> Option { let mut buf: [u8; 32] = [0; 32]; - block.random = rand::random(); - debug!("Mining block {}", serde_json::to_string(&block).unwrap()); - for nonce in 0..std::u64::MAX { - if !running.load(Ordering::Relaxed) { - return None; - } - block.timestamp = Utc::now().timestamp(); - block.nonce = nonce; + loop { + block.random = rand::random(); + debug!("Mining block {}", serde_json::to_string(&block).unwrap()); + for nonce in 0..std::u64::MAX { + if !running.load(Ordering::Relaxed) { + return None; + } + block.timestamp = Utc::now().timestamp(); + block.nonce = nonce; - digest.reset(); - digest.input(serde_json::to_string(&block).unwrap().as_bytes()); - digest.result(&mut buf); - if hash_is_good(&buf, block.difficulty) { - block.hash = Bytes::from_bytes(&buf); - return Some(block); + digest.reset(); + digest.input(serde_json::to_string(&block).unwrap().as_bytes()); + digest.result(&mut buf); + if hash_is_good(&buf, block.difficulty) { + block.hash = Bytes::from_bytes(&buf); + return Some(block); + } } } None diff --git a/src/p2p/network.rs b/src/p2p/network.rs index 31302d0..db867a4 100644 --- a/src/p2p/network.rs +++ b/src/p2p/network.rs @@ -93,7 +93,7 @@ impl Network { let _ = peers.close_peer(poll.registry(), &token); let mut context = context.lock().unwrap(); let blocks_count = context.blockchain.height(); - context.bus.post(crate::event::Event::StatsCount { nodes: peers.get_peers_active_count(), blocks: blocks_count }); + context.bus.post(crate::event::Event::NetworkStatus { nodes: peers.get_peers_active_count(), blocks: blocks_count }); } } } @@ -283,10 +283,10 @@ fn handle_message(context: Arc>, message: Message, peers: &mut Pe peer.set_active(true); let mut context = context.lock().unwrap(); let blocks_count = context.blockchain.height(); - context.bus.post(crate::event::Event::StatsCount { nodes: active_count, blocks: blocks_count }); + context.bus.post(crate::event::Event::NetworkStatus { nodes: active_count + 1, blocks: blocks_count }); if peer.is_higher(my_height) { context.blockchain.update_max_height(height); - context.bus.post(crate::event::Event::SyncStarted { have: my_height, height}); + context.bus.post(crate::event::Event::Syncing { have: my_height, height}); State::message(Message::GetBlock { index: my_height }) } else { State::message(Message::GetPeers) @@ -315,8 +315,7 @@ fn handle_message(context: Arc>, message: Message, peers: &mut Pe } else { let mut context = context.lock().unwrap(); let blocks_count = context.blockchain.height(); - context.bus.post(crate::event::Event::ActionIdle); - context.bus.post(crate::event::Event::StatsCount { nodes: peers.get_peers_active_count(), blocks: blocks_count }); + context.bus.post(crate::event::Event::NetworkStatus { nodes: peers.get_peers_active_count(), blocks: blocks_count }); State::idle() } } @@ -352,9 +351,9 @@ fn handle_message(context: Arc>, message: Message, peers: &mut Pe context.bus.post(crate::event::Event::BlockchainChanged); // If it was the last block to sync if my_height == max_height { - context.bus.post(crate::event::Event::ActionIdle); + context.bus.post(crate::event::Event::SyncFinished); } else { - context.bus.post(crate::event::Event::SyncStarted { have: my_height, height: max_height}); + context.bus.post(crate::event::Event::Syncing { have: my_height, height: max_height}); } } Err(_) => { warn!("Discarded received block"); }