mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(provider): StateRootProvider::state_root_with_updates (#5485)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -6297,6 +6297,7 @@ dependencies = [
|
|||||||
"reth-primitives",
|
"reth-primitives",
|
||||||
"reth-provider",
|
"reth-provider",
|
||||||
"reth-revm-inspectors",
|
"reth-revm-inspectors",
|
||||||
|
"reth-trie",
|
||||||
"revm",
|
"revm",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -104,8 +104,8 @@ impl<DB: Database, EF: ExecutorFactory> BlockchainTree<DB, EF> {
|
|||||||
externals.fetch_latest_canonical_hashes(config.num_of_canonical_hashes() as usize)?;
|
externals.fetch_latest_canonical_hashes(config.num_of_canonical_hashes() as usize)?;
|
||||||
|
|
||||||
// TODO(rakita) save last finalized block inside database but for now just take
|
// TODO(rakita) save last finalized block inside database but for now just take
|
||||||
// tip-max_reorg_depth
|
// `tip - max_reorg_depth`
|
||||||
// task: https://github.com/paradigmxyz/reth/issues/1712
|
// https://github.com/paradigmxyz/reth/issues/1712
|
||||||
let last_finalized_block_number = if last_canonical_hashes.len() > max_reorg_depth {
|
let last_finalized_block_number = if last_canonical_hashes.len() > max_reorg_depth {
|
||||||
// we pick `Highest - max_reorg_depth` block as last finalized block.
|
// we pick `Highest - max_reorg_depth` block as last finalized block.
|
||||||
last_canonical_hashes.keys().nth_back(max_reorg_depth)
|
last_canonical_hashes.keys().nth_back(max_reorg_depth)
|
||||||
|
|||||||
@ -158,15 +158,19 @@ impl AppendableChain {
|
|||||||
state.revert_to(parent.number);
|
state.revert_to(parent.number);
|
||||||
|
|
||||||
// Revert changesets to get the state of the parent that we need to apply the change.
|
// Revert changesets to get the state of the parent that we need to apply the change.
|
||||||
let post_state_data = BundleStateDataRef {
|
let bundle_state_data = BundleStateDataRef {
|
||||||
state: &state,
|
state: &state,
|
||||||
sidechain_block_hashes: &side_chain_block_hashes,
|
sidechain_block_hashes: &side_chain_block_hashes,
|
||||||
canonical_block_hashes,
|
canonical_block_hashes,
|
||||||
canonical_fork,
|
canonical_fork,
|
||||||
};
|
};
|
||||||
let block_state =
|
let block_state = Self::validate_and_execute_sidechain(
|
||||||
Self::validate_and_execute_sidechain(block.clone(), parent, post_state_data, externals)
|
block.clone(),
|
||||||
.map_err(|err| InsertBlockError::new(block.block.clone(), err.into()))?;
|
parent,
|
||||||
|
bundle_state_data,
|
||||||
|
externals,
|
||||||
|
)
|
||||||
|
.map_err(|err| InsertBlockError::new(block.block.clone(), err.into()))?;
|
||||||
state.extend(block_state);
|
state.extend(block_state);
|
||||||
|
|
||||||
// If all is okay, return new chain back. Present chain is not modified.
|
// If all is okay, return new chain back. Present chain is not modified.
|
||||||
@ -185,7 +189,7 @@ impl AppendableChain {
|
|||||||
fn validate_and_execute<BSDP, DB, EF>(
|
fn validate_and_execute<BSDP, DB, EF>(
|
||||||
block: SealedBlockWithSenders,
|
block: SealedBlockWithSenders,
|
||||||
parent_block: &SealedHeader,
|
parent_block: &SealedHeader,
|
||||||
post_state_data_provider: BSDP,
|
bundle_state_data_provider: BSDP,
|
||||||
externals: &TreeExternals<DB, EF>,
|
externals: &TreeExternals<DB, EF>,
|
||||||
block_kind: BlockKind,
|
block_kind: BlockKind,
|
||||||
block_validation_kind: BlockValidationKind,
|
block_validation_kind: BlockValidationKind,
|
||||||
@ -203,10 +207,10 @@ impl AppendableChain {
|
|||||||
|
|
||||||
// get the state provider.
|
// get the state provider.
|
||||||
let db = externals.database();
|
let db = externals.database();
|
||||||
let canonical_fork = post_state_data_provider.canonical_fork();
|
let canonical_fork = bundle_state_data_provider.canonical_fork();
|
||||||
let state_provider = db.history_by_block_number(canonical_fork.number)?;
|
let state_provider = db.history_by_block_number(canonical_fork.number)?;
|
||||||
|
|
||||||
let provider = BundleStateProvider::new(state_provider, post_state_data_provider);
|
let provider = BundleStateProvider::new(state_provider, bundle_state_data_provider);
|
||||||
|
|
||||||
let mut executor = externals.executor_factory.with_state(&provider);
|
let mut executor = externals.executor_factory.with_state(&provider);
|
||||||
executor.execute_and_verify_receipt(&block, U256::MAX, Some(senders))?;
|
executor.execute_and_verify_receipt(&block, U256::MAX, Some(senders))?;
|
||||||
@ -232,7 +236,7 @@ impl AppendableChain {
|
|||||||
fn validate_and_execute_sidechain<BSDP, DB, EF>(
|
fn validate_and_execute_sidechain<BSDP, DB, EF>(
|
||||||
block: SealedBlockWithSenders,
|
block: SealedBlockWithSenders,
|
||||||
parent_block: &SealedHeader,
|
parent_block: &SealedHeader,
|
||||||
post_state_data_provider: BSDP,
|
bundle_state_data_provider: BSDP,
|
||||||
externals: &TreeExternals<DB, EF>,
|
externals: &TreeExternals<DB, EF>,
|
||||||
) -> RethResult<BundleStateWithReceipts>
|
) -> RethResult<BundleStateWithReceipts>
|
||||||
where
|
where
|
||||||
@ -243,7 +247,7 @@ impl AppendableChain {
|
|||||||
Self::validate_and_execute(
|
Self::validate_and_execute(
|
||||||
block,
|
block,
|
||||||
parent_block,
|
parent_block,
|
||||||
post_state_data_provider,
|
bundle_state_data_provider,
|
||||||
externals,
|
externals,
|
||||||
BlockKind::ForksHistoricalBlock,
|
BlockKind::ForksHistoricalBlock,
|
||||||
BlockValidationKind::SkipStateRootValidation,
|
BlockValidationKind::SkipStateRootValidation,
|
||||||
@ -279,7 +283,7 @@ impl AppendableChain {
|
|||||||
{
|
{
|
||||||
let parent_block = self.chain.tip();
|
let parent_block = self.chain.tip();
|
||||||
|
|
||||||
let post_state_data = BundleStateDataRef {
|
let bundle_state_data = BundleStateDataRef {
|
||||||
state: self.state(),
|
state: self.state(),
|
||||||
sidechain_block_hashes: &side_chain_block_hashes,
|
sidechain_block_hashes: &side_chain_block_hashes,
|
||||||
canonical_block_hashes,
|
canonical_block_hashes,
|
||||||
@ -289,7 +293,7 @@ impl AppendableChain {
|
|||||||
let block_state = Self::validate_and_execute(
|
let block_state = Self::validate_and_execute(
|
||||||
block.clone(),
|
block.clone(),
|
||||||
parent_block,
|
parent_block,
|
||||||
post_state_data,
|
bundle_state_data,
|
||||||
externals,
|
externals,
|
||||||
block_kind,
|
block_kind,
|
||||||
block_validation_kind,
|
block_validation_kind,
|
||||||
|
|||||||
@ -22,6 +22,9 @@ revm.workspace = true
|
|||||||
# common
|
# common
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
reth-trie.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
optimism = [
|
optimism = [
|
||||||
"revm/optimism",
|
"revm/optimism",
|
||||||
|
|||||||
@ -568,6 +568,7 @@ mod tests {
|
|||||||
use reth_provider::{
|
use reth_provider::{
|
||||||
AccountReader, BlockHashReader, BundleStateWithReceipts, StateRootProvider,
|
AccountReader, BlockHashReader, BundleStateWithReceipts, StateRootProvider,
|
||||||
};
|
};
|
||||||
|
use reth_trie::updates::TrieUpdates;
|
||||||
use revm::{Database, TransitionState};
|
use revm::{Database, TransitionState};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@ -627,6 +628,13 @@ mod tests {
|
|||||||
fn state_root(&self, _bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
fn state_root(&self, _bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
||||||
unimplemented!("state root computation is not supported")
|
unimplemented!("state root computation is not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state_root_with_updates(
|
||||||
|
&self,
|
||||||
|
_bundle_state: &BundleStateWithReceipts,
|
||||||
|
) -> ProviderResult<(B256, TrieUpdates)> {
|
||||||
|
unimplemented!("state root computation is not supported")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StateProvider for StateProviderTest {
|
impl StateProvider for StateProviderTest {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ use reth_primitives::{
|
|||||||
};
|
};
|
||||||
use reth_trie::{
|
use reth_trie::{
|
||||||
hashed_cursor::{HashedPostState, HashedPostStateCursorFactory, HashedStorage},
|
hashed_cursor::{HashedPostState, HashedPostStateCursorFactory, HashedStorage},
|
||||||
|
updates::TrieUpdates,
|
||||||
StateRoot, StateRootError,
|
StateRoot, StateRootError,
|
||||||
};
|
};
|
||||||
use revm::{db::states::BundleState, primitives::AccountInfo};
|
use revm::{db::states::BundleState, primitives::AccountInfo};
|
||||||
@ -154,6 +155,20 @@ impl BundleStateWithReceipts {
|
|||||||
hashed_state.sorted()
|
hashed_state.sorted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns [StateRoot] calculator.
|
||||||
|
fn state_root_calculator<'a, 'b, TX: DbTx>(
|
||||||
|
&self,
|
||||||
|
tx: &'a TX,
|
||||||
|
hashed_post_state: &'b HashedPostState,
|
||||||
|
) -> StateRoot<'a, TX, HashedPostStateCursorFactory<'a, 'b, TX>> {
|
||||||
|
let (account_prefix_set, storage_prefix_set) = hashed_post_state.construct_prefix_sets();
|
||||||
|
let hashed_cursor_factory = HashedPostStateCursorFactory::new(tx, hashed_post_state);
|
||||||
|
StateRoot::new(tx)
|
||||||
|
.with_hashed_cursor_factory(hashed_cursor_factory)
|
||||||
|
.with_changed_account_prefixes(account_prefix_set)
|
||||||
|
.with_changed_storage_prefixes(storage_prefix_set)
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate the state root for this [BundleState].
|
/// Calculate the state root for this [BundleState].
|
||||||
/// Internally, function calls [Self::hash_state_slow] to obtain the [HashedPostState].
|
/// Internally, function calls [Self::hash_state_slow] to obtain the [HashedPostState].
|
||||||
/// Afterwards, it retrieves the prefixsets from the [HashedPostState] and uses them to
|
/// Afterwards, it retrieves the prefixsets from the [HashedPostState] and uses them to
|
||||||
@ -196,13 +211,17 @@ impl BundleStateWithReceipts {
|
|||||||
/// The state root for this [BundleState].
|
/// The state root for this [BundleState].
|
||||||
pub fn state_root_slow<TX: DbTx>(&self, tx: &TX) -> Result<B256, StateRootError> {
|
pub fn state_root_slow<TX: DbTx>(&self, tx: &TX) -> Result<B256, StateRootError> {
|
||||||
let hashed_post_state = self.hash_state_slow();
|
let hashed_post_state = self.hash_state_slow();
|
||||||
let (account_prefix_set, storage_prefix_set) = hashed_post_state.construct_prefix_sets();
|
self.state_root_calculator(tx, &hashed_post_state).root()
|
||||||
let hashed_cursor_factory = HashedPostStateCursorFactory::new(tx, &hashed_post_state);
|
}
|
||||||
StateRoot::new(tx)
|
|
||||||
.with_hashed_cursor_factory(hashed_cursor_factory)
|
/// Calculates the state root for this [BundleState] and returns it alongside trie updates.
|
||||||
.with_changed_account_prefixes(account_prefix_set)
|
/// See [Self::state_root_slow] for more info.
|
||||||
.with_changed_storage_prefixes(storage_prefix_set)
|
pub fn state_root_slow_with_updates<TX: DbTx>(
|
||||||
.root()
|
&self,
|
||||||
|
tx: &TX,
|
||||||
|
) -> Result<(B256, TrieUpdates), StateRootError> {
|
||||||
|
let hashed_post_state = self.hash_state_slow();
|
||||||
|
self.state_root_calculator(tx, &hashed_post_state).root_with_updates()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transform block number to the index of block.
|
/// Transform block number to the index of block.
|
||||||
|
|||||||
@ -19,7 +19,7 @@ impl From<StateChangeset> for StateChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StateChanges {
|
impl StateChanges {
|
||||||
/// Write the post state to the database.
|
/// Write the bundle state to the database.
|
||||||
pub fn write_to_db<TX: DbTxMut + DbTx>(mut self, tx: &TX) -> Result<(), DatabaseError> {
|
pub fn write_to_db<TX: DbTxMut + DbTx>(mut self, tx: &TX) -> Result<(), DatabaseError> {
|
||||||
// sort all entries so they can be written to database in more performant way.
|
// sort all entries so they can be written to database in more performant way.
|
||||||
// and take smaller memory footprint.
|
// and take smaller memory footprint.
|
||||||
@ -28,28 +28,28 @@ impl StateChanges {
|
|||||||
self.0.contracts.par_sort_by_key(|a| a.0);
|
self.0.contracts.par_sort_by_key(|a| a.0);
|
||||||
|
|
||||||
// Write new account state
|
// Write new account state
|
||||||
tracing::trace!(target: "provider::post_state", len = self.0.accounts.len(), "Writing new account state");
|
tracing::trace!(target: "provider::bundle_state", len = self.0.accounts.len(), "Writing new account state");
|
||||||
let mut accounts_cursor = tx.cursor_write::<tables::PlainAccountState>()?;
|
let mut accounts_cursor = tx.cursor_write::<tables::PlainAccountState>()?;
|
||||||
// write account to database.
|
// write account to database.
|
||||||
for (address, account) in self.0.accounts.into_iter() {
|
for (address, account) in self.0.accounts.into_iter() {
|
||||||
if let Some(account) = account {
|
if let Some(account) = account {
|
||||||
tracing::trace!(target: "provider::post_state", ?address, "Updating plain state account");
|
tracing::trace!(target: "provider::bundle_state", ?address, "Updating plain state account");
|
||||||
accounts_cursor.upsert(address, into_reth_acc(account))?;
|
accounts_cursor.upsert(address, into_reth_acc(account))?;
|
||||||
} else if accounts_cursor.seek_exact(address)?.is_some() {
|
} else if accounts_cursor.seek_exact(address)?.is_some() {
|
||||||
tracing::trace!(target: "provider::post_state", ?address, "Deleting plain state account");
|
tracing::trace!(target: "provider::bundle_state", ?address, "Deleting plain state account");
|
||||||
accounts_cursor.delete_current()?;
|
accounts_cursor.delete_current()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write bytecode
|
// Write bytecode
|
||||||
tracing::trace!(target: "provider::post_state", len = self.0.contracts.len(), "Writing bytecodes");
|
tracing::trace!(target: "provider::bundle_state", len = self.0.contracts.len(), "Writing bytecodes");
|
||||||
let mut bytecodes_cursor = tx.cursor_write::<tables::Bytecodes>()?;
|
let mut bytecodes_cursor = tx.cursor_write::<tables::Bytecodes>()?;
|
||||||
for (hash, bytecode) in self.0.contracts.into_iter() {
|
for (hash, bytecode) in self.0.contracts.into_iter() {
|
||||||
bytecodes_cursor.upsert(hash, Bytecode(bytecode))?;
|
bytecodes_cursor.upsert(hash, Bytecode(bytecode))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write new storage state and wipe storage if needed.
|
// Write new storage state and wipe storage if needed.
|
||||||
tracing::trace!(target: "provider::post_state", len = self.0.storage.len(), "Writing new storage state");
|
tracing::trace!(target: "provider::bundle_state", len = self.0.storage.len(), "Writing new storage state");
|
||||||
let mut storages_cursor = tx.cursor_dup_write::<tables::PlainStorageState>()?;
|
let mut storages_cursor = tx.cursor_dup_write::<tables::PlainStorageState>()?;
|
||||||
for PlainStorageChangeset { address, wipe_storage, storage } in self.0.storage.into_iter() {
|
for PlainStorageChangeset { address, wipe_storage, storage } in self.0.storage.into_iter() {
|
||||||
// Wiping of storage.
|
// Wiping of storage.
|
||||||
@ -65,7 +65,7 @@ impl StateChanges {
|
|||||||
storage.par_sort_unstable_by_key(|a| a.key);
|
storage.par_sort_unstable_by_key(|a| a.key);
|
||||||
|
|
||||||
for entry in storage.into_iter() {
|
for entry in storage.into_iter() {
|
||||||
tracing::trace!(target: "provider::post_state", ?address, ?entry.key, "Updating plain state storage");
|
tracing::trace!(target: "provider::bundle_state", ?address, ?entry.key, "Updating plain state storage");
|
||||||
if let Some(db_entry) = storages_cursor.seek_by_key_subkey(address, entry.key)? {
|
if let Some(db_entry) = storages_cursor.seek_by_key_subkey(address, entry.key)? {
|
||||||
if db_entry.key == entry.key {
|
if db_entry.key == entry.key {
|
||||||
storages_cursor.delete_current()?;
|
storages_cursor.delete_current()?;
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use reth_interfaces::provider::{ProviderError, ProviderResult};
|
use reth_interfaces::provider::{ProviderError, ProviderResult};
|
||||||
use reth_primitives::{trie::AccountProof, Account, Address, BlockNumber, Bytecode, B256};
|
use reth_primitives::{trie::AccountProof, Account, Address, BlockNumber, Bytecode, B256};
|
||||||
|
use reth_trie::updates::TrieUpdates;
|
||||||
|
|
||||||
/// A state provider that either resolves to data in a wrapped [`crate::BundleStateWithReceipts`],
|
/// A state provider that either resolves to data in a wrapped [`crate::BundleStateWithReceipts`],
|
||||||
/// or an underlying state provider.
|
/// or an underlying state provider.
|
||||||
@ -11,14 +12,14 @@ use reth_primitives::{trie::AccountProof, Account, Address, BlockNumber, Bytecod
|
|||||||
pub struct BundleStateProvider<SP: StateProvider, BSDP: BundleStateDataProvider> {
|
pub struct BundleStateProvider<SP: StateProvider, BSDP: BundleStateDataProvider> {
|
||||||
/// The inner state provider.
|
/// The inner state provider.
|
||||||
pub(crate) state_provider: SP,
|
pub(crate) state_provider: SP,
|
||||||
/// Post state data,
|
/// Bundle state data,
|
||||||
pub(crate) post_state_data_provider: BSDP,
|
pub(crate) bundle_state_data_provider: BSDP,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP: StateProvider, BSDP: BundleStateDataProvider> BundleStateProvider<SP, BSDP> {
|
impl<SP: StateProvider, BSDP: BundleStateDataProvider> BundleStateProvider<SP, BSDP> {
|
||||||
/// Create new post-state provider
|
/// Create new bundle state provider
|
||||||
pub fn new(state_provider: SP, post_state_data_provider: BSDP) -> Self {
|
pub fn new(state_provider: SP, bundle_state_data_provider: BSDP) -> Self {
|
||||||
Self { state_provider, post_state_data_provider }
|
Self { state_provider, bundle_state_data_provider }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ impl<SP: StateProvider, BSDP: BundleStateDataProvider> BlockHashReader
|
|||||||
for BundleStateProvider<SP, BSDP>
|
for BundleStateProvider<SP, BSDP>
|
||||||
{
|
{
|
||||||
fn block_hash(&self, block_number: BlockNumber) -> ProviderResult<Option<B256>> {
|
fn block_hash(&self, block_number: BlockNumber) -> ProviderResult<Option<B256>> {
|
||||||
let block_hash = self.post_state_data_provider.block_hash(block_number);
|
let block_hash = self.bundle_state_data_provider.block_hash(block_number);
|
||||||
if block_hash.is_some() {
|
if block_hash.is_some() {
|
||||||
return Ok(block_hash)
|
return Ok(block_hash)
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@ impl<SP: StateProvider, BSDP: BundleStateDataProvider> AccountReader
|
|||||||
for BundleStateProvider<SP, BSDP>
|
for BundleStateProvider<SP, BSDP>
|
||||||
{
|
{
|
||||||
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
|
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
|
||||||
if let Some(account) = self.post_state_data_provider.state().account(&address) {
|
if let Some(account) = self.bundle_state_data_provider.state().account(&address) {
|
||||||
Ok(account)
|
Ok(account)
|
||||||
} else {
|
} else {
|
||||||
self.state_provider.basic_account(address)
|
self.state_provider.basic_account(address)
|
||||||
@ -59,11 +60,20 @@ impl<SP: StateProvider, BSDP: BundleStateDataProvider> AccountReader
|
|||||||
impl<SP: StateProvider, BSDP: BundleStateDataProvider> StateRootProvider
|
impl<SP: StateProvider, BSDP: BundleStateDataProvider> StateRootProvider
|
||||||
for BundleStateProvider<SP, BSDP>
|
for BundleStateProvider<SP, BSDP>
|
||||||
{
|
{
|
||||||
fn state_root(&self, post_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
fn state_root(&self, bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
||||||
let mut state = self.post_state_data_provider.state().clone();
|
let mut state = self.bundle_state_data_provider.state().clone();
|
||||||
state.extend(post_state.clone());
|
state.extend(bundle_state.clone());
|
||||||
self.state_provider.state_root(&state)
|
self.state_provider.state_root(&state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state_root_with_updates(
|
||||||
|
&self,
|
||||||
|
bundle_state: &BundleStateWithReceipts,
|
||||||
|
) -> ProviderResult<(B256, TrieUpdates)> {
|
||||||
|
let mut state = self.bundle_state_data_provider.state().clone();
|
||||||
|
state.extend(bundle_state.clone());
|
||||||
|
self.state_provider.state_root_with_updates(&state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SP: StateProvider, BSDP: BundleStateDataProvider> StateProvider
|
impl<SP: StateProvider, BSDP: BundleStateDataProvider> StateProvider
|
||||||
@ -76,7 +86,7 @@ impl<SP: StateProvider, BSDP: BundleStateDataProvider> StateProvider
|
|||||||
) -> ProviderResult<Option<reth_primitives::StorageValue>> {
|
) -> ProviderResult<Option<reth_primitives::StorageValue>> {
|
||||||
let u256_storage_key = storage_key.into();
|
let u256_storage_key = storage_key.into();
|
||||||
if let Some(value) =
|
if let Some(value) =
|
||||||
self.post_state_data_provider.state().storage(&account, u256_storage_key)
|
self.bundle_state_data_provider.state().storage(&account, u256_storage_key)
|
||||||
{
|
{
|
||||||
return Ok(Some(value))
|
return Ok(Some(value))
|
||||||
}
|
}
|
||||||
@ -85,7 +95,7 @@ impl<SP: StateProvider, BSDP: BundleStateDataProvider> StateProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
|
fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
|
||||||
if let Some(bytecode) = self.post_state_data_provider.state().bytecode(&code_hash) {
|
if let Some(bytecode) = self.bundle_state_data_provider.state().bytecode(&code_hash) {
|
||||||
return Ok(Some(bytecode))
|
return Ok(Some(bytecode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -571,14 +571,14 @@ where
|
|||||||
|
|
||||||
fn pending_with_provider(
|
fn pending_with_provider(
|
||||||
&self,
|
&self,
|
||||||
post_state_data: Box<dyn BundleStateDataProvider>,
|
bundle_state_data: Box<dyn BundleStateDataProvider>,
|
||||||
) -> ProviderResult<StateProviderBox<'_>> {
|
) -> ProviderResult<StateProviderBox<'_>> {
|
||||||
let canonical_fork = post_state_data.canonical_fork();
|
let canonical_fork = bundle_state_data.canonical_fork();
|
||||||
trace!(target: "providers::blockchain", ?canonical_fork, "Returning post state provider");
|
trace!(target: "providers::blockchain", ?canonical_fork, "Returning post state provider");
|
||||||
|
|
||||||
let state_provider = self.history_by_block_hash(canonical_fork.hash)?;
|
let state_provider = self.history_by_block_hash(canonical_fork.hash)?;
|
||||||
let post_state_provider = BundleStateProvider::new(state_provider, post_state_data);
|
let bundle_state_provider = BundleStateProvider::new(state_provider, bundle_state_data);
|
||||||
Ok(Box::new(post_state_provider))
|
Ok(Box::new(bundle_state_provider))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ use reth_interfaces::provider::ProviderResult;
|
|||||||
use reth_primitives::{
|
use reth_primitives::{
|
||||||
trie::AccountProof, Account, Address, BlockNumber, Bytecode, StorageKey, StorageValue, B256,
|
trie::AccountProof, Account, Address, BlockNumber, Bytecode, StorageKey, StorageValue, B256,
|
||||||
};
|
};
|
||||||
|
use reth_trie::updates::TrieUpdates;
|
||||||
|
|
||||||
/// State provider for a given block number which takes a tx reference.
|
/// State provider for a given block number which takes a tx reference.
|
||||||
///
|
///
|
||||||
@ -198,7 +199,14 @@ impl<'b, TX: DbTx> BlockHashReader for HistoricalStateProviderRef<'b, TX> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, TX: DbTx> StateRootProvider for HistoricalStateProviderRef<'b, TX> {
|
impl<'b, TX: DbTx> StateRootProvider for HistoricalStateProviderRef<'b, TX> {
|
||||||
fn state_root(&self, _post_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
fn state_root(&self, _bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
||||||
|
Err(ProviderError::StateRootNotAvailableForHistoricalBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_root_with_updates(
|
||||||
|
&self,
|
||||||
|
_bundle_state: &BundleStateWithReceipts,
|
||||||
|
) -> ProviderResult<(B256, TrieUpdates)> {
|
||||||
Err(ProviderError::StateRootNotAvailableForHistoricalBlock)
|
Err(ProviderError::StateRootNotAvailableForHistoricalBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use reth_primitives::{
|
|||||||
keccak256, trie::AccountProof, Account, Address, BlockNumber, Bytecode, StorageKey,
|
keccak256, trie::AccountProof, Account, Address, BlockNumber, Bytecode, StorageKey,
|
||||||
StorageValue, B256,
|
StorageValue, B256,
|
||||||
};
|
};
|
||||||
|
use reth_trie::updates::TrieUpdates;
|
||||||
|
|
||||||
/// State provider over latest state that takes tx reference.
|
/// State provider over latest state that takes tx reference.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -62,6 +63,15 @@ impl<'b, TX: DbTx> StateRootProvider for LatestStateProviderRef<'b, TX> {
|
|||||||
fn state_root(&self, bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
fn state_root(&self, bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
||||||
bundle_state.state_root_slow(self.db).map_err(|err| ProviderError::Database(err.into()))
|
bundle_state.state_root_slow(self.db).map_err(|err| ProviderError::Database(err.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state_root_with_updates(
|
||||||
|
&self,
|
||||||
|
bundle_state: &BundleStateWithReceipts,
|
||||||
|
) -> ProviderResult<(B256, TrieUpdates)> {
|
||||||
|
bundle_state
|
||||||
|
.state_root_slow_with_updates(self.db)
|
||||||
|
.map_err(|err| ProviderError::Database(err.into()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, TX: DbTx> StateProvider for LatestStateProviderRef<'b, TX> {
|
impl<'b, TX: DbTx> StateProvider for LatestStateProviderRef<'b, TX> {
|
||||||
|
|||||||
@ -32,6 +32,7 @@ macro_rules! delegate_provider_impls {
|
|||||||
for $target =>
|
for $target =>
|
||||||
StateRootProvider $(where [$($generics)*])? {
|
StateRootProvider $(where [$($generics)*])? {
|
||||||
fn state_root(&self, state: &crate::BundleStateWithReceipts) -> reth_interfaces::provider::ProviderResult<reth_primitives::B256>;
|
fn state_root(&self, state: &crate::BundleStateWithReceipts) -> reth_interfaces::provider::ProviderResult<reth_primitives::B256>;
|
||||||
|
fn state_root_with_updates(&self, state: &crate::BundleStateWithReceipts) -> reth_interfaces::provider::ProviderResult<(reth_primitives::B256, reth_trie::updates::TrieUpdates)>;
|
||||||
}
|
}
|
||||||
AccountReader $(where [$($generics)*])? {
|
AccountReader $(where [$($generics)*])? {
|
||||||
fn basic_account(&self, address: reth_primitives::Address) -> reth_interfaces::provider::ProviderResult<Option<reth_primitives::Account>>;
|
fn basic_account(&self, address: reth_primitives::Address) -> reth_interfaces::provider::ProviderResult<Option<reth_primitives::Account>>;
|
||||||
|
|||||||
@ -15,6 +15,7 @@ use reth_primitives::{
|
|||||||
SealedBlock, SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned,
|
SealedBlock, SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned,
|
||||||
TransactionSignedNoHash, TxHash, TxNumber, B256, U256,
|
TransactionSignedNoHash, TxHash, TxNumber, B256, U256,
|
||||||
};
|
};
|
||||||
|
use reth_trie::updates::TrieUpdates;
|
||||||
use revm::primitives::{BlockEnv, CfgEnv};
|
use revm::primitives::{BlockEnv, CfgEnv};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap},
|
collections::{BTreeMap, HashMap},
|
||||||
@ -496,7 +497,14 @@ impl AccountReader for MockEthProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StateRootProvider for MockEthProvider {
|
impl StateRootProvider for MockEthProvider {
|
||||||
fn state_root(&self, _state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
fn state_root(&self, _bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_root_with_updates(
|
||||||
|
&self,
|
||||||
|
_bundle_state: &BundleStateWithReceipts,
|
||||||
|
) -> ProviderResult<(B256, TrieUpdates)> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,7 +610,7 @@ impl StateProviderFactory for MockEthProvider {
|
|||||||
|
|
||||||
fn pending_with_provider<'a>(
|
fn pending_with_provider<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
_post_state_data: Box<dyn BundleStateDataProvider + 'a>,
|
_bundle_state_data: Box<dyn BundleStateDataProvider + 'a>,
|
||||||
) -> ProviderResult<StateProviderBox<'a>> {
|
) -> ProviderResult<StateProviderBox<'a>> {
|
||||||
Ok(Box::new(self.clone()))
|
Ok(Box::new(self.clone()))
|
||||||
}
|
}
|
||||||
@ -638,7 +646,7 @@ impl StateProviderFactory for Arc<MockEthProvider> {
|
|||||||
|
|
||||||
fn pending_with_provider<'a>(
|
fn pending_with_provider<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
_post_state_data: Box<dyn BundleStateDataProvider + 'a>,
|
_bundle_state_data: Box<dyn BundleStateDataProvider + 'a>,
|
||||||
) -> ProviderResult<StateProviderBox<'a>> {
|
) -> ProviderResult<StateProviderBox<'a>> {
|
||||||
Ok(Box::new(self.clone()))
|
Ok(Box::new(self.clone()))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ use reth_primitives::{
|
|||||||
SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned,
|
SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned,
|
||||||
TransactionSignedNoHash, TxHash, TxNumber, B256, MAINNET, U256,
|
TransactionSignedNoHash, TxHash, TxNumber, B256, MAINNET, U256,
|
||||||
};
|
};
|
||||||
|
use reth_trie::updates::TrieUpdates;
|
||||||
use revm::primitives::{BlockEnv, CfgEnv};
|
use revm::primitives::{BlockEnv, CfgEnv};
|
||||||
use std::{
|
use std::{
|
||||||
ops::{RangeBounds, RangeInclusive},
|
ops::{RangeBounds, RangeInclusive},
|
||||||
@ -274,6 +275,13 @@ impl StateRootProvider for NoopProvider {
|
|||||||
fn state_root(&self, _state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
fn state_root(&self, _state: &BundleStateWithReceipts) -> ProviderResult<B256> {
|
||||||
Ok(B256::default())
|
Ok(B256::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state_root_with_updates(
|
||||||
|
&self,
|
||||||
|
_bundle_state: &BundleStateWithReceipts,
|
||||||
|
) -> ProviderResult<(B256, TrieUpdates)> {
|
||||||
|
Ok((B256::default(), TrieUpdates::default()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StateProvider for NoopProvider {
|
impl StateProvider for NoopProvider {
|
||||||
@ -368,7 +376,7 @@ impl StateProviderFactory for NoopProvider {
|
|||||||
|
|
||||||
fn pending_with_provider<'a>(
|
fn pending_with_provider<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
_post_state_data: Box<dyn crate::BundleStateDataProvider + 'a>,
|
_bundle_state_data: Box<dyn crate::BundleStateDataProvider + 'a>,
|
||||||
) -> ProviderResult<StateProviderBox<'a>> {
|
) -> ProviderResult<StateProviderBox<'a>> {
|
||||||
Ok(Box::new(*self))
|
Ok(Box::new(*self))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use reth_primitives::{
|
|||||||
trie::AccountProof, Address, BlockHash, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag,
|
trie::AccountProof, Address, BlockHash, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag,
|
||||||
Bytecode, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256,
|
Bytecode, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256,
|
||||||
};
|
};
|
||||||
|
use reth_trie::updates::TrieUpdates;
|
||||||
|
|
||||||
/// Type alias of boxed [StateProvider].
|
/// Type alias of boxed [StateProvider].
|
||||||
pub type StateProviderBox<'a> = Box<dyn StateProvider + 'a>;
|
pub type StateProviderBox<'a> = Box<dyn StateProvider + 'a>;
|
||||||
@ -180,11 +181,11 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync {
|
|||||||
block_hash: B256,
|
block_hash: B256,
|
||||||
) -> ProviderResult<Option<StateProviderBox<'_>>>;
|
) -> ProviderResult<Option<StateProviderBox<'_>>>;
|
||||||
|
|
||||||
/// Return a [StateProvider] that contains post state data provider.
|
/// Return a [StateProvider] that contains bundle state data provider.
|
||||||
/// Used to inspect or execute transaction on the pending state.
|
/// Used to inspect or execute transaction on the pending state.
|
||||||
fn pending_with_provider(
|
fn pending_with_provider(
|
||||||
&self,
|
&self,
|
||||||
post_state_data: Box<dyn BundleStateDataProvider>,
|
bundle_state_data: Box<dyn BundleStateDataProvider>,
|
||||||
) -> ProviderResult<StateProviderBox<'_>>;
|
) -> ProviderResult<StateProviderBox<'_>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +233,17 @@ pub trait BundleStateDataProvider: Send + Sync {
|
|||||||
/// A type that can compute the state root of a given post state.
|
/// A type that can compute the state root of a given post state.
|
||||||
#[auto_impl[Box,&, Arc]]
|
#[auto_impl[Box,&, Arc]]
|
||||||
pub trait StateRootProvider: Send + Sync {
|
pub trait StateRootProvider: Send + Sync {
|
||||||
/// Returns the state root of the BundleState on top of the current state.
|
/// Returns the state root of the `BundleState` on top of the current state.
|
||||||
fn state_root(&self, post_state: &BundleStateWithReceipts) -> ProviderResult<B256>;
|
///
|
||||||
|
/// NOTE: It is recommended to provide a different implementation from
|
||||||
|
/// `state_root_with_updates` since it affects the memory usage during state root
|
||||||
|
/// computation.
|
||||||
|
fn state_root(&self, bundle_state: &BundleStateWithReceipts) -> ProviderResult<B256>;
|
||||||
|
|
||||||
|
/// Returns the state root of the BundleState on top of the current state with trie
|
||||||
|
/// updates to be committed to the database.
|
||||||
|
fn state_root_with_updates(
|
||||||
|
&self,
|
||||||
|
bundle_state: &BundleStateWithReceipts,
|
||||||
|
) -> ProviderResult<(B256, TrieUpdates)>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user