chore: add find_block_by_hash and more docs (#2405)

This commit is contained in:
Matthias Seitz
2023-04-26 14:58:18 +02:00
committed by GitHub
parent a7b3749312
commit 0678137a0d
7 changed files with 99 additions and 14 deletions

View File

@ -11,7 +11,7 @@
/// Various provider traits.
mod traits;
pub use traits::{
AccountProvider, BlockExecutor, BlockHashProvider, BlockIdProvider, BlockProvider,
AccountProvider, BlockExecutor, BlockHashProvider, BlockIdProvider, BlockProvider, BlockSource,
BlockchainTreePendingStateProvider, CanonStateNotification, CanonStateNotificationSender,
CanonStateNotifications, CanonStateSubscriptions, EvmEnvProvider, ExecutorFactory,
HeaderProvider, PostStateDataProvider, ReceiptProvider, StateProvider, StateProviderBox,

View File

@ -1,6 +1,6 @@
use crate::{
providers::state::{historical::HistoricalStateProvider, latest::LatestStateProvider},
traits::ReceiptProvider,
traits::{BlockSource, ReceiptProvider},
BlockHashProvider, BlockIdProvider, BlockProvider, EvmEnvProvider, HeaderProvider,
ProviderError, StateProviderBox, TransactionsProvider, WithdrawalsProvider,
};
@ -158,6 +158,14 @@ impl<DB: Database> BlockIdProvider for ShareableDatabase<DB> {
}
impl<DB: Database> BlockProvider for ShareableDatabase<DB> {
fn find_block_by_hash(&self, hash: H256, source: BlockSource) -> Result<Option<Block>> {
if source.is_database() {
self.block(hash.into())
} else {
Ok(None)
}
}
fn block(&self, id: BlockId) -> Result<Option<Block>> {
if let Some(number) = self.block_number_for_id(id)? {
if let Some(header) = self.header_by_number(number)? {

View File

@ -27,6 +27,7 @@ use std::{
mod database;
mod post_state_provider;
mod state;
use crate::traits::BlockSource;
pub use database::*;
pub use post_state_provider::PostStateProvider;
@ -140,6 +141,25 @@ where
DB: Database,
Tree: BlockchainTreeViewer + Send + Sync,
{
fn find_block_by_hash(&self, hash: H256, source: BlockSource) -> Result<Option<Block>> {
let block = match source {
BlockSource::Any => {
// check pending source first
// Note: it's fine to return the unsealed block because the caller already has the
// hash
let mut block = self.tree.block_by_hash(hash).map(|block| block.unseal());
if block.is_none() {
block = self.database.block_by_hash(hash)?;
}
block
}
BlockSource::Pending => self.tree.block_by_hash(hash).map(|block| block.unseal()),
BlockSource::Database => self.database.block_by_hash(hash)?,
};
Ok(block)
}
fn block(&self, id: BlockId) -> Result<Option<Block>> {
self.database.block(id)
}

View File

@ -1,7 +1,8 @@
use crate::{
traits::ReceiptProvider, AccountProvider, BlockHashProvider, BlockIdProvider, BlockProvider,
EvmEnvProvider, HeaderProvider, PostState, PostStateDataProvider, StateProvider,
StateProviderBox, StateProviderFactory, StateRootProvider, TransactionsProvider,
traits::{BlockSource, ReceiptProvider},
AccountProvider, BlockHashProvider, BlockIdProvider, BlockProvider, EvmEnvProvider,
HeaderProvider, PostState, PostStateDataProvider, StateProvider, StateProviderBox,
StateProviderFactory, StateRootProvider, TransactionsProvider,
};
use parking_lot::Mutex;
use reth_interfaces::Result;
@ -254,6 +255,10 @@ impl BlockIdProvider for MockEthProvider {
}
impl BlockProvider for MockEthProvider {
fn find_block_by_hash(&self, hash: H256, _source: BlockSource) -> Result<Option<Block>> {
self.block(hash.into())
}
fn block(&self, id: BlockId) -> Result<Option<Block>> {
let lock = self.blocks.lock();
match id {

View File

@ -1,7 +1,8 @@
use crate::{
traits::ReceiptProvider, AccountProvider, BlockHashProvider, BlockIdProvider, BlockProvider,
EvmEnvProvider, HeaderProvider, PostState, StateProvider, StateProviderBox,
StateProviderFactory, StateRootProvider, TransactionsProvider,
traits::{BlockSource, ReceiptProvider},
AccountProvider, BlockHashProvider, BlockIdProvider, BlockProvider, EvmEnvProvider,
HeaderProvider, PostState, StateProvider, StateProviderBox, StateProviderFactory,
StateRootProvider, TransactionsProvider,
};
use reth_interfaces::Result;
use reth_primitives::{
@ -43,6 +44,10 @@ impl BlockIdProvider for NoopProvider {
}
impl BlockProvider for NoopProvider {
fn find_block_by_hash(&self, hash: H256, _source: BlockSource) -> Result<Option<Block>> {
self.block(hash.into())
}
fn block(&self, _id: BlockId) -> Result<Option<Block>> {
Ok(None)
}

View File

@ -2,32 +2,79 @@ use crate::{BlockIdProvider, HeaderProvider, ReceiptProvider, TransactionsProvid
use reth_interfaces::Result;
use reth_primitives::{Block, BlockId, BlockNumberOrTag, Header, H256};
/// A helper enum that represents the origin of the requested block.
///
/// This helper type's sole purpose is to give the caller more control over from where blocks can be
/// fetched.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum BlockSource {
/// Check all available sources.
///
/// Note: it's expected that looking up pending blocks is faster than looking up blocks in the
/// database so this prioritizes Pending > Database.
#[default]
Any,
/// The block was fetched from the pending block source, the blockchain tree that buffers
/// blocks that are not yet finalized.
Pending,
/// The block was fetched from the database.
Database,
}
impl BlockSource {
/// Returns `true` if the block source is `Pending` or `Any`.
pub fn is_pending(&self) -> bool {
matches!(self, BlockSource::Pending | BlockSource::Any)
}
/// Returns `true` if the block source is `Database` or `Any`.
pub fn is_database(&self) -> bool {
matches!(self, BlockSource::Database | BlockSource::Any)
}
}
/// Api trait for fetching `Block` related data.
///
/// If not requested otherwise, implementers of this trait should prioritize fetching blocks from
/// the database.
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockProvider:
BlockIdProvider + HeaderProvider + TransactionsProvider + ReceiptProvider + Send + Sync
{
/// Returns the block.
/// Tries to find in the given block source.
///
/// Note: this only operates on the hash because the number might be ambiguous.
///
/// Returns `None` if block is not found.
fn find_block_by_hash(&self, hash: H256, source: BlockSource) -> Result<Option<Block>>;
/// Returns the block with given id from the database.
///
/// Returns `None` if block is not found.
fn block(&self, id: BlockId) -> Result<Option<Block>>;
/// Returns the ommers/uncle headers of the given block.
/// Returns the ommers/uncle headers of the given block from the database.
///
/// Returns `None` if block is not found.
fn ommers(&self, id: BlockId) -> Result<Option<Vec<Header>>>;
/// Returns the block. Returns `None` if block is not found.
/// Returns the block with matching hash from the database.
///
/// Returns `None` if block is not found.
fn block_by_hash(&self, hash: H256) -> Result<Option<Block>> {
self.block(hash.into())
}
/// Returns the block. Returns `None` if block is not found.
/// Returns the block with matching tag from the database
///
/// Returns `None` if block is not found.
fn block_by_number_or_tag(&self, num: BlockNumberOrTag) -> Result<Option<Block>> {
self.block(num.into())
}
/// Returns the block. Returns `None` if block is not found.
/// Returns the block with matching number from database.
///
/// Returns `None` if block is not found.
fn block_by_number(&self, num: u64) -> Result<Option<Block>> {
self.block(num.into())
}

View File

@ -4,7 +4,7 @@ mod account;
pub use account::AccountProvider;
mod block;
pub use block::BlockProvider;
pub use block::{BlockProvider, BlockSource};
mod block_hash;
pub use block_hash::BlockHashProvider;