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
			
			
This commit is contained in:
		
							parent
							
								
									67066eb32a
								
							
						
					
					
						commit
						3c3d2ef2b9
					
				
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -1049,6 +1049,7 @@ dependencies = [
 | 
			
		||||
 "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "vm 0.1.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ panic_hook = { path = "../util/panic_hook" }
 | 
			
		||||
rustc-hex = "1.0"
 | 
			
		||||
serde = "1.0"
 | 
			
		||||
serde_derive = "1.0"
 | 
			
		||||
serde_json = "1.0"
 | 
			
		||||
vm = { path = "../ethcore/vm" }
 | 
			
		||||
 | 
			
		||||
[dev-dependencies]
 | 
			
		||||
 | 
			
		||||
@ -43,31 +43,9 @@ pub struct Informant {
 | 
			
		||||
	unmatched: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Informant {
 | 
			
		||||
	fn memory(&self) -> String {
 | 
			
		||||
		format!("\"0x{}\"", self.memory.to_hex())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn stack(&self) -> String {
 | 
			
		||||
		let items = self.stack.iter().map(|i| format!("\"0x{:x}\"", i)).collect::<Vec<_>>();
 | 
			
		||||
		format!("[{}]", items.join(","))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn storage(&self) -> String {
 | 
			
		||||
		let vals = self.storage.iter()
 | 
			
		||||
			.map(|(k, v)| format!("\"0x{:?}\": \"0x{:?}\"", k, v))
 | 
			
		||||
			.collect::<Vec<_>>();
 | 
			
		||||
		format!("{{{}}}", vals.join(","))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl vm::Informant for Informant {
 | 
			
		||||
	fn before_test(&mut self, name: &str, action: &str) {
 | 
			
		||||
		println!(
 | 
			
		||||
			"{{\"test\":\"{name}\",\"action\":\"{action}\"}}",
 | 
			
		||||
			name = name,
 | 
			
		||||
			action = action,
 | 
			
		||||
		);
 | 
			
		||||
		println!("{}", json!({"action": action, "test": name}));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn set_gas(&mut self, gas: U256) {
 | 
			
		||||
@ -81,24 +59,26 @@ impl vm::Informant for Informant {
 | 
			
		||||
					println!("{}", trace);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				println!(
 | 
			
		||||
					"{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}",
 | 
			
		||||
					output = success.output.to_hex(),
 | 
			
		||||
					gas = success.gas_used,
 | 
			
		||||
					time = display::as_micros(&success.time),
 | 
			
		||||
				)
 | 
			
		||||
				let success_msg = json!({
 | 
			
		||||
					"output": format!("0x{}", success.output.to_hex()),
 | 
			
		||||
					"gasUsed": format!("{:#x}", success.gas_used),
 | 
			
		||||
					"time": display::as_micros(&success.time),
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				println!("{}", success_msg)
 | 
			
		||||
			},
 | 
			
		||||
			Err(failure) => {
 | 
			
		||||
				for trace in failure.traces.unwrap_or_else(Vec::new) {
 | 
			
		||||
					println!("{}", trace);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				println!(
 | 
			
		||||
					"{{\"error\":\"{error}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}",
 | 
			
		||||
					error = display::escape_newlines(&failure.error),
 | 
			
		||||
					gas = failure.gas_used,
 | 
			
		||||
					time = display::as_micros(&failure.time),
 | 
			
		||||
				)
 | 
			
		||||
				let failure_msg = json!({
 | 
			
		||||
					"error": &failure.error.to_string(),
 | 
			
		||||
					"gasUsed": format!("{:#x}", failure.gas_used),
 | 
			
		||||
					"time": display::as_micros(&failure.time),
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				println!("{}", failure_msg)
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -123,19 +103,19 @@ impl trace::VMTracer for Informant {
 | 
			
		||||
	fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) {
 | 
			
		||||
		let info = ::evm::Instruction::from_u8(self.instruction).map(|i| i.info());
 | 
			
		||||
 | 
			
		||||
		let trace = format!(
 | 
			
		||||
			"{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"gasCost\":\"0x{gas_cost:x}\",\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}",
 | 
			
		||||
			pc = self.pc,
 | 
			
		||||
			op = self.instruction,
 | 
			
		||||
			name = info.map(|i| i.name).unwrap_or(""),
 | 
			
		||||
			gas = gas_used.saturating_add(self.gas_cost),
 | 
			
		||||
			gas_cost = self.gas_cost,
 | 
			
		||||
			memory = self.memory(),
 | 
			
		||||
			stack = self.stack(),
 | 
			
		||||
			storage = self.storage(),
 | 
			
		||||
			depth = self.depth,
 | 
			
		||||
		);
 | 
			
		||||
		self.traces.push(trace);
 | 
			
		||||
		let trace = json!({
 | 
			
		||||
			"pc": self.pc,
 | 
			
		||||
			"op": self.instruction,
 | 
			
		||||
			"opName": info.map(|i| i.name).unwrap_or(""),
 | 
			
		||||
			"gas": format!("{:#x}", gas_used.saturating_add(self.gas_cost)),
 | 
			
		||||
			"gasCost": format!("{:#x}", self.gas_cost),
 | 
			
		||||
			"memory": format!("0x{}", self.memory.to_hex()),
 | 
			
		||||
			"stack": self.stack,
 | 
			
		||||
			"storage": self.storage,
 | 
			
		||||
			"depth": self.depth,
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		self.traces.push(trace.to_string());
 | 
			
		||||
 | 
			
		||||
		self.unmatched = false;
 | 
			
		||||
		self.gas_used = gas_used;
 | 
			
		||||
@ -193,6 +173,23 @@ impl trace::VMTracer for Informant {
 | 
			
		||||
mod tests {
 | 
			
		||||
	use super::*;
 | 
			
		||||
	use info::tests::run_test;
 | 
			
		||||
	use serde_json;
 | 
			
		||||
 | 
			
		||||
	#[derive(Serialize, Deserialize, Debug, PartialEq)]
 | 
			
		||||
	#[serde(rename_all = "camelCase")]
 | 
			
		||||
	struct TestTrace {
 | 
			
		||||
		pc: usize,
 | 
			
		||||
		#[serde(rename = "op")]
 | 
			
		||||
		instruction: u8,
 | 
			
		||||
		op_name: String,
 | 
			
		||||
		#[serde(rename = "gas")]
 | 
			
		||||
		gas_used: U256,
 | 
			
		||||
		gas_cost: U256,
 | 
			
		||||
		memory: String,
 | 
			
		||||
		stack: Vec<U256>,
 | 
			
		||||
		storage: HashMap<H256, H256>,
 | 
			
		||||
		depth: usize,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn assert_traces_eq(
 | 
			
		||||
		a: &[String],
 | 
			
		||||
@ -204,7 +201,10 @@ mod tests {
 | 
			
		||||
		loop {
 | 
			
		||||
			match (ita.next(), itb.next()) {
 | 
			
		||||
				(Some(a), Some(b)) => {
 | 
			
		||||
					assert_eq!(a, b);
 | 
			
		||||
					// Compare both without worrying about the order of the fields
 | 
			
		||||
					let actual: TestTrace = serde_json::from_str(a).unwrap();
 | 
			
		||||
					let expected: TestTrace = serde_json::from_str(b).unwrap();
 | 
			
		||||
					assert_eq!(actual, expected);
 | 
			
		||||
					println!("{}", a);
 | 
			
		||||
				},
 | 
			
		||||
				(None, None) => return,
 | 
			
		||||
@ -280,7 +280,20 @@ mod tests {
 | 
			
		||||
{"pc":5,"op":88,"opName":"PC","gas":"0x2102","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","gasCost":"0x0","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2}
 | 
			
		||||
			"#,
 | 
			
		||||
"#,
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		run_test(
 | 
			
		||||
			Informant::default(),
 | 
			
		||||
			&compare_json,
 | 
			
		||||
			"3260D85554",
 | 
			
		||||
			0xffff,
 | 
			
		||||
			r#"
 | 
			
		||||
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","gasCost":"0x2","memory":"0x","stack":[],"storage":{},"depth":1}
 | 
			
		||||
{"pc":1,"op":96,"opName":"PUSH1","gas":"0xfffd","gasCost":"0x3","memory":"0x","stack":["0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":3,"op":85,"opName":"SSTORE","gas":"0xfffa","gasCost":"0x1388","memory":"0x","stack":["0x0","0xd8"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":4,"op":84,"opName":"SLOAD","gas":"0xec72","gasCost":"0x0","memory":"0x","stack":[],"storage":{"0x00000000000000000000000000000000000000000000000000000000000000d8":"0x0000000000000000000000000000000000000000000000000000000000000000"},"depth":1}
 | 
			
		||||
"#,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,3 @@ pub fn format_time(time: &Duration) -> String {
 | 
			
		||||
pub fn as_micros(time: &Duration) -> u64 {
 | 
			
		||||
	time.as_secs() * 1_000_000 + time.subsec_nanos() as u64 / 1_000
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn escape_newlines<D: ::std::fmt::Display>(s: D) -> String {
 | 
			
		||||
	format!("{}", s).replace("\r\n", "\n").replace('\n', "\\n")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -81,28 +81,14 @@ impl<Trace: Writer, Out: Writer> Informant<Trace, Out> {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<Trace: Writer, Out: Writer> Informant<Trace, Out> {
 | 
			
		||||
	fn stack(&self) -> String {
 | 
			
		||||
		let items = self.stack.iter().map(|i| format!("\"0x{:x}\"", i)).collect::<Vec<_>>();
 | 
			
		||||
		format!("[{}]", items.join(","))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn storage(&self) -> String {
 | 
			
		||||
		let vals = self.storage.iter()
 | 
			
		||||
			.map(|(k, v)| format!("\"0x{:?}\": \"0x{:?}\"", k, v))
 | 
			
		||||
			.collect::<Vec<_>>();
 | 
			
		||||
		format!("{{{}}}", vals.join(","))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<Trace: Writer, Out: Writer> vm::Informant for Informant<Trace, Out> {
 | 
			
		||||
	fn before_test(&mut self, name: &str, action: &str) {
 | 
			
		||||
		writeln!(
 | 
			
		||||
			&mut self.out_sink,
 | 
			
		||||
			"{{\"test\":\"{name}\",\"action\":\"{action}\"}}",
 | 
			
		||||
			name = name,
 | 
			
		||||
			action = action,
 | 
			
		||||
		).expect("The sink must be writeable.");
 | 
			
		||||
		let out_data = json!({
 | 
			
		||||
			"action": action,
 | 
			
		||||
			"test": name,
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		writeln!(&mut self.out_sink, "{}", out_data).expect("The sink must be writeable.");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn set_gas(&mut self, _gas: U256) {}
 | 
			
		||||
@ -113,26 +99,26 @@ impl<Trace: Writer, Out: Writer> vm::Informant for Informant<Trace, Out> {
 | 
			
		||||
 | 
			
		||||
		match result {
 | 
			
		||||
			Ok(success) => {
 | 
			
		||||
				writeln!(
 | 
			
		||||
					&mut trace_sink,
 | 
			
		||||
					"{{\"stateRoot\":\"{:?}\"}}", success.state_root
 | 
			
		||||
				).expect("The sink must be writeable.");
 | 
			
		||||
				writeln!(
 | 
			
		||||
					&mut out_sink,
 | 
			
		||||
					"{{\"output\":\"0x{output}\",\"gasUsed\":\"0x{gas:x}\",\"time\":{time}}}",
 | 
			
		||||
					output = success.output.to_hex(),
 | 
			
		||||
					gas = success.gas_used,
 | 
			
		||||
					time = display::as_micros(&success.time),
 | 
			
		||||
				).expect("The sink must be writeable.");
 | 
			
		||||
				let trace_data = json!({"stateRoot": success.state_root});
 | 
			
		||||
				writeln!(&mut trace_sink, "{}", trace_data)
 | 
			
		||||
					.expect("The sink must be writeable.");
 | 
			
		||||
 | 
			
		||||
				let out_data = json!({
 | 
			
		||||
					"output": format!("0x{}", success.output.to_hex()),
 | 
			
		||||
					"gasUsed": format!("{:#x}", success.gas_used),
 | 
			
		||||
					"time": display::as_micros(&success.time),
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				writeln!(&mut out_sink, "{}", out_data).expect("The sink must be writeable.");
 | 
			
		||||
			},
 | 
			
		||||
			Err(failure) => {
 | 
			
		||||
				writeln!(
 | 
			
		||||
					&mut out_sink,
 | 
			
		||||
					"{{\"error\":\"{error}\",\"gasUsed\":\"0x{gas:x}\",\"time\":{time}}}",
 | 
			
		||||
					error = display::escape_newlines(&failure.error),
 | 
			
		||||
					gas = failure.gas_used,
 | 
			
		||||
					time = display::as_micros(&failure.time),
 | 
			
		||||
				).expect("The sink must be writeable.");
 | 
			
		||||
				let out_data = json!({
 | 
			
		||||
					"error": &failure.error.to_string(),
 | 
			
		||||
					"gasUsed": format!("{:#x}", failure.gas_used),
 | 
			
		||||
					"time": display::as_micros(&failure.time),
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				writeln!(&mut out_sink, "{}", out_data).expect("The sink must be writeable.");
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -144,20 +130,17 @@ impl<Trace: Writer, Out: Writer> trace::VMTracer for Informant<Trace, Out> {
 | 
			
		||||
	fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool {
 | 
			
		||||
		let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info());
 | 
			
		||||
		self.instruction = instruction;
 | 
			
		||||
		let storage = self.storage();
 | 
			
		||||
		let stack = self.stack();
 | 
			
		||||
		let trace_data = json!({
 | 
			
		||||
			"pc": pc,
 | 
			
		||||
			"op": instruction,
 | 
			
		||||
			"opName": info.map(|i| i.name).unwrap_or(""),
 | 
			
		||||
			"gas": format!("{:#x}", current_gas),
 | 
			
		||||
			"stack": self.stack,
 | 
			
		||||
			"storage": self.storage,
 | 
			
		||||
			"depth": self.depth,
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		writeln!(
 | 
			
		||||
			&mut self.trace_sink,
 | 
			
		||||
			"{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}",
 | 
			
		||||
			pc = pc,
 | 
			
		||||
			op = instruction,
 | 
			
		||||
			name = info.map(|i| i.name).unwrap_or(""),
 | 
			
		||||
			gas = current_gas,
 | 
			
		||||
			stack = stack,
 | 
			
		||||
			storage = storage,
 | 
			
		||||
			depth = self.depth,
 | 
			
		||||
		).expect("The sink must be writeable.");
 | 
			
		||||
		writeln!(&mut self.trace_sink, "{}", trace_data).expect("The sink must be writeable.");
 | 
			
		||||
 | 
			
		||||
		true
 | 
			
		||||
	}
 | 
			
		||||
@ -232,8 +215,8 @@ pub mod tests {
 | 
			
		||||
			},
 | 
			
		||||
			"60F8d6",
 | 
			
		||||
			0xffff,
 | 
			
		||||
			r#"{"pc":0,"op":96,"opName":"PUSH1","gas":"0xffff","stack":[],"storage":{},"depth":1}
 | 
			
		||||
{"pc":2,"op":214,"opName":"","gas":"0xfffc","stack":["0xf8"],"storage":{},"depth":1}
 | 
			
		||||
			r#"{"depth":1,"gas":"0xffff","op":96,"opName":"PUSH1","pc":0,"stack":[],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfffc","op":214,"opName":"","pc":2,"stack":["0xf8"],"storage":{}}
 | 
			
		||||
"#,
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
@ -246,7 +229,7 @@ pub mod tests {
 | 
			
		||||
			},
 | 
			
		||||
			"F8d6",
 | 
			
		||||
			0xffff,
 | 
			
		||||
			r#"{"pc":0,"op":248,"opName":"","gas":"0xffff","stack":[],"storage":{},"depth":1}
 | 
			
		||||
			r#"{"depth":1,"gas":"0xffff","op":248,"opName":"","pc":0,"stack":[],"storage":{}}
 | 
			
		||||
"#,
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
@ -262,30 +245,30 @@ pub mod tests {
 | 
			
		||||
			},
 | 
			
		||||
			"32343434345830f138343438323439f0",
 | 
			
		||||
			0xffff,
 | 
			
		||||
			r#"{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","stack":[],"storage":{},"depth":1}
 | 
			
		||||
{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0xfffd","stack":["0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0xfffb","stack":["0x0","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0xfff9","stack":["0x0","0x0","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0xfff7","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":5,"op":88,"opName":"PC","gas":"0xfff5","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0xfff3","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":7,"op":241,"opName":"CALL","gas":"0xfff1","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":8,"op":56,"opName":"CODESIZE","gas":"0x9e21","stack":["0x1"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":9,"op":52,"opName":"CALLVALUE","gas":"0x9e1f","stack":["0x1","0x10"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":10,"op":52,"opName":"CALLVALUE","gas":"0x9e1d","stack":["0x1","0x10","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":11,"op":56,"opName":"CODESIZE","gas":"0x9e1b","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":12,"op":50,"opName":"ORIGIN","gas":"0x9e19","stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":13,"op":52,"opName":"CALLVALUE","gas":"0x9e17","stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":14,"op":57,"opName":"CODECOPY","gas":"0x9e15","stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":15,"op":240,"opName":"CREATE","gas":"0x9e0c","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0x210c","stack":[],"storage":{},"depth":2}
 | 
			
		||||
{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0x210a","stack":["0x0"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0x2108","stack":["0x0","0x0"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0x2106","stack":["0x0","0x0","0x0"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0x2104","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":5,"op":88,"opName":"PC","gas":"0x2102","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2}
 | 
			
		||||
{"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2}
 | 
			
		||||
			r#"{"depth":1,"gas":"0xffff","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfffd","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfffb","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff9","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff7","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff5","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff3","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff1","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e21","op":56,"opName":"CODESIZE","pc":8,"stack":["0x1"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e1f","op":52,"opName":"CALLVALUE","pc":9,"stack":["0x1","0x10"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e1d","op":52,"opName":"CALLVALUE","pc":10,"stack":["0x1","0x10","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e1b","op":56,"opName":"CODESIZE","pc":11,"stack":["0x1","0x10","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e19","op":50,"opName":"ORIGIN","pc":12,"stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e17","op":52,"opName":"CALLVALUE","pc":13,"stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e15","op":57,"opName":"CODECOPY","pc":14,"stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0x9e0c","op":240,"opName":"CREATE","pc":15,"stack":["0x1","0x10","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x210c","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x210a","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x2108","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x2106","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x2104","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x2102","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x2100","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}}
 | 
			
		||||
{"depth":2,"gas":"0x20fe","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{}}
 | 
			
		||||
"#,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -225,16 +225,16 @@ pub mod tests {
 | 
			
		||||
 | 
			
		||||
		assert_eq!(
 | 
			
		||||
			&String::from_utf8_lossy(&**res.lock().unwrap()),
 | 
			
		||||
r#"{"pc":0,"op":98,"opName":"PUSH3","gas":"0xffff","stack":[],"storage":{},"depth":1}
 | 
			
		||||
{"pc":4,"op":96,"opName":"PUSH1","gas":"0xfffc","stack":["0xaaaaaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":6,"op":96,"opName":"PUSH1","gas":"0xfff9","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":8,"op":80,"opName":"POP","gas":"0xfff6","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":9,"op":96,"opName":"PUSH1","gas":"0xfff4","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":11,"op":96,"opName":"PUSH1","gas":"0xfff1","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":13,"op":96,"opName":"PUSH1","gas":"0xffee","stack":["0xaaaaaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":15,"op":96,"opName":"PUSH1","gas":"0xffeb","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":17,"op":96,"opName":"PUSH1","gas":"0xffe8","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
{"pc":19,"op":96,"opName":"PUSH1","gas":"0xffe5","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
 | 
			
		||||
r#"{"depth":1,"gas":"0xffff","op":98,"opName":"PUSH3","pc":0,"stack":[],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfffc","op":96,"opName":"PUSH1","pc":4,"stack":["0xaaaaaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff9","op":96,"opName":"PUSH1","pc":6,"stack":["0xaaaaaa","0xaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff6","op":80,"opName":"POP","pc":8,"stack":["0xaaaaaa","0xaa","0xaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff4","op":96,"opName":"PUSH1","pc":9,"stack":["0xaaaaaa","0xaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xfff1","op":96,"opName":"PUSH1","pc":11,"stack":["0xaaaaaa","0xaa","0xaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xffee","op":96,"opName":"PUSH1","pc":13,"stack":["0xaaaaaa","0xaa","0xaa","0xaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xffeb","op":96,"opName":"PUSH1","pc":15,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xffe8","op":96,"opName":"PUSH1","pc":17,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}}
 | 
			
		||||
{"depth":1,"gas":"0xffe5","op":96,"opName":"PUSH1","pc":19,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}}
 | 
			
		||||
"#);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,8 @@ extern crate rustc_hex;
 | 
			
		||||
extern crate serde;
 | 
			
		||||
#[macro_use]
 | 
			
		||||
extern crate serde_derive;
 | 
			
		||||
#[macro_use]
 | 
			
		||||
extern crate serde_json;
 | 
			
		||||
extern crate docopt;
 | 
			
		||||
extern crate ethcore_transaction as transaction;
 | 
			
		||||
extern crate parity_bytes as bytes;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user