From 297934fe21bf4870871e2311dda01fc3cef5f3c6 Mon Sep 17 00:00:00 2001 From: greged93 <82421016+greged93@users.noreply.github.com> Date: Mon, 19 Aug 2024 04:29:17 -0700 Subject: [PATCH] feat(rpc): get_account (#10369) --- crates/rpc/rpc-eth-api/src/core.rs | 7 +++-- crates/rpc/rpc-eth-api/src/helpers/state.rs | 32 +++++++++++++++++++-- crates/trie/trie/src/state.rs | 2 +- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/crates/rpc/rpc-eth-api/src/core.rs b/crates/rpc/rpc-eth-api/src/core.rs index ba9d75fa29..30c51a9f7e 100644 --- a/crates/rpc/rpc-eth-api/src/core.rs +++ b/crates/rpc/rpc-eth-api/src/core.rs @@ -650,10 +650,11 @@ where /// Handler for: `eth_getAccount` async fn get_account( &self, - _address: Address, - _block: BlockId, + address: Address, + block: BlockId, ) -> RpcResult { - Err(internal_rpc_err("unimplemented")) + trace!(target: "rpc::eth", "Serving eth_getAccount"); + Ok(EthState::get_account(self, address, block).await?) } /// Handler for: `eth_maxPriorityFeePerGas` diff --git a/crates/rpc/rpc-eth-api/src/helpers/state.rs b/crates/rpc/rpc-eth-api/src/helpers/state.rs index b59e524c40..2d2c159751 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/state.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/state.rs @@ -4,12 +4,13 @@ use futures::Future; use reth_errors::RethError; use reth_evm::ConfigureEvmEnv; -use reth_primitives::{Address, BlockId, Bytes, Header, B256, U256}; +use reth_primitives::{Address, BlockId, Bytes, Header, B256, KECCAK_EMPTY, U256}; use reth_provider::{ BlockIdReader, ChainSpecProvider, StateProvider, StateProviderBox, StateProviderFactory, + StateRootProvider, }; use reth_rpc_eth_types::{EthApiError, EthStateCache, PendingBlockEnv, RpcInvalidTransactionError}; -use reth_rpc_types::{serde_helpers::JsonStorageKey, EIP1186AccountProofResponse}; +use reth_rpc_types::{serde_helpers::JsonStorageKey, Account, EIP1186AccountProofResponse}; use reth_rpc_types_compat::proof::from_primitive_account_proof; use reth_transaction_pool::{PoolTransaction, TransactionPool}; use revm::db::BundleState; @@ -127,6 +128,33 @@ pub trait EthState: LoadState + SpawnBlocking { .await }) } + + /// Returns the account at the given address for the provided block identifier. + fn get_account( + &self, + address: Address, + block_id: BlockId, + ) -> impl Future> + 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)? + .unwrap_or_default(); + let balance = account.balance; + let nonce = account.nonce; + let code_hash = account.bytecode_hash.unwrap_or(KECCAK_EMPTY); + + // Provide a default `HashedStorage` value in order to + // get the storage root hash of the current state. + let storage_root = state + .hashed_storage_root(address, Default::default()) + .map_err(Self::Error::from_eth_err)?; + + Ok(Account { balance, nonce, code_hash, storage_root }) + }) + } } /// Loads state from database. diff --git a/crates/trie/trie/src/state.rs b/crates/trie/trie/src/state.rs index 0246ce9787..5d25c44c44 100644 --- a/crates/trie/trie/src/state.rs +++ b/crates/trie/trie/src/state.rs @@ -136,7 +136,7 @@ impl HashedPostState { } /// Representation of in-memory hashed storage. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(PartialEq, Eq, Clone, Debug, Default)] pub struct HashedStorage { /// Flag indicating whether the storage was wiped or not. pub wiped: bool,