diff --git a/chain/src/chain.rs b/chain/src/chain.rs index be4dd05ec..e19298b58 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -28,6 +28,7 @@ use crate::lmdb; use crate::pipe; use crate::store; use crate::txhashset; +use crate::txhashset::TxHashSet; use crate::types::{ BlockStatus, ChainAdapter, NoStatus, Options, Tip, TxHashSetRoots, TxHashsetWriteStatus, }; @@ -207,6 +208,11 @@ impl Chain { Ok(chain) } + /// Return our shared txhashset instance. + pub fn txhashset(&self) -> Arc> { + self.txhashset.clone() + } + fn log_heads(store: &store::ChainStore) -> Result<(), Error> { let head = store.head()?; debug!( @@ -1106,19 +1112,16 @@ impl Chain { .map_err(|e| ErrorKind::StoreErr(e, "chain get block_sums".to_owned()).into()) } - /// Gets the block header at the provided height + /// Gets the block header at the provided height. + /// Note: This takes a read lock on the txhashset. + /// Take care not to call this repeatedly in a tight loop. pub fn get_header_by_height(&self, height: u64) -> Result { - let mut txhashset = self.txhashset.write(); - let mut batch = self.store.batch()?; - let header = txhashset::header_extending(&mut txhashset, &mut batch, |extension| { - let header = extension.get_header_by_height(height)?; - Ok(header) - })?; - + let txhashset = self.txhashset.read(); + let header = txhashset.get_header_by_height(height)?; Ok(header) } - /// Gets the block header in which a given output appears in the txhashset + /// Gets the block header in which a given output appears in the txhashset. pub fn get_header_for_output( &self, output_ref: &OutputIdentifier, diff --git a/servers/src/common/adapters.rs b/servers/src/common/adapters.rs index e5e231755..3fe0a6bd8 100644 --- a/servers/src/common/adapters.rs +++ b/servers/src/common/adapters.rs @@ -260,6 +260,9 @@ impl p2p::ChainAdapter for NetToChainAdapter { let max_height = self.chain().header_head().unwrap().height; + let txhashset = self.chain().txhashset(); + let txhashset = txhashset.read(); + // looks like we know one, getting as many following headers as allowed let hh = header.height; let mut headers = vec![]; @@ -268,7 +271,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { break; } - if let Ok(header) = self.chain().get_header_by_height(h) { + if let Ok(header) = txhashset.get_header_by_height(h) { headers.push(header); } else { error!("Failed to locate headers successfully."); @@ -399,9 +402,12 @@ impl NetToChainAdapter { // Find the first locator hash that refers to a known header on our main chain. fn find_common_header(&self, locator: &[Hash]) -> Option { + let txhashset = self.chain().txhashset(); + let txhashset = txhashset.read(); + for hash in locator { if let Ok(header) = self.chain().get_block_header(&hash) { - if let Ok(header_at_height) = self.chain().get_header_by_height(header.height) { + if let Ok(header_at_height) = txhashset.get_header_by_height(header.height) { if header.hash() == header_at_height.hash() { return Some(header); } diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index 6f267de4f..89b1e3f9a 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -374,6 +374,9 @@ impl Server { let tip_height = self.chain.head().unwrap().height as i64; let mut height = tip_height as i64 - last_blocks.len() as i64 + 1; + let txhashset = self.chain.txhashset(); + let txhashset = txhashset.read(); + let diff_entries: Vec = last_blocks .windows(2) .map(|pair| { @@ -385,7 +388,7 @@ impl Server { // Use header hash if real header. // Default to "zero" hash if synthetic header_info. let hash = if height >= 0 { - if let Ok(header) = self.chain.get_header_by_height(height as u64) { + if let Ok(header) = txhashset.get_header_by_height(height as u64) { header.hash() } else { ZERO_HASH