Skip to content

Commit

Permalink
consensus: Make the state service pluggable in block verification
Browse files Browse the repository at this point in the history
We want to allow different state service implementations, and wrapped
state services. So we make verify::init() take a state_service, and
store that service in the BlockVerifier state_service field.

Part of ZcashFoundation#428.
  • Loading branch information
teor2345 committed Jun 11, 2020
1 parent d2c587d commit 8097c66
Showing 1 changed file with 31 additions and 12 deletions.
43 changes: 31 additions & 12 deletions zebra-consensus/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,27 @@ use zebra_chain::block::{Block, BlockHeaderHash};
mod script;
mod transaction;

/// The trait constraints that we expect from `zebra_state::ZebraState` errors.
type ZSE = Box<dyn error::Error + Send + Sync + 'static>;
/// The trait constraints that we expect from the `zebra_state::ZebraState` service.
/// `ZSF` is the `Future` type for `zebra_state::ZebraState`. This type is generic,
/// because `tower::Service` function calls require a `Sized` future type.
type ZS<ZSF> = Box<
dyn Service<zebra_state::Request, Response = zebra_state::Response, Error = ZSE, Future = ZSF>
+ Send
+ 'static,
>;

/// Block verification service.
///
/// After verification, blocks and their associated transactions are added to
/// `zebra_state::ZebraState`.
#[derive(Default)]
struct BlockVerifier {}
struct BlockVerifier<ZSF>
where
ZSF: Future<Output = Result<zebra_state::Response, ZSE>> + Send + 'static,
{
state_service: ZS<ZSF>,
}

/// The result type for the BlockVerifier Service.
type Response = BlockHeaderHash;
Expand All @@ -36,29 +51,28 @@ type Response = BlockHeaderHash;
type Error = Box<dyn error::Error + Send + Sync + 'static>;

/// The BlockVerifier service implementation.
impl Service<Block> for BlockVerifier {
impl<ZSF> Service<Block> for BlockVerifier<ZSF>
where
ZSF: Future<Output = Result<zebra_state::Response, ZSE>> + Send + 'static,
{
type Response = Response;
type Error = Error;
type Future =
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;

fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
// TODO(teor): is this a shared state?
let mut state_service = zebra_state::in_memory::init();
state_service.poll_ready(context)
self.state_service.poll_ready(context)
}

fn call(&mut self, block: Block) -> Self::Future {
let mut state_service = zebra_state::in_memory::init();

let header_hash: BlockHeaderHash = (&block).into();

// Ignore errors for now.
// 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)
let _ = state_service.call(zebra_state::Request::AddBlock {
let _: ZSF = self.state_service.call(zebra_state::Request::AddBlock {
block: block.into(),
});

Expand All @@ -67,13 +81,18 @@ impl Service<Block> for BlockVerifier {
}

/// Initialise the BlockVerifier service.
pub fn init() -> impl Service<
pub fn init<ZSF>(
state_service: ZS<ZSF>,
) -> impl Service<
Block,
Response = Response,
Error = Error,
Future = impl Future<Output = Result<Response, Error>>,
> + Send
+ Clone
+ 'static {
Buffer::new(BlockVerifier::default(), 1)
+ 'static
where
ZSF: Future<Output = Result<zebra_state::Response, ZSE>> + Send + 'static,
{
Buffer::new(BlockVerifier::<ZSF> { state_service }, 1)
}

0 comments on commit 8097c66

Please sign in to comment.