chore: implement recalculate tree function

This commit is contained in:
Magamedrasul Ibragimov 2022-10-30 23:12:58 +03:00
parent b08d1710a0
commit b032d03f53
2 changed files with 47 additions and 8 deletions

View File

@ -4,7 +4,7 @@
//! ## How it stored //! ## How it stored
//! { (usize::MAX - 1) : depth } //! { (usize::MAX - 1) : depth }
//! { (usize::MAX) : next_index} //! { (usize::MAX) : next_index}
//! { Position (tuple, converted to DBKey) : Value} //! { Position (tuple - (depth, index), converted to DBKey) : Value}
pub mod database; pub mod database;
pub mod hasher; pub mod hasher;

View File

@ -8,6 +8,7 @@ const DEPTH_KEY: DBKey = (usize::MAX - 1).to_be_bytes();
const NEXT_INDEX_KEY: DBKey = usize::MAX.to_be_bytes(); const NEXT_INDEX_KEY: DBKey = usize::MAX.to_be_bytes();
// Denotes keys (depth, index) in Merkle Tree. Can be converted to DBKey // Denotes keys (depth, index) in Merkle Tree. Can be converted to DBKey
#[derive(Clone, Copy)]
struct Key(usize, usize); struct Key(usize, usize);
impl From<Key> for DBKey { impl From<Key> for DBKey {
fn from(key: Key) -> DBKey { fn from(key: Key) -> DBKey {
@ -26,6 +27,7 @@ where
h: PhantomData<H>, h: PhantomData<H>,
depth: usize, depth: usize,
next_index: usize, next_index: usize,
cache: Vec<H::Fr>,
} }
impl<D, H> MerkleTree<D, H> impl<D, H> MerkleTree<D, H>
@ -47,12 +49,15 @@ where
let next_index_val = next_index.to_be_bytes().to_vec(); let next_index_val = next_index.to_be_bytes().to_vec();
db.put(NEXT_INDEX_KEY, next_index_val); db.put(NEXT_INDEX_KEY, next_index_val);
// Cache nodes
let mut cache = Vec::with_capacity(depth + 1);
// Initialize one branch of the `Merkle Tree` from bottom to top // Initialize one branch of the `Merkle Tree` from bottom to top
let mut prev = H::default_leaf(); cache[depth] = H::default_leaf();
db.put(Key(depth, 0).into(), prev.into()); db.put(Key(depth, 0).into(), cache[depth].into());
for i in (0..depth).rev() { for i in (0..depth).rev() {
prev = H::hash(&[prev, prev]); cache[i] = H::hash(&[cache[i + 1], cache[i + 1]]);
db.put(Key(i, 0).into(), prev.into()); db.put(Key(i, 0).into(), cache[i].into());
} }
Self { Self {
@ -60,6 +65,7 @@ where
h: PhantomData, h: PhantomData,
depth, depth,
next_index, next_index,
cache,
} }
} }
@ -69,18 +75,25 @@ where
let db = D::load(dbpath); let db = D::load(dbpath);
// Load depth & next_index values from db // Load depth & next_index values from db
// TODO: proper handling instead of unwrap
let depth = db.get(DEPTH_KEY).unwrap().try_into().unwrap(); let depth = db.get(DEPTH_KEY).unwrap().try_into().unwrap();
let depth = usize::from_be_bytes(depth); let depth = usize::from_be_bytes(depth);
let next_index = db.get(NEXT_INDEX_KEY).unwrap().try_into().unwrap(); let next_index = db.get(NEXT_INDEX_KEY).unwrap().try_into().unwrap();
let next_index = usize::from_be_bytes(next_index); let next_index = usize::from_be_bytes(next_index);
// Load cache vec
let mut cache = Vec::with_capacity(depth + 1);
cache[depth] = H::default_leaf();
for i in (0..depth).rev() {
cache[i] = H::hash(&[cache[i + 1], cache[i + 1]]);
}
Self { Self {
db, db,
h: PhantomData, h: PhantomData,
depth, depth,
next_index, next_index,
cache,
} }
} }
@ -111,12 +124,38 @@ where
/// Sets a leaf at the specified tree index /// Sets a leaf at the specified tree index
fn set(&mut self, key: usize, leaf: H::Fr) { fn set(&mut self, key: usize, leaf: H::Fr) {
todo!() self.db.put(Key(self.depth, key).into(), leaf.into());
self.recalculate_from(key);
} }
// Recalculates `Merkle Tree` from the specified key // Recalculates `Merkle Tree` from the specified key
fn recalculate_from(&mut self, key: usize) { fn recalculate_from(&mut self, key: usize) {
todo!() let mut depth = self.depth;
let mut i = key;
while depth != 0 {
let value = self.hash_couple(depth, key);
i >>= 1;
depth -= 1;
self.db.put(Key(depth, i).into(), value.into());
}
}
// Hashes the right couple for the key
fn hash_couple(&mut self, depth: usize, key: usize) -> H::Fr {
let b = key & !1;
H::hash(&[
self.get_elem(Key(depth, b)),
self.get_elem(Key(depth, b + 1)),
])
}
// Returns elem by the key
fn get_elem(&self, key: Key) -> H::Fr {
self.db
.get(key.into())
.unwrap_or_else(|| self.cache[key.0].into())
.into()
} }
/// Returns the root of the tree /// Returns the root of the tree