Builder style implementation for trace_call (#5074)

This commit is contained in:
Supernovahs.eth
2023-10-19 01:38:56 +05:30
committed by GitHub
parent ce73d933c9
commit ae3914eb66
6 changed files with 141 additions and 55 deletions

View File

@ -1,9 +1,8 @@
use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_primitives::{BlockId, Bytes, B256}; use reth_primitives::{BlockId, Bytes, B256};
use reth_rpc_types::{ use reth_rpc_types::{
state::StateOverride, trace::{filter::TraceFilter, parity::*, tracerequest::TraceRequest},
trace::{filter::TraceFilter, parity::*}, CallRequest, Index,
BlockOverrides, CallRequest, Index,
}; };
use std::collections::HashSet; use std::collections::HashSet;
@ -13,14 +12,7 @@ use std::collections::HashSet;
pub trait TraceApi { pub trait TraceApi {
/// Executes the given call and returns a number of possible traces for it. /// Executes the given call and returns a number of possible traces for it.
#[method(name = "call")] #[method(name = "call")]
async fn trace_call( async fn trace_call(&self, trace_request: TraceRequest) -> RpcResult<TraceResults>;
&self,
call: CallRequest,
trace_types: HashSet<TraceType>,
block_id: Option<BlockId>,
state_overrides: Option<StateOverride>,
block_overrides: Option<Box<BlockOverrides>>,
) -> RpcResult<TraceResults>;
/// Performs multiple call traces on top of the same block. i.e. transaction n will be executed /// Performs multiple call traces on top of the same block. i.e. transaction n will be executed
/// on top of a pending block with all n-1 transactions applied (traced) first. Allows to trace /// on top of a pending block with all n-1 transactions applied (traced) first. Allows to trace

View File

@ -4,3 +4,4 @@ pub mod common;
pub mod filter; pub mod filter;
pub mod geth; pub mod geth;
pub mod parity; pub mod parity;
pub mod tracerequest;

View File

@ -0,0 +1,82 @@
//! Builder style functions for `trace_call`
use crate::{state::StateOverride, trace::parity::TraceType, BlockOverrides, CallRequest};
use reth_primitives::BlockId;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
/// Trace Request builder style function implementation
#[derive(Debug, Serialize, Deserialize)]
pub struct TraceRequest {
/// call request object
pub call: CallRequest,
/// trace types
pub trace_types: HashSet<TraceType>,
/// Optional: blockId
pub block_id: Option<BlockId>,
/// Optional: StateOverride
pub state_overrides: Option<StateOverride>,
/// Optional: BlockOverrides
pub block_overrides: Option<Box<BlockOverrides>>,
}
impl TraceRequest {
/// Returns a new [`TraceRequest`] given a [`CallRequest`] and [`HashSet<TraceType>`]
pub fn new(call: CallRequest) -> Self {
Self {
call,
trace_types: HashSet::new(),
block_id: None,
state_overrides: None,
block_overrides: None,
}
}
/// Sets the [`BlockId`]
/// Note: this is optional
pub fn with_block_id(mut self, block_id: BlockId) -> Self {
self.block_id = Some(block_id);
self
}
/// Sets the [`StateOverride`]
/// Note: this is optional
pub fn with_state_override(mut self, state_overrides: StateOverride) -> Self {
self.state_overrides = Some(state_overrides);
self
}
/// Sets the [`BlockOverrides`]
/// Note: this is optional
pub fn with_block_overrides(mut self, block_overrides: Box<BlockOverrides>) -> Self {
self.block_overrides = Some(block_overrides);
self
}
/// Inserts a single trace type.
pub fn with_trace_type(mut self, trace_type: TraceType) -> Self {
self.trace_types.insert(trace_type);
self
}
/// Inserts multiple trace types from an iterator.
pub fn with_trace_types<I: IntoIterator<Item = TraceType>>(mut self, trace_types: I) -> Self {
self.trace_types.extend(trace_types);
self
}
/// Inserts [`TraceType::Trace`]
pub fn with_trace(self) -> Self {
self.with_trace_type(TraceType::Trace)
}
/// Inserts [`TraceType::VmTrace`]
pub fn with_vm_trace(self) -> Self {
self.with_trace_type(TraceType::VmTrace)
}
/// Inserts [`TraceType::StateDiff`]
pub fn with_statediff(self) -> Self {
self.with_trace_type(TraceType::StateDiff)
}
}

View File

@ -0,0 +1,37 @@
use crate::{CallRequest,state::StateOverride,BlockOverrides};
use std::{collections::HashSet};
use reth_primitives::{BlockId};
use reth_rpc::{types::tracerequest::parity::TraceType};
pub struct TraceRequest{
call: CallRequest,
trace_types: HashSet<TraceType>,
block_id: Option<BlockId>,
state_overrides: Option<StateOverride>,
block_overrides: Option<Box<BlockOverrides>>
}
impl TraceRequest{
pub fn new(call:CallRequest,trace_types:HashSet<TraceType>) -> Self{
Self { call,trace_types,block_id:None, state_overrides: None, block_overrides:None }
}
pub fn with_block_id(mut self, block_id: BlockId) -> Self{
self.block_id = Some(block_id);
self
}
pub fn with_state_override(mut self, state_overrides:StateOverride) -> Self{
self.state_overrides = Some(state_overrides);
self
}
pub fn with_block_overrides(mut self, block_overrides:Box<BlockOverrides>) -> Self{
self.block_overrides = Some(block_overrides);
self
}
}

View File

@ -19,9 +19,8 @@ use reth_revm::{
}; };
use reth_rpc_api::TraceApiServer; use reth_rpc_api::TraceApiServer;
use reth_rpc_types::{ use reth_rpc_types::{
state::StateOverride, trace::{filter::TraceFilter, parity::*, tracerequest::TraceRequest},
trace::{filter::TraceFilter, parity::*}, BlockError, CallRequest, Index,
BlockError, BlockOverrides, CallRequest, Index,
}; };
use revm::{db::CacheDB, primitives::Env}; use revm::{db::CacheDB, primitives::Env};
use revm_primitives::db::DatabaseCommit; use revm_primitives::db::DatabaseCommit;
@ -65,25 +64,19 @@ where
Eth: EthTransactions + 'static, Eth: EthTransactions + 'static,
{ {
/// Executes the given call and returns a number of possible traces for it. /// Executes the given call and returns a number of possible traces for it.
pub async fn trace_call( pub async fn trace_call(&self, trace_request: TraceRequest) -> EthResult<TraceResults> {
&self, let at = trace_request.block_id.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
call: CallRequest, let config = tracing_config(&trace_request.trace_types);
trace_types: HashSet<TraceType>, let overrides =
block_id: Option<BlockId>, EvmOverrides::new(trace_request.state_overrides, trace_request.block_overrides);
state_overrides: Option<StateOverride>,
block_overrides: Option<Box<BlockOverrides>>,
) -> EthResult<TraceResults> {
let at = block_id.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
let config = tracing_config(&trace_types);
let overrides = EvmOverrides::new(state_overrides, block_overrides);
let mut inspector = TracingInspector::new(config); let mut inspector = TracingInspector::new(config);
self.inner self.inner
.eth_api .eth_api
.spawn_with_call_at(call, at, overrides, move |db, env| { .spawn_with_call_at(trace_request.call, at, overrides, move |db, env| {
let (res, _, db) = inspect_and_return_db(db, env, &mut inspector)?; let (res, _, db) = inspect_and_return_db(db, env, &mut inspector)?;
let trace_res = inspector.into_parity_builder().into_trace_results_with_state( let trace_res = inspector.into_parity_builder().into_trace_results_with_state(
&res, &res,
&trace_types, &trace_request.trace_types,
&db, &db,
)?; )?;
Ok(trace_res) Ok(trace_res)
@ -439,24 +432,9 @@ where
/// Executes the given call and returns a number of possible traces for it. /// Executes the given call and returns a number of possible traces for it.
/// ///
/// Handler for `trace_call` /// Handler for `trace_call`
async fn trace_call( async fn trace_call(&self, trace_request: TraceRequest) -> Result<TraceResults> {
&self,
call: CallRequest,
trace_types: HashSet<TraceType>,
block_id: Option<BlockId>,
state_overrides: Option<StateOverride>,
block_overrides: Option<Box<BlockOverrides>>,
) -> Result<TraceResults> {
let _permit = self.acquire_trace_permit().await; let _permit = self.acquire_trace_permit().await;
Ok(TraceApi::trace_call( Ok(TraceApi::trace_call(self, trace_request).await?)
self,
call,
trace_types,
block_id,
state_overrides,
block_overrides,
)
.await?)
} }
/// Handler for `trace_callMany` /// Handler for `trace_callMany`

View File

@ -17,7 +17,10 @@ use reth::{
Cli, Cli,
}, },
primitives::{Address, IntoRecoveredTransaction}, primitives::{Address, IntoRecoveredTransaction},
rpc::{compat::transaction::transaction_to_call_request, types::trace::parity::TraceType}, rpc::{
compat::transaction::transaction_to_call_request,
types::trace::{parity::TraceType, tracerequest::TraceRequest},
},
tasks::TaskSpawner, tasks::TaskSpawner,
transaction_pool::TransactionPool, transaction_pool::TransactionPool,
}; };
@ -76,16 +79,9 @@ impl RethNodeCommandConfig for RethCliTxpoolExt {
// trace the transaction with `trace_call` // trace the transaction with `trace_call`
let callrequest = let callrequest =
transaction_to_call_request(tx.to_recovered_transaction()); transaction_to_call_request(tx.to_recovered_transaction());
if let Ok(trace_result) = traceapi let tracerequest =
.trace_call( TraceRequest::new(callrequest).with_trace_type(TraceType::Trace);
callrequest, if let Ok(trace_result) = traceapi.trace_call(tracerequest).await {
HashSet::from([TraceType::Trace]),
None,
None,
None,
)
.await
{
println!( println!(
"trace result for transaction : {:?} is {:?}", "trace result for transaction : {:?} is {:?}",
tx.hash(), tx.hash(),