diff --git a/runtime/src/accounts_hash.rs b/runtime/src/accounts_hash.rs index 07d059e0cf..3a1d726e71 100644 --- a/runtime/src/accounts_hash.rs +++ b/runtime/src/accounts_hash.rs @@ -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> { + 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>> { + 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, where src is really Vec> (or later Vec>>) // 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], 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>], 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![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,