Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 3c3d2ef

Browse files
HCastano5chdn
authored andcommitted
Replace hardcoded JSON with serde json! macro (#9489)
* Replace hardcoded JSON with serde json! macro * Use "{:#x}" formatter instead of "0x{:x}" * Sort fields of JSON test strings alphabetically * Stop escaping new lines in evmbin JSON errors * Remove unnecessary 'to_string()' calls * Add test with non-empty storage values
1 parent 67066eb commit 3c3d2ef

File tree

7 files changed

+139
-143
lines changed

7 files changed

+139
-143
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

evmbin/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ panic_hook = { path = "../util/panic_hook" }
2121
rustc-hex = "1.0"
2222
serde = "1.0"
2323
serde_derive = "1.0"
24+
serde_json = "1.0"
2425
vm = { path = "../ethcore/vm" }
2526

2627
[dev-dependencies]

evmbin/src/display/json.rs

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -43,31 +43,9 @@ pub struct Informant {
4343
unmatched: bool,
4444
}
4545

46-
impl Informant {
47-
fn memory(&self) -> String {
48-
format!("\"0x{}\"", self.memory.to_hex())
49-
}
50-
51-
fn stack(&self) -> String {
52-
let items = self.stack.iter().map(|i| format!("\"0x{:x}\"", i)).collect::<Vec<_>>();
53-
format!("[{}]", items.join(","))
54-
}
55-
56-
fn storage(&self) -> String {
57-
let vals = self.storage.iter()
58-
.map(|(k, v)| format!("\"0x{:?}\": \"0x{:?}\"", k, v))
59-
.collect::<Vec<_>>();
60-
format!("{{{}}}", vals.join(","))
61-
}
62-
}
63-
6446
impl vm::Informant for Informant {
6547
fn before_test(&mut self, name: &str, action: &str) {
66-
println!(
67-
"{{\"test\":\"{name}\",\"action\":\"{action}\"}}",
68-
name = name,
69-
action = action,
70-
);
48+
println!("{}", json!({"action": action, "test": name}));
7149
}
7250

7351
fn set_gas(&mut self, gas: U256) {
@@ -81,24 +59,26 @@ impl vm::Informant for Informant {
8159
println!("{}", trace);
8260
}
8361

84-
println!(
85-
"{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}",
86-
output = success.output.to_hex(),
87-
gas = success.gas_used,
88-
time = display::as_micros(&success.time),
89-
)
62+
let success_msg = json!({
63+
"output": format!("0x{}", success.output.to_hex()),
64+
"gasUsed": format!("{:#x}", success.gas_used),
65+
"time": display::as_micros(&success.time),
66+
});
67+
68+
println!("{}", success_msg)
9069
},
9170
Err(failure) => {
9271
for trace in failure.traces.unwrap_or_else(Vec::new) {
9372
println!("{}", trace);
9473
}
9574

96-
println!(
97-
"{{\"error\":\"{error}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}",
98-
error = display::escape_newlines(&failure.error),
99-
gas = failure.gas_used,
100-
time = display::as_micros(&failure.time),
101-
)
75+
let failure_msg = json!({
76+
"error": &failure.error.to_string(),
77+
"gasUsed": format!("{:#x}", failure.gas_used),
78+
"time": display::as_micros(&failure.time),
79+
});
80+
81+
println!("{}", failure_msg)
10282
},
10383
}
10484
}
@@ -123,19 +103,19 @@ impl trace::VMTracer for Informant {
123103
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) {
124104
let info = ::evm::Instruction::from_u8(self.instruction).map(|i| i.info());
125105

126-
let trace = format!(
127-
"{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"gasCost\":\"0x{gas_cost:x}\",\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}",
128-
pc = self.pc,
129-
op = self.instruction,
130-
name = info.map(|i| i.name).unwrap_or(""),
131-
gas = gas_used.saturating_add(self.gas_cost),
132-
gas_cost = self.gas_cost,
133-
memory = self.memory(),
134-
stack = self.stack(),
135-
storage = self.storage(),
136-
depth = self.depth,
137-
);
138-
self.traces.push(trace);
106+
let trace = json!({
107+
"pc": self.pc,
108+
"op": self.instruction,
109+
"opName": info.map(|i| i.name).unwrap_or(""),
110+
"gas": format!("{:#x}", gas_used.saturating_add(self.gas_cost)),
111+
"gasCost": format!("{:#x}", self.gas_cost),
112+
"memory": format!("0x{}", self.memory.to_hex()),
113+
"stack": self.stack,
114+
"storage": self.storage,
115+
"depth": self.depth,
116+
});
117+
118+
self.traces.push(trace.to_string());
139119

140120
self.unmatched = false;
141121
self.gas_used = gas_used;
@@ -193,6 +173,23 @@ impl trace::VMTracer for Informant {
193173
mod tests {
194174
use super::*;
195175
use info::tests::run_test;
176+
use serde_json;
177+
178+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
179+
#[serde(rename_all = "camelCase")]
180+
struct TestTrace {
181+
pc: usize,
182+
#[serde(rename = "op")]
183+
instruction: u8,
184+
op_name: String,
185+
#[serde(rename = "gas")]
186+
gas_used: U256,
187+
gas_cost: U256,
188+
memory: String,
189+
stack: Vec<U256>,
190+
storage: HashMap<H256, H256>,
191+
depth: usize,
192+
}
196193

197194
fn assert_traces_eq(
198195
a: &[String],
@@ -204,7 +201,10 @@ mod tests {
204201
loop {
205202
match (ita.next(), itb.next()) {
206203
(Some(a), Some(b)) => {
207-
assert_eq!(a, b);
204+
// Compare both without worrying about the order of the fields
205+
let actual: TestTrace = serde_json::from_str(a).unwrap();
206+
let expected: TestTrace = serde_json::from_str(b).unwrap();
207+
assert_eq!(actual, expected);
208208
println!("{}", a);
209209
},
210210
(None, None) => return,
@@ -280,7 +280,20 @@ mod tests {
280280
{"pc":5,"op":88,"opName":"PC","gas":"0x2102","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
281281
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2}
282282
{"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","gasCost":"0x0","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2}
283-
"#,
283+
"#,
284+
);
285+
286+
run_test(
287+
Informant::default(),
288+
&compare_json,
289+
"3260D85554",
290+
0xffff,
291+
r#"
292+
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","gasCost":"0x2","memory":"0x","stack":[],"storage":{},"depth":1}
293+
{"pc":1,"op":96,"opName":"PUSH1","gas":"0xfffd","gasCost":"0x3","memory":"0x","stack":["0x0"],"storage":{},"depth":1}
294+
{"pc":3,"op":85,"opName":"SSTORE","gas":"0xfffa","gasCost":"0x1388","memory":"0x","stack":["0x0","0xd8"],"storage":{},"depth":1}
295+
{"pc":4,"op":84,"opName":"SLOAD","gas":"0xec72","gasCost":"0x0","memory":"0x","stack":[],"storage":{"0x00000000000000000000000000000000000000000000000000000000000000d8":"0x0000000000000000000000000000000000000000000000000000000000000000"},"depth":1}
296+
"#,
284297
)
285298
}
286299
}

evmbin/src/display/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,3 @@ pub fn format_time(time: &Duration) -> String {
3131
pub fn as_micros(time: &Duration) -> u64 {
3232
time.as_secs() * 1_000_000 + time.subsec_nanos() as u64 / 1_000
3333
}
34-
35-
fn escape_newlines<D: ::std::fmt::Display>(s: D) -> String {
36-
format!("{}", s).replace("\r\n", "\n").replace('\n', "\\n")
37-
}

evmbin/src/display/std_json.rs

Lines changed: 62 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -81,28 +81,14 @@ impl<Trace: Writer, Out: Writer> Informant<Trace, Out> {
8181
}
8282
}
8383

84-
impl<Trace: Writer, Out: Writer> Informant<Trace, Out> {
85-
fn stack(&self) -> String {
86-
let items = self.stack.iter().map(|i| format!("\"0x{:x}\"", i)).collect::<Vec<_>>();
87-
format!("[{}]", items.join(","))
88-
}
89-
90-
fn storage(&self) -> String {
91-
let vals = self.storage.iter()
92-
.map(|(k, v)| format!("\"0x{:?}\": \"0x{:?}\"", k, v))
93-
.collect::<Vec<_>>();
94-
format!("{{{}}}", vals.join(","))
95-
}
96-
}
97-
9884
impl<Trace: Writer, Out: Writer> vm::Informant for Informant<Trace, Out> {
9985
fn before_test(&mut self, name: &str, action: &str) {
100-
writeln!(
101-
&mut self.out_sink,
102-
"{{\"test\":\"{name}\",\"action\":\"{action}\"}}",
103-
name = name,
104-
action = action,
105-
).expect("The sink must be writeable.");
86+
let out_data = json!({
87+
"action": action,
88+
"test": name,
89+
});
90+
91+
writeln!(&mut self.out_sink, "{}", out_data).expect("The sink must be writeable.");
10692
}
10793

10894
fn set_gas(&mut self, _gas: U256) {}
@@ -113,26 +99,26 @@ impl<Trace: Writer, Out: Writer> vm::Informant for Informant<Trace, Out> {
11399

114100
match result {
115101
Ok(success) => {
116-
writeln!(
117-
&mut trace_sink,
118-
"{{\"stateRoot\":\"{:?}\"}}", success.state_root
119-
).expect("The sink must be writeable.");
120-
writeln!(
121-
&mut out_sink,
122-
"{{\"output\":\"0x{output}\",\"gasUsed\":\"0x{gas:x}\",\"time\":{time}}}",
123-
output = success.output.to_hex(),
124-
gas = success.gas_used,
125-
time = display::as_micros(&success.time),
126-
).expect("The sink must be writeable.");
102+
let trace_data = json!({"stateRoot": success.state_root});
103+
writeln!(&mut trace_sink, "{}", trace_data)
104+
.expect("The sink must be writeable.");
105+
106+
let out_data = json!({
107+
"output": format!("0x{}", success.output.to_hex()),
108+
"gasUsed": format!("{:#x}", success.gas_used),
109+
"time": display::as_micros(&success.time),
110+
});
111+
112+
writeln!(&mut out_sink, "{}", out_data).expect("The sink must be writeable.");
127113
},
128114
Err(failure) => {
129-
writeln!(
130-
&mut out_sink,
131-
"{{\"error\":\"{error}\",\"gasUsed\":\"0x{gas:x}\",\"time\":{time}}}",
132-
error = display::escape_newlines(&failure.error),
133-
gas = failure.gas_used,
134-
time = display::as_micros(&failure.time),
135-
).expect("The sink must be writeable.");
115+
let out_data = json!({
116+
"error": &failure.error.to_string(),
117+
"gasUsed": format!("{:#x}", failure.gas_used),
118+
"time": display::as_micros(&failure.time),
119+
});
120+
121+
writeln!(&mut out_sink, "{}", out_data).expect("The sink must be writeable.");
136122
},
137123
}
138124
}
@@ -144,20 +130,17 @@ impl<Trace: Writer, Out: Writer> trace::VMTracer for Informant<Trace, Out> {
144130
fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool {
145131
let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info());
146132
self.instruction = instruction;
147-
let storage = self.storage();
148-
let stack = self.stack();
149-
150-
writeln!(
151-
&mut self.trace_sink,
152-
"{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}",
153-
pc = pc,
154-
op = instruction,
155-
name = info.map(|i| i.name).unwrap_or(""),
156-
gas = current_gas,
157-
stack = stack,
158-
storage = storage,
159-
depth = self.depth,
160-
).expect("The sink must be writeable.");
133+
let trace_data = json!({
134+
"pc": pc,
135+
"op": instruction,
136+
"opName": info.map(|i| i.name).unwrap_or(""),
137+
"gas": format!("{:#x}", current_gas),
138+
"stack": self.stack,
139+
"storage": self.storage,
140+
"depth": self.depth,
141+
});
142+
143+
writeln!(&mut self.trace_sink, "{}", trace_data).expect("The sink must be writeable.");
161144

162145
true
163146
}
@@ -232,8 +215,8 @@ pub mod tests {
232215
},
233216
"60F8d6",
234217
0xffff,
235-
r#"{"pc":0,"op":96,"opName":"PUSH1","gas":"0xffff","stack":[],"storage":{},"depth":1}
236-
{"pc":2,"op":214,"opName":"","gas":"0xfffc","stack":["0xf8"],"storage":{},"depth":1}
218+
r#"{"depth":1,"gas":"0xffff","op":96,"opName":"PUSH1","pc":0,"stack":[],"storage":{}}
219+
{"depth":1,"gas":"0xfffc","op":214,"opName":"","pc":2,"stack":["0xf8"],"storage":{}}
237220
"#,
238221
);
239222

@@ -246,7 +229,7 @@ pub mod tests {
246229
},
247230
"F8d6",
248231
0xffff,
249-
r#"{"pc":0,"op":248,"opName":"","gas":"0xffff","stack":[],"storage":{},"depth":1}
232+
r#"{"depth":1,"gas":"0xffff","op":248,"opName":"","pc":0,"stack":[],"storage":{}}
250233
"#,
251234
);
252235
}
@@ -262,30 +245,30 @@ pub mod tests {
262245
},
263246
"32343434345830f138343438323439f0",
264247
0xffff,
265-
r#"{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","stack":[],"storage":{},"depth":1}
266-
{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0xfffd","stack":["0x0"],"storage":{},"depth":1}
267-
{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0xfffb","stack":["0x0","0x0"],"storage":{},"depth":1}
268-
{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0xfff9","stack":["0x0","0x0","0x0"],"storage":{},"depth":1}
269-
{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0xfff7","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
270-
{"pc":5,"op":88,"opName":"PC","gas":"0xfff5","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
271-
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0xfff3","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":1}
272-
{"pc":7,"op":241,"opName":"CALL","gas":"0xfff1","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{},"depth":1}
273-
{"pc":8,"op":56,"opName":"CODESIZE","gas":"0x9e21","stack":["0x1"],"storage":{},"depth":1}
274-
{"pc":9,"op":52,"opName":"CALLVALUE","gas":"0x9e1f","stack":["0x1","0x10"],"storage":{},"depth":1}
275-
{"pc":10,"op":52,"opName":"CALLVALUE","gas":"0x9e1d","stack":["0x1","0x10","0x0"],"storage":{},"depth":1}
276-
{"pc":11,"op":56,"opName":"CODESIZE","gas":"0x9e1b","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
277-
{"pc":12,"op":50,"opName":"ORIGIN","gas":"0x9e19","stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{},"depth":1}
278-
{"pc":13,"op":52,"opName":"CALLVALUE","gas":"0x9e17","stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{},"depth":1}
279-
{"pc":14,"op":57,"opName":"CODECOPY","gas":"0x9e15","stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{},"depth":1}
280-
{"pc":15,"op":240,"opName":"CREATE","gas":"0x9e0c","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
281-
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0x210c","stack":[],"storage":{},"depth":2}
282-
{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0x210a","stack":["0x0"],"storage":{},"depth":2}
283-
{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0x2108","stack":["0x0","0x0"],"storage":{},"depth":2}
284-
{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0x2106","stack":["0x0","0x0","0x0"],"storage":{},"depth":2}
285-
{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0x2104","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
286-
{"pc":5,"op":88,"opName":"PC","gas":"0x2102","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
287-
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2}
288-
{"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2}
248+
r#"{"depth":1,"gas":"0xffff","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}}
249+
{"depth":1,"gas":"0xfffd","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}}
250+
{"depth":1,"gas":"0xfffb","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}}
251+
{"depth":1,"gas":"0xfff9","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}}
252+
{"depth":1,"gas":"0xfff7","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}}
253+
{"depth":1,"gas":"0xfff5","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}}
254+
{"depth":1,"gas":"0xfff3","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}}
255+
{"depth":1,"gas":"0xfff1","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{}}
256+
{"depth":1,"gas":"0x9e21","op":56,"opName":"CODESIZE","pc":8,"stack":["0x1"],"storage":{}}
257+
{"depth":1,"gas":"0x9e1f","op":52,"opName":"CALLVALUE","pc":9,"stack":["0x1","0x10"],"storage":{}}
258+
{"depth":1,"gas":"0x9e1d","op":52,"opName":"CALLVALUE","pc":10,"stack":["0x1","0x10","0x0"],"storage":{}}
259+
{"depth":1,"gas":"0x9e1b","op":56,"opName":"CODESIZE","pc":11,"stack":["0x1","0x10","0x0","0x0"],"storage":{}}
260+
{"depth":1,"gas":"0x9e19","op":50,"opName":"ORIGIN","pc":12,"stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{}}
261+
{"depth":1,"gas":"0x9e17","op":52,"opName":"CALLVALUE","pc":13,"stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{}}
262+
{"depth":1,"gas":"0x9e15","op":57,"opName":"CODECOPY","pc":14,"stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{}}
263+
{"depth":1,"gas":"0x9e0c","op":240,"opName":"CREATE","pc":15,"stack":["0x1","0x10","0x0","0x0"],"storage":{}}
264+
{"depth":2,"gas":"0x210c","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}}
265+
{"depth":2,"gas":"0x210a","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}}
266+
{"depth":2,"gas":"0x2108","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}}
267+
{"depth":2,"gas":"0x2106","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}}
268+
{"depth":2,"gas":"0x2104","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}}
269+
{"depth":2,"gas":"0x2102","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}}
270+
{"depth":2,"gas":"0x2100","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}}
271+
{"depth":2,"gas":"0x20fe","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{}}
289272
"#,
290273
)
291274
}

0 commit comments

Comments
 (0)