mirror of
https://gitlab.com/pulsechaincom/lighthouse-pulse.git
synced 2024-12-25 21:17:17 +00:00
Make tree hash pass tests
This commit is contained in:
parent
e33d1d0ebb
commit
acb1dd47cd
@ -10,6 +10,7 @@ pub struct TreeHashCache<'a> {
|
|||||||
chunk_offset: usize,
|
chunk_offset: usize,
|
||||||
cache: &'a mut [u8],
|
cache: &'a mut [u8],
|
||||||
chunk_modified: &'a mut [bool],
|
chunk_modified: &'a mut [bool],
|
||||||
|
hash_count: &'a mut usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TreeHashCache<'a> {
|
impl<'a> TreeHashCache<'a> {
|
||||||
@ -17,17 +18,20 @@ impl<'a> TreeHashCache<'a> {
|
|||||||
vec![false; bytes.len() / BYTES_PER_CHUNK]
|
vec![false; bytes.len() / BYTES_PER_CHUNK]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_mut_slice(bytes: &'a mut [u8], changes: &'a mut [bool]) -> Option<Self> {
|
pub fn from_mut_slice(
|
||||||
|
bytes: &'a mut [u8],
|
||||||
|
changes: &'a mut [bool],
|
||||||
|
hash_count: &'a mut usize,
|
||||||
|
) -> Option<Self> {
|
||||||
if bytes.len() % BYTES_PER_CHUNK > 0 {
|
if bytes.len() % BYTES_PER_CHUNK > 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let chunk_modified = vec![false; bytes.len() / BYTES_PER_CHUNK];
|
|
||||||
|
|
||||||
Some(Self {
|
Some(Self {
|
||||||
chunk_offset: 0,
|
chunk_offset: 0,
|
||||||
cache: bytes,
|
cache: bytes,
|
||||||
chunk_modified: changes,
|
chunk_modified: changes,
|
||||||
|
hash_count,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,12 +40,13 @@ impl<'a> TreeHashCache<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn modify_current_chunk(&mut self, to: &[u8]) -> Option<()> {
|
pub fn modify_current_chunk(&mut self, to: &[u8]) -> Option<()> {
|
||||||
self.modify_chunk(0, to)
|
self.modify_chunk(self.chunk_offset, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn modify_chunk(&mut self, chunk: usize, to: &[u8]) -> Option<()> {
|
pub fn modify_chunk(&mut self, chunk: usize, to: &[u8]) -> Option<()> {
|
||||||
let start = chunk * BYTES_PER_CHUNK;
|
let start = chunk * BYTES_PER_CHUNK;
|
||||||
let end = start + BYTES_PER_CHUNK;
|
let end = start + BYTES_PER_CHUNK;
|
||||||
|
|
||||||
self.cache.get_mut(start..end)?.copy_from_slice(to);
|
self.cache.get_mut(start..end)?.copy_from_slice(to);
|
||||||
|
|
||||||
self.chunk_modified[chunk] = true;
|
self.chunk_modified[chunk] = true;
|
||||||
@ -79,9 +84,10 @@ impl<'a> TreeHashCache<'a> {
|
|||||||
let modified_end = modified_start + leaves;
|
let modified_end = modified_start + leaves;
|
||||||
|
|
||||||
Some(TreeHashCache {
|
Some(TreeHashCache {
|
||||||
chunk_offset: self.chunk_offset + internal,
|
chunk_offset: 0,
|
||||||
cache: self.cache.get_mut(leaves_start..leaves_end)?,
|
cache: self.cache.get_mut(leaves_start..leaves_end)?,
|
||||||
chunk_modified: self.chunk_modified.get_mut(modified_start..modified_end)?,
|
chunk_modified: self.chunk_modified.get_mut(modified_start..modified_end)?,
|
||||||
|
hash_count: self.hash_count,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +117,8 @@ impl CachedTreeHash for u64 {
|
|||||||
|
|
||||||
fn cached_hash_tree_root(&self, other: &Self, cache: &mut TreeHashCache) -> Option<()> {
|
fn cached_hash_tree_root(&self, other: &Self, cache: &mut TreeHashCache) -> Option<()> {
|
||||||
if self != other {
|
if self != other {
|
||||||
cache.modify_current_chunk(&merkleize(&int_to_bytes32(*self)));
|
*cache.hash_count += 1;
|
||||||
|
cache.modify_current_chunk(&merkleize(&int_to_bytes32(*self)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.increment();
|
cache.increment();
|
||||||
@ -156,6 +163,7 @@ impl CachedTreeHash for Inner {
|
|||||||
|
|
||||||
for chunk in (0..internal_chunks).into_iter().rev() {
|
for chunk in (0..internal_chunks).into_iter().rev() {
|
||||||
if cache.children_modified(chunk)? {
|
if cache.children_modified(chunk)? {
|
||||||
|
*cache.hash_count += 1;
|
||||||
cache.modify_chunk(chunk, &cache.hash_children(chunk)?)?;
|
cache.modify_chunk(chunk, &cache.hash_children(chunk)?)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +205,7 @@ pub fn merkleize(values: &[u8]) -> Vec<u8> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn join(many: Vec<&[u8]>) -> Vec<u8> {
|
fn join(many: Vec<Vec<u8>>) -> Vec<u8> {
|
||||||
let mut all = vec![];
|
let mut all = vec![];
|
||||||
for one in many {
|
for one in many {
|
||||||
all.extend_from_slice(&mut one.clone())
|
all.extend_from_slice(&mut one.clone())
|
||||||
@ -205,8 +213,7 @@ mod tests {
|
|||||||
all
|
all
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn generic_test(index: usize) {
|
||||||
fn cached_hash_on_inner() {
|
|
||||||
let inner = Inner {
|
let inner = Inner {
|
||||||
a: 1,
|
a: 1,
|
||||||
b: 2,
|
b: 2,
|
||||||
@ -216,37 +223,69 @@ mod tests {
|
|||||||
|
|
||||||
let mut cache = inner.build_cache_bytes();
|
let mut cache = inner.build_cache_bytes();
|
||||||
|
|
||||||
let changed_inner = Inner {
|
let changed_inner = match index {
|
||||||
a: 42,
|
0 => Inner {
|
||||||
..inner.clone()
|
a: 42,
|
||||||
|
..inner.clone()
|
||||||
|
},
|
||||||
|
1 => Inner {
|
||||||
|
b: 42,
|
||||||
|
..inner.clone()
|
||||||
|
},
|
||||||
|
2 => Inner {
|
||||||
|
c: 42,
|
||||||
|
..inner.clone()
|
||||||
|
},
|
||||||
|
3 => Inner {
|
||||||
|
d: 42,
|
||||||
|
..inner.clone()
|
||||||
|
},
|
||||||
|
_ => panic!("bad index"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut changes = TreeHashCache::build_changes_vec(&cache);
|
let mut changes = TreeHashCache::build_changes_vec(&cache);
|
||||||
let mut cache_struct = TreeHashCache::from_mut_slice(&mut cache, &mut changes).unwrap();
|
let mut hash_count = 0;
|
||||||
|
let mut cache_struct =
|
||||||
|
TreeHashCache::from_mut_slice(&mut cache, &mut changes, &mut hash_count).unwrap();
|
||||||
|
|
||||||
changed_inner.cached_hash_tree_root(&inner, &mut cache_struct);
|
changed_inner
|
||||||
|
.cached_hash_tree_root(&inner, &mut cache_struct)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(*cache_struct.hash_count, 3);
|
||||||
|
|
||||||
let new_cache = cache_struct.into_slice();
|
let new_cache = cache_struct.into_slice();
|
||||||
|
|
||||||
let data1 = &int_to_bytes32(42);
|
let data1 = int_to_bytes32(1);
|
||||||
let data2 = &int_to_bytes32(2);
|
let data2 = int_to_bytes32(2);
|
||||||
let data3 = &int_to_bytes32(3);
|
let data3 = int_to_bytes32(3);
|
||||||
let data4 = &int_to_bytes32(4);
|
let data4 = int_to_bytes32(4);
|
||||||
|
|
||||||
let data = join(vec![&data1, &data2, &data3, &data4]);
|
let mut data = vec![data1, data2, data3, data4];
|
||||||
let expected = merkleize(&data);
|
|
||||||
|
data[index] = int_to_bytes32(42);
|
||||||
|
|
||||||
|
let expected = merkleize(&join(data));
|
||||||
|
|
||||||
assert_eq!(expected, new_cache);
|
assert_eq!(expected, new_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn build_cache_matches_merkelize() {
|
fn cached_hash_on_inner() {
|
||||||
let data1 = &int_to_bytes32(1);
|
generic_test(0);
|
||||||
let data2 = &int_to_bytes32(2);
|
generic_test(1);
|
||||||
let data3 = &int_to_bytes32(3);
|
generic_test(2);
|
||||||
let data4 = &int_to_bytes32(4);
|
generic_test(3);
|
||||||
|
}
|
||||||
|
|
||||||
let data = join(vec![&data1, &data2, &data3, &data4]);
|
#[test]
|
||||||
|
fn build_cache_matches_merkelize() {
|
||||||
|
let data1 = int_to_bytes32(1);
|
||||||
|
let data2 = int_to_bytes32(2);
|
||||||
|
let data3 = int_to_bytes32(3);
|
||||||
|
let data4 = int_to_bytes32(4);
|
||||||
|
|
||||||
|
let data = join(vec![data1, data2, data3, data4]);
|
||||||
let expected = merkleize(&data);
|
let expected = merkleize(&data);
|
||||||
|
|
||||||
let inner = Inner {
|
let inner = Inner {
|
||||||
@ -268,7 +307,12 @@ mod tests {
|
|||||||
let data3 = hash(&int_to_bytes32(3));
|
let data3 = hash(&int_to_bytes32(3));
|
||||||
let data4 = hash(&int_to_bytes32(4));
|
let data4 = hash(&int_to_bytes32(4));
|
||||||
|
|
||||||
let data = join(vec![&data1, &data2, &data3, &data4]);
|
let data = join(vec![
|
||||||
|
data1.clone(),
|
||||||
|
data2.clone(),
|
||||||
|
data3.clone(),
|
||||||
|
data4.clone(),
|
||||||
|
]);
|
||||||
|
|
||||||
let cache = merkleize(&data);
|
let cache = merkleize(&data);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user