Skip to content

Commit

Permalink
fix: debug_traceCallMany and trace_callMany (alloy-rs#1278)
Browse files Browse the repository at this point in the history
* apply bug fixes and add tests

* use constants
  • Loading branch information
zerosnacks authored and lwedge99 committed Oct 8, 2024
1 parent dc2f46c commit 6dc46bc
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 46 deletions.
53 changes: 19 additions & 34 deletions crates/node-bindings/src/nodes/reth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,46 +566,37 @@ mod tests {

#[test]
#[cfg(not(windows))]
fn can_launch_reth_p2p_instance1() {
fn can_launch_reth_p2p_instances() {
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
let reth = Reth::new().instance(1).data_dir(temp_dir_path).spawn();
let reth = Reth::new().instance(100).data_dir(temp_dir_path).spawn();

assert_eq!(reth.http_port(), 8545);
assert_eq!(reth.ws_port(), 8546);
assert_eq!(reth.auth_port(), Some(8551));
assert_eq!(reth.p2p_port(), Some(30303));
});
}
assert_ports(&reth, false);

#[test]
#[cfg(not(windows))]
fn can_launch_reth_p2p_instance2() {
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
let reth = Reth::new().instance(2).data_dir(temp_dir_path).spawn();
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
let reth = Reth::new().instance(101).data_dir(temp_dir_path).spawn();

assert_eq!(reth.http_port(), 8544);
assert_eq!(reth.ws_port(), 8548);
assert_eq!(reth.auth_port(), Some(8651));
assert_eq!(reth.p2p_port(), Some(30304));
assert_ports(&reth, false);
});
});
}

// Tests that occupy the same port are combined so they are ran sequentially, to prevent
// flakiness.
#[test]
#[cfg(not(windows))]
fn can_launch_reth_default_ports() {
fn can_launch_reth_custom_ports() {
// Assert that all ports are default if no custom ports are set
// and the instance is set to 0.
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
let reth = Reth::new().instance(0).data_dir(temp_dir_path).spawn();

assert_eq!(reth.http_port(), 8545);
assert_eq!(reth.ws_port(), 8546);
assert_eq!(reth.auth_port(), Some(8551));
assert_eq!(reth.p2p_port(), Some(30303));
assert_eq!(reth.http_port(), DEFAULT_HTTP_PORT);
assert_eq!(reth.ws_port(), DEFAULT_WS_PORT);
assert_eq!(reth.auth_port(), Some(DEFAULT_AUTH_PORT));
assert_eq!(reth.p2p_port(), Some(DEFAULT_P2P_PORT));
});
}

#[test]
#[cfg(not(windows))]
fn can_launch_reth_custom_port() {
// Assert that only the HTTP port is set and the rest are default.
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
let reth = Reth::new().http_port(8577).data_dir(temp_dir_path).spawn();

Expand All @@ -614,11 +605,8 @@ mod tests {
assert_eq!(reth.auth_port(), Some(DEFAULT_AUTH_PORT));
assert_eq!(reth.p2p_port(), Some(DEFAULT_P2P_PORT));
});
}

#[test]
#[cfg(not(windows))]
fn can_launch_reth_custom_ports() {
// Assert that all ports can be set.
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
let reth = Reth::new()
.http_port(8577)
Expand All @@ -633,11 +621,8 @@ mod tests {
assert_eq!(reth.auth_port(), Some(8579));
assert_eq!(reth.p2p_port(), Some(30307));
});
}

