(cherry picked from commit 2dc6969858
)
# Conflicts:
# runtime/src/accounts_hash.rs
Co-authored-by: Jeff Washington (jwash) <wash678@gmail.com>
This commit is contained in:
@ -108,6 +108,22 @@ impl CumulativeOffset {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ExtractSliceFromRawData<'b, T: 'b> {
|
||||
fn extract<'a>(&'b self, offset: &'a CumulativeOffset, start: usize) -> &'b [T];
|
||||
}
|
||||
|
||||
impl<'b, T: 'b> ExtractSliceFromRawData<'b, T> for Vec<Vec<T>> {
|
||||
fn extract<'a>(&'b self, offset: &'a CumulativeOffset, start: usize) -> &'b [T] {
|
||||
&self[offset.index[0]][start..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, T: 'b> ExtractSliceFromRawData<'b, T> for Vec<Vec<Vec<T>>> {
|
||||
fn extract<'a>(&'b self, offset: &'a CumulativeOffset, start: usize) -> &'b [T] {
|
||||
&self[offset.index[0]][offset.index[1]][start..]
|
||||
}
|
||||
}
|
||||
|
||||
// Allow retrieving &[start..end] from a logical src: Vec<T>, where src is really Vec<Vec<T>> (or later Vec<Vec<Vec<T>>>)
|
||||
// This model prevents callers from having to flatten which saves both working memory and time.
|
||||
#[derive(Default, Debug)]
|
||||
@ -163,32 +179,28 @@ impl CumulativeOffsets {
|
||||
}
|
||||
}
|
||||
|
||||
fn find(&self, start: usize) -> (usize, &CumulativeOffset) {
|
||||
fn find_index(&self, start: usize) -> usize {
|
||||
assert!(!self.cumulative_offsets.is_empty());
|
||||
let index = match self.cumulative_offsets[..]
|
||||
.binary_search_by(|index| index.start_offset.cmp(&start))
|
||||
{
|
||||
match self.cumulative_offsets[..].binary_search_by(|index| index.start_offset.cmp(&start)) {
|
||||
Ok(index) => index,
|
||||
Err(index) => index - 1, // we would insert at index so we are before the item at index
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn find(&self, start: usize) -> (usize, &CumulativeOffset) {
|
||||
let index = self.find_index(start);
|
||||
let index = &self.cumulative_offsets[index];
|
||||
let start = start - index.start_offset;
|
||||
(start, index)
|
||||
}
|
||||
|
||||
// return the biggest slice possible that starts at 'start'
|
||||
pub fn get_slice<'a, T>(&self, raw: &'a [Vec<T>], start: usize) -> &'a [T] {
|
||||
pub fn get_slice<'a, 'b, T, U>(&'a self, raw: &'b U, start: usize) -> &'b [T]
|
||||
where
|
||||
U: ExtractSliceFromRawData<'b, T> + 'b,
|
||||
{
|
||||
let (start, index) = self.find(start);
|
||||
const DIMENSION: usize = 0;
|
||||
&raw[index.index[DIMENSION]][start..]
|
||||
}
|
||||
|
||||
// return the biggest slice possible that starts at 'start'
|
||||
pub fn get_slice_2d<'a, T>(&self, raw: &'a [Vec<Vec<T>>], start: usize) -> &'a [T] {
|
||||
let (start, index) = self.find(start);
|
||||
const DIMENSION_0: usize = 0;
|
||||
const DIMENSION_1: usize = 1;
|
||||
&raw[index.index[DIMENSION_0]][index.index[DIMENSION_1]][start..]
|
||||
raw.extract(index, start)
|
||||
}
|
||||
}
|
||||
|
||||
@ -751,7 +763,7 @@ impl AccountsHash {
|
||||
// move tail hashes that don't evenly hash into a 1d vector for next time
|
||||
let mut i = hash_total - left_over_hashes;
|
||||
while i < hash_total {
|
||||
let data = cumulative.get_slice_2d(&hashes, i);
|
||||
let data = cumulative.get_slice(&hashes, i);
|
||||
next_pass.remaining_unhashed.extend(data);
|
||||
i += data.len();
|
||||
}
|
||||
@ -769,7 +781,7 @@ impl AccountsHash {
|
||||
hash_total, // note this does not include the ones that didn't divide evenly, unless we're in the last iteration
|
||||
MERKLE_FANOUT,
|
||||
Some(TARGET_FANOUT_LEVEL),
|
||||
|start| cumulative.get_slice_2d(&hashes, start),
|
||||
|start| cumulative.get_slice(&hashes, start),
|
||||
Some(TARGET_FANOUT_LEVEL),
|
||||
)
|
||||
.1;
|
||||
@ -1636,7 +1648,7 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_accountsdb_cumulative_offsets2_d() {
|
||||
let input = vec![vec![vec![0, 1], vec![], vec![2, 3, 4], vec![]]];
|
||||
let input: Vec<Vec<Vec<u64>>> = vec![vec![vec![0, 1], vec![], vec![2, 3, 4], vec![]]];
|
||||
let cumulative = CumulativeOffsets::from_raw_2d(&input);
|
||||
|
||||
let src: Vec<_> = input
|
||||
@ -1661,7 +1673,7 @@ pub mod tests {
|
||||
assert_eq!(cumulative.cumulative_offsets[1].start_offset, 2);
|
||||
|
||||
for start in 0..len {
|
||||
let slice = cumulative.get_slice_2d(&input, start);
|
||||
let slice: &[u64] = cumulative.get_slice(&input, start);
|
||||
let len = slice.len();
|
||||
assert!(len > 0);
|
||||
assert_eq!(&src[start..(start + len)], slice);
|
||||
@ -1690,7 +1702,7 @@ pub mod tests {
|
||||
assert_eq!(cumulative.cumulative_offsets[1].start_offset, 2);
|
||||
|
||||
for start in 0..len {
|
||||
let slice = cumulative.get_slice_2d(&input, start);
|
||||
let slice: &[u64] = cumulative.get_slice(&input, start);
|
||||
let len = slice.len();
|
||||
assert!(len > 0);
|
||||
assert_eq!(&src[start..(start + len)], slice);
|
||||
@ -1731,7 +1743,7 @@ pub mod tests {
|
||||
assert_eq!(cumulative.cumulative_offsets[1].start_offset, 2);
|
||||
|
||||
for start in 0..len {
|
||||
let slice = cumulative.get_slice_2d(&input, start);
|
||||
let slice: &[u64] = cumulative.get_slice(&input, start);
|
||||
let len = slice.len();
|
||||
assert!(len > 0);
|
||||
assert_eq!(&src[start..(start + len)], slice);
|
||||
@ -1903,7 +1915,7 @@ pub mod tests {
|
||||
];
|
||||
let offsets = CumulativeOffsets::from_raw_2d(&src);
|
||||
|
||||
let get_slice = |start: usize| -> &[Hash] { offsets.get_slice_2d(&src, start) };
|
||||
let get_slice = |start: usize| -> &[Hash] { offsets.get_slice(&src, start) };
|
||||
let result2 = AccountsHash::compute_merkle_root_from_slices(
|
||||
offsets.total_count,
|
||||
fanout,
|
||||
|
Reference in New Issue
Block a user