web3_etz/types/
traces.rs

1//! Types for the Parity Ad-Hoc Trace API
2use std::collections::BTreeMap;
3
4use crate::types::{Action, Bytes, Res, H160, H256, U256};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize)]
8/// Description of the type of trace to make
9pub enum TraceType {
10    /// Transaction Trace
11    #[serde(rename = "trace")]
12    Trace,
13    /// Virtual Machine Execution Trace
14    #[serde(rename = "vmTrace")]
15    VmTrace,
16    /// State Difference
17    #[serde(rename = "stateDiff")]
18    StateDiff,
19}
20
21#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
22/// Ad-Hoc trace API type
23pub struct BlockTrace {
24    /// Output Bytes
25    pub output: Bytes,
26    /// Transaction Trace
27    pub trace: Option<Vec<TransactionTrace>>,
28    /// Virtual Machine Execution Trace
29    #[serde(rename = "vmTrace")]
30    pub vm_trace: Option<VMTrace>,
31    /// State Difference
32    #[serde(rename = "stateDiff")]
33    pub state_diff: Option<StateDiff>,
34}
35
36//---------------- State Diff ----------------
37#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
38/// Aux type for Diff::Changed.
39pub struct ChangedType<T> {
40    from: T,
41    to: T,
42}
43
44#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
45/// Serde-friendly `Diff` shadow.
46pub enum Diff<T> {
47    #[serde(rename = "=")]
48    Same,
49    #[serde(rename = "+")]
50    Born(T),
51    #[serde(rename = "-")]
52    Died(T),
53    #[serde(rename = "*")]
54    Changed(ChangedType<T>),
55}
56
57#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
58/// Serde-friendly `AccountDiff` shadow.
59pub struct AccountDiff {
60    pub balance: Diff<U256>,
61    pub nonce: Diff<U256>,
62    pub code: Diff<Bytes>,
63    pub storage: BTreeMap<H256, Diff<H256>>,
64}
65
66#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
67/// Serde-friendly `StateDiff` shadow.
68pub struct StateDiff(BTreeMap<H160, AccountDiff>);
69
70// ------------------ Trace -------------
71/// Trace
72#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
73pub struct TransactionTrace {
74    /// Trace address
75    #[serde(rename = "traceAddress")]
76    trace_address: Vec<usize>,
77    /// Subtraces
78    subtraces: usize,
79    /// Action
80    action: Action,
81    /// Result
82    result: Option<Res>,
83}
84
85// ---------------- VmTrace ------------------------------
86#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
87/// A record of a full VM trace for a CALL/CREATE.
88pub struct VMTrace {
89    /// The code to be executed.
90    pub code: Bytes,
91    /// The operations executed.
92    pub ops: Vec<VMOperation>,
93}
94
95#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
96/// A record of the execution of a single VM operation.
97pub struct VMOperation {
98    /// The program counter.
99    pub pc: usize,
100    /// The gas cost for this instruction.
101    pub cost: u64,
102    /// Information concerning the execution of the operation.
103    pub ex: Option<VMExecutedOperation>,
104    /// Subordinate trace of the CALL/CREATE if applicable.
105    // #[serde(bound="VMTrace: Deserialize")]
106    pub sub: Option<VMTrace>,
107}
108
109#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
110/// A record of an executed VM operation.
111pub struct VMExecutedOperation {
112    /// The total gas used.
113    #[serde(rename = "used")]
114    pub used: u64,
115    /// The stack item placed, if any.
116    pub push: Vec<U256>,
117    /// If altered, the memory delta.
118    #[serde(rename = "mem")]
119    pub mem: Option<MemoryDiff>,
120    /// The altered storage value, if any.
121    #[serde(rename = "store")]
122    pub store: Option<StorageDiff>,
123}
124
125#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
126/// A diff of some chunk of memory.
127pub struct MemoryDiff {
128    /// Offset into memory the change begins.
129    pub off: usize,
130    /// The changed data.
131    pub data: Bytes,
132}
133
134#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
135/// A diff of some storage value.
136pub struct StorageDiff {
137    /// Which key in storage is changed.
138    pub key: U256,
139    /// What the value has been changed to.
140    pub val: U256,
141}
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146    use serde_json;
147
148    // tx: https://etherscan.io/tx/0x4a91b11dbd2b11c308cfe7775eac2036f20c501691e3f8005d83b2dcce62d6b5
149    // using the 'trace_replayTransaction' API function
150    // with 'trace', 'vmTrace', 'stateDiff'
151    const EXAMPLE_TRACE: &'static str = include!("./example-trace-str.rs");
152
153    #[test]
154    fn test_serialize_trace_type() {
155        let trace_type_str = r#"["trace","vmTrace","stateDiff"]"#;
156        let trace_type = vec![TraceType::Trace, TraceType::VmTrace, TraceType::StateDiff];
157
158        let se_trace_str: String = serde_json::to_string(&trace_type).unwrap();
159        assert_eq!(trace_type_str, se_trace_str);
160    }
161
162    #[test]
163    fn test_deserialize_blocktrace() {
164        let _trace: BlockTrace = serde_json::from_str(EXAMPLE_TRACE).unwrap();
165    }
166}