2019-04-12 23:42:43 +00:00
|
|
|
use super::*;
|
2019-04-22 06:58:40 +00:00
|
|
|
use std::cmp::min;
|
2019-04-12 23:42:43 +00:00
|
|
|
|
|
|
|
/// New vec is bigger than old vec.
|
2019-04-13 07:21:50 +00:00
|
|
|
pub fn grow_merkle_cache(
|
2019-04-13 02:12:56 +00:00
|
|
|
old_bytes: &[u8],
|
|
|
|
old_flags: &[bool],
|
|
|
|
from_height: usize,
|
|
|
|
to_height: usize,
|
2019-04-13 07:21:50 +00:00
|
|
|
) -> Option<(Vec<u8>, Vec<bool>)> {
|
2019-04-13 02:12:56 +00:00
|
|
|
// Determine the size of our new tree. It is not just a simple `1 << to_height` as there can be
|
2019-04-14 03:54:04 +00:00
|
|
|
// an arbitrary number of nodes in `old_bytes` leaves if those leaves are subtrees.
|
|
|
|
let to_nodes = {
|
|
|
|
let old_nodes = old_bytes.len() / HASHSIZE;
|
|
|
|
let additional_nodes = old_nodes - nodes_in_tree_of_height(from_height);
|
|
|
|
nodes_in_tree_of_height(to_height) + additional_nodes
|
2019-04-13 02:12:56 +00:00
|
|
|
};
|
2019-04-12 23:42:43 +00:00
|
|
|
|
2019-04-14 03:54:04 +00:00
|
|
|
let mut bytes = vec![0; to_nodes * HASHSIZE];
|
2019-04-13 02:12:56 +00:00
|
|
|
let mut flags = vec![true; to_nodes];
|
2019-04-12 23:42:43 +00:00
|
|
|
|
2019-04-14 03:54:04 +00:00
|
|
|
let leaf_level = from_height;
|
2019-04-12 23:42:43 +00:00
|
|
|
|
2019-04-14 03:54:04 +00:00
|
|
|
for i in 0..=from_height as usize {
|
2019-04-13 02:12:56 +00:00
|
|
|
// If we're on the leaf slice, grab the first byte and all the of the bytes after that.
|
|
|
|
// This is required because we can have an arbitrary number of bytes at the leaf level
|
|
|
|
// (e.g., the case where there are subtrees as leaves).
|
|
|
|
//
|
|
|
|
// If we're not on a leaf level, the number of nodes is fixed and known.
|
2019-04-14 04:20:33 +00:00
|
|
|
let (old_byte_slice, old_flag_slice) = if i == leaf_level {
|
2019-04-13 07:21:50 +00:00
|
|
|
(
|
|
|
|
old_bytes.get(first_byte_at_height(i)..)?,
|
|
|
|
old_flags.get(first_node_at_height(i)..)?,
|
|
|
|
)
|
2019-04-13 02:12:56 +00:00
|
|
|
} else {
|
2019-04-13 07:21:50 +00:00
|
|
|
(
|
|
|
|
old_bytes.get(byte_range_at_height(i))?,
|
2019-04-14 03:54:04 +00:00
|
|
|
old_flags.get(node_range_at_height(i))?,
|
2019-04-13 07:21:50 +00:00
|
|
|
)
|
|
|
|
};
|
2019-04-13 02:12:56 +00:00
|
|
|
|
2019-04-14 04:20:33 +00:00
|
|
|
let new_i = i + to_height - from_height;
|
|
|
|
let (new_byte_slice, new_flag_slice) = if i == leaf_level {
|
|
|
|
(
|
|
|
|
bytes.get_mut(first_byte_at_height(new_i)..)?,
|
|
|
|
flags.get_mut(first_node_at_height(new_i)..)?,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
bytes.get_mut(byte_range_at_height(new_i))?,
|
|
|
|
flags.get_mut(node_range_at_height(new_i))?,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
new_byte_slice
|
|
|
|
.get_mut(0..old_byte_slice.len())?
|
|
|
|
.copy_from_slice(old_byte_slice);
|
|
|
|
new_flag_slice
|
|
|
|
.get_mut(0..old_flag_slice.len())?
|
|
|
|
.copy_from_slice(old_flag_slice);
|
2019-04-12 23:42:43 +00:00
|
|
|
}
|
|
|
|
|
2019-04-13 07:21:50 +00:00
|
|
|
Some((bytes, flags))
|
2019-04-13 03:02:41 +00:00
|
|
|
}
|
|
|
|
|
2019-04-14 06:31:47 +00:00
|
|
|
/// New vec is smaller than old vec.
|
|
|
|
pub fn shrink_merkle_cache(
|
|
|
|
from_bytes: &[u8],
|
|
|
|
from_flags: &[bool],
|
|
|
|
from_height: usize,
|
|
|
|
to_height: usize,
|
|
|
|
to_nodes: usize,
|
|
|
|
) -> Option<(Vec<u8>, Vec<bool>)> {
|
|
|
|
let mut bytes = vec![0; to_nodes * HASHSIZE];
|
|
|
|
let mut flags = vec![true; to_nodes];
|
|
|
|
|
2019-04-14 08:50:12 +00:00
|
|
|
for i in 0..=to_height as usize {
|
2019-04-14 06:31:47 +00:00
|
|
|
let from_i = i + from_height - to_height;
|
2019-04-14 08:50:12 +00:00
|
|
|
|
|
|
|
let (from_byte_slice, from_flag_slice) = if from_i == from_height {
|
2019-04-14 06:31:47 +00:00
|
|
|
(
|
|
|
|
from_bytes.get(first_byte_at_height(from_i)..)?,
|
|
|
|
from_flags.get(first_node_at_height(from_i)..)?,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
from_bytes.get(byte_range_at_height(from_i))?,
|
|
|
|
from_flags.get(node_range_at_height(from_i))?,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2019-04-14 08:50:12 +00:00
|
|
|
let (to_byte_slice, to_flag_slice) = if i == to_height {
|
2019-04-14 06:31:47 +00:00
|
|
|
(
|
|
|
|
bytes.get_mut(first_byte_at_height(i)..)?,
|
|
|
|
flags.get_mut(first_node_at_height(i)..)?,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
bytes.get_mut(byte_range_at_height(i))?,
|
|
|
|
flags.get_mut(node_range_at_height(i))?,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2019-04-22 06:58:40 +00:00
|
|
|
let num_bytes = min(from_byte_slice.len(), to_byte_slice.len());
|
|
|
|
let num_flags = min(from_flag_slice.len(), to_flag_slice.len());
|
|
|
|
|
|
|
|
to_byte_slice
|
|
|
|
.get_mut(0..num_bytes)?
|
|
|
|
.copy_from_slice(from_byte_slice.get(0..num_bytes)?);
|
|
|
|
to_flag_slice
|
|
|
|
.get_mut(0..num_flags)?
|
|
|
|
.copy_from_slice(from_flag_slice.get(0..num_flags)?);
|
2019-04-14 06:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Some((bytes, flags))
|
|
|
|
}
|
|
|
|
|
2019-04-14 03:54:04 +00:00
|
|
|
fn nodes_in_tree_of_height(h: usize) -> usize {
|
|
|
|
2 * (1 << h) - 1
|
|
|
|
}
|
|
|
|
|
2019-04-13 02:12:56 +00:00
|
|
|
fn byte_range_at_height(h: usize) -> Range<usize> {
|
2019-04-14 03:54:04 +00:00
|
|
|
let node_range = node_range_at_height(h);
|
|
|
|
node_range.start * HASHSIZE..node_range.end * HASHSIZE
|
2019-04-13 02:12:56 +00:00
|
|
|
}
|
|
|
|
|
2019-04-13 07:21:50 +00:00
|
|
|
fn node_range_at_height(h: usize) -> Range<usize> {
|
2019-04-14 03:54:04 +00:00
|
|
|
first_node_at_height(h)..last_node_at_height(h) + 1
|
2019-04-13 07:21:50 +00:00
|
|
|
}
|
|
|
|
|
2019-04-13 02:12:56 +00:00
|
|
|
fn first_byte_at_height(h: usize) -> usize {
|
|
|
|
first_node_at_height(h) * HASHSIZE
|
|
|
|
}
|
|
|
|
|
|
|
|
fn first_node_at_height(h: usize) -> usize {
|
|
|
|
(1 << h) - 1
|
|
|
|
}
|
|
|
|
|
|
|
|
fn last_node_at_height(h: usize) -> usize {
|
2019-04-14 03:54:04 +00:00
|
|
|
(1 << (h + 1)) - 2
|
2019-04-13 02:12:56 +00:00
|
|
|
}
|
|
|
|
|
2019-04-12 23:42:43 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2019-04-13 02:12:56 +00:00
|
|
|
use super::*;
|
|
|
|
|
2019-04-12 23:42:43 +00:00
|
|
|
#[test]
|
2019-04-14 06:31:47 +00:00
|
|
|
fn can_grow_and_shrink_three_levels() {
|
|
|
|
let small: usize = 1;
|
|
|
|
let big: usize = 15;
|
|
|
|
|
|
|
|
let original_bytes = vec![42; small * HASHSIZE];
|
|
|
|
let original_flags = vec![false; small];
|
|
|
|
|
|
|
|
let (grown_bytes, grown_flags) = grow_merkle_cache(
|
|
|
|
&original_bytes,
|
|
|
|
&original_flags,
|
|
|
|
(small + 1).trailing_zeros() as usize - 1,
|
|
|
|
(big + 1).trailing_zeros() as usize - 1,
|
2019-04-13 07:21:50 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let mut expected_bytes = vec![];
|
|
|
|
let mut expected_flags = vec![];
|
|
|
|
// First level
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(true);
|
|
|
|
// Second level
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
// Third level
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
// Fourth level
|
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
|
2019-04-14 06:31:47 +00:00
|
|
|
assert_eq!(expected_bytes, grown_bytes);
|
|
|
|
assert_eq!(expected_flags, grown_flags);
|
|
|
|
|
|
|
|
let (shrunk_bytes, shrunk_flags) = shrink_merkle_cache(
|
|
|
|
&grown_bytes,
|
|
|
|
&grown_flags,
|
|
|
|
(big + 1).trailing_zeros() as usize - 1,
|
|
|
|
(small + 1).trailing_zeros() as usize - 1,
|
|
|
|
small,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_eq!(original_bytes, shrunk_bytes);
|
|
|
|
assert_eq!(original_flags, shrunk_flags);
|
2019-04-13 07:21:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2019-04-14 06:31:47 +00:00
|
|
|
fn can_grow_and_shrink_one_level() {
|
|
|
|
let small: usize = 7;
|
|
|
|
let big: usize = 15;
|
|
|
|
|
|
|
|
let original_bytes = vec![42; small * HASHSIZE];
|
|
|
|
let original_flags = vec![false; small];
|
|
|
|
|
|
|
|
let (grown_bytes, grown_flags) = grow_merkle_cache(
|
|
|
|
&original_bytes,
|
|
|
|
&original_flags,
|
|
|
|
(small + 1).trailing_zeros() as usize - 1,
|
|
|
|
(big + 1).trailing_zeros() as usize - 1,
|
2019-04-13 02:12:56 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
2019-04-13 07:21:50 +00:00
|
|
|
let mut expected_bytes = vec![];
|
|
|
|
let mut expected_flags = vec![];
|
2019-04-13 02:12:56 +00:00
|
|
|
// First level
|
2019-04-13 07:21:50 +00:00
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(true);
|
2019-04-13 02:12:56 +00:00
|
|
|
// Second level
|
2019-04-13 07:21:50 +00:00
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(true);
|
2019-04-13 02:12:56 +00:00
|
|
|
// Third level
|
2019-04-13 07:21:50 +00:00
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
2019-04-13 02:12:56 +00:00
|
|
|
// Fourth level
|
2019-04-13 07:21:50 +00:00
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![42; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_bytes.append(&mut vec![0; 32]);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(false);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
expected_flags.push(true);
|
|
|
|
|
2019-04-14 06:31:47 +00:00
|
|
|
assert_eq!(expected_bytes, grown_bytes);
|
|
|
|
assert_eq!(expected_flags, grown_flags);
|
|
|
|
|
|
|
|
let (shrunk_bytes, shrunk_flags) = shrink_merkle_cache(
|
|
|
|
&grown_bytes,
|
|
|
|
&grown_flags,
|
|
|
|
(big + 1).trailing_zeros() as usize - 1,
|
|
|
|
(small + 1).trailing_zeros() as usize - 1,
|
|
|
|
small,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_eq!(original_bytes, shrunk_bytes);
|
|
|
|
assert_eq!(original_flags, shrunk_flags);
|
2019-04-12 23:42:43 +00:00
|
|
|
}
|
|
|
|
}
|