diff --git a/src/event.rs b/src/event.rs index 596dba4..fde9772 100644 --- a/src/event.rs +++ b/src/event.rs @@ -10,7 +10,7 @@ pub enum Event { KeyLoaded { path: String, public: String, hash: String }, KeySaved { path: String, public: String, hash: String }, NewBlockReceived, - BlockchainChanged, + BlockchainChanged { index: u64 }, ActionStopMining, ActionMineLocker { index: u64, hash: Bytes }, NetworkStatus { nodes: usize, blocks: u64 }, diff --git a/src/keys.rs b/src/keys.rs index a641366..70b1522 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -170,7 +170,7 @@ fn generate_key(difficulty: usize, mining: Arc) -> Option digest.input(&keystore.public_key); digest.result(&mut buf); if hash_is_good(&buf, difficulty) { - info!("Generated keypair: {:?}", &keystore); + info!("Generated keypair with public key: {:?} and hash {:?}", &keystore.get_public(), &keystore.get_hash()); return Some(keystore); } if !mining.load(atomic::Ordering::SeqCst) { diff --git a/src/main.rs b/src/main.rs index ec0eeb8..20a3348 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,7 +69,7 @@ fn main() { info!(target: LOG_TARGET_MAIN, "Starting ALFIS {}", env!("CARGO_PKG_VERSION")); let settings = Settings::load(&config_name); - info!("Loaded settings: {:?}", &settings); + info!(target: LOG_TARGET_MAIN, "Loaded settings: {:?}", &settings); let keystore: Keystore = match Keystore::from_file(&settings.key_file, "") { None => { warn!(target: LOG_TARGET_MAIN, "Generated temporary keystore. Please, generate full-privileged keys."); diff --git a/src/miner.rs b/src/miner.rs index 25b1663..6de2230 100644 --- a/src/miner.rs +++ b/src/miner.rs @@ -1,5 +1,5 @@ use std::sync::{Arc, Condvar, Mutex}; -use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU32, Ordering, AtomicU64}; use std::thread; use std::time::Duration; @@ -80,7 +80,7 @@ impl Miner { self.context.lock().unwrap().bus.register(move |_uuid, e| { match e { Event::NewBlockReceived => {} - Event::BlockchainChanged => {} + Event::BlockchainChanged {..} => {} Event::ActionStopMining => { mining.store(false, Ordering::SeqCst); } @@ -142,19 +142,37 @@ impl Miner { } context.lock().unwrap().bus.post(Event::MinerStarted); + let thread_spawn_interval = Duration::from_millis(10); let live_threads = Arc::new(AtomicU32::new(0u32)); + let top_block = Arc::new(AtomicU64::new(block.index - 1)); let cpus = num_cpus::get(); debug!("Starting {} threads for mining", cpus); - for _ in 0..cpus { - let context = context.clone(); + for cpu in 0..cpus { + let context = Arc::clone(&context); let block = block.clone(); - let mining = mining.clone(); - let live_threads = live_threads.clone(); + let mining = Arc::clone(&mining); + let top_block = Arc::clone(&top_block); + let live_threads = Arc::clone(&live_threads); thread::spawn(move || { + // Register this thread to receive events from bus + let top = Arc::clone(&top_block); + context.lock().unwrap().bus.register(move |_uuid, e| { + match e { + Event::NewBlockReceived => {} + Event::BlockchainChanged { index } => { + top.store(index, Ordering::SeqCst); + } + _ => {} + } + true + }); + #[cfg(not(target_os = "macos"))] let _ = set_current_thread_priority(ThreadPriority::Min); + let _ = set_current_thread_ideal_processor(IdealProcessor::from(cpu as u32)); live_threads.fetch_add(1, Ordering::SeqCst); - match find_hash(&mut *get_hasher_for_version(block.version), block, mining.clone()) { + let mut hasher = get_hasher_for_version(block.version); + match find_hash(Arc::clone(&context), &mut *hasher, block, Arc::clone(&mining), top_block) { None => { debug!("Mining was cancelled"); let count = live_threads.fetch_sub(1, Ordering::SeqCst); @@ -181,15 +199,26 @@ impl Miner { }, } }); + thread::sleep(thread_spawn_interval); } } } -fn find_hash(digest: &mut dyn Digest, mut block: Block, running: Arc) -> Option { +fn find_hash(context: Arc>, digest: &mut dyn Digest, mut block: Block, running: Arc, top_block: Arc) -> Option { let mut buf: [u8; 32] = [0; 32]; let difficulty = block.difficulty as usize; loop { block.random = rand::random(); + block.index = context.lock().unwrap().chain.height() + 1; + if let Some(last_block) = context.lock().unwrap().chain.last_block() { + block.prev_block_hash = last_block.hash; + if block.transaction.is_some() && last_block.transaction.is_some() { + // We can't mine our domain block over a block with domain + // TODO make a method in Chain to get next available to mine bock index + thread::sleep(Duration::from_millis(1000)); + continue; + } + } debug!("Mining block {}", serde_json::to_string(&block).unwrap()); for nonce in 0..std::u64::MAX { if !running.load(Ordering::Relaxed) { @@ -205,6 +234,11 @@ fn find_hash(digest: &mut dyn Digest, mut block: Block, running: Arc block.hash = Bytes::from_bytes(&buf); return Some(block); } + + if top_block.load(Ordering::SeqCst) >= block.index { + // If there is a new block in chain we restart hashing with new data + break; + } } } } \ No newline at end of file diff --git a/src/p2p/network.rs b/src/p2p/network.rs index 5dc4bd1..b994ca8 100644 --- a/src/p2p/network.rs +++ b/src/p2p/network.rs @@ -370,7 +370,7 @@ fn handle_message(context: Arc>, message: Message, peers: &mut Pe BlockQuality::Good => { context.chain.add_block(block); let my_height = context.chain.height(); - context.bus.post(crate::event::Event::BlockchainChanged); + context.bus.post(crate::event::Event::BlockchainChanged { index: my_height }); // If it was the last block to sync if my_height == max_height { context.bus.post(crate::event::Event::SyncFinished);