diff --git a/Cargo.lock b/Cargo.lock index ffb4fc12b..46d494600 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "parity" version = "1.3.0" dependencies = [ "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)", "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -129,15 +129,15 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.78" +version = "0.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clippy_lints 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy_lints 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clippy_lints" -version = "0.0.78" +version = "0.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -239,7 +239,7 @@ name = "ethcore" version = "1.3.0" dependencies = [ "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.3.0", @@ -267,7 +267,7 @@ dependencies = [ name = "ethcore-dapps" version = "1.3.0" dependencies = [ - "clippy 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.3.0", "ethcore-util 1.3.0", "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", @@ -343,7 +343,7 @@ dependencies = [ name = "ethcore-rpc" version = "1.3.0" dependencies = [ - "clippy 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.3.0", "ethcore 1.3.0", "ethcore-devtools 1.3.0", @@ -367,7 +367,7 @@ dependencies = [ name = "ethcore-signer" version = "1.3.0" dependencies = [ - "clippy 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.3.0", "ethcore-util 1.3.0", @@ -387,7 +387,7 @@ dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 0.1.0", "chrono 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -459,7 +459,7 @@ dependencies = [ name = "ethsync" version = "1.3.0" dependencies = [ - "clippy 0.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.3.0", "ethcore-util 1.3.0", diff --git a/Cargo.toml b/Cargo.toml index 9d72a15c4..fe035c348 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ fdlimit = { path = "util/fdlimit" } num_cpus = "0.2" number_prefix = "0.2" rpassword = "0.2.1" -clippy = { version = "0.0.78", optional = true} +clippy = { version = "0.0.79", optional = true} ethcore = { path = "ethcore" } ethcore-util = { path = "util" } ethsync = { path = "sync" } diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index c42ed8eff..481388ed9 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -29,7 +29,7 @@ parity-dapps-wallet = { git = "https://github.com/ethcore/parity-dapps-wallet-rs parity-dapps-dao = { git = "https://github.com/ethcore/parity-dapps-dao-rs.git", version = "0.4.0", optional = true } parity-dapps-makerotc = { git = "https://github.com/ethcore/parity-dapps-makerotc-rs.git", version = "0.3.0", optional = true } mime_guess = { version = "1.6.1" } -clippy = { version = "0.0.78", optional = true} +clippy = { version = "0.0.79", optional = true} [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } diff --git a/db/Cargo.toml b/db/Cargo.toml index 92bc8282c..246e27c37 100644 --- a/db/Cargo.toml +++ b/db/Cargo.toml @@ -12,7 +12,7 @@ syntex = "*" ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] -clippy = { version = "0.0.78", optional = true} +clippy = { version = "0.0.79", optional = true} ethcore-devtools = { path = "../devtools" } ethcore-ipc = { path = "../ipc/rpc" } rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" } diff --git a/db/src/database.rs b/db/src/database.rs index 0ad02b783..2360e69ca 100644 --- a/db/src/database.rs +++ b/db/src/database.rs @@ -60,7 +60,7 @@ impl WriteCache { self.entries.insert(key, WriteCacheEntry::Remove); } - fn get(&self, key: &Vec) -> Option> { + fn get(&self, key: &[u8]) -> Option> { self.entries.get(key).and_then( |vec_ref| match vec_ref { &WriteCacheEntry::Write(ref val) => Some(val.clone()), diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 24dad7331..8b10fadea 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -22,7 +22,7 @@ ethcore-util = { path = "../util" } evmjit = { path = "../evmjit", optional = true } ethash = { path = "../ethash" } num_cpus = "0.2" -clippy = { version = "0.0.78", optional = true} +clippy = { version = "0.0.79", optional = true} crossbeam = "0.2.9" lazy_static = "0.2" ethcore-devtools = { path = "../devtools" } diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 4e5bc468a..e15a4b168 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -16,8 +16,6 @@ //! Blockchain block. -#![cfg_attr(feature="dev", allow(ptr_arg))] // Because of &LastHashes -> &Vec<_> - use common::*; use engine::*; use state::*; @@ -76,11 +74,11 @@ pub struct BlockRefMut<'a> { /// Block header. pub header: &'a mut Header, /// Block transactions. - pub transactions: &'a Vec, + pub transactions: &'a [SignedTransaction], /// Block uncles. - pub uncles: &'a Vec
, + pub uncles: &'a [Header], /// Transaction receipts. - pub receipts: &'a Vec, + pub receipts: &'a [Receipt], /// State. pub state: &'a mut State, /// Traces. @@ -92,11 +90,11 @@ pub struct BlockRef<'a> { /// Block header. pub header: &'a Header, /// Block transactions. - pub transactions: &'a Vec, + pub transactions: &'a [SignedTransaction], /// Block uncles. - pub uncles: &'a Vec
, + pub uncles: &'a [Header], /// Transaction receipts. - pub receipts: &'a Vec, + pub receipts: &'a [Receipt], /// State. pub state: &'a State, /// Traces. @@ -152,16 +150,16 @@ pub trait IsBlock { fn state(&self) -> &State { &self.block().state } /// Get all information on transactions in this block. - fn transactions(&self) -> &Vec { &self.block().base.transactions } + fn transactions(&self) -> &[SignedTransaction] { &self.block().base.transactions } /// Get all information on receipts in this block. - fn receipts(&self) -> &Vec { &self.block().receipts } + fn receipts(&self) -> &[Receipt] { &self.block().receipts } /// Get all information concerning transaction tracing in this block. fn traces(&self) -> &Option> { &self.block().traces } /// Get all uncles in this block. - fn uncles(&self) -> &Vec
{ &self.block().base.uncles } + fn uncles(&self) -> &[Header] { &self.block().base.uncles } } /// Trait for a object that has a state database. diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 64ccb7db1..94424d3ef 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -426,7 +426,7 @@ impl Client { }; // Commit results - let receipts = block.receipts().clone(); + let receipts = block.receipts().to_owned(); let traces = From::from(block.traces().clone().unwrap_or_else(Vec::new)); // CHECK! I *think* this is fine, even if the state_root is equal to another diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index 3ec943f18..77b57bf69 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -107,6 +107,9 @@ pub trait CostType: ops::Mul + ops::Div + ops::Add (Self, bool); /// Multiple with overflow fn overflow_mul(self, other: Self) -> (Self, bool); + /// Single-step full multiplication and division: `self*other/div` + /// Should not overflow on intermediate steps + fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool); } impl CostType for U256 { @@ -129,6 +132,17 @@ impl CostType for U256 { fn overflow_mul(self, other: Self) -> (Self, bool) { Uint::overflowing_mul(self, other) } + + fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) { + let x = self.full_mul(other); + let (U512(parts), o) = Uint::overflowing_div(x, U512::from(div)); + let overflow = (parts[4] | parts[5] | parts[6] | parts[7]) > 0; + + ( + U256([parts[0], parts[1], parts[2], parts[3]]), + o | overflow + ) + } } impl CostType for usize { @@ -154,6 +168,14 @@ impl CostType for usize { fn overflow_mul(self, other: Self) -> (Self, bool) { self.overflowing_mul(other) } + + fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) { + let (c, o) = U128::from(self).overflowing_mul(U128::from(other)); + let (U128(parts), o1) = c.overflowing_div(U128::from(div)); + let result = parts[0] as usize; + let overflow = o | o1 | (parts[1] > 0) | (parts[0] > result as u64); + (result, overflow) + } } /// Evm interface @@ -164,3 +186,41 @@ pub trait Evm { /// to compute the final gas left. fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result; } + + +#[test] +fn should_calculate_overflow_mul_div_without_overflow() { + // given + let num = 10_000_000; + + // when + let (res1, o1) = U256::from(num).overflow_mul_div(U256::from(num), U256::from(num)); + let (res2, o2) = num.overflow_mul_div(num, num); + + // then + assert_eq!(res1, U256::from(num)); + assert!(!o1); + assert_eq!(res2, num); + assert!(!o2); +} + +#[test] +fn should_calculate_overflow_mul_div_with_overflow() { + // given + let max = ::std::u64::MAX; + let num1 = U256([max, max, max, max]); + let num2 = ::std::usize::MAX; + + // when + let (res1, o1) = num1.overflow_mul_div(num1, num1 - U256::from(2)); + let (res2, o2) = num2.overflow_mul_div(num2, num2 - 2); + + // then + // (x+2)^2/x = (x^2 + 4x + 4)/x = x + 4 + 4/x ~ (MAX-2) + 4 + 0 = 1 + assert_eq!(res2, 1); + assert!(o2); + + assert_eq!(res1, U256::from(1)); + assert!(o1); +} + diff --git a/ethcore/src/evm/interpreter/gasometer.rs b/ethcore/src/evm/interpreter/gasometer.rs index 069d70e19..0fc349a27 100644 --- a/ethcore/src/evm/interpreter/gasometer.rs +++ b/ethcore/src/evm/interpreter/gasometer.rs @@ -68,6 +68,9 @@ impl Gasometer { let default_gas = Gas::from(schedule.tier_step_gas[tier]); let cost = match instruction { + instructions::JUMPDEST => { + InstructionCost::Gas(Gas::from(1)) + }, instructions::SSTORE => { let address = H256::from(stack.peek(0)); let newval = stack.peek(1); @@ -106,9 +109,6 @@ impl Gasometer { instructions::EXTCODECOPY => { InstructionCost::GasMemCopy(default_gas, try!(self.mem_needed(stack.peek(1), stack.peek(3))), try!(Gas::from_u256(*stack.peek(3)))) }, - instructions::JUMPDEST => { - InstructionCost::Gas(Gas::from(1)) - }, instructions::LOG0...instructions::LOG4 => { let no_of_topics = instructions::get_log_topics(instruction); let log_gas = schedule.log_gas + schedule.log_topic_gas * no_of_topics; @@ -199,14 +199,12 @@ impl Gasometer { let s = mem_size >> 5; // s * memory_gas + s * s / quad_coeff_div let a = overflowing!(s.overflow_mul(Gas::from(schedule.memory_gas))); - // We need to go to U512 to calculate s*s/quad_coeff_div - let b = U512::from(s.as_u256()) * U512::from(s.as_u256()) / U512::from(schedule.quad_coeff_div); - if b > U512::from(!U256::zero()) { - Err(evm::Error::OutOfGas) - } else { - Ok(overflowing!(a.overflow_add(try!(Gas::from_u256(U256::from(b)))))) - } + + // Calculate s*s/quad_coeff_div + let b = overflowing!(s.overflow_mul_div(s, Gas::from(schedule.quad_coeff_div))); + Ok(overflowing!(a.overflow_add(b))) }; + let current_mem_size = Gas::from(current_mem_size); let req_mem_size_rounded = (overflowing!(mem_size.overflow_add(Gas::from(31 as usize))) >> 5) << 5; diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs index 77ec4813b..01d0bbb3d 100644 --- a/ethcore/src/header.rs +++ b/ethcore/src/header.rs @@ -143,7 +143,7 @@ impl Header { /// Get the difficulty field of the header. pub fn difficulty(&self) -> &U256 { &self.difficulty } /// Get the seal field of the header. - pub fn seal(&self) -> &Vec { &self.seal } + pub fn seal(&self) -> &[Bytes] { &self.seal } // TODO: seal_at, set_seal_at &c. diff --git a/ethcore/src/migrations/state/v7.rs b/ethcore/src/migrations/state/v7.rs index a69eecb2d..15b457d32 100644 --- a/ethcore/src/migrations/state/v7.rs +++ b/ethcore/src/migrations/state/v7.rs @@ -98,7 +98,7 @@ const V7_VERSION_KEY: &'static [u8] = &[ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, const DB_VERSION: u32 = 0x203; const PADDING : [u8; 10] = [0u8; 10]; -/// Version for OverlayRecent database. +/// Version for `OverlayRecent` database. /// more involved than the archive version because of journaling. #[derive(Default)] pub struct OverlayRecentV7 { @@ -258,4 +258,4 @@ impl Migration for OverlayRecentV7 { try!(self.walk_journal(source)); self.migrate_journal(source, batch, dest) } -} \ No newline at end of file +} diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c5e4b4a5c..800f8f492 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -665,7 +665,7 @@ impl MinerService for Miner { }; match (&self.options.pending_set, sealing_set) { (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.top_transactions(), - (_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().clone()), + (_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().to_owned()), } } @@ -702,7 +702,7 @@ impl MinerService for Miner { .iter() .map(|t| t.hash()); - let receipts = pending.receipts().clone().into_iter(); + let receipts = pending.receipts().iter().cloned(); hashes.zip(receipts).collect() }, diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 5c2a7d8d7..1f7bd6fd8 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -143,7 +143,7 @@ impl Spec { } /// Get the known knodes of the network in enode format. - pub fn nodes(&self) -> &Vec { &self.nodes } + pub fn nodes(&self) -> &[String] { &self.nodes } /// Get the configured Network ID. pub fn network_id(&self) -> U256 { self.params.network_id } diff --git a/evmbin/Cargo.toml b/evmbin/Cargo.toml index 3e531f5d3..8ec687687 100644 --- a/evmbin/Cargo.toml +++ b/evmbin/Cargo.toml @@ -4,6 +4,14 @@ description = "Parity's EVM implementation" version = "0.1.0" authors = ["Ethcore "] +[lib] +name = "evm" +path = "./src/main.rs" + +[[bin]] +name = "evm" +path = "./src/main.rs" + [dependencies] rustc-serialize = "0.3" docopt = { version = "0.6" } diff --git a/evmbin/bench.sh b/evmbin/bench.sh new file mode 100755 index 000000000..a7d5557cb --- /dev/null +++ b/evmbin/bench.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +set -x +set -e + +cargo build --release + +# LOOP TEST +CODE1=606060405260005b620f42408112156019575b6001016007565b600081905550600680602b6000396000f3606060405200 +ethvm --code $CODE1 +echo "^^^^ ethvm" +./target/release/evm stats --code $CODE1 --gas 4402000 +echo "^^^^ usize" +./target/release/evm stats --code $CODE1 +echo "^^^^ U256" + +# RNG TEST +CODE2=6060604052600360056007600b60005b620f4240811215607f5767ffe7649d5eca84179490940267f47ed85c4b9a6379019367f8e5dd9a5c994bba9390930267f91d87e4b8b74e55019267ff97f6f3b29cda529290920267f393ada8dd75c938019167fe8d437c45bb3735830267f47d9a7b5428ffec019150600101600f565b838518831882186000555050505050600680609a6000396000f3606060405200 +ethvm --code $CODE2 +echo "^^^^ ethvm" +./target/release/evm stats --code $CODE2 --gas 143020115 +echo "^^^^ usize" +./target/release/evm stats --code $CODE2 +echo "^^^^ U256" diff --git a/evmbin/benches/mod.rs b/evmbin/benches/mod.rs new file mode 100644 index 000000000..3013dca54 --- /dev/null +++ b/evmbin/benches/mod.rs @@ -0,0 +1,85 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! benchmarking for EVM +//! should be started with: +//! ```bash +//! multirust run nightly cargo bench +//! ``` + +#![feature(test)] + +extern crate test; +extern crate ethcore; +extern crate evm; +extern crate ethcore_util; +extern crate rustc_serialize; + +use self::test::{Bencher, black_box}; + +use evm::run_vm; +use ethcore::action_params::ActionParams; +use ethcore_util::{U256, Uint}; +use rustc_serialize::hex::FromHex; + +#[bench] +fn simple_loop_usize(b: &mut Bencher) { + simple_loop(U256::from(::std::usize::MAX), b) +} + +#[bench] +fn simple_loop_u256(b: &mut Bencher) { + simple_loop(!U256::zero(), b) +} + +fn simple_loop(gas: U256, b: &mut Bencher) { + let code = black_box( + "606060405260005b620042408112156019575b6001016007565b600081905550600680602b6000396000f3606060405200".from_hex().unwrap() + ); + + b.iter(|| { + let mut params = ActionParams::default(); + params.gas = gas; + params.code = Some(code.clone()); + + run_vm(params) + }); +} + +#[bench] +fn rng_usize(b: &mut Bencher) { + rng(U256::from(::std::usize::MAX), b) +} + +#[bench] +fn rng_u256(b: &mut Bencher) { + rng(!U256::zero(), b) +} + +fn rng(gas: U256, b: &mut Bencher) { + let code = black_box( + "6060604052600360056007600b60005b62004240811215607f5767ffe7649d5eca84179490940267f47ed85c4b9a6379019367f8e5dd9a5c994bba9390930267f91d87e4b8b74e55019267ff97f6f3b29cda529290920267f393ada8dd75c938019167fe8d437c45bb3735830267f47d9a7b5428ffec019150600101600f565b838518831882186000555050505050600680609a6000396000f3606060405200".from_hex().unwrap() + ); + + b.iter(|| { + let mut params = ActionParams::default(); + params.gas = gas; + params.code = Some(code.clone()); + + run_vm(params) + }); +} + diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 3fa06d004..94684129c 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -17,6 +17,7 @@ //! Parity EVM interpreter binary. #![warn(missing_docs)] +#![allow(dead_code)] extern crate ethcore; extern crate rustc_serialize; extern crate docopt; @@ -25,7 +26,7 @@ extern crate ethcore_util as util; mod ext; -use std::time::Instant; +use std::time::{Instant, Duration}; use std::str::FromStr; use docopt::Docopt; use util::{U256, FromHex, Uint, Bytes}; @@ -58,6 +59,15 @@ fn main() { params.code = Some(args.code()); params.data = args.data(); + let result = run_vm(params); + println!("Gas used: {:?}", result.gas_used); + println!("Output: {:?}", result.output); + println!("Time: {}.{:.9}s", result.time.as_secs(), result.time.subsec_nanos()); +} + +/// Execute VM with given `ActionParams` +pub fn run_vm(params: ActionParams) -> ExecutionResults { + let initial_gas = params.gas; let factory = Factory::new(VMType::Interpreter); let mut vm = factory.create(params.gas); let mut ext = ext::FakeExt::default(); @@ -66,9 +76,21 @@ fn main() { let gas_left = vm.exec(params, &mut ext).finalize(ext).expect("OK"); let duration = start.elapsed(); - println!("Gas used: {:?}", args.gas() - gas_left); - println!("Output: {:?}", ""); - println!("Time: {}.{:.9}s", duration.as_secs(), duration.subsec_nanos()); + ExecutionResults { + gas_used: initial_gas - gas_left, + output: Vec::new(), + time: duration, + } +} + +/// VM execution results +pub struct ExecutionResults { + /// Used gas + pub gas_used: U256, + /// Output as bytes + pub output: Vec, + /// Time Taken + pub time: Duration, } #[derive(Debug, RustcDecodable)] diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index dd93933cc..89aae7eae 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -62,24 +62,10 @@ pub fn expand_ipc_implementation( }; push_client(cx, &builder, &interface_map, push); - push_handshake_struct(cx, push); push(Annotatable::Item(interface_map.item)); } -fn push_handshake_struct(cx: &ExtCtxt, push: &mut FnMut(Annotatable)) { - let handshake_item = quote_item!(cx, - #[derive(Binary)] - pub struct BinHandshake { - api_version: String, - protocol_version: String, - reserved: Vec, - } - ).unwrap(); - - push(Annotatable::Item(handshake_item)); -} - fn field_name(builder: &aster::AstBuilder, arg: &Arg) -> ast::Ident { match arg.pat.node { PatKind::Ident(_, ref ident, _) => builder.id(ident.node), @@ -601,15 +587,14 @@ fn push_client_implementation( let handshake_item = quote_impl_item!(cx, pub fn handshake(&self) -> Result<(), ::ipc::Error> { - let payload = BinHandshake { - protocol_version: $item_ident::protocol_version().to_string(), - api_version: $item_ident::api_version().to_string(), - reserved: vec![0u8; 64], + let payload = ::ipc::Handshake { + protocol_version: $item_ident::protocol_version(), + api_version: $item_ident::api_version(), }; ::ipc::invoke( 0, - &Some(::ipc::binary::serialize(&payload).unwrap()), + &Some(::ipc::binary::serialize(&::ipc::BinHandshake::from(payload)).unwrap()), &mut *self.socket.write().unwrap()); let mut result = vec![0u8; 1]; @@ -673,18 +658,15 @@ fn implement_handshake_arm( ) -> (ast::Arm, ast::Arm) { let handshake_deserialize = quote_stmt!(&cx, - let handshake_payload = ::ipc::binary::deserialize_from::(r).unwrap(); + let handshake_payload = ::ipc::binary::deserialize_from::<::ipc::BinHandshake, _>(r).unwrap(); ); let handshake_deserialize_buf = quote_stmt!(&cx, - let handshake_payload = ::ipc::binary::deserialize::(buf).unwrap(); + let handshake_payload = ::ipc::binary::deserialize::<::ipc::BinHandshake>(buf).unwrap(); ); let handshake_serialize = quote_expr!(&cx, - ::ipc::binary::serialize::(&Self::handshake(&::ipc::Handshake { - api_version: ::semver::Version::parse(&handshake_payload.api_version).unwrap(), - protocol_version: ::semver::Version::parse(&handshake_payload.protocol_version).unwrap(), - })).unwrap() + ::ipc::binary::serialize::(&Self::handshake(&handshake_payload.to_semver())).unwrap() ); ( diff --git a/ipc/rpc/Cargo.toml b/ipc/rpc/Cargo.toml index ab00523de..b8512b2bb 100644 --- a/ipc/rpc/Cargo.toml +++ b/ipc/rpc/Cargo.toml @@ -8,6 +8,6 @@ license = "GPL-3.0" [dependencies] ethcore-devtools = { path = "../../devtools" } -semver = "0.2.0" nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" } ethcore-util = { path = "../../util" } +semver = "0.2" diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index cfc7420f2..94d930941 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -21,6 +21,7 @@ use util::numbers::{U256, U512, H256, H2048, Address}; use std::mem; use std::collections::{VecDeque, BTreeMap}; use std::ops::Range; +use super::Handshake; #[derive(Debug)] pub struct BinaryConvertError; @@ -554,6 +555,61 @@ macro_rules! binary_fixed_size { } } +/// Fixed-sized version of Handshake struct +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BinHandshake { + api_version: BinVersion, + protocol_version: BinVersion, +} + +/// Shorten version of semver Version without `pre` and `build` information +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BinVersion { + pub major: u64, + pub minor: u64, + pub patch: u64, +} + +impl From for BinHandshake { + fn from(other: Handshake) -> Self { + BinHandshake { + api_version: BinVersion::from(other.api_version), + protocol_version: BinVersion::from(other.protocol_version), + } + } +} + +impl BinHandshake { + pub fn to_semver(self) -> Handshake { + Handshake { + api_version: self.api_version.to_semver(), + protocol_version: self.protocol_version.to_semver(), + } + } +} + +impl BinVersion { + pub fn to_semver(self) -> ::semver::Version { + ::semver::Version { + major: self.major, + minor: self.minor, + patch: self.patch, + pre: vec![], + build: vec![], + } + } +} + +impl From<::semver::Version> for BinVersion { + fn from(other: ::semver::Version) -> Self { + BinVersion { + major: other.major, + minor: other.minor, + patch: other.patch, + } + } +} + binary_fixed_size!(u64); binary_fixed_size!(u32); binary_fixed_size!(usize); @@ -564,6 +620,7 @@ binary_fixed_size!(U512); binary_fixed_size!(H256); binary_fixed_size!(H2048); binary_fixed_size!(Address); +binary_fixed_size!(BinHandshake); #[test] fn vec_serialize() { @@ -706,8 +763,6 @@ fn serialize_opt_vec() { #[test] fn serialize_opt_vec_payload() { - use std::io::Cursor; - let optional_vec: Option> = None; let payload = serialize(&optional_vec).unwrap(); @@ -776,3 +831,23 @@ fn serialize_btree() { assert_eq!(res[&1u64], 5u64); } + +#[test] +fn serialize_handshake() { + use std::io::{Cursor, SeekFrom, Seek}; + + let mut buff = Cursor::new(Vec::new()); + + let handshake = Handshake { + api_version: ::semver::Version::parse("1.2.0").unwrap(), + protocol_version: ::semver::Version::parse("1.2.0").unwrap(), + }; + + serialize_into(&BinHandshake::from(handshake.clone()), &mut buff).unwrap(); + + buff.seek(SeekFrom::Start(0)).unwrap(); + let res = deserialize_from::(&mut buff).unwrap().to_semver(); + + assert_eq!(res, handshake); + +} diff --git a/ipc/rpc/src/interface.rs b/ipc/rpc/src/interface.rs index d4514467f..3d97d59bc 100644 --- a/ipc/rpc/src/interface.rs +++ b/ipc/rpc/src/interface.rs @@ -20,6 +20,7 @@ use std::io::{Read, Write}; use std::marker::Sync; use semver::Version; +#[derive(Debug, PartialEq, Eq, Clone)] /// Handshake for client and server to negotiate api/protocol version pub struct Handshake { pub protocol_version: Version, diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs index a19302fb2..a78320343 100644 --- a/ipc/rpc/src/lib.rs +++ b/ipc/rpc/src/lib.rs @@ -24,4 +24,4 @@ extern crate ethcore_util as util; pub mod interface; pub mod binary; pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket}; -pub use binary::{BinaryConvertable, BinaryConvertError}; +pub use binary::{BinaryConvertable, BinaryConvertError, BinHandshake}; diff --git a/json/Cargo.toml b/json/Cargo.toml index 591d3969f..bcb056239 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -10,7 +10,7 @@ rustc-serialize = "0.3" serde = "0.7.0" serde_json = "0.7.0" serde_macros = { version = "0.7.0", optional = true } -clippy = { version = "0.0.78", optional = true} +clippy = { version = "0.0.79", optional = true} [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } diff --git a/json/src/bytes.rs b/json/src/bytes.rs index 7741b8d3b..8772cd207 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -40,9 +40,9 @@ impl Into> for Bytes { } impl Deref for Bytes { - type Target = Vec; + type Target = [u8]; - fn deref(&self) -> &Vec { + fn deref(&self) -> &[u8] { &self.0 } } diff --git a/parity/configuration.rs b/parity/configuration.rs index 3f4955d50..dc00cb237 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -238,7 +238,7 @@ impl Configuration { }) }).collect(), Some(_) => Vec::new(), - None => spec.nodes().clone(), + None => spec.nodes().to_owned(), } } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index ed9bfd347..733ed521c 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -23,7 +23,7 @@ ethcore-devtools = { path = "../devtools" } rustc-serialize = "0.3" transient-hashmap = "0.1" serde_macros = { version = "0.7.0", optional = true } -clippy = { version = "0.0.78", optional = true} +clippy = { version = "0.0.79", optional = true} json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } ethcore-ipc = { path = "../ipc/rpc" } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 544c337b4..7cfe251fd 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -508,7 +508,7 @@ impl Eth for EthClient where fn compilers(&self, params: Params) -> Result { try!(self.active()); match params { - Params::None => to_value(&vec![] as &Vec), + Params::None => to_value(&(&[] as &[String])), _ => Err(Error::invalid_params()) } } diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 5e59d04a7..4d9b77c47 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -20,7 +20,7 @@ ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc" } parity-minimal-sysui = { git = "https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git", version = "0.2.0" } -clippy = { version = "0.0.78", optional = true} +clippy = { version = "0.0.79", optional = true} [features] dev = ["clippy"] diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs index 4b2eb808c..1bf0332b4 100644 --- a/signer/src/ws_server/session.rs +++ b/signer/src/ws_server/session.rs @@ -25,11 +25,11 @@ use std::str::FromStr; use jsonrpc_core::IoHandler; use util::H256; -fn origin_is_allowed(self_origin: &str, header: Option<&Vec>) -> bool { +fn origin_is_allowed(self_origin: &str, header: Option<&[u8]>) -> bool { match header { None => false, Some(h) => { - let v = String::from_utf8(h.clone()).ok(); + let v = String::from_utf8(h.to_owned()).ok(); match v { Some(ref origin) if origin.starts_with("chrome-extension://") => true, Some(ref origin) if origin.starts_with(self_origin) => true, @@ -84,8 +84,8 @@ pub struct Session { impl ws::Handler for Session { fn on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)> { - let origin = req.header("origin").or_else(|| req.header("Origin")); - let host = req.header("host").or_else(|| req.header("Host")); + let origin = req.header("origin").or_else(|| req.header("Origin")).map(|x| &x[..]); + let host = req.header("host").or_else(|| req.header("Host")).map(|x| &x[..]); // Check request origin and host header. if !origin_is_allowed(&self.self_origin, origin) && !(origin.is_none() && origin_is_allowed(&self.self_origin, host)) { diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 1cf9d21a4..939381a56 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Ethcore Result; } @@ -255,7 +255,7 @@ impl FromRawBytes for T where T: FixedHash { Ordering::Equal => () }; - let mut res: Self = unsafe { mem::uninitialized() }; + let mut res = T::zero(); res.copy_raw(bytes); Ok(res) } @@ -271,7 +271,7 @@ macro_rules! sized_binary_map { ::std::cmp::Ordering::Greater => return Err(FromBytesError::TooLong), ::std::cmp::Ordering::Equal => () }; - let mut res: Self = unsafe { ::std::mem::uninitialized() }; + let mut res: Self = 0; res.copy_raw(bytes); Ok(res) } @@ -298,7 +298,7 @@ sized_binary_map!(u32); sized_binary_map!(u64); /// Value that can be serialized from variable-length byte array -pub trait FromRawBytesVariable : Sized { +pub trait FromRawBytesVariable: Sized { /// Create value from slice fn from_bytes_variable(bytes: &[u8]) -> Result; } @@ -326,7 +326,7 @@ impl FromRawBytesVariable for Vec where T: FromRawBytes { let size_of_t = mem::size_of::(); let length_in_chunks = bytes.len() / size_of_t; - let mut result = Vec::with_capacity(length_in_chunks ); + let mut result = Vec::with_capacity(length_in_chunks); unsafe { result.set_len(length_in_chunks) }; for i in 0..length_in_chunks { *result.get_mut(i).unwrap() = try!(T::from_bytes( @@ -339,7 +339,7 @@ impl FromRawBytesVariable for Vec where T: FromRawBytes { impl FromRawBytes for (V1, T2) where V1: FromRawBytesVariable, T2: FromRawBytes { fn from_bytes(bytes: &[u8]) -> Result { let header = 8usize; - let mut map: (u64, ) = unsafe { mem::uninitialized() }; + let mut map: (u64, ) = (0,); if bytes.len() < header { return Err(FromBytesError::NotLongEnough); } map.copy_raw(&bytes[0..header]); @@ -358,7 +358,7 @@ impl FromRawBytes for (V1, V2, T3) { fn from_bytes(bytes: &[u8]) -> Result { let header = 16usize; - let mut map: (u64, u64, ) = unsafe { mem::uninitialized() }; + let mut map: (u64, u64, ) = (0, 0,); if bytes.len() < header { return Err(FromBytesError::NotLongEnough); } map.copy_raw(&bytes[0..header]); @@ -373,7 +373,7 @@ impl FromRawBytes for (V1, V2, T3) } } -impl<'a, V1, T2> ToBytesWithMap for (&'a Vec, &'a T2) where V1: ToBytesWithMap, T2: ToBytesWithMap { +impl<'a, V1, X1, T2> ToBytesWithMap for (X1, &'a T2) where V1: ToBytesWithMap, X1: Deref, T2: ToBytesWithMap { fn to_bytes_map(&self) -> Vec { let header = 8usize; let v1_size = mem::size_of::(); @@ -390,9 +390,9 @@ impl<'a, V1, T2> ToBytesWithMap for (&'a Vec, &'a T2) where V1: ToBytesWithM } -impl<'a, V1, V2, T3> ToBytesWithMap for (&'a Vec, &'a Vec, &'a T3) - where V1: ToBytesWithMap, - V2: ToBytesWithMap, +impl<'a, V1, X1, V2, X2, T3> ToBytesWithMap for (X1, X2, &'a T3) + where V1: ToBytesWithMap, X1: Deref, + V2: ToBytesWithMap, X2: Deref, T3: ToBytesWithMap { fn to_bytes_map(&self) -> Vec { @@ -433,7 +433,7 @@ pub trait ToBytesWithMap { impl ToBytesWithMap for T where T: FixedHash { fn to_bytes_map(&self) -> Vec { - self.as_slice().to_vec() + self.as_slice().to_owned() } } @@ -493,7 +493,7 @@ fn populate_big_types() { fn raw_bytes_from_tuple() { type Tup = (Vec, u16); - let tup = (vec![1u16, 1u16, 1u16, 1u16], 10u16); + let tup: (&[u16], u16) = (&[1; 4], 10); let bytes = vec![ // map 8u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, @@ -505,18 +505,19 @@ fn raw_bytes_from_tuple() { // 10u16 10u8, 0u8]; - let tup_from = Tup::from_bytes(&bytes).unwrap(); - assert_eq!(tup, tup_from); + let (v, x) = Tup::from_bytes(&bytes).unwrap(); + assert_eq!(tup, (&v[..], x)); + let tup_from = (v, x); - let tup_to = (&tup_from.0, &tup_from.1); + let tup_to = (tup_from.0, &tup_from.1); let bytes_to = tup_to.to_bytes_map(); assert_eq!(bytes_to, bytes); } #[test] fn bytes_map_from_triple() { - let data = (vec![2u16; 6], vec![6u32; 3], 12u64); - let bytes_map = (&data.0, &data.1, &data.2).to_bytes_map(); + let data: (&[u16], &[u32], u64) = (&[2; 6], &[6; 3], 12u64); + let bytes_map = (data.0, data.1, &data.2).to_bytes_map(); assert_eq!(bytes_map, vec![ // data map 2 x u64 12, 0, 0, 0, 0, 0, 0, 0, diff --git a/util/src/triehash.rs b/util/src/triehash.rs index f5f4e2123..bedea9b0f 100644 --- a/util/src/triehash.rs +++ b/util/src/triehash.rs @@ -195,7 +195,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre } // take slices - let key: &Vec = &input[0].0; + let key: &[u8] = &input[0].0; let value: &[u8] = &input[0].1; // if the slice contains just one item, append the suffix of the key diff --git a/util/src/vector.rs b/util/src/vector.rs index 51a167a48..0fccac586 100644 --- a/util/src/vector.rs +++ b/util/src/vector.rs @@ -17,23 +17,23 @@ //! Vector extensions. /// Returns len of prefix shared with elem -/// +/// /// ```rust /// extern crate ethcore_util as util; /// use util::vector::SharedPrefix; -/// +/// /// fn main () { /// let a = vec![1,2,3,3,5]; /// let b = vec![1,2,3]; /// assert_eq!(a.shared_prefix_len(&b), 3); /// } /// ``` -pub trait SharedPrefix { +pub trait SharedPrefix { /// Get common prefix length fn shared_prefix_len(&self, elem: &[T]) -> usize; } -impl SharedPrefix for Vec where T: Eq { +impl SharedPrefix for [T] where T: Eq { fn shared_prefix_len(&self, elem: &[T]) -> usize { use std::cmp; let len = cmp::min(self.len(), elem.len()); @@ -58,7 +58,7 @@ mod test { let b = vec![1,2,3]; assert_eq!(a.shared_prefix_len(&b), 3); } - + #[test] fn test_shared_prefix3() { let a = vec![1,2,3,4,5,6];