mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
refactor: improve state writing functions for db provider (#12885)
This commit is contained in:
@ -15,7 +15,7 @@ use crate::{
|
||||
HeaderSyncGapProvider, HistoricalStateProvider, HistoricalStateProviderRef, HistoryWriter,
|
||||
LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError,
|
||||
PruneCheckpointReader, PruneCheckpointWriter, RevertsInit, StageCheckpointReader,
|
||||
StateChangeWriter, StateCommitmentProvider, StateProviderBox, StateReader, StateWriter,
|
||||
StateChangeWriter, StateCommitmentProvider, StateProviderBox, StateWriter,
|
||||
StaticFileProviderFactory, StatsReader, StorageLocation, StorageReader, StorageTrieWriter,
|
||||
TransactionVariant, TransactionsProvider, TransactionsProviderExt, TrieWriter,
|
||||
WithdrawalsProvider,
|
||||
@ -679,94 +679,6 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> DatabaseProvider<TX, N> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the last N blocks of state, recreating the [`ExecutionOutcome`].
|
||||
///
|
||||
/// 1. Iterate over the [`BlockBodyIndices`][tables::BlockBodyIndices] table to get all the
|
||||
/// transaction ids.
|
||||
/// 2. Iterate over the [`StorageChangeSets`][tables::StorageChangeSets] table and the
|
||||
/// [`AccountChangeSets`][tables::AccountChangeSets] tables in reverse order to reconstruct
|
||||
/// the changesets.
|
||||
/// - In order to have both the old and new values in the changesets, we also access the
|
||||
/// plain state tables.
|
||||
/// 3. While iterating over the changeset tables, if we encounter a new account or storage slot,
|
||||
/// we:
|
||||
/// 1. Take the old value from the changeset
|
||||
/// 2. Take the new value from the plain state
|
||||
/// 3. Save the old value to the local state
|
||||
/// 4. While iterating over the changeset tables, if we encounter an account/storage slot we
|
||||
/// have seen before we:
|
||||
/// 1. Take the old value from the changeset
|
||||
/// 2. Take the new value from the local state
|
||||
/// 3. Set the local state to the value in the changeset
|
||||
///
|
||||
/// If the range is empty, or there are no blocks for the given range, then this returns `None`.
|
||||
pub fn get_state(
|
||||
&self,
|
||||
range: RangeInclusive<BlockNumber>,
|
||||
) -> ProviderResult<Option<ExecutionOutcome>> {
|
||||
if range.is_empty() {
|
||||
return Ok(None)
|
||||
}
|
||||
let start_block_number = *range.start();
|
||||
|
||||
// We are not removing block meta as it is used to get block changesets.
|
||||
let block_bodies = self.get::<tables::BlockBodyIndices>(range.clone())?;
|
||||
|
||||
// get transaction receipts
|
||||
let Some(from_transaction_num) = block_bodies.first().map(|bodies| bodies.1.first_tx_num())
|
||||
else {
|
||||
return Ok(None)
|
||||
};
|
||||
let Some(to_transaction_num) = block_bodies.last().map(|bodies| bodies.1.last_tx_num())
|
||||
else {
|
||||
return Ok(None)
|
||||
};
|
||||
|
||||
let storage_range = BlockNumberAddress::range(range.clone());
|
||||
|
||||
let storage_changeset = self.get::<tables::StorageChangeSets>(storage_range)?;
|
||||
let account_changeset = self.get::<tables::AccountChangeSets>(range)?;
|
||||
|
||||
// This is not working for blocks that are not at tip. as plain state is not the last
|
||||
// state of end range. We should rename the functions or add support to access
|
||||
// History state. Accessing history state can be tricky but we are not gaining
|
||||
// anything.
|
||||
let mut plain_accounts_cursor = self.tx.cursor_read::<tables::PlainAccountState>()?;
|
||||
let mut plain_storage_cursor = self.tx.cursor_dup_read::<tables::PlainStorageState>()?;
|
||||
|
||||
let (state, reverts) = self.populate_bundle_state(
|
||||
account_changeset,
|
||||
storage_changeset,
|
||||
&mut plain_accounts_cursor,
|
||||
&mut plain_storage_cursor,
|
||||
)?;
|
||||
|
||||
// iterate over block body and create ExecutionResult
|
||||
let mut receipt_iter =
|
||||
self.get::<tables::Receipts>(from_transaction_num..=to_transaction_num)?.into_iter();
|
||||
|
||||
let mut receipts = Vec::with_capacity(block_bodies.len());
|
||||
// loop break if we are at the end of the blocks.
|
||||
for (_, block_body) in block_bodies {
|
||||
let mut block_receipts = Vec::with_capacity(block_body.tx_count as usize);
|
||||
for _ in block_body.tx_num_range() {
|
||||
if let Some((_, receipt)) = receipt_iter.next() {
|
||||
block_receipts.push(Some(receipt));
|
||||
}
|
||||
}
|
||||
receipts.push(block_receipts);
|
||||
}
|
||||
|
||||
Ok(Some(ExecutionOutcome::new_init(
|
||||
state,
|
||||
reverts,
|
||||
Vec::new(),
|
||||
receipts.into(),
|
||||
start_block_number,
|
||||
Vec::new(),
|
||||
)))
|
||||
}
|
||||
|
||||
/// Populate a [`BundleStateInit`] and [`RevertsInit`] using cursors over the
|
||||
/// [`PlainAccountState`] and [`PlainStorageState`] tables, based on the given storage and
|
||||
/// account changesets.
|
||||
@ -2039,9 +1951,11 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateChangeWriter
|
||||
/// 1. Take the old value from the changeset
|
||||
/// 2. Take the new value from the local state
|
||||
/// 3. Set the local state to the value in the changeset
|
||||
fn remove_state(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<()> {
|
||||
fn remove_state_above(&self, block: BlockNumber) -> ProviderResult<()> {
|
||||
let range = block + 1..=self.last_block_number()?;
|
||||
|
||||
if range.is_empty() {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// We are not removing block meta as it is used to get block changesets.
|
||||
@ -2131,7 +2045,9 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateChangeWriter
|
||||
/// 1. Take the old value from the changeset
|
||||
/// 2. Take the new value from the local state
|
||||
/// 3. Set the local state to the value in the changeset
|
||||
fn take_state(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<ExecutionOutcome> {
|
||||
fn take_state_above(&self, block: BlockNumber) -> ProviderResult<ExecutionOutcome> {
|
||||
let range = block + 1..=self.last_block_number()?;
|
||||
|
||||
if range.is_empty() {
|
||||
return Ok(ExecutionOutcome::default())
|
||||
}
|
||||
@ -2672,12 +2588,6 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypes> HistoryWriter for DatabaseProvi
|
||||
}
|
||||
}
|
||||
|
||||
impl<TX: DbTx + 'static, N: NodeTypesForProvider> StateReader for DatabaseProvider<TX, N> {
|
||||
fn get_state(&self, block: BlockNumber) -> ProviderResult<Option<ExecutionOutcome>> {
|
||||
self.get_state(block..=block)
|
||||
}
|
||||
}
|
||||
|
||||
impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider + 'static> BlockExecutionWriter
|
||||
for DatabaseProvider<TX, N>
|
||||
{
|
||||
@ -2691,7 +2601,7 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider + 'static> BlockExecu
|
||||
self.unwind_trie_state_range(range.clone())?;
|
||||
|
||||
// get execution res
|
||||
let execution_state = self.take_state(range.clone())?;
|
||||
let execution_state = self.take_state_above(block)?;
|
||||
|
||||
let blocks = self.sealed_block_with_senders_range(range)?;
|
||||
|
||||
@ -2712,10 +2622,10 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider + 'static> BlockExecu
|
||||
) -> ProviderResult<()> {
|
||||
let range = block + 1..=self.last_block_number()?;
|
||||
|
||||
self.unwind_trie_state_range(range.clone())?;
|
||||
self.unwind_trie_state_range(range)?;
|
||||
|
||||
// remove execution res
|
||||
self.remove_state(range)?;
|
||||
self.remove_state_above(block)?;
|
||||
|
||||
// remove block bodies it is needed for both get block range and get block execution results
|
||||
// that is why it is deleted afterwards.
|
||||
|
||||
Reference in New Issue
Block a user