From 8f2ddef0a41be4d466b669af5ec4a099d7c29acb Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 8 Jun 2020 14:27:38 +1000 Subject: [PATCH] consensus: Add a block verification service Part of #428. --- Cargo.lock | 6 +++ zebra-consensus/Cargo.toml | 4 ++ zebra-consensus/src/lib.rs | 19 +++++---- zebra-consensus/src/verify.rs | 72 +++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 zebra-consensus/src/verify.rs diff --git a/Cargo.lock b/Cargo.lock index a2cd3e0c..c1711f60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2124,6 +2124,12 @@ version = "0.1.0" [[package]] name = "zebra-consensus" version = "0.1.0" +dependencies = [ + "futures", + "tower", + "zebra-chain", + "zebra-state", +] [[package]] name = "zebra-network" diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index 629cd74e..4a3448c4 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -8,3 +8,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +zebra-chain = { path = "../zebra-chain" } +zebra-state = { path = "../zebra-state" } +tower = "0.3.1" +futures = "0.3.5" diff --git a/zebra-consensus/src/lib.rs b/zebra-consensus/src/lib.rs index ead69bed..5054fa47 100644 --- a/zebra-consensus/src/lib.rs +++ b/zebra-consensus/src/lib.rs @@ -1,10 +1,15 @@ +//! Consensus handling for Zebra. +//! +//! `verify::BlockVerifier` verifies blocks and their transactions, then adds them to +//! `zebra_state::ZebraState`. +//! +//! `mempool::ZebraMempool` verifies transactions, and adds them to the mempool state. +//! +//! Consensus handling is provided using `tower::Service`s, to support backpressure +//! and batch verification. + #![doc(html_logo_url = "https://www.zfnd.org/images/zebra-icon.png")] #![doc(html_root_url = "https://doc.zebra.zfnd.org/zebra_consensus")] +#![deny(missing_docs)] -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} +pub mod verify; diff --git a/zebra-consensus/src/verify.rs b/zebra-consensus/src/verify.rs new file mode 100644 index 00000000..909c4fa6 --- /dev/null +++ b/zebra-consensus/src/verify.rs @@ -0,0 +1,72 @@ +//! Block verification and chain state updates for Zebra. +//! +//! Verification occurs in multiple stages: +//! - getting blocks (disk- or network-bound) +//! - context-free verification of signatures, proofs, and scripts (CPU-bound) +//! - context-dependent verification of the chain state (awaits a verified parent block) +//! +//! Verification is provided via a `tower::Service`, to support backpressure and batch +//! verification. + +use std::{ + error::Error, + future::Future, + pin::Pin, + task::{Context, Poll}, +}; +use tower::{buffer::Buffer, Service}; + +use zebra_chain::block::Block; + +/// Block verification service. +/// +/// After verification, blocks and their associated transactions are added to +/// `zebra_state::ZebraState`. +#[derive(Default)] +struct BlockVerifier {} + +/// The result type for the BlockVerifier Service. +// TODO(teor): Response = BlockHeaderHash +type Response = (); + +/// The error type for the BlockVerifier Service. +// TODO(jlusby): Error = Report ? +type ServiceError = Box; + +/// The BlockVerifier service implementation. +impl Service for BlockVerifier { + type Response = Response; + type Error = ServiceError; + type Future = + Pin> + Send + 'static>>; + + fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll> { + // TODO(teor): is this a shared state? + let mut state_service = zebra_state::in_memory::init(); + state_service.poll_ready(context) + } + + fn call(&mut self, block: Block) -> Self::Future { + let mut state_service = zebra_state::in_memory::init(); + + // Ignore errors, they are already handled correctly. + // AddBlock discards invalid blocks. + let _ = state_service.call(zebra_state::Request::AddBlock { + block: block.into(), + }); + + Box::pin(async { Ok(()) }) + } +} + +/// Initialise the BlockVerifier service. +pub fn init() -> impl Service< + Block, + Response = Response, + Error = ServiceError, + Future = impl Future>, +> + Send + + Clone + + 'static { + Buffer::new(BlockVerifier::default(), 1) +}