diff options
| -rw-r--r-- | src/hash_chain.rs | 71 | ||||
| -rw-r--r-- | src/lib.rs | 2 |
2 files changed, 73 insertions, 0 deletions
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<T: Encode> { + data: Vec<(Vec<u8>, T)>, // Vector of (hash, value) pairs +} + +impl<T: Encode> HashChain<T> { + 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<u8> { + 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<T: Encode> Deref for HashChain<T> { + type Target = Vec<(Vec<u8>, T)>; + + fn deref(&self) -> &Self::Target { + &self.data + } +} @@ -1,3 +1,5 @@ +pub mod hash_chain; + pub mod blocks; pub mod transaction; |
