perf: query accounts with &Address to avoid copying address (#13554)

This commit is contained in:
Hai | RISE
2024-12-25 19:31:28 +07:00
committed by GitHub
parent 14c1c0be69
commit 031f430b8f
27 changed files with 74 additions and 71 deletions

View File

@ -1019,7 +1019,7 @@ mod tests {
}
impl AccountReader for MockStateProvider {
fn basic_account(&self, _address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
Ok(None)
}
}

View File

@ -96,9 +96,9 @@ impl<N: NodePrimitives> BlockHashReader for MemoryOverlayStateProviderRef<'_, N>
}
impl<N: NodePrimitives> AccountReader for MemoryOverlayStateProviderRef<'_, N> {
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
for block in &self.in_memory {
if let Some(account) = block.execution_output.account(&address) {
if let Some(account) = block.execution_output.account(address) {
return Ok(account);
}
}

View File

@ -396,7 +396,7 @@ mod tests {
}
impl AccountReader for Provider {
fn basic_account(&self, _address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
Ok(self.account)
}
}

View File

@ -119,7 +119,7 @@ fn setup_provider(
// other updates
let should_process = match account.status {
AccountStatus::SelfDestructed => {
provider_rw.basic_account(*address).ok().flatten().is_some()
provider_rw.basic_account(address).ok().flatten().is_some()
}
_ => true,
};

View File

@ -16,7 +16,7 @@ pub trait EvmStateProvider: Send + Sync {
/// Get basic account information.
///
/// Returns [`None`] if the account doesn't exist.
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>>;
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>>;
/// Get the hash of the block with the given number. Returns [`None`] if no block with this
/// number exists.
@ -38,7 +38,7 @@ pub trait EvmStateProvider: Send + Sync {
// Blanket implementation of EvmStateProvider for any type that implements StateProvider.
impl<T: reth_storage_api::StateProvider> EvmStateProvider for T {
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
<T as reth_storage_api::AccountReader>::basic_account(self, address)
}
@ -141,7 +141,7 @@ impl<DB: EvmStateProvider> DatabaseRef for StateProviderDatabase<DB> {
/// Returns `Ok` with `Some(AccountInfo)` if the account exists,
/// `None` if it doesn't, or an error if encountered.
fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
Ok(self.basic_account(address)?.map(Into::into))
Ok(self.basic_account(&address)?.map(Into::into))
}
/// Retrieves the bytecode associated with a given code hash.

View File

@ -47,8 +47,8 @@ impl StateProviderTest {
}
impl AccountReader for StateProviderTest {
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
Ok(self.accounts.get(&address).map(|(_, acc)| *acc))
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
Ok(self.accounts.get(address).map(|(_, acc)| *acc))
}
}

View File

@ -87,7 +87,7 @@ pub trait EstimateCall: Call {
// Optimize for simple transfer transactions, potentially reducing the gas estimate.
if env.tx.data.is_empty() {
if let TransactTo::Call(to) = env.tx.transact_to {
if let Ok(code) = db.db.account_code(to) {
if let Ok(code) = db.db.account_code(&to) {
let no_code_callee = code.map(|code| code.is_empty()).unwrap_or(true);
if no_code_callee {
// If the tx is a simple transfer (call to an account with no code) we can

View File

@ -53,7 +53,7 @@ pub trait EthState: LoadState + SpawnBlocking {
self.spawn_blocking_io(move |this| {
Ok(this
.state_at_block_id_or_latest(block_id)?
.account_balance(address)
.account_balance(&address)
.map_err(Self::Error::from_eth_err)?
.unwrap_or_default())
})
@ -131,7 +131,7 @@ pub trait EthState: LoadState + SpawnBlocking {
) -> impl Future<Output = Result<Option<Account>, Self::Error>> + Send {
self.spawn_blocking_io(move |this| {
let state = this.state_at_block_id(block_id)?;
let account = state.basic_account(address).map_err(Self::Error::from_eth_err)?;
let account = state.basic_account(&address).map_err(Self::Error::from_eth_err)?;
let Some(account) = account else { return Ok(None) };
// Check whether the distance to the block exceeds the maximum configured proof window.
@ -252,7 +252,7 @@ pub trait LoadState:
// first fetch the on chain nonce of the account
let on_chain_account_nonce = this
.latest_state()?
.account_nonce(address)
.account_nonce(&address)
.map_err(Self::Error::from_eth_err)?
.unwrap_or_default();
@ -290,7 +290,7 @@ pub trait LoadState:
// first fetch the on chain nonce of the account
let on_chain_account_nonce = this
.state_at_block_id_or_latest(block_id)?
.account_nonce(address)
.account_nonce(&address)
.map_err(Self::Error::from_eth_err)?
.unwrap_or_default();
@ -333,7 +333,7 @@ pub trait LoadState:
self.spawn_blocking_io(move |this| {
Ok(this
.state_at_block_id_or_latest(block_id)?
.account_code(address)
.account_code(&address)
.map_err(Self::Error::from_eth_err)?
.unwrap_or_default()
.original_bytes())

View File

@ -106,7 +106,7 @@ impl reth_storage_api::StateProofProvider for StateProviderTraitObjWrapper<'_> {
impl reth_storage_api::AccountReader for StateProviderTraitObjWrapper<'_> {
fn basic_account(
&self,
address: revm_primitives::Address,
address: &revm_primitives::Address,
) -> reth_errors::ProviderResult<Option<reth_primitives::Account>> {
self.0.basic_account(address)
}
@ -163,21 +163,21 @@ impl StateProvider for StateProviderTraitObjWrapper<'_> {
fn account_code(
&self,
addr: revm_primitives::Address,
addr: &revm_primitives::Address,
) -> reth_errors::ProviderResult<Option<reth_primitives::Bytecode>> {
self.0.account_code(addr)
}
fn account_balance(
&self,
addr: revm_primitives::Address,
addr: &revm_primitives::Address,
) -> reth_errors::ProviderResult<Option<U256>> {
self.0.account_balance(addr)
}
fn account_nonce(
&self,
addr: revm_primitives::Address,
addr: &revm_primitives::Address,
) -> reth_errors::ProviderResult<Option<u64>> {
self.0.account_nonce(addr)
}

View File

@ -73,7 +73,7 @@ where
let hash_map = accounts_before.iter().try_fold(
HashMap::default(),
|mut hash_map, account_before| -> RethResult<_> {
let current_balance = state.account_balance(account_before.address)?;
let current_balance = state.account_balance(&account_before.address)?;
let prev_balance = account_before.info.map(|info| info.balance);
if current_balance != prev_balance {
hash_map.insert(account_before.address, current_balance.unwrap_or_default());

View File

@ -939,17 +939,17 @@ mod tests {
// assert accounts
assert_eq!(
provider.basic_account(account1),
provider.basic_account(&account1),
Ok(Some(account1_info)),
"Post changed of a account"
);
assert_eq!(
provider.basic_account(account2),
provider.basic_account(&account2),
Ok(Some(account2_info)),
"Post changed of a account"
);
assert_eq!(
provider.basic_account(account3),
provider.basic_account(&account3),
Ok(Some(account3_info)),
"Post changed of a account"
);
@ -1075,19 +1075,19 @@ mod tests {
// assert unwind stage
assert_eq!(
provider.basic_account(acc1),
provider.basic_account(&acc1),
Ok(Some(acc1_info)),
"Pre changed of a account"
);
assert_eq!(
provider.basic_account(acc2),
provider.basic_account(&acc2),
Ok(Some(acc2_info)),
"Post changed of a account"
);
let miner_acc = address!("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba");
assert_eq!(
provider.basic_account(miner_acc),
provider.basic_account(&miner_acc),
Ok(None),
"Third account should be unwound"
);
@ -1173,7 +1173,7 @@ mod tests {
// assert unwind stage
let provider = test_db.factory.database_provider_rw().unwrap();
assert_eq!(provider.basic_account(destroyed_address), Ok(None), "Account was destroyed");
assert_eq!(provider.basic_account(&destroyed_address), Ok(None), "Account was destroyed");
assert_eq!(
provider.tx_ref().get::<tables::PlainStorageState>(destroyed_address),

View File

@ -748,7 +748,7 @@ impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider2<N> {
impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider2<N> {
/// Get basic account information.
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
self.consistent_provider()?.basic_account(address)
}
}

View File

@ -68,9 +68,9 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> BlockHashReader
}
impl<SP: StateProvider, EDP: ExecutionDataProvider> AccountReader for BundleStateProvider<SP, EDP> {
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
if let Some(account) =
self.block_execution_data_provider.execution_outcome().account(&address)
self.block_execution_data_provider.execution_outcome().account(address)
{
Ok(account)
} else {

View File

@ -234,7 +234,7 @@ impl<N: ProviderNodeTypes> ConsistentProvider<N> {
let AccountBeforeTx { info: old_info, address } = account_before;
match state.entry(address) {
hash_map::Entry::Vacant(entry) => {
let new_info = state_provider.basic_account(address)?;
let new_info = state_provider.basic_account(&address)?;
entry.insert((old_info, new_info, HashMap::new()));
}
hash_map::Entry::Occupied(mut entry) => {
@ -252,7 +252,7 @@ impl<N: ProviderNodeTypes> ConsistentProvider<N> {
// get account state or insert from plain state.
let account_state = match state.entry(address) {
hash_map::Entry::Vacant(entry) => {
let present_info = state_provider.basic_account(address)?;
let present_info = state_provider.basic_account(&address)?;
entry.insert((present_info, present_info, HashMap::new()))
}
hash_map::Entry::Occupied(entry) => entry.into_mut(),
@ -1441,7 +1441,7 @@ impl<N: ProviderNodeTypes> ChangeSetReader for ConsistentProvider<N> {
impl<N: ProviderNodeTypes> AccountReader for ConsistentProvider<N> {
/// Get basic account information.
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
// use latest state provider
let state_provider = self.latest_ref()?;
state_provider.basic_account(address)

View File

@ -862,8 +862,8 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypes> DatabaseProvider<TX, N> {
}
impl<TX: DbTx, N: NodeTypes> AccountReader for DatabaseProvider<TX, N> {
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
Ok(self.tx.get::<tables::PlainAccountState>(address)?)
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
Ok(self.tx.get_by_encoded_key::<tables::PlainAccountState>(address)?)
}
}

View File

@ -949,7 +949,7 @@ impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider<N> {
/// Get basic account information.
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
self.database.provider()?.basic_account(address)
}
}

View File

@ -249,21 +249,21 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider> AccountRea
for HistoricalStateProviderRef<'_, Provider>
{
/// Get basic account information.
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
match self.account_history_lookup(address)? {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
match self.account_history_lookup(*address)? {
HistoryInfo::NotYetWritten => Ok(None),
HistoryInfo::InChangeset(changeset_block_number) => Ok(self
.tx()
.cursor_dup_read::<tables::AccountChangeSets>()?
.seek_by_key_subkey(changeset_block_number, address)?
.filter(|acc| acc.address == address)
.seek_by_key_subkey(changeset_block_number, *address)?
.filter(|acc| &acc.address == address)
.ok_or(ProviderError::AccountChangesetNotFound {
block_number: changeset_block_number,
address,
address: *address,
})?
.info),
HistoryInfo::InPlainState | HistoryInfo::MaybeInPlainState => {
Ok(self.tx().get::<tables::PlainAccountState>(address)?)
Ok(self.tx().get_by_encoded_key::<tables::PlainAccountState>(address)?)
}
}
}
@ -633,43 +633,46 @@ mod tests {
let db = factory.provider().unwrap();
// run
assert_eq!(HistoricalStateProviderRef::new(&db, 1).basic_account(ADDRESS), Ok(None));
assert_eq!(HistoricalStateProviderRef::new(&db, 1).basic_account(&ADDRESS), Ok(None));
assert_eq!(
HistoricalStateProviderRef::new(&db, 2).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 2).basic_account(&ADDRESS),
Ok(Some(acc_at3))
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 3).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 3).basic_account(&ADDRESS),
Ok(Some(acc_at3))
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 4).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 4).basic_account(&ADDRESS),
Ok(Some(acc_at7))
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 7).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 7).basic_account(&ADDRESS),
Ok(Some(acc_at7))
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 9).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 9).basic_account(&ADDRESS),
Ok(Some(acc_at10))
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 10).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 10).basic_account(&ADDRESS),
Ok(Some(acc_at10))
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 11).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 11).basic_account(&ADDRESS),
Ok(Some(acc_at15))
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 16).basic_account(ADDRESS),
HistoricalStateProviderRef::new(&db, 16).basic_account(&ADDRESS),
Ok(Some(acc_plain))
);
assert_eq!(HistoricalStateProviderRef::new(&db, 1).basic_account(HIGHER_ADDRESS), Ok(None));
assert_eq!(
HistoricalStateProviderRef::new(&db, 1000).basic_account(HIGHER_ADDRESS),
HistoricalStateProviderRef::new(&db, 1).basic_account(&HIGHER_ADDRESS),
Ok(None)
);
assert_eq!(
HistoricalStateProviderRef::new(&db, 1000).basic_account(&HIGHER_ADDRESS),
Ok(Some(higher_acc_plain))
);
}

View File

@ -43,8 +43,8 @@ impl<'b, Provider: DBProvider> LatestStateProviderRef<'b, Provider> {
impl<Provider: DBProvider> AccountReader for LatestStateProviderRef<'_, Provider> {
/// Get basic account information.
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
self.tx().get::<tables::PlainAccountState>(address).map_err(Into::into)
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
self.tx().get_by_encoded_key::<tables::PlainAccountState>(address).map_err(Into::into)
}
}

View File

@ -31,7 +31,7 @@ macro_rules! delegate_provider_impls {
$crate::providers::state::macros::delegate_impls_to_as_ref!(
for $target =>
AccountReader $(where [$($generics)*])? {
fn basic_account(&self, address: alloy_primitives::Address) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::Account>>;
fn basic_account(&self, address: &alloy_primitives::Address) -> reth_storage_errors::provider::ProviderResult<Option<reth_primitives::Account>>;
}
BlockHashReader $(where [$($generics)*])? {
fn block_hash(&self, number: u64) -> reth_storage_errors::provider::ProviderResult<Option<alloy_primitives::B256>>;

View File

@ -577,8 +577,8 @@ impl BlockReaderIdExt for MockEthProvider {
}
impl AccountReader for MockEthProvider {
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
Ok(self.accounts.lock().get(&address).cloned().map(|a| a.account))
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
Ok(self.accounts.lock().get(address).cloned().map(|a| a.account))
}
}

View File

@ -361,12 +361,12 @@ mod tests {
// Check plain state
assert_eq!(
provider.basic_account(address_a).expect("Could not read account state"),
provider.basic_account(&address_a).expect("Could not read account state"),
Some(reth_account_a),
"Account A state is wrong"
);
assert_eq!(
provider.basic_account(address_b).expect("Could not read account state"),
provider.basic_account(&address_b).expect("Could not read account state"),
Some(reth_account_b_changed),
"Account B state is wrong"
);
@ -422,7 +422,7 @@ mod tests {
// Check new plain state for account B
assert_eq!(
provider.basic_account(address_b).expect("Could not read account state"),
provider.basic_account(&address_b).expect("Could not read account state"),
None,
"Account B should be deleted"
);

View File

@ -14,7 +14,7 @@ pub trait AccountReader: Send + Sync {
/// Get basic account information.
///
/// Returns `None` if the account doesn't exist.
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>>;
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>>;
}
/// Account reader

View File

@ -357,7 +357,7 @@ impl<C: Send + Sync, N: NodePrimitives> HeaderProvider for NoopProvider<C, N> {
}
impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
fn basic_account(&self, _address: Address) -> ProviderResult<Option<Account>> {
fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
Ok(None)
}
}

View File

@ -40,7 +40,7 @@ pub trait StateProvider:
/// Get account code by its address.
///
/// Returns `None` if the account doesn't exist or account is not a contract
fn account_code(&self, addr: Address) -> ProviderResult<Option<Bytecode>> {
fn account_code(&self, addr: &Address) -> ProviderResult<Option<Bytecode>> {
// Get basic account information
// Returns None if acc doesn't exist
let acc = match self.basic_account(addr)? {
@ -63,7 +63,7 @@ pub trait StateProvider:
/// Get account balance by its address.
///
/// Returns `None` if the account doesn't exist
fn account_balance(&self, addr: Address) -> ProviderResult<Option<U256>> {
fn account_balance(&self, addr: &Address) -> ProviderResult<Option<U256>> {
// Get basic account information
// Returns None if acc doesn't exist
match self.basic_account(addr)? {
@ -75,7 +75,7 @@ pub trait StateProvider:
/// Get account nonce by its address.
///
/// Returns `None` if the account doesn't exist
fn account_nonce(&self, addr: Address) -> ProviderResult<Option<u64>> {
fn account_nonce(&self, addr: &Address) -> ProviderResult<Option<u64>> {
// Get basic account information
// Returns None if acc doesn't exist
match self.basic_account(addr)? {

View File

@ -535,7 +535,7 @@ where
Err(err) => return Err(Box::new((addresses.collect(), err))),
};
for addr in addresses {
if let Ok(maybe_acc) = state.basic_account(addr) {
if let Ok(maybe_acc) = state.basic_account(&addr) {
let acc = maybe_acc
.map(|acc| ChangedAccount { address: addr, nonce: acc.nonce, balance: acc.balance })
.unwrap_or_else(|| ChangedAccount::empty(addr));

View File

@ -367,7 +367,7 @@ where
let state = maybe_state.as_deref().expect("provider is set");
// Use provider to get account info
let account = match state.basic_account(transaction.sender()) {
let account = match state.basic_account(transaction.sender_ref()) {
Ok(account) => account.unwrap_or_default(),
Err(err) => {
return TransactionValidationOutcome::Error(*transaction.hash(), Box::new(err))

View File

@ -234,8 +234,8 @@ fn state_provider_example<T: StateProvider + AccountReader>(provider: T) -> eyre
let storage_key = B256::random();
// Can get account / storage state with simple point queries
let _account = provider.basic_account(address)?;
let _code = provider.account_code(address)?;
let _account = provider.basic_account(&address)?;
let _code = provider.account_code(&address)?;
let _storage = provider.storage(address, storage_key)?;
// TODO: unimplemented.
// let _proof = provider.proof(address, &[])?;