consensus: integrate block, transaction Verifiers

This commit is contained in:
Jane Lusby 2020-10-16 15:17:49 -07:00 committed by Deirdre Connolly
parent 4a36c4485a
commit 8a64c056fb
1 changed files with 36 additions and 7 deletions

View File

@ -16,6 +16,7 @@ use std::{
};
use chrono::Utc;
use futures::stream::FuturesUnordered;
use futures_util::FutureExt;
use thiserror::Error;
use tower::{Service, ServiceExt};
@ -23,12 +24,16 @@ use tower::{Service, ServiceExt};
use zebra_chain::{
block::{self, Block},
parameters::Network,
parameters::NetworkUpgrade,
work::equihash,
};
use zebra_state as zs;
use crate::error::*;
use crate::BoxError;
use crate::{
error::*,
transaction::{self, VerifyTransactionError},
};
use crate::{script, BoxError};
mod check;
mod subsidy;
@ -37,16 +42,15 @@ mod tests;
/// A service that verifies blocks.
#[derive(Debug)]
pub struct BlockVerifier<S>
where
S: Service<zs::Request, Response = zs::Response, Error = BoxError> + Send + Clone + 'static,
S::Future: Send + 'static,
{
pub struct BlockVerifier<S> {
/// The network to be verified.
network: Network,
/// The underlying state service, possibly wrapped in other services.
state_service: S,
/// The transaction verification service
transaction_verifier: transaction::Verifier<S>,
}
#[non_exhaustive]
@ -68,6 +72,8 @@ pub enum VerifyBlockError {
Time(zebra_chain::block::BlockTimeError),
#[error("unable to commit block after semantic verification")]
Commit(#[source] BoxError),
#[error("invalid transaction")]
Transaction(#[source] VerifyTransactionError),
}
impl<S> BlockVerifier<S>
@ -76,9 +82,14 @@ where
S::Future: Send + 'static,
{
pub fn new(network: Network, state_service: S) -> Self {
let branch = NetworkUpgrade::Sapling.branch_id().unwrap();
let script_verifier = script::Verifier::new(state_service.clone(), branch);
let transaction_verifier = transaction::Verifier::new(script_verifier);
Self {
network,
state_service,
transaction_verifier,
}
}
}
@ -102,6 +113,7 @@ where
fn call(&mut self, block: Arc<Block>) -> Self::Future {
let mut state_service = self.state_service.clone();
let mut transaction_verifier = self.transaction_verifier.clone();
let network = self.network;
// TODO(jlusby): Error = Report, handle errors from state_service.
@ -159,6 +171,23 @@ where
metrics::gauge!("block.verified.block.height", height.0 as _);
metrics::counter!("block.verified.block.count", 1);
let mut async_checks = FuturesUnordered::new();
for transaction in &block.transactions {
let req = transaction::Request::Block(transaction.clone());
let rsp = transaction_verifier
.ready_and()
.await
.expect("transaction verifier is always ready")
.call(req);
async_checks.push(rsp);
}
use futures::StreamExt;
while let Some(result) = async_checks.next().await {
result.map_err(VerifyBlockError::Transaction)?;
}
// Finally, submit the block for contextual verification.
match state_service
.ready_and()