diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-10-21 20:41:50 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-10-21 21:14:12 +0800 |
| commit | ec257dc4496f4dd9f7b6a5a6cea033ee81206673 (patch) | |
| tree | 3fa4a04e9a03d12f088509a057ba4e3d2cab28a5 /src | |
| parent | 0ca3804ac22491ce00ef5391abef40a8444ff814 (diff) | |
refactor(blocks): use sha256
Diffstat (limited to 'src')
| -rw-r--r-- | src/blocks.rs | 103 | ||||
| -rw-r--r-- | src/client.rs | 3 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/network.rs | 18 | ||||
| -rw-r--r-- | src/transaction.rs | 3 |
5 files changed, 70 insertions, 59 deletions
diff --git a/src/blocks.rs b/src/blocks.rs index 1fa8486..17e6d4f 100644 --- a/src/blocks.rs +++ b/src/blocks.rs @@ -1,5 +1,7 @@ +use bincode::Encode; +use sha2::{Digest, Sha256, digest::DynDigest}; use std::{ - hash::{DefaultHasher, Hash, Hasher}, + hash::{Hash, Hasher}, ops::Deref, }; @@ -7,68 +9,69 @@ use serde::{Deserialize, Serialize}; use crate::{ZERO_PREFIX_AMOUNT, transaction::Transaction}; -#[derive(Deserialize, Serialize, Clone, Copy, PartialEq)] +pub trait CryptoDigest { + fn digest(&self, state: &mut impl DynDigest); +} + +#[derive(Deserialize, Serialize, Clone, PartialEq, Encode)] pub struct Block { - pub prev_hash: u64, + pub prev_hash: Vec<u8>, pub trans: Transaction, - pub pow: Option<u64>, + pub pow: Vec<u8>, } impl Block { - fn new(prev_hash: Option<u64>, trans: Transaction) -> Self { + fn new(prev_hash: Option<&[u8]>, trans: Transaction) -> Self { Self { - prev_hash: prev_hash.unwrap_or(0), // special blocks + prev_hash: prev_hash + .unwrap_or(&[]) + .to_vec(), // special blocks trans, - pow: None, + pow: Vec::default(), } } - fn calc_pow(&self) -> u64 { + fn pref_zeros(hashed: &[u8]) -> Result<usize, usize> { + hashed + .iter() + .try_fold(0, |nonce, x| { + if nonce >= ZERO_PREFIX_AMOUNT { + Ok(nonce) + } else if *x == 0 { + Ok(nonce + 1) + } else { + Err(nonce) + } + }) + } + + fn calc_pow(&self) -> Vec<u8> { for i in 0.. { // reset every loop - let mut hasher = DefaultHasher::new(); - (&self.prev_hash, &self.trans, i).hash(&mut hasher); - let hashed = hasher.finish(); - if hashed - .to_string() - .starts_with( - &"0".repeat(ZERO_PREFIX_AMOUNT) - .to_string(), - ) - { - return hashed; + let mut hasher = Sha256::new(); + Digest::update(&mut hasher, bincode::encode_to_vec((&self.prev_hash, &self.trans, i), bincode::config::standard()).unwrap()); + let hashed = hasher.finalize(); + if Self::pref_zeros(&hashed).is_ok() { + return hashed.to_vec(); } } unreachable!() } pub fn verify_pow(&mut self) -> bool { - let mut hasher = DefaultHasher::new(); - self.hash(&mut hasher); - hasher - .finish() - .to_string() - .to_string() - .starts_with( - &"0".repeat(ZERO_PREFIX_AMOUNT) - .to_string(), - ) + let mut hasher = Sha256::new(); + Digest::update(&mut hasher, bincode::encode_to_vec(&*self, bincode::config::standard()).unwrap()); + Self::pref_zeros(&hasher.finalize()).is_ok() } pub fn calc_set_pow(&mut self) { - self.pow = Some(self.calc_pow()); + self.pow = self.calc_pow(); } } -impl Hash for Block { - fn hash<H: Hasher>(&self, state: &mut H) { - self.prev_hash - .hash(state); - self.trans - .hash(state); - self.pow - .expect("Cannot hash whole block with no PoW") - .hash(state); +impl CryptoDigest for Block { + fn digest(&self, state: &mut impl DynDigest) { + state.update(&bincode::encode_to_vec((&self.prev_hash, &self.trans, &self.pow), bincode::config::standard()).unwrap()); } } @@ -85,16 +88,17 @@ impl BlockChain { } pub fn new_block(&self, trans: Transaction) -> Block { - let mut hasher = DefaultHasher::new(); - Block::new( - self.blocks - .last() - .map(|b| { - b.hash(&mut hasher); - hasher.finish() - }), - trans, - ) + let mut hasher = Sha256::new(); + let prev = self + .blocks + .last(); + let prev_hash = if let Some(b) = prev { + b.digest(&mut hasher); + Some(&*hasher.finalize()) + } else { + None + }; + Block::new(prev_hash, trans) } pub fn store(&mut self, block: Block) { @@ -106,6 +110,7 @@ impl BlockChain { impl Deref for BlockChain { type Target = Vec<Block>; + fn deref(&self) -> &Self::Target { &self.blocks } diff --git a/src/client.rs b/src/client.rs index 457a70d..eb417fd 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,7 +1,8 @@ +use bincode::Encode; use rand::Rng; use serde::{Deserialize, Serialize}; -#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq)] +#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Encode)] pub struct Client { id: u32, } @@ -6,4 +6,4 @@ pub mod client; pub mod network; -const ZERO_PREFIX_AMOUNT: usize = 5; // TODO: make this dynamic +const ZERO_PREFIX_AMOUNT: usize = 2; // TODO: make this dynamic diff --git a/src/network.rs b/src/network.rs index 753f743..c18ae07 100644 --- a/src/network.rs +++ b/src/network.rs @@ -75,7 +75,7 @@ impl Network { let peer = Arc::new(Mutex::new(Peer::new( self.this .clone(), - TcpStream::connect("192.168.143.90:6767") + TcpStream::connect("192.168.1.16:6767") .await .unwrap(), ))); @@ -222,8 +222,11 @@ impl Peer { async fn handle(parent: Weak<Mutex<Network>>, req: Request) { match req { - Request::Block(mut block) => match block.pow { - Some(_pow) => { + Request::Block(mut block) => { + if !block + .pow + .is_empty() + { if !block.verify_pow() { eprintln!("Rejecting remote block, POW verification failed"); // TODO: log remote IP return; @@ -237,8 +240,8 @@ impl Peer { .lock() .await .store(block) - } - None => { + } else { + print!("as"); block.calc_set_pow(); let parent = parent .upgrade() @@ -250,7 +253,7 @@ impl Peer { .broadcast(Request::Block(block)) .await; } - }, + } Request::Ibd(bc) => match bc { Some(bc) => { let parent = parent @@ -267,10 +270,11 @@ impl Peer { || (self_bc .blocks .iter() + // TODO: Optimize via try_fold .fold(true, |i, b| { if i { b.pow - .is_none() + .is_empty() } else { false } diff --git a/src/transaction.rs b/src/transaction.rs index dcaff49..760f080 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,8 +1,9 @@ +use bincode::Encode; use serde::{Deserialize, Serialize}; use crate::client::Client; -#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq)] +#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Encode)] pub struct Transaction { from: Client, to: Client, |
