From 02e33c4f91864d3bfbd3ccbbbd4591c654c6afbf Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Thu, 4 Jul 2019 00:02:41 +1000 Subject: [PATCH 1/6] 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 | 201 ++++++++++++++++++--------- evmbin/src/info.rs | 20 +-- 4 files changed, 225 insertions(+), 100 deletions(-) diff --git a/accounts/ethstore/src/json/crypto.rs b/accounts/ethstore/src/json/crypto.rs index 34664f98b0e..a7315d7e5c9 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 449938eab56..195e00c7379 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 74d9e0040a2..1734c305e24 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 9090c5377e6..ca068c36b0d 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} "#); } } From 09edb94d5355759a03a1c982b29035f02af5642c Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Thu, 4 Jul 2019 01:44:58 +1000 Subject: [PATCH 2/6] tests: Relates to #10655: Test instructions for Readme (#10835) * tests: Relates to #10655: Test instructions for Readme * Add instructions to run tests * Update instructions to view docs * fix: Fix link to package list * fix: Move link to line about title of package list * Update README.md --- README.md | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 50715eaf1c6..e4aec89927a 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,12 @@ 3.2 [Building from Source Code](#chapter-0032)
3.3 [Simple One-Line Installer for Mac and Linux](#chapter-0033)
3.4 [Starting Parity Ethereum](#chapter-0034) -4. [Documentation](#chapter-004) -5. [Toolchain](#chapter-005) -6. [Community](#chapter-006) -7. [Contributing](#chapter-007) -8. [License](#chapter-008) +4. [Testing](#chapter-004) +5. [Documentation](#chapter-005) +6. [Toolchain](#chapter-006) +7. [Community](#chapter-007) +8. [Contributing](#chapter-008) +9. [License](#chapter-009) ## 1. Description @@ -148,7 +149,25 @@ To start Parity Ethereum as a regular user using `systemd` init: 2. Copy release to bin folder, write `sudo install ./target/release/parity /usr/bin/parity` 3. To configure Parity Ethereum, write a `/etc/parity/config.toml` config file, see [Configuring Parity Ethereum](https://paritytech.github.io/wiki/Configuring-Parity) for details. -## 4. Documentation +## 4. Testing + +You can run tests with the following commands: + +* **All** packages + ``` + cargo test --all + ``` + +* Specific package + ``` + cargo test --package + ``` + +Replace `` with one of the packages from the [package list](#package-list) (e.g. `cargo test --package evmbin`). + +You can show your logs in the test output by passing `--nocapture` (i.e. `cargo test --package evmbin -- --nocapture`) + +## 5. Documentation Official website: https://parity.io @@ -160,16 +179,20 @@ You can generate documentation for Parity Ethereum Rust packages that automatica * **All** packages ``` - cargo doc --open + cargo doc --document-private-items --open ``` * Specific package ``` - cargo doc --package --open + cargo doc --package -- --document-private-items --open ``` +Use`--document-private-items` to also view private documentation and `--no-deps` to exclude building documentation for dependencies. + Replacing `` with one of the following from the details section below (i.e. `cargo doc --package parity-ethereum --open`): + +**Package List**

* Parity Ethereum (EthCore) Client Application @@ -330,7 +353,7 @@ Example (generic documentation comment): /// ``` -## 5. Toolchain +## 6. Toolchain In addition to the Parity Ethereum client, there are additional tools in this repository available: @@ -342,7 +365,7 @@ In addition to the Parity Ethereum client, there are additional tools in this re The following tool is available in a separate repository: - [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum Encoding of Function Calls. [Docs here](https://crates.io/crates/ethabi) -## 6. Community +## 7. Community ### Join the chat! @@ -355,7 +378,7 @@ Questions? Get in touch with us on Gitter: Alternatively, join our community on Matrix: [![Riot: +Parity](https://img.shields.io/badge/riot-%2Bparity%3Amatrix.parity.io-orange.svg)](https://riot.im/app/#/group/+parity:matrix.parity.io) -## 7. Contributing +## 8. Contributing An introduction has been provided in the ["So You Want to be a Core Developer" presentation slides by Hernando Castano](http://tiny.cc/contrib-to-parity-eth). Additional guidelines are provided in [CONTRIBUTING](./.github/CONTRIBUTING.md). @@ -363,6 +386,6 @@ An introduction has been provided in the ["So You Want to be a Core Developer" p [CODE_OF_CONDUCT](./.github/CODE_OF_CONDUCT.md) -## 8. License +## 9. License [LICENSE](./LICENSE) From 582a4ea33962479524a1eed83e3b67458816cb65 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 4 Jul 2019 13:43:20 +0200 Subject: [PATCH 3/6] Break circular dependency between Client and Engine (part 1) (#10833) * First draft: pass the parent block header to on_close_block * typos and cleanup * whitespace * Store parent in ClosedBlock as well so it can be reopen()'d * Don't pass parent when reopening a block * Remove the unused ancestry param --- ethcore/src/block.rs | 49 ++++++++++------------ ethcore/src/client/client.rs | 2 - ethcore/src/client/test_client.rs | 1 - ethcore/src/engines/authority_round/mod.rs | 49 +++++++++------------- ethcore/src/engines/basic_authority.rs | 2 +- ethcore/src/engines/clique/mod.rs | 7 +++- ethcore/src/engines/clique/tests.rs | 3 +- ethcore/src/engines/instant_seal.rs | 2 +- ethcore/src/engines/mod.rs | 7 +++- ethcore/src/engines/null_engine.rs | 6 ++- ethcore/src/ethereum/ethash.rs | 8 ++-- ethcore/src/miner/miner.rs | 2 +- ethcore/src/test_helpers.rs | 1 - ethcore/src/tests/client.rs | 2 +- ethcore/src/tests/trace.rs | 3 -- 15 files changed, 64 insertions(+), 80 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index d2cb128c48c..7eb81f4238d 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -22,13 +22,13 @@ //! and can be appended to with transactions and uncles. //! //! When ready, `OpenBlock` can be closed and turned into a `ClosedBlock`. A `ClosedBlock` can -//! be reopend again by a miner under certain circumstances. On block close, state commit is +//! be re-opend again by a miner under certain circumstances. On block close, state commit is //! performed. //! //! `LockedBlock` is a version of a `ClosedBlock` that cannot be reopened. It can be sealed //! using an engine. //! -//! `ExecutedBlock` is an underlaying data structure used by all structs above to store block +//! `ExecutedBlock` is an underlying data structure used by all structs above to store block //! related info. use std::{cmp, ops}; @@ -52,7 +52,7 @@ use vm::{EnvInfo, LastHashes}; use hash::keccak; use rlp::{RlpStream, Encodable, encode_list}; use types::transaction::{SignedTransaction, Error as TransactionError}; -use types::header::{Header, ExtendedHeader}; +use types::header::Header; use types::receipt::{Receipt, TransactionOutcome}; /// Block that is ready for transactions to be added. @@ -62,6 +62,7 @@ use types::receipt::{Receipt, TransactionOutcome}; pub struct OpenBlock<'x> { block: ExecutedBlock, engine: &'x dyn Engine, + parent: Header, } /// Just like `OpenBlock`, except that we've applied `Engine::on_close_block`, finished up the non-seal header fields, @@ -72,6 +73,7 @@ pub struct OpenBlock<'x> { pub struct ClosedBlock { block: ExecutedBlock, unclosed_state: State, + parent: Header, } /// Just like `ClosedBlock` except that we can't reopen it and it's faster. @@ -102,7 +104,7 @@ pub struct ExecutedBlock { pub receipts: Vec, /// Hashes of already executed transactions. pub transactions_set: HashSet, - /// Underlaying state. + /// Underlying state. pub state: State, /// Transaction traces. pub traces: Tracing, @@ -119,13 +121,13 @@ impl ExecutedBlock { uncles: Default::default(), receipts: Default::default(), transactions_set: Default::default(), - state: state, + state, traces: if tracing { Tracing::enabled() } else { Tracing::Disabled }, - last_hashes: last_hashes, + last_hashes, } } @@ -162,7 +164,7 @@ pub trait Drain { impl<'x> OpenBlock<'x> { /// Create a new `OpenBlock` ready for transaction pushing. - pub fn new<'a, I: IntoIterator>( + pub fn new<'a>( engine: &'x dyn Engine, factories: Factories, tracing: bool, @@ -173,14 +175,11 @@ impl<'x> OpenBlock<'x> { gas_range_target: (U256, U256), extra_data: Bytes, is_epoch_begin: bool, - ancestry: I, ) -> Result { let number = parent.number() + 1; let state = State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce(number), factories)?; - let mut r = OpenBlock { - block: ExecutedBlock::new(state, last_hashes, tracing), - engine: engine, - }; + + let mut r = OpenBlock { block: ExecutedBlock::new(state, last_hashes, tracing), engine, parent: parent.clone() }; r.block.header.set_parent_hash(parent.hash()); r.block.header.set_number(number); @@ -195,7 +194,7 @@ impl<'x> OpenBlock<'x> { engine.populate_from_parent(&mut r.block.header, parent); engine.machine().on_new_block(&mut r.block)?; - engine.on_new_block(&mut r.block, is_epoch_begin, &mut ancestry.into_iter())?; + engine.on_new_block(&mut r.block, is_epoch_begin)?; Ok(r) } @@ -297,19 +296,20 @@ impl<'x> OpenBlock<'x> { /// Turn this into a `ClosedBlock`. pub fn close(self) -> Result { let unclosed_state = self.block.state.clone(); + let parent = self.parent.clone(); let locked = self.close_and_lock()?; Ok(ClosedBlock { block: locked.block, unclosed_state, + parent, }) } /// Turn this into a `LockedBlock`. pub fn close_and_lock(self) -> Result { let mut s = self; - - s.engine.on_close_block(&mut s.block)?; + s.engine.on_close_block(&mut s.block, &s.parent)?; s.block.state.commit()?; s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes()))); @@ -378,10 +378,8 @@ impl ClosedBlock { // revert rewards (i.e. set state back at last transaction's state). let mut block = self.block; block.state = self.unclosed_state; - OpenBlock { - block: block, - engine: engine, - } + let parent = self.parent; + OpenBlock { block, engine, parent } } } @@ -479,7 +477,6 @@ pub(crate) fn enact( last_hashes: Arc, factories: Factories, is_epoch_begin: bool, - ancestry: &mut dyn Iterator, ) -> Result { // For trace log let trace_state = if log_enabled!(target: "enact", ::log::Level::Trace) { @@ -501,7 +498,6 @@ pub(crate) fn enact( (3141562.into(), 31415620.into()), vec![], is_epoch_begin, - ancestry, )?; if let Some(ref s) = trace_state { @@ -522,7 +518,7 @@ pub(crate) fn enact( b.close_and_lock() } -/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header +/// Enact the block given by `block_bytes` using `engine` on the database `db` with the given `parent` block header pub fn enact_verified( block: PreverifiedBlock, engine: &dyn Engine, @@ -532,7 +528,6 @@ pub fn enact_verified( last_hashes: Arc, factories: Factories, is_epoch_begin: bool, - ancestry: &mut dyn Iterator, ) -> Result { enact( @@ -546,7 +541,6 @@ pub fn enact_verified( last_hashes, factories, is_epoch_begin, - ancestry, ) } @@ -608,7 +602,6 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, - None, )?; b.populate_from(&header); @@ -643,7 +636,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b = b.close_and_lock().unwrap(); let _ = b.seal(&*spec.engine, vec![]); } @@ -657,7 +650,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap() + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap() .close_and_lock().unwrap().seal(engine, vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain().state.drop().1; @@ -682,7 +675,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); let mut uncle1_header = Header::new(); uncle1_header.set_extra_data(b"uncle1".to_vec()); let mut uncle2_header = Header::new(); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 7678314f0ee..e9847437c9d 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -407,7 +407,6 @@ impl Importer { last_hashes, client.factories.clone(), is_epoch_begin, - &mut chain.ancestry_with_metadata_iter(*header.parent_hash()), ); let mut locked_block = match enact_result { @@ -2361,7 +2360,6 @@ impl PrepareOpenBlock for Client { gas_range_target, extra_data, is_epoch_begin, - chain.ancestry_with_metadata_iter(best_header.hash()), )?; // Add uncles diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 9eb1b14eb8f..7894a665de3 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -417,7 +417,6 @@ impl PrepareOpenBlock for TestBlockChainClient { gas_range_target, extra_data, false, - None, )?; // TODO [todr] Override timestamp for predictability open_block.set_timestamp(*self.latest_block_timestamp.read()); diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 97305efad84..cb9b8a49954 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1211,7 +1211,6 @@ impl Engine for AuthorityRound { &self, block: &mut ExecutedBlock, epoch_begin: bool, - _ancestry: &mut dyn Iterator, ) -> Result<(), Error> { // with immediate transitions, we don't use the epoch mechanism anyway. // the genesis is always considered an epoch, but we ignore it intentionally. @@ -1236,26 +1235,18 @@ impl Engine for AuthorityRound { } /// Apply the block reward on finalisation of the block. - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block( + &self, + block: &mut ExecutedBlock, + parent: &Header, + ) -> Result<(), Error> { let mut beneficiaries = Vec::new(); if block.header.number() >= self.empty_steps_transition { let empty_steps = if block.header.seal().is_empty() { // this is a new block, calculate rewards based on the empty steps messages we have accumulated - let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) { - Some(client) => client, - None => { - debug!(target: "engine", "Unable to close block: missing client ref."); - return Err(EngineError::RequiresClient.into()) - }, - }; - - let parent = client.block_header(::client::BlockId::Hash(*block.header.parent_hash())) - .expect("hash is from parent; parent header must exist; qed") - .decode()?; - - let parent_step = header_step(&parent, self.empty_steps_transition)?; + let parent_step = header_step(parent, self.empty_steps_transition)?; let current_step = self.step.inner.load(); - self.empty_steps(parent_step.into(), current_step.into(), parent.hash()) + self.empty_steps(parent_step, current_step, parent.hash()) } else { // we're verifying a block, extract empty steps from the seal header_empty_steps(&block.header)? @@ -1707,9 +1698,9 @@ mod tests { let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b1 = b1.close_and_lock().unwrap(); - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b2 = b2.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); @@ -1741,9 +1732,9 @@ mod tests { let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b1 = b1.close_and_lock().unwrap(); - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b2 = b2.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); @@ -1991,7 +1982,7 @@ mod tests { engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b1 = b1.close_and_lock().unwrap(); // the block is empty so we don't seal and instead broadcast an empty step message @@ -2029,7 +2020,7 @@ mod tests { engine.register_client(Arc::downgrade(&client) as _); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps @@ -2038,7 +2029,7 @@ mod tests { engine.step(); // step 3 - let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); b2.push_transaction(Transaction { action: Action::Create, nonce: U256::from(0), @@ -2082,7 +2073,7 @@ mod tests { engine.register_client(Arc::downgrade(&client) as _); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps @@ -2091,7 +2082,7 @@ mod tests { engine.step(); // step 3 - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b2 = b2.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); assert_eq!(engine.generate_seal(&b2, &genesis_header), Seal::None); @@ -2099,7 +2090,7 @@ mod tests { // step 4 // the spec sets the maximum_empty_steps to 2 so we will now seal an empty block and include the empty step messages - let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b3 = b3.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); @@ -2132,7 +2123,7 @@ mod tests { engine.register_client(Arc::downgrade(&client) as _); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps @@ -2142,7 +2133,7 @@ mod tests { // step 3 // the signer of the accumulated empty step message should be rewarded - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let addr1_balance = b2.state.balance(&addr1).unwrap(); // after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation @@ -2242,7 +2233,6 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, - None, ).unwrap(); let b1 = b1.close_and_lock().unwrap(); @@ -2264,7 +2254,6 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, - None, ).unwrap(); let addr1_balance = b2.state.balance(&addr1).unwrap(); diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 18afc51ce68..b08512b79b5 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -268,7 +268,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b = b.close_and_lock().unwrap(); if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); diff --git a/ethcore/src/engines/clique/mod.rs b/ethcore/src/engines/clique/mod.rs index 9c8e1823feb..89bcef94c2b 100644 --- a/ethcore/src/engines/clique/mod.rs +++ b/ethcore/src/engines/clique/mod.rs @@ -368,13 +368,16 @@ impl Engine for Clique { &self, _block: &mut ExecutedBlock, _epoch_begin: bool, - _ancestry: &mut dyn Iterator, ) -> Result<(), Error> { Ok(()) } // Clique has no block reward. - fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block( + &self, + _block: &mut ExecutedBlock, + _parent_header: &Header + ) -> Result<(), Error> { Ok(()) } diff --git a/ethcore/src/engines/clique/tests.rs b/ethcore/src/engines/clique/tests.rs index 76140284f6d..97e218a05ce 100644 --- a/ethcore/src/engines/clique/tests.rs +++ b/ethcore/src/engines/clique/tests.rs @@ -111,7 +111,7 @@ impl CliqueTester { /// Get signers after a certain state // This is generally used to fetch the state after a test has been executed and checked against - // the intial list of signers provided in the test + // the initial list of signers provided in the test pub fn clique_signers(&self, hash: &H256) -> impl Iterator { self.get_state_at_block(hash).signers().clone().into_iter() } @@ -171,7 +171,6 @@ impl CliqueTester { (3141562.into(), 31415620.into()), extra_data, false, - None, ).unwrap(); { diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 27f133424d5..58fbfeed1d4 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -110,7 +110,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let genesis_header = spec.genesis_header(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b = b.close_and_lock().unwrap(); if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index c550f74c2b0..b0207b075eb 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -304,13 +304,16 @@ pub trait Engine: Sync + Send { &self, _block: &mut ExecutedBlock, _epoch_begin: bool, - _ancestry: &mut dyn Iterator, ) -> Result<(), Error> { Ok(()) } /// Block transformation functions, after the transactions. - fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block( + &self, + _block: &mut ExecutedBlock, + _parent_header: &Header, + ) -> Result<(), Error> { Ok(()) } diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index a291969772c..71cb9d459b5 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -61,7 +61,11 @@ impl Engine for NullEngine { fn machine(&self) -> &Machine { &self.machine } - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block( + &self, + block: &mut ExecutedBlock, + _parent_header: &Header + ) -> Result<(), Error> { use std::ops::Shr; let author = *block.header.author(); diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index c29f960e573..a6540ab7908 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -239,7 +239,7 @@ impl Engine for Arc { /// Apply the block reward on finalisation of the block. /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block(&self, block: &mut ExecutedBlock, _parent_header: &Header) -> Result<(), Error> { use std::ops::Shr; let author = *block.header.author(); @@ -540,7 +540,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b = b.close().unwrap(); assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap()); } @@ -589,7 +589,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); let mut uncle = Header::new(); let uncle_author = Address::from_str("ef2d6d194084c2de36e0dabfce45d046b37d1106").unwrap(); uncle.set_author(uncle_author); @@ -607,7 +607,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); let b = b.close().unwrap(); let ubi_contract = Address::from_str("00efdd5883ec628983e9063c7d969fe268bbf310").unwrap(); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c35423d7403..e933d7d58b6 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -548,7 +548,7 @@ impl Miner { } }, // Invalid nonce error can happen only if previous transaction is skipped because of gas limit. - // If there is errornous state of transaction queue it will be fixed when next block is imported. + // If there is erroneous state of transaction queue it will be fixed when next block is imported. Err(Error::Execution(ExecutionError::InvalidNonce { expected, got })) => { debug!(target: "miner", "Skipping adding transaction to block because of invalid nonce: {:?} (expected: {:?}, got: {:?})", hash, expected, got); }, diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 6bdaeadf9bd..5137aade025 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -155,7 +155,6 @@ pub fn generate_dummy_client_with_spec_and_data(test_spec: F, block_number: u (3141562.into(), 31415620.into()), vec![], false, - None, ).unwrap(); rolling_timestamp += 10; b.set_timestamp(rolling_timestamp); diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 093c55a9137..343751b0481 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -117,7 +117,7 @@ fn query_none_block() { Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); - let non_existant = client.block_header(BlockId::Number(188)); + let non_existant = client.block_header(BlockId::Number(188)); assert!(non_existant.is_none()); } diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 882fed4436a..b80c7485128 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -87,7 +87,6 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, - None, ).unwrap(); rolling_timestamp += 10; root_block.set_timestamp(rolling_timestamp); @@ -116,7 +115,6 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, - None, ).unwrap(); rolling_timestamp += 10; parent_block.set_timestamp(rolling_timestamp); @@ -144,7 +142,6 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, - None, ).unwrap(); rolling_timestamp += 10; block.set_timestamp(rolling_timestamp); From bacc0f0b9aa2b20db82ea051e68eab8dba1d17be Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Thu, 4 Jul 2019 21:45:56 +1000 Subject: [PATCH 4/6] refactor: whisper: Add type aliases and update rustdocs in message.rs (#10812) * refactor: Add type aliases to Whisper and update rustdocs * remove my question that was answered --- whisper/src/message.rs | 190 +++++++++++++++++++++++--------------- whisper/src/rpc/filter.rs | 10 +- whisper/src/rpc/mod.rs | 7 +- 3 files changed, 123 insertions(+), 84 deletions(-) diff --git a/whisper/src/message.rs b/whisper/src/message.rs index ad50e3d9bf0..cf12d65b3a8 100644 --- a/whisper/src/message.rs +++ b/whisper/src/message.rs @@ -27,11 +27,38 @@ use tiny_keccak::{keccak256, Keccak}; #[cfg(not(time_checked_add))] use time_utils::CheckedSystemTime; +/// Bloom of topics. +type Bloom = H512; +/// Topic data index within a bloom. +type BloomTopicIndex = usize; +/// List of envelope topics. +type EnvelopeTopics = SmallVec<[EnvelopeTopic; 4]>; +/// Envelope topic data. +type EnvelopeTopicData = u8; +/// List of envelope topics data. +type EnvelopeTopicsData = [EnvelopeTopicData; 4]; +/// Expiry timestamp of an envelope. +type EnvelopeExpiryTimestamp = u64; +/// Message contained within an envelope +type EnvelopeMessage = Vec; +/// Arbitrary value used to target lower PoW hash. +type EnvelopeNonce = u64; +/// Envelope nonce in bytes. +type EnvelopeNonceBytes = [u8; 8]; +/// Envelope proving work duration in milliseconds. +type EnvelopeProvingWorkDuration = u64; +/// Envelope message uniquely identifying proving hash. +type EnvelopeProvingHash = H256; +/// Envelope work that has been proved by the proving hash. +type EnvelopeProvenWork = f64; +/// Time-to-live of an envelope in seconds. +type EnvelopeTTLDuration = u64; + /// Work-factor proved. Takes 3 parameters: size of message, time to live, /// and hash. /// /// Panics if size or TTL is zero. -pub fn work_factor_proved(size: u64, ttl: u64, hash: H256) -> f64 { +pub fn work_factor_proved(size: u64, ttl: EnvelopeTTLDuration, hash: EnvelopeProvingHash) -> EnvelopeProvenWork { assert!(size != 0 && ttl != 0); let leading_zeros = { @@ -44,51 +71,51 @@ pub fn work_factor_proved(size: u64, ttl: u64, hash: H256) -> f64 { 2.0_f64.powi(leading_zeros as i32) / spacetime } -/// A topic of a message. +/// A topic of a message. The topic is an abridged version of the first four bytes of the original topic's hash. #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct Topic(pub [u8; 4]); +pub struct EnvelopeTopic(pub EnvelopeTopicsData); -impl From<[u8; 4]> for Topic { - fn from(x: [u8; 4]) -> Self { - Topic(x) +impl From for EnvelopeTopic { + fn from(x: EnvelopeTopicsData) -> Self { + EnvelopeTopic(x) } } -impl Topic { - /// set up to three bits in the 64-byte bloom passed. +impl EnvelopeTopic { + /// Set up to three bits in the 64-byte bloom passed. /// - /// this takes 3 sets of 9 bits, treating each as an index in the range + /// This takes 3 sets of 9 bits, treating each as an index in the range /// 0..512 into the bloom and setting the corresponding bit in the bloom to 1. - pub fn bloom_into(&self, bloom: &mut H512) { + pub fn bloom_into(&self, bloom: &mut Bloom) { - let data = &self.0; + let topics_data = &self.0; for i in 0..3 { - let mut idx = data[i] as usize; + let mut topic_idx = topics_data[i] as BloomTopicIndex; - if data[3] & (1 << i) != 0 { - idx += 256; + if topics_data[3] & (1 << i) != 0 { + topic_idx += 256; } - debug_assert!(idx <= 511); - bloom.as_bytes_mut()[idx / 8] |= 1 << (7 - idx % 8); + debug_assert!(topic_idx <= 511); + bloom.as_bytes_mut()[topic_idx / 8] |= 1 << (7 - topic_idx % 8); } } /// Get bloom for single topic. - pub fn bloom(&self) -> H512 { + pub fn bloom(&self) -> Bloom { let mut bloom = Default::default(); self.bloom_into(&mut bloom); bloom } } -impl rlp::Encodable for Topic { +impl rlp::Encodable for EnvelopeTopic { fn rlp_append(&self, s: &mut RlpStream) { s.encoder().encode_value(&self.0); } } -impl rlp::Decodable for Topic { +impl rlp::Decodable for EnvelopeTopic { fn decode(rlp: &Rlp) -> Result { use std::cmp; @@ -96,16 +123,16 @@ impl rlp::Decodable for Topic { cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort), cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig), cmp::Ordering::Equal => { - let mut t = [0u8; 4]; + let mut t: EnvelopeTopicsData = [0u8; 4]; t.copy_from_slice(bytes); - Ok(Topic(t)) + Ok(EnvelopeTopic(t)) } }) } } /// Calculate union of blooms for given topics. -pub fn bloom_topics(topics: &[Topic]) -> H512 { +pub fn bloom_topics(topics: &[EnvelopeTopic]) -> Bloom { let mut bloom = H512::default(); for topic in topics { topic.bloom_into(&mut bloom); @@ -143,7 +170,8 @@ impl fmt::Display for Error { } } -fn append_topics<'a>(s: &'a mut RlpStream, topics: &[Topic]) -> &'a mut RlpStream { +/// Append given topic(s) to RLP stream. +fn append_topics<'a>(s: &'a mut RlpStream, topics: &[EnvelopeTopic]) -> &'a mut RlpStream { if topics.len() == 1 { s.append(&topics[0]) } else { @@ -151,27 +179,27 @@ fn append_topics<'a>(s: &'a mut RlpStream, topics: &[Topic]) -> &'a mut RlpStrea } } -fn decode_topics(rlp: Rlp) -> Result, DecoderError> { +fn decode_topics(rlp: Rlp) -> Result { if rlp.is_list() { - rlp.iter().map(|r| r.as_val::()).collect() + rlp.iter().map(|r| r.as_val::()).collect() } else { rlp.as_val().map(|t| SmallVec::from_slice(&[t])) } } -// Raw envelope struct. +/// An `Envelope` instance is contained in each `Message`. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Envelope { - /// Expiry timestamp - pub expiry: u64, - /// Time-to-live in seconds - pub ttl: u64, - /// series of 4-byte topics. - pub topics: SmallVec<[Topic; 4]>, - /// The message contained within. - pub data: Vec, + /// Expiry timestamp. + pub expiry: EnvelopeExpiryTimestamp, + /// Time-to-live in seconds. + pub ttl: EnvelopeTTLDuration, + /// Series of 4-byte topics. + pub topics: EnvelopeTopics, + /// The message contained within an envelope. + pub message_data: EnvelopeMessage, /// Arbitrary value used to target lower PoW hash. - pub nonce: u64, + pub nonce: EnvelopeNonce, } impl Envelope { @@ -180,7 +208,8 @@ impl Envelope { self.topics.len() != 1 } - fn proving_hash(&self) -> H256 { + // Generate the uniquely identifying proving hash for the message. + fn proving_hash(&self) -> EnvelopeProvingHash { use byteorder::{BigEndian, ByteOrder}; let mut buf = [0; 32]; @@ -189,7 +218,7 @@ impl Envelope { stream.append(&self.expiry).append(&self.ttl); append_topics(&mut stream, &self.topics) - .append(&self.data); + .append(&self.message_data); let mut digest = Keccak::new_keccak256(); digest.update(&*stream.drain()); @@ -212,7 +241,7 @@ impl rlp::Encodable for Envelope { .append(&self.ttl); append_topics(s, &self.topics) - .append(&self.data) + .append(&self.message_data) .append(&self.nonce); } } @@ -225,7 +254,7 @@ impl rlp::Decodable for Envelope { expiry: rlp.val_at(0)?, ttl: rlp.val_at(1)?, topics: decode_topics(rlp.at(2)?)?, - data: rlp.val_at(3)?, + message_data: rlp.val_at(3)?, nonce: rlp.val_at(4)?, }) } @@ -234,22 +263,22 @@ impl rlp::Decodable for Envelope { /// Message creation parameters. /// Pass this to `Message::create` to make a message. pub struct CreateParams { - /// time-to-live in seconds. - pub ttl: u64, - /// payload data. - pub payload: Vec, - /// Topics. May not be empty. - pub topics: Vec, + /// Envelope time-to-live in seconds. + pub ttl: EnvelopeTTLDuration, + /// Envelope payload of message data. + pub payload: EnvelopeMessage, + /// Envelope topics. Must not be empty. + pub topics: Vec, /// How many milliseconds to spend proving work. - pub work: u64, + pub work: EnvelopeProvingWorkDuration, } /// A whisper message. This is a checked message carrying around metadata. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Message { envelope: Envelope, - bloom: H512, - hash: H256, + bloom: Bloom, + hash: EnvelopeProvingHash, encoded_size: usize, } @@ -270,6 +299,7 @@ impl Message { assert!(params.ttl > 0); + // Expiry period since the last epoch rounded up to the nearest second. let expiry = { let since_epoch = SystemTime::now() .checked_add(Duration::from_secs(params.ttl)) @@ -277,10 +307,13 @@ impl Message { .ok_or(Error::TimestampOverflow)? .duration_since(time::UNIX_EPOCH).expect("time after now is after unix epoch; qed"); - // round up the sub-second to next whole second. + // Round up the sub-second to next whole second. since_epoch.as_secs() + if since_epoch.subsec_nanos() == 0 { 0 } else { 1 } }; + // Encrypt an RLP stream into a digest. Create the RLP stream by appending + // to it the envelope topics, envelope payload of message data, + // envelope ttl, and the expiry period since the last epoch. let start_digest = { let mut stream = RlpStream::new_list(4); stream.append(&expiry).append(¶ms.ttl); @@ -291,8 +324,10 @@ impl Message { digest }; + // Find the best nonce based on using updating the digest with + // randomly generated envelope nonce bytes let mut buf = [0; 32]; - let mut try_nonce = move |nonce: &[u8; 8]| { + let mut try_nonce = move |nonce: &EnvelopeNonceBytes| { let mut digest = start_digest.clone(); digest.update(&nonce[..]); digest.finalize(&mut buf[..]); @@ -300,9 +335,12 @@ impl Message { buf.clone() }; - let mut nonce: [u8; 8] = rng.gen(); + let mut nonce: EnvelopeNonceBytes = rng.gen(); let mut best_found = try_nonce(&nonce); + // Start proving work, which involves repeatedly trying to create another + // nonce hash that is better (lower PoW hash) than the latest best nonce, + // to replace it. let start = Instant::now(); while start.elapsed() <= Duration::from_millis(params.work) { @@ -316,10 +354,10 @@ impl Message { } let envelope = Envelope { - expiry: expiry, + expiry, ttl: params.ttl, topics: params.topics.into_iter().collect(), - data: params.payload, + message_data: params.payload, nonce: BigEndian::read_u64(&nonce[..]), }; @@ -344,9 +382,9 @@ impl Message { Message::from_components(envelope, encoded_size, hash, now) } - // create message from envelope, hash, and encoded size. - // does checks for validity. - fn from_components(envelope: Envelope, size: usize, hash: H256, now: SystemTime) + // Create message from envelope, hash, and encoded size. + // Does checks for validity. + fn from_components(envelope: Envelope, size: usize, hash: EnvelopeProvingHash, now: SystemTime) -> Result { const LEEWAY_SECONDS: u64 = 2; @@ -371,9 +409,9 @@ impl Message { let bloom = bloom_topics(&envelope.topics); Ok(Message { - envelope: envelope, - bloom: bloom, - hash: hash, + envelope, + bloom, + hash, encoded_size: size, }) } @@ -388,18 +426,18 @@ impl Message { self.encoded_size } - /// Get a uniquely identifying hash for the message. - pub fn hash(&self) -> &H256 { + /// Get a uniquely identifying proving hash for the message. + pub fn hash(&self) -> &EnvelopeProvingHash { &self.hash } - /// Get the bloom filter of the topics + /// Get the bloom filter of the topics. pub fn bloom(&self) -> &H512 { &self.bloom } /// Get the work proved by the hash. - pub fn work_proved(&self) -> f64 { + pub fn work_proved(&self) -> EnvelopeProvenWork { let proving_hash = self.envelope.proving_hash(); work_factor_proved(self.encoded_size as _, self.envelope.ttl, proving_hash) @@ -411,13 +449,13 @@ impl Message { } /// Get the topics. - pub fn topics(&self) -> &[Topic] { + pub fn topics(&self) -> &[EnvelopeTopic] { &self.envelope.topics } /// Get the message data. - pub fn data(&self) -> &[u8] { - &self.envelope.data + pub fn message_data(&self) -> &EnvelopeMessage { + &self.envelope.message_data } } @@ -438,7 +476,7 @@ mod tests { assert!(Message::create(CreateParams { ttl: 100, payload: vec![1, 2, 3, 4], - topics: vec![Topic([1, 2, 1, 2])], + topics: vec![EnvelopeTopic([1, 2, 1, 2])], work: 50, }).is_ok()); } @@ -448,7 +486,7 @@ mod tests { let envelope = Envelope { expiry: 100_000, ttl: 30, - data: vec![9; 256], + message_data: vec![9; 256], topics: SmallVec::from_slice(&[Default::default()]), nonce: 1010101, }; @@ -464,8 +502,8 @@ mod tests { let envelope = Envelope { expiry: 100_000, ttl: 30, - data: vec![9; 256], - topics: SmallVec::from_slice(&[Default::default(), Topic([1, 2, 3, 4])]), + message_data: vec![9; 256], + topics: SmallVec::from_slice(&[Default::default(), EnvelopeTopic([1, 2, 3, 4])]), nonce: 1010101, }; @@ -480,7 +518,7 @@ mod tests { let envelope = Envelope { expiry: 100_000, ttl: 30, - data: vec![9; 256], + message_data: vec![9; 256], topics: SmallVec::from_slice(&[Default::default()]), nonce: 1010101, }; @@ -499,7 +537,7 @@ mod tests { let envelope = Envelope { expiry: 100_000, ttl: 30, - data: vec![9; 256], + message_data: vec![9; 256], topics: SmallVec::from_slice(&[Default::default()]), nonce: 1010101, }; @@ -516,7 +554,7 @@ mod tests { let envelope = Envelope { expiry: 100_000, ttl: 200_000, - data: vec![9; 256], + message_data: vec![9; 256], topics: SmallVec::from_slice(&[Default::default()]), nonce: 1010101, }; @@ -530,10 +568,10 @@ mod tests { #[test] fn work_factor() { // 256 leading zeros -> 2^256 / 1 - assert_eq!(work_factor_proved(1, 1, H256::zero()), 115792089237316200000000000000000000000000000000000000000000000000000000000000.0); + assert_eq!(work_factor_proved(1, 1, EnvelopeProvingHash::zero()), 115792089237316200000000000000000000000000000000000000000000000000000000000000.0); // 255 leading zeros -> 2^255 / 1 - assert_eq!(work_factor_proved(1, 1, H256::from_low_u64_be(1)), 57896044618658100000000000000000000000000000000000000000000000000000000000000.0); + assert_eq!(work_factor_proved(1, 1, EnvelopeProvingHash::from_low_u64_be(1)), 57896044618658100000000000000000000000000000000000000000000000000000000000000.0); // 0 leading zeros -> 2^0 / 1 - assert_eq!(work_factor_proved(1, 1, serde_json::from_str::("\"0xff00000000000000000000000000000000000000000000000000000000000000\"").unwrap()), 1.0); + assert_eq!(work_factor_proved(1, 1, serde_json::from_str::("\"0xff00000000000000000000000000000000000000000000000000000000000000\"").unwrap()), 1.0); } } diff --git a/whisper/src/rpc/filter.rs b/whisper/src/rpc/filter.rs index a58f16f9c85..84a6445ca51 100644 --- a/whisper/src/rpc/filter.rs +++ b/whisper/src/rpc/filter.rs @@ -24,7 +24,7 @@ use ethkey::Public; use jsonrpc_pubsub::typed::{Subscriber, Sink}; use parking_lot::{Mutex, RwLock}; -use message::{Message, Topic}; +use message::{Message, EnvelopeTopic}; use super::{key_store::KeyStore, types::{self, FilterItem, HexEncode}}; /// Kinds of filters, @@ -198,7 +198,7 @@ impl Drop for Manager { /// Filter incoming messages by critera. pub struct Filter { - topics: Vec<(Vec, H512, Topic)>, + topics: Vec<(Vec, H512, EnvelopeTopic)>, from: Option, decrypt_with: Option, } @@ -278,7 +278,7 @@ impl Filter { } }; - let decrypted = match decrypt.decrypt(message.data()) { + let decrypted = match decrypt.decrypt(message.message_data()) { Some(d) => d, None => { trace!(target: "whisper", "Failed to decrypt message with {} matching topics", @@ -317,7 +317,7 @@ impl Filter { #[cfg(test)] mod tests { - use message::{CreateParams, Message, Topic}; + use message::{CreateParams, Message, EnvelopeTopic}; use rpc::types::{FilterRequest, HexEncode}; use rpc::abridge_topic; use super::*; @@ -366,7 +366,7 @@ mod tests { let message = Message::create(CreateParams { ttl: 100, payload: vec![1, 3, 5, 7, 9], - topics: vec![Topic([1, 8, 3, 99])], + topics: vec![EnvelopeTopic([1, 8, 3, 99])], work: 0, }).unwrap(); diff --git a/whisper/src/rpc/mod.rs b/whisper/src/rpc/mod.rs index 57ec4c6c4f7..0612fb5ac33 100644 --- a/whisper/src/rpc/mod.rs +++ b/whisper/src/rpc/mod.rs @@ -19,7 +19,7 @@ //! Manages standard message format decoding, ephemeral identities, signing, //! encryption, and decryption. //! -//! Provides an interface for using whisper to transmit data securely. +//! Provides an interface for using Whisper to transmit data securely. use std::sync::Arc; @@ -35,7 +35,7 @@ use self::filter::Filter; use self::key_store::{Key, KeyStore}; use self::types::HexEncode; -use message::{CreateParams, Message, Topic}; +use message::{CreateParams, Message, EnvelopeTopic}; mod crypto; mod filter; @@ -61,7 +61,7 @@ fn topic_hash(topic: &[u8]) -> H256 { } // abridge topic using first four bytes of hash. -fn abridge_topic(topic: &[u8]) -> Topic { +fn abridge_topic(topic: &[u8]) -> EnvelopeTopic { let mut abridged = [0; 4]; let hash = topic_hash(topic).0; abridged.copy_from_slice(&hash[..4]); @@ -99,6 +99,7 @@ pub trait Whisper { #[rpc(name = "shh_getPrivateKey")] fn get_private(&self, types::Identity) -> Result; + /// Get symmetric key. Succeeds if identity has been stored. #[rpc(name = "shh_getSymKey")] fn get_symmetric(&self, types::Identity) -> Result; From bbae075c6048d4d96652ae5a2c3aae8013e41d8a Mon Sep 17 00:00:00 2001 From: Seun LanLege Date: Thu, 4 Jul 2019 13:59:37 +0100 Subject: [PATCH 5/6] logs (#10817) --- util/network-devp2p/src/connection.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/network-devp2p/src/connection.rs b/util/network-devp2p/src/connection.rs index a0a6da17156..4892d0be6e3 100644 --- a/util/network-devp2p/src/connection.rs +++ b/util/network-devp2p/src/connection.rs @@ -194,7 +194,10 @@ impl Connection { /// Get remote peer address string pub fn remote_addr_str(&self) -> String { - self.socket.peer_addr().map(|a| a.to_string()).unwrap_or_else(|_| "Unknown".to_owned()) + self.socket.peer_addr().map(|a| a.to_string()).unwrap_or_else(|err| { + debug!("error occurred getting peer_addr: {}, connection token: {}", err, self.token); + "Unknown peer address".to_owned() + }) } /// Get local peer address string From 9f96fa0a73584cbc31547ac50cd2d264d28c9524 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 4 Jul 2019 15:20:44 +0200 Subject: [PATCH 6/6] Extricate PodAccount and state Account to own crates (#10838) * WIP move errors, pod_account and state account to own crates * Sort out dependencies, fix broken code and tests Remove botched ethcore-error crate * remove template line * fix review feedback * Remove test-only AccountDBMut::new --- Cargo.lock | 57 +++++++++++++++++++ Cargo.toml | 2 +- ethcore/Cargo.toml | 2 + ethcore/pod-account/Cargo.toml | 27 +++++++++ .../pod_account.rs => pod-account/src/lib.rs} | 27 +++------ ethcore/src/account_db.rs | 15 +---- ethcore/src/lib.rs | 7 +-- ethcore/src/snapshot/account.rs | 20 +++---- ethcore/src/state/mod.rs | 7 +-- ethcore/state-account/Cargo.toml | 28 +++++++++ .../account.rs => state-account/src/lib.rs} | 48 ++++++++++------ 11 files changed, 172 insertions(+), 68 deletions(-) create mode 100644 ethcore/pod-account/Cargo.toml rename ethcore/{src/pod_account.rs => pod-account/src/lib.rs} (93%) create mode 100644 ethcore/state-account/Cargo.toml rename ethcore/{src/state/account.rs => state-account/src/lib.rs} (95%) diff --git a/Cargo.lock b/Cargo.lock index 3bf2f113f45..d5c2ba0d420 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -914,6 +914,7 @@ dependencies = [ "parity-util-mem 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie-ethereum 0.1.0", + "pod-account 0.1.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -924,6 +925,7 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "state-account 0.1.0", "stats 0.1.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "time-utils 0.1.0", @@ -1916,6 +1918,14 @@ dependencies = [ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itertools-num" version = "0.1.3" @@ -3219,6 +3229,29 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pod-account" +version = "0.1.0" +dependencies = [ + "common-types 0.1.0", + "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethjson 0.1.0", + "hash-db 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.1.1", + "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "macros 0.1.0", + "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia-trie-ethereum 0.1.0", + "rlp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", + "triehash-ethereum 0.2.0", +] + [[package]] name = "pretty_assertions" version = "0.1.2" @@ -3898,6 +3931,29 @@ name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "state-account" +version = "0.1.0" +dependencies = [ + "common-types 0.1.0", + "ethcore 1.12.0", + "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", + "journaldb 0.2.0", + "keccak-hash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.1.1", + "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia-trie-ethereum 0.1.0", + "pod-account 0.1.0", + "rlp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp_compress 0.1.0", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "static_assertions" version = "0.2.5" @@ -4870,6 +4926,7 @@ dependencies = [ "checksum ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)" = "70783119ac90828aaba91eae39db32c6c1b8838deea3637e5238efa0130801ab" "checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itertools-num 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a872a22f9e6f7521ca557660adb96dd830e54f0f490fa115bb55dd69d38b27e7" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" diff --git a/Cargo.toml b/Cargo.toml index 764a2d30d29..369fa5bd68a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,5 +139,5 @@ members = [ "util/keccak-hasher", "util/patricia-trie-ethereum", "util/fastmap", - "util/time-utils" + "util/time-utils", ] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 9c315fffbbc..3a1f17e9017 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -52,6 +52,7 @@ parity-bytes = "0.1" parity-crypto = "0.4.0" parity-snappy = "0.1" parking_lot = "0.7" +pod-account = { path = "pod-account" } trie-db = "0.12.4" patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" } rand = "0.6" @@ -61,6 +62,7 @@ rlp_derive = { path = "../util/rlp-derive" } rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" +state-account = { path = "state-account" } stats = { path = "../util/stats" } tempdir = { version = "0.3", optional = true } time-utils = { path = "../util/time-utils" } diff --git a/ethcore/pod-account/Cargo.toml b/ethcore/pod-account/Cargo.toml new file mode 100644 index 00000000000..23d752489e1 --- /dev/null +++ b/ethcore/pod-account/Cargo.toml @@ -0,0 +1,27 @@ +[package] +description = "Account system expressed in Plain Old Data." +name = "pod-account" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +common-types = { path = "../types" } +ethereum-types = "0.6" +ethjson = { path = "../../json" } +ethtrie = { package = "patricia-trie-ethereum", path = "../../util/patricia-trie-ethereum" } +hash-db = "0.12" +itertools = "0.8" +keccak-hash = "0.2.0" +keccak-hasher = { path = "../../util/keccak-hasher" } +kvdb = "0.1" +log = "0.4" +parity-bytes = "0.1.0" +rlp = "0.4" +rustc-hex = "1" +serde = { version = "1.0", features = ["derive"] } +trie-db = "0.12.4" +triehash = { package = "triehash-ethereum", version = "0.2", path = "../../util/triehash-ethereum" } + +[dev-dependencies] +macros = { path = "../../util/macros" } diff --git a/ethcore/src/pod_account.rs b/ethcore/pod-account/src/lib.rs similarity index 93% rename from ethcore/src/pod_account.rs rename to ethcore/pod-account/src/lib.rs index 196d627b124..ea004f01715 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/pod-account/src/lib.rs @@ -15,23 +15,22 @@ // along with Parity Ethereum. If not, see . //! Account system expressed in Plain Old Data. - +use log::warn; use std::collections::BTreeMap; use itertools::Itertools; -use hash::{keccak}; +use keccak_hash::keccak; use ethereum_types::{H256, U256, BigEndianHash}; use hash_db::HashDB; use kvdb::DBValue; use keccak_hasher::KeccakHasher; use triehash::sec_trie_root; -use bytes::Bytes; -use trie::TrieFactory; +use parity_bytes::Bytes; +use trie_db::TrieFactory; use ethtrie::RlpCodec; -use state::Account; use ethjson; -use types::account_diff::*; +use common_types::account_diff::*; use rlp::{self, RlpStream}; -use serde::Serializer; +use serde::{Serializer, Serialize}; use rustc_hex::ToHex; #[derive(Debug, Clone, PartialEq, Eq, Serialize)] @@ -57,17 +56,6 @@ fn opt_bytes_to_hex(opt_bytes: &Option, serializer: S) -> Result PodAccount { - PodAccount { - balance: *acc.balance(), - nonce: *acc.nonce(), - storage: acc.storage_changes().iter().fold(BTreeMap::new(), |mut m, (k, v)| {m.insert(k.clone(), v.clone()); m}), - code: acc.code().map(|x| x.to_vec()), - } - } - /// Returns the RLP for this account. pub fn rlp(&self) -> Bytes { let mut stream = RlpStream::new_list(4); @@ -170,9 +158,10 @@ pub fn diff_pod(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option { } impl<'db> AccountDBMut<'db> { - /// Create a new AccountDB from an address. - #[cfg(test)] - pub fn new(db: &'db mut dyn HashDB, address: &Address) -> Self { - Self::from_hash(db, keccak(address)) - } - - /// Create a new AcountDB from an address' hash. + /// Create a new `AccountDBMut` from an address' hash. pub fn from_hash(db: &'db mut dyn HashDB, address_hash: H256) -> Self { - AccountDBMut { - db: db, - address_hash: address_hash, - } + AccountDBMut { db, address_hash } } - #[cfg(test)] + /// Create an `AccountDB` from an `AccountDBMut` (used in tests). pub fn immutable(&'db self) -> AccountDB<'db> { AccountDB { db: self.db, address_hash: self.address_hash.clone() } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index a0ee0c2d701..ea3347ffd51 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -88,6 +88,7 @@ extern crate parity_bytes as bytes; extern crate parity_crypto; extern crate parity_snappy as snappy; extern crate parking_lot; +extern crate pod_account; extern crate trie_db as trie; extern crate patricia_trie_ethereum as ethtrie; extern crate rand; @@ -98,6 +99,7 @@ extern crate parity_util_mem as malloc_size_of; extern crate rustc_hex; extern crate serde; extern crate stats; +extern crate state_account; extern crate time_utils; extern crate triehash_ethereum as triehash; extern crate unexpected; @@ -120,8 +122,6 @@ extern crate blooms_db; #[cfg(any(test, feature = "env_logger"))] extern crate env_logger; #[cfg(test)] -extern crate rlp_compress; -#[cfg(test)] extern crate serde_json; #[macro_use] @@ -162,7 +162,6 @@ pub mod executive; pub mod machine; pub mod miner; pub mod pod_state; -pub mod pod_account; pub mod snapshot; pub mod spec; pub mod state; @@ -170,8 +169,8 @@ pub mod state_db; pub mod trace; pub mod transaction_ext; pub mod verification; +pub mod account_db; -mod account_db; mod externalities; mod factory; mod tx_filter; diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 84baf543d7b..1b437388ce8 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -253,7 +253,7 @@ mod tests { let p = Progress::default(); let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), usize::max_value(), usize::max_value(), &p).unwrap(); let fat_rlp = Rlp::new(&fat_rlps[0]).at(1).unwrap(); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); + assert_eq!(from_fat_rlp(&mut AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr)), fat_rlp, H256::zero()).unwrap().0, account); } #[test] @@ -262,7 +262,7 @@ mod tests { let addr = Address::random(); let account = { - let acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr); + let acct_db = AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr)); let mut root = KECCAK_NULL_RLP; fill_storage(acct_db, &mut root, &mut H256::zero()); BasicAccount { @@ -280,7 +280,7 @@ mod tests { let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), usize::max_value(), usize::max_value(), &p).unwrap(); let fat_rlp = Rlp::new(&fat_rlp[0]).at(1).unwrap(); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); + assert_eq!(from_fat_rlp(&mut AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr)), fat_rlp, H256::zero()).unwrap().0, account); } #[test] @@ -289,7 +289,7 @@ mod tests { let addr = Address::random(); let account = { - let acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr); + let acct_db = AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr)); let mut root = KECCAK_NULL_RLP; fill_storage(acct_db, &mut root, &mut H256::zero()); BasicAccount { @@ -309,7 +309,7 @@ mod tests { let mut restored_account = None; for rlp in fat_rlps { let fat_rlp = Rlp::new(&rlp).at(1).unwrap(); - restored_account = Some(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, root).unwrap().0); + restored_account = Some(from_fat_rlp(&mut AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr)), fat_rlp, root).unwrap().0); root = restored_account.as_ref().unwrap().storage_root.clone(); } assert_eq!(restored_account, Some(account)); @@ -323,12 +323,12 @@ mod tests { let addr2 = Address::random(); let code_hash = { - let mut acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr1); + let mut acct_db = AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr1)); acct_db.insert(EMPTY_PREFIX, b"this is definitely code") }; { - let mut acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr2); + let mut acct_db = AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr2)); acct_db.emplace(code_hash.clone(), EMPTY_PREFIX, DBValue::from_slice(b"this is definitely code")); } @@ -356,11 +356,11 @@ mod tests { let fat_rlp1 = Rlp::new(&fat_rlp1[0]).at(1).unwrap(); let fat_rlp2 = Rlp::new(&fat_rlp2[0]).at(1).unwrap(); - let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr2), fat_rlp2, H256::zero()).unwrap(); + let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr2)), fat_rlp2, H256::zero()).unwrap(); assert!(maybe_code.is_none()); assert_eq!(acc, account2); - let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr1), fat_rlp1, H256::zero()).unwrap(); + let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(addr1)), fat_rlp1, H256::zero()).unwrap(); assert_eq!(maybe_code, Some(b"this is definitely code".to_vec())); assert_eq!(acc, account1); } @@ -368,6 +368,6 @@ mod tests { #[test] fn encoding_empty_acc() { let mut db = get_temp_state_db(); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &Address::zero()), Rlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None)); + assert_eq!(from_fat_rlp(&mut AccountDBMut::from_hash(db.as_hash_db_mut(), keccak(Address::zero())), Rlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None)); } } diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 4f26823aea6..cae58224e73 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -51,12 +51,11 @@ use bytes::Bytes; use trie::{Trie, TrieError, Recorder}; use ethtrie::{TrieDB, Result as TrieResult}; -mod account; mod substate; pub mod backend; -pub use self::account::Account; +pub use state_account::Account; pub use self::backend::Backend; pub use self::substate::Substate; @@ -964,7 +963,7 @@ impl State { assert!(self.checkpoints.borrow().is_empty()); PodState::from(self.cache.borrow().iter().fold(BTreeMap::new(), |mut m, (add, opt)| { if let Some(ref acc) = opt.account { - m.insert(*add, PodAccount::from_account(acc)); + m.insert(*add, acc.to_pod()); } m })) @@ -1031,7 +1030,7 @@ impl State { } } - let mut pod_account = PodAccount::from_account(&account); + let mut pod_account = account.to_pod(); // cached one first pod_storage.append(&mut pod_account.storage); pod_account.storage = pod_storage; diff --git a/ethcore/state-account/Cargo.toml b/ethcore/state-account/Cargo.toml new file mode 100644 index 00000000000..3e2d8bc6a42 --- /dev/null +++ b/ethcore/state-account/Cargo.toml @@ -0,0 +1,28 @@ +[package] +description = "Ethereum accounts, keeps track of changes to the code and storage." +name = "state-account" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +common-types = { path = "../types"} +ethereum-types = "0.6.0" +ethtrie = { package = "patricia-trie-ethereum", path = "../../util/patricia-trie-ethereum" } +hash-db = "0.12.4" +keccak-hash = "0.2.0" +keccak-hasher = { path = "../../util/keccak-hasher" } +kvdb = "0.1.0" +log = "0.4" +lru-cache = "0.1.2" +parity-bytes = "0.1.0" +pod-account = { path = "../pod-account" } +rlp = "0.4.0" +serde = { version = "1.0", features = ["derive"] } +trie-db = "0.12.4" + +[dev-dependencies] +ethcore = { path = ".." } +rlp_compress = { path = "../../util/rlp-compress" } +journaldb = { path = "../../util/journaldb" } +parity-bytes = "0.1.0" diff --git a/ethcore/src/state/account.rs b/ethcore/state-account/src/lib.rs similarity index 95% rename from ethcore/src/state/account.rs rename to ethcore/state-account/src/lib.rs index 2c9abc0df67..24e136d1e7b 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/state-account/src/lib.rs @@ -15,23 +15,22 @@ // along with Parity Ethereum. If not, see . //! Single account in the system. - +use log::{warn, trace}; use std::fmt; use std::sync::Arc; use std::collections::{HashMap, BTreeMap}; -use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; +use keccak_hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; use ethereum_types::{H256, U256, Address, BigEndianHash}; -use error::Error; use hash_db::HashDB; use keccak_hasher::KeccakHasher; use kvdb::DBValue; -use bytes::{Bytes, ToPretty}; -use trie::{Trie, Recorder}; +use parity_bytes::{Bytes, ToPretty}; +use trie_db::{Trie, Recorder}; use ethtrie::{TrieFactory, TrieDB, SecTrieDB, Result as TrieResult}; -use pod_account::*; -use rlp::{RlpStream, encode}; +use pod_account::PodAccount; +use rlp::{RlpStream, DecoderError, encode}; use lru_cache::LruCache; -use types::basic_account::BasicAccount; +use common_types::basic_account::BasicAccount; use std::cell::{RefCell, Cell}; @@ -136,6 +135,20 @@ impl Account { } } + /// Convert Account to a PodAccount. + /// NOTE: This will silently fail unless the account is fully cached. + pub fn to_pod(&self) -> PodAccount { + PodAccount { + balance: self.balance, + nonce: self.nonce, + storage: self.storage_changes.iter().fold(BTreeMap::new(), |mut m, (k, v)| { + m.insert(k.clone(), v.clone()); + m + }), + code: self.code().map(|x| x.to_vec()), + } + } + /// Create a new account with the given balance. pub fn new_basic(balance: U256, nonce: U256) -> Account { Account { @@ -154,10 +167,9 @@ impl Account { } /// Create a new account from RLP. - pub fn from_rlp(rlp: &[u8]) -> Result { + pub fn from_rlp(rlp: &[u8]) -> Result { ::rlp::decode::(rlp) .map(|ba| ba.into()) - .map_err(|e| e.into()) } /// Create a new contract account. @@ -618,9 +630,9 @@ mod tests { use rlp_compress::{compress, decompress, snapshot_swapper}; use ethereum_types::{H256, Address}; use journaldb::new_memory_db; - use bytes::Bytes; + use parity_bytes::Bytes; use super::*; - use account_db::*; + use ethcore::account_db::*; use std::str::FromStr; #[test] @@ -635,7 +647,7 @@ mod tests { #[test] fn storage_at() { let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::zero()); + let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero())); let rlp = { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); a.set_storage(H256::zero(), H256::from_low_u64_be(0x1234)); @@ -654,7 +666,7 @@ mod tests { #[test] fn note_code() { let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::zero()); + let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero())); let rlp = { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); @@ -674,7 +686,7 @@ mod tests { fn commit_storage() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::zero()); + let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero())); a.set_storage(H256::from_low_u64_be(0), H256::from_low_u64_be(0x1234)); assert_eq!(a.storage_root(), None); a.commit_storage(&Default::default(), &mut db).unwrap(); @@ -685,7 +697,7 @@ mod tests { fn commit_remove_commit_storage() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::zero()); + let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero())); a.set_storage(H256::from_low_u64_be(0), H256::from_low_u64_be(0x1234)); a.commit_storage(&Default::default(), &mut db).unwrap(); a.set_storage(H256::from_low_u64_be(1), H256::from_low_u64_be(0x1234)); @@ -699,7 +711,7 @@ mod tests { fn commit_code() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::zero()); + let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero())); a.init_code(vec![0x55, 0x44, 0xffu8]); assert_eq!(a.code_filth, Filth::Dirty); assert_eq!(a.code_size(), Some(3)); @@ -711,7 +723,7 @@ mod tests { fn reset_code() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::zero()); + let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero())); a.init_code(vec![0x55, 0x44, 0xffu8]); assert_eq!(a.code_filth, Filth::Dirty); a.commit_code(&mut db);