#[test]
#[cfg(not(windows))]
fn can_launch_reth_random_port() {
// Assert that the HTTP port is picked by the OS and the rest are default.
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
let reth = Reth::new().http_port(0).data_dir(temp_dir_path).spawn();

Expand Down
66 changes: 59 additions & 7 deletions crates/provider/src/ext/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
use crate::Provider;
use alloy_network::Network;
use alloy_primitives::{hex, Bytes, TxHash, B256};
use alloy_rpc_types_eth::{Block, BlockId, BlockNumberOrTag, TransactionRequest};
use alloy_rpc_types_eth::{
Block, BlockId, BlockNumberOrTag, Bundle, StateContext, TransactionRequest,
};
use alloy_rpc_types_trace::geth::{
BlockTraceResult, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult,
};
Expand Down Expand Up @@ -122,8 +124,8 @@ pub trait DebugApi<N, T>: Send + Sync {
/// Not all nodes support this call.
async fn debug_trace_call_many(
&self,
txs: Vec<TransactionRequest>,
block: BlockId,
bundles: Vec<Bundle>,
state_context: StateContext,
trace_options: GethDebugTracingCallOptions,
) -> TransportResult<Vec<GethTrace>>;
}
Expand Down Expand Up @@ -208,11 +210,11 @@ where

async fn debug_trace_call_many(
&self,
txs: Vec<TransactionRequest>,
block: BlockId,
bundles: Vec<Bundle>,
state_context: StateContext,
trace_options: GethDebugTracingCallOptions,
) -> TransportResult<Vec<GethTrace>> {
self.client().request("debug_traceCallMany", (txs, block, trace_options)).await
self.client().request("debug_traceCallMany", (bundles, state_context, trace_options)).await
}
}

Expand All @@ -222,7 +224,7 @@ mod test {

use super::*;
use alloy_network::TransactionBuilder;
use alloy_node_bindings::{utils::run_with_tempdir, Geth};
use alloy_node_bindings::{utils::run_with_tempdir, Geth, Reth};
use alloy_primitives::{address, U256};

fn init_tracing() {
Expand Down Expand Up @@ -337,4 +339,54 @@ mod test {
})
.await
}

