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 } }