From eb43893de0f0e0f18a8af89c33d24abd4b574109 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Fri, 16 Oct 2020 16:44:30 -0700 Subject: [PATCH] consensus: minimize API, clean docs This reduces the API surface to the minimum required for functionality, and cleans up module documentation. The stub mempool module is deleted entirely, since it will need to be redone later anyways. --- zebra-consensus/src/block.rs | 19 ++++------- zebra-consensus/src/checkpoint.rs | 22 ++++++------ zebra-consensus/src/config.rs | 2 -- zebra-consensus/src/error.rs | 7 +++- zebra-consensus/src/lib.rs | 20 +++++------ zebra-consensus/src/mempool.rs | 29 ---------------- zebra-consensus/src/script.rs | 34 +++++++++---------- zebra-utils/src/bin/zebra-checkpoints/main.rs | 2 +- zebrad/src/components/sync.rs | 7 ++-- 9 files changed, 55 insertions(+), 87 deletions(-) delete mode 100644 zebra-consensus/src/mempool.rs diff --git a/zebra-consensus/src/block.rs b/zebra-consensus/src/block.rs index b12a71eb..aed15fdd 100644 --- a/zebra-consensus/src/block.rs +++ b/zebra-consensus/src/block.rs @@ -1,12 +1,11 @@ -//! Block verification for Zebra. +//! Consensus-based block verification. //! -//! 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 (depends on previous blocks) +//! In contrast to checkpoint verification, which only checks hardcoded +//! hashes, block verification checks all Zcash consensus rules. //! -//! Verification is provided via a `tower::Service`, to support backpressure and batch -//! verification. +//! 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. use std::{ future::Future, @@ -40,16 +39,12 @@ mod subsidy; #[cfg(test)] mod tests; -/// A service that verifies blocks. +/// Asynchronous block verification. #[derive(Debug)] pub struct BlockVerifier { /// 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, } diff --git a/zebra-consensus/src/checkpoint.rs b/zebra-consensus/src/checkpoint.rs index 1ae074ad..7e27c542 100644 --- a/zebra-consensus/src/checkpoint.rs +++ b/zebra-consensus/src/checkpoint.rs @@ -1,17 +1,17 @@ -//! Checkpoint-based block verification for Zebra. +//! Checkpoint-based block verification. //! -//! Checkpoint-based verification uses a list of checkpoint hashes to speed up the -//! initial chain sync for Zebra. This list is distributed with Zebra. +//! Checkpoint-based verification uses a list of checkpoint hashes to +//! speed up the initial chain sync for Zebra. This list is distributed +//! with Zebra. //! -//! The CheckpointVerifier queues pending blocks. Once there is a chain from the -//! previous checkpoint to a target checkpoint, it verifies all the blocks in -//! that chain. +//! The checkpoint verifier queues pending blocks. Once there is a +//! chain from the previous checkpoint to a target checkpoint, it +//! verifies all the blocks in that chain, and sends accepted blocks to +//! the state service as finalized chain state, skipping contextual +//! verification checks. //! -//! Verification starts at the first checkpoint, which is the genesis block for the -//! configured network. -//! -//! Verification is provided via a `tower::Service`, to support backpressure and batch -//! verification. +//! Verification starts at the first checkpoint, which is the genesis +//! block for the configured network. use std::{ collections::BTreeMap, diff --git a/zebra-consensus/src/config.rs b/zebra-consensus/src/config.rs index 661cd457..c66766b2 100644 --- a/zebra-consensus/src/config.rs +++ b/zebra-consensus/src/config.rs @@ -1,5 +1,3 @@ -//! Configuration for zebra-consensus - use serde::{Deserialize, Serialize}; /// Consensus configuration. diff --git a/zebra-consensus/src/error.rs b/zebra-consensus/src/error.rs index 27b456a4..5b836d3d 100644 --- a/zebra-consensus/src/error.rs +++ b/zebra-consensus/src/error.rs @@ -1,4 +1,9 @@ -//! Consensus validation errors +//! Errors that can occur when checking consensus rules. +//! +//! Each error variant corresponds to a consensus rule, so enumerating +//! all possible verification failures enumerates the consensus rules we +//! implement, and ensures that we don't reject blocks or transactions +//! for a non-enumerated reason. use thiserror::Error; diff --git a/zebra-consensus/src/lib.rs b/zebra-consensus/src/lib.rs index 442f56dc..fd2e0a71 100644 --- a/zebra-consensus/src/lib.rs +++ b/zebra-consensus/src/lib.rs @@ -37,20 +37,20 @@ //#![deny(missing_docs)] #![allow(clippy::try_err)] -pub mod block; -pub mod chain; -pub mod checkpoint; -pub mod config; -pub mod error; -pub mod mempool; -pub mod parameters; -pub mod script; - +mod block; +mod checkpoint; +mod config; +mod parameters; #[allow(dead_code)] // Remove this once transaction verification is implemented mod primitives; +mod script; mod transaction; -pub use crate::config::Config; +pub mod chain; +pub mod error; + +pub use checkpoint::MAX_CHECKPOINT_HEIGHT_GAP; +pub use config::Config; /// A boxed [`std::error::Error`]. pub type BoxError = Box; diff --git a/zebra-consensus/src/mempool.rs b/zebra-consensus/src/mempool.rs deleted file mode 100644 index e1e5f95b..00000000 --- a/zebra-consensus/src/mempool.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! Mempool transaction verification and state for Zebra. -//! -//! Mempool updates occur in multiple stages: -//! - getting transactions (disk- or network-bound) -//! - context-free verification of signatures, proofs, and scripts (CPU-bound) -//! - context-dependent verification of mempool transactions against the chain state -//! (awaits an up-to-date chain) -//! - adding transactions to the mempool -//! -//! The mempool is provided via a `tower::Service`, to support backpressure and batch -//! verification. - -/// Mempool state. -/// -/// New transactions are verified, checked against the chain state, then added to the -/// mempool. -/// -/// `ZebraMempoolState` is not yet implemented. -#[derive(Default)] -struct ZebraMempoolState {} - -/// Mempool transaction verification. -/// -/// New transactions are verified, checked against the chain state, then added to the -/// mempool. -/// -/// `MempoolTransactionVerifier` is not yet implemented. -#[derive(Default)] -struct MempoolTransactionVerifier {} diff --git a/zebra-consensus/src/script.rs b/zebra-consensus/src/script.rs index 0b342e1a..4d37c1a0 100644 --- a/zebra-consensus/src/script.rs +++ b/zebra-consensus/src/script.rs @@ -1,17 +1,3 @@ -//! Script verification for Zebra. -//! -//! Verification occurs in multiple stages: -//! - getting transactions from blocks or the mempool (disk- or network-bound) -//! - context-free verification of scripts, signatures, and proofs (CPU-bound) -//! - context-dependent verification of transactions against the chain state -//! (awaits an up-to-date chain) -//! -//! Verification is provided via a `tower::Service`, to support backpressure and batch -//! verification. -//! -//! This is an internal module. Use `verify::BlockVerifier` for blocks and their -//! transactions, or `mempool::MempoolTransactionVerifier` for mempool transactions. - use std::{pin::Pin, sync::Arc}; use std::future::Future; @@ -19,10 +5,17 @@ use zebra_chain::{parameters::ConsensusBranchId, transaction::Transaction, trans use crate::BoxError; -/// Internal script verification service. +/// Asynchronous script verification. /// -/// After verification, the script future completes. State changes are handled by -/// `BlockVerifier` or `MempoolTransactionVerifier`. +/// The verifier asynchronously requests the UTXO a transaction attempts +/// to use as an input, and verifies the script as soon as it becomes +/// available. This allows script verification to be performed +/// asynchronously, rather than requiring that the entire chain up to +/// the previous block is ready. +/// +/// The asynchronous script verification design is documented in [RFC4]. +/// +/// [RFC4]: https://zebra.zfnd.org/dev/rfcs/0004-asynchronous-script-verification.html #[derive(Debug, Clone)] pub struct Verifier { state: ZS, @@ -35,6 +28,13 @@ impl Verifier { } } +/// A script verification request. +/// +/// Ideally, this would supply only an `Outpoint` and the unlock script, +/// rather than the entire `Transaction`, but we call a C++ +/// implementation, and its FFI requires the entire transaction. +/// At some future point, we could investigate reducing the size of the +/// request. #[derive(Debug)] pub struct Request { pub transaction: Arc, diff --git a/zebra-utils/src/bin/zebra-checkpoints/main.rs b/zebra-utils/src/bin/zebra-checkpoints/main.rs index 456f75f4..17184305 100644 --- a/zebra-utils/src/bin/zebra-checkpoints/main.rs +++ b/zebra-utils/src/bin/zebra-checkpoints/main.rs @@ -152,7 +152,7 @@ fn main() -> Result<()> { // check if checkpoint if height == block::Height(0) || cumulative_bytes >= MAX_CHECKPOINT_BYTE_COUNT - || height_gap.0 >= zebra_consensus::checkpoint::MAX_CHECKPOINT_HEIGHT_GAP as u32 + || height_gap.0 >= zebra_consensus::MAX_CHECKPOINT_HEIGHT_GAP as u32 { // print to output println!("{} {}", height.0, &hex::encode(hash.0),); diff --git a/zebrad/src/components/sync.rs b/zebrad/src/components/sync.rs index 1609f4b2..a9362d6a 100644 --- a/zebrad/src/components/sync.rs +++ b/zebrad/src/components/sync.rs @@ -13,13 +13,12 @@ use zebra_chain::{ block::{self, Block}, parameters::{genesis_hash, Network}, }; -use zebra_consensus::checkpoint; use zebra_network as zn; use zebra_state as zs; /// Controls the number of peers used for each ObtainTips and ExtendTips request. -// XXX in the future, we may not be able to access the checkpoint module. -const FANOUT: usize = checkpoint::MAX_QUEUED_BLOCKS_PER_HEIGHT; +const FANOUT: usize = 4; + /// Controls how many times we will retry each block download. /// /// If all the retries fail, then the syncer will reset, and start downloading @@ -40,7 +39,7 @@ const BLOCK_DOWNLOAD_RETRY_LIMIT: usize = 5; /// /// Some checkpoints contain larger blocks, so the maximum checkpoint gap can /// represent multiple gigabytes of data. -const LOOKAHEAD_LIMIT: usize = checkpoint::MAX_CHECKPOINT_HEIGHT_GAP * 2; +const LOOKAHEAD_LIMIT: usize = zebra_consensus::MAX_CHECKPOINT_HEIGHT_GAP * 2; /// Controls how long we wait for a tips response to return. ///