2020-10-16 16:44:30 -07:00
|
|
|
//! Consensus-based block verification.
|
2020-07-09 23:51:01 -07:00
|
|
|
//!
|
2020-10-16 16:44:30 -07:00
|
|
|
//! In contrast to checkpoint verification, which only checks hardcoded
|
|
|
|
//! hashes, block verification checks all Zcash consensus rules.
|
2020-07-09 23:51:01 -07:00
|
|
|
//!
|
2020-10-16 16:44:30 -07:00
|
|
|
//! The block verifier performs all of the semantic validation checks.
|
|
|
|
//! If accepted, the block is sent to the state service for contextual
|
|
|
|
//! verification, where it may be accepted or rejected.
|
2020-07-09 23:51:01 -07:00
|
|
|
|
|
|
|
use std::{
|
|
|
|
future::Future,
|
|
|
|
pin::Pin,
|
|
|
|
sync::Arc,
|
|
|
|
task::{Context, Poll},
|
|
|
|
};
|
2020-09-09 18:53:40 -07:00
|
|
|
|
|
|
|
use chrono::Utc;
|
2020-10-16 15:17:49 -07:00
|
|
|
use futures::stream::FuturesUnordered;
|
2020-09-09 18:53:40 -07:00
|
|
|
use futures_util::FutureExt;
|
2020-09-21 11:54:06 -07:00
|
|
|
use thiserror::Error;
|
2020-09-09 20:16:11 -07:00
|
|
|
use tower::{Service, ServiceExt};
|
2020-11-19 16:55:36 -08:00
|
|
|
use tracing::Instrument;
|
2020-07-09 23:51:01 -07:00
|
|
|
|
2023-01-11 15:39:51 -08:00
|
|
|
use zebra_chain::{amount::Amount, block, parameters::Network, transparent, work::equihash};
|
2020-09-09 18:53:40 -07:00
|
|
|
use zebra_state as zs;
|
|
|
|
|
2021-08-25 08:07:26 -07:00
|
|
|
use crate::{error::*, transaction as tx, BoxError};
|
2020-09-09 18:53:40 -07:00
|
|
|
|
2021-03-10 18:10:47 -08:00
|
|
|
pub mod check;
|
2023-01-11 15:39:51 -08:00
|
|
|
pub mod request;
|
2022-11-09 16:12:27 -08:00
|
|
|
pub mod subsidy;
|
2021-08-25 08:07:26 -07:00
|
|
|
|
2023-01-11 15:39:51 -08:00
|
|
|
pub use request::Request;
|
|
|
|
|
2020-09-09 18:53:40 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
2020-07-09 23:51:01 -07:00
|
|
|
|
2023-06-01 05:29:03 -07:00
|
|
|
/// Asynchronous semantic block verification.
|
2020-07-30 17:21:20 -07:00
|
|
|
#[derive(Debug)]
|
2023-06-01 05:29:03 -07:00
|
|
|
pub struct SemanticBlockVerifier<S, V> {
|
2020-10-12 13:54:48 -07:00
|
|
|
/// The network to be verified.
|
|
|
|
network: Network,
|
2020-07-09 23:51:01 -07:00
|
|
|
state_service: S,
|
2021-08-25 08:07:26 -07:00
|
|
|
transaction_verifier: V,
|
2020-07-09 23:51:01 -07:00
|
|
|
}
|
|
|
|
|
2020-10-26 23:42:27 -07:00
|
|
|
// TODO: dedupe with crate::error::BlockError
|
2020-09-21 11:54:06 -07:00
|
|
|
#[non_exhaustive]
|
2021-10-19 18:07:19 -07:00
|
|
|
#[allow(missing_docs)]
|
2020-09-21 11:54:06 -07:00
|
|
|
#[derive(Debug, Error)]
|
|
|
|
pub enum VerifyBlockError {
|
|
|
|
#[error("unable to verify depth for block {hash} from chain state during block verification")]
|
|
|
|
Depth { source: BoxError, hash: block::Hash },
|
2020-10-26 23:42:27 -07:00
|
|
|
|
2020-09-21 11:54:06 -07:00
|
|
|
#[error(transparent)]
|
|
|
|
Block {
|
|
|
|
#[from]
|
|
|
|
source: BlockError,
|
|
|
|
},
|
2020-10-26 23:42:27 -07:00
|
|
|
|
2020-09-21 11:54:06 -07:00
|
|
|
#[error(transparent)]
|
|
|
|
Equihash {
|
|
|
|
#[from]
|
|
|
|
source: equihash::Error,
|
|
|
|
},
|
2020-10-26 23:42:27 -07:00
|
|
|
|
2020-09-21 11:54:06 -07:00
|
|
|
#[error(transparent)]
|
2020-10-12 14:33:32 -07:00
|
|
|
Time(zebra_chain::block::BlockTimeError),
|
2020-10-26 23:42:27 -07:00
|
|
|
|
2020-09-21 11:54:06 -07:00
|
|
|
#[error("unable to commit block after semantic verification")]
|
2022-12-07 22:11:33 -08:00
|
|
|
// TODO: make this into a concrete type, and add it to is_duplicate_request() (#2908)
|
2020-09-21 11:54:06 -07:00
|
|
|
Commit(#[source] BoxError),
|
2020-10-26 23:42:27 -07:00
|
|
|
|
2023-01-11 15:39:51 -08:00
|
|
|
#[cfg(feature = "getblocktemplate-rpcs")]
|
|
|
|
#[error("unable to validate block proposal: failed semantic verification (proof of work is not checked for proposals)")]
|
|
|
|
// TODO: make this into a concrete type (see #5732)
|
|
|
|
ValidateProposal(#[source] BoxError),
|
|
|
|
|
2020-10-16 15:17:49 -07:00
|
|
|
#[error("invalid transaction")]
|
2021-08-25 08:07:26 -07:00
|
|
|
Transaction(#[from] TransactionError),
|
2020-09-21 11:54:06 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 22:11:33 -08:00
|
|
|
impl VerifyBlockError {
|
|
|
|
/// Returns `true` if this is definitely a duplicate request.
|
|
|
|
/// Some duplicate requests might not be detected, and therefore return `false`.
|
|
|
|
pub fn is_duplicate_request(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
VerifyBlockError::Block { source, .. } => source.is_duplicate_request(),
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-15 12:55:32 -08:00
|
|
|
/// The maximum allowed number of legacy signature check operations in a block.
|
|
|
|
///
|
|
|
|
/// This consensus rule is not documented, so Zebra follows the `zcashd` implementation.
|
|
|
|
/// We re-use some `zcashd` C++ script code via `zebra-script` and `zcash_script`.
|
|
|
|
///
|
|
|
|
/// See:
|
2022-05-30 13:12:11 -07:00
|
|
|
/// <https://github.com/zcash/zcash/blob/bad7f7eadbbb3466bebe3354266c7f69f607fcfd/src/consensus/consensus.h#L30>
|
2021-11-15 12:55:32 -08:00
|
|
|
pub const MAX_BLOCK_SIGOPS: u64 = 20_000;
|
|
|
|
|
2023-06-01 05:29:03 -07:00
|
|
|
impl<S, V> SemanticBlockVerifier<S, V>
|
2020-09-09 20:16:11 -07:00
|
|
|
where
|
|
|
|
S: Service<zs::Request, Response = zs::Response, Error = BoxError> + Send + Clone + 'static,
|
|
|
|
S::Future: Send + 'static,
|
2021-08-25 08:07:26 -07:00
|
|
|
V: Service<tx::Request, Response = tx::Response, Error = BoxError> + Send + Clone + 'static,
|
|
|
|
V::Future: Send + 'static,
|
2020-09-09 20:16:11 -07:00
|
|
|
{
|
2023-06-01 05:29:03 -07:00
|
|
|
/// Creates a new SemanticBlockVerifier
|
2021-08-25 08:07:26 -07:00
|
|
|
pub fn new(network: Network, state_service: S, transaction_verifier: V) -> Self {
|
2020-10-12 13:54:48 -07:00
|
|
|
Self {
|
|
|
|
network,
|
|
|
|
state_service,
|
2020-10-16 15:17:49 -07:00
|
|
|
transaction_verifier,
|
2020-10-12 13:54:48 -07:00
|
|
|
}
|
2020-09-09 20:16:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-01 05:29:03 -07:00
|
|
|
impl<S, V> Service<Request> for SemanticBlockVerifier<S, V>
|
2020-07-09 23:51:01 -07:00
|
|
|
where
|
2020-09-09 18:53:40 -07:00
|
|
|
S: Service<zs::Request, Response = zs::Response, Error = BoxError> + Send + Clone + 'static,
|
2020-07-09 23:51:01 -07:00
|
|
|
S::Future: Send + 'static,
|
2021-08-25 08:07:26 -07:00
|
|
|
V: Service<tx::Request, Response = tx::Response, Error = BoxError> + Send + Clone + 'static,
|
|
|
|
V::Future: Send + 'static,
|
2020-07-09 23:51:01 -07:00
|
|
|
{
|
2020-08-15 23:20:01 -07:00
|
|
|
type Response = block::Hash;
|
2020-09-21 11:54:06 -07:00
|
|
|
type Error = VerifyBlockError;
|
2020-07-09 23:51:01 -07:00
|
|
|
type Future =
|
|
|
|
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
|
|
|
|
|
|
|
|
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
2020-07-20 18:31:01 -07:00
|
|
|
// We use the state for contextual verification, and we expect those
|
|
|
|
// queries to be fast. So we don't need to call
|
|
|
|
// `state_service.poll_ready()` here.
|
2020-07-09 23:51:01 -07:00
|
|
|
Poll::Ready(Ok(()))
|
|
|
|
}
|
|
|
|
|
2023-01-11 15:39:51 -08:00
|
|
|
fn call(&mut self, request: Request) -> Self::Future {
|
2020-09-02 21:23:57 -07:00
|
|
|
let mut state_service = self.state_service.clone();
|
2020-10-16 15:17:49 -07:00
|
|
|
let mut transaction_verifier = self.transaction_verifier.clone();
|
2020-10-12 13:54:48 -07:00
|
|
|
let network = self.network;
|
2020-07-09 23:51:01 -07:00
|
|
|
|
2023-01-11 15:39:51 -08:00
|
|
|
let block = request.block();
|
|
|
|
|
2020-11-19 16:55:36 -08:00
|
|
|
// We don't include the block hash, because it's likely already in a parent span
|
|
|
|
let span = tracing::debug_span!("block", height = ?block.coinbase_height());
|
|
|
|
|
2020-07-09 23:51:01 -07:00
|
|
|
async move {
|
2020-11-19 16:55:36 -08:00
|
|
|
let hash = block.hash();
|
2020-09-09 18:53:40 -07:00
|
|
|
// Check that this block is actually a new block.
|
2020-11-20 15:17:36 -08:00
|
|
|
tracing::trace!("checking that block is not already in state");
|
2020-09-21 11:54:06 -07:00
|
|
|
match state_service
|
2021-11-02 11:46:57 -07:00
|
|
|
.ready()
|
2020-09-21 11:54:06 -07:00
|
|
|
.await
|
|
|
|
.map_err(|source| VerifyBlockError::Depth { source, hash })?
|
2023-03-24 00:10:07 -07:00
|
|
|
.call(zs::Request::KnownBlock(hash))
|
2020-09-21 11:54:06 -07:00
|
|
|
.await
|
|
|
|
.map_err(|source| VerifyBlockError::Depth { source, hash })?
|
|
|
|
{
|
2023-03-24 00:10:07 -07:00
|
|
|
zs::Response::KnownBlock(Some(location)) => {
|
|
|
|
return Err(BlockError::AlreadyInChain(hash, location).into())
|
2020-09-21 11:54:06 -07:00
|
|
|
}
|
2023-03-24 00:10:07 -07:00
|
|
|
zs::Response::KnownBlock(None) => {}
|
|
|
|
_ => unreachable!("wrong response to Request::KnownBlock"),
|
2020-09-09 18:53:40 -07:00
|
|
|
}
|
|
|
|
|
2020-11-20 15:17:36 -08:00
|
|
|
tracing::trace!("performing block checks");
|
2020-08-05 22:26:26 -07:00
|
|
|
let height = block
|
|
|
|
.coinbase_height()
|
2020-09-28 18:10:51 -07:00
|
|
|
.ok_or(BlockError::MissingHeight(hash))?;
|
2021-11-15 12:55:32 -08:00
|
|
|
|
2022-02-10 16:32:57 -08:00
|
|
|
// Zebra does not support heights greater than
|
|
|
|
// [`block::Height::MAX`].
|
2020-08-16 11:42:02 -07:00
|
|
|
if height > block::Height::MAX {
|
2020-09-21 11:54:06 -07:00
|
|
|
Err(BlockError::MaxHeight(height, hash, block::Height::MAX))?;
|
2020-08-05 22:26:26 -07:00
|
|
|
}
|
|
|
|
|
2023-01-11 15:39:51 -08:00
|
|
|
// > The block data MUST be validated and checked against the server's usual
|
|
|
|
// > acceptance rules (excluding the check for a valid proof-of-work).
|
|
|
|
// <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
|
|
|
|
if request.is_proposal() {
|
|
|
|
check::difficulty_threshold_is_valid(&block.header, network, &height, &hash)?;
|
|
|
|
} else {
|
|
|
|
// Do the difficulty checks first, to raise the threshold for
|
|
|
|
// attacks that use any other fields.
|
|
|
|
check::difficulty_is_valid(&block.header, network, &height, &hash)?;
|
|
|
|
check::equihash_solution_is_valid(&block.header)?;
|
|
|
|
}
|
2020-08-03 00:37:08 -07:00
|
|
|
|
2020-11-30 15:24:29 -08:00
|
|
|
// Next, check the Merkle root validity, to ensure that
|
|
|
|
// the header binds to the transactions in the blocks.
|
2020-07-09 23:51:01 -07:00
|
|
|
|
2020-11-24 19:55:15 -08:00
|
|
|
// Precomputing this avoids duplicating transaction hash computations.
|
2021-08-30 11:42:07 -07:00
|
|
|
let transaction_hashes: Arc<[_]> =
|
|
|
|
block.transactions.iter().map(|t| t.hash()).collect();
|
2020-11-24 19:55:15 -08:00
|
|
|
|
2021-05-09 18:31:45 -07:00
|
|
|
check::merkle_root_validity(network, &block, &transaction_hashes)?;
|
2020-08-03 00:37:08 -07:00
|
|
|
|
2020-11-30 15:24:29 -08:00
|
|
|
// Since errors cause an early exit, try to do the
|
|
|
|
// quick checks first.
|
|
|
|
|
2021-11-23 07:31:56 -08:00
|
|
|
// Quick field validity and structure checks
|
2020-11-30 15:24:29 -08:00
|
|
|
let now = Utc::now();
|
|
|
|
check::time_is_valid_at(&block.header, now, &height, &hash)
|
|
|
|
.map_err(VerifyBlockError::Time)?;
|
2022-04-20 02:31:12 -07:00
|
|
|
let coinbase_tx = check::coinbase_is_first(&block)?;
|
2020-11-30 15:24:29 -08:00
|
|
|
check::subsidy_is_valid(&block, network)?;
|
|
|
|
|
2021-11-23 07:31:56 -08:00
|
|
|
// Now do the slower checks
|
|
|
|
|
|
|
|
// Check compatibility with ZIP-212 shielded Sapling and Orchard coinbase output decryption
|
2022-04-20 02:31:12 -07:00
|
|
|
tx::check::coinbase_outputs_are_decryptable(&coinbase_tx, network, height)?;
|
2021-11-23 07:31:56 -08:00
|
|
|
|
|
|
|
// Send transactions to the transaction verifier to be checked
|
2020-10-16 15:17:49 -07:00
|
|
|
let mut async_checks = FuturesUnordered::new();
|
|
|
|
|
2021-07-19 06:52:32 -07:00
|
|
|
let known_utxos = Arc::new(transparent::new_ordered_outputs(
|
|
|
|
&block,
|
|
|
|
&transaction_hashes,
|
|
|
|
));
|
2020-10-16 15:17:49 -07:00
|
|
|
for transaction in &block.transactions {
|
|
|
|
let rsp = transaction_verifier
|
2021-11-02 11:46:57 -07:00
|
|
|
.ready()
|
2020-10-16 15:17:49 -07:00
|
|
|
.await
|
|
|
|
.expect("transaction verifier is always ready")
|
2020-11-24 19:55:15 -08:00
|
|
|
.call(tx::Request::Block {
|
2020-11-20 19:47:30 -08:00
|
|
|
transaction: transaction.clone(),
|
|
|
|
known_utxos: known_utxos.clone(),
|
2020-11-24 12:30:58 -08:00
|
|
|
height,
|
2021-11-22 21:53:53 -08:00
|
|
|
time: block.header.time,
|
2020-11-20 19:47:30 -08:00
|
|
|
});
|
2020-10-16 15:17:49 -07:00
|
|
|
async_checks.push(rsp);
|
|
|
|
}
|
2020-11-20 15:17:36 -08:00
|
|
|
tracing::trace!(len = async_checks.len(), "built async tx checks");
|
2020-10-16 15:17:49 -07:00
|
|
|
|
2021-11-23 07:31:56 -08:00
|
|
|
// Get the transaction results back from the transaction verifier.
|
|
|
|
|
|
|
|
// Sum up some block totals from the transaction responses.
|
2021-11-15 12:55:32 -08:00
|
|
|
let mut legacy_sigop_count = 0;
|
2021-11-23 07:31:56 -08:00
|
|
|
let mut block_miner_fees = Ok(Amount::zero());
|
2021-11-15 12:55:32 -08:00
|
|
|
|
2020-10-16 15:17:49 -07:00
|
|
|
use futures::StreamExt;
|
|
|
|
while let Some(result) = async_checks.next().await {
|
2020-11-20 15:17:36 -08:00
|
|
|
tracing::trace!(?result, remaining = async_checks.len());
|
2021-11-15 12:55:32 -08:00
|
|
|
let response = result
|
2021-08-25 08:07:26 -07:00
|
|
|
.map_err(Into::into)
|
|
|
|
.map_err(VerifyBlockError::Transaction)?;
|
2021-11-23 07:31:56 -08:00
|
|
|
|
|
|
|
assert!(
|
|
|
|
matches!(response, tx::Response::Block { .. }),
|
2022-12-07 17:05:57 -08:00
|
|
|
"unexpected response from transaction verifier: {response:?}"
|
2021-11-23 07:31:56 -08:00
|
|
|
);
|
|
|
|
|
2022-11-03 10:03:41 -07:00
|
|
|
legacy_sigop_count += response.legacy_sigop_count();
|
2021-11-23 07:31:56 -08:00
|
|
|
|
|
|
|
// Coinbase transactions consume the miner fee,
|
|
|
|
// so they don't add any value to the block's total miner fee.
|
|
|
|
if let Some(miner_fee) = response.miner_fee() {
|
|
|
|
block_miner_fees += miner_fee;
|
|
|
|
}
|
2021-11-15 12:55:32 -08:00
|
|
|
}
|
|
|
|
|
2021-11-23 07:31:56 -08:00
|
|
|
// Check the summed block totals
|
|
|
|
|
2021-11-15 12:55:32 -08:00
|
|
|
if legacy_sigop_count > MAX_BLOCK_SIGOPS {
|
|
|
|
Err(BlockError::TooManyTransparentSignatureOperations {
|
|
|
|
height,
|
|
|
|
hash,
|
|
|
|
legacy_sigop_count,
|
|
|
|
})?;
|
2020-10-16 15:17:49 -07:00
|
|
|
}
|
2020-10-26 06:11:52 -07:00
|
|
|
|
2021-11-23 19:36:17 -08:00
|
|
|
let block_miner_fees =
|
2021-11-23 07:31:56 -08:00
|
|
|
block_miner_fees.map_err(|amount_error| BlockError::SummingMinerFees {
|
|
|
|
height,
|
|
|
|
hash,
|
|
|
|
source: amount_error,
|
|
|
|
})?;
|
2021-11-23 19:36:17 -08:00
|
|
|
check::miner_fees_are_valid(&block, network, block_miner_fees)?;
|
2021-11-23 07:31:56 -08:00
|
|
|
|
|
|
|
// Finally, submit the block for contextual verification.
|
2023-06-21 13:44:53 -07:00
|
|
|
let new_outputs = Arc::into_inner(known_utxos)
|
state: introduce PreparedBlock, FinalizedBlock
This change introduces two new types:
- `PreparedBlock`, representing a block which has undergone semantic
validation and has been prepared for contextual validation;
- `FinalizedBlock`, representing a block which is ready to be finalized
immediately;
and changes the `Request::CommitBlock`,`Request::CommitFinalizedBlock`
variants to use these types instead of their previous fields.
This change solves the problem of passing data between semantic
validation and contextual validation, and cleans up the state code by
allowing it to pass around a bundle of data. Previously, the state code
just passed around an `Arc<Block>`, which forced it to needlessly
recompute block hashes and other data, and was incompatible with the
already-known but not-yet-implemented data transfer requirements, namely
passing in the Sprout and Sapling anchors computed during contextual
validation.
This commit propagates the `PreparedBlock` and `FinalizedBlock` types
through the state code but only uses their data opportunistically, e.g.,
changing .hash() computations to use the precomputed hash. In the
future, these structures can be extended to pass data through the
verification pipeline for reuse as appropriate. For instance, these
changes allow the sprout and sapling anchors to be propagated through
the state.
2020-11-21 01:16:14 -08:00
|
|
|
.expect("all verification tasks using known_utxos are complete");
|
2021-08-19 09:55:36 -07:00
|
|
|
|
2023-06-01 05:29:03 -07:00
|
|
|
let prepared_block = zs::SemanticallyVerifiedBlock {
|
state: introduce PreparedBlock, FinalizedBlock
This change introduces two new types:
- `PreparedBlock`, representing a block which has undergone semantic
validation and has been prepared for contextual validation;
- `FinalizedBlock`, representing a block which is ready to be finalized
immediately;
and changes the `Request::CommitBlock`,`Request::CommitFinalizedBlock`
variants to use these types instead of their previous fields.
This change solves the problem of passing data between semantic
validation and contextual validation, and cleans up the state code by
allowing it to pass around a bundle of data. Previously, the state code
just passed around an `Arc<Block>`, which forced it to needlessly
recompute block hashes and other data, and was incompatible with the
already-known but not-yet-implemented data transfer requirements, namely
passing in the Sprout and Sapling anchors computed during contextual
validation.
This commit propagates the `PreparedBlock` and `FinalizedBlock` types
through the state code but only uses their data opportunistically, e.g.,
changing .hash() computations to use the precomputed hash. In the
future, these structures can be extended to pass data through the
verification pipeline for reuse as appropriate. For instance, these
changes allow the sprout and sapling anchors to be propagated through
the state.
2020-11-21 01:16:14 -08:00
|
|
|
block,
|
|
|
|
hash,
|
|
|
|
height,
|
|
|
|
new_outputs,
|
2020-11-24 19:55:15 -08:00
|
|
|
transaction_hashes,
|
state: introduce PreparedBlock, FinalizedBlock
This change introduces two new types:
- `PreparedBlock`, representing a block which has undergone semantic
validation and has been prepared for contextual validation;
- `FinalizedBlock`, representing a block which is ready to be finalized
immediately;
and changes the `Request::CommitBlock`,`Request::CommitFinalizedBlock`
variants to use these types instead of their previous fields.
This change solves the problem of passing data between semantic
validation and contextual validation, and cleans up the state code by
allowing it to pass around a bundle of data. Previously, the state code
just passed around an `Arc<Block>`, which forced it to needlessly
recompute block hashes and other data, and was incompatible with the
already-known but not-yet-implemented data transfer requirements, namely
passing in the Sprout and Sapling anchors computed during contextual
validation.
This commit propagates the `PreparedBlock` and `FinalizedBlock` types
through the state code but only uses their data opportunistically, e.g.,
changing .hash() computations to use the precomputed hash. In the
future, these structures can be extended to pass data through the
verification pipeline for reuse as appropriate. For instance, these
changes allow the sprout and sapling anchors to be propagated through
the state.
2020-11-21 01:16:14 -08:00
|
|
|
};
|
2023-01-11 15:39:51 -08:00
|
|
|
|
|
|
|
// Return early for proposal requests when getblocktemplate-rpcs feature is enabled
|
|
|
|
#[cfg(feature = "getblocktemplate-rpcs")]
|
|
|
|
if request.is_proposal() {
|
|
|
|
return match state_service
|
|
|
|
.ready()
|
|
|
|
.await
|
|
|
|
.map_err(VerifyBlockError::ValidateProposal)?
|
|
|
|
.call(zs::Request::CheckBlockProposalValidity(prepared_block))
|
|
|
|
.await
|
|
|
|
.map_err(VerifyBlockError::ValidateProposal)?
|
|
|
|
{
|
|
|
|
zs::Response::ValidBlockProposal => Ok(hash),
|
|
|
|
_ => unreachable!("wrong response for CheckBlockProposalValidity"),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-09-10 10:34:59 -07:00
|
|
|
match state_service
|
2021-11-02 11:46:57 -07:00
|
|
|
.ready()
|
2020-09-21 11:54:06 -07:00
|
|
|
.await
|
|
|
|
.map_err(VerifyBlockError::Commit)?
|
2023-06-01 05:29:03 -07:00
|
|
|
.call(zs::Request::CommitSemanticallyVerifiedBlock(prepared_block))
|
2020-09-21 11:54:06 -07:00
|
|
|
.await
|
|
|
|
.map_err(VerifyBlockError::Commit)?
|
2020-09-10 10:34:59 -07:00
|
|
|
{
|
2020-09-09 18:53:40 -07:00
|
|
|
zs::Response::Committed(committed_hash) => {
|
2020-09-10 10:34:59 -07:00
|
|
|
assert_eq!(committed_hash, hash, "state must commit correct hash");
|
2020-09-02 21:23:57 -07:00
|
|
|
Ok(hash)
|
|
|
|
}
|
2023-06-01 05:29:03 -07:00
|
|
|
_ => unreachable!("wrong response for CommitSemanticallyVerifiedBlock"),
|
2020-09-02 21:23:57 -07:00
|
|
|
}
|
2020-07-09 23:51:01 -07:00
|
|
|
}
|
2020-11-19 16:55:36 -08:00
|
|
|
.instrument(span)
|
2020-07-09 23:51:01 -07:00
|
|
|
.boxed()
|
|
|
|
}
|
|
|
|
}
|