Readonly pmmr cleanup (#2083)

* avoid locking txhashset by using a readonly PMMR

* rustfmt
This commit is contained in:
Antioch Peverell
2018-12-05 14:52:53 +00:00
committed by GitHub
parent 8d8f533b8e
commit bf815aa5cd
6 changed files with 150 additions and 110 deletions
+7 -11
View File
@@ -583,7 +583,7 @@ impl Chain {
Ok(())
}
/// Return a pre-built Merkle proof for the given commitment from the store.
/// Return a Merkle proof for the given commitment from the store.
pub fn get_merkle_proof(
&self,
output: &OutputIdentifier,
@@ -606,10 +606,9 @@ impl Chain {
txhashset.merkle_proof(commit)
}
/// Returns current txhashset roots
/// Returns current txhashset roots.
pub fn get_txhashset_roots(&self) -> TxHashSetRoots {
let mut txhashset = self.txhashset.write();
txhashset.roots()
self.txhashset.read().roots()
}
/// Provides a reading view into the current txhashset state as well as
@@ -967,20 +966,17 @@ impl Chain {
/// returns the last n nodes inserted into the output sum tree
pub fn get_last_n_output(&self, distance: u64) -> Vec<(Hash, OutputIdentifier)> {
let mut txhashset = self.txhashset.write();
txhashset.last_n_output(distance)
self.txhashset.read().last_n_output(distance)
}
/// as above, for rangeproofs
pub fn get_last_n_rangeproof(&self, distance: u64) -> Vec<(Hash, RangeProof)> {
let mut txhashset = self.txhashset.write();
txhashset.last_n_rangeproof(distance)
self.txhashset.read().last_n_rangeproof(distance)
}
/// as above, for kernels
pub fn get_last_n_kernel(&self, distance: u64) -> Vec<(Hash, TxKernelEntry)> {
let mut txhashset = self.txhashset.write();
txhashset.last_n_kernel(distance)
self.txhashset.read().last_n_kernel(distance)
}
/// outputs by insertion index
@@ -989,7 +985,7 @@ impl Chain {
start_index: u64,
max: u64,
) -> Result<(u64, u64, Vec<Output>), Error> {
let mut txhashset = self.txhashset.write();
let txhashset = self.txhashset.read();
let max_index = txhashset.highest_output_insertion_index();
let outputs = txhashset.outputs_by_insertion_index(start_index, max);
let rangeproofs = txhashset.rangeproofs_by_insertion_index(start_index, max);
+31 -39
View File
@@ -163,7 +163,7 @@ impl TxHashSet {
pub fn is_unspent(&self, output_id: &OutputIdentifier) -> Result<(Hash, u64), Error> {
match self.commit_index.get_output_pos(&output_id.commit) {
Ok(pos) => {
let output_pmmr: ReadonlyPMMR<Output, _> =
let output_pmmr =
ReadonlyPMMR::at(&self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
if let Some(hash) = output_pmmr.get_hash(pos) {
if hash == output_id.hash_with_index(pos - 1) {
@@ -184,34 +184,30 @@ impl TxHashSet {
/// nodes at level 0
/// TODO: These need to return the actual data from the flat-files instead
/// of hashes now
pub fn last_n_output(&mut self, distance: u64) -> Vec<(Hash, OutputIdentifier)> {
let output_pmmr: PMMR<Output, _> =
PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
output_pmmr.get_last_n_insertions(distance)
pub fn last_n_output(&self, distance: u64) -> Vec<(Hash, OutputIdentifier)> {
ReadonlyPMMR::at(&self.output_pmmr_h.backend, self.output_pmmr_h.last_pos)
.get_last_n_insertions(distance)
}
/// as above, for range proofs
pub fn last_n_rangeproof(&mut self, distance: u64) -> Vec<(Hash, RangeProof)> {
let rproof_pmmr: PMMR<RangeProof, _> =
PMMR::at(&mut self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos);
rproof_pmmr.get_last_n_insertions(distance)
pub fn last_n_rangeproof(&self, distance: u64) -> Vec<(Hash, RangeProof)> {
ReadonlyPMMR::at(&self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos)
.get_last_n_insertions(distance)
}
/// as above, for kernels
pub fn last_n_kernel(&mut self, distance: u64) -> Vec<(Hash, TxKernelEntry)> {
let kernel_pmmr: PMMR<TxKernel, _> =
PMMR::at(&mut self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos);
kernel_pmmr.get_last_n_insertions(distance)
pub fn last_n_kernel(&self, distance: u64) -> Vec<(Hash, TxKernelEntry)> {
ReadonlyPMMR::at(&self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos)
.get_last_n_insertions(distance)
}
/// Get the header at the specified height based on the current state of the txhashset.
/// Derives the MMR pos from the height (insertion index) and retrieves the header hash.
/// Looks the header up in the db by hash.
pub fn get_header_by_height(&mut self, height: u64) -> Result<BlockHeader, Error> {
pub fn get_header_by_height(&self, height: u64) -> Result<BlockHeader, Error> {
let pos = pmmr::insertion_to_pmmr_index(height + 1);
let header_pmmr: PMMR<BlockHeader, _> =
PMMR::at(&mut self.header_pmmr_h.backend, self.header_pmmr_h.last_pos);
let header_pmmr =
ReadonlyPMMR::at(&self.header_pmmr_h.backend, self.header_pmmr_h.last_pos);
if let Some(hash) = header_pmmr.get_data(pos) {
let header = self.commit_index.get_block_header(&hash)?;
Ok(header)
@@ -223,41 +219,39 @@ impl TxHashSet {
/// returns outputs from the given insertion (leaf) index up to the
/// specified limit. Also returns the last index actually populated
pub fn outputs_by_insertion_index(
&mut self,
&self,
start_index: u64,
max_count: u64,
) -> (u64, Vec<OutputIdentifier>) {
let output_pmmr: PMMR<Output, _> =
PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
output_pmmr.elements_from_insertion_index(start_index, max_count)
ReadonlyPMMR::at(&self.output_pmmr_h.backend, self.output_pmmr_h.last_pos)
.elements_from_insertion_index(start_index, max_count)
}
/// highest output insertion index available
pub fn highest_output_insertion_index(&mut self) -> u64 {
pub fn highest_output_insertion_index(&self) -> u64 {
pmmr::n_leaves(self.output_pmmr_h.last_pos)
}
/// As above, for rangeproofs
pub fn rangeproofs_by_insertion_index(
&mut self,
&self,
start_index: u64,
max_count: u64,
) -> (u64, Vec<RangeProof>) {
let rproof_pmmr: PMMR<RangeProof, _> =
PMMR::at(&mut self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos);
rproof_pmmr.elements_from_insertion_index(start_index, max_count)
ReadonlyPMMR::at(&self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos)
.elements_from_insertion_index(start_index, max_count)
}
/// Get MMR roots.
pub fn roots(&mut self) -> TxHashSetRoots {
let header_pmmr: PMMR<BlockHeader, _> =
PMMR::at(&mut self.header_pmmr_h.backend, self.header_pmmr_h.last_pos);
let output_pmmr: PMMR<Output, _> =
PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
let rproof_pmmr: PMMR<RangeProof, _> =
PMMR::at(&mut self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos);
let kernel_pmmr: PMMR<TxKernel, _> =
PMMR::at(&mut self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos);
pub fn roots(&self) -> TxHashSetRoots {
let header_pmmr =
ReadonlyPMMR::at(&self.header_pmmr_h.backend, self.header_pmmr_h.last_pos);
let output_pmmr =
ReadonlyPMMR::at(&self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
let rproof_pmmr =
ReadonlyPMMR::at(&self.rproof_pmmr_h.backend, self.rproof_pmmr_h.last_pos);
let kernel_pmmr =
ReadonlyPMMR::at(&self.kernel_pmmr_h.backend, self.kernel_pmmr_h.last_pos);
TxHashSetRoots {
header_root: header_pmmr.root(),
@@ -267,12 +261,10 @@ impl TxHashSet {
}
}
/// build a new merkle proof for the given position
/// build a new merkle proof for the given position.
pub fn merkle_proof(&mut self, commit: Commitment) -> Result<MerkleProof, String> {
let pos = self.commit_index.get_output_pos(&commit).unwrap();
let output_pmmr: PMMR<Output, _> =
PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos);
output_pmmr.merkle_proof(pos)
PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos).merkle_proof(pos)
}
/// Compact the MMR data files and flush the rm logs