Skip to content

Commit

Permalink
feat: add pending receipts (#3320)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Jun 22, 2023
1 parent a4c2f5f commit e8b09cc
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 20 deletions.
13 changes: 11 additions & 2 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use reth_interfaces::{
Error,
};
use reth_primitives::{
BlockHash, BlockNumHash, BlockNumber, ForkBlock, Hardfork, SealedBlock, SealedBlockWithSenders,
SealedHeader, U256,
BlockHash, BlockNumHash, BlockNumber, ForkBlock, Hardfork, Receipt, SealedBlock,
SealedBlockWithSenders, SealedHeader, U256,
};
use reth_provider::{
chain::{ChainSplit, SplitAt},
Expand Down Expand Up @@ -217,6 +217,15 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTree<DB, C, EF>
chain.block(block_hash)
}

/// Returns the block's receipts with matching hash from any side-chain.
///
/// Caution: This will not return blocks from the canonical chain.
pub fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<&[Receipt]> {
let id = self.block_indices.get_blocks_chain_id(&block_hash)?;
let chain = self.chains.get(&id)?;
chain.receipts_by_block_hash(block_hash)
}

/// Returns true if the block is included in a side-chain.
fn is_block_hash_inside_chain(&self, block_hash: BlockHash) -> bool {
self.block_by_hash(block_hash).is_some()
Expand Down
8 changes: 7 additions & 1 deletion crates/blockchain-tree/src/shareable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use reth_interfaces::{
Error,
};
use reth_primitives::{
BlockHash, BlockNumHash, BlockNumber, SealedBlock, SealedBlockWithSenders, SealedHeader,
BlockHash, BlockNumHash, BlockNumber, Receipt, SealedBlock, SealedBlockWithSenders,
SealedHeader,
};
use reth_provider::{
BlockchainTreePendingStateProvider, CanonStateSubscriptions, ExecutorFactory,
Expand Down Expand Up @@ -152,6 +153,11 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTreeViewer
trace!(target: "blockchain_tree", "Returning first pending block");
self.tree.read().pending_block().cloned()
}

fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<Receipt>> {
let tree = self.tree.read();
Some(tree.receipts_by_block_hash(block_hash)?.to_vec())
}
}

impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTreePendingStateProvider
Expand Down
11 changes: 10 additions & 1 deletion crates/interfaces/src/blockchain_tree/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{blockchain_tree::error::InsertBlockError, Error};
use reth_primitives::{
BlockHash, BlockNumHash, BlockNumber, SealedBlock, SealedBlockWithSenders, SealedHeader,
BlockHash, BlockNumHash, BlockNumber, Receipt, SealedBlock, SealedBlockWithSenders,
SealedHeader,
};
use std::collections::{BTreeMap, HashSet};

Expand Down Expand Up @@ -215,6 +216,14 @@ pub trait BlockchainTreeViewer: Send + Sync {
self.block_by_hash(self.pending_block_num_hash()?.hash)
}

/// Returns the pending receipts if there is one.
fn pending_receipts(&self) -> Option<Vec<Receipt>> {
self.receipts_by_block_hash(self.pending_block_num_hash()?.hash)
}

/// Returns the pending receipts if there is one.
fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<Receipt>>;

/// Returns the pending block if there is one.
fn pending_header(&self) -> Option<SealedHeader> {
self.header_by_hash(self.pending_block_num_hash()?.hash)
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/rpc/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
use async_trait::async_trait;
use jsonrpsee::core::RpcResult;
use reth_primitives::{Account, Block, BlockId, BlockNumberOrTag, Bytes, TransactionSigned, H256};
use reth_provider::{BlockProviderIdExt, HeaderProvider, ReceiptProviderIdExt, StateProviderBox};
use reth_provider::{BlockProviderIdExt, HeaderProvider, StateProviderBox};
use reth_revm::{
database::{State, SubState},
env::tx_env_with_recovered,
Expand Down
6 changes: 6 additions & 0 deletions crates/storage/provider/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ impl Chain {
Self { state, blocks: block_num_hash }
}

/// Get all receipts for the given block.
pub fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<&[Receipt]> {
let num = self.block_number(block_hash)?;
Some(self.state.receipts(num))
}

/// Get all receipts with attachment.
///
/// Attachment includes block number, block hash, transaction hash and transaction index.
Expand Down
37 changes: 34 additions & 3 deletions crates/storage/provider/src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
BlockHashProvider, BlockIdProvider, BlockNumProvider, BlockProvider, BlockProviderIdExt,
BlockchainTreePendingStateProvider, CanonChainTracker, CanonStateNotifications,
CanonStateSubscriptions, EvmEnvProvider, HeaderProvider, PostStateDataProvider, ProviderError,
ReceiptProvider, StageCheckpointReader, StateProviderBox, StateProviderFactory,
TransactionsProvider, WithdrawalsProvider,
ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProviderBox,
StateProviderFactory, TransactionsProvider, WithdrawalsProvider,
};
use reth_db::{database::Database, models::StoredBlockBodyIndices};
use reth_interfaces::{
Expand Down Expand Up @@ -327,6 +327,33 @@ where
self.database.provider()?.receipts_by_block(block)
}
}
impl<DB, Tree> ReceiptProviderIdExt for BlockchainProvider<DB, Tree>
where
DB: Database,
Tree: BlockchainTreeViewer + Send + Sync,
{
fn receipts_by_block_id(&self, block: BlockId) -> Result<Option<Vec<Receipt>>> {
match block {
BlockId::Hash(rpc_block_hash) => {
let mut receipts = self.receipts_by_block(rpc_block_hash.block_hash.into())?;
if receipts.is_none() && !rpc_block_hash.require_canonical.unwrap_or(false) {
receipts = self.tree.receipts_by_block_hash(rpc_block_hash.block_hash);
}
Ok(receipts)
}
BlockId::Number(num_tag) => match num_tag {
BlockNumberOrTag::Pending => Ok(self.tree.pending_receipts()),
_ => {
if let Some(num) = self.convert_block_number(num_tag)? {
self.receipts_by_block(num.into())
} else {
Ok(None)
}
}
},
}
}
}

impl<DB, Tree> WithdrawalsProvider for BlockchainProvider<DB, Tree>
where
Expand Down Expand Up @@ -600,6 +627,10 @@ where
fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
self.tree.pending_block_num_hash()
}

fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<Receipt>> {
self.tree.receipts_by_block_hash(block_hash)
}
}

impl<DB, Tree> CanonChainTracker for BlockchainProvider<DB, Tree>
Expand Down Expand Up @@ -640,7 +671,7 @@ where

impl<DB, Tree> BlockProviderIdExt for BlockchainProvider<DB, Tree>
where
Self: BlockProvider + BlockIdProvider,
Self: BlockProvider + BlockIdProvider + ReceiptProviderIdExt,
Tree: BlockchainTreeEngine,
{
fn block_by_id(&self, id: BlockId) -> Result<Option<Block>> {
Expand Down
6 changes: 4 additions & 2 deletions crates/storage/provider/src/test_utils/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
traits::{BlockSource, ReceiptProvider},
AccountReader, BlockHashProvider, BlockIdProvider, BlockNumProvider, BlockProvider,
BlockProviderIdExt, EvmEnvProvider, HeaderProvider, PostState, PostStateDataProvider,
StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, TransactionsProvider,
WithdrawalsProvider,
ReceiptProviderIdExt, StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider,
TransactionsProvider, WithdrawalsProvider,
};
use parking_lot::Mutex;
use reth_db::models::StoredBlockBodyIndices;
Expand Down Expand Up @@ -239,6 +239,8 @@ impl ReceiptProvider for MockEthProvider {
}
}

impl ReceiptProviderIdExt for MockEthProvider {}

impl BlockHashProvider for MockEthProvider {
fn block_hash(&self, number: u64) -> Result<Option<H256>> {
let lock = self.blocks.lock();
Expand Down
8 changes: 5 additions & 3 deletions crates/storage/provider/src/test_utils/noop.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
traits::{BlockSource, ReceiptProvider},
AccountReader, BlockHashProvider, BlockIdProvider, BlockNumProvider, BlockProvider,
BlockProviderIdExt, EvmEnvProvider, HeaderProvider, PostState, StageCheckpointReader,
StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, TransactionsProvider,
WithdrawalsProvider,
BlockProviderIdExt, EvmEnvProvider, HeaderProvider, PostState, ReceiptProviderIdExt,
StageCheckpointReader, StateProvider, StateProviderBox, StateProviderFactory,
StateRootProvider, TransactionsProvider, WithdrawalsProvider,
};
use reth_db::models::StoredBlockBodyIndices;
use reth_interfaces::Result;
Expand Down Expand Up @@ -179,6 +179,8 @@ impl ReceiptProvider for NoopProvider {
}
}

impl ReceiptProviderIdExt for NoopProvider {}

impl HeaderProvider for NoopProvider {
fn header(&self, _block_hash: &BlockHash) -> Result<Option<Header>> {
Ok(None)
Expand Down
6 changes: 3 additions & 3 deletions crates/storage/provider/src/traits/block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
BlockIdProvider, BlockNumProvider, HeaderProvider, ReceiptProvider, TransactionsProvider,
WithdrawalsProvider,
BlockIdProvider, BlockNumProvider, HeaderProvider, ReceiptProvider, ReceiptProviderIdExt,
TransactionsProvider, WithdrawalsProvider,
};
use reth_db::models::StoredBlockBodyIndices;
use reth_interfaces::Result;
Expand Down Expand Up @@ -113,7 +113,7 @@ pub trait BlockProvider:
/// `BlockIdProvider` methods should be used to resolve `BlockId`s to block numbers or hashes, and
/// retrieving the block should be done using the type's `BlockProvider` methods.
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockProviderIdExt: BlockProvider + BlockIdProvider {
pub trait BlockProviderIdExt: BlockProvider + BlockIdProvider + ReceiptProviderIdExt {
/// Returns the block with matching tag from the database
///
/// Returns `None` if block is not found.
Expand Down
21 changes: 17 additions & 4 deletions crates/storage/provider/src/traits/receipts.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
use reth_interfaces::Result;
use reth_primitives::{BlockHashOrNumber, BlockId, Receipt, TxHash, TxNumber};
use reth_primitives::{BlockHashOrNumber, BlockId, BlockNumberOrTag, Receipt, TxHash, TxNumber};

use crate::BlockIdProvider;

/// Client trait for fetching [Receipt] data .
#[auto_impl::auto_impl(&, Arc)]
pub trait ReceiptProvider: Send + Sync {
/// Get receipt by transaction number
///
/// Returns `None` if the transaction is not found.
fn receipt(&self, id: TxNumber) -> Result<Option<Receipt>>;

/// Get receipt by transaction hash.
///
/// Returns `None` if the transaction is not found.
fn receipt_by_hash(&self, hash: TxHash) -> Result<Option<Receipt>>;

/// Get receipts by block num or hash.
///
/// Returns `None` if the block is not found.
fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result<Option<Vec<Receipt>>>;
}

Expand All @@ -29,7 +35,6 @@ pub trait ReceiptProvider: Send + Sync {
pub trait ReceiptProviderIdExt: ReceiptProvider + BlockIdProvider {
/// Get receipt by block id
fn receipts_by_block_id(&self, block: BlockId) -> Result<Option<Vec<Receipt>>> {
// TODO: to implement EIP-1898 at the provider level or not
let id = match block {
BlockId::Hash(hash) => BlockHashOrNumber::Hash(hash.block_hash),
BlockId::Number(num_tag) => {
Expand All @@ -43,6 +48,14 @@ pub trait ReceiptProviderIdExt: ReceiptProvider + BlockIdProvider {

self.receipts_by_block(id)
}
}

impl<T> ReceiptProviderIdExt for T where T: ReceiptProvider + BlockIdProvider {}
/// Returns the block with the matching `BlockId` from the database.
///
/// Returns `None` if block is not found.
fn receipts_by_number_or_tag(
&self,
number_or_tag: BlockNumberOrTag,
) -> Result<Option<Vec<Receipt>>> {
self.receipts_by_block_id(number_or_tag.into())
}
}

0 comments on commit e8b09cc

Please sign in to comment.