Created
June 26, 2021 00:10
-
-
Save Jackzmc/4590d58519ca99f0a25246dd6ee491bf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use sha2::{Sha256, Digest}; | |
| use std::time::{SystemTime, UNIX_EPOCH}; | |
| type HashResult = Vec<u8>; | |
| type Hash = Sha256; | |
| #[derive(Debug)] | |
| struct Data { | |
| id: u64 | |
| } | |
| #[derive(Debug)] | |
| struct Block { | |
| timestamp: u64, | |
| data: Data, | |
| prev_hash: Option<HashResult>, | |
| hash: HashResult | |
| } | |
| impl Block { | |
| pub fn new(data: Data, prev_hash: Option<HashResult>) -> Block { | |
| let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); | |
| let hash = | |
| if let Some(hash) = prev_hash.clone() { | |
| let payload = [hash, timestamp.to_be_bytes().to_vec()].concat(); | |
| Hash::digest(&payload) | |
| }else{ | |
| Hash::digest(×tamp.to_be_bytes()) | |
| }; | |
| Block { | |
| timestamp, | |
| data, | |
| prev_hash, | |
| hash: hash.to_vec() | |
| } | |
| } | |
| pub fn compute_hash(&self) -> HashResult { | |
| if let Some(hash) = self.prev_hash.clone() { | |
| let payload = [hash, self.timestamp.to_be_bytes().to_vec()].concat(); | |
| return Hash::digest(&payload).to_vec() | |
| }else{ | |
| return Hash::digest(&self.timestamp.to_be_bytes()).to_vec() | |
| }; | |
| } | |
| } | |
| struct BlockChain { | |
| blocks: Vec<Block> | |
| } | |
| impl BlockChain { | |
| pub fn new() -> BlockChain { | |
| let data = Data { | |
| id: 0 | |
| }; | |
| BlockChain { | |
| blocks: vec![Block::new(data, None)] | |
| } | |
| } | |
| pub fn get_last(&self) -> &Block { | |
| &self.blocks[self.blocks.len() - 1] | |
| } | |
| pub fn add_block(&mut self, mut block: Block) { | |
| let last = &self.get_last(); | |
| block.prev_hash = Some(last.hash.clone()); | |
| block.hash = block.compute_hash(); | |
| block.data.id = last.data.id + 1; | |
| self.blocks.push(block); | |
| } | |
| pub fn is_valid(&self) -> bool { | |
| for i in 1..self.blocks.len() { | |
| let current = &self.blocks[i]; | |
| let previous = &self.blocks[i -1]; | |
| // Is the hash correctly computed, or was it tampered with? | |
| if current.hash != current.compute_hash() { | |
| return false | |
| } | |
| // Does it have the correct prevHash value?; ie: What a previous block tampered with? | |
| if current.prev_hash.as_ref().unwrap() != &previous.hash { | |
| return false | |
| } | |
| } | |
| true | |
| } | |
| pub fn size(&self) -> usize { | |
| self.blocks.len() | |
| } | |
| } | |
| fn main() { | |
| let a = Block::new(Data { | |
| id: 0 | |
| }, None); | |
| let b = Block::new(Data { | |
| id: 0 | |
| }, None); | |
| let mut chain = BlockChain::new(); | |
| chain.add_block(a); // Add block a | |
| chain.add_block(b); // Add block b | |
| println!("Items in chain: {}", chain.size()); | |
| println!("Is valid: {}", chain.is_valid()); | |
| for (i, block) in chain.blocks.iter().enumerate() { | |
| println!("Block[{}]: {:?}", i, block.data); | |
| print!("Hash: 0x"); | |
| for bit in &block.hash { | |
| print!("{:X}", bit); | |
| } | |
| println!(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment