diff --git a/src/miner/mod.rs b/src/miner/mod.rs index c856aeac9a200b7163de55eb05ace0aa4d02d9e8..e5c6441073d066519cbd78e0959b97d773a7e4f0 100644 --- a/src/miner/mod.rs +++ b/src/miner/mod.rs @@ -7,7 +7,13 @@ use std::time; use std::thread; -use crate::types::block::Block; +use crate::types::block::{Block, Header}; +use crate::types::hash::{H256, Hashable}; +use crate::types::transaction; +use crate::types::transaction::SignedTransaction; +use std::sync:: {Arc, Mutex}; +use crate::Blockchain; +use std::time::{SystemTime, UNIX_EPOCH}; enum ControlSignal { Start(u64), // the number controls the lambda of interval between block generation @@ -26,6 +32,7 @@ pub struct Context { control_chan: Receiver<ControlSignal>, operating_state: OperatingState, finished_block_chan: Sender<Block>, + blockchain: Arc<Mutex<Blockchain>>, } #[derive(Clone)] @@ -34,7 +41,7 @@ pub struct Handle { control_chan: Sender<ControlSignal>, } -pub fn new() -> (Context, Handle, Receiver<Block>) { +pub fn new(blockchain: &Arc<Mutex<Blockchain>>) -> (Context, Handle, Receiver<Block>) { let (signal_chan_sender, signal_chan_receiver) = unbounded(); let (finished_block_sender, finished_block_receiver) = unbounded(); @@ -42,6 +49,7 @@ pub fn new() -> (Context, Handle, Receiver<Block>) { control_chan: signal_chan_receiver, operating_state: OperatingState::Paused, finished_block_chan: finished_block_sender, + blockchain: Arc::clone(blockchain), }; let handle = Handle { @@ -53,7 +61,9 @@ pub fn new() -> (Context, Handle, Receiver<Block>) { #[cfg(any(test,test_utilities))] fn test_new() -> (Context, Handle, Receiver<Block>) { - new() + let temp_blockchain = Blockchain::new(); + let blockchain = Arc::new(Mutex::new(temp_blockchain)); + return new(&blockchain); } impl Handle { @@ -85,6 +95,9 @@ impl Context { fn miner_loop(&mut self) { // main mining loop + let mut locked_blockchain = self.blockchain.lock().unwrap(); + let mut parent = locked_blockchain.tip(); + let const_difficulty = locked_blockchain.blocks.get(&parent).unwrap().header.difficulty; loop { // check and react to control signals match self.operating_state { @@ -120,7 +133,8 @@ impl Context { self.operating_state = OperatingState::Run(i); } ControlSignal::Update => { - unimplemented!() + //unimplemented!() + parent = locked_blockchain.tip(); } }; } @@ -134,6 +148,33 @@ impl Context { // TODO for student: actual mining, create a block // TODO for student: if block mining finished, you can have something like: self.finished_block_chan.send(block.clone()).expect("Send finished block error"); + let nonce:u32 = rand::random(); + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(); + let content: Vec<SignedTransaction> = Vec::new(); + let bytes = bincode::serialize(&content).unwrap(); + let merkle_root = ring::digest::digest(&ring::digest::SHA256, &bytes).into(); + + let header = Header { + parent, + nonce, + difficulty: const_difficulty, + timestamp, + merkle_root + }; + + let new_block = Block { + header, + content + }; + + if new_block.hash() <= const_difficulty { + match self.finished_block_chan.send(new_block.clone()) { + Ok(()) => { + parent = new_block.hash(); + } + Err (_) => eprintln!("Send new_block Error!") + } + } if let OperatingState::Run(i) = self.operating_state { if i != 0 { @@ -167,4 +208,4 @@ mod test { } } -// DO NOT CHANGE THIS COMMENT, IT IS FOR AUTOGRADER. AFTER TEST \ No newline at end of file +// DO NOT CHANGE THIS COMMENT, IT IS FOR AUTOGRADER. AFTER TEST