mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
fix: load code by hash for prestate trace (#5115)
Co-authored-by: Alexey Shekhirin <a.shekhirin@gmail.com>
This commit is contained in:
@ -11,7 +11,7 @@ use reth_rpc_types::trace::geth::{
|
|||||||
};
|
};
|
||||||
use revm::{
|
use revm::{
|
||||||
db::DatabaseRef,
|
db::DatabaseRef,
|
||||||
primitives::{ResultAndState, KECCAK_EMPTY},
|
primitives::{AccountInfo, ResultAndState, KECCAK_EMPTY},
|
||||||
};
|
};
|
||||||
use std::collections::{BTreeMap, HashMap, VecDeque};
|
use std::collections::{BTreeMap, HashMap, VecDeque};
|
||||||
|
|
||||||
@ -188,17 +188,35 @@ impl GethTraceBuilder {
|
|||||||
where
|
where
|
||||||
DB: DatabaseRef,
|
DB: DatabaseRef,
|
||||||
{
|
{
|
||||||
|
// loads the code from the account or the database
|
||||||
|
// Geth always includes the contract code in the prestate. However,
|
||||||
|
// the code hash will be KECCAK_EMPTY if the account is an EOA. Therefore
|
||||||
|
// we need to filter it out.
|
||||||
|
let load_account_code = |db_acc: &AccountInfo| {
|
||||||
|
db_acc
|
||||||
|
.code
|
||||||
|
.as_ref()
|
||||||
|
.map(|code| code.original_bytes())
|
||||||
|
.or_else(|| {
|
||||||
|
if db_acc.code_hash == KECCAK_EMPTY {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
db.code_by_hash_ref(db_acc.code_hash).ok().map(|code| code.original_bytes())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(Into::into)
|
||||||
|
};
|
||||||
|
|
||||||
let account_diffs = state.into_iter().map(|(addr, acc)| (*addr, acc));
|
let account_diffs = state.into_iter().map(|(addr, acc)| (*addr, acc));
|
||||||
let is_diff = prestate_config.is_diff_mode();
|
let is_diff = prestate_config.is_diff_mode();
|
||||||
if !is_diff {
|
if !is_diff {
|
||||||
let mut prestate = PreStateMode::default();
|
let mut prestate = PreStateMode::default();
|
||||||
for (addr, changed_acc) in account_diffs {
|
for (addr, changed_acc) in account_diffs {
|
||||||
let db_acc = db.basic_ref(addr)?.unwrap_or_default();
|
let db_acc = db.basic_ref(addr)?.unwrap_or_default();
|
||||||
let mut pre_state = AccountState::from_account_info(
|
let code = load_account_code(&db_acc);
|
||||||
db_acc.nonce,
|
|
||||||
db_acc.balance,
|
let mut pre_state =
|
||||||
db_acc.code.as_ref().map(|code| code.original_bytes()),
|
AccountState::from_account_info(db_acc.nonce, db_acc.balance, code);
|
||||||
);
|
|
||||||
|
|
||||||
// handle _touched_ storage slots
|
// handle _touched_ storage slots
|
||||||
for (key, slot) in changed_acc.storage.iter() {
|
for (key, slot) in changed_acc.storage.iter() {
|
||||||
@ -213,22 +231,8 @@ impl GethTraceBuilder {
|
|||||||
let mut account_change_kinds = HashMap::with_capacity(account_diffs.len());
|
let mut account_change_kinds = HashMap::with_capacity(account_diffs.len());
|
||||||
for (addr, changed_acc) in account_diffs {
|
for (addr, changed_acc) in account_diffs {
|
||||||
let db_acc = db.basic_ref(addr)?.unwrap_or_default();
|
let db_acc = db.basic_ref(addr)?.unwrap_or_default();
|
||||||
let db_code = db_acc.code.as_ref();
|
|
||||||
let db_code_hash = db_acc.code_hash;
|
|
||||||
|
|
||||||
// Geth always includes the contract code in the prestate. However,
|
let pre_code = load_account_code(&db_acc);
|
||||||
// the code hash will be KECCAK_EMPTY if the account is an EOA. Therefore
|
|
||||||
// we need to filter it out.
|
|
||||||
let pre_code = db_code
|
|
||||||
.map(|code| code.original_bytes())
|
|
||||||
.or_else(|| {
|
|
||||||
if db_code_hash == KECCAK_EMPTY {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
db.code_by_hash_ref(db_code_hash).ok().map(|code| code.original_bytes())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(Into::into);
|
|
||||||
|
|
||||||
let mut pre_state =
|
let mut pre_state =
|
||||||
AccountState::from_account_info(db_acc.nonce, db_acc.balance, pre_code);
|
AccountState::from_account_info(db_acc.nonce, db_acc.balance, pre_code);
|
||||||
|
|||||||
Reference in New Issue
Block a user