mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
fix(provider): consider static files in last block num/hash lookups (#7327)
This commit is contained in:
@ -158,8 +158,11 @@ pub struct RootMismatch {
|
||||
#[derive(Clone, Debug, Error, PartialEq, Eq)]
|
||||
pub enum ConsistentViewError {
|
||||
/// Error thrown on attempt to initialize provider while node is still syncing.
|
||||
#[error("node is syncing. best block: {0}")]
|
||||
Syncing(BlockNumber),
|
||||
#[error("node is syncing. best block: {best_block:?}")]
|
||||
Syncing {
|
||||
/// Best block diff.
|
||||
best_block: GotExpected<BlockNumber>,
|
||||
},
|
||||
/// Error thrown on inconsistent database view.
|
||||
#[error("inconsistent database state: {tip:?}")]
|
||||
Inconsistent {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::{BlockNumReader, DatabaseProviderFactory, DatabaseProviderRO, ProviderError};
|
||||
use reth_db::{cursor::DbCursorRO, database::Database, tables, transaction::DbTx};
|
||||
use crate::{BlockNumReader, DatabaseProviderFactory, DatabaseProviderRO, HeaderProvider};
|
||||
use reth_db::database::Database;
|
||||
use reth_interfaces::provider::ProviderResult;
|
||||
use reth_primitives::{GotExpected, B256};
|
||||
use std::marker::PhantomData;
|
||||
@ -40,24 +40,24 @@ where
|
||||
|
||||
/// Creates new consistent database view with latest tip.
|
||||
pub fn new_with_latest_tip(provider: Provider) -> ProviderResult<Self> {
|
||||
let tip = provider
|
||||
.database_provider_ro()?
|
||||
.tx_ref()
|
||||
.cursor_read::<tables::CanonicalHeaders>()?
|
||||
.last()?;
|
||||
Ok(Self::new(provider, tip.map(|(_, hash)| hash)))
|
||||
let provider_ro = provider.database_provider_ro()?;
|
||||
let last_num = provider_ro.last_block_number()?;
|
||||
let tip = provider_ro.sealed_header(last_num)?.map(|h| h.hash());
|
||||
Ok(Self::new(provider, tip))
|
||||
}
|
||||
|
||||
/// Creates new read-only provider and performs consistency checks on the current tip.
|
||||
pub fn provider_ro(&self) -> ProviderResult<DatabaseProviderRO<DB>> {
|
||||
// Create a new provider.
|
||||
let provider_ro = self.provider.database_provider_ro()?;
|
||||
let last_entry = provider_ro
|
||||
.tx_ref()
|
||||
.cursor_read::<tables::CanonicalHeaders>()
|
||||
.and_then(|mut cursor| cursor.last())
|
||||
.map_err(ProviderError::Database)?;
|
||||
|
||||
let tip = last_entry.map(|(_, hash)| hash);
|
||||
// Check that the latest stored header number matches the number
|
||||
// that consistent view was initialized with.
|
||||
// The mismatch can happen if a new block was appended while
|
||||
// the view was being used.
|
||||
// We compare block hashes instead of block numbers to account for reorgs.
|
||||
let last_num = provider_ro.last_block_number()?;
|
||||
let tip = provider_ro.sealed_header(last_num)?.map(|h| h.hash());
|
||||
if self.tip != tip {
|
||||
return Err(ConsistentViewError::Inconsistent {
|
||||
tip: GotExpected { got: tip, expected: self.tip },
|
||||
@ -65,9 +65,15 @@ where
|
||||
.into())
|
||||
}
|
||||
|
||||
// Check that the best block number is the same as the latest stored header.
|
||||
// This ensures that the consistent view cannot be used for initializing new providers
|
||||
// if the node fell back to the staged sync.
|
||||
let best_block_number = provider_ro.best_block_number()?;
|
||||
if last_entry.map(|(number, _)| number).unwrap_or_default() != best_block_number {
|
||||
return Err(ConsistentViewError::Syncing(best_block_number).into())
|
||||
if last_num != best_block_number {
|
||||
return Err(ConsistentViewError::Syncing {
|
||||
best_block: GotExpected { got: best_block_number, expected: last_num },
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
||||
Ok(provider_ro)
|
||||
|
||||
@ -1219,7 +1219,15 @@ impl<TX: DbTx> BlockNumReader for DatabaseProvider<TX> {
|
||||
}
|
||||
|
||||
fn last_block_number(&self) -> ProviderResult<BlockNumber> {
|
||||
Ok(self.tx.cursor_read::<tables::CanonicalHeaders>()?.last()?.unwrap_or_default().0)
|
||||
Ok(self
|
||||
.tx
|
||||
.cursor_read::<tables::CanonicalHeaders>()?
|
||||
.last()?
|
||||
.map(|(num, _)| num)
|
||||
.max(
|
||||
self.static_file_provider.get_highest_static_file_block(StaticFileSegment::Headers),
|
||||
)
|
||||
.unwrap_or_default())
|
||||
}
|
||||
|
||||
fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>> {
|
||||
|
||||
Reference in New Issue
Block a user