diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-10-22 14:54:46 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-10-23 22:00:56 +0800 |
| commit | 9b2dcd8bae4021d692ba5f44194d2020d736012b (patch) | |
| tree | 78712d47c0fac63d7433ab1c560b14f4e63752af /src | |
| parent | bb1e8a814aa3b1846e51f0d1a6c344af94228e96 (diff) | |
refactor: hash_chain
Diffstat (limited to 'src')
| -rw-r--r-- | src/hash_chain.rs | 79 |
1 files changed, 60 insertions, 19 deletions
diff --git a/src/hash_chain.rs b/src/hash_chain.rs index b87ac61..4a37c67 100644 --- a/src/hash_chain.rs +++ b/src/hash_chain.rs @@ -35,48 +35,89 @@ impl<T: Encode> HashChain<T> { }) .unwrap_or_default(); self.data - .push((Self::hash(&prev_hash, &data), data)); + .push((Self::with_hash((&prev_hash, &data)), data)); } - fn insert(&mut self, data: T, base_hash: &[u8]) { + // TODO: make try_last that does same as this but returns Err() if it's not the + // last one and/or refuse to insert + fn insert(&mut self, data: T, base_hash: &Vec<u8>) { let pos = self .data .iter() - .position(|x| x.0 == base_hash) + .position(|x| x.0 == *base_hash) .unwrap(); self.data - .insert(pos, (Self::hash(base_hash, &data), data)); + .insert(pos + 1, (Self::with_hash((base_hash, &data)), data)); + + // everything after that hash is invalidated + self.rehash(&base_hash); + } + + fn verify(&self, until_hash: &[u8]) -> bool { + let pos = self + .data + .iter() + .position(|x| x.0 == until_hash) + .unwrap(); + self.data[pos..=1] + .iter() + .enumerate() + .all(|(prev_hash, (pred_prev_hash, _))| { + let prev_hash = Self::with_hash({ + let prev_hash = &self.data[prev_hash - 1]; + (&prev_hash.0, &prev_hash.1) + }); + prev_hash == *pred_prev_hash + }) } - fn verify(&self, from_hash: &[u8]) -> bool { - let i = self + fn rehash(&mut self, from_hash: &[u8]) { + let pos = self .data .iter() - .position(|x| x.0 == from_hash) + .position(|x| x.0 == *from_hash) .unwrap(); - (i..self + + let prev_hashes: Vec<_> = (pos..self .data .len()) - .all(|i| { - Self::hash( - if i == 0 { - &[] - } else { - &self.data[i - 1].0 - }, - &self.data[i].1, - ) == self.data[i].0 + .map(|i| { + Self::with_hash({ + let prev_hash = &self.data[i - 1]; + (&prev_hash.0, &prev_hash.1) + }) }) + .collect(); + + self.data[pos..] + .iter_mut() + .enumerate() + .map(|(idx, item)| (item, prev_hashes[idx].clone())) + .for_each(|((pred_prev_hash, _), prev_hash)| { + if prev_hash != *pred_prev_hash { + *pred_prev_hash = prev_hash; + } + }); } - fn hash(prev_hash: &[u8], data: &T) -> Vec<u8> { + fn with_hash(data: (&Vec<u8>, &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() } + + fn hash_last(&self) -> Vec<u8> { + Self::with_hash({ + let last = self + .data + .iter() + .last() + .unwrap(); + (&last.0, &last.1) + }) + } } impl<T: Encode> Deref for HashChain<T> { |
