From bd18188be91eddc9983277ff659d62a13ef70c42 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 18 Oct 2022 22:04:04 +0200 Subject: [PATCH] feat: add block provider trait (#90) * feat: add block provider trait * rustmft * rename BlockInfo to ChainInfo --- crates/interfaces/src/error.rs | 13 +++++ crates/interfaces/src/lib.rs | 8 +++ crates/interfaces/src/provider/block.rs | 71 +++++++++++++++++++++++++ crates/interfaces/src/provider/mod.rs | 3 ++ 4 files changed, 95 insertions(+) create mode 100644 crates/interfaces/src/error.rs create mode 100644 crates/interfaces/src/provider/block.rs create mode 100644 crates/interfaces/src/provider/mod.rs diff --git a/crates/interfaces/src/error.rs b/crates/interfaces/src/error.rs new file mode 100644 index 000000000..d1d3f5fb5 --- /dev/null +++ b/crates/interfaces/src/error.rs @@ -0,0 +1,13 @@ +/// Result alias for `Error` +pub type Result = std::result::Result; + +/// Core error variants possible when interacting with the blockchain +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum Error { + #[error(transparent)] + Execution(#[from] crate::executor::Error), + + #[error(transparent)] + Consensus(#[from] crate::consensus::Error), +} diff --git a/crates/interfaces/src/lib.rs b/crates/interfaces/src/lib.rs index c7624b35d..bf9766c68 100644 --- a/crates/interfaces/src/lib.rs +++ b/crates/interfaces/src/lib.rs @@ -12,3 +12,11 @@ pub mod executor; /// Consensus traits. pub mod consensus; + +/// Traits that provide chain access. +pub mod provider; + +/// Possible errors when interacting with the chain. +mod error; + +pub use error::{Error, Result}; diff --git a/crates/interfaces/src/provider/block.rs b/crates/interfaces/src/provider/block.rs new file mode 100644 index 000000000..3a7d439c9 --- /dev/null +++ b/crates/interfaces/src/provider/block.rs @@ -0,0 +1,71 @@ +use crate::Result; +use reth_primitives::{ + rpc::{BlockId, BlockNumber}, + Block, H256, U256, +}; + +/// Client trait for fetching `Block` related data. +pub trait BlockProvider: Send + Sync { + /// Returns the current info for the chain. + fn chain_info(&self) -> Result; + + /// Returns the block. Returns `None` if block is not found. + fn block(&self, id: BlockId) -> Result>; + + /// Converts the `BlockNumber` variants. + fn convert_block_number( + &self, + num: BlockNumber, + ) -> Result> { + let num = match num { + BlockNumber::Latest => self.chain_info()?.best_number, + BlockNumber::Earliest => 0, + BlockNumber::Pending => return Ok(None), + BlockNumber::Number(num) => num.as_u64(), + }; + Ok(Some(num)) + } + + /// Get the hash of the block by matching the given id. + fn block_hash_for_id(&self, block_id: BlockId) -> Result> { + match block_id { + BlockId::Hash(hash) => Ok(Some(hash)), + BlockId::Number(num) => { + if matches!(num, BlockNumber::Latest) { + return Ok(Some(self.chain_info()?.best_hash)) + } + self.convert_block_number(num)? + .map(|num| self.block_hash(num.into())) + .transpose() + .map(|maybe_hash| maybe_hash.flatten()) + } + } + } + + /// Get the number of the block by matching the given id. + fn block_number_for_id( + &self, + block_id: BlockId, + ) -> Result> { + match block_id { + BlockId::Hash(hash) => self.block_number(hash), + BlockId::Number(num) => self.convert_block_number(num), + } + } + + /// Gets the `Block` for the given hash. Returns `None` if no block with this hash exists. + fn block_number(&self, hash: H256) -> Result>; + + /// Get the hash of the block with the given number. Returns `None` if no block with this number + /// exists. + fn block_hash(&self, number: U256) -> Result>; +} + +/// Current status of the blockchain's head. +#[derive(Debug, Eq, PartialEq)] +pub struct ChainInfo { + /// Best block hash. + pub best_hash: H256, + /// Best block number. + pub best_number: reth_primitives::BlockNumber, +} diff --git a/crates/interfaces/src/provider/mod.rs b/crates/interfaces/src/provider/mod.rs new file mode 100644 index 000000000..6b8087081 --- /dev/null +++ b/crates/interfaces/src/provider/mod.rs @@ -0,0 +1,3 @@ +mod block; + +pub use block::BlockProvider;