diff --git a/chain/src/chain.rs b/chain/src/chain.rs index d244a9405..878b670c0 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -438,7 +438,7 @@ impl Chain { /// current chain state, specifically the current winning (valid, most /// work) fork. pub fn is_unspent(&self, output_ref: &OutputIdentifier) -> Result { - let mut txhashset = self.txhashset.write(); + let txhashset = self.txhashset.read(); let res = txhashset.is_unspent(output_ref); match res { Err(e) => Err(e), @@ -1096,7 +1096,7 @@ impl Chain { output_ref: &OutputIdentifier, ) -> Result { let pos = { - let mut txhashset = self.txhashset.write(); + let txhashset = self.txhashset.read(); let (_, pos) = txhashset.is_unspent(output_ref)?; pos }; diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index d7114fb5d..09d7c96da 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -160,11 +160,11 @@ impl TxHashSet { /// Check if an output is unspent. /// We look in the index to find the output MMR pos. /// Then we check the entry in the output MMR and confirm the hash matches. - pub fn is_unspent(&mut self, output_id: &OutputIdentifier) -> Result<(Hash, u64), Error> { + 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: PMMR = - PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos); + let output_pmmr: ReadonlyPMMR = + 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) { Ok((hash, pos)) diff --git a/core/src/core/pmmr/readonly_pmmr.rs b/core/src/core/pmmr/readonly_pmmr.rs index a9a3a7562..e4557b3d5 100644 --- a/core/src/core/pmmr/readonly_pmmr.rs +++ b/core/src/core/pmmr/readonly_pmmr.rs @@ -16,6 +16,7 @@ use std::marker; +use core::hash::Hash; use core::pmmr::{is_leaf, Backend}; use ser::PMMRable; @@ -70,4 +71,17 @@ where None } } + + /// Get the hash at provided position in the MMR. + pub fn get_hash(&self, pos: u64) -> Option { + if pos > self.last_pos { + None + } else if is_leaf(pos) { + // If we are a leaf then get hash from the backend. + self.backend.get_hash(pos) + } else { + // If we are not a leaf get hash ignoring the remove log. + self.backend.get_from_file(pos) + } + } }