From 93586867bca9555e302b03949f960e279c7d14aa Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 10 Sep 2020 14:29:27 -0700 Subject: [PATCH] consensus: change verifier poll_ready handling. This makes the component verifiers both always return `poll_ready`, because they do not exert backpressure and cannot fail. The checkpoint verifier now immediately rejects any blocks that arrive after it finishes checkpointing, instead of marking the service itself as failed. The chain verifier is agnostic to the readiness behavior of its components, and reports readiness when they are both ready. --- zebra-consensus/src/chain.rs | 14 +++++++++----- zebra-consensus/src/checkpoint.rs | 10 ++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/zebra-consensus/src/chain.rs b/zebra-consensus/src/chain.rs index 96d0c320c..9a800a550 100644 --- a/zebra-consensus/src/chain.rs +++ b/zebra-consensus/src/chain.rs @@ -50,11 +50,15 @@ where type Future = Pin> + Send + 'static>>; - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { - // We don't expect the verifiers to exert backpressure on our - // users, so we don't need to call the verifier's `poll_ready` here. - // (And we don't know which verifier to choose at this point, anyway.) - Poll::Ready(Ok(())) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + match (self.checkpoint.poll_ready(cx), self.block.poll_ready(cx)) { + // First, fail if either service fails. + (Poll::Ready(Err(e)), _) | (_, Poll::Ready(Err(e))) => Poll::Ready(Err(e)), + // Second, we're unready if either service is unready. + (Poll::Pending, _) | (_, Poll::Pending) => Poll::Pending, + // Finally, we're ready if both services are ready and OK. + (Poll::Ready(Ok(())), Poll::Ready(Ok(()))) => Poll::Ready(Ok(())), + } } fn call(&mut self, block: Arc) -> Self::Future { diff --git a/zebra-consensus/src/checkpoint.rs b/zebra-consensus/src/checkpoint.rs index b2d20b800..f49833ce7 100644 --- a/zebra-consensus/src/checkpoint.rs +++ b/zebra-consensus/src/checkpoint.rs @@ -763,13 +763,15 @@ where Pin> + Send + 'static>>; fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { - match self.previous_checkpoint_height() { - FinalCheckpoint => Poll::Ready(Err("there are no checkpoints left to verify".into())), - _ => Poll::Ready(Ok(())), - } + Poll::Ready(Ok(())) } fn call(&mut self, block: Arc) -> Self::Future { + // Immediately reject all incoming blocks that arrive after we've finished. + if let FinalCheckpoint = self.previous_checkpoint_height() { + return async { Err("checkpoint request after checkpointing finished".into()) }.boxed(); + } + // Queue the block for verification, until we receive all the blocks for // the current checkpoint range. let rx = self.queue_block(block.clone());