Skip to content

Commit f50313a

Browse files
authored
fix: debug_traceCallMany and trace_callMany (#1278)
* apply bug fixes and add tests * use constants
1 parent 3d8c680 commit f50313a

File tree

4 files changed

+218
-46
lines changed

4 files changed

+218
-46
lines changed

Diff for: crates/node-bindings/src/nodes/reth.rs

+19-34
Original file line numberDiff line numberDiff line change
@@ -566,46 +566,37 @@ mod tests {
566566

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

573-
assert_eq!(reth.http_port(), 8545);
574-
assert_eq!(reth.ws_port(), 8546);
575-
assert_eq!(reth.auth_port(), Some(8551));
576-
assert_eq!(reth.p2p_port(), Some(30303));
577-
});
578-
}
573+
assert_ports(&reth, false);
579574

580-
#[test]
581-
#[cfg(not(windows))]
582-
fn can_launch_reth_p2p_instance2() {
583-
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
584-
let reth = Reth::new().instance(2).data_dir(temp_dir_path).spawn();
575+
run_with_tempdir_sync("reth-test-", |temp_dir_path| {
576+
let reth = Reth::new().instance(101).data_dir(temp_dir_path).spawn();
585577

586-
assert_eq!(reth.http_port(), 8544);
587-
assert_eq!(reth.ws_port(), 8548);
588-
assert_eq!(reth.auth_port(), Some(8651));
589-
assert_eq!(reth.p2p_port(), Some(30304));
578+
assert_ports(&reth, false);
579+
});
590580
});
591581
}
592582

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

599-
assert_eq!(reth.http_port(), 8545);
600-
assert_eq!(reth.ws_port(), 8546);
601-
assert_eq!(reth.auth_port(), Some(8551));
602-
assert_eq!(reth.p2p_port(), Some(30303));
593+
assert_eq!(reth.http_port(), DEFAULT_HTTP_PORT);
594+
assert_eq!(reth.ws_port(), DEFAULT_WS_PORT);
595+
assert_eq!(reth.auth_port(), Some(DEFAULT_AUTH_PORT));
596+
assert_eq!(reth.p2p_port(), Some(DEFAULT_P2P_PORT));
603597
});
604-
}
605598

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

@@ -614,11 +605,8 @@ mod tests {
614605
assert_eq!(reth.auth_port(), Some(DEFAULT_AUTH_PORT));
615606
assert_eq!(reth.p2p_port(), Some(DEFAULT_P2P_PORT));
616607
});
617-
}
618608

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

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

Diff for: crates/provider/src/ext/debug.rs

+59-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
use crate::Provider;
33
use alloy_network::Network;
44
use alloy_primitives::{hex, Bytes, TxHash, B256};
5-
use alloy_rpc_types_eth::{Block, BlockId, BlockNumberOrTag, TransactionRequest};
5+
use alloy_rpc_types_eth::{
6+
Block, BlockId, BlockNumberOrTag, Bundle, StateContext, TransactionRequest,
7+
};
68
use alloy_rpc_types_trace::geth::{
79
BlockTraceResult, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult,
810
};
@@ -122,8 +124,8 @@ pub trait DebugApi<N, T>: Send + Sync {
122124
/// Not all nodes support this call.
123125
async fn debug_trace_call_many(
124126
&self,
125-
txs: Vec<TransactionRequest>,
126-
block: BlockId,
127+
bundles: Vec<Bundle>,
128+
state_context: StateContext,
127129
trace_options: GethDebugTracingCallOptions,
128130
) -> TransportResult<Vec<GethTrace>>;
129131
}
@@ -208,11 +210,11 @@ where
208210

209211
async fn debug_trace_call_many(
210212
&self,
211-
txs: Vec<TransactionRequest>,
212-
block: BlockId,
213+
bundles: Vec<Bundle>,
214+
state_context: StateContext,
213215
trace_options: GethDebugTracingCallOptions,
214216
) -> TransportResult<Vec<GethTrace>> {
215-
self.client().request("debug_traceCallMany", (txs, block, trace_options)).await
217+
self.client().request("debug_traceCallMany", (bundles, state_context, trace_options)).await
216218
}
217219
}
218220

