Skip to content

Commit

Permalink
check db transaction in block builder helper
Browse files Browse the repository at this point in the history
  • Loading branch information
dvush committed Dec 10, 2024
1 parent 17776cc commit 5313984
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::{
primitives::SimulatedOrder,
roothash::RootHashConfig,
telemetry,
utils::{check_block_hash_reader_health, HistoricalBlockError},
};

use super::Block;
Expand Down Expand Up @@ -125,6 +126,8 @@ pub enum BlockBuildingHelperError {
FinalizeError(#[from] FinalizeError),
#[error("Payout tx not allowed for block")]
PayoutTxNotAllowed,
#[error("Provider historical block hashes error: {0}")]
HistoricalBlockError(#[from] HistoricalBlockError),
}

impl BlockBuildingHelperError {
Expand Down Expand Up @@ -174,6 +177,10 @@ where
) -> Result<Self, BlockBuildingHelperError> {
// @Maybe an issue - we have 2 db txs here (one for hash and one for finalize)
let state_provider = provider.history_by_block_hash(building_ctx.attributes.parent)?;

let last_committed_block = building_ctx.block() - 1;
check_block_hash_reader_health(last_committed_block, &state_provider)?;

let fee_recipient_balance_start = state_provider
.account_balance(building_ctx.attributes.suggested_fee_recipient)?
.unwrap_or_default();
Expand All @@ -196,6 +203,7 @@ where
partial_block.reserve_gas(payout_tx_gas);
Some(payout_tx_gas)
};

Ok(Self {
_fee_recipient_balance_start: fee_recipient_balance_start,
block_state,
Expand Down
3 changes: 2 additions & 1 deletion crates/rbuilder/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ use alloy_consensus::TxEnvelope;
use alloy_eips::eip2718::Encodable2718;
pub use noncer::{NonceCache, NonceCacheRef};
pub use provider_factory_reopen::{
check_provider_factory_health, is_provider_factory_health_error, ProviderFactoryReopener,
check_block_hash_reader_health, is_provider_factory_health_error, HistoricalBlockError,
ProviderFactoryReopener,
};
use reth_chainspec::ChainSpec;
use reth_evm_ethereum::revm_spec_by_timestamp_after_merge;
Expand Down
42 changes: 27 additions & 15 deletions crates/rbuilder/src/utils/provider_factory_reopen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use reth_provider::{
HeaderProvider, StateProviderBox, StateProviderFactory, StaticFileProviderFactory,
};
use revm_primitives::{B256, U256};
use std::ops::DerefMut;
use std::{ops::RangeBounds, path::PathBuf, sync::Arc};
use tracing::debug;

Expand Down Expand Up @@ -87,7 +88,7 @@ impl<N: NodeTypesWithDB + ProviderNodeTypes + Clone> ProviderFactoryReopener<N>
// Don't need to check consistency for the block that was just checked.
let last_consistent_block = *self.last_consistent_block.read();
if !self.testing_mode && last_consistent_block != Some(best_block_number) {
match check_provider_factory_health(best_block_number, &provider_factory) {
match check_block_hash_reader_health(best_block_number, provider_factory.deref_mut()) {
Ok(()) => {}
Err(err) => {
debug!(?err, "Provider factory is inconsistent, reopening");
Expand All @@ -102,7 +103,7 @@ impl<N: NodeTypesWithDB + ProviderNodeTypes + Clone> ProviderFactoryReopener<N>
}
}

match check_provider_factory_health(best_block_number, &provider_factory) {
match check_block_hash_reader_health(best_block_number, provider_factory.deref_mut()) {
Ok(()) => {}
Err(err) => {
inc_provider_bad_reopen_counter();
Expand All @@ -127,23 +128,34 @@ pub fn is_provider_factory_health_error(report: &eyre::Error) -> bool {
.contains("Missing historical block hash for block")
}

#[derive(Debug, thiserror::Error)]
pub enum HistoricalBlockError {
#[error("ProviderError while checking block hashes: {0}")]
ProviderError(#[from] ProviderError),
#[error("Missing historical block hash for block {missing_hash_block}, latest block: {latest_block}")]
MissingHash {
missing_hash_block: u64,
latest_block: u64,
},
}

/// Here we check if we have all the necessary historical block hashes in the database
/// This was added as a debugging method because static_files storage was not working correctly
pub fn check_provider_factory_health<N: NodeTypesWithDB + ProviderNodeTypes>(
current_block_number: u64,
provider_factory: &ProviderFactory<N>,
) -> eyre::Result<()> {
/// last_block_number is the number of the latest committed block (i.e. if we build block 1001 it should be 1000)
pub fn check_block_hash_reader_health<R: BlockHashReader>(
last_block_number: u64,
reader: &R,
) -> Result<(), HistoricalBlockError> {
// evm must have access to block hashes of 256 of the previous blocks
let blocks_to_check = current_block_number.min(256);
for i in 1..=blocks_to_check {
let num = current_block_number - i;
let hash = provider_factory.block_hash(num)?;
let blocks_to_check = last_block_number.min(256);
for i in 0..blocks_to_check {
let num = last_block_number - i;
let hash = reader.block_hash(num)?;
if hash.is_none() {
eyre::bail!(
"Missing historical block hash for block {}, current block: {}",
num,
current_block_number
);
return Err(HistoricalBlockError::MissingHash {
missing_hash_block: num,
latest_block: last_block_number,
});
}
}

Expand Down

0 comments on commit 5313984

Please sign in to comment.