consensus: integrate block, transaction Verifiers
This commit is contained in:
parent
4a36c4485a
commit
8a64c056fb
|
@ -16,6 +16,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
use futures::stream::FuturesUnordered;
|
||||||
use futures_util::FutureExt;
|
use futures_util::FutureExt;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
|
@ -23,12 +24,16 @@ use tower::{Service, ServiceExt};
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
block::{self, Block},
|
block::{self, Block},
|
||||||
parameters::Network,
|
parameters::Network,
|
||||||
|
parameters::NetworkUpgrade,
|
||||||
work::equihash,
|
work::equihash,
|
||||||
};
|
};
|
||||||
use zebra_state as zs;
|
use zebra_state as zs;
|
||||||
|
|
||||||
use crate::error::*;
|
use crate::{
|
||||||
use crate::BoxError;
|
error::*,
|
||||||
|
transaction::{self, VerifyTransactionError},
|
||||||
|
};
|
||||||
|
use crate::{script, BoxError};
|
||||||
|
|
||||||
mod check;
|
mod check;
|
||||||
mod subsidy;
|
mod subsidy;
|
||||||
|
@ -37,16 +42,15 @@ mod tests;
|
||||||
|
|
||||||
/// A service that verifies blocks.
|
/// A service that verifies blocks.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BlockVerifier<S>
|
pub struct BlockVerifier<S> {
|
||||||
where
|
|
||||||
S: Service<zs::Request, Response = zs::Response, Error = BoxError> + Send + Clone + 'static,
|
|
||||||
S::Future: Send + 'static,
|
|
||||||
{
|
|
||||||
/// The network to be verified.
|
/// The network to be verified.
|
||||||
network: Network,
|
network: Network,
|
||||||
|
|
||||||
/// The underlying state service, possibly wrapped in other services.
|
/// The underlying state service, possibly wrapped in other services.
|
||||||
state_service: S,
|
state_service: S,
|
||||||
|
|
||||||
|
/// The transaction verification service
|
||||||
|
transaction_verifier: transaction::Verifier<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -68,6 +72,8 @@ pub enum VerifyBlockError {
|
||||||
Time(zebra_chain::block::BlockTimeError),
|
Time(zebra_chain::block::BlockTimeError),
|
||||||
#[error("unable to commit block after semantic verification")]
|
#[error("unable to commit block after semantic verification")]
|
||||||
Commit(#[source] BoxError),
|
Commit(#[source] BoxError),
|
||||||
|
#[error("invalid transaction")]
|
||||||
|
Transaction(#[source] VerifyTransactionError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> BlockVerifier<S>
|
impl<S> BlockVerifier<S>
|
||||||
|
@ -76,9 +82,14 @@ where
|
||||||
S::Future: Send + 'static,
|
S::Future: Send + 'static,
|
||||||
{
|
{
|
||||||
pub fn new(network: Network, state_service: S) -> Self {
|
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 {
|
Self {
|
||||||
network,
|
network,
|
||||||
state_service,
|
state_service,
|
||||||
|
transaction_verifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +113,7 @@ where
|
||||||
|
|
||||||
fn call(&mut self, block: Arc<Block>) -> Self::Future {
|
fn call(&mut self, block: Arc<Block>) -> Self::Future {
|
||||||
let mut state_service = self.state_service.clone();
|
let mut state_service = self.state_service.clone();
|
||||||
|
let mut transaction_verifier = self.transaction_verifier.clone();
|
||||||
let network = self.network;
|
let network = self.network;
|
||||||
|
|
||||||
// TODO(jlusby): Error = Report, handle errors from state_service.
|
// TODO(jlusby): Error = Report, handle errors from state_service.
|
||||||
|
@ -159,6 +171,23 @@ where
|
||||||
metrics::gauge!("block.verified.block.height", height.0 as _);
|
metrics::gauge!("block.verified.block.height", height.0 as _);
|
||||||
metrics::counter!("block.verified.block.count", 1);
|
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.
|
// Finally, submit the block for contextual verification.
|
||||||
match state_service
|
match state_service
|
||||||
.ready_and()
|
.ready_and()
|
||||||
|
|
Loading…
Reference in New Issue