Skip to content

Commit

Permalink
Better Error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
rakita committed Nov 1, 2022
1 parent 4405515 commit 37b41d6
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 37 deletions.
64 changes: 32 additions & 32 deletions crates/consensus/src/verification.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! ALl functions for verification of block
use crate::{config, Config};
use auto_impl::auto_impl;
use reth_interfaces::consensus::Error;
use reth_primitives::{BlockHash, BlockLocked, Header, HeaderLocked};
use reth_interfaces::{consensus::Error, provider::HeaderProvider, Result as RethResult};
use reth_primitives::{BlockLocked, HeaderLocked, TransactionSigned};
use std::time::SystemTime;

/// Validate header standalone
Expand Down Expand Up @@ -33,6 +32,15 @@ pub fn validate_header_standalone(
Ok(())
}

/// Validate transactions standlone
pub fn validate_transactions_standalone(
_transactions: &[TransactionSigned],
_config: &Config,
) -> Result<(), Error> {
// TODO
Ok(())
}

/// Validate block standalone
pub fn validate_block_standalone(block: &BlockLocked) -> Result<(), Error> {
// check omners hash
Expand All @@ -53,6 +61,11 @@ pub fn validate_block_standalone(block: &BlockLocked) -> Result<(), Error> {
})
}

// TODO transaction verification, Maybe make it configurable as in check only
// signatures/limits/types

// check if all transactions limit does not goes over block limit

// check receipts root
let receipts_root = crate::proofs::calculate_receipt_root(block.receipts.iter());
if block.header.receipts_root != receipts_root {
Expand Down Expand Up @@ -163,53 +176,39 @@ pub fn validate_header_regarding_parent(
Ok(())
}

/// Provider needs for verification of block agains the chain
///
/// TODO wrap all function around `Result` as this can trigger internal db error.
/// I didn't know what error to put (Probably needs to be database) so i left it for later as it
/// will be easy to integrate
#[auto_impl(&)]
pub trait BlockhainProvider {
/// Check if block is known
fn is_known(&self, block_hash: &BlockHash) -> bool;

/// Get header by block hash
fn header(&self, block_number: &BlockHash) -> Option<Header>;
}

/// Validate block in regards to chain (parent)
///
/// Checks:
/// If we already know the block.
/// If parent is known
///
/// Returns parent block header
pub fn validate_block_regarding_chain<PROV: BlockhainProvider>(
pub fn validate_block_regarding_chain<PROV: HeaderProvider>(
block: &BlockLocked,
provider: PROV,
) -> Result<HeaderLocked, Error> {
provider: &PROV,
) -> RethResult<HeaderLocked> {
let hash = block.header.hash();

// Check if block is known.
if provider.is_known(&hash) {
return Err(Error::BlockKnown { hash, number: block.header.number })
if provider.is_known(&hash)? {
return Err(Error::BlockKnown { hash, number: block.header.number }.into())
}

// Check if parent is known.
let parent = provider
.header(&block.parent_hash)
.header(&block.parent_hash)?
.ok_or(Error::ParentUnknown { hash: block.parent_hash })?;

// Return parent header.
Ok(parent.lock())
}

/// Full validation of block before execution.
pub fn full_validation<PROV: BlockhainProvider>(
pub fn full_validation<PROV: HeaderProvider>(
block: &BlockLocked,
provider: PROV,
config: &Config,
) -> Result<(), Error> {
) -> RethResult<()> {
validate_header_standalone(&block.header, config)?;
validate_block_standalone(block)?;
let parent = validate_block_regarding_chain(block, &provider)?;
Expand All @@ -219,7 +218,8 @@ pub fn full_validation<PROV: BlockhainProvider>(

#[cfg(test)]
mod tests {
use reth_primitives::hex_literal::hex;
use reth_interfaces::Result;
use reth_primitives::{hex_literal::hex, BlockHash, Header};

use super::*;

Expand Down Expand Up @@ -266,13 +266,13 @@ mod tests {
}
}

impl BlockhainProvider for Provider {
fn is_known(&self, _block_hash: &BlockHash) -> bool {
self.is_known
impl HeaderProvider for Provider {
fn is_known(&self, _block_hash: &BlockHash) -> Result<bool> {
Ok(self.is_known)
}

fn header(&self, _block_number: &BlockHash) -> Option<Header> {
self.parent.clone()
fn header(&self, _block_number: &BlockHash) -> Result<Option<Header>> {
Ok(self.parent.clone())
}
}
/// got test block
Expand Down Expand Up @@ -330,7 +330,7 @@ mod tests {

assert_eq!(
full_validation(&block, provider, &config),
Err(Error::BlockKnown { hash: block.hash(), number: block.number }),
Err(Error::BlockKnown { hash: block.hash(), number: block.number }.into()),
"Should fail with error"
);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/executor/src/revm_wrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl<DB: ExecutorDb> State<DB> {
}

/// Consume State and return inner DbExecutable.
pub fn unwrap(self) -> DB {
pub fn into_inner(self) -> DB {
self.0
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/interfaces/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pub type Result<T> = std::result::Result<T, Error>;

/// Core error variants possible when interacting with the blockchain
#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Expand Down
2 changes: 1 addition & 1 deletion crates/interfaces/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub trait BlockExecutor {
}

/// BlockExecutor Errors
#[derive(Error, Debug, Clone)]
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum Error {
/// Example of error
#[error("Example of error.")]
Expand Down
15 changes: 14 additions & 1 deletion crates/interfaces/src/provider/block.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
use crate::Result;
use auto_impl::auto_impl;
use reth_primitives::{
rpc::{BlockId, BlockNumber},
Block, H256, U256,
Block, BlockHash, Header, H256, U256,
};

/// Client trait for fetching `Header` related data.
#[auto_impl(&)]
pub trait HeaderProvider: Send + Sync + 'static {
/// Check if block is known
fn is_known(&self, block_hash: &BlockHash) -> Result<bool> {
self.header(block_hash).map(|header| header.is_some())
}

/// Get header by block hash
fn header(&self, block_hash: &BlockHash) -> Result<Option<Header>>;
}

/// Client trait for fetching `Block` related data.
pub trait BlockProvider: Send + Sync + 'static {
/// Returns the current info for the chain.
Expand Down
2 changes: 1 addition & 1 deletion crates/interfaces/src/provider/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod block;
mod storage;

pub use block::BlockProvider;
pub use block::{BlockProvider, HeaderProvider};
pub use storage::StorageProvider;

0 comments on commit 37b41d6

Please sign in to comment.