From 7f2bebb97d8514735726c52317a5a340d3c2cf9d Mon Sep 17 00:00:00 2001 From: teor Date: Fri, 4 Sep 2020 20:54:14 +1000 Subject: [PATCH] Stop awaiting the previous block in the block verifier Instead, the state should cache blocks until the previous block has been committed. --- zebra-consensus/src/block.rs | 64 ++---------------------------------- 1 file changed, 2 insertions(+), 62 deletions(-) diff --git a/zebra-consensus/src/block.rs b/zebra-consensus/src/block.rs index d9fc50e94..57e4d6bd2 100644 --- a/zebra-consensus/src/block.rs +++ b/zebra-consensus/src/block.rs @@ -22,9 +22,7 @@ use std::{ pin::Pin, sync::Arc, task::{Context, Poll}, - time::Duration, }; -use tokio::time; use tower::{buffer::Buffer, Service, ServiceExt}; use zebra_chain::block::{self, Block}; @@ -125,42 +123,6 @@ where // TODO: context-free header verification: merkle root - // As a temporary solution for chain gaps, wait for the previous block, - // and check its height. - // - // TODO: replace this check with the contextual verification RFC design - // - // Skip contextual checks for the genesis block - let previous_block_hash = block.header.previous_block_hash; - if previous_block_hash != crate::parameters::GENESIS_PREVIOUS_BLOCK_HASH { - if height == block::Height(0) { - Err(format!("invalid block {:?}: height is 0, but previous block hash {:?} is not null", - hash, - previous_block_hash))?; - } - - let expected_height = block::Height(height.0 - 1); - tracing::trace!(?expected_height, ?previous_block_hash, "Waiting for previous block"); - metrics::gauge!("block.waiting.block.height", expected_height.0 as i64); - metrics::counter!("block.waiting.count", 1); - - let previous_block = BlockVerifier::await_block( - &mut state_service, - previous_block_hash, - expected_height, - ) - .await?; - - let previous_height = previous_block.coinbase_height().unwrap(); - if previous_height != expected_height { - Err(format!("invalid block height {:?} for {:?}: must be 1 more than the previous block height {:?} in {:?}", - height, - hash, - previous_height, - previous_block_hash))?; - } - } - tracing::trace!("verified block"); metrics::gauge!( "block.verified.block.height", @@ -168,9 +130,8 @@ where ); metrics::counter!("block.verified.block.count", 1); - // We need to add the block after the previous block is in the state, - // and before this future returns. Otherwise, blocks could be - // committed out of order. + // Commit the block in the future - the state will handle out of + // order blocks. let ready_state = state_service .ready_and() .await?; @@ -221,27 +182,6 @@ where Ok(block) } - - /// Wait until a block with `hash` is in `state_service`. - /// - /// Returns an error if `state_service.poll_ready` errors. - async fn await_block( - state_service: &mut S, - hash: block::Hash, - height: block::Height, - ) -> Result, Report> { - loop { - match BlockVerifier::get_block(state_service, hash).await? { - Some(block) => return Ok(block), - // Busy-waiting is only a temporary solution to waiting for blocks. - // Replace with the contextual verification RFC design - None => { - tracing::debug!(?height, ?hash, "Waiting for state to have block"); - time::delay_for(Duration::from_millis(50)).await - } - }; - } - } } /// Return a block verification service, using the provided state service.