Skip to content

Commit 86ca0f1

Browse files
insipxtomusdrw
authored andcommitted
Add traces namespace (#148)
* Add `traces` namespace basic code for traces namespace and types tests for traces and trace_filtering types builder for Trace Filter tests for `traces` namespace and traces types (traces + trace_filtering) move ValueOrArray back * Add `traces` namespace basic code for traces namespace and types tests for traces and trace_filtering types builder for Trace Filter tests for `traces` namespace and traces types (traces + trace_filtering) * fix return type of `trace_get` * Fix types for Addresses Some addresses were usize, some were H160. This changes all addresses in `traces` to be `Address` * make blockNumber and blockHash optional in TransactionReceipt (#164) * Derive Eq and Hash for Bytes (tomusdrw#168) This just forwards to the implementation of Vec. * Fix build with OpenSSL 1.1.1 (tomusdrw#170) * Fix build with OpenSSL 1.1.1 Update hyper to 0.12 Update hyper-tls to 0.3 update websocket to 0.21 Update http.rs to new hyper 0.12 API bump version * fix comment placement * Revise `Traces` namespace remove custom deserialize, switch to untagged serde representation
1 parent 4d6c6d7 commit 86ca0f1

File tree

6 files changed

+2906
-0
lines changed

6 files changed

+2906
-0
lines changed

src/api/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod eth_filter;
55
mod eth_subscribe;
66
mod net;
77
mod personal;
8+
mod traces;
89
mod web3;
910

1011
pub use self::eth::Eth;
@@ -13,6 +14,7 @@ pub use self::eth_subscribe::{SubscriptionId, SubscriptionStream};
1314
pub use self::net::Net;
1415
pub use self::personal::Personal;
1516
pub use self::web3::Web3 as Web3Api;
17+
pub use self::traces::Traces;
1618

1719
use std::time::Duration;
1820
use futures::IntoFuture;
@@ -75,6 +77,11 @@ impl<T: Transport> Web3<T> {
7577
self.api()
7678
}
7779

80+
/// Access methods from `trace` namespace
81+
pub fn trace(&self) -> traces::Traces<T> {
82+
self.api()
83+
}
84+
7885
/// Should be used to wait for confirmations
7986
pub fn wait_for_confirmations<F, V>(&self, poll_interval: Duration, confirmations: usize, check: V) -> confirm::Confirmations<T, V, F::Future>
8087
where

src/api/traces.rs

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
use api::Namespace;
2+
use helpers::{self, CallFuture};
3+
use types::{TraceType, BlockTrace, Trace, TraceFilter, CallRequest, BlockNumber, Bytes, H256, Index};
4+
use Transport;
5+
6+
/// `Trace` namespace
7+
#[derive(Debug, Clone)]
8+
pub struct Traces<T> {
9+
transport: T,
10+
}
11+
12+
impl<T: Transport> Namespace<T> for Traces<T> {
13+
fn new(transport: T) -> Self
14+
where
15+
Self: Sized,
16+
{
17+
Traces { transport }
18+
}
19+
20+
fn transport(&self) -> &T {
21+
&self.transport
22+
}
23+
}
24+
impl<T: Transport> Traces<T> {
25+
/// Executes the given call and returns a number of possible traces for it
26+
pub fn call(&self, req: CallRequest, trace_type: Vec<TraceType>, block: Option<BlockNumber>) -> CallFuture<BlockTrace, T::Out> {
27+
let req = helpers::serialize(&req);
28+
let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest));
29+
let trace_type = helpers::serialize(&trace_type);
30+
CallFuture::new(self.transport.execute("trace_call", vec![req, trace_type, block]))
31+
}
32+
33+
/// Traces a call to `eth_sendRawTransaction` without making the call, returning the traces
34+
pub fn raw_transaction(&self, data: Bytes, trace_type: Vec<TraceType>) -> CallFuture<BlockTrace, T::Out> {
35+
let data = helpers::serialize(&data);
36+
let trace_type = helpers::serialize(&trace_type);
37+
CallFuture::new(self.transport.execute("trace_rawTransaction", vec![data, trace_type]))
38+
}
39+
40+
/// Replays a transaction, returning the traces
41+
pub fn replay_transaction(&self, hash: H256, trace_type: Vec<TraceType>) -> CallFuture<BlockTrace, T::Out> {
42+
let hash = helpers::serialize(&hash);
43+
let trace_type = helpers::serialize(&trace_type);
44+
CallFuture::new(self.transport.execute("trace_replayTransaction", vec![hash, trace_type]))
45+
}
46+
47+
/// Replays all transactions in a block returning the requested traces for each transaction
48+
pub fn replay_block_transactions(&self, block: BlockNumber, trace_type: Vec<TraceType>) -> CallFuture<BlockTrace, T::Out> {
49+
let block = helpers::serialize(&block);
50+
let trace_type = helpers::serialize(&trace_type);
51+
CallFuture::new(self.transport.execute("trace_replayBlockTransaction", vec![block, trace_type]))
52+
}
53+
54+
/// Returns traces created at given block
55+
pub fn block(&self, block: BlockNumber) -> CallFuture<Vec<Trace>, T::Out> {
56+
let block = helpers::serialize(&block);
57+
CallFuture::new(self.transport.execute("trace_block", vec![block]))
58+
}
59+
60+
/// Return traces matching the given filter
61+
///
62+
/// See [TraceFilterBuilder](../types/struct.TraceFilterBuilder.html)
63+
pub fn filter(&self, filter: TraceFilter) -> CallFuture<Vec<Trace>, T::Out> {
64+
let filter = helpers::serialize(&filter);
65+
CallFuture::new(self.transport.execute("trace_filter", vec![filter]))
66+
}
67+
68+
/// Returns trace at the given position
69+
pub fn get(&self, hash: H256, index: Vec<Index>) -> CallFuture<Trace, T::Out> {
70+
let hash = helpers::serialize(&hash);
71+
let index = helpers::serialize(&index);
72+
CallFuture::new(self.transport.execute("trace_get", vec![hash, index]))
73+
}
74+
75+
/// Returns all traces of a given transaction
76+
pub fn transaction(&self, hash: H256) -> CallFuture<Vec<Trace>, T::Out> {
77+
let hash = helpers::serialize(&hash);
78+
CallFuture::new(self.transport.execute("trace_transaction", vec![hash]))
79+
}
80+
}
81+
82+
#[cfg(test)]
83+
mod tests {
84+
use futures::Future;
85+
86+
use api::Namespace;
87+
use types::{TraceType, BlockNumber, BlockTrace, Trace, TraceFilterBuilder, Bytes, CallRequest, H256};
88+
89+
use super::Traces;
90+
91+
const EXAMPLE_BLOCKTRACE: &'static str = r#"
92+
{
93+
"output": "0x010203",
94+
"stateDiff": null,
95+
"trace": [
96+
{
97+
"action": {
98+
"callType": "call",
99+
"from": "0x0000000000000000000000000000000000000000",
100+
"gas": "0x1dcd12f8",
101+
"input": "0x",
102+
"to": "0x0000000000000000000000000000000000000123",
103+
"value": "0x1"
104+
},
105+
"result": {
106+
"gasUsed": "0x0",
107+
"output": "0x"
108+
},
109+
"subtraces": 0,
110+
"traceAddress": [],
111+
"type": "call"
112+
}
113+
],
114+
"vmTrace": null
115+
}
116+
"#;
117+
118+
const EXAMPLE_TRACE_ARR: &'static str = r#"
119+
[
120+
{
121+
"action": {
122+
"callType": "call",
123+
"from": "0xaa7b131dc60b80d3cf5e59b5a21a666aa039c951",
124+
"gas": "0x0",
125+
"input": "0x",
126+
"to": "0xd40aba8166a212d6892125f079c33e6f5ca19814",
127+
"value": "0x4768d7effc3fbe"
128+
},
129+
"blockHash": "0x7eb25504e4c202cf3d62fd585d3e238f592c780cca82dacb2ed3cb5b38883add",
130+
"blockNumber": 3068185,
131+
"result": {
132+
"gasUsed": "0x0",
133+
"output": "0x"
134+
},
135+
"subtraces": 0,
136+
"traceAddress": [],
137+
"transactionHash": "0x07da28d752aba3b9dd7060005e554719c6205c8a3aea358599fc9b245c52f1f6",
138+
"transactionPosition": 0,
139+
"type": "call"
140+
}
141+
]
142+
"#;
143+
144+
const EXAMPLE_TRACE: &'static str = r#"
145+
{
146+
"action": {
147+
"callType": "call",
148+
"from": "0xaa7b131dc60b80d3cf5e59b5a21a666aa039c951",
149+
"gas": "0x0",
150+
"input": "0x",
151+
"to": "0xd40aba8166a212d6892125f079c33e6f5ca19814",
152+
"value": "0x4768d7effc3fbe"
153+
},
154+
"blockHash": "0x7eb25504e4c202cf3d62fd585d3e238f592c780cca82dacb2ed3cb5b38883add",
155+
"blockNumber": 3068185,
156+
"result": {
157+
"gasUsed": "0x0",
158+
"output": "0x"
159+
},
160+
"subtraces": 0,
161+
"traceAddress": [],
162+
"transactionHash": "0x07da28d752aba3b9dd7060005e554719c6205c8a3aea358599fc9b245c52f1f6",
163+
"transactionPosition": 0,
164+
"type": "call"
165+
}
166+
"#;
167+
168+
rpc_test! (
169+
Traces:call, CallRequest {
170+
from: None, to: 0x123.into(),
171+
gas: None, gas_price: None,
172+
value: Some(0x1.into()), data: None,
173+
}, vec![TraceType::Trace], None
174+
=>
175+
"trace_call", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#"["trace"]"#, r#""latest""#];
176+
::serde_json::from_str(EXAMPLE_BLOCKTRACE).unwrap()
177+
=> ::serde_json::from_str::<BlockTrace>(EXAMPLE_BLOCKTRACE).unwrap()
178+
);
179+
180+
rpc_test!(
181+
Traces:raw_transaction, Bytes(vec![1, 2, 3, 4]), vec![TraceType::Trace]
182+
=>
183+
"trace_rawTransaction", vec![r#""0x01020304""#, r#"["trace"]"#];
184+
::serde_json::from_str(EXAMPLE_BLOCKTRACE).unwrap()
185+
=> ::serde_json::from_str::<BlockTrace>(EXAMPLE_BLOCKTRACE).unwrap()
186+
);
187+
188+
rpc_test!(
189+
Traces:replay_transaction, H256::from("0x0000000000000000000000000000000000000000000000000000000000000123"), vec![TraceType::Trace]
190+
=>
191+
"trace_replayTransaction", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#,r#"["trace"]"#];
192+
::serde_json::from_str(EXAMPLE_BLOCKTRACE).unwrap()
193+
=> ::serde_json::from_str::<BlockTrace>(EXAMPLE_BLOCKTRACE).unwrap()
194+
);
195+
196+
rpc_test!(
197+
Traces:replay_block_transactions, BlockNumber::Latest, vec![TraceType::Trace]
198+
=>
199+
"trace_replayBlockTransaction", vec![r#""latest""#, r#"["trace"]"#];
200+
::serde_json::from_str(EXAMPLE_BLOCKTRACE).unwrap()
201+
=> ::serde_json::from_str::<BlockTrace>(EXAMPLE_BLOCKTRACE).unwrap()
202+
);
203+
204+
rpc_test!(
205+
Traces:block, BlockNumber::Latest
206+
=>
207+
"trace_block", vec![r#""latest""#];
208+
::serde_json::from_str(EXAMPLE_TRACE_ARR).unwrap()
209+
=> ::serde_json::from_str::<Vec<Trace>>(EXAMPLE_TRACE_ARR).unwrap()
210+
);
211+
212+
rpc_test!(
213+
Traces:filter, TraceFilterBuilder::default().build() => "trace_filter", vec!["{}"];
214+
::serde_json::from_str(EXAMPLE_TRACE_ARR).unwrap()
215+
=> ::serde_json::from_str::<Vec<Trace>>(EXAMPLE_TRACE_ARR).unwrap()
216+
);
217+
218+
rpc_test!(
219+
Traces:get, H256::from("0x0000000000000000000000000000000000000000000000000000000000000123"), vec![0.into()]
220+
=>
221+
"trace_get", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#, r#"["0x0"]"#];
222+
::serde_json::from_str(EXAMPLE_TRACE).unwrap()
223+
=> ::serde_json::from_str::<Trace>(EXAMPLE_TRACE).unwrap()
224+
);
225+
226+
rpc_test!(
227+
Traces:transaction, H256::from("0x0000000000000000000000000000000000000000000000000000000000000123")
228+
=>
229+
"trace_transaction", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#];
230+
::serde_json::from_str(EXAMPLE_TRACE_ARR).unwrap()
231+
=> ::serde_json::from_str::<Vec<Trace>>(EXAMPLE_TRACE_ARR).unwrap()
232+
);
233+
}

0 commit comments

Comments
 (0)