summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2025-10-21 20:41:50 +0800
committerlittleblack111 <littleblack11111@gmail.com>2025-10-21 21:14:12 +0800
commitec257dc4496f4dd9f7b6a5a6cea033ee81206673 (patch)
tree3fa4a04e9a03d12f088509a057ba4e3d2cab28a5 /src
parent0ca3804ac22491ce00ef5391abef40a8444ff814 (diff)
refactor(blocks): use sha256
Diffstat (limited to 'src')
-rw-r--r--src/blocks.rs103
-rw-r--r--src/client.rs3
-rw-r--r--src/lib.rs2
-rw-r--r--src/network.rs18
-rw-r--r--src/transaction.rs3
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,
}
diff --git a/src/lib.rs b/src/lib.rs
index 0545aa5..9cdbdcd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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,