Skip to content

Commit

Permalink
Builder style implementation for trace_call (paradigmxyz#5074)
Browse files Browse the repository at this point in the history
  • Loading branch information
supernovahs authored Oct 18, 2023
1 parent ce73d93 commit ae3914e
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 55 deletions.
14 changes: 3 additions & 11 deletions crates/rpc/rpc-api/src/trace.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_primitives::{BlockId, Bytes, B256};
use reth_rpc_types::{
state::StateOverride,
trace::{filter::TraceFilter, parity::*},
BlockOverrides, CallRequest, Index,
trace::{filter::TraceFilter, parity::*, tracerequest::TraceRequest},
CallRequest, Index,
};
use std::collections::HashSet;

Expand All @@ -13,14 +12,7 @@ use std::collections::HashSet;
pub trait TraceApi {
/// Executes the given call and returns a number of possible traces for it.
#[method(name = "call")]
async fn trace_call(
&self,
call: CallRequest,
trace_types: HashSet<TraceType>,
block_id: Option<BlockId>,
state_overrides: Option<StateOverride>,
block_overrides: Option<Box<BlockOverrides>>,
) -> RpcResult<TraceResults>;
async fn trace_call(&self, trace_request: TraceRequest) -> RpcResult<TraceResults>;

/// 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
Expand Down
1 change: 1 addition & 0 deletions crates/rpc/rpc-types/src/eth/trace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod common;
pub mod filter;
pub mod geth;
pub mod parity;
pub mod tracerequest;
82 changes: 82 additions & 0 deletions crates/rpc/rpc-types/src/eth/trace/tracerequest.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
37 changes: 37 additions & 0 deletions crates/rpc/rpc-types/src/eth/tracerequest.rs
Original file line number Diff line number Diff line change
@@ -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
}

}
44 changes: 11 additions & 33 deletions crates/rpc/rpc/src/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ use reth_revm::{
};
use reth_rpc_api::TraceApiServer;
use reth_rpc_types::{
state::StateOverride,
trace::{filter::TraceFilter, parity::*},
BlockError, BlockOverrides, CallRequest, Index,
trace::{filter::TraceFilter, parity::*, tracerequest::TraceRequest},
BlockError, CallRequest, Index,
};
use revm::{db::CacheDB, primitives::Env};
use revm_primitives::db::DatabaseCommit;
Expand Down Expand Up @@ -65,25 +64,19 @@ where
Eth: EthTransactions + 'static,
{
/// Executes the given call and returns a number of possible traces for it.
pub async fn trace_call(
&self,
call: CallRequest,
trace_types: HashSet<TraceType>,
block_id: Option<BlockId>,
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);
pub async fn trace_call(&self, trace_request: TraceRequest) -> EthResult<TraceResults> {
let at = trace_request.block_id.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
let config = tracing_config(&trace_request.trace_types);
let overrides =
EvmOverrides::new(trace_request.state_overrides, trace_request.block_overrides);
let mut inspector = TracingInspector::new(config);
self.inner
.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 trace_res = inspector.into_parity_builder().into_trace_results_with_state(
&res,
&trace_types,
&trace_request.trace_types,
&db,
)?;
Ok(trace_res)
Expand Down Expand Up @@ -439,24 +432,9 @@ where
/// Executes the given call and returns a number of possible traces for it.
///
/// Handler for `trace_call`
async fn trace_call(
&self,
call: CallRequest,
trace_types: HashSet<TraceType>,
block_id: Option<BlockId>,
state_overrides: Option<StateOverride>,
block_overrides: Option<Box<BlockOverrides>>,
) -> Result<TraceResults> {
async fn trace_call(&self, trace_request: TraceRequest) -> Result<TraceResults> {
let _permit = self.acquire_trace_permit().await;
Ok(TraceApi::trace_call(
self,
call,
trace_types,
block_id,
state_overrides,
block_overrides,
)
.await?)
Ok(TraceApi::trace_call(self, trace_request).await?)
}

/// Handler for `trace_callMany`
Expand Down
18 changes: 7 additions & 11 deletions examples/trace-transaction-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ use reth::{
Cli,
},
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,
transaction_pool::TransactionPool,
};
Expand Down Expand Up @@ -76,16 +79,9 @@ impl RethNodeCommandConfig for RethCliTxpoolExt {
// trace the transaction with `trace_call`
let callrequest =
transaction_to_call_request(tx.to_recovered_transaction());
if let Ok(trace_result) = traceapi
.trace_call(
callrequest,
HashSet::from([TraceType::Trace]),
None,
None,
None,
)
.await
{
let tracerequest =
TraceRequest::new(callrequest).with_trace_type(TraceType::Trace);
if let Ok(trace_result) = traceapi.trace_call(tracerequest).await {
println!(
"trace result for transaction : {:?} is {:?}",
tx.hash(),
Expand Down

0 comments on commit ae3914e

Please sign in to comment.