Stop awaiting the previous block in the block verifier
Instead, the state should cache blocks until the previous block has been committed.
This commit is contained in:
parent
8463b705c8
commit
7f2bebb97d
|
@ -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<Arc<Block>, 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.
|
||||
|
|
Loading…
Reference in New Issue