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 <write@reusable.software>

* fix: Change style from unwrap to expect in evmbin/src/display/std_json.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* 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 <write@reusable.software>

* refactor: Update evmbin/src/display/json.rs with serialization in set_gas success

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/json.rs with serialization in set_gas failure

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization in finish for state root

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization in before_test

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization for state root

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization for finish success

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization for finish failure

Co-Authored-By: Andronik Ordian <write@reusable.software>

* 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 <dvdplm@gmail.com>
This commit is contained in:
Luke Schoen 2019-07-04 00:02:41 +10:00 committed by David
parent 8d24b4e804
commit 02e33c4f91
4 changed files with 224 additions and 99 deletions

View File

@ -41,7 +41,7 @@ impl str::FromStr for Crypto {
impl From<Crypto> for String { impl From<Crypto> for String {
fn from(c: Crypto) -> Self { 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")
} }
} }

View File

@ -47,6 +47,42 @@ pub struct Informant {
unmatched: bool, 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<H256, H256>,
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 { impl Informant {
fn with_informant_in_depth<F: Fn(&mut Informant)>(informant: &mut Informant, depth: usize, f: F) { fn with_informant_in_depth<F: Fn(&mut Informant)>(informant: &mut Informant, depth: usize, f: F) {
if depth == 0 { if depth == 0 {
@ -59,17 +95,21 @@ impl Informant {
fn informant_trace(informant: &Informant, gas_used: U256) -> String { fn informant_trace(informant: &Informant, gas_used: U256) -> String {
let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info()); let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info());
json!({ let trace_data =
"pc": informant.pc, TraceData {
"op": informant.instruction, pc: informant.pc,
"opName": info.map(|i| i.name).unwrap_or(""), op: informant.instruction,
"gas": format!("{:#x}", gas_used.saturating_add(informant.gas_cost)), op_name: info.map(|i| i.name).unwrap_or(""),
"gasCost": format!("{:#x}", informant.gas_cost), gas: &format!("{:#x}", gas_used.saturating_add(informant.gas_cost)),
"memory": format!("0x{}", informant.memory.to_hex()), gas_cost: &format!("{:#x}", informant.gas_cost),
"stack": informant.stack, memory: &format!("0x{}", informant.memory.to_hex()),
"storage": informant.storage, stack: &informant.stack,
"depth": informant.depth, storage: &informant.storage,
}).to_string() 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 = (); type Sink = ();
fn before_test(&mut self, name: &str, action: &str) { 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) { fn set_gas(&mut self, gas: U256) {
@ -93,26 +141,32 @@ impl vm::Informant for Informant {
println!("{}", trace); println!("{}", trace);
} }
let success_msg = json!({ let message_success =
"output": format!("0x{}", success.output.to_hex()), MessageSuccess {
"gasUsed": format!("{:#x}", success.gas_used), output: &format!("0x{}", success.output.to_hex()),
"time": display::as_micros(&success.time), 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) => { Err(failure) => {
for trace in failure.traces.unwrap_or_else(Vec::new) { for trace in failure.traces.unwrap_or_else(Vec::new) {
println!("{}", trace); println!("{}", trace);
} }
let failure_msg = json!({ let message_failure =
"error": &failure.error.to_string(), MessageFailure {
"gasUsed": format!("{:#x}", failure.gas_used), error: &failure.error.to_string(),
"time": display::as_micros(&failure.time), 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);
}, },
} }
} }

View File

@ -64,6 +64,52 @@ pub struct Informant<Trace, Out> {
out_sink: Out, 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<H256, H256>,
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<io::Stderr, io::Stdout> { impl Default for Informant<io::Stderr, io::Stdout> {
fn default() -> Self { fn default() -> Self {
Self::new(io::stderr(), io::stdout()) Self::new(io::stderr(), io::stdout())
@ -95,7 +141,8 @@ impl<Trace: Writer, Out: Writer> Informant<Trace, Out> {
storage: Default::default(), storage: Default::default(),
subinfos: Default::default(), subinfos: Default::default(),
subdepth: 0, subdepth: 0,
trace_sink, out_sink trace_sink,
out_sink,
} }
} }
@ -108,12 +155,16 @@ impl<Trace: Writer, Out: Writer> Informant<Trace, Out> {
} }
fn dump_state_into(trace_sink: &mut Trace, root: H256, end_state: &Option<pod_state::PodState>) { fn dump_state_into(trace_sink: &mut Trace, root: H256, end_state: &Option<pod_state::PodState>) {
if let Some(ref end_state) = end_state { if let Some(ref end_state) = end_state {
let dump_data = json!({ let dump_data =
"root": root, DumpData {
"accounts": end_state, root: &root,
}); accounts: end_state,
writeln!(trace_sink, "{}", dump_data).expect("The sink must be writeable."); }
;
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<Trace: Writer, Out: Writer> vm::Informant for Informant<Trace, Out> {
type Sink = (Trace, Out); type Sink = (Trace, Out);
fn before_test(&mut self, name: &str, action: &str) { fn before_test(&mut self, name: &str, action: &str) {
let out_data = json!({ let message_init =
"action": action, MessageInitial {
"test": name, 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) {} fn set_gas(&mut self, _gas: U256) {}
@ -137,34 +191,46 @@ impl<Trace: Writer, Out: Writer> vm::Informant for Informant<Trace, Out> {
fn clone_sink(&self) -> Self::Sink { fn clone_sink(&self) -> Self::Sink {
(self.trace_sink.clone(), self.out_sink.clone()) (self.trace_sink.clone(), self.out_sink.clone())
} }
fn finish(result: vm::RunResult<<Self as trace::VMTracer>::Output>, (ref mut trace_sink, ref mut out_sink): &mut Self::Sink) { fn finish(result: vm::RunResult<<Self as trace::VMTracer>::Output>, (ref mut trace_sink, ref mut out_sink): &mut Self::Sink) {
match result { match result {
Ok(success) => { Ok(success) => {
let trace_data = json!({"stateRoot": success.state_root}); let state_root_data =
writeln!(trace_sink, "{}", trace_data) TraceDataStateRoot {
.expect("The sink must be writeable."); 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); Self::dump_state_into(trace_sink, success.state_root, &success.end_state);
let out_data = json!({ let message_success =
"output": format!("0x{}", success.output.to_hex()), MessageSuccess {
"gasUsed": format!("{:#x}", success.gas_used), output: &format!("0x{}", success.output.to_hex()),
"time": display::as_micros(&success.time), 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) => { Err(failure) => {
let out_data = json!({ let message_failure =
"error": &failure.error.to_string(), MessageFailure {
"gasUsed": format!("{:#x}", failure.gas_used), error: &failure.error.to_string(),
"time": display::as_micros(&failure.time), 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); 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: Writer, Out: Writer> trace::VMTracer for Informant<Trace, Out> {
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| { Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| {
let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info()); let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info());
informant.instruction = instruction; 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 true
} }
@ -279,8 +350,8 @@ pub mod tests {
}, },
"60F8d6", "60F8d6",
0xffff, 0xffff,
r#"{"depth":1,"gas":"0xffff","op":96,"opName":"PUSH1","pc":0,"stack":[],"storage":{}} r#"{"pc":0,"op":96,"opName":"PUSH1","gas":"0xffff","stack":[],"storage":{},"depth":1}
{"depth":1,"gas":"0xfffc","op":214,"opName":"","pc":2,"stack":["0xf8"],"storage":{}} {"pc":2,"op":214,"opName":"","gas":"0xfffc","stack":["0xf8"],"storage":{},"depth":1}
"#, "#,
); );
@ -293,7 +364,7 @@ pub mod tests {
}, },
"F8d6", "F8d6",
0xffff, 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", "32343434345830f138343438323439f0",
0xffff, 0xffff,
r#"{"depth":1,"gas":"0xffff","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}} r#"{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","stack":[],"storage":{},"depth":1}
{"depth":1,"gas":"0xfffd","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}} {"pc":1,"op":52,"opName":"CALLVALUE","gas":"0xfffd","stack":["0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfffb","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}} {"pc":2,"op":52,"opName":"CALLVALUE","gas":"0xfffb","stack":["0x0","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff9","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}} {"pc":3,"op":52,"opName":"CALLVALUE","gas":"0xfff9","stack":["0x0","0x0","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff7","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}} {"pc":4,"op":52,"opName":"CALLVALUE","gas":"0xfff7","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff5","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}} {"pc":5,"op":88,"opName":"PC","gas":"0xfff5","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff3","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}} {"pc":6,"op":48,"opName":"ADDRESS","gas":"0xfff3","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff1","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{}} {"pc":7,"op":241,"opName":"CALL","gas":"0xfff1","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e21","op":56,"opName":"CODESIZE","pc":8,"stack":["0x1"],"storage":{}} {"pc":8,"op":56,"opName":"CODESIZE","gas":"0x9e21","stack":["0x1"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e1f","op":52,"opName":"CALLVALUE","pc":9,"stack":["0x1","0x10"],"storage":{}} {"pc":9,"op":52,"opName":"CALLVALUE","gas":"0x9e1f","stack":["0x1","0x10"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e1d","op":52,"opName":"CALLVALUE","pc":10,"stack":["0x1","0x10","0x0"],"storage":{}} {"pc":10,"op":52,"opName":"CALLVALUE","gas":"0x9e1d","stack":["0x1","0x10","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e1b","op":56,"opName":"CODESIZE","pc":11,"stack":["0x1","0x10","0x0","0x0"],"storage":{}} {"pc":11,"op":56,"opName":"CODESIZE","gas":"0x9e1b","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e19","op":50,"opName":"ORIGIN","pc":12,"stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{}} {"pc":12,"op":50,"opName":"ORIGIN","gas":"0x9e19","stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e17","op":52,"opName":"CALLVALUE","pc":13,"stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{}} {"pc":13,"op":52,"opName":"CALLVALUE","gas":"0x9e17","stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e15","op":57,"opName":"CODECOPY","pc":14,"stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{}} {"pc":14,"op":57,"opName":"CODECOPY","gas":"0x9e15","stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{},"depth":1}
{"depth":1,"gas":"0x9e0c","op":240,"opName":"CREATE","pc":15,"stack":["0x1","0x10","0x0","0x0"],"storage":{}} {"pc":15,"op":240,"opName":"CREATE","gas":"0x9e0c","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
{"depth":2,"gas":"0x210c","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}} {"pc":0,"op":50,"opName":"ORIGIN","gas":"0x210c","stack":[],"storage":{},"depth":2}
{"depth":2,"gas":"0x210a","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}} {"pc":1,"op":52,"opName":"CALLVALUE","gas":"0x210a","stack":["0x0"],"storage":{},"depth":2}
{"depth":2,"gas":"0x2108","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}} {"pc":2,"op":52,"opName":"CALLVALUE","gas":"0x2108","stack":["0x0","0x0"],"storage":{},"depth":2}
{"depth":2,"gas":"0x2106","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}} {"pc":3,"op":52,"opName":"CALLVALUE","gas":"0x2106","stack":["0x0","0x0","0x0"],"storage":{},"depth":2}
{"depth":2,"gas":"0x2104","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}} {"pc":4,"op":52,"opName":"CALLVALUE","gas":"0x2104","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
{"depth":2,"gas":"0x2102","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}} {"pc":5,"op":88,"opName":"PC","gas":"0x2102","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
{"depth":2,"gas":"0x2100","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}} {"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2}
{"depth":2,"gas":"0x20fe","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{}} {"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2}
"#, "#,
) )
} }

View File

@ -256,16 +256,16 @@ pub mod tests {
assert_eq!( assert_eq!(
&String::from_utf8_lossy(&**res.lock().unwrap()), &String::from_utf8_lossy(&**res.lock().unwrap()),
r#"{"depth":1,"gas":"0xffff","op":98,"opName":"PUSH3","pc":0,"stack":[],"storage":{}} r#"{"pc":0,"op":98,"opName":"PUSH3","gas":"0xffff","stack":[],"storage":{},"depth":1}
{"depth":1,"gas":"0xfffc","op":96,"opName":"PUSH1","pc":4,"stack":["0xaaaaaa"],"storage":{}} {"pc":4,"op":96,"opName":"PUSH1","gas":"0xfffc","stack":["0xaaaaaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff9","op":96,"opName":"PUSH1","pc":6,"stack":["0xaaaaaa","0xaa"],"storage":{}} {"pc":6,"op":96,"opName":"PUSH1","gas":"0xfff9","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff6","op":80,"opName":"POP","pc":8,"stack":["0xaaaaaa","0xaa","0xaa"],"storage":{}} {"pc":8,"op":80,"opName":"POP","gas":"0xfff6","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff4","op":96,"opName":"PUSH1","pc":9,"stack":["0xaaaaaa","0xaa"],"storage":{}} {"pc":9,"op":96,"opName":"PUSH1","gas":"0xfff4","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xfff1","op":96,"opName":"PUSH1","pc":11,"stack":["0xaaaaaa","0xaa","0xaa"],"storage":{}} {"pc":11,"op":96,"opName":"PUSH1","gas":"0xfff1","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xffee","op":96,"opName":"PUSH1","pc":13,"stack":["0xaaaaaa","0xaa","0xaa","0xaa"],"storage":{}} {"pc":13,"op":96,"opName":"PUSH1","gas":"0xffee","stack":["0xaaaaaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xffeb","op":96,"opName":"PUSH1","pc":15,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}} {"pc":15,"op":96,"opName":"PUSH1","gas":"0xffeb","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xffe8","op":96,"opName":"PUSH1","pc":17,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}} {"pc":17,"op":96,"opName":"PUSH1","gas":"0xffe8","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"depth":1,"gas":"0xffe5","op":96,"opName":"PUSH1","pc":19,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}} {"pc":19,"op":96,"opName":"PUSH1","gas":"0xffe5","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
"#); "#);
} }
} }