1
// Copyright 2019-2022 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use super::blockscout::BlockscoutCallInner;
18
use crate::types::{
19
	single::{Call, Log, TransactionTrace},
20
	CallResult, CallType, CreateResult,
21
};
22

            
23
use crate::listeners::call_list::Listener;
24

            
25
use crate::types::serialization::*;
26
use serde::Serialize;
27

            
28
use ethereum_types::{H160, U256};
29
use parity_scale_codec::{Decode, Encode};
30
use sp_std::{cmp::Ordering, vec::Vec};
31

            
32
pub struct Formatter;
33

            
34
impl super::ResponseFormatter for Formatter {
35
	type Listener = Listener;
36
	type Response = Vec<TransactionTrace>;
37

            
38
	fn format(mut listener: Listener) -> Option<Vec<TransactionTrace>> {
39
		// Remove empty BTreeMaps pushed to `entries`.
40
		// I.e. InvalidNonce or other pallet_evm::runner exits
41
		listener.entries.retain(|x| !x.is_empty());
42
		let mut traces = Vec::new();
43
		for entry in listener.entries.iter() {
44
			let mut result: Vec<Call> = entry
45
				.into_iter()
46
				.map(|(_, it)| {
47
					let from = it.from;
48
					let trace_address = it.trace_address.clone();
49
					let value = it.value;
50
					let gas = it.gas;
51
					let gas_used = it.gas_used;
52
					let inner = it.inner.clone();
53
					Call::CallTracer(CallTracerCall {
54
						from: from,
55
						gas: gas,
56
						gas_used: gas_used,
57
						trace_address: Some(trace_address.clone()),
58
						inner: match inner.clone() {
59
							BlockscoutCallInner::Call {
60
								input,
61
								to,
62
								res,
63
								call_type,
64
							} => CallTracerInner::Call {
65
								call_type: match call_type {
66
									CallType::Call => "CALL".as_bytes().to_vec(),
67
									CallType::CallCode => "CALLCODE".as_bytes().to_vec(),
68
									CallType::DelegateCall => "DELEGATECALL".as_bytes().to_vec(),
69
									CallType::StaticCall => "STATICCALL".as_bytes().to_vec(),
70
								},
71
								to,
72
								input,
73
								res: res.clone(),
74
								value: Some(value),
75
								logs: match res {
76
									CallResult::Output { .. } => it.logs.clone(),
77
									CallResult::Error { .. } => Vec::new(),
78
								},
79
							},
80
							BlockscoutCallInner::Create { init, res } => CallTracerInner::Create {
81
								input: init,
82
								error: match res {
83
									CreateResult::Success { .. } => None,
84
									CreateResult::Error { ref error } => Some(error.clone()),
85
								},
86
								to: match res {
87
									CreateResult::Success {
88
										created_contract_address_hash,
89
										..
90
									} => Some(created_contract_address_hash),
91
									CreateResult::Error { .. } => None,
92
								},
93
								output: match res {
94
									CreateResult::Success {
95
										created_contract_code,
96
										..
97
									} => Some(created_contract_code),
98
									CreateResult::Error { .. } => None,
99
								},
100
								value: value,
101
								call_type: "CREATE".as_bytes().to_vec(),
102
							},
103
							BlockscoutCallInner::SelfDestruct { balance, to } => {
104
								CallTracerInner::SelfDestruct {
105
									value: balance,
106
									to,
107
									call_type: "SELFDESTRUCT".as_bytes().to_vec(),
108
								}
109
							}
110
						},
111
						calls: Vec::new(),
112
					})
113
				})
114
				.collect();
115
			// Geth's `callTracer` expects a tree of nested calls and we have a stack.
116
			//
117
			// We iterate over the sorted stack, and push each children to it's
118
			// parent (the item which's `trace_address` matches &T[0..T.len()-1]) until there
119
			// is a single item on the list.
120
			//
121
			// The last remaining item is the context call with all it's descendants. I.e.
122
			//
123
			// 		# Input
124
			// 		[]
125
			// 		[0]
126
			// 		[0,0]
127
			// 		[0,0,0]
128
			// 		[0,1]
129
			// 		[0,1,0]
130
			// 		[0,1,1]
131
			// 		[0,1,2]
132
			// 		[1]
133
			// 		[1,0]
134
			//
135
			// 		# Sorted
136
			// 		[0,0,0] -> pop 0 and push to [0,0]
137
			// 		[0,1,0] -> pop 0 and push to [0,1]
138
			// 		[0,1,1] -> pop 1 and push to [0,1]
139
			// 		[0,1,2] -> pop 2 and push to [0,1]
140
			// 		[0,0] -> pop 0 and push to [0]
141
			// 		[0,1] -> pop 1 and push to [0]
142
			// 		[1,0] -> pop 0 and push to [1]
143
			// 		[0] -> pop 0 and push to root
144
			// 		[1] -> pop 1 and push to root
145
			// 		[]
146
			//
147
			// 		# Result
148
			// 		root {
149
			// 			calls: {
150
			// 				0 { 0 { 0 }, 1 { 0, 1, 2 }},
151
			// 				1 { 0 },
152
			// 			}
153
			// 		}
154
			if result.len() > 1 {
155
				// Sort the stack. Assume there is no `Ordering::Equal`, as we are
156
				// sorting by index.
157
				//
158
				// We consider an item to be `Ordering::Less` when:
159
				// 	- Is closer to the root or
160
				//	- Is greater than its sibling.
161
				result.sort_by(|a, b| match (a, b) {
162
					(
163
						Call::CallTracer(CallTracerCall {
164
							trace_address: Some(a),
165
							..
166
						}),
167
						Call::CallTracer(CallTracerCall {
168
							trace_address: Some(b),
169
							..
170
						}),
171
					) => {
172
						let a_len = a.len();
173
						let b_len = b.len();
174
						let sibling_greater_than = |a: &Vec<u32>, b: &Vec<u32>| -> bool {
175
							for (i, a_value) in a.iter().enumerate() {
176
								if a_value > &b[i] {
177
									return true;
178
								} else if a_value < &b[i] {
179
									return false;
180
								} else {
181
									continue;
182
								}
183
							}
184
							return false;
185
						};
186
						if b_len > a_len || (a_len == b_len && sibling_greater_than(&a, &b)) {
187
							Ordering::Less
188
						} else {
189
							Ordering::Greater
190
						}
191
					}
192
					_ => unreachable!(),
193
				});
194
				// Stack pop-and-push.
195
				while result.len() > 1 {
196
					let mut last = result
197
						.pop()
198
						.expect("result.len() > 1, so pop() necessarily returns an element");
199
					// Find the parent index.
200
					if let Some(index) =
201
						result
202
							.iter()
203
							.position(|current| match (last.clone(), current) {
204
								(
205
									Call::CallTracer(CallTracerCall {
206
										trace_address: Some(a),
207
										..
208
									}),
209
									Call::CallTracer(CallTracerCall {
210
										trace_address: Some(b),
211
										..
212
									}),
213
								) => {
214
									&b[..]
215
										== a.get(0..a.len() - 1).expect(
216
											"non-root element while traversing trace result",
217
										)
218
								}
219
								_ => unreachable!(),
220
							}) {
221
						// Remove `trace_address` from result.
222
						if let Call::CallTracer(CallTracerCall {
223
							ref mut trace_address,
224
							..
225
						}) = last
226
						{
227
							*trace_address = None;
228
						}
229
						// Push the children to parent.
230
						if let Some(Call::CallTracer(CallTracerCall { calls, .. })) =
231
							result.get_mut(index)
232
						{
233
							calls.push(last);
234
						}
235
					}
236
				}
237
			}
238
			// Remove `trace_address` from result.
239
			if let Some(Call::CallTracer(CallTracerCall { trace_address, .. })) = result.get_mut(0)
240
			{
241
				*trace_address = None;
242
			}
243
			if result.len() == 1 {
244
				traces.push(TransactionTrace::CallListNested(result.pop().expect(
245
					"result.len() == 1, so pop() necessarily returns this element",
246
				)));
247
			}
248
		}
249
		if traces.is_empty() {
250
			return None;
251
		}
252
		return Some(traces);
253
	}
254
}
255

            
256
#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, Serialize)]
257
#[serde(rename_all = "camelCase")]
258
pub struct CallTracerCall {
259
	pub from: H160,
260

            
261
	/// Indices of parent calls. Used to build the Etherscan nested response.
262
	#[serde(skip_serializing_if = "Option::is_none")]
263
	pub trace_address: Option<Vec<u32>>,
264

            
265
	/// Remaining gas in the runtime.
266
	pub gas: U256,
267
	/// Gas used by this context.
268
	pub gas_used: U256,
269

            
270
	#[serde(flatten)]
271
	pub inner: CallTracerInner,
272

            
273
	#[serde(skip_serializing_if = "Vec::is_empty")]
274
	pub calls: Vec<Call>,
275
}
276

            
277
#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, Serialize)]
278
#[serde(untagged)]
279
pub enum CallTracerInner {
280
	Call {
281
		#[serde(rename = "type", serialize_with = "opcode_serialize")]
282
		call_type: Vec<u8>,
283
		to: H160,
284
		#[serde(serialize_with = "bytes_0x_serialize")]
285
		input: Vec<u8>,
286
		/// "output" or "error" field
287
		#[serde(flatten)]
288
		res: CallResult,
289

            
290
		#[serde(skip_serializing_if = "Option::is_none")]
291
		value: Option<U256>,
292

            
293
		#[serde(skip_serializing_if = "Vec::is_empty")]
294
		logs: Vec<Log>,
295
	},
296
	Create {
297
		#[serde(rename = "type", serialize_with = "opcode_serialize")]
298
		call_type: Vec<u8>,
299
		#[serde(serialize_with = "bytes_0x_serialize")]
300
		input: Vec<u8>,
301
		#[serde(skip_serializing_if = "Option::is_none")]
302
		to: Option<H160>,
303
		#[serde(
304
			skip_serializing_if = "Option::is_none",
305
			serialize_with = "option_bytes_0x_serialize"
306
		)]
307
		output: Option<Vec<u8>>,
308
		#[serde(
309
			skip_serializing_if = "Option::is_none",
310
			serialize_with = "option_string_serialize"
311
		)]
312
		error: Option<Vec<u8>>,
313
		value: U256,
314
	},
315
	SelfDestruct {
316
		#[serde(rename = "type", serialize_with = "opcode_serialize")]
317
		call_type: Vec<u8>,
318
		to: H160,
319
		value: U256,
320
	},
321
}