@@ -222,7 +224,7 @@ mod test {
222224

223225
use super::*;
224226
use alloy_network::TransactionBuilder;
225-
use alloy_node_bindings::{utils::run_with_tempdir, Geth};
227+
use alloy_node_bindings::{utils::run_with_tempdir, Geth, Reth};
226228
use alloy_primitives::{address, U256};
227229

228230
fn init_tracing() {
@@ -337,4 +339,54 @@ mod test {
337339
})
338340
.await
339341
}
342+
343+
#[tokio::test]
344+
#[cfg(not(windows))]
345+
async fn debug_trace_call_many() {
346+
run_with_tempdir("reth-test-", |temp_dir| async move {
347+
let reth = Reth::new().dev().disable_discovery().data_dir(temp_dir).spawn();
348+
let provider =
349+
ProviderBuilder::new().with_recommended_fillers().on_http(reth.endpoint_url());
350+
351+
let tx1 = TransactionRequest::default()
352+
.with_from(address!("0000000000000000000000000000000000000123"))
353+
.with_to(address!("0000000000000000000000000000000000000456"));
354+
355+
let tx2 = TransactionRequest::default()
356+
.with_from(address!("0000000000000000000000000000000000000456"))
357+
.with_to(address!("0000000000000000000000000000000000000789"));
358+
359+
let bundles = vec![Bundle { transactions: vec![tx1, tx2], block_override: None }];
360+
let state_context = StateContext::default();
361+
let trace_options = GethDebugTracingCallOptions::default();
362+
let result =
363+
provider.debug_trace_call_many(bundles, state_context, trace_options).await;
364+
assert!(result.is_ok());
365+
366+
let traces = result.unwrap();
367+
assert_eq!(
368+
serde_json::to_string_pretty(&traces).unwrap().trim(),
369+
r#"
370+
[
371+
[
372+
{
373+
"failed": false,
374+
"gas": 21000,
375+
"returnValue": "",
376+
"structLogs": []
377+
},
378+
{
379+
"failed": false,
380+
"gas": 21000,
381+
"returnValue": "",
382+
"structLogs": []
383+
}
384+
]
385+
]
386+
"#
387+
.trim(),
388+
);
389+
})
390+
.await
391+
}
340392
}

Diff for: crates/provider/src/ext/trace.rs

+139-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use alloy_rpc_types_trace::{
1111
use alloy_transport::{Transport, TransportResult};
1212

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

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

4848
/// Parity trace transaction.
4949
async fn trace_transaction(
@@ -118,8 +118,8 @@ where
118118
fn trace_call_many<'a>(
119119
&self,
120120
request: TraceCallList<'a, N>,
121-
) -> RpcWithBlock<T, TraceCallList<'a, N>, TraceResults> {
122-
RpcWithBlock::new(self.weak_client(), "trace_callMany", request)
121+
) -> RpcWithBlock<T, (TraceCallList<'a, N>,), Vec<TraceResults>> {
122+
RpcWithBlock::new(self.weak_client(), "trace_callMany", (request,))
123123
}
124124

