fix: improve account diff populate (#4934)

This commit is contained in:
Matthias Seitz
2023-10-06 21:23:22 +02:00
committed by GitHub
parent 851831f4b8
commit 51ecf3e96d
2 changed files with 37 additions and 31 deletions

View File

@ -8,7 +8,7 @@ use reth_rpc_types::{trace::parity::*, TransactionInfo};
use revm::{ use revm::{
db::DatabaseRef, db::DatabaseRef,
interpreter::opcode::{self, spec_opcode_gas}, interpreter::opcode::{self, spec_opcode_gas},
primitives::{AccountInfo, ExecutionResult, ResultAndState, SpecId, KECCAK_EMPTY}, primitives::{Account, ExecutionResult, ResultAndState, SpecId, KECCAK_EMPTY},
}; };
use std::collections::{HashSet, VecDeque}; use std::collections::{HashSet, VecDeque};
@ -207,11 +207,7 @@ impl ParityTraceBuilder {
// check the state diff case // check the state diff case
if let Some(ref mut state_diff) = trace_res.state_diff { if let Some(ref mut state_diff) = trace_res.state_diff {
populate_account_balance_nonce_diffs( populate_account_balance_nonce_diffs(state_diff, &db, state.iter())?;
state_diff,
&db,
state.into_iter().map(|(addr, acc)| (addr, acc.info)),
)?;
} }
// check the vm trace case // check the vm trace case
@ -569,31 +565,49 @@ where
/// ///
/// It's expected that `DB` is a revm [Database](revm::db::Database) which at this point already /// It's expected that `DB` is a revm [Database](revm::db::Database) which at this point already
/// contains all the accounts that are in the state map and never has to fetch them from disk. /// contains all the accounts that are in the state map and never has to fetch them from disk.
pub fn populate_account_balance_nonce_diffs<DB, I>( ///
/// This is intended to be called after inspecting a transaction with the returned state.
pub fn populate_account_balance_nonce_diffs<'a, DB, I>(
state_diff: &mut StateDiff, state_diff: &mut StateDiff,
db: DB, db: DB,
account_diffs: I, account_diffs: I,
) -> Result<(), DB::Error> ) -> Result<(), DB::Error>
where where
I: IntoIterator<Item = (Address, AccountInfo)>, I: IntoIterator<Item = (&'a Address, &'a Account)>,
DB: DatabaseRef, DB: DatabaseRef,
{ {
for (addr, changed_acc) in account_diffs.into_iter() { for (addr, changed_acc) in account_diffs.into_iter() {
let addr = *addr;
let entry = state_diff.entry(addr).or_default(); let entry = state_diff.entry(addr).or_default();
let db_acc = db.basic(addr)?.unwrap_or_default();
entry.balance = if db_acc.balance == changed_acc.balance { // we check if this account was created during the transaction
Delta::Unchanged if changed_acc.is_created() {
entry.balance = Delta::Added(changed_acc.info.balance);
entry.nonce = Delta::Added(U64::from(changed_acc.info.nonce));
if changed_acc.info.code_hash == KECCAK_EMPTY {
// this is an additional check to ensure new accounts always get the empty code
// marked as added
entry.code = Delta::Added(Default::default());
}
} else { } else {
Delta::Changed(ChangedType { from: db_acc.balance, to: changed_acc.balance }) // account already exists, we need to fetch the account from the db
}; let db_acc = db.basic(addr)?.unwrap_or_default();
entry.nonce = if db_acc.nonce == changed_acc.nonce { entry.balance = if db_acc.balance == changed_acc.info.balance {
Delta::Unchanged Delta::Unchanged
} else { } else {
Delta::Changed(ChangedType { Delta::Changed(ChangedType { from: db_acc.balance, to: changed_acc.info.balance })
from: U64::from(db_acc.nonce), };
to: U64::from(changed_acc.nonce),
}) // this is relevant for the caller and contracts
}; entry.nonce = if db_acc.nonce == changed_acc.info.nonce {
Delta::Unchanged
} else {
Delta::Changed(ChangedType {
from: U64::from(db_acc.nonce),
to: U64::from(changed_acc.info.nonce),
})
};
}
} }
Ok(()) Ok(())

View File

@ -168,11 +168,7 @@ where
// If statediffs were requested, populate them with the account balance and // If statediffs were requested, populate them with the account balance and
// nonce from pre-state // nonce from pre-state
if let Some(ref mut state_diff) = trace_res.state_diff { if let Some(ref mut state_diff) = trace_res.state_diff {
populate_account_balance_nonce_diffs( populate_account_balance_nonce_diffs(state_diff, &db, state.iter())?;
state_diff,
&db,
state.iter().map(|(addr, acc)| (*addr, acc.info.clone())),
)?;
} }
results.push(trace_res); results.push(trace_res);
@ -513,11 +509,7 @@ where
// If statediffs were requested, populate them with the account balance and nonce // If statediffs were requested, populate them with the account balance and nonce
// from pre-state // from pre-state
if let Some(ref mut state_diff) = full_trace.state_diff { if let Some(ref mut state_diff) = full_trace.state_diff {
populate_account_balance_nonce_diffs( populate_account_balance_nonce_diffs(state_diff, db, state.iter())?;
state_diff,
db,
state.iter().map(|(addr, acc)| (*addr, acc.info.clone())),
)?;
} }
let trace = TraceResultsWithTransactionHash { let trace = TraceResultsWithTransactionHash {