@@ -38,7 +38,7 @@ pub struct TracerEip3155<CTX, INTR> {
38
38
// The CUT MUST output a `json` object for EACH operation.
39
39
#[ derive( Serialize ) ]
40
40
#[ serde( rename_all = "camelCase" ) ]
41
- struct Output {
41
+ struct Output < ' a > {
42
42
// Required fields:
43
43
/// Program counter
44
44
pc : u64 ,
@@ -48,22 +48,26 @@ struct Output {
48
48
/// OpCode
49
49
op : u8 ,
50
50
/// Gas left before executing this operation
51
- gas : String ,
51
+ #[ serde( serialize_with = "serde_hex_u64" ) ]
52
+ gas : u64 ,
52
53
/// Gas cost of this operation
53
- gas_cost : String ,
54
+ #[ serde( serialize_with = "serde_hex_u64" ) ]
55
+ gas_cost : u64 ,
54
56
/// Array of all values on the stack
55
- stack : Vec < String > ,
57
+ stack : & ' a [ U256 ] ,
56
58
/// Depth of the call stack
57
59
depth : u64 ,
58
60
/// Depth of the EOF function call stack
59
61
#[ serde( default , skip_serializing_if = "Option::is_none" ) ]
60
62
function_depth : Option < u64 > ,
61
63
/// Data returned by the function call
62
- return_data : String ,
64
+ return_data : & ' static str ,
63
65
/// Amount of **global** gas refunded
64
- refund : String ,
66
+ #[ serde( serialize_with = "serde_hex_u64" ) ]
67
+ refund : u64 ,
65
68
/// Size of memory array
66
- mem_size : String ,
69
+ #[ serde( serialize_with = "serde_hex_u64" ) ]
70
+ mem_size : u64 ,
67
71
68
72
// Optional fields:
69
73
/// Name of the operation
@@ -93,7 +97,8 @@ struct Summary {
93
97
/// Return values of the function
94
98
output : String ,
95
99
/// All gas used by the transaction
96
- gas_used : String ,
100
+ #[ serde( serialize_with = "serde_hex_u64" ) ]
101
+ gas_used : u64 ,
97
102
/// Bool whether transaction was executed successfully
98
103
pass : bool ,
99
104
@@ -111,35 +116,13 @@ where
111
116
CTX : CfgGetter + TransactionGetter ,
112
117
INTR : ,
113
118
{
114
- /// Sets the writer to use for the output.
115
- pub fn set_writer ( & mut self , writer : Box < dyn Write > ) {
116
- self . output = writer;
117
- }
118
-
119
- /// Resets the Tracer to its initial state of [Self::new].
120
- /// This makes the inspector ready to be used again.
121
- pub fn clear ( & mut self ) {
122
- let Self {
123
- gas_inspector,
124
- stack,
125
- pc,
126
- opcode,
127
- gas,
128
- refunded,
129
- mem_size,
130
- skip,
131
- ..
132
- } = self ;
133
- * gas_inspector = GasInspector :: new ( ) ;
134
- stack. clear ( ) ;
135
- * pc = 0 ;
136
- * opcode = 0 ;
137
- * gas = 0 ;
138
- * refunded = 0 ;
139
- * mem_size = 0 ;
140
- * skip = false ;
119
+ /// Creates a new EIP-3155 tracer with the given output writer, by first wrapping it in a
120
+ /// [`BufWriter`](std::io::BufWriter).
121
+ pub fn buffered ( output : impl Write + ' static ) -> Self {
122
+ Self :: new ( Box :: new ( std:: io:: BufWriter :: new ( output) ) )
141
123
}
142
124
125
+ /// Creates a new EIP-3155 tracer with the given output writer.
143
126
pub fn new ( output : Box < dyn Write > ) -> Self {
144
127
Self {
145
128
output,
@@ -160,6 +143,11 @@ where
160
143
}
161
144
}
162
145
146
+ /// Sets the writer to use for the output.
147
+ pub fn set_writer ( & mut self , writer : Box < dyn Write > ) {
148
+ self . output = writer;
149
+ }
150
+
163
151
/// Don't include a summary at the end of the trace
164
152
pub fn without_summary ( mut self ) -> Self {
165
153
self . print_summary = false ;
@@ -172,10 +160,29 @@ where
172
160
self
173
161
}
174
162
175
- fn write_value ( & mut self , value : & impl serde:: Serialize ) -> std:: io:: Result < ( ) > {
176
- serde_json:: to_writer ( & mut * self . output , value) ?;
177
- self . output . write_all ( b"\n " ) ?;
178
- self . output . flush ( )
163
+ /// Resets the tracer to its initial state of [`Self::new`].
164
+ ///
165
+ /// This makes the inspector ready to be used again.
166
+ pub fn clear ( & mut self ) {
167
+ let Self {
168
+ gas_inspector,
169
+ stack,
170
+ pc,
171
+ opcode,
172
+ gas,
173
+ refunded,
174
+ mem_size,
175
+ skip,
176
+ ..
177
+ } = self ;
178
+ * gas_inspector = GasInspector :: new ( ) ;
179
+ stack. clear ( ) ;
180
+ * pc = 0 ;
181
+ * opcode = 0 ;
182
+ * gas = 0 ;
183
+ * refunded = 0 ;
184
+ * mem_size = 0 ;
185
+ * skip = false ;
179
186
}
180
187
181
188
fn print_summary ( & mut self , result : & InterpreterResult , context : & mut CTX ) {
@@ -185,23 +192,27 @@ where
185
192
let value = Summary {
186
193
state_root : B256 :: ZERO . to_string ( ) ,
187
194
output : result. output . to_string ( ) ,
188
- gas_used : hex_number ( gas_limit - self . gas_inspector . gas_remaining ( ) ) ,
195
+ gas_used : gas_limit - self . gas_inspector . gas_remaining ( ) ,
189
196
pass : result. is_ok ( ) ,
190
197
time : None ,
191
198
fork : Some ( spec. to_string ( ) ) ,
192
199
} ;
193
200
let _ = self . write_value ( & value) ;
194
201
}
195
202
}
203
+
204
+ fn write_value ( & mut self , value : & impl serde:: Serialize ) -> std:: io:: Result < ( ) > {
205
+ write_value ( & mut * self . output , value)
206
+ }
196
207
}
197
208
198
209
pub trait CloneStack {
199
- fn clone_from ( & self ) -> Vec < U256 > ;
210
+ fn clone_into ( & self , stack : & mut Vec < U256 > ) ;
200
211
}
201
212
202
213
impl CloneStack for Stack {
203
- fn clone_from ( & self ) -> Vec < U256 > {
204
- self . data ( ) . to_vec ( )
214
+ fn clone_into ( & self , stack : & mut Vec < U256 > ) {
215
+ stack . extend_from_slice ( self . data ( ) ) ;
205
216
}
206
217
}
207
218
@@ -216,10 +227,11 @@ where
216
227
217
228
fn step ( & mut self , interp : & mut Interpreter < INTR > , _: & mut CTX ) {
218
229
self . gas_inspector . step ( interp. control . gas ( ) ) ;
219
- self . stack = interp. stack . clone_from ( ) ;
230
+ self . stack . clear ( ) ;
231
+ interp. stack . clone_into ( & mut self . stack ) ;
220
232
self . memory = if self . include_memory {
221
233
Some ( hex:: encode_prefixed (
222
- interp. memory . slice ( 0 ..usize :: MAX ) . as_ref ( ) ,
234
+ interp. memory . slice ( 0 ..interp . memory . size ( ) ) . as_ref ( ) ,
223
235
) )
224
236
} else {
225
237
None
@@ -252,14 +264,14 @@ where
252
264
pc : self . pc ,
253
265
section : self . section ,
254
266
op : self . opcode ,
255
- gas : hex_number ( self . gas ) ,
256
- gas_cost : hex_number ( self . gas_inspector . last_gas_cost ( ) ) ,
257
- stack : self . stack . iter ( ) . map ( hex_number_u256 ) . collect ( ) ,
267
+ gas : self . gas ,
268
+ gas_cost : self . gas_inspector . last_gas_cost ( ) ,
269
+ stack : & self . stack ,
258
270
depth : context. journal ( ) . depth ( ) as u64 ,
259
271
function_depth : self . function_depth ,
260
- return_data : "0x" . to_string ( ) ,
261
- refund : hex_number ( self . refunded as u64 ) ,
262
- mem_size : self . mem_size . to_string ( ) ,
272
+ return_data : "0x" ,
273
+ refund : self . refunded as u64 ,
274
+ mem_size : self . mem_size as u64 ,
263
275
264
276
op_name : OpCode :: new ( self . opcode ) . map ( |i| i. as_str ( ) ) ,
265
277
error : if !interp. control . instruction_result ( ) . is_ok ( ) {
@@ -271,15 +283,15 @@ where
271
283
storage : None ,
272
284
return_stack : None ,
273
285
} ;
274
- let _ = self . write_value ( & value) ;
286
+ let _ = write_value ( & mut self . output , & value) ;
275
287
}
276
288
277
289
fn call_end ( & mut self , context : & mut CTX , _: & CallInputs , outcome : & mut CallOutcome ) {
278
290
self . gas_inspector . call_end ( outcome) ;
279
291
280
292
if context. journal ( ) . depth ( ) == 0 {
281
293
self . print_summary ( & outcome. result , context) ;
282
- // Clear the state if we are at the top level
294
+ // Clear the state if we are at the top level.
283
295
self . clear ( ) ;
284
296
}
285
297
}
@@ -289,23 +301,20 @@ where
289
301
290
302
if context. journal ( ) . depth ( ) == 0 {
291
303
self . print_summary ( & outcome. result , context) ;
292
-
293
- // Clear the state if we are at the top level
304
+ // Clear the state if we are at the top level.
294
305
self . clear ( ) ;
295
306
}
296
307
}
297
308
}
298
309
299
- fn hex_number ( uint : u64 ) -> String {
300
- format ! ( "0x{uint:x}" )
310
+ fn write_value (
311
+ output : & mut dyn std:: io:: Write ,
312
+ value : & impl serde:: Serialize ,
313
+ ) -> std:: io:: Result < ( ) > {
314
+ serde_json:: to_writer ( & mut * output, value) ?;
315
+ output. write_all ( b"\n " )
301
316
}
302
317
303
- fn hex_number_u256 ( b : & U256 ) -> String {
304
- let s = hex:: encode ( b. to_be_bytes :: < 32 > ( ) ) ;
305
- let s = s. trim_start_matches ( '0' ) ;
306
- if s. is_empty ( ) {
307
- "0x0" . to_string ( )
308
- } else {
309
- format ! ( "0x{s}" )
310
- }
318
+ fn serde_hex_u64 < S : serde:: Serializer > ( n : & u64 , serializer : S ) -> Result < S :: Ok , S :: Error > {
319
+ serializer. serialize_str ( & format ! ( "{:#x}" , * n) )
311
320
}
0 commit comments