consensus: Check block times against the local clock
Part of
@@ -88,16 +88,35 @@ where
fn call(&mut self, block: Arc<Block>) -> Self::Future {
// TODO(jlusby): Error = Report, handle errors from state_service.
// TODO(teor):
- // - handle chain reorgs, adjust state_service "unique block height" conditions
- // - handle block validation errors (including errors in the block's transactions)
+ // - handle chain reorgs
+ // - adjust state_service "unique block height" conditions
+ // - move expensive checks into the async block
+ // Create an AddBlock Future, but don't run it yet.
+ //
// `state_service.call` is OK here because we already called
// `state_service.poll_ready` in our `poll_ready`.
- let add_block = self
- .state_service
- .call(zebra_state::Request::AddBlock { block });
+ //
+ // `tower::Buffer` expects exactly one `call` for each
+ // `poll_ready`. So we unconditionally create the AddBlock
+ // Future using `state_service.call`. If verification fails,
+ // we return an error, and implicitly cancel the future.
+ let add_block = self.state_service.call(zebra_state::Request::AddBlock {
+ block: block.clone(),
+ });
async move {
+ // If verification fails, return an error result.
+ // The AddBlock Future is implicitly cancelled by the
+ // error return in `?`.
+
+ // Since errors cause an early exit, try to do the
+ // quick checks first.
+ block::node_time_check(block)?;
+
+ // Verification was successful.
+ // Add the block to the state by awaiting the AddBlock
+ // Future, and return its result.
match add_block.await? {
zebra_state::Response::Added { hash } => Ok(hash),
_ => Err("adding block to zebra-state failed".into()),
