summaryrefslogtreecommitdiff
path: root/src/hash_chain.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/hash_chain.rs')
-rw-r--r--src/hash_chain.rs79
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> {