Skip to content

Instantly share code, notes, and snippets.

@Jackzmc
Created June 26, 2021 00:10
Show Gist options
  • Select an option

  • Save Jackzmc/4590d58519ca99f0a25246dd6ee491bf to your computer and use it in GitHub Desktop.

Select an option

Save Jackzmc/4590d58519ca99f0a25246dd6ee491bf to your computer and use it in GitHub Desktop.
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(&timestamp.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