cfx_execute_helper/observer/exec_tracer/
mod.rs1mod 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#[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}