125125
async fn trace_transaction(
@@ -178,6 +178,10 @@ where
178178
mod test {
179179
use crate::ProviderBuilder;
180180
use alloy_eips::BlockNumberOrTag;
181+
use alloy_network::TransactionBuilder;
182+
use alloy_node_bindings::{utils::run_with_tempdir, Reth};
183+
use alloy_primitives::address;
184+
use alloy_rpc_types_eth::TransactionRequest;
181185

182186
use super::*;
183187

@@ -186,10 +190,140 @@ mod test {
186190
}
187191

188192
#[tokio::test]
189-
async fn test_trace_block() {
193+
async fn trace_block() {
190194
init_tracing();
191195
let provider = ProviderBuilder::new().on_anvil();
192196
let traces = provider.trace_block(BlockId::Number(BlockNumberOrTag::Latest)).await.unwrap();
193197
assert_eq!(traces.len(), 0);
194198
}
199+
200+
#[tokio::test]
201+
#[cfg(not(windows))]
202+
async fn trace_call() {
203+
run_with_tempdir("reth-test-", |temp_dir| async move {
204+
let reth = Reth::new().dev().disable_discovery().data_dir(temp_dir).spawn();
205+
let provider = ProviderBuilder::new().on_http(reth.endpoint_url());
206+
207+
let tx = TransactionRequest::default()
208+
.with_from(address!("0000000000000000000000000000000000000123"))
209+
.with_to(address!("0000000000000000000000000000000000000456"));
210+
211+
let result = provider.trace_call(&tx, &[TraceType::Trace]).await;
212+
assert!(result.is_ok());
213+
214+
let traces = result.unwrap();
215+
assert_eq!(
216+
serde_json::to_string_pretty(&traces).unwrap().trim(),
217+
r#"
218+
{
219+
"output": "0x",
220+
"stateDiff": null,
221+
"trace": [
222+
{
223+
"type": "call",
224+
"action": {
225+
"from": "0x0000000000000000000000000000000000000123",
226+
"callType": "call",
227+
"gas": "0x2fa9e78",
228+
"input": "0x",
229+
"to": "0x0000000000000000000000000000000000000456",
230+
"value": "0x0"
231+
},
232+
"result": {
233+
"gasUsed": "0x0",
234+
"output": "0x"
235+
},
236+
"subtraces": 0,
237+
"traceAddress": []
238+
}
239+
],
240+
"vmTrace": null
241+
}
242+
"#
243+
.trim(),
244+
);
245+
})
246+
.await;
247+
}
248+
249+
#[tokio::test]
250+
#[cfg(not(windows))]
251+
async fn trace_call_many() {
252+
run_with_tempdir("reth-test-", |temp_dir| async move {
253+
let reth = Reth::new().dev().disable_discovery().data_dir(temp_dir).spawn();
254+
let provider = ProviderBuilder::new().on_http(reth.endpoint_url());
255+
256+
let tx1 = TransactionRequest::default()
257+
.with_from(address!("0000000000000000000000000000000000000123"))
258+
.with_to(address!("0000000000000000000000000000000000000456"));
259+
260+
let tx2 = TransactionRequest::default()
261+
.with_from(address!("0000000000000000000000000000000000000456"))
262+
.with_to(address!("0000000000000000000000000000000000000789"));
263+
264+
let result = provider
265+
.trace_call_many(&[(tx1, &[TraceType::Trace]), (tx2, &[TraceType::Trace])])
266+
.await;
267+
assert!(result.is_ok());
268+
269+
let traces = result.unwrap();
270+
assert_eq!(
271+
serde_json::to_string_pretty(&traces).unwrap().trim(),
272+
r#"
273+
[
274+
{
275+
"output": "0x",
276+
"stateDiff": null,
277+
"trace": [
278+
{
279+
"type": "call",
280+
"action": {
281+
"from": "0x0000000000000000000000000000000000000123",
282+
"callType": "call",
283+
"gas": "0x2fa9e78",
284+
"input": "0x",
285+
"to": "0x0000000000000000000000000000000000000456",
286+
"value": "0x0"
287+
},
288+
"result": {
289+
"gasUsed": "0x0",
290+
"output": "0x"
291+
},
292+
"subtraces": 0,
293+
"traceAddress": []
294+
}
295+
],
296+
"vmTrace": null
297+
},
298+
{
299+
"output": "0x",
300+
"stateDiff": null,
301+
"trace": [
302+
{
303+
"type": "call",
304+
"action": {
305+
"from": "0x0000000000000000000000000000000000000456",
306+
"callType": "call",
307+
"gas": "0x2fa9e78",
308+
"input": "0x",
309+
"to": "0x0000000000000000000000000000000000000789",
310+
"value": "0x0"
311+
},
312+
"result": {
313+
"gasUsed": "0x0",
314+
"output": "0x"
315+
},
316+
"subtraces": 0,
317+
"traceAddress": []
318+
}
319+
],
320+
"vmTrace": null
321+
}
322+
]
323+
"#
324+
.trim()
325+
);
326+
})
327+
.await;
328+
}
195329
}

Diff for: crates/rpc-types-eth/src/call.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub struct Bundle {
1515
/// All transactions to execute
1616
pub transactions: Vec<TransactionRequest>,
1717
/// Block overrides to apply
18+
#[serde(default, skip_serializing_if = "Option::is_none")]
1819
pub block_override: Option<BlockOverrides>,
1920
}
2021

0 commit comments

Comments
 (0)