state: Move block header hashing to block_index

Only hash block headers in the lowest-level block index code.

This design has a few benefits:
  - failures are obvious, because the hash is not available,
  - get_tip() returns a smaller object,
  - we avoid re-hashing block headers multiple times.

These efficiency changes may be needed to support chain reorganisations,
multiple tips, and heavy query loads.
This commit is contained in:
teor 2020-06-12 15:04:52 +10:00 committed by Henry de Valence
parent 26a58b23de
commit 334329f38a
2 changed files with 8 additions and 7 deletions

View File

@ -30,8 +30,10 @@ impl Service<Request> for ZebraState {
fn call(&mut self, req: Request) -> Self::Future { fn call(&mut self, req: Request) -> Self::Future {
match req { match req {
Request::AddBlock { block } => { Request::AddBlock { block } => {
let hash = block.as_ref().into(); let result = self
let result = self.index.insert(block).map(|_| Response::Added { hash }); .index
.insert(block)
.map(|hash| Response::Added { hash });
async { result }.boxed() async { result }.boxed()
} }
@ -48,7 +50,6 @@ impl Service<Request> for ZebraState {
let result = self let result = self
.index .index
.get_tip() .get_tip()
.map(|block| block.as_ref().into())
.map(|hash| Response::Tip { hash }) .map(|hash| Response::Tip { hash })
.ok_or_else(|| "zebra-state contains no blocks".into()); .ok_or_else(|| "zebra-state contains no blocks".into());

View File

@ -17,7 +17,7 @@ impl BlockIndex {
pub(super) fn insert( pub(super) fn insert(
&mut self, &mut self,
block: impl Into<Arc<Block>>, block: impl Into<Arc<Block>>,
) -> Result<(), Box<dyn Error + Send + Sync + 'static>> { ) -> Result<BlockHeaderHash, Box<dyn Error + Send + Sync + 'static>> {
let block = block.into(); let block = block.into();
let hash = block.as_ref().into(); let hash = block.as_ref().into();
let height = block.coinbase_height().unwrap(); let height = block.coinbase_height().unwrap();
@ -26,7 +26,7 @@ impl BlockIndex {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
let _ = entry.insert(block.clone()); let _ = entry.insert(block.clone());
let _ = self.by_hash.insert(hash, block); let _ = self.by_hash.insert(hash, block);
Ok(()) Ok(hash)
} }
Entry::Occupied(_) => Err("forks in the chain aren't supported yet")?, Entry::Occupied(_) => Err("forks in the chain aren't supported yet")?,
} }
@ -40,12 +40,12 @@ impl BlockIndex {
.cloned() .cloned()
} }
pub(super) fn get_tip(&self) -> Option<Arc<Block>> { pub(super) fn get_tip(&self) -> Option<BlockHeaderHash> {
self.by_height self.by_height
.iter() .iter()
.next_back() .next_back()
.map(|(_key, value)| value) .map(|(_key, value)| value)
.cloned() .map(|block| block.as_ref().into())
} }
} }