feat: store safe block num as well (#11648)

This commit is contained in:
Matthias Seitz
2024-10-10 19:32:15 +02:00
committed by GitHub
parent 250785f833
commit 1ba631ba95
14 changed files with 130 additions and 44 deletions

View File

@ -1,8 +1,8 @@
use crate::{
providers::StaticFileProvider, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader,
BlockReader, BlockReaderIdExt, BlockSource, CanonChainTracker, CanonStateNotifications,
CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, DatabaseProviderFactory,
DatabaseProviderRO, EvmEnvProvider, FinalizedBlockReader, HeaderProvider, ProviderError,
CanonStateSubscriptions, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader,
DatabaseProviderFactory, DatabaseProviderRO, EvmEnvProvider, HeaderProvider, ProviderError,
ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt,
RequestsProvider, StageCheckpointReader, StateProviderBox, StateProviderFactory, StateReader,
StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
@ -93,9 +93,23 @@ impl<N: ProviderNodeTypes> BlockchainProvider2<N> {
.map(|num| provider.sealed_header(num))
.transpose()?
.flatten();
let safe_header = provider
.last_safe_block_number()?
.or_else(|| {
// for the purpose of this we can also use the finalized block if we don't have the
// safe block
provider.last_finalized_block_number().ok().flatten()
})
.map(|num| provider.sealed_header(num))
.transpose()?
.flatten();
Ok(Self {
database,
canonical_in_memory_state: CanonicalInMemoryState::with_head(latest, finalized_header),
canonical_in_memory_state: CanonicalInMemoryState::with_head(
latest,
finalized_header,
safe_header,
),
})
}

View File

@ -7,13 +7,14 @@ use crate::{
},
writer::UnifiedStorageWriter,
AccountReader, BlockExecutionReader, BlockExecutionWriter, BlockHashReader, BlockNumReader,
BlockReader, BlockWriter, BundleStateInit, DBProvider, EvmEnvProvider, FinalizedBlockReader,
FinalizedBlockWriter, HashingWriter, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider,
HistoricalStateProvider, HistoryWriter, LatestStateProvider, OriginalValuesKnown,
ProviderError, PruneCheckpointReader, PruneCheckpointWriter, RequestsProvider, RevertsInit,
StageCheckpointReader, StateChangeWriter, StateProviderBox, StateReader, StateWriter,
StaticFileProviderFactory, StatsReader, StorageReader, StorageTrieWriter, TransactionVariant,
TransactionsProvider, TransactionsProviderExt, TrieWriter, WithdrawalsProvider,
BlockReader, BlockWriter, BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter,
DBProvider, EvmEnvProvider, HashingWriter, HeaderProvider, HeaderSyncGap,
HeaderSyncGapProvider, HistoricalStateProvider, HistoryWriter, LatestStateProvider,
OriginalValuesKnown, ProviderError, PruneCheckpointReader, PruneCheckpointWriter,
RequestsProvider, RevertsInit, StageCheckpointReader, StateChangeWriter, StateProviderBox,
StateReader, StateWriter, StaticFileProviderFactory, StatsReader, StorageReader,
StorageTrieWriter, TransactionVariant, TransactionsProvider, TransactionsProviderExt,
TrieWriter, WithdrawalsProvider,
};
use alloy_eips::BlockHashOrNumber;
use alloy_primitives::{keccak256, Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256};
@ -3596,7 +3597,7 @@ impl<TX: DbTx, Spec: Send + Sync> StatsReader for DatabaseProvider<TX, Spec> {
}
}
impl<TX: DbTx, Spec: Send + Sync> FinalizedBlockReader for DatabaseProvider<TX, Spec> {
impl<TX: DbTx, Spec: Send + Sync> ChainStateBlockReader for DatabaseProvider<TX, Spec> {
fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>> {
let mut finalized_blocks = self
.tx
@ -3608,14 +3609,32 @@ impl<TX: DbTx, Spec: Send + Sync> FinalizedBlockReader for DatabaseProvider<TX,
let last_finalized_block_number = finalized_blocks.pop_first().map(|pair| pair.1);
Ok(last_finalized_block_number)
}
fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>> {
let mut finalized_blocks = self
.tx
.cursor_read::<tables::ChainState>()?
.walk(Some(tables::ChainStateKey::LastSafeBlockBlock))?
.take(1)
.collect::<Result<BTreeMap<tables::ChainStateKey, BlockNumber>, _>>()?;
let last_finalized_block_number = finalized_blocks.pop_first().map(|pair| pair.1);
Ok(last_finalized_block_number)
}
}
impl<TX: DbTxMut, Spec: Send + Sync> FinalizedBlockWriter for DatabaseProvider<TX, Spec> {
impl<TX: DbTxMut, Spec: Send + Sync> ChainStateBlockWriter for DatabaseProvider<TX, Spec> {
fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()> {
Ok(self
.tx
.put::<tables::ChainState>(tables::ChainStateKey::LastFinalizedBlock, block_number)?)
}
fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()> {
Ok(self
.tx
.put::<tables::ChainState>(tables::ChainStateKey::LastSafeBlockBlock, block_number)?)
}
}
impl<TX: DbTx + 'static, Spec: Send + Sync + 'static> DBProvider for DatabaseProvider<TX, Spec> {

View File

@ -1,9 +1,9 @@
use crate::{
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockSource, BlockchainTreePendingStateProvider, CanonChainTracker, CanonStateNotifications,
CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, DatabaseProviderFactory,
EvmEnvProvider, FinalizedBlockReader, FullExecutionDataProvider, HeaderProvider, ProviderError,
PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, RequestsProvider,
CanonStateSubscriptions, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader,
DatabaseProviderFactory, EvmEnvProvider, FullExecutionDataProvider, HeaderProvider,
ProviderError, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, RequestsProvider,
StageCheckpointReader, StateProviderBox, StateProviderFactory, StaticFileProviderFactory,
TransactionVariant, TransactionsProvider, TreeViewer, WithdrawalsProvider,
};
@ -109,8 +109,9 @@ impl<N: ProviderNodeTypes> BlockchainProvider<N> {
tree: Arc<dyn TreeViewer>,
latest: SealedHeader,
finalized: Option<SealedHeader>,
safe: Option<SealedHeader>,
) -> Self {
Self { database, tree, chain_info: ChainInfoTracker::new(latest, finalized) }
Self { database, tree, chain_info: ChainInfoTracker::new(latest, finalized, safe) }
}
/// Create a new provider using only the database and the tree, fetching the latest header from
@ -128,11 +129,18 @@ impl<N: ProviderNodeTypes> BlockchainProvider<N> {
.transpose()?
.flatten();
let safe_header = provider
.last_safe_block_number()?
.map(|num| provider.sealed_header(num))
.transpose()?
.flatten();
Ok(Self::with_blocks(
database,
tree,
SealedHeader::new(latest_header, best.best_hash),
finalized_header,
safe_header,
))
}

View File

@ -1,16 +1,23 @@
use alloy_primitives::BlockNumber;
use reth_errors::ProviderResult;
/// Functionality to read the last known finalized block from the database.
pub trait FinalizedBlockReader: Send + Sync {
/// Functionality to read the last known chain blocks from the database.
pub trait ChainStateBlockReader: Send + Sync {
/// Returns the last finalized block number.
///
/// If no finalized block has been written yet, this returns `None`.
fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
/// Returns the last safe block number.
///
/// If no safe block has been written yet, this returns `None`.
fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
}
/// Functionality to write the last known finalized block to the database.
pub trait FinalizedBlockWriter: Send + Sync {
/// Functionality to write the last known chain blocks to the database.
pub trait ChainStateBlockWriter: Send + Sync {
/// Saves the given finalized block number in the DB.
fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
/// Saves the given safe block number in the DB.
fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
}

View File

@ -42,4 +42,4 @@ mod tree_viewer;
pub use tree_viewer::TreeViewer;
mod finalized_block;
pub use finalized_block::{FinalizedBlockReader, FinalizedBlockWriter};
pub use finalized_block::{ChainStateBlockReader, ChainStateBlockWriter};