#[tokio::test]
#[cfg(not(windows))]
async fn debug_trace_call_many() {
run_with_tempdir("reth-test-", |temp_dir| async move {
let reth = Reth::new().dev().disable_discovery().data_dir(temp_dir).spawn();
let provider =
ProviderBuilder::new().with_recommended_fillers().on_http(reth.endpoint_url());

let tx1 = TransactionRequest::default()
.with_from(address!("0000000000000000000000000000000000000123"))
.with_to(address!("0000000000000000000000000000000000000456"));

let tx2 = TransactionRequest::default()
.with_from(address!("0000000000000000000000000000000000000456"))
.with_to(address!("0000000000000000000000000000000000000789"));

let bundles = vec![Bundle { transactions: vec![tx1, tx2], block_override: None }];
let state_context = StateContext::default();
let trace_options = GethDebugTracingCallOptions::default();
let result =
provider.debug_trace_call_many(bundles, state_context, trace_options).await;
assert!(result.is_ok());

let traces = result.unwrap();
assert_eq!(
serde_json::to_string_pretty(&traces).unwrap().trim(),
r#"
[
[
{
"failed": false,
"gas": 21000,
"returnValue": "",
"structLogs": []
},
{
"failed": false,
"gas": 21000,
"returnValue": "",
"structLogs": []
}
]
]
"#
.trim(),
);
})
.await
}
}
144 changes: 139 additions & 5 deletions crates/provider/src/ext/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use alloy_rpc_types_trace::{
use alloy_transport::{Transport, TransportResult};

/// List of trace calls for use with [`TraceApi::trace_call_many`]
pub type TraceCallList<'a, N> = &'a [(<N as Network>::TransactionRequest, Vec<TraceType>)];
pub type TraceCallList<'a, N> = &'a [(<N as Network>::TransactionRequest, &'a [TraceType])];

/// Trace namespace rpc interface that gives access to several non-standard RPC methods.
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
Expand Down Expand Up @@ -43,7 +43,7 @@ where
fn trace_call_many<'a>(
&self,
request: TraceCallList<'a, N>,
) -> RpcWithBlock<T, TraceCallList<'a, N>, TraceResults>;
) -> RpcWithBlock<T, (TraceCallList<'a, N>,), Vec<TraceResults>>;

/// Parity trace transaction.
async fn trace_transaction(
Expand Down Expand Up @@ -118,8 +118,8 @@ where
fn trace_call_many<'a>(
&self,
request: TraceCallList<'a, N>,
) -> RpcWithBlock<T, TraceCallList<'a, N>, TraceResults> {
RpcWithBlock::new(self.weak_client(), "trace_callMany", request)
) -> RpcWithBlock<T, (TraceCallList<'a, N>,), Vec<TraceResults>> {
RpcWithBlock::new(self.weak_client(), "trace_callMany", (request,))
}

async fn trace_transaction(
Expand Down Expand Up @@ -178,6 +178,10 @@ where
mod test {
use crate::ProviderBuilder;
use alloy_eips::BlockNumberOrTag;
use alloy_network::TransactionBuilder;
use alloy_node_bindings::{utils::run_with_tempdir, Reth};
use alloy_primitives::address;
use alloy_rpc_types_eth::TransactionRequest;

use super::*;

Expand All @@ -186,10 +190,140 @@ mod test {
}

#[tokio::test]
async fn test_trace_block() {
async fn trace_block() {
init_tracing();
let provider = ProviderBuilder::new().on_anvil();
let traces = provider.trace_block(BlockId::Number(BlockNumberOrTag::Latest)).await.unwrap();
assert_eq!(traces.len(), 0);
}

#[tokio::test]
#[cfg(not(windows))]
async fn trace_call() {
run_with_tempdir("reth-test-", |temp_dir| async move {
let reth = Reth::new().dev().disable_discovery().data_dir(temp_dir).spawn();
let provider = ProviderBuilder::new().on_http(reth.endpoint_url());

let tx = TransactionRequest::default()
.with_from(address!("0000000000000000000000000000000000000123"))
.with_to(address!("0000000000000000000000000000000000000456"));

let result = provider.trace_call(&tx, &[TraceType::Trace]).await;
assert!(result.is_ok());

let traces = result.unwrap();
assert_eq!(
serde_json::to_string_pretty(&traces).unwrap().trim(),
r#"
{
"output": "0x",
"stateDiff": null,
"trace": [
{
"type": "call",
"action": {
"from": "0x0000000000000000000000000000000000000123",
"callType": "call",
"gas": "0x2fa9e78",
"input": "0x",
"to": "0x0000000000000000000000000000000000000456",
"value": "0x0"
},
"result": {
"gasUsed": "0x0",
"output": "0x"
},
"subtraces": 0,
"traceAddress": []
}
],
"vmTrace": null
}
"#
.trim(),
);
})
.await;
}

#[tokio::test]
#[cfg(not(windows))]
async fn trace_call_many() {
run_with_tempdir("reth-test-", |temp_dir| async move {
let reth = Reth::new().dev().disable_discovery().data_dir(temp_dir).spawn();
let provider = ProviderBuilder::new().on_http(reth.endpoint_url());

let tx1 = TransactionRequest::default()
.with_from(address!("0000000000000000000000000000000000000123"))
.with_to(address!("0000000000000000000000000000000000000456"));

let tx2 = TransactionRequest::default()
.with_from(address!("0000000000000000000000000000000000000456"))
.with_to(address!("0000000000000000000000000000000000000789"));

let result = provider
.trace_call_many(&[(tx1, &[TraceType::Trace]), (tx2, &[TraceType::Trace])])
.await;
assert!(result.is_ok());

let traces = result.unwrap();
assert_eq!(
serde_json::to_string_pretty(&traces).unwrap().trim(),
r#"
[
{
"output": "0x",
"stateDiff": null,
"trace": [
{
"type": "call",
"action": {
"from": "0x0000000000000000000000000000000000000123",
"callType": "call",
"gas": "0x2fa9e78",
"input": "0x",
"to": "0x0000000000000000000000000000000000000456",
"value": "0x0"
},
"result": {
"gasUsed": "0x0",
"output": "0x"
},
"subtraces": 0,
"traceAddress": []
}
],
"vmTrace": null
},
{
"output": "0x",
"stateDiff": null,
"trace": [
{
"type": "call",
"action": {
"from": "0x0000000000000000000000000000000000000456",
"callType": "call",
"gas": "0x2fa9e78",
"input": "0x",
"to": "0x0000000000000000000000000000000000000789",
"value": "0x0"
},
"result": {
"gasUsed": "0x0",
"output": "0x"
},
"subtraces": 0,
"traceAddress": []
}
],
"vmTrace": null
}
]
"#
.trim()
);
})
.await;
}
}
1 change: 1 addition & 0 deletions crates/rpc-types-eth/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct Bundle {
/// All transactions to execute
pub transactions: Vec<TransactionRequest>,
/// Block overrides to apply
#[serde(default, skip_serializing_if = "Option::is_none")]
pub block_override: Option<BlockOverrides>,
}

Expand Down

0 comments on commit 6dc46bc

Please sign in to comment.