mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-29 09:08:05 -05:00
chore(rpc): more trace prep (#1752)
This commit is contained in:
@@ -576,7 +576,9 @@ where
|
||||
NetApi::new(self.network.clone(), eth_api.clone()).into_rpc().into()
|
||||
}
|
||||
RethRpcModule::Trace => {
|
||||
TraceApi::new(self.client.clone(), eth_cache.clone()).into_rpc().into()
|
||||
TraceApi::new(self.client.clone(), eth_api.clone(), eth_cache.clone())
|
||||
.into_rpc()
|
||||
.into()
|
||||
}
|
||||
RethRpcModule::Web3 => Web3Api::new(self.network.clone()).into_rpc().into(),
|
||||
})
|
||||
|
||||
@@ -198,9 +198,6 @@ where
|
||||
assert!(is_unimplemented(
|
||||
TraceApiClient::trace_get(client, H256::default(), vec![]).await.err().unwrap()
|
||||
));
|
||||
assert!(is_unimplemented(
|
||||
TraceApiClient::trace_transaction(client, H256::default()).await.err().unwrap()
|
||||
));
|
||||
}
|
||||
|
||||
async fn test_basic_web3_calls<C>(client: &C)
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::{
|
||||
eth::{
|
||||
error::{EthApiError, EthResult, InvalidTransactionError, RevertError},
|
||||
revm_utils::{build_call_evm_env, get_precompiles, inspect, transact},
|
||||
EthTransactions,
|
||||
},
|
||||
EthApi,
|
||||
};
|
||||
@@ -18,6 +19,7 @@ use reth_rpc_types::{
|
||||
state::{AccountOverride, StateOverride},
|
||||
CallRequest,
|
||||
};
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use revm::{
|
||||
db::{CacheDB, DatabaseRef},
|
||||
primitives::{
|
||||
@@ -33,31 +35,10 @@ const MIN_CREATE_GAS: u64 = 53_000u64;
|
||||
|
||||
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
|
||||
where
|
||||
Pool: TransactionPool + Clone + 'static,
|
||||
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
|
||||
Network: Send + Sync + 'static,
|
||||
{
|
||||
/// Returns the revm evm env for the requested [BlockId]
|
||||
///
|
||||
/// If the [BlockId] this will return the [BlockId::Hash] of the block the env was configured
|
||||
/// for.
|
||||
async fn evm_env_at(&self, at: BlockId) -> EthResult<(CfgEnv, BlockEnv, BlockId)> {
|
||||
// TODO handle Pending state's env
|
||||
match at {
|
||||
BlockId::Number(BlockNumberOrTag::Pending) => {
|
||||
// This should perhaps use the latest env settings and update block specific
|
||||
// settings like basefee/number
|
||||
unimplemented!("support pending state env")
|
||||
}
|
||||
hash_or_num => {
|
||||
let block_hash = self
|
||||
.client()
|
||||
.block_hash_for_id(hash_or_num)?
|
||||
.ok_or_else(|| EthApiError::UnknownBlockNumber)?;
|
||||
let (cfg, env) = self.cache().get_evm_env(block_hash).await?;
|
||||
Ok((cfg, env, block_hash.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes the call request at the given [BlockId]
|
||||
pub(crate) async fn call_at(
|
||||
&self,
|
||||
|
||||
@@ -27,10 +27,10 @@ use std::collections::BTreeMap;
|
||||
#[async_trait::async_trait]
|
||||
impl<Client, Pool, Network> EthApiServer for EthApi<Client, Pool, Network>
|
||||
where
|
||||
Self: EthApiSpec,
|
||||
Self: EthApiSpec + EthTransactions,
|
||||
Pool: TransactionPool + 'static,
|
||||
Client: BlockProvider + HeaderProvider + StateProviderFactory + EvmEnvProvider + 'static,
|
||||
Network: 'static,
|
||||
Network: Send + Sync + 'static,
|
||||
{
|
||||
/// Handler for: `eth_protocolVersion`
|
||||
async fn protocol_version(&self) -> Result<U64> {
|
||||
|
||||
@@ -5,32 +5,64 @@ use crate::{
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use reth_primitives::{
|
||||
BlockId, Bytes, FromRecoveredTransaction, IntoRecoveredTransaction, TransactionSigned,
|
||||
TransactionSignedEcRecovered, H256, U256,
|
||||
BlockId, BlockNumberOrTag, Bytes, FromRecoveredTransaction, IntoRecoveredTransaction,
|
||||
TransactionSigned, TransactionSignedEcRecovered, H256, U256,
|
||||
};
|
||||
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory, TransactionsProvider};
|
||||
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory};
|
||||
use reth_rlp::Decodable;
|
||||
use reth_rpc_types::{Index, Transaction, TransactionRequest};
|
||||
use reth_transaction_pool::{TransactionOrigin, TransactionPool};
|
||||
use revm::primitives::{BlockEnv, CfgEnv};
|
||||
|
||||
/// Commonly used transaction related functions for the [EthApi] type in the `eth_` namespace
|
||||
#[async_trait::async_trait]
|
||||
pub trait EthTransactions: Send + Sync {
|
||||
/// Returns the revm evm env for the requested [BlockId]
|
||||
///
|
||||
/// If the [BlockId] this will return the [BlockId::Hash] of the block the env was configured
|
||||
/// for.
|
||||
async fn evm_env_at(&self, at: BlockId) -> EthResult<(CfgEnv, BlockEnv, BlockId)>;
|
||||
|
||||
/// Returns the transaction by hash.
|
||||
///
|
||||
/// Checks the pool and state.
|
||||
///
|
||||
/// Returns `Ok(None)` if no matching transaction was found.
|
||||
async fn transaction_by_hash(&self, hash: H256) -> EthResult<Option<TransactionSource>>;
|
||||
|
||||
/// Returns the transaction by including its corresponding [BlockId]
|
||||
async fn transaction_by_hash_at(
|
||||
&self,
|
||||
hash: H256,
|
||||
) -> EthResult<Option<(TransactionSource, BlockId)>>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<Client, Pool, Network> EthTransactions for EthApi<Client, Pool, Network>
|
||||
where
|
||||
Pool: TransactionPool + Clone + 'static,
|
||||
Client: TransactionsProvider + 'static,
|
||||
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
|
||||
Network: Send + Sync + 'static,
|
||||
{
|
||||
async fn evm_env_at(&self, at: BlockId) -> EthResult<(CfgEnv, BlockEnv, BlockId)> {
|
||||
// TODO handle Pending state's env
|
||||
match at {
|
||||
BlockId::Number(BlockNumberOrTag::Pending) => {
|
||||
// This should perhaps use the latest env settings and update block specific
|
||||
// settings like basefee/number
|
||||
unimplemented!("support pending state env")
|
||||
}
|
||||
hash_or_num => {
|
||||
let block_hash = self
|
||||
.client()
|
||||
.block_hash_for_id(hash_or_num)?
|
||||
.ok_or_else(|| EthApiError::UnknownBlockNumber)?;
|
||||
let (cfg, env) = self.cache().get_evm_env(block_hash).await?;
|
||||
Ok((cfg, env, block_hash.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn transaction_by_hash(&self, hash: H256) -> EthResult<Option<TransactionSource>> {
|
||||
if let Some(tx) = self.pool().get(&hash).map(|tx| tx.transaction.to_recovered_transaction())
|
||||
{
|
||||
@@ -55,6 +87,38 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn transaction_by_hash_at(
|
||||
&self,
|
||||
hash: H256,
|
||||
) -> EthResult<Option<(TransactionSource, BlockId)>> {
|
||||
match self.transaction_by_hash(hash).await? {
|
||||
None => return Ok(None),
|
||||
Some(tx) => {
|
||||
let res = match tx {
|
||||
tx @ TransactionSource::Pool(_) => {
|
||||
(tx, BlockId::Number(BlockNumberOrTag::Pending))
|
||||
}
|
||||
TransactionSource::Database {
|
||||
transaction,
|
||||
index,
|
||||
block_hash,
|
||||
block_number,
|
||||
} => {
|
||||
let at = BlockId::Hash(block_hash.into());
|
||||
let tx = TransactionSource::Database {
|
||||
transaction,
|
||||
index,
|
||||
block_hash,
|
||||
block_number,
|
||||
};
|
||||
(tx, at)
|
||||
}
|
||||
};
|
||||
Ok(Some(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === impl EthApi ===
|
||||
@@ -140,6 +204,15 @@ pub enum TransactionSource {
|
||||
},
|
||||
}
|
||||
|
||||
impl From<TransactionSource> for TransactionSignedEcRecovered {
|
||||
fn from(value: TransactionSource) -> Self {
|
||||
match value {
|
||||
TransactionSource::Pool(tx) => tx,
|
||||
TransactionSource::Database { transaction, .. } => transaction,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransactionSource> for Transaction {
|
||||
fn from(value: TransactionSource) -> Self {
|
||||
match value {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::{eth::cache::EthStateCache, result::internal_rpc_err};
|
||||
use crate::{
|
||||
eth::{cache::EthStateCache, EthTransactions},
|
||||
result::internal_rpc_err,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult as Result;
|
||||
use reth_primitives::{BlockId, Bytes, H256};
|
||||
@@ -14,26 +17,29 @@ use std::collections::HashSet;
|
||||
///
|
||||
/// This type provides the functionality for handling `trace` related requests.
|
||||
#[derive(Clone)]
|
||||
pub struct TraceApi<Client> {
|
||||
pub struct TraceApi<Client, Eth> {
|
||||
/// The client that can interact with the chain.
|
||||
client: Client,
|
||||
/// Access to commonly used code of the `eth` namespace
|
||||
eth_api: Eth,
|
||||
/// The async cache frontend for eth related data
|
||||
eth_cache: EthStateCache,
|
||||
}
|
||||
|
||||
// === impl TraceApi ===
|
||||
|
||||
impl<Client> TraceApi<Client> {
|
||||
impl<Client, Eth> TraceApi<Client, Eth> {
|
||||
/// Create a new instance of the [TraceApi]
|
||||
pub fn new(client: Client, eth_cache: EthStateCache) -> Self {
|
||||
Self { client, eth_cache }
|
||||
pub fn new(client: Client, eth_api: Eth, eth_cache: EthStateCache) -> Self {
|
||||
Self { client, eth_api, eth_cache }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<Client> TraceApiServer for TraceApi<Client>
|
||||
impl<Client, Eth> TraceApiServer for TraceApi<Client, Eth>
|
||||
where
|
||||
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
|
||||
Eth: EthTransactions + 'static,
|
||||
{
|
||||
/// Handler for `trace_call`
|
||||
async fn trace_call(
|
||||
@@ -107,13 +113,20 @@ where
|
||||
/// Handler for `trace_transaction`
|
||||
async fn trace_transaction(
|
||||
&self,
|
||||
_hash: H256,
|
||||
hash: H256,
|
||||
) -> Result<Option<Vec<LocalizedTransactionTrace>>> {
|
||||
let (_transaction, at) = match self.eth_api.transaction_by_hash_at(hash).await? {
|
||||
None => return Ok(None),
|
||||
Some(res) => res,
|
||||
};
|
||||
|
||||
let (_cfg, _block_env, _at) = self.eth_api.evm_env_at(at).await?;
|
||||
|
||||
Err(internal_rpc_err("unimplemented"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Client> std::fmt::Debug for TraceApi<Client> {
|
||||
impl<Client, Eth> std::fmt::Debug for TraceApi<Client, Eth> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("TraceApi").finish_non_exhaustive()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user