consensus: Make the state service pluggable in block verification
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
@@ -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;
@@ -36,21 +51,20 @@ 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.
@@ -58,7 +72,7 @@ impl Service<Block> for BlockVerifier {
// 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(),
});
@@ -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)
}
