From 02e33c4f91864d3bfbd3ccbbbd4591c654c6afbf Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Thu, 4 Jul 2019 00:02:41 +1000 Subject: [PATCH] refactor: Related #9459 - evmbin: replace untyped json! macro with fully typed serde serialization using Rust structs (#10657) * fix: Replace multirust with rustup wince multirust is deprecated * docs: Update evmbin Rust docs and code comments * WIP: Add Response struct. Initial step using serde to serialize instead of hardcoding with JSON * fix: Update Response struct types to be string after formatting * fix: Fix move out of borrowed content error by cloning informant * refactor: Change from camelcase to snake case to fix linting errors * restore: Restore some code since now covered in separate PR #10658 * restore: Restore original Rustdocs of evmbin * WIP * add Clone type * add newlines to end of json files * remove uml file that was unintentionally commited * rename chain spec to state test JSON fle * remove log. fix indentation * revert: Restore indentation now handled by separate PR #10740 * remove state test json files as moved to PR #10742 * revert changes in info.rs since covered in PR #10742 * revert changes to main.rs since covered in PR #10742 * revert newlines back to master * revert newlines back to master2 * refactor: Rename Response to TraceData * fix: Remove Clone and replace with lifetimes. Update tests since not ordered * refactor: Change all json! to typed serde * docs: Update rustdocs. Remove fixme * fix: Add missing semicolons from printf * fix: Change style from unwrap to expect in evmbin/src/display/json.rs Co-Authored-By: Andronik Ordian * fix: Change style from unwrap to expect in evmbin/src/display/std_json.rs Co-Authored-By: Andronik Ordian * revert updating module comments as will be done in separate PR #10742 instead * review-fix: Remove useless reference * Remove unncessary use of format macro * Update evmbin/src/display/json.rs Co-Authored-By: Andronik Ordian * refactor: Update evmbin/src/display/json.rs with serialization in set_gas success Co-Authored-By: Andronik Ordian * refactor: Update evmbin/src/display/json.rs with serialization in set_gas failure Co-Authored-By: Andronik Ordian * refactor: Update evmbin/src/display/std_json.rs with serialization in finish for state root Co-Authored-By: Andronik Ordian * refactor: Update evmbin/src/display/std_json.rs with serialization in before_test Co-Authored-By: Andronik Ordian * refactor: Update evmbin/src/display/std_json.rs with serialization for state root Co-Authored-By: Andronik Ordian * refactor: Update evmbin/src/display/std_json.rs with serialization for finish success Co-Authored-By: Andronik Ordian * refactor: Update evmbin/src/display/std_json.rs with serialization for finish failure Co-Authored-By: Andronik Ordian * refactor: Rename structs and variables. Remove space. Simplify MessageInitial struct * refactor: Captialize expect message * revert to previous struct name TraceDataStateRoot * refactor: Simplify variable for consistency * Update accounts/ethstore/src/json/crypto.rs Co-Authored-By: David --- accounts/ethstore/src/json/crypto.rs | 2 +- evmbin/src/display/json.rs | 102 ++++++++++---- evmbin/src/display/std_json.rs | 199 ++++++++++++++++++--------- evmbin/src/info.rs | 20 +-- 4 files changed, 224 insertions(+), 99 deletions(-) diff --git a/accounts/ethstore/src/json/crypto.rs b/accounts/ethstore/src/json/crypto.rs index 34664f98b..a7315d7e5 100644 --- a/accounts/ethstore/src/json/crypto.rs +++ b/accounts/ethstore/src/json/crypto.rs @@ -41,7 +41,7 @@ impl str::FromStr for Crypto { impl From for String { fn from(c: Crypto) -> Self { - serde_json::to_string(&c).expect("serialization cannot fail, cause all crypto keys are strings") + serde_json::to_string(&c).expect("Serialization cannot fail, because all crypto keys are strings") } } diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index 449938eab..195e00c73 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -47,6 +47,42 @@ pub struct Informant { unmatched: bool, } +#[derive(Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TraceData<'a> { + pc: usize, + op: u8, + op_name: &'a str, + gas: &'a str, + gas_cost: &'a str, + memory: &'a str, + stack: &'a [U256], + storage: &'a HashMap, + depth: usize, +} + +#[derive(Serialize, Debug)] +pub struct MessageInitial<'a> { + action: &'a str, + test: &'a str, +} + +#[derive(Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct MessageSuccess<'a> { + output: &'a str, + gas_used: &'a str, + time: &'a u64, +} + +#[derive(Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct MessageFailure<'a> { + error: &'a str, + gas_used: &'a str, + time: &'a u64, +} + impl Informant { fn with_informant_in_depth(informant: &mut Informant, depth: usize, f: F) { if depth == 0 { @@ -59,17 +95,21 @@ impl Informant { fn informant_trace(informant: &Informant, gas_used: U256) -> String { let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info()); - json!({ - "pc": informant.pc, - "op": informant.instruction, - "opName": info.map(|i| i.name).unwrap_or(""), - "gas": format!("{:#x}", gas_used.saturating_add(informant.gas_cost)), - "gasCost": format!("{:#x}", informant.gas_cost), - "memory": format!("0x{}", informant.memory.to_hex()), - "stack": informant.stack, - "storage": informant.storage, - "depth": informant.depth, - }).to_string() + let trace_data = + TraceData { + pc: informant.pc, + op: informant.instruction, + op_name: info.map(|i| i.name).unwrap_or(""), + gas: &format!("{:#x}", gas_used.saturating_add(informant.gas_cost)), + gas_cost: &format!("{:#x}", informant.gas_cost), + memory: &format!("0x{}", informant.memory.to_hex()), + stack: &informant.stack, + storage: &informant.storage, + depth: informant.depth, + } + ; + + serde_json::to_string(&trace_data).expect("Serialization cannot fail; qed") } } @@ -77,7 +117,15 @@ impl vm::Informant for Informant { type Sink = (); fn before_test(&mut self, name: &str, action: &str) { - println!("{}", json!({"action": action, "test": name})); + let message_init = + MessageInitial { + action, + test: &name, + } + ; + + let s = serde_json::to_string(&message_init).expect("Serialization cannot fail; qed"); + println!("{}", s); } fn set_gas(&mut self, gas: U256) { @@ -93,26 +141,32 @@ impl vm::Informant for Informant { println!("{}", trace); } - let success_msg = json!({ - "output": format!("0x{}", success.output.to_hex()), - "gasUsed": format!("{:#x}", success.gas_used), - "time": display::as_micros(&success.time), - }); + let message_success = + MessageSuccess { + output: &format!("0x{}", success.output.to_hex()), + gas_used: &format!("{:#x}", success.gas_used), + time: &display::as_micros(&success.time), + } + ; - println!("{}", success_msg) + let s = serde_json::to_string(&message_success).expect("Serialization cannot fail; qed"); + println!("{}", s); }, Err(failure) => { for trace in failure.traces.unwrap_or_else(Vec::new) { println!("{}", trace); } - let failure_msg = json!({ - "error": &failure.error.to_string(), - "gasUsed": format!("{:#x}", failure.gas_used), - "time": display::as_micros(&failure.time), - }); + let message_failure = + MessageFailure { + error: &failure.error.to_string(), + gas_used: &format!("{:#x}", failure.gas_used), + time: &display::as_micros(&failure.time), + } + ; - println!("{}", failure_msg) + let s = serde_json::to_string(&message_failure).expect("Serialization cannot fail; qed"); + println!("{}", s); }, } } diff --git a/evmbin/src/display/std_json.rs b/evmbin/src/display/std_json.rs index 74d9e0040..1734c305e 100644 --- a/evmbin/src/display/std_json.rs +++ b/evmbin/src/display/std_json.rs @@ -64,6 +64,52 @@ pub struct Informant { out_sink: Out, } +#[derive(Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TraceData<'a> { + pc: usize, + op: u8, + op_name: &'a str, + gas: &'a str, + stack: &'a [U256], + storage: &'a HashMap, + depth: usize, +} + +#[derive(Serialize, Debug)] +pub struct MessageInitial<'a> { + action: &'a str, + test: &'a str, +} + +#[derive(Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct MessageSuccess<'a> { + output: &'a str, + gas_used: &'a str, + time: &'a u64, +} + +#[derive(Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct MessageFailure<'a> { + error: &'a str, + gas_used: &'a str, + time: &'a u64, +} + +#[derive(Serialize, Debug)] +pub struct DumpData<'a> { + root: &'a H256, + accounts: &'a pod_state::PodState, +} + +#[derive(Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TraceDataStateRoot<'a> { + state_root: &'a H256, +} + impl Default for Informant { fn default() -> Self { Self::new(io::stderr(), io::stdout()) @@ -95,7 +141,8 @@ impl Informant { storage: Default::default(), subinfos: Default::default(), subdepth: 0, - trace_sink, out_sink + trace_sink, + out_sink, } } @@ -108,12 +155,16 @@ impl Informant { } fn dump_state_into(trace_sink: &mut Trace, root: H256, end_state: &Option) { - if let Some(ref end_state) = end_state { - let dump_data = json!({ - "root": root, - "accounts": end_state, - }); - writeln!(trace_sink, "{}", dump_data).expect("The sink must be writeable."); + if let Some(ref end_state) = end_state { + let dump_data = + DumpData { + root: &root, + accounts: end_state, + } + ; + + let s = serde_json::to_string(&dump_data).expect("Serialization cannot fail; qed"); + writeln!(trace_sink, "{}", s).expect("The sink must be writeable."); } } @@ -124,12 +175,15 @@ impl vm::Informant for Informant { type Sink = (Trace, Out); fn before_test(&mut self, name: &str, action: &str) { - let out_data = json!({ - "action": action, - "test": name, - }); + let message_init = + MessageInitial { + action, + test: &name, + } + ; - writeln!(&mut self.out_sink, "{}", out_data).expect("The sink must be writeable."); + let s = serde_json::to_string(&message_init).expect("Serialization cannot fail; qed"); + writeln!(&mut self.out_sink, "{}", s).expect("The sink must be writeable."); } fn set_gas(&mut self, _gas: U256) {} @@ -137,34 +191,46 @@ impl vm::Informant for Informant { fn clone_sink(&self) -> Self::Sink { (self.trace_sink.clone(), self.out_sink.clone()) } + fn finish(result: vm::RunResult<::Output>, (ref mut trace_sink, ref mut out_sink): &mut Self::Sink) { match result { Ok(success) => { - let trace_data = json!({"stateRoot": success.state_root}); - writeln!(trace_sink, "{}", trace_data) - .expect("The sink must be writeable."); + let state_root_data = + TraceDataStateRoot { + state_root: &success.state_root, + } + ; + + let s = serde_json::to_string(&state_root_data).expect("Serialization cannot fail; qed"); + writeln!(trace_sink, "{}", s).expect("The sink must be writeable."); Self::dump_state_into(trace_sink, success.state_root, &success.end_state); - let out_data = json!({ - "output": format!("0x{}", success.output.to_hex()), - "gasUsed": format!("{:#x}", success.gas_used), - "time": display::as_micros(&success.time), - }); + let message_success = + MessageSuccess { + output: &format!("0x{}", success.output.to_hex()), + gas_used: &format!("{:#x}", success.gas_used), + time: &display::as_micros(&success.time), + } + ; - writeln!(out_sink, "{}", out_data).expect("The sink must be writeable."); + let s = serde_json::to_string(&message_success).expect("Serialization cannot fail; qed"); + writeln!(out_sink, "{}", s).expect("The sink must be writeable."); }, Err(failure) => { - let out_data = json!({ - "error": &failure.error.to_string(), - "gasUsed": format!("{:#x}", failure.gas_used), - "time": display::as_micros(&failure.time), - }); + let message_failure = + MessageFailure { + error: &failure.error.to_string(), + gas_used: &format!("{:#x}", failure.gas_used), + time: &display::as_micros(&failure.time), + } + ; Self::dump_state_into(trace_sink, failure.state_root, &failure.end_state); - writeln!(out_sink, "{}", out_data).expect("The sink must be writeable."); + let s = serde_json::to_string(&message_failure).expect("Serialization cannot fail; qed"); + writeln!(out_sink, "{}", s).expect("The sink must be writeable."); }, } } @@ -178,17 +244,22 @@ impl trace::VMTracer for Informant { Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| { let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info()); informant.instruction = instruction; - let trace_data = json!({ - "pc": pc, - "op": instruction, - "opName": info.map(|i| i.name).unwrap_or(""), - "gas": format!("{:#x}", current_gas), - "stack": informant.stack, - "storage": informant.storage, - "depth": informant.depth, - }); - writeln!(&mut informant.trace_sink, "{}", trace_data).expect("The sink must be writeable."); + let trace_data = + TraceData { + pc: pc, + op: instruction, + op_name: info.map(|i| i.name).unwrap_or(""), + gas: &format!("{:#x}", current_gas), + stack: &informant.stack, + storage: &informant.storage, + depth: informant.depth, + } + ; + + let s = serde_json::to_string(&trace_data).expect("Serialization cannot fail; qed"); + + writeln!(&mut informant.trace_sink, "{}", s).expect("The sink must be writeable."); }); true } @@ -279,8 +350,8 @@ pub mod tests { }, "60F8d6", 0xffff, - 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":{}} + 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} "#, ); @@ -293,7 +364,7 @@ pub mod tests { }, "F8d6", 0xffff, - r#"{"depth":1,"gas":"0xffff","op":248,"opName":"","pc":0,"stack":[],"storage":{}} + r#"{"pc":0,"op":248,"opName":"","gas":"0xffff","stack":[],"storage":{},"depth":1} "#, ); } @@ -309,30 +380,30 @@ pub mod tests { }, "32343434345830f138343438323439f0", 0xffff, - 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":{}} + 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} "#, ) } diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index 9090c5377..ca068c36b 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -256,16 +256,16 @@ pub mod tests { assert_eq!( &String::from_utf8_lossy(&**res.lock().unwrap()), -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":{}} +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} "#); } }