mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: add pending receipts (#3320)
This commit is contained in:
@ -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},
|
||||
@ -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()
|
||||
|
||||
@ -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,
|
||||
@ -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
|
||||
|
||||
@ -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};
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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::{
|
||||
@ -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
|
||||
@ -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>
|
||||
@ -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>> {
|
||||
|
||||
@ -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;
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
@ -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.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{BlockHashOrNumber, BlockId, Receipt, TxHash, TxNumber};
|
||||
use reth_primitives::{BlockHashOrNumber, BlockId, BlockNumberOrTag, Receipt, TxHash, TxNumber};
|
||||
|
||||
use crate::BlockIdProvider;
|
||||
|
||||
@ -7,12 +7,18 @@ use crate::BlockIdProvider;
|
||||
#[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>>>;
|
||||
}
|
||||
|
||||
@ -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) => {
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user