chore: use DatabaseProviderRW instead of TX on *State*::write_to_db (#9460)

This commit is contained in:
joshieDo
2024-07-11 23:01:07 +02:00
committed by GitHub
parent 1c27262902
commit 345798c77d
7 changed files with 48 additions and 33 deletions

View File

@ -85,7 +85,7 @@ impl<DB: Database> Persistence<DB> {
{
let trie_updates = block.trie_updates().clone();
let hashed_state = block.hashed_state();
HashedStateChanges(hashed_state.clone()).write_to_db(provider_rw.tx_ref())?;
HashedStateChanges(hashed_state.clone()).write_to_db(&provider_rw)?;
trie_updates.write_to_database(provider_rw.tx_ref())?;
}

View File

@ -25,7 +25,7 @@ impl StateWriter for ExecutionOutcome {
let tx = provider_rw.tx_ref();
let (plain_state, reverts) = self.bundle.into_plain_state_and_reverts(is_value_known);
StateReverts(reverts).write_to_db(tx, self.first_block)?;
StateReverts(reverts).write_to_db(provider_rw, self.first_block)?;
// write receipts
let mut bodies_cursor = tx.cursor_read::<tables::BlockBodyIndices>()?;
@ -63,7 +63,7 @@ impl StateWriter for ExecutionOutcome {
}
}
StateChanges(plain_state).write_to_db(tx)?;
StateChanges(plain_state).write_to_db(provider_rw)?;
Ok(())
}
@ -143,13 +143,11 @@ mod tests {
assert!(plain_state.storage.is_empty());
assert!(plain_state.contracts.is_empty());
StateChanges(plain_state)
.write_to_db(provider.tx_ref())
.write_to_db(&provider)
.expect("Could not write plain state to DB");
assert_eq!(reverts.storage, [[]]);
StateReverts(reverts)
.write_to_db(provider.tx_ref(), 1)
.expect("Could not write reverts to DB");
StateReverts(reverts).write_to_db(&provider, 1).expect("Could not write reverts to DB");
let reth_account_a = account_a.into();
let reth_account_b = account_b.into();
@ -209,16 +207,14 @@ mod tests {
);
assert!(plain_state.contracts.is_empty());
StateChanges(plain_state)
.write_to_db(provider.tx_ref())
.write_to_db(&provider)
.expect("Could not write plain state to DB");
assert_eq!(
reverts.storage,
[[PlainStorageRevert { address: address_b, wiped: true, storage_revert: vec![] }]]
);
StateReverts(reverts)
.write_to_db(provider.tx_ref(), 2)
.expect("Could not write reverts to DB");
StateReverts(reverts).write_to_db(&provider, 2).expect("Could not write reverts to DB");
// Check new plain state for account B
assert_eq!(

View File

@ -1,8 +1,9 @@
use crate::DatabaseProviderRW;
use itertools::Itertools;
use reth_db::tables;
use reth_db::{tables, Database};
use reth_db_api::{
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW},
transaction::{DbTx, DbTxMut},
transaction::DbTxMut,
DatabaseError,
};
use reth_primitives::{StorageEntry, U256};
@ -14,10 +15,14 @@ pub struct HashedStateChanges(pub HashedPostState);
impl HashedStateChanges {
/// Write the bundle state to the database.
pub fn write_to_db<TX: DbTxMut + DbTx>(self, tx: &TX) -> Result<(), DatabaseError> {
pub fn write_to_db<DB>(self, provider: &DatabaseProviderRW<DB>) -> Result<(), DatabaseError>
where
DB: Database,
{
// Write hashed account updates.
let sorted_accounts = self.0.accounts.into_iter().sorted_unstable_by_key(|(key, _)| *key);
let mut hashed_accounts_cursor = tx.cursor_write::<tables::HashedAccounts>()?;
let mut hashed_accounts_cursor =
provider.tx_ref().cursor_write::<tables::HashedAccounts>()?;
for (hashed_address, account) in sorted_accounts {
if let Some(account) = account {
hashed_accounts_cursor.upsert(hashed_address, account)?;
@ -28,7 +33,8 @@ impl HashedStateChanges {
// Write hashed storage changes.
let sorted_storages = self.0.storages.into_iter().sorted_by_key(|(key, _)| *key);
let mut hashed_storage_cursor = tx.cursor_dup_write::<tables::HashedStorages>()?;
let mut hashed_storage_cursor =
provider.tx_ref().cursor_dup_write::<tables::HashedStorages>()?;
for (hashed_address, storage) in sorted_storages {
if storage.wiped && hashed_storage_cursor.seek_exact(hashed_address)?.is_some() {
hashed_storage_cursor.delete_current_duplicates()?;
@ -59,6 +65,7 @@ impl HashedStateChanges {
mod tests {
use super::*;
use crate::test_utils::create_test_provider_factory;
use reth_db_api::transaction::DbTx;
use reth_primitives::{keccak256, Account, Address, B256};
use reth_trie::HashedStorage;
@ -95,7 +102,7 @@ mod tests {
hashed_state.storages.insert(destroyed_address_hashed, HashedStorage::new(true));
let provider_rw = provider_factory.provider_rw().unwrap();
assert_eq!(HashedStateChanges(hashed_state).write_to_db(provider_rw.tx_ref()), Ok(()));
assert_eq!(HashedStateChanges(hashed_state).write_to_db(&provider_rw), Ok(()));
provider_rw.commit().unwrap();
let provider = provider_factory.provider().unwrap();

View File

@ -1,8 +1,9 @@
use crate::DatabaseProviderRW;
use rayon::slice::ParallelSliceMut;
use reth_db::tables;
use reth_db::{tables, Database};
use reth_db_api::{
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW},
transaction::{DbTx, DbTxMut},
transaction::DbTxMut,
};
use reth_primitives::{Bytecode, StorageEntry, U256};
use reth_storage_errors::db::DatabaseError;
@ -20,7 +21,10 @@ impl From<StateChangeset> for StateChanges {
impl StateChanges {
/// 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<DB>(mut self, provider: &DatabaseProviderRW<DB>) -> Result<(), DatabaseError>
where
DB: Database,
{
// sort all entries so they can be written to database in more performant way.
// and take smaller memory footprint.
self.0.accounts.par_sort_by_key(|a| a.0);
@ -29,7 +33,7 @@ impl StateChanges {
// Write 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 = provider.tx_ref().cursor_write::<tables::PlainAccountState>()?;
// write account to database.
for (address, account) in self.0.accounts {
if let Some(account) = account {
@ -43,14 +47,15 @@ impl StateChanges {
// Write bytecode
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 = provider.tx_ref().cursor_write::<tables::Bytecodes>()?;
for (hash, bytecode) in self.0.contracts {
bytecodes_cursor.upsert(hash, Bytecode(bytecode))?;
}
// Write new storage state and wipe storage if needed.
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 =
provider.tx_ref().cursor_dup_write::<tables::PlainStorageState>()?;
for PlainStorageChangeset { address, wipe_storage, storage } in self.0.storage {
// Wiping of storage.
if wipe_storage && storages_cursor.seek_exact(address)?.is_some() {

View File

@ -1,9 +1,10 @@
use crate::DatabaseProviderRW;
use rayon::slice::ParallelSliceMut;
use reth_db::tables;
use reth_db::{tables, Database};
use reth_db_api::{
cursor::{DbCursorRO, DbDupCursorRO, DbDupCursorRW},
models::{AccountBeforeTx, BlockNumberAddress},
transaction::{DbTx, DbTxMut},
transaction::DbTxMut,
};
use reth_primitives::{BlockNumber, StorageEntry, B256, U256};
use reth_storage_errors::db::DatabaseError;
@ -24,15 +25,20 @@ impl StateReverts {
/// Write reverts to database.
///
/// `Note::` Reverts will delete all wiped storage from plain state.
pub fn write_to_db<TX: DbTxMut + DbTx>(
pub fn write_to_db<DB>(
self,
tx: &TX,
provider: &DatabaseProviderRW<DB>,
first_block: BlockNumber,
) -> Result<(), DatabaseError> {
) -> Result<(), DatabaseError>
where
DB: Database,
{
// Write storage changes
tracing::trace!(target: "provider::reverts", "Writing storage changes");
let mut storages_cursor = tx.cursor_dup_write::<tables::PlainStorageState>()?;
let mut storage_changeset_cursor = tx.cursor_dup_write::<tables::StorageChangeSets>()?;
let mut storages_cursor =
provider.tx_ref().cursor_dup_write::<tables::PlainStorageState>()?;
let mut storage_changeset_cursor =
provider.tx_ref().cursor_dup_write::<tables::StorageChangeSets>()?;
for (block_index, mut storage_changes) in self.0.storage.into_iter().enumerate() {
let block_number = first_block + block_index as BlockNumber;
@ -72,7 +78,8 @@ impl StateReverts {
// Write account changes
tracing::trace!(target: "provider::reverts", "Writing account changes");
let mut account_changeset_cursor = tx.cursor_dup_write::<tables::AccountChangeSets>()?;
let mut account_changeset_cursor =
provider.tx_ref().cursor_dup_write::<tables::AccountChangeSets>()?;
for (block_index, mut account_block_reverts) in self.0.accounts.into_iter().enumerate() {
let block_number = first_block + block_index as BlockNumber;

View File

@ -3270,7 +3270,7 @@ impl<DB: Database> BlockWriter for DatabaseProviderRW<DB> {
// insert hashes and intermediate merkle nodes
{
HashedStateChanges(hashed_state).write_to_db(&self.tx)?;
HashedStateChanges(hashed_state).write_to_db(self)?;
trie_updates.write_to_database(&self.tx)?;
}
durations_recorder.record_relative(metrics::Action::InsertHashes);

View File

@ -27,7 +27,7 @@ pub fn calculate_state_root(c: &mut Criterion) {
let provider_factory = create_test_provider_factory();
{
let provider_rw = provider_factory.provider_rw().unwrap();
HashedStateChanges(db_state).write_to_db(provider_rw.tx_ref()).unwrap();
HashedStateChanges(db_state).write_to_db(&provider_rw).unwrap();
let (_, updates) =
StateRoot::from_tx(provider_rw.tx_ref()).root_with_updates().unwrap();
updates.write_to_database(provider_rw.tx_ref()).unwrap();