mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-29 09:08:05 -05:00
feat: check if blocknumber is latest block number (#2428)
This commit is contained in:
@@ -74,8 +74,6 @@ pub enum ProviderError {
|
||||
/// Some error occurred while interacting with the state tree.
|
||||
#[error("Unknown error occurred while interacting with the state trie.")]
|
||||
StateTrie,
|
||||
#[error("History state root, can't be calculated")]
|
||||
HistoryStateRoot,
|
||||
/// Thrown when required header related data was not found but was required.
|
||||
#[error("requested data not found")]
|
||||
HeaderNotFound,
|
||||
@@ -91,6 +89,7 @@ pub enum ProviderError {
|
||||
/// Thrown when we failed to lookup a block for the pending state
|
||||
#[error("Unknown block hash: {0:}")]
|
||||
UnknownBlockHash(H256),
|
||||
/// Unable to compute state root on top of historical block
|
||||
#[error("Unable to compute state root on top of historical block")]
|
||||
StateRootNotAvailableForHistoricalBlock,
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ impl<DB: Database> ShareableDatabase<DB> {
|
||||
) -> Result<StateProviderBox<'_>> {
|
||||
let tx = self.db.tx()?;
|
||||
|
||||
if is_latest_block_number(&tx, block_number)? {
|
||||
return Ok(Box::new(LatestStateProvider::new(tx)))
|
||||
}
|
||||
|
||||
// +1 as the changeset that we want is the one that was applied after this block.
|
||||
block_number += 1;
|
||||
|
||||
@@ -68,6 +72,10 @@ impl<DB: Database> ShareableDatabase<DB> {
|
||||
.get::<tables::HeaderNumbers>(block_hash)?
|
||||
.ok_or(ProviderError::BlockHash { block_hash })?;
|
||||
|
||||
if is_latest_block_number(&tx, block_number)? {
|
||||
return Ok(Box::new(LatestStateProvider::new(tx)))
|
||||
}
|
||||
|
||||
// +1 as the changeset that we want is the one that was applied after this block.
|
||||
// as the changeset contains old values.
|
||||
block_number += 1;
|
||||
@@ -145,11 +153,7 @@ impl<DB: Database> BlockIdProvider for ShareableDatabase<DB> {
|
||||
}
|
||||
|
||||
fn best_block_number(&self) -> Result<BlockNumber> {
|
||||
Ok(self
|
||||
.db
|
||||
.view(|tx| tx.get::<tables::SyncStage>("Finish".to_string()))?
|
||||
.map_err(Into::<reth_interfaces::db::Error>::into)?
|
||||
.unwrap_or_default())
|
||||
Ok(self.db.view(|tx| best_block_number(tx))??.unwrap_or_default())
|
||||
}
|
||||
|
||||
fn block_number(&self, hash: H256) -> Result<Option<BlockNumber>> {
|
||||
@@ -452,6 +456,44 @@ impl<DB: Database> EvmEnvProvider for ShareableDatabase<DB> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches checks if the block number is the latest block number.
|
||||
#[inline]
|
||||
fn is_latest_block_number<'a, TX>(
|
||||
tx: &TX,
|
||||
block_number: BlockNumber,
|
||||
) -> std::result::Result<bool, reth_interfaces::db::Error>
|
||||
where
|
||||
TX: DbTx<'a> + Send + Sync,
|
||||
{
|
||||
// check if the block number is the best block number
|
||||
// there's always at least one header in the database (genesis)
|
||||
let best = best_block_number(tx)?.unwrap_or_default();
|
||||
let last = last_canonical_header(tx)?.map(|(last, _)| last).unwrap_or_default();
|
||||
Ok(block_number == best && block_number == last)
|
||||
}
|
||||
|
||||
/// Fetches the best block number from the database.
|
||||
#[inline]
|
||||
fn best_block_number<'a, TX>(
|
||||
tx: &TX,
|
||||
) -> std::result::Result<Option<BlockNumber>, reth_interfaces::db::Error>
|
||||
where
|
||||
TX: DbTx<'a> + Send + Sync,
|
||||
{
|
||||
tx.get::<tables::SyncStage>("Finish".to_string())
|
||||
}
|
||||
|
||||
/// Fetches the last canonical header from the database.
|
||||
#[inline]
|
||||
fn last_canonical_header<'a, TX>(
|
||||
tx: &TX,
|
||||
) -> std::result::Result<Option<(BlockNumber, BlockHash)>, reth_interfaces::db::Error>
|
||||
where
|
||||
TX: DbTx<'a> + Send + Sync,
|
||||
{
|
||||
tx.cursor_read::<tables::CanonicalHeaders>()?.last()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ShareableDatabase;
|
||||
|
||||
@@ -299,7 +299,6 @@ where
|
||||
if let Some(pending) = self.tree.find_pending_state_provider(block) {
|
||||
return self.pending_with_provider(pending)
|
||||
}
|
||||
|
||||
// not found in tree, check database
|
||||
self.history_by_block_hash(block)
|
||||
}
|
||||
|
||||
@@ -94,6 +94,6 @@ impl<SP: StateProvider, PSDP: PostStateDataProvider> StateProvider for PostState
|
||||
_address: Address,
|
||||
_keys: &[H256],
|
||||
) -> Result<(Vec<Bytes>, H256, Vec<Vec<Bytes>>)> {
|
||||
Err(ProviderError::HistoryStateRoot.into())
|
||||
Err(ProviderError::StateRootNotAvailableForHistoricalBlock.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ impl<'a, 'b, TX: DbTx<'a>> StateProvider for HistoricalStateProviderRef<'a, 'b,
|
||||
_address: Address,
|
||||
_keys: &[H256],
|
||||
) -> Result<(Vec<Bytes>, H256, Vec<Vec<Bytes>>)> {
|
||||
Err(ProviderError::HistoryStateRoot.into())
|
||||
Err(ProviderError::StateRootNotAvailableForHistoricalBlock.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user