cfx_execute_helper/observer/exec_tracer/
mod.rs

1mod error_unwind;
2mod phantom_traces;
3
4pub use error_unwind::ErrorUnwind;
5pub use phantom_traces::{
6    recover_phantom_trace_for_call, recover_phantom_trace_for_withdraw,
7    recover_phantom_traces,
8};
9
10pub use cfx_parity_trace_types::{
11    action_types::{
12        self, Action, ActionType, Call, CallResult, Create, CreateResult,
13        InternalTransferAction, Outcome, SelfDestructAction, SetAuth,
14    },
15    filter::{self, TraceFilter},
16    trace_types::{
17        self, BlockExecTraces, ExecTrace, LocalizedTrace, TransactionExecTraces,
18    },
19};
20
21use super::utils::CheckpointLog;
22
23use cfx_executor::{
24    observer::{
25        AddressPocket, CallTracer, CheckpointTracer, DrainTrace,
26        InternalTransferTracer, OpcodeTracer, SetAuthTracer, StorageTracer,
27    },
28    stack::{FrameResult, FrameReturn},
29};
30use cfx_types::{Address, Space, U256};
31use cfx_vm_types::ActionParams;
32use typemap::ShareDebugMap;
33
34/// Simple executive tracer. Traces all calls and creates.
35#[derive(Default)]
36pub struct ExecTracer {
37    traces: Vec<Action>,
38    valid_indices: CheckpointLog<usize>,
39}
40
41impl ExecTracer {
42    pub fn drain(self) -> Vec<ExecTrace> {
43        let mut validity: Vec<bool> = vec![false; self.traces.len()];
44        for index in self.valid_indices.drain() {
45            validity[index] = true;
46        }
47        self.traces
48            .into_iter()
49            .zip(validity.into_iter())
50            .map(|(action, valid)| ExecTrace { action, valid })
51            .collect()
52    }
53}
54
55impl DrainTrace for ExecTracer {
56    fn drain_trace(self, map: &mut ShareDebugMap) {
57        map.insert::<ExecTraceKey>(self.drain());
58    }
59}
60
61pub struct ExecTraceKey;
62
63impl typemap::Key for ExecTraceKey {
64    type Value = Vec<ExecTrace>;
65}
66
67impl InternalTransferTracer for ExecTracer {
68    fn trace_internal_transfer(
69        &mut self, from: AddressPocket, to: AddressPocket, value: U256,
70    ) {
71        let action = Action::InternalTransferAction(InternalTransferAction {
72            from,
73            to,
74            value,
75        });
76
77        self.valid_indices.push(self.traces.len());
78        self.traces.push(action);
79    }
80}
81
82impl CheckpointTracer for ExecTracer {
83    fn trace_checkpoint(&mut self) { self.valid_indices.checkpoint(); }
84
85    fn trace_checkpoint_discard(&mut self) {
86        self.valid_indices.discard_checkpoint();
87    }
88
89    fn trace_checkpoint_revert(&mut self) {
90        self.valid_indices.revert_checkpoint();
91    }
92}
93
94impl CallTracer for ExecTracer {
95    fn record_call(&mut self, params: &ActionParams) {
96        let action = Action::Call(Call::from(params.clone()));
97
98        self.valid_indices.checkpoint();
99        self.valid_indices.push(self.traces.len());
100
101        self.traces.push(action);
102    }
103
104    fn record_call_result(&mut self, result: &FrameResult) {
105        let action = Action::CallResult(frame_result_to_call_result(result));
106        let success = matches!(
107            result,
108            Ok(FrameReturn {
109                apply_state: true,
110                ..
111            })
112        );
113
114        self.valid_indices.push(self.traces.len());
115        self.traces.push(action);
116        if success {
117            self.valid_indices.discard_checkpoint();
118        } else {
119            self.valid_indices.revert_checkpoint();
120        }
121    }
122
123    fn record_create(&mut self, params: &ActionParams) {
124        let action = Action::Create(Create::from(params.clone()));
125
126        self.valid_indices.checkpoint();
127        self.valid_indices.push(self.traces.len());
128        self.traces.push(action);
129    }
130
131    fn record_create_result(&mut self, result: &FrameResult) {
132        let action =
133            Action::CreateResult(frame_result_to_create_result(result));
134        let success = matches!(
135            result,
136            Ok(FrameReturn {
137                apply_state: true,
138                ..
139            })
140        );
141
142        self.valid_indices.push(self.traces.len());
143        self.traces.push(action);
144        if success {
145            self.valid_indices.discard_checkpoint();
146        } else {
147            self.valid_indices.revert_checkpoint();
148        }
149    }
150}
151
152impl StorageTracer for ExecTracer {}
153impl OpcodeTracer for ExecTracer {
154    fn selfdestruct(
155        &mut self, space: Space, contract: &Address, target: &Address,
156        value: U256,
157    ) {
158        let self_destruct = SelfDestructAction {
159            space,
160            address: contract.clone(),
161            refund_address: *target,
162            balance: value,
163        };
164        let action = Action::SelfDestruct(self_destruct);
165        self.valid_indices.push(self.traces.len());
166        self.traces.push(action);
167    }
168}
169
170impl SetAuthTracer for ExecTracer {
171    fn record_set_auth(&mut self, set_auth_action: SetAuth) {
172        let action = Action::SetAuth(set_auth_action);
173        self.valid_indices.push(self.traces.len());
174        self.traces.push(action);
175    }
176}
177
178fn frame_result_to_call_result(r: &FrameResult) -> CallResult {
179    match r {
180        Ok(FrameReturn {
181            gas_left,
182            return_data,
183            apply_state: true,
184            ..
185        }) => CallResult {
186            outcome: Outcome::Success,
187            gas_left: gas_left.clone(),
188            return_data: return_data.to_vec(),
189        },
190        Ok(FrameReturn {
191            gas_left,
192            return_data,
193            apply_state: false,
194            ..
195        }) => CallResult {
196            outcome: Outcome::Reverted,
197            gas_left: gas_left.clone(),
198            return_data: return_data.to_vec(),
199        },
200        Err(err) => CallResult {
201            outcome: Outcome::Fail,
202            gas_left: U256::zero(),
203            return_data: format!("{:?}", err).into(),
204        },
205    }
206}
207
208fn frame_result_to_create_result(r: &FrameResult) -> CreateResult {
209    match r {
210        Ok(FrameReturn {
211            gas_left,
212            return_data,
213            apply_state: true,
214            create_address,
215            ..
216        }) => CreateResult {
217            outcome: Outcome::Success,
218            addr: create_address.expect(
219                "Address should not be none in executive result of
220create",
221            ),
222            gas_left: gas_left.clone(),
223            return_data: return_data.to_vec(),
224        },
225        Ok(FrameReturn {
226            gas_left,
227            return_data,
228            apply_state: false,
229            ..
230        }) => CreateResult {
231            outcome: Outcome::Reverted,
232            addr: Address::zero(),
233            gas_left: gas_left.clone(),
234            return_data: return_data.to_vec(),
235        },
236        Err(err) => CreateResult {
237            outcome: Outcome::Fail,
238            addr: Address::zero(),
239            gas_left: U256::zero(),
240            return_data: format!("{:?}", err).into(),
241        },
242    }
243}