mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
optimization for reading peak hashes from backend file (#3575)
This commit is contained in:
parent
7487ffd75b
commit
adddff9155
5 changed files with 43 additions and 8 deletions
|
@ -46,6 +46,11 @@ pub trait Backend<T: PMMRable> {
|
||||||
/// (ignoring the remove log).
|
/// (ignoring the remove log).
|
||||||
fn get_from_file(&self, position: u64) -> Option<Hash>;
|
fn get_from_file(&self, position: u64) -> Option<Hash>;
|
||||||
|
|
||||||
|
/// Get hash for peak pos.
|
||||||
|
/// Optimized for reading peak hashes rather than arbitrary pos hashes.
|
||||||
|
/// Peaks can be assumed to not be compacted.
|
||||||
|
fn get_peak_from_file(&self, position: u64) -> Option<Hash>;
|
||||||
|
|
||||||
/// Get a Data Element by original insertion position
|
/// Get a Data Element by original insertion position
|
||||||
/// (ignoring the remove log).
|
/// (ignoring the remove log).
|
||||||
fn get_data_from_file(&self, position: u64) -> Option<T::E>;
|
fn get_data_from_file(&self, position: u64) -> Option<T::E>;
|
||||||
|
|
|
@ -39,6 +39,11 @@ pub trait ReadablePMMR {
|
||||||
/// Get the hash from the underlying MMR file (ignores the remove log).
|
/// Get the hash from the underlying MMR file (ignores the remove log).
|
||||||
fn get_from_file(&self, pos: u64) -> Option<Hash>;
|
fn get_from_file(&self, pos: u64) -> Option<Hash>;
|
||||||
|
|
||||||
|
/// Get the hash for the provided peak pos.
|
||||||
|
/// Optimized for reading peak hashes rather than arbitrary pos hashes.
|
||||||
|
/// Peaks can be assumed to not be compacted.
|
||||||
|
fn get_peak_from_file(&self, pos: u64) -> Option<Hash>;
|
||||||
|
|
||||||
/// Get the data element at provided position in the MMR (ignores the remove log).
|
/// Get the data element at provided position in the MMR (ignores the remove log).
|
||||||
fn get_data_from_file(&self, pos: u64) -> Option<Self::Item>;
|
fn get_data_from_file(&self, pos: u64) -> Option<Self::Item>;
|
||||||
|
|
||||||
|
@ -84,11 +89,7 @@ pub trait ReadablePMMR {
|
||||||
fn peaks(&self) -> Vec<Hash> {
|
fn peaks(&self) -> Vec<Hash> {
|
||||||
peaks(self.unpruned_size())
|
peaks(self.unpruned_size())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(move |pi| {
|
.filter_map(move |pi| self.get_peak_from_file(pi))
|
||||||
// here we want to get from underlying hash file
|
|
||||||
// as the pos *may* have been "removed"
|
|
||||||
self.get_from_file(pi)
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ pub trait ReadablePMMR {
|
||||||
let mut res = peaks(self.unpruned_size())
|
let mut res = peaks(self.unpruned_size())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|&x| x < peak_pos)
|
.filter(|&x| x < peak_pos)
|
||||||
.filter_map(|x| self.get_from_file(x))
|
.filter_map(|x| self.get_peak_from_file(x))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if let Some(rhs) = rhs {
|
if let Some(rhs) = rhs {
|
||||||
res.push(rhs);
|
res.push(rhs);
|
||||||
|
@ -227,7 +228,7 @@ where
|
||||||
let left_sibling = pos + 1 - 2 * peak;
|
let left_sibling = pos + 1 - 2 * peak;
|
||||||
let left_hash = self
|
let left_hash = self
|
||||||
.backend
|
.backend
|
||||||
.get_from_file(left_sibling)
|
.get_peak_from_file(left_sibling)
|
||||||
.ok_or("missing left sibling in tree, should not have been pruned")?;
|
.ok_or("missing left sibling in tree, should not have been pruned")?;
|
||||||
peak *= 2;
|
peak *= 2;
|
||||||
pos += 1;
|
pos += 1;
|
||||||
|
@ -414,6 +415,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_peak_from_file(&self, pos: u64) -> Option<Hash> {
|
||||||
|
if pos > self.last_pos {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.backend.get_peak_from_file(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_data_from_file(&self, pos: u64) -> Option<Self::Item> {
|
fn get_data_from_file(&self, pos: u64) -> Option<Self::Item> {
|
||||||
if pos > self.last_pos {
|
if pos > self.last_pos {
|
||||||
None
|
None
|
||||||
|
|
|
@ -148,6 +148,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_peak_from_file(&self, pos: u64) -> Option<Hash> {
|
||||||
|
if pos > self.last_pos {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.backend.get_peak_from_file(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_data_from_file(&self, pos: u64) -> Option<Self::Item> {
|
fn get_data_from_file(&self, pos: u64) -> Option<Self::Item> {
|
||||||
if pos > self.last_pos {
|
if pos > self.last_pos {
|
||||||
None
|
None
|
||||||
|
|
|
@ -64,6 +64,10 @@ impl<T: PMMRable> Backend<T> for VecBackend<T> {
|
||||||
self.hashes.get(idx).cloned()
|
self.hashes.get(idx).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_peak_from_file(&self, position: u64) -> Option<Hash> {
|
||||||
|
self.get_from_file(position)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_data_from_file(&self, position: u64) -> Option<T::E> {
|
fn get_data_from_file(&self, position: u64) -> Option<T::E> {
|
||||||
if let Some(data) = &self.data {
|
if let Some(data) = &self.data {
|
||||||
let idx = usize::try_from(pmmr::n_leaves(position).saturating_sub(1))
|
let idx = usize::try_from(pmmr::n_leaves(position).saturating_sub(1))
|
||||||
|
|
|
@ -94,6 +94,11 @@ impl<T: PMMRable> Backend<T> for PMMRBackend<T> {
|
||||||
self.hash_file.read(position - shift)
|
self.hash_file.read(position - shift)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_peak_from_file(&self, position: u64) -> Option<Hash> {
|
||||||
|
let shift = self.prune_list.get_shift(position);
|
||||||
|
self.hash_file.read(position - shift)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_data_from_file(&self, position: u64) -> Option<T::E> {
|
fn get_data_from_file(&self, position: u64) -> Option<T::E> {
|
||||||
if !pmmr::is_leaf(position) {
|
if !pmmr::is_leaf(position) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -284,11 +289,15 @@ impl<T: PMMRable> PMMRBackend<T> {
|
||||||
self.prune_list.is_pruned_root(pos)
|
self.prune_list.is_pruned_root(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if pos is pruned but not a pruned root itself.
|
||||||
|
// Checking for pruned root is faster so we do this check first.
|
||||||
|
// We can do a fast initial check as well -
|
||||||
|
// if its in the current leaf_set then we know it is not compacted.
|
||||||
fn is_compacted(&self, pos: u64) -> bool {
|
fn is_compacted(&self, pos: u64) -> bool {
|
||||||
if self.leaf_set.includes(pos) {
|
if self.leaf_set.includes(pos) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
self.is_pruned(pos) && !self.is_pruned_root(pos)
|
!self.is_pruned_root(pos) && self.is_pruned(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Number of hashes in the PMMR stored by this backend. Only produces the
|
/// Number of hashes in the PMMR stored by this backend. Only produces the
|
||||||
|
|
Loading…
Reference in a new issue