feat: Add eth_getBalance, eth_getTransactionCount, eth_getStorageAt handlers (#1422)

Co-authored-by: lambdaclass-user <github@lambdaclass.com>
This commit is contained in:
Tomás
2023-02-17 08:42:24 -03:00
committed by GitHub
parent 1edb9d4ccd
commit 2306bfe998
4 changed files with 65 additions and 25 deletions

View File

@ -61,12 +61,14 @@ where
// Implemented
EthApiClient::protocol_version(client).await.unwrap();
EthApiClient::chain_id(client).await.unwrap();
EthApiClient::chain_id(client).await.unwrap();
EthApiClient::accounts(client).await.unwrap();
EthApiClient::block_number(client).await.unwrap();
EthApiClient::get_code(client, address, None).await.unwrap();
EthApiClient::send_raw_transaction(client, tx).await.unwrap();
EthApiClient::fee_history(client, 0.into(), block_number.into(), None).await.unwrap();
EthApiClient::balance(client, address, None).await.unwrap();
EthApiClient::transaction_count(client, address, None).await.unwrap();
EthApiClient::storage_at(client, address, U256::default(), None).await.unwrap();
// Unimplemented
assert!(is_unimplemented(EthApiClient::syncing(client).await.err().unwrap()));
@ -109,13 +111,6 @@ where
.unwrap()
));
assert!(is_unimplemented(EthApiClient::transaction_receipt(client, hash).await.err().unwrap()));
assert!(is_unimplemented(EthApiClient::balance(client, address, None).await.err().unwrap()));
assert!(is_unimplemented(
EthApiClient::storage_at(client, address, U256::default(), None).await.err().unwrap()
));
assert!(is_unimplemented(
EthApiClient::transaction_count(client, address, None).await.err().unwrap()
));
assert!(is_unimplemented(
EthApiClient::call(client, call_request.clone(), None).await.err().unwrap()
));

View File

@ -130,25 +130,25 @@ where
Err(internal_rpc_err("unimplemented"))
}
async fn balance(&self, _address: Address, _block_number: Option<BlockId>) -> Result<U256> {
Err(internal_rpc_err("unimplemented"))
async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
Ok(EthApi::balance(self, address, block_number)?)
}
async fn storage_at(
&self,
_address: Address,
_index: U256,
_block_number: Option<BlockId>,
address: Address,
index: U256,
block_number: Option<BlockId>,
) -> Result<H256> {
Err(internal_rpc_err("unimplemented"))
Ok(EthApi::storage_at(self, address, index, block_number)?)
}
async fn transaction_count(
&self,
_address: Address,
_block_number: Option<BlockId>,
address: Address,
block_number: Option<BlockId>,
) -> Result<U256> {
Err(internal_rpc_err("unimplemented"))
Ok(EthApi::get_transaction_count(self, address, block_number)?)
}
async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {

View File

@ -4,7 +4,6 @@ use crate::{
eth::error::{EthApiError, EthResult},
EthApi,
};
use reth_interfaces::Result;
use reth_primitives::{rpc::BlockId, Address, Bytes, H256, U256};
use reth_provider::{BlockProvider, StateProvider, StateProviderFactory};
@ -19,12 +18,34 @@ where
Ok(code)
}
async fn storage_at(
pub(crate) fn balance(&self, address: Address, block_id: Option<BlockId>) -> EthResult<U256> {
let state =
self.state_at_block_id_or_latest(block_id)?.ok_or(EthApiError::UnknownBlockNumber)?;
let balance = state.account_balance(address)?.unwrap_or_default();
Ok(balance)
}
pub(crate) fn get_transaction_count(
&self,
_address: Address,
_index: U256,
_block_number: Option<BlockId>,
) -> Result<H256> {
todo!()
address: Address,
block_id: Option<BlockId>,
) -> EthResult<U256> {
let state =
self.state_at_block_id_or_latest(block_id)?.ok_or(EthApiError::UnknownBlockNumber)?;
let nonce = U256::from(state.account_nonce(address)?.unwrap_or_default());
Ok(nonce)
}
pub(crate) fn storage_at(
&self,
address: Address,
index: U256,
block_id: Option<BlockId>,
) -> EthResult<H256> {
let state =
self.state_at_block_id_or_latest(block_id)?.ok_or(EthApiError::UnknownBlockNumber)?;
let storage_key = H256(index.to_be_bytes());
let value = state.storage(address, storage_key)?.unwrap_or_default();
Ok(H256(value.to_be_bytes()))
}
}

View File

@ -3,7 +3,7 @@ use crate::BlockHashProvider;
use auto_impl::auto_impl;
use reth_interfaces::Result;
use reth_primitives::{
Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, H256, KECCAK_EMPTY,
Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, H256, KECCAK_EMPTY, U256,
};
/// An abstraction for a type that provides state data.
@ -37,6 +37,30 @@ pub trait StateProvider: BlockHashProvider + AccountProvider + Send + Sync {
// Return `None` if no code hash is set
Ok(None)
}
/// Get account balance by its address.
///
/// Returns `None` if the account doesn't exist
fn account_balance(&self, addr: Address) -> Result<Option<U256>> {
// Get basic account information
// Returns None if acc doesn't exist
match self.basic_account(addr)? {
Some(acc) => Ok(Some(acc.balance)),
None => Ok(None),
}
}
/// Get account nonce by its address.
///
/// Returns `None` if the account doesn't exist
fn account_nonce(&self, addr: Address) -> Result<Option<u64>> {
// Get basic account information
// Returns None if acc doesn't exist
match self.basic_account(addr)? {
Some(acc) => Ok(Some(acc.nonce)),
None => Ok(None),
}
}
}
/// Light wrapper that returns `StateProvider` implementations that correspond to the given