From a54046f51ec00aab7a4f3a35e67b7422d92db98b Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Wed, 22 Oct 2025 11:37:35 +0800 Subject: feat: actual hash_chain --- src/hash_chain.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 2 files changed, 73 insertions(+) create mode 100644 src/hash_chain.rs diff --git a/src/hash_chain.rs b/src/hash_chain.rs new file mode 100644 index 0000000..2079e1c --- /dev/null +++ b/src/hash_chain.rs @@ -0,0 +1,71 @@ +use std::ops::Deref; + +use bincode::Encode; +use sha2::{Digest, Sha256}; + +pub struct HashChain { + data: Vec<(Vec, T)>, // Vector of (hash, value) pairs +} + +impl HashChain { + fn push(&mut self, data: T) { + let prev_hash = self + .data + .last() + .map(|p| { + p.0.clone() + }) + .unwrap_or_default(); + self.data + .push((Self::hash(&prev_hash, &data), data)); + } + + fn insert(&mut self, data: T, base_hash: &[u8]) { + let pos = self + .data + .iter() + .position(|x| x.0 == base_hash) + .unwrap(); + self.data + .insert(pos, (Self::hash(base_hash, &data), data)); + } + + fn verify(&self, from_hash: &[u8]) -> bool { + let start_idx = self + .data + .iter() + .position(|x| x.0 == from_hash) + .unwrap(); + (start_idx + ..self + .data + .len()) + .all(|i| { + Self::hash( + if i == 0 { + &Vec::default() + } else { + &self.data[i - 1].0 + }, + &self.data[i].1, + ) == self.data[i].0 + }) + } + + fn hash(prev_hash: &[u8], data: &T) -> Vec { + let mut hasher = Sha256::new(); + hasher.update(prev_hash); + hasher.update(bincode::encode_to_vec(data, bincode::config::standard()).unwrap()); + hasher + .finalize() + .to_vec() + } +} + +impl Deref for HashChain { + type Target = Vec<(Vec, T)>; + + fn deref(&self) -> &Self::Target { + &self.data + } +} diff --git a/src/lib.rs b/src/lib.rs index 9cdbdcd..1ee9fc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +pub mod hash_chain; + pub mod blocks; pub mod transaction; -- cgit v1.2.3