Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a TraceRpc helper type #1086

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/provider/src/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub use net::NetApi;
#[cfg(feature = "trace-api")]
mod trace;
#[cfg(feature = "trace-api")]
pub use trace::{TraceApi, TraceCallList};
pub use trace::{TraceApi, TraceCallList, TraceRpcWithBlock};

#[cfg(feature = "rpc-api")]
mod rpc;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! This module extends the Ethereum JSON-RPC provider with the Trace namespace's RPC methods.
use crate::{Provider, RpcWithBlock};
use super::TraceRpcWithBlock;
use crate::Provider;
use alloy_eips::BlockNumberOrTag;
use alloy_network::Network;
use alloy_primitives::TxHash;
Expand All @@ -26,11 +27,10 @@ where
/// # Note
///
/// Not all nodes support this call.
fn trace_call<'a, 'b>(
fn trace_call(
&self,
request: &'a N::TransactionRequest,
trace_type: &'b [TraceType],
) -> RpcWithBlock<T, (&'a N::TransactionRequest, &'b [TraceType]), TraceResults>;
request: N::TransactionRequest,
) -> TraceRpcWithBlock<T, N::TransactionRequest, TraceResults>;

/// Traces multiple transactions on top of the same block, i.e. transaction `n` will be executed
/// on top of the given block with all `n - 1` transaction applied first.
Expand All @@ -40,10 +40,10 @@ where
/// # Note
///
/// Not all nodes support this call.
fn trace_call_many<'a>(
fn trace_call_many(
&self,
request: TraceCallList<'a, N>,
) -> RpcWithBlock<T, TraceCallList<'a, N>, TraceResults>;
requests: Vec<N::TransactionRequest>,
) -> TraceRpcWithBlock<T, Vec<N::TransactionRequest>, Vec<TraceResults>>;

/// Parity trace transaction.
async fn trace_transaction(
Expand All @@ -64,16 +64,12 @@ where
) -> TransportResult<LocalizedTransactionTrace>;

/// Trace the given raw transaction.
async fn trace_raw_transaction(
&self,
data: &[u8],
trace_type: &[TraceType],
) -> TransportResult<TraceResults>;
fn trace_raw_transaction(&self, data: Vec<u8>) -> TraceRpcWithBlock<T, Vec<u8>, TraceResults>;

/// Traces matching given filter.
async fn trace_filter(
&self,
tracer: &TraceFilter,
filter: TraceFilter,
) -> TransportResult<Vec<LocalizedTransactionTrace>>;

/// Trace all transactions in the given block.
Expand All @@ -87,18 +83,13 @@ where
) -> TransportResult<Vec<LocalizedTransactionTrace>>;

/// Replays a transaction.
async fn trace_replay_transaction(
&self,
hash: TxHash,
trace_type: &[TraceType],
) -> TransportResult<TraceResults>;
fn trace_replay_transaction(&self, hash: TxHash) -> TraceRpcWithBlock<T, TxHash, TraceResults>;

/// Replays all transactions in the given block.
async fn trace_replay_block_transactions(
fn trace_replay_block_transactions(
&self,
block: BlockNumberOrTag,
trace_type: &[TraceType],
) -> TransportResult<Vec<TraceResultsWithTransactionHash>>;
) -> TraceRpcWithBlock<T, BlockNumberOrTag, Vec<TraceResultsWithTransactionHash>>;
}

#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
Expand All @@ -109,20 +100,18 @@ where
T: Transport + Clone,
P: Provider<T, N>,
{
fn trace_call<'a, 'b>(
fn trace_call(
&self,
request: &'a <N as Network>::TransactionRequest,
trace_type: &'b [TraceType],
) -> RpcWithBlock<T, (&'a <N as Network>::TransactionRequest, &'b [TraceType]), TraceResults>
{
RpcWithBlock::new(self.weak_client(), "trace_call", (request, trace_type))
request: N::TransactionRequest,
) -> TraceRpcWithBlock<T, N::TransactionRequest, TraceResults> {
TraceRpcWithBlock::new(self.weak_client(), "trace_call", request)
}

fn trace_call_many<'a>(
fn trace_call_many(
&self,
request: TraceCallList<'a, N>,
) -> RpcWithBlock<T, TraceCallList<'a, N>, TraceResults> {
RpcWithBlock::new(self.weak_client(), "trace_callMany", request)
requests: Vec<N::TransactionRequest>,
) -> TraceRpcWithBlock<T, Vec<N::TransactionRequest>, Vec<TraceResults>> {
TraceRpcWithBlock::new(self.weak_client(), "trace_callMany", requests)
}

async fn trace_transaction(
Expand All @@ -141,19 +130,15 @@ where
self.client().request("trace_get", (hash, (Index::from(index),))).await
}

async fn trace_raw_transaction(
&self,
data: &[u8],
trace_type: &[TraceType],
) -> TransportResult<TraceResults> {
self.client().request("trace_rawTransaction", (data, trace_type)).await
fn trace_raw_transaction(&self, data: Vec<u8>) -> TraceRpcWithBlock<T, Vec<u8>, TraceResults> {
TraceRpcWithBlock::new(self.weak_client(), "trace_rawTransaction", data)
}

async fn trace_filter(
&self,
tracer: &TraceFilter,
filter: TraceFilter,
) -> TransportResult<Vec<LocalizedTransactionTrace>> {
self.client().request("trace_filter", (tracer,)).await
self.client().request("trace_filter", (filter,)).await
}

async fn trace_block(
Expand All @@ -163,20 +148,15 @@ where
self.client().request("trace_block", (block,)).await
}

async fn trace_replay_transaction(
&self,
hash: TxHash,
trace_type: &[TraceType],
) -> TransportResult<TraceResults> {
self.client().request("trace_replayTransaction", (hash, trace_type)).await
fn trace_replay_transaction(&self, hash: TxHash) -> TraceRpcWithBlock<T, TxHash, TraceResults> {
TraceRpcWithBlock::new(self.weak_client(), "trace_replayTransaction", hash)
}

async fn trace_replay_block_transactions(
fn trace_replay_block_transactions(
&self,
block: BlockNumberOrTag,
trace_type: &[TraceType],
) -> TransportResult<Vec<TraceResultsWithTransactionHash>> {
self.client().request("trace_replayBlockTransactions", (block, trace_type)).await
) -> TraceRpcWithBlock<T, BlockNumberOrTag, Vec<TraceResultsWithTransactionHash>> {
TraceRpcWithBlock::new(self.weak_client(), "trace_replayBlockTransactions", block)
}
}

Expand Down
5 changes: 5 additions & 0 deletions crates/provider/src/ext/trace/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod api;
mod with_block;

pub use api::*;
pub use with_block::*;
110 changes: 110 additions & 0 deletions crates/provider/src/ext/trace/with_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use crate::{RpcWithBlock, RpcWithBlockFut};
use alloy_json_rpc::{RpcParam, RpcReturn};
use alloy_rpc_client::WeakClient;
use alloy_rpc_types_trace::parity::TraceType;
use alloy_transport::{Transport, TransportResult};
use std::{borrow::Cow, collections::HashSet, future::IntoFuture, ops::Deref};

/// An wrapper for [`TraceRpcWithBlock`] that takes an optional [`TraceType`] parameter. By default
/// this will use "trace".
#[derive(Debug, Clone)]
pub struct TraceRpcWithBlock<T, Params, Resp, Output = Resp, Map = fn(Resp) -> Output>
where
T: Transport + Clone,
Params: RpcParam,
Resp: RpcReturn,
Map: Fn(Resp) -> Output,
{
inner: RpcWithBlock<T, Params, Resp, Output, Map>,
trace_types: HashSet<TraceType>,
}

impl<T, Params, Resp, Output, Map> Deref for TraceRpcWithBlock<T, Params, Resp, Output, Map>
where
T: Transport + Clone,
Params: RpcParam,
Resp: RpcReturn,
Map: Fn(Resp) -> Output,
{
type Target = RpcWithBlock<T, Params, Resp, Output, Map>;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

impl<T, Params, Resp> TraceRpcWithBlock<T, Params, Resp>
where
T: Transport + Clone,
Params: RpcParam,
Resp: RpcReturn,
{
/// Create a new [`TraceRpcWithBlock`] instance.
pub fn new(
client: WeakClient<T>,
method: impl Into<Cow<'static, str>>,
params: Params,
) -> Self {
Self {
inner: RpcWithBlock::new(client, method, params),
trace_types: vec![TraceType::Trace].into_iter().collect(),
}
}
}

impl<T, Params, Resp, Output, Map> TraceRpcWithBlock<T, Params, Resp, Output, Map>
where
T: Transport + Clone,
Params: RpcParam,
Resp: RpcReturn,
Map: Fn(Resp) -> Output + 'static,
{
/// Set the trace type.
pub fn trace_type(mut self, trace_type: TraceType) -> Self {
self.trace_types.insert(trace_type);
self
}

/// Set the trace types.
pub fn trace_types<I: IntoIterator<Item = TraceType>>(mut self, trace_types: I) -> Self {
self.trace_types.extend(trace_types);
self
}

/// Set the trace type to "trace".
pub fn trace(self) -> Self {
self.trace_type(TraceType::Trace)
}

/// Set the trace type to "vmTrace".
pub fn vm_trace(self) -> Self {
self.trace_type(TraceType::VmTrace)
}

/// Set the trace type to "stateDiff".
pub fn state_diff(self) -> Self {
self.trace_type(TraceType::StateDiff)
}

/// Get the trace types.
pub const fn get_trace_types(&self) -> &HashSet<TraceType> {
&self.trace_types
}
}

impl<T, Params, Resp, Output, Map> IntoFuture for TraceRpcWithBlock<T, Params, Resp, Output, Map>
where
T: Transport + Clone,
Params: RpcParam,
Resp: RpcReturn,
Output: 'static,
Map: Fn(Resp) -> Output + 'static + Copy,
{
type Output = TransportResult<Output>;
type IntoFuture = RpcWithBlockFut<T, Params, Resp, Output, Map>;

fn into_future(self) -> Self::IntoFuture {
let inner: RpcWithBlock<T, Params, Resp, Output, Map> = self.into();
inner.into_future()
}
}
4 changes: 2 additions & 2 deletions crates/provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ pub use heart::{PendingTransaction, PendingTransactionBuilder, PendingTransactio

mod provider;
pub use provider::{
builder, EthCall, FilterPollerBuilder, Provider, RootProvider, RpcWithBlock, SendableTx,
WalletProvider,
builder, EthCall, FilterPollerBuilder, Provider, RootProvider, RpcWithBlock, RpcWithBlockFut,
SendableTx, WalletProvider,
};

pub mod utils;
Expand Down
2 changes: 1 addition & 1 deletion crates/provider/src/provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ mod wallet;
pub use wallet::WalletProvider;

mod with_block;
pub use with_block::RpcWithBlock;
pub use with_block::{RpcWithBlock, RpcWithBlockFut};
Loading