191 lines
5.5 KiB
Rust
191 lines
5.5 KiB
Rust
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
|
// This file is part of Parity Ethereum.
|
|
|
|
// Parity Ethereum is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// Parity Ethereum is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! Definition of valid items for the verification queue.
|
|
|
|
use engine::Engine;
|
|
|
|
use parity_util_mem::MallocSizeOf;
|
|
use ethereum_types::{H256, U256};
|
|
|
|
use common_types::errors::EthcoreError as Error;
|
|
|
|
pub use self::blocks::Blocks;
|
|
pub use self::headers::Headers;
|
|
|
|
/// Something which can produce a hash and a parent hash.
|
|
pub trait BlockLike {
|
|
/// Get the hash of this item.
|
|
fn hash(&self) -> H256;
|
|
|
|
/// Get the hash of this item's parent.
|
|
fn parent_hash(&self) -> H256;
|
|
|
|
/// Get the difficulty of this item.
|
|
fn difficulty(&self) -> U256;
|
|
}
|
|
|
|
/// Defines transitions between stages of verification.
|
|
///
|
|
/// It starts with a fallible transformation from an "input" into the unverified item.
|
|
/// This consists of quick, simply done checks as well as extracting particular data.
|
|
///
|
|
/// Then, there is a `verify` function which performs more expensive checks and
|
|
/// produces the verified output.
|
|
///
|
|
/// For correctness, the hashes produced by each stage of the pipeline should be
|
|
/// consistent.
|
|
pub trait Kind: 'static + Sized + Send + Sync {
|
|
/// The first stage: completely unverified.
|
|
type Input: Sized + Send + BlockLike + MallocSizeOf;
|
|
|
|
/// The second stage: partially verified.
|
|
type Unverified: Sized + Send + BlockLike + MallocSizeOf;
|
|
|
|
/// The third stage: completely verified.
|
|
type Verified: Sized + Send + BlockLike + MallocSizeOf;
|
|
|
|
/// Attempt to create the `Unverified` item from the input.
|
|
fn create(input: Self::Input, engine: &dyn Engine, check_seal: bool) -> Result<Self::Unverified, (Self::Input, Error)>;
|
|
|
|
/// Attempt to verify the `Unverified` item using the given engine.
|
|
fn verify(unverified: Self::Unverified, engine: &dyn Engine, check_seal: bool) -> Result<Self::Verified, Error>;
|
|
}
|
|
|
|
/// The blocks verification module.
|
|
pub mod blocks {
|
|
use super::{Kind, BlockLike};
|
|
|
|
use engine::Engine;
|
|
use common_types::{
|
|
block::PreverifiedBlock,
|
|
errors::{EthcoreError as Error, BlockError},
|
|
verification::Unverified,
|
|
};
|
|
use log::{debug, warn};
|
|
use crate::verification::{verify_block_basic, verify_block_unordered};
|
|
|
|
use ethereum_types::{H256, U256};
|
|
|
|
/// A mode for verifying blocks.
|
|
pub struct Blocks;
|
|
|
|
impl Kind for Blocks {
|
|
type Input = Unverified;
|
|
type Unverified = Unverified;
|
|
type Verified = PreverifiedBlock;
|
|
|
|
fn create(input: Self::Input, engine: &dyn Engine, check_seal: bool) -> Result<Self::Unverified, (Self::Input, Error)> {
|
|
match verify_block_basic(&input, engine, check_seal) {
|
|
Ok(()) => Ok(input),
|
|
Err(Error::Block(BlockError::TemporarilyInvalid(oob))) => {
|
|
debug!(target: "client", "Block received too early {}: {:?}", input.hash(), oob);
|
|
Err((input, BlockError::TemporarilyInvalid(oob).into()))
|
|
},
|
|
Err(e) => {
|
|
warn!(target: "client", "Stage 1 block verification failed for {}: {:?}", input.hash(), e);
|
|
Err((input, e))
|
|
}
|
|
}
|
|
}
|
|
|
|
fn verify(un: Self::Unverified, engine: &dyn Engine, check_seal: bool) -> Result<Self::Verified, Error> {
|
|
let hash = un.hash();
|
|
match verify_block_unordered(un, engine, check_seal) {
|
|
Ok(verified) => Ok(verified),
|
|
Err(e) => {
|
|
warn!(target: "client", "Stage 2 block verification failed for {}: {:?}", hash, e);
|
|
Err(e)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BlockLike for Unverified {
|
|
fn hash(&self) -> H256 {
|
|
self.header.hash()
|
|
}
|
|
|
|
fn parent_hash(&self) -> H256 {
|
|
self.header.parent_hash().clone()
|
|
}
|
|
|
|
fn difficulty(&self) -> U256 {
|
|
self.header.difficulty().clone()
|
|
}
|
|
}
|
|
|
|
impl BlockLike for PreverifiedBlock {
|
|
fn hash(&self) -> H256 {
|
|
self.header.hash()
|
|
}
|
|
|
|
fn parent_hash(&self) -> H256 {
|
|
self.header.parent_hash().clone()
|
|
}
|
|
|
|
fn difficulty(&self) -> U256 {
|
|
self.header.difficulty().clone()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Verification for headers.
|
|
pub mod headers {
|
|
use super::{Kind, BlockLike};
|
|
|
|
use engine::Engine;
|
|
use common_types::{
|
|
header::Header,
|
|
errors::EthcoreError as Error,
|
|
};
|
|
use crate::verification::{verify_header_params, verify_header_time};
|
|
|
|
use ethereum_types::{H256, U256};
|
|
|
|
impl BlockLike for Header {
|
|
fn hash(&self) -> H256 { self.hash() }
|
|
fn parent_hash(&self) -> H256 { self.parent_hash().clone() }
|
|
fn difficulty(&self) -> U256 { self.difficulty().clone() }
|
|
}
|
|
|
|
/// A mode for verifying headers.
|
|
pub struct Headers;
|
|
|
|
impl Kind for Headers {
|
|
type Input = Header;
|
|
type Unverified = Header;
|
|
type Verified = Header;
|
|
|
|
fn create(input: Self::Input, engine: &dyn Engine, check_seal: bool) -> Result<Self::Unverified, (Self::Input, Error)> {
|
|
let res = verify_header_params(&input, engine, check_seal)
|
|
.and_then(|_| verify_header_time(&input));
|
|
|
|
match res {
|
|
Ok(_) => Ok(input),
|
|
Err(err) => Err((input, err))
|
|
}
|
|
}
|
|
|
|
fn verify(unverified: Self::Unverified, engine: &dyn Engine, check_seal: bool) -> Result<Self::Verified, Error> {
|
|
match check_seal {
|
|
true => engine.verify_block_unordered(&unverified,).map(|_| unverified),
|
|
false => Ok(unverified),
|
|
}
|
|
}
|
|
}
|
|
}
|