diff --git a/docker/hub/Dockerfile b/docker/hub/Dockerfile new file mode 100644 index 000000000..3120eeba7 --- /dev/null +++ b/docker/hub/Dockerfile @@ -0,0 +1,83 @@ +FROM ubuntu:14.04 +MAINTAINER Parity Technologies +WORKDIR /build +#ENV for build TAG +ARG BUILD_TAG +ENV BUILD_TAG ${BUILD_TAG:-master} +RUN echo $BUILD_TAG +# install tools and dependencies +RUN apt-get update && \ + apt-get install -y --force-yes --no-install-recommends \ + # make + build-essential \ + # add-apt-repository + software-properties-common \ + make \ + curl \ + wget \ + git \ + g++ \ + gcc \ + libc6 \ + libc6-dev \ + binutils \ + file \ + openssl \ + libssl-dev \ + libudev-dev \ + pkg-config \ + dpkg-dev \ + # evmjit dependencies + zlib1g-dev \ + libedit-dev \ + libudev-dev &&\ +# cmake and llvm ppa's. then update ppa's + add-apt-repository -y "ppa:george-edison55/cmake-3.x" && \ + add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \ + apt-get update && \ + apt-get install -y --force-yes cmake llvm-3.7-dev && \ +# install evmjit + git clone https://github.com/debris/evmjit && \ + cd evmjit && \ + mkdir build && cd build && \ + cmake .. && make && make install && cd && \ +# install rustup + curl https://sh.rustup.rs -sSf | sh -s -- -y && \ +# rustup directory + PATH=/root/.cargo/bin:$PATH && \ +# show backtraces + RUST_BACKTRACE=1 && \ +# build parity + cd /build&&git clone https://github.com/paritytech/parity && \ + cd parity && \ + git pull&& \ + git checkout $BUILD_TAG && \ + cargo build --verbose --release --features final && \ + #ls /build/parity/target/release/parity && \ + strip /build/parity/target/release/parity && \ + file /build/parity/target/release/parity&&mkdir -p /parity&& cp /build/parity/target/release/parity /parity&&\ +#cleanup Docker image + rm -rf /root/.cargo&&rm -rf /root/.multirust&&rm -rf /root/.rustup&&rm -rf /build&&\ + apt-get purge -y \ + # make + build-essential \ + # add-apt-repository + software-properties-common \ + make \ + curl \ + wget \ + git \ + g++ \ + gcc \ + binutils \ + file \ + pkg-config \ + dpkg-dev \ + # evmjit dependencies + zlib1g-dev \ + libedit-dev \ + cmake llvm-3.7-dev&&\ + rm -rf /var/lib/apt/lists/* +# setup ENTRYPOINT +EXPOSE 8080 8545 8180 +ENTRYPOINT ["/parity/parity"] diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs new file mode 100644 index 000000000..2fd071062 --- /dev/null +++ b/ethcore/src/client/evm_test_client.rs @@ -0,0 +1,117 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +//! Simple Client used for EVM tests. + +use std::fmt; +use std::sync::Arc; +use util::{self, U256, journaldb, trie}; +use util::kvdb::{self, KeyValueDB}; +use {state, state_db, client, executive, trace, db, spec}; +use factory::Factories; +use evm::{self, VMType}; +use action_params::ActionParams; + +/// EVM test Error. +#[derive(Debug)] +pub enum EvmTestError { + /// Trie integrity error. + Trie(util::TrieError), + /// EVM error. + Evm(evm::Error), + /// Initialization error. + Initialization(::error::Error), + /// Low-level database error. + Database(String), +} + +impl fmt::Display for EvmTestError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + use self::EvmTestError::*; + + match *self { + Trie(ref err) => write!(fmt, "Trie: {}", err), + Evm(ref err) => write!(fmt, "EVM: {}", err), + Initialization(ref err) => write!(fmt, "Initialization: {}", err), + Database(ref err) => write!(fmt, "DB: {}", err), + } + } +} + +/// Simplified, single-block EVM test client. +pub struct EvmTestClient { + state_db: state_db::StateDB, + factories: Factories, + spec: spec::Spec, +} + +impl EvmTestClient { + /// Creates new EVM test client with in-memory DB initialized with genesis of given Spec. + pub fn new(spec: spec::Spec) -> Result { + let factories = Factories { + vm: evm::Factory::new(VMType::Interpreter, 5 * 1024), + trie: trie::TrieFactory::new(trie::TrieSpec::Secure), + accountdb: Default::default(), + }; + let db = Arc::new(kvdb::in_memory(db::NUM_COLUMNS.expect("We use column-based DB; qed"))); + let journal_db = journaldb::new(db.clone(), journaldb::Algorithm::EarlyMerge, db::COL_STATE); + let mut state_db = state_db::StateDB::new(journal_db, 5 * 1024 * 1024); + state_db = spec.ensure_db_good(state_db, &factories).map_err(EvmTestError::Initialization)?; + // Write DB + { + let mut batch = kvdb::DBTransaction::new(); + state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash()).map_err(|e| EvmTestError::Initialization(e.into()))?; + db.write(batch).map_err(EvmTestError::Database)?; + } + + Ok(EvmTestClient { + state_db, + factories, + spec, + }) + } + + /// Call given contract. + pub fn call(&mut self, params: ActionParams, vm_tracer: &mut T) + -> Result<(U256, Vec), EvmTestError> + { + let genesis = self.spec.genesis_header(); + let mut state = state::State::from_existing(self.state_db.boxed_clone(), *genesis.state_root(), self.spec.engine.account_start_nonce(), self.factories.clone()) + .map_err(EvmTestError::Trie)?; + let info = client::EnvInfo { + number: genesis.number(), + author: *genesis.author(), + timestamp: genesis.timestamp(), + difficulty: *genesis.difficulty(), + last_hashes: Arc::new([util::H256::default(); 256].to_vec()), + gas_used: 0.into(), + gas_limit: *genesis.gas_limit(), + }; + let mut substate = state::Substate::new(); + let mut tracer = trace::NoopTracer; + let mut output = vec![]; + let mut executive = executive::Executive::new(&mut state, &info, &*self.spec.engine, &self.factories.vm); + let gas_left = executive.call( + params, + &mut substate, + util::BytesRef::Flexible(&mut output), + &mut tracer, + vm_tracer, + ).map_err(EvmTestError::Evm)?; + + Ok((gas_left, output)) + } +} diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index f768e8d43..cd5c867e5 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -19,6 +19,7 @@ mod ancient_import; mod config; mod error; +mod evm_test_client; mod test_client; mod trace; mod client; @@ -26,6 +27,7 @@ mod client; pub use self::client::*; pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType}; pub use self::error::Error; +pub use self::evm_test_client::{EvmTestClient, EvmTestError}; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; pub use self::chain_notify::ChainNotify; pub use self::traits::{BlockChainClient, MiningBlockChainClient, EngineClient}; diff --git a/ethcore/src/evm/ext.rs b/ethcore/src/evm/ext.rs index e6b644874..d2ef23159 100644 --- a/ethcore/src/evm/ext.rs +++ b/ethcore/src/evm/ext.rs @@ -131,7 +131,7 @@ pub trait Ext { fn inc_sstore_clears(&mut self); /// Prepare to trace an operation. Passthrough for the VM trace. - fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: &U256) -> bool { false } + fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _stack_pop: usize, _gas_cost: &U256) -> bool { false } /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index c0a151f49..fe3f34013 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -129,7 +129,7 @@ impl evm::Evm for Interpreter { // Calculate gas cost let requirements = gasometer.requirements(ext, instruction, info, &stack, self.mem.size())?; // TODO: make compile-time removable if too much of a performance hit. - let trace_executed = ext.trace_prepare_execute(reader.position - 1, instruction, &requirements.gas_cost.as_u256()); + let trace_executed = ext.trace_prepare_execute(reader.position - 1, instruction, info.args, &requirements.gas_cost.as_u256()); gasometer.verify_gas(&requirements.gas_cost)?; self.mem.expand(requirements.memory_required_size); diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 0b849033e..d351f3cc4 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -333,8 +333,8 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one(); } - fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: &U256) -> bool { - self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost) + fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, stack_pop: usize, gas_cost: &U256) -> bool { + self.vm_tracer.trace_prepare_execute(pc, instruction, stack_pop, gas_cost) } fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index db92b0554..6cca0020c 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -192,7 +192,7 @@ impl ExecutiveVMTracer { } impl VMTracer for ExecutiveVMTracer { - fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: &U256) -> bool { + fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, _stack_pop: usize, gas_cost: &U256) -> bool { self.data.operations.push(VMOperation { pc: pc, instruction: instruction, diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index 2d13e3260..6cb9e47e9 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -89,7 +89,7 @@ pub trait Tracer: Send { pub trait VMTracer: Send { /// Trace the preparation to execute a single instruction. /// @returns true if `trace_executed` should be called. - fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: &U256) -> bool { false } + fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _stack_pop: usize, _gas_cost: &U256) -> bool { false } /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} @@ -97,7 +97,7 @@ pub trait VMTracer: Send { /// Spawn subtracer which will be used to trace deeper levels of execution. fn prepare_subtrace(&self, code: &[u8]) -> Self where Self: Sized; - /// Spawn subtracer which will be used to trace deeper levels of execution. + /// Finalize subtracer. fn done_subtrace(&mut self, sub: Self) where Self: Sized; /// Consumes self and returns the VM trace. diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index d5d04696d..d69ed9a16 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -72,7 +72,7 @@ pub struct NoopVMTracer; impl VMTracer for NoopVMTracer { /// Trace the preparation to execute a single instruction. - fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: &U256) -> bool { false } + fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _stack_pop: usize, _gas_cost: &U256) -> bool { false } /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs new file mode 100644 index 000000000..685579521 --- /dev/null +++ b/evmbin/src/display/json.rs @@ -0,0 +1,116 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +//! JSON VM output. + +use ethcore::trace; +use std::collections::HashMap; +use util::{U256, H256, ToPretty}; + +use display; +use vm; + +/// JSON formatting informant. +#[derive(Default)] +pub struct Informant { + depth: usize, + pc: usize, + instruction: u8, + gas_cost: U256, + stack: Vec, + memory: Vec, + storage: HashMap, +} + +impl Informant { + fn memory(&self) -> String { + format!("\"0x{}\"", self.memory.to_hex()) + } + + fn stack(&self) -> String { + let items = self.stack.iter().map(display::u256_as_str).collect::>(); + format!("[{}]", items.join(",")) + } + + fn storage(&self) -> String { + let vals = self.storage.iter() + .map(|(k, v)| format!("\"0x{:?}\": \"0x{:?}\"", k, v)) + .collect::>(); + format!("{{{}}}", vals.join(",")) + } +} + +impl vm::Informant for Informant { + fn finish(&mut self, result: Result) { + match result { + Ok(success) => println!( + "{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":\"{time}\"}}", + output = success.output.to_hex(), + gas = success.gas_used, + time = display::format_time(&success.time), + ), + Err(failure) => println!( + "{{\"error\":\"{error}\",\"time\":\"{time}\"}}", + error = failure.error, + time = display::format_time(&failure.time), + ), + } + } +} + +impl trace::VMTracer for Informant { + fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, stack_pop: usize, gas_cost: &U256) -> bool { + self.pc = pc; + self.instruction = instruction; + self.gas_cost = *gas_cost; + let len = self.stack.len(); + self.stack.truncate(len - stack_pop); + true + } + + fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { + self.stack.extend_from_slice(stack_push); + + if let Some((pos, data)) = mem_diff { + self.memory[pos..pos + data.len()].copy_from_slice(data); + } + + if let Some((pos, val)) = store_diff { + self.storage.insert(pos.into(), val.into()); + } + + println!( + "{{\"pc\":{pc},\"op\":{op},\"gas\":{gas},\"gasCost\":{gas_cost},\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", + pc = self.pc, + op = self.instruction, + gas = display::u256_as_str(&gas_used), + gas_cost = display::u256_as_str(&self.gas_cost), + memory = self.memory(), + stack = self.stack(), + storage = self.storage(), + depth = self.depth, + ); + } + + fn prepare_subtrace(&self, _code: &[u8]) -> Self where Self: Sized { + let mut vm = Informant::default(); + vm.depth = self.depth + 1; + vm + } + + fn done_subtrace(&mut self, _sub: Self) where Self: Sized {} + fn drain(self) -> Option { None } +} diff --git a/evmbin/src/display/mod.rs b/evmbin/src/display/mod.rs new file mode 100644 index 000000000..2d6179859 --- /dev/null +++ b/evmbin/src/display/mod.rs @@ -0,0 +1,38 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +//! VM Output display utils. + +use std::time::Duration; +use util::U256; + +pub mod json; +pub mod simple; + +/// Formats duration into human readable format. +pub fn format_time(time: &Duration) -> String { + format!("{}.{:.9}s", time.as_secs(), time.subsec_nanos()) +} + +/// Converts U256 into string. +/// TODO Overcomes: https://github.com/paritytech/bigint/issues/13 +pub fn u256_as_str(v: &U256) -> String { + if v.is_zero() { + "\"0x0\"".into() + } else { + format!("\"{:x}\"", v) + } +} diff --git a/evmbin/src/display/simple.rs b/evmbin/src/display/simple.rs new file mode 100644 index 000000000..5dcefd92c --- /dev/null +++ b/evmbin/src/display/simple.rs @@ -0,0 +1,49 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +//! Simple VM output. + +use ethcore::trace; +use util::ToPretty; + +use display; +use vm; + +/// Simple formatting informant. +#[derive(Default)] +pub struct Informant; + +impl vm::Informant for Informant { + fn finish(&mut self, result: Result) { + match result { + Ok(success) => { + println!("Output: 0x{}", success.output.to_hex()); + println!("Gas used: {:x}", success.gas_used); + println!("Time: {}", display::format_time(&success.time)); + }, + Err(failure) => { + println!("Error: {}", failure.error); + println!("Time: {}", display::format_time(&failure.time)); + }, + } + } +} + +impl trace::VMTracer for Informant { + fn prepare_subtrace(&self, _code: &[u8]) -> Self where Self: Sized { Default::default() } + fn done_subtrace(&mut self, _sub: Self) where Self: Sized {} + fn drain(self) -> Option { None } +} diff --git a/evmbin/src/ext.rs b/evmbin/src/ext.rs deleted file mode 100644 index 781120c36..000000000 --- a/evmbin/src/ext.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (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 . - -//! Externalities implementation. - -use std::sync::Arc; -use std::collections::HashMap; -use util::{U256, H256, Address, Bytes, trie}; -use ethcore::client::EnvInfo; -use ethcore::evm::{self, Ext, ContractCreateResult, MessageCallResult, Schedule, CallType, CreateContractAddress}; - -pub struct FakeExt { - schedule: Schedule, - store: HashMap, - depth: usize, -} - -impl Default for FakeExt { - fn default() -> Self { - FakeExt { - schedule: Schedule::new_post_eip150(usize::max_value(), true, true, true, true), - store: HashMap::new(), - depth: 1, - } - } -} - -impl Ext for FakeExt { - fn storage_at(&self, key: &H256) -> trie::Result { - Ok(self.store.get(key).unwrap_or(&H256::new()).clone()) - } - - fn set_storage(&mut self, key: H256, value: H256) -> trie::Result<()> { - self.store.insert(key, value); - Ok(()) - } - - fn exists(&self, _address: &Address) -> trie::Result { - unimplemented!(); - } - - fn exists_and_not_null(&self, _address: &Address) -> trie::Result { - unimplemented!(); - } - - fn origin_balance(&self) -> trie::Result { - unimplemented!(); - } - - fn balance(&self, _address: &Address) -> trie::Result { - unimplemented!(); - } - - fn blockhash(&self, _number: &U256) -> H256 { - unimplemented!(); - } - - fn create(&mut self, _gas: &U256, _value: &U256, _code: &[u8], _address: CreateContractAddress) -> ContractCreateResult { - unimplemented!(); - } - - fn call(&mut self, - _gas: &U256, - _sender_address: &Address, - _receive_address: &Address, - _value: Option, - _data: &[u8], - _code_address: &Address, - _output: &mut [u8], - _call_type: CallType) -> MessageCallResult { - unimplemented!(); - } - - fn extcode(&self, _address: &Address) -> trie::Result> { - unimplemented!(); - } - - fn extcodesize(&self, _address: &Address) -> trie::Result { - unimplemented!(); - } - - fn log(&mut self, _topics: Vec, _data: &[u8]) { - unimplemented!(); - } - - fn ret(self, gas: &U256, _data: &[u8]) -> evm::Result { - Ok(*gas) - } - - fn suicide(&mut self, _refund_address: &Address) -> trie::Result<()> { - unimplemented!(); - } - - fn schedule(&self) -> &Schedule { - &self.schedule - } - - fn env_info(&self) -> &EnvInfo { - unimplemented!() - } - - fn depth(&self) -> usize { - self.depth - } - - fn inc_sstore_clears(&mut self) { - unimplemented!(); - // self.sstore_clears += 1; - } -} diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 505eae86e..6f50249e0 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -23,31 +23,36 @@ extern crate rustc_serialize; extern crate docopt; extern crate ethcore_util as util; -mod ext; - use std::sync::Arc; -use std::time::{Instant, Duration}; -use std::fmt; -use std::str::FromStr; +use std::{fmt, fs}; use docopt::Docopt; -use util::{U256, FromHex, Bytes}; -use ethcore::evm::{self, Factory, VMType, Finalize}; +use util::{U256, FromHex, Bytes, Address}; +use ethcore::spec; use ethcore::action_params::ActionParams; +mod vm; +mod display; + +use vm::Informant; + const USAGE: &'static str = r#" EVM implementation for Parity. Copyright 2016, 2017 Parity Technologies (UK) Ltd Usage: evmbin stats [options] + evmbin [options] evmbin [-h | --help] Transaction options: - --code CODE Contract code as hex (without 0x) - --input DATA Input data as hex (without 0x) - --gas GAS Supplied gas as hex (without 0x) + --code CODE Contract code as hex (without 0x). + --from ADDRESS Sender address (without 0x). + --input DATA Input data as hex (without 0x). + --gas GAS Supplied gas as hex (without 0x). General options: + --json Display verbose results in JSON. + --chain CHAIN Chain spec file path. -h, --help Display this message and exit. "#; @@ -55,107 +60,93 @@ General options: fn main() { let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit()); + if args.flag_json { + run(args, display::json::Informant::default()) + } else { + run(args, display::simple::Informant::default()) + } +} + +fn run(args: Args, mut informant: T) { + let from = arg(args.from(), "--from"); + let code = arg(args.code(), "--code"); + let spec = arg(args.spec(), "--chain"); + let gas = arg(args.gas(), "--gas"); + let data = arg(args.data(), "--input"); + let mut params = ActionParams::default(); - params.gas = args.gas(); - params.code = Some(Arc::new(args.code())); - params.data = args.data(); + params.sender = from; + params.origin = from; + params.gas = gas; + params.code = Some(Arc::new(code)); + params.data = data; - let result = run_vm(params); - match result { - Ok(success) => println!("{}", success), - Err(failure) => println!("{}", failure), - } -} - -/// Execute VM with given `ActionParams` -pub fn run_vm(params: ActionParams) -> Result { - let initial_gas = params.gas; - let factory = Factory::new(VMType::Interpreter, 1024); - let mut vm = factory.create(params.gas); - let mut ext = ext::FakeExt::default(); - - let start = Instant::now(); - let res = vm.exec(params, &mut ext).finalize(ext); - let duration = start.elapsed(); - - match res { - Ok(res) => Ok(Success { - gas_used: initial_gas - res.gas_left, - // TODO [ToDr] get output from ext - output: Vec::new(), - time: duration, - }), - Err(e) => Err(Failure { - error: e, - time: duration, - }), - } -} - -/// Execution finished correctly -pub struct Success { - /// Used gas - gas_used: U256, - /// Output as bytes - output: Vec, - /// Time Taken - time: Duration, -} -impl fmt::Display for Success { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - writeln!(f, "Gas used: {:?}", self.gas_used)?; - writeln!(f, "Output: {:?}", self.output)?; - writeln!(f, "Time: {}.{:.9}s", self.time.as_secs(), self.time.subsec_nanos())?; - Ok(()) - } -} - -/// Execution failed -pub struct Failure { - /// Internal error - error: evm::Error, - /// Duration - time: Duration, -} -impl fmt::Display for Failure { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - writeln!(f, "Error: {:?}", self.error)?; - writeln!(f, "Time: {}.{:.9}s", self.time.as_secs(), self.time.subsec_nanos())?; - Ok(()) - } + let result = vm::run(&mut informant, spec, params); + informant.finish(result); } #[derive(Debug, RustcDecodable)] struct Args { cmd_stats: bool, + flag_from: Option, flag_code: Option, flag_gas: Option, flag_input: Option, + flag_spec: Option, + flag_json: bool, } impl Args { - pub fn gas(&self) -> U256 { - self.flag_gas - .clone() - .and_then(|g| U256::from_str(&g).ok()) - .unwrap_or_else(|| !U256::zero()) + pub fn gas(&self) -> Result { + match self.flag_gas { + Some(ref gas) => gas.parse().map_err(to_string), + None => Ok(!U256::zero()), + } } - pub fn code(&self) -> Bytes { - self.flag_code - .clone() - .and_then(|c| c.from_hex().ok()) - .unwrap_or_else(|| die("Code is required.")) + pub fn from(&self) -> Result { + match self.flag_from { + Some(ref from) => from.parse().map_err(to_string), + None => Ok(Address::default()), + } } - pub fn data(&self) -> Option { - self.flag_input - .clone() - .and_then(|d| d.from_hex().ok()) + pub fn code(&self) -> Result { + match self.flag_code { + Some(ref code) => code.from_hex().map_err(to_string), + None => Err("Code is required!".into()), + } + } + + pub fn data(&self) -> Result, String> { + match self.flag_input { + Some(ref input) => input.from_hex().map_err(to_string).map(Some), + None => Ok(None), + } + } + + pub fn spec(&self) -> Result { + Ok(match self.flag_spec { + Some(ref filename) => { + let file = fs::File::open(filename).map_err(|e| format!("{}", e))?; + spec::Spec::load(file)? + }, + None => { + spec::Spec::new_instant() + }, + }) } } -fn die(msg: &'static str) -> ! { +fn arg(v: Result, param: &str) -> T { + v.unwrap_or_else(|e| die(format!("Invalid {}: {}", param, e))) +} + +fn to_string(msg: T) -> String { + format!("{}", msg) +} + +fn die(msg: T) -> ! { println!("{}", msg); ::std::process::exit(-1) } diff --git a/evmbin/src/vm.rs b/evmbin/src/vm.rs new file mode 100644 index 000000000..6e45c5dc8 --- /dev/null +++ b/evmbin/src/vm.rs @@ -0,0 +1,72 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +//! VM runner. + +use std::time::{Instant, Duration}; +use util::U256; +use ethcore::{trace, spec}; +use ethcore::client::{EvmTestClient, EvmTestError}; +use ethcore::action_params::ActionParams; + +/// VM execution informant +pub trait Informant: trace::VMTracer { + /// Display final result. + fn finish(&mut self, result: Result); +} + +/// Execution finished correctly +pub struct Success { + /// Used gas + pub gas_used: U256, + /// Output as bytes + pub output: Vec, + /// Time Taken + pub time: Duration, +} + +/// Execution failed +pub struct Failure { + /// Internal error + pub error: EvmTestError, + /// Duration + pub time: Duration, +} + +/// Execute VM with given `ActionParams` +pub fn run(vm_tracer: &mut T, spec: spec::Spec, params: ActionParams) -> Result { + let mut test_client = EvmTestClient::new(spec).map_err(|error| Failure { + error, + time: Duration::from_secs(0) + })?; + + let initial_gas = params.gas; + let start = Instant::now(); + let result = test_client.call(params, vm_tracer); + let duration = start.elapsed(); + + match result { + Ok((gas_left, output)) => Ok(Success { + gas_used: initial_gas - gas_left, + output: output, + time: duration, + }), + Err(e) => Err(Failure { + error: e, + time: duration, + }), + } +} diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 78f9de03a..ec76bf5f4 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -226,7 +226,7 @@ impl FullDependencies { ($namespace:ident, $handler:expr, $deps:expr) => { { let deps = &$deps; - let dispatcher = FullDispatcher::new(Arc::downgrade(&deps.client), Arc::downgrade(&deps.miner)); + let dispatcher = FullDispatcher::new(deps.client.clone(), deps.miner.clone()); if deps.signer_service.is_enabled() { $handler.extend_with($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, dispatcher, &deps.secret_store))) } else { @@ -236,7 +236,7 @@ impl FullDependencies { } } - let dispatcher = FullDispatcher::new(Arc::downgrade(&self.client), Arc::downgrade(&self.miner)); + let dispatcher = FullDispatcher::new(self.client.clone(), self.miner.clone()); for api in apis { match *api { Api::Web3 => { diff --git a/rpc/src/v1/helpers/accounts.rs b/rpc/src/v1/helpers/accounts.rs index 329f25f0f..970603935 100644 --- a/rpc/src/v1/helpers/accounts.rs +++ b/rpc/src/v1/helpers/accounts.rs @@ -14,14 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::sync::{Arc, Weak}; +use std::sync::Arc; use ethcore::account_provider::AccountProvider; use jsonrpc_core::Error; use v1::helpers::errors; -pub fn unwrap_provider(provider: &Option>) -> Result, Error> { +pub fn unwrap_provider(provider: &Option>) -> Result, Error> { match *provider { - Some(ref weak) => weak.upgrade().ok_or_else(Error::internal_error), + Some(ref arc) => Ok(arc.clone()), None => Err(errors::public_unsupported(None)), } } diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 31223c77e..be46a4763 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -18,7 +18,7 @@ use std::fmt::Debug; use std::ops::Deref; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use futures::{future, Future, BoxFuture}; use light::cache::Cache as LightDataCache; @@ -74,16 +74,16 @@ pub trait Dispatcher: Send + Sync + Clone { /// requests locally. #[derive(Debug)] pub struct FullDispatcher { - client: Weak, - miner: Weak, + client: Arc, + miner: Arc, } impl FullDispatcher { - /// Create a `FullDispatcher` from weak references to a client and miner. - pub fn new(client: Weak, miner: Weak) -> Self { + /// Create a `FullDispatcher` from Arc references to a client and miner. + pub fn new(client: Arc, miner: Arc) -> Self { FullDispatcher { - client: client, - miner: miner, + client, + miner, } } } @@ -109,7 +109,7 @@ impl Dispatcher for FullDispatcher BoxFuture { - let (client, miner) = (take_weakf!(self.client), take_weakf!(self.miner)); + let (client, miner) = (self.client.clone(), self.miner.clone()); let request = request; let from = request.from.unwrap_or(default_sender); let nonce = match force_nonce { @@ -132,7 +132,7 @@ impl Dispatcher for FullDispatcher, filled: FilledTransactionRequest, password: SignWith) -> BoxFuture, Error> { - let (client, miner) = (take_weakf!(self.client), take_weakf!(self.miner)); + let (client, miner) = (self.client.clone(), self.miner.clone()); let network_id = client.signing_network_id(); let address = filled.from; future::done({ @@ -161,7 +161,7 @@ impl Dispatcher for FullDispatcher Result { let hash = signed_transaction.transaction.hash(); - take_weak!(self.miner).import_own_transaction(&*take_weak!(self.client), signed_transaction) + self.miner.import_own_transaction(&*self.client, signed_transaction) .map_err(errors::from_transaction_error) .map(|_| hash) } diff --git a/rpc/src/v1/helpers/fake_sign.rs b/rpc/src/v1/helpers/fake_sign.rs index c8e835bb3..a80afb0bb 100644 --- a/rpc/src/v1/helpers/fake_sign.rs +++ b/rpc/src/v1/helpers/fake_sign.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::sync::Weak; +use std::sync::Arc; use ethcore::client::MiningBlockChainClient; use ethcore::miner::MinerService; use ethcore::transaction::{Transaction, SignedTransaction, Action}; @@ -24,19 +24,17 @@ use v1::helpers::CallRequest; use v1::helpers::dispatch::default_gas_price; pub fn sign_call( - client: &Weak, - miner: &Weak, + client: &Arc, + miner: &Arc, request: CallRequest, ) -> Result { - let client = take_weak!(client); - let miner = take_weak!(miner); let from = request.from.unwrap_or(0.into()); Ok(Transaction { nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), action: request.to.map_or(Action::Create, Action::Call), gas: request.gas.unwrap_or(50_000_000.into()), - gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)), + gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&**client, &**miner)), value: request.value.unwrap_or(0.into()), data: request.data.map_or_else(Vec::new, |d| d.to_vec()) }.fake_sign(from)) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 17835485c..dacae2e67 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -18,7 +18,7 @@ use std::thread; use std::time::{Instant, Duration}; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use futures::{self, future, BoxFuture, Future}; use rlp::{self, UntrustedRlp}; @@ -95,11 +95,11 @@ pub struct EthClient where M: MinerService, EM: ExternalMinerService { - client: Weak, - snapshot: Weak, - sync: Weak, - accounts: Option>, - miner: Weak, + client: Arc, + snapshot: Arc, + sync: Arc, + accounts: Option>, + miner: Arc, external_miner: Arc, seed_compute: Mutex, options: EthClientOptions, @@ -124,11 +124,11 @@ impl EthClient where options: EthClientOptions ) -> Self { EthClient { - client: Arc::downgrade(client), - snapshot: Arc::downgrade(snapshot), - sync: Arc::downgrade(sync), - miner: Arc::downgrade(miner), - accounts: accounts.as_ref().map(Arc::downgrade), + client: client.clone(), + snapshot: snapshot.clone(), + sync: sync.clone(), + miner: miner.clone(), + accounts: accounts.clone(), external_miner: em.clone(), seed_compute: Mutex::new(SeedHashCompute::new()), options: options, @@ -137,13 +137,13 @@ impl EthClient where } /// Attempt to get the `Arc`, errors if provider was not - /// set, or if upgrading the weak reference failed. + /// set. fn account_provider(&self) -> Result, Error> { unwrap_provider(&self.accounts) } fn block(&self, id: BlockId, include_txs: bool) -> Result, Error> { - let client = take_weak!(self.client); + let client = &self.client; match (client.block(id.clone()), client.block_total_difficulty(id)) { (Some(block), Some(total_difficulty)) => { let view = block.header_view(); @@ -181,14 +181,14 @@ impl EthClient where } fn transaction(&self, id: TransactionId) -> Result, Error> { - match take_weak!(self.client).transaction(id) { + match self.client.transaction(id) { Some(t) => Ok(Some(Transaction::from_localized(t, self.eip86_transition))), None => Ok(None), } } fn uncle(&self, id: UncleId) -> Result, Error> { - let client = take_weak!(self.client); + let client = &self.client; let uncle: BlockHeader = match client.uncle(id) { Some(hdr) => hdr.decode(), None => { return Ok(None); } @@ -280,16 +280,16 @@ impl Eth for EthClient where type Metadata = Metadata; fn protocol_version(&self) -> Result { - let version = take_weak!(self.sync).status().protocol_version.to_owned(); + let version = self.sync.status().protocol_version.to_owned(); Ok(format!("{}", version)) } fn syncing(&self) -> Result { use ethcore::snapshot::RestorationStatus; - let status = take_weak!(self.sync).status(); - let client = take_weak!(self.client); - let snapshot_status = take_weak!(self.snapshot).status(); + let status = self.sync.status(); + let client = &self.client; + let snapshot_status = self.snapshot.status(); let (warping, warp_chunks_amount, warp_chunks_processed) = match snapshot_status { RestorationStatus::Ongoing { state_chunks, block_chunks, state_chunks_done, block_chunks_done } => @@ -320,7 +320,7 @@ impl Eth for EthClient where let dapp = meta.dapp_id(); let author = move || { - let mut miner = take_weak!(self.miner).author(); + let mut miner = self.miner.author(); if miner == 0.into() { miner = self.dapp_accounts(dapp.into())?.get(0).cloned().unwrap_or_default(); } @@ -332,7 +332,7 @@ impl Eth for EthClient where } fn is_mining(&self) -> Result { - Ok(take_weak!(self.miner).is_sealing()) + Ok(self.miner.is_sealing()) } fn hashrate(&self) -> Result { @@ -340,8 +340,7 @@ impl Eth for EthClient where } fn gas_price(&self) -> Result { - let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); - Ok(RpcU256::from(default_gas_price(&*client, &*miner))) + Ok(RpcU256::from(default_gas_price(&*self.client, &*self.miner))) } fn accounts(&self, meta: Metadata) -> BoxFuture, Error> { @@ -356,23 +355,22 @@ impl Eth for EthClient where } fn block_number(&self) -> Result { - Ok(RpcU256::from(take_weak!(self.client).chain_info().best_block_number)) + Ok(RpcU256::from(self.client.chain_info().best_block_number)) } fn balance(&self, address: RpcH160, num: Trailing) -> BoxFuture { let address = address.into(); - let client = take_weakf!(self.client); let res = match num.0.clone() { BlockNumber::Pending => { - match take_weakf!(self.miner).balance(&*client, &address) { + match self.miner.balance(&*self.client, &address) { Some(balance) => Ok(balance.into()), None => Err(errors::database_error("latest balance missing")) } } id => { - try_bf!(check_known(&*client, id.clone())); - match client.balance(&address, id.into()) { + try_bf!(check_known(&*self.client, id.clone())); + match self.client.balance(&address, id.into()) { Some(balance) => Ok(balance.into()), None => Err(errors::state_pruned()), } @@ -388,17 +386,14 @@ impl Eth for EthClient where let res = match num.0.clone() { BlockNumber::Pending => { - let client = take_weakf!(self.client); - match take_weakf!(self.miner).storage_at(&*client, &address, &H256::from(position)) { + match self.miner.storage_at(&*self.client, &address, &H256::from(position)) { Some(s) => Ok(s.into()), None => Err(errors::database_error("latest storage missing")) } } id => { - let client = take_weakf!(self.client); - - try_bf!(check_known(&*client, id.clone())); - match client.storage_at(&address, &H256::from(position), id.into()) { + try_bf!(check_known(&*self.client, id.clone())); + match self.client.storage_at(&address, &H256::from(position), id.into()) { Some(s) => Ok(s.into()), None => Err(errors::state_pruned()), } @@ -410,28 +405,26 @@ impl Eth for EthClient where fn transaction_count(&self, address: RpcH160, num: Trailing) -> BoxFuture { let address: Address = RpcH160::into(address); - let client = take_weakf!(self.client); - let miner = take_weakf!(self.miner); let res = match num.0.clone() { BlockNumber::Pending if self.options.pending_nonce_from_queue => { - let nonce = miner.last_nonce(&address) + let nonce = self.miner.last_nonce(&address) .map(|n| n + 1.into()) - .or_else(|| miner.nonce(&*client, &address)); + .or_else(|| self.miner.nonce(&*self.client, &address)); match nonce { Some(nonce) => Ok(nonce.into()), None => Err(errors::database_error("latest nonce missing")) } } BlockNumber::Pending => { - match miner.nonce(&*client, &address) { + match self.miner.nonce(&*self.client, &address) { Some(nonce) => Ok(nonce.into()), None => Err(errors::database_error("latest nonce missing")) } } id => { - try_bf!(check_known(&*client, id.clone())); - match client.nonce(&address, id.into()) { + try_bf!(check_known(&*self.client, id.clone())); + match self.client.nonce(&address, id.into()) { Some(nonce) => Ok(nonce.into()), None => Err(errors::state_pruned()), } @@ -442,23 +435,23 @@ impl Eth for EthClient where } fn block_transaction_count_by_hash(&self, hash: RpcH256) -> BoxFuture, Error> { - future::ok(take_weakf!(self.client).block(BlockId::Hash(hash.into())) + future::ok(self.client.block(BlockId::Hash(hash.into())) .map(|block| block.transactions_count().into())).boxed() } fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture, Error> { future::ok(match num { BlockNumber::Pending => Some( - take_weakf!(self.miner).status().transactions_in_pending_block.into() + self.miner.status().transactions_in_pending_block.into() ), _ => - take_weakf!(self.client).block(num.into()) + self.client.block(num.into()) .map(|block| block.transactions_count().into()) }).boxed() } fn block_uncles_count_by_hash(&self, hash: RpcH256) -> BoxFuture, Error> { - future::ok(take_weakf!(self.client).block(BlockId::Hash(hash.into())) + future::ok(self.client.block(BlockId::Hash(hash.into())) .map(|block| block.uncles_count().into())) .boxed() } @@ -466,7 +459,7 @@ impl Eth for EthClient where fn block_uncles_count_by_number(&self, num: BlockNumber) -> BoxFuture, Error> { future::ok(match num { BlockNumber::Pending => Some(0.into()), - _ => take_weakf!(self.client).block(num.into()) + _ => self.client.block(num.into()) .map(|block| block.uncles_count().into() ), }).boxed() @@ -477,17 +470,14 @@ impl Eth for EthClient where let res = match num.0.clone() { BlockNumber::Pending => { - let client = take_weakf!(self.client); - match take_weakf!(self.miner).code(&*client, &address) { + match self.miner.code(&*self.client, &address) { Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)), None => Err(errors::database_error("latest code missing")) } } id => { - let client = take_weakf!(self.client); - - try_bf!(check_known(&*client, id.clone())); - match client.code(&address, id.into()) { + try_bf!(check_known(&*self.client, id.clone())); + match self.client.code(&address, id.into()) { Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)), None => Err(errors::state_pruned()), } @@ -507,10 +497,8 @@ impl Eth for EthClient where fn transaction_by_hash(&self, hash: RpcH256) -> Result, Error> { let hash: H256 = hash.into(); - let miner = take_weak!(self.miner); - let client = take_weak!(self.client); - let block_number = client.chain_info().best_block_number; - Ok(self.transaction(TransactionId::Hash(hash))?.or_else(|| miner.transaction(block_number, &hash).map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)))) + let block_number = self.client.chain_info().best_block_number; + Ok(self.transaction(TransactionId::Hash(hash))?.or_else(|| self.miner.transaction(block_number, &hash).map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)))) } fn transaction_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> Result, Error> { @@ -522,14 +510,12 @@ impl Eth for EthClient where } fn transaction_receipt(&self, hash: RpcH256) -> Result, Error> { - let miner = take_weak!(self.miner); - let best_block = take_weak!(self.client).chain_info().best_block_number; + let best_block = self.client.chain_info().best_block_number; let hash: H256 = hash.into(); - match (miner.pending_receipt(best_block, &hash), self.options.allow_pending_receipt_query) { + match (self.miner.pending_receipt(best_block, &hash), self.options.allow_pending_receipt_query) { (Some(receipt), true) => Ok(Some(receipt.into())), _ => { - let client = take_weak!(self.client); - let receipt = client.transaction_receipt(TransactionId::Hash(hash)); + let receipt = self.client.transaction_receipt(TransactionId::Hash(hash)); Ok(receipt.map(Into::into)) } } @@ -550,14 +536,14 @@ impl Eth for EthClient where fn logs(&self, filter: Filter) -> BoxFuture, Error> { let include_pending = filter.to_block == Some(BlockNumber::Pending); let filter: EthcoreFilter = filter.into(); - let mut logs = take_weakf!(self.client).logs(filter.clone()) + let mut logs = self.client.logs(filter.clone()) .into_iter() .map(From::from) .collect::>(); if include_pending { - let best_block = take_weakf!(self.client).chain_info().best_block_number; - let pending = pending_logs(&*take_weakf!(self.miner), best_block, &filter); + let best_block = self.client.chain_info().best_block_number; + let pending = pending_logs(&*self.miner, best_block, &filter); logs.extend(pending); } @@ -569,29 +555,27 @@ impl Eth for EthClient where fn work(&self, no_new_work_timeout: Trailing) -> Result { let no_new_work_timeout = no_new_work_timeout.0; - let client = take_weak!(self.client); // check if we're still syncing and return empty strings in that case { //TODO: check if initial sync is complete here - //let sync = take_weak!(self.sync); - if /*sync.status().state != SyncState::Idle ||*/ client.queue_info().total_queue_size() > MAX_QUEUE_SIZE_TO_MINE_ON { + //let sync = self.sync; + if /*sync.status().state != SyncState::Idle ||*/ self.client.queue_info().total_queue_size() > MAX_QUEUE_SIZE_TO_MINE_ON { trace!(target: "miner", "Syncing. Cannot give any work."); return Err(errors::no_work()); } // Otherwise spin until our submitted block has been included. let timeout = Instant::now() + Duration::from_millis(1000); - while Instant::now() < timeout && client.queue_info().total_queue_size() > 0 { + while Instant::now() < timeout && self.client.queue_info().total_queue_size() > 0 { thread::sleep(Duration::from_millis(1)); } } - let miner = take_weak!(self.miner); - if miner.author().is_zero() { + if self.miner.author().is_zero() { warn!(target: "miner", "Cannot give work package - no author is configured. Use --author to configure!"); return Err(errors::no_author()) } - miner.map_sealing_work(&*client, |b| { + self.miner.map_sealing_work(&*self.client, |b| { let pow_hash = b.hash(); let target = Ethash::difficulty_to_boundary(b.block().header().difficulty()); let seed_hash = self.seed_compute.lock().get_seedhash(b.block().header().number()); @@ -623,10 +607,8 @@ impl Eth for EthClient where let mix_hash: H256 = mix_hash.into(); trace!(target: "miner", "submit_work: Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash); - let miner = take_weak!(self.miner); - let client = take_weak!(self.client); let seal = vec![rlp::encode(&mix_hash).to_vec(), rlp::encode(&nonce).to_vec()]; - Ok(miner.submit_seal(&*client, pow_hash, seal).is_ok()) + Ok(self.miner.submit_seal(&*self.client, pow_hash, seal).is_ok()) } fn submit_hashrate(&self, rate: RpcU256, id: RpcH256) -> Result { @@ -657,8 +639,8 @@ impl Eth for EthClient where }; let result = match num.0 { - BlockNumber::Pending => take_weakf!(self.miner).call(&*take_weakf!(self.client), &signed, Default::default()), - num => take_weakf!(self.client).call(&signed, num.into(), Default::default()), + BlockNumber::Pending => self.miner.call(&*self.client, &signed, Default::default()), + num => self.client.call(&signed, num.into(), Default::default()), }; future::done(result @@ -673,7 +655,7 @@ impl Eth for EthClient where Ok(signed) => signed, Err(e) => return future::err(e).boxed(), }; - future::done(take_weakf!(self.client).estimate_gas(&signed, num.0.into()) + future::done(self.client.estimate_gas(&signed, num.0.into()) .map(Into::into) .map_err(errors::from_call_error) ).boxed() diff --git a/rpc/src/v1/impls/net.rs b/rpc/src/v1/impls/net.rs index 399b2201a..97f50b633 100644 --- a/rpc/src/v1/impls/net.rs +++ b/rpc/src/v1/impls/net.rs @@ -15,32 +15,32 @@ // along with Parity. If not, see . //! Net rpc implementation. -use std::sync::{Arc, Weak}; +use std::sync::Arc; use jsonrpc_core::Error; use ethsync::SyncProvider; use v1::traits::Net; /// Net rpc implementation. pub struct NetClient { - sync: Weak + sync: Arc } impl NetClient where S: SyncProvider { /// Creates new NetClient. pub fn new(sync: &Arc) -> Self { NetClient { - sync: Arc::downgrade(sync) + sync: sync.clone(), } } } impl Net for NetClient where S: SyncProvider + 'static { fn version(&self) -> Result { - Ok(format!("{}", take_weak!(self.sync).status().network_id).to_owned()) + Ok(format!("{}", self.sync.status().network_id).to_owned()) } fn peer_count(&self) -> Result { - Ok(format!("0x{:x}", take_weak!(self.sync).status().num_peers as u64).to_owned()) + Ok(format!("0x{:x}", self.sync.status().num_peers as u64).to_owned()) } fn is_listening(&self) -> Result { diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 377be5bb0..2c5bcbef4 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . //! Parity-specific rpc implementation. -use std::sync::{Arc, Weak}; +use std::sync::Arc; use std::str::FromStr; use std::collections::{BTreeMap, HashSet}; use futures::{future, Future, BoxFuture}; @@ -58,12 +58,12 @@ pub struct ParityClient where S: SyncProvider, U: UpdateService, { - client: Weak, - miner: Weak, - sync: Weak, - updater: Weak, - net: Weak, - accounts: Option>, + client: Arc, + miner: Arc, + sync: Arc, + updater: Arc, + net: Arc, + accounts: Option>, logger: Arc, settings: Arc, signer: Option>, @@ -93,12 +93,12 @@ impl ParityClient where ws_address: Option<(String, u16)>, ) -> Self { ParityClient { - client: Arc::downgrade(client), - miner: Arc::downgrade(miner), - sync: Arc::downgrade(sync), - updater: Arc::downgrade(updater), - net: Arc::downgrade(net), - accounts: store.as_ref().map(Arc::downgrade), + client: client.clone(), + miner: miner.clone(), + sync: sync.clone(), + updater: updater.clone(), + net: net.clone(), + accounts: store.clone(), logger: logger, settings: settings, signer: signer, @@ -109,7 +109,7 @@ impl ParityClient where } /// Attempt to get the `Arc`, errors if provider was not - /// set, or if upgrading the weak reference failed. + /// set. fn account_provider(&self) -> Result, Error> { unwrap_provider(&self.accounts) } @@ -167,23 +167,23 @@ impl Parity for ParityClient where } fn transactions_limit(&self) -> Result { - Ok(take_weak!(self.miner).transactions_limit()) + Ok(self.miner.transactions_limit()) } fn min_gas_price(&self) -> Result { - Ok(U256::from(take_weak!(self.miner).minimal_gas_price())) + Ok(U256::from(self.miner.minimal_gas_price())) } fn extra_data(&self) -> Result { - Ok(Bytes::new(take_weak!(self.miner).extra_data())) + Ok(Bytes::new(self.miner.extra_data())) } fn gas_floor_target(&self) -> Result { - Ok(U256::from(take_weak!(self.miner).gas_floor_target())) + Ok(U256::from(self.miner.gas_floor_target())) } fn gas_ceil_target(&self) -> Result { - Ok(U256::from(take_weak!(self.miner).gas_ceil_target())) + Ok(U256::from(self.miner.gas_ceil_target())) } fn dev_logs(&self) -> Result, Error> { @@ -200,14 +200,13 @@ impl Parity for ParityClient where } fn chain(&self) -> Result { - Ok(take_weak!(self.client).spec_name()) + Ok(self.client.spec_name()) } fn net_peers(&self) -> Result { - let sync = take_weak!(self.sync); - let sync_status = sync.status(); - let net_config = take_weak!(self.net).network_config(); - let peers = sync.peers().into_iter().map(Into::into).collect(); + let sync_status = self.sync.status(); + let net_config = self.net.network_config(); + let peers = self.sync.peers().into_iter().map(Into::into).collect(); Ok(Peers { active: sync_status.num_active_peers, @@ -227,7 +226,7 @@ impl Parity for ParityClient where fn registry_address(&self) -> Result, Error> { Ok( - take_weak!(self.client) + self.client .additional_params() .get("registrar") .and_then(|s| Address::from_str(s).ok()) @@ -248,7 +247,7 @@ impl Parity for ParityClient where } fn gas_price_histogram(&self) -> BoxFuture { - future::done(take_weakf!(self.client) + future::done(self.client .gas_price_corpus(100) .histogram(10) .ok_or_else(errors::not_enough_data) @@ -272,13 +271,13 @@ impl Parity for ParityClient where } fn list_accounts(&self, count: u64, after: Option, block_number: Trailing) -> Result>, Error> { - Ok(take_weak!(self.client) + Ok(self.client .list_accounts(block_number.0.into(), after.map(Into::into).as_ref(), count) .map(|a| a.into_iter().map(Into::into).collect())) } fn list_storage_keys(&self, address: H160, count: u64, after: Option, block_number: Trailing) -> Result>, Error> { - Ok(take_weak!(self.client) + Ok(self.client .list_storage(block_number.0.into(), &address.into(), after.map(Into::into).as_ref(), count) .map(|a| a.into_iter().map(Into::into).collect())) } @@ -290,17 +289,17 @@ impl Parity for ParityClient where } fn pending_transactions(&self) -> Result, Error> { - let block_number = take_weak!(self.client).chain_info().best_block_number; - Ok(take_weak!(self.miner).pending_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::>()) + let block_number = self.client.chain_info().best_block_number; + Ok(self.miner.pending_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::>()) } fn future_transactions(&self) -> Result, Error> { - let block_number = take_weak!(self.client).chain_info().best_block_number; - Ok(take_weak!(self.miner).future_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::>()) + let block_number = self.client.chain_info().best_block_number; + Ok(self.miner.future_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::>()) } fn pending_transactions_stats(&self) -> Result, Error> { - let stats = take_weak!(self.sync).transactions_stats(); + let stats = self.sync.transactions_stats(); Ok(stats.into_iter() .map(|(hash, stats)| (hash.into(), stats.into())) .collect() @@ -308,8 +307,8 @@ impl Parity for ParityClient where } fn local_transactions(&self) -> Result, Error> { - let transactions = take_weak!(self.miner).local_transactions(); - let block_number = take_weak!(self.client).chain_info().best_block_number; + let transactions = self.miner.local_transactions(); + let block_number = self.client.chain_info().best_block_number; Ok(transactions .into_iter() .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status, block_number, self.eip86_transition))) @@ -329,18 +328,16 @@ impl Parity for ParityClient where fn next_nonce(&self, address: H160) -> BoxFuture { let address: Address = address.into(); - let miner = take_weakf!(self.miner); - let client = take_weakf!(self.client); - future::ok(miner.last_nonce(&address) + future::ok(self.miner.last_nonce(&address) .map(|n| n + 1.into()) - .unwrap_or_else(|| client.latest_nonce(&address)) + .unwrap_or_else(|| self.client.latest_nonce(&address)) .into() ).boxed() } fn mode(&self) -> Result { - Ok(match take_weak!(self.client).mode() { + Ok(match self.client.mode() { Mode::Off => "offline", Mode::Dark(..) => "dark", Mode::Passive(..) => "passive", @@ -349,26 +346,23 @@ impl Parity for ParityClient where } fn enode(&self) -> Result { - take_weak!(self.sync).enode().ok_or_else(errors::network_disabled) + self.sync.enode().ok_or_else(errors::network_disabled) } fn consensus_capability(&self) -> Result { - let updater = take_weak!(self.updater); - Ok(updater.capability().into()) + Ok(self.updater.capability().into()) } fn version_info(&self) -> Result { - let updater = take_weak!(self.updater); - Ok(updater.version_info().into()) + Ok(self.updater.version_info().into()) } fn releases_info(&self) -> Result, Error> { - let updater = take_weak!(self.updater); - Ok(updater.info().map(Into::into)) + Ok(self.updater.info().map(Into::into)) } fn chain_status(&self) -> Result { - let chain_info = take_weak!(self.client).chain_info(); + let chain_info = self.client.chain_info(); let gap = chain_info.ancient_block_number.map(|x| U256::from(x + 1)) .and_then(|first| chain_info.first_block_number.map(|last| (first, U256::from(last)))); @@ -395,16 +389,15 @@ impl Parity for ParityClient where fn block_header(&self, number: Trailing) -> BoxFuture { const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed"; - let client = take_weakf!(self.client); let id: BlockId = number.0.into(); - let encoded = match client.block_header(id.clone()) { + let encoded = match self.client.block_header(id.clone()) { Some(encoded) => encoded, None => return future::err(errors::unknown_block()).boxed(), }; future::ok(RichHeader { inner: encoded.into(), - extra_info: client.block_extra_info(id).expect(EXTRA_INFO_PROOF), + extra_info: self.client.block_extra_info(id).expect(EXTRA_INFO_PROOF), }).boxed() } diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index 5ee153db5..6bf8a069e 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . //! Account management (personal) rpc implementation -use std::sync::{Arc, Weak}; +use std::sync::Arc; use std::collections::BTreeMap; use util::Address; @@ -31,19 +31,19 @@ use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, DappId, Deriv /// Account management (personal) rpc implementation. pub struct ParityAccountsClient { - accounts: Option>, + accounts: Option>, } impl ParityAccountsClient { /// Creates new PersonalClient pub fn new(store: &Option>) -> Self { ParityAccountsClient { - accounts: store.as_ref().map(Arc::downgrade), + accounts: store.clone(), } } /// Attempt to get the `Arc`, errors if provider was not - /// set, or if upgrading the weak reference failed. + /// set. fn account_provider(&self) -> Result, Error> { unwrap_provider(&self.accounts) } diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index a6baa4a94..4be41f7c1 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -16,7 +16,7 @@ /// Parity-specific rpc interface for operations altering the settings. use std::io; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; @@ -35,10 +35,10 @@ use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction, LocalDapp}; /// Parity-specific rpc interface for operations altering the settings. pub struct ParitySetClient { - client: Weak, - miner: Weak, - updater: Weak, - net: Weak, + client: Arc, + miner: Arc, + updater: Arc, + net: Arc, dapps: Option>, fetch: F, eip86_transition: u64, @@ -57,10 +57,10 @@ impl ParitySetClient fetch: F, ) -> Self { ParitySetClient { - client: Arc::downgrade(client), - miner: Arc::downgrade(miner), - updater: Arc::downgrade(updater), - net: Arc::downgrade(net), + client: client.clone(), + miner: miner.clone(), + updater: updater.clone(), + net: net.clone(), dapps: dapps, fetch: fetch, eip86_transition: client.eip86_transition(), @@ -76,81 +76,81 @@ impl ParitySet for ParitySetClient where { fn set_min_gas_price(&self, gas_price: U256) -> Result { - take_weak!(self.miner).set_minimal_gas_price(gas_price.into()); + self.miner.set_minimal_gas_price(gas_price.into()); Ok(true) } fn set_gas_floor_target(&self, target: U256) -> Result { - take_weak!(self.miner).set_gas_floor_target(target.into()); + self.miner.set_gas_floor_target(target.into()); Ok(true) } fn set_gas_ceil_target(&self, target: U256) -> Result { - take_weak!(self.miner).set_gas_ceil_target(target.into()); + self.miner.set_gas_ceil_target(target.into()); Ok(true) } fn set_extra_data(&self, extra_data: Bytes) -> Result { - take_weak!(self.miner).set_extra_data(extra_data.into_vec()); + self.miner.set_extra_data(extra_data.into_vec()); Ok(true) } fn set_author(&self, author: H160) -> Result { - take_weak!(self.miner).set_author(author.into()); + self.miner.set_author(author.into()); Ok(true) } fn set_engine_signer(&self, address: H160, password: String) -> Result { - take_weak!(self.miner).set_engine_signer(address.into(), password).map_err(Into::into).map_err(errors::from_password_error)?; + self.miner.set_engine_signer(address.into(), password).map_err(Into::into).map_err(errors::from_password_error)?; Ok(true) } fn set_transactions_limit(&self, limit: usize) -> Result { - take_weak!(self.miner).set_transactions_limit(limit); + self.miner.set_transactions_limit(limit); Ok(true) } fn set_tx_gas_limit(&self, limit: U256) -> Result { - take_weak!(self.miner).set_tx_gas_limit(limit.into()); + self.miner.set_tx_gas_limit(limit.into()); Ok(true) } fn add_reserved_peer(&self, peer: String) -> Result { - match take_weak!(self.net).add_reserved_peer(peer) { + match self.net.add_reserved_peer(peer) { Ok(()) => Ok(true), Err(e) => Err(errors::invalid_params("Peer address", e)), } } fn remove_reserved_peer(&self, peer: String) -> Result { - match take_weak!(self.net).remove_reserved_peer(peer) { + match self.net.remove_reserved_peer(peer) { Ok(()) => Ok(true), Err(e) => Err(errors::invalid_params("Peer address", e)), } } fn drop_non_reserved_peers(&self) -> Result { - take_weak!(self.net).deny_unreserved_peers(); + self.net.deny_unreserved_peers(); Ok(true) } fn accept_non_reserved_peers(&self) -> Result { - take_weak!(self.net).accept_unreserved_peers(); + self.net.accept_unreserved_peers(); Ok(true) } fn start_network(&self) -> Result { - take_weak!(self.net).start_network(); + self.net.start_network(); Ok(true) } fn stop_network(&self) -> Result { - take_weak!(self.net).stop_network(); + self.net.stop_network(); Ok(true) } fn set_mode(&self, mode: String) -> Result { - take_weak!(self.client).set_mode(match mode.as_str() { + self.client.set_mode(match mode.as_str() { "offline" => Mode::Off, "dark" => Mode::Dark(300), "passive" => Mode::Passive(300, 3600), @@ -161,7 +161,7 @@ impl ParitySet for ParitySetClient where } fn set_spec_name(&self, spec_name: String) -> Result { - take_weak!(self.client).set_spec_name(spec_name); + self.client.set_spec_name(spec_name); Ok(true) } @@ -181,21 +181,17 @@ impl ParitySet for ParitySetClient where } fn upgrade_ready(&self) -> Result, Error> { - let updater = take_weak!(self.updater); - Ok(updater.upgrade_ready().map(Into::into)) + Ok(self.updater.upgrade_ready().map(Into::into)) } fn execute_upgrade(&self) -> Result { - let updater = take_weak!(self.updater); - Ok(updater.execute_upgrade()) + Ok(self.updater.execute_upgrade()) } fn remove_transaction(&self, hash: H256) -> Result, Error> { - let miner = take_weak!(self.miner); - let client = take_weak!(self.client); - let block_number = take_weak!(self.client).chain_info().best_block_number; + let block_number = self.client.chain_info().best_block_number; let hash = hash.into(); - Ok(miner.remove_pending_transaction(&*client, &hash).map(|t| Transaction::from_pending(t, block_number, self.eip86_transition))) + Ok(self.miner.remove_pending_transaction(&*self.client, &hash).map(|t| Transaction::from_pending(t, block_number, self.eip86_transition))) } } diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 84c29399c..0bb0be9a7 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . //! Account management (personal) rpc implementation -use std::sync::{Arc, Weak}; +use std::sync::Arc; use ethcore::account_provider::AccountProvider; use ethcore::transaction::PendingTransaction; @@ -33,7 +33,7 @@ use v1::metadata::Metadata; /// Account management (personal) rpc implementation. pub struct PersonalClient { - accounts: Option>, + accounts: Option>, dispatcher: D, allow_perm_unlock: bool, } @@ -42,7 +42,7 @@ impl PersonalClient { /// Creates new PersonalClient pub fn new(store: &Option>, dispatcher: D, allow_perm_unlock: bool) -> Self { PersonalClient { - accounts: store.as_ref().map(Arc::downgrade), + accounts: store.clone(), dispatcher: dispatcher, allow_perm_unlock: allow_perm_unlock, } diff --git a/rpc/src/v1/impls/secretstore.rs b/rpc/src/v1/impls/secretstore.rs index 570e12760..26a09705d 100644 --- a/rpc/src/v1/impls/secretstore.rs +++ b/rpc/src/v1/impls/secretstore.rs @@ -16,7 +16,7 @@ //! SecretStore-specific rpc implementation. -use std::sync::{Arc, Weak}; +use std::sync::Arc; use crypto::DEFAULT_MAC; use ethkey::Secret; @@ -31,19 +31,19 @@ use v1::types::{H160, H512, Bytes}; /// Parity implementation. pub struct SecretStoreClient { - accounts: Option>, + accounts: Option>, } impl SecretStoreClient { /// Creates new SecretStoreClient pub fn new(store: &Option>) -> Self { SecretStoreClient { - accounts: store.as_ref().map(Arc::downgrade), + accounts: store.clone(), } } /// Attempt to get the `Arc`, errors if provider was not - /// set, or if upgrading the weak reference failed. + /// set. fn account_provider(&self) -> Result, Error> { unwrap_provider(&self.accounts) } diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index e67042ed0..d596bde86 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -16,7 +16,7 @@ //! Transactions Confirmations rpc implementation -use std::sync::{Arc, Weak}; +use std::sync::Arc; use ethcore::account_provider::AccountProvider; use ethcore::transaction::{SignedTransaction, PendingTransaction}; @@ -38,8 +38,8 @@ use v1::types::{TransactionModification, ConfirmationRequest, ConfirmationRespon /// Transactions confirmation (personal) rpc implementation. pub struct SignerClient { - signer: Weak, - accounts: Option>, + signer: Arc, + accounts: Option>, dispatcher: D, subscribers: Arc>>>>, } @@ -70,8 +70,8 @@ impl SignerClient { }); SignerClient { - signer: Arc::downgrade(signer), - accounts: store.as_ref().map(Arc::downgrade), + signer: signer.clone(), + accounts: store.clone(), dispatcher: dispatcher, subscribers: subscribers, } @@ -90,7 +90,7 @@ impl SignerClient { let dispatcher = self.dispatcher.clone(); let setup = || { - Ok((self.account_provider()?, take_weak!(self.signer))) + Ok((self.account_provider()?, self.signer.clone())) }; let (accounts, signer) = match setup() { @@ -166,8 +166,7 @@ impl Signer for SignerClient { type Metadata = Metadata; fn requests_to_confirm(&self) -> Result, Error> { - let signer = take_weak!(self.signer); - Ok(signer.requests() + Ok(self.signer.requests() .into_iter() .map(Into::into) .collect() @@ -200,9 +199,8 @@ impl Signer for SignerClient { fn confirm_request_raw(&self, id: U256, bytes: Bytes) -> Result { let id = id.into(); - let signer = take_weak!(self.signer); - signer.peek(&id).map(|confirmation| { + self.signer.peek(&id).map(|confirmation| { let result = match confirmation.payload { ConfirmationPayload::SendTransaction(request) => { Self::verify_transaction(bytes, request, |pending_transaction| { @@ -231,24 +229,24 @@ impl Signer for SignerClient { }, }; if let Ok(ref response) = result { - signer.request_confirmed(id, Ok(response.clone())); + self.signer.request_confirmed(id, Ok(response.clone())); } result }).unwrap_or_else(|| Err(errors::invalid_params("Unknown RequestID", id))) } fn reject_request(&self, id: U256) -> Result { - let res = take_weak!(self.signer).request_rejected(id.into()); + let res = self.signer.request_rejected(id.into()); Ok(res.is_some()) } fn generate_token(&self) -> Result { - take_weak!(self.signer).generate_token() + self.signer.generate_token() .map_err(|e| errors::token(e)) } fn generate_web_proxy_token(&self) -> Result { - Ok(take_weak!(self.signer).generate_web_proxy_access_token()) + Ok(self.signer.generate_web_proxy_access_token()) } fn subscribe_pending(&self, _meta: Self::Metadata, sub: Subscriber>) { @@ -260,4 +258,3 @@ impl Signer for SignerClient { futures::future::ok(res).boxed() } } - diff --git a/rpc/src/v1/impls/signing.rs b/rpc/src/v1/impls/signing.rs index ccbaeac78..23ce3c78a 100644 --- a/rpc/src/v1/impls/signing.rs +++ b/rpc/src/v1/impls/signing.rs @@ -16,7 +16,7 @@ //! Signing RPC implementation. -use std::sync::{Arc, Weak}; +use std::sync::Arc; use transient_hashmap::TransientHashMap; use util::{U256, Mutex}; @@ -55,8 +55,8 @@ enum DispatchResult { /// Implementation of functions that require signing when no trusted signer is used. pub struct SigningQueueClient { - signer: Weak, - accounts: Option>, + signer: Arc, + accounts: Option>, dispatcher: D, pending: Arc>>, } @@ -94,8 +94,8 @@ impl SigningQueueClient { /// Creates a new signing queue client given shared signing queue. pub fn new(signer: &Arc, dispatcher: D, accounts: &Option>) -> Self { SigningQueueClient { - signer: Arc::downgrade(signer), - accounts: accounts.as_ref().map(Arc::downgrade), + signer: signer.clone(), + accounts: accounts.clone(), dispatcher: dispatcher, pending: Arc::new(Mutex::new(TransientHashMap::new(MAX_PENDING_DURATION_SEC))), } @@ -113,7 +113,7 @@ impl SigningQueueClient { }; let dispatcher = self.dispatcher.clone(); - let signer = take_weakf!(self.signer); + let signer = self.signer.clone(); dispatch::from_rpc(payload, default_account, &dispatcher) .and_then(move |payload| { let sender = payload.sender(); diff --git a/rpc/src/v1/impls/signing_unsafe.rs b/rpc/src/v1/impls/signing_unsafe.rs index 0cb50ac3c..cd027e960 100644 --- a/rpc/src/v1/impls/signing_unsafe.rs +++ b/rpc/src/v1/impls/signing_unsafe.rs @@ -16,7 +16,7 @@ //! Unsafe Signing RPC implementation. -use std::sync::{Arc, Weak}; +use std::sync::Arc; use ethcore::account_provider::AccountProvider; @@ -39,7 +39,7 @@ use v1::types::{ /// Implementation of functions that require signing when no trusted signer is used. pub struct SigningUnsafeClient { - accounts: Option>, + accounts: Option>, dispatcher: D, } @@ -47,7 +47,7 @@ impl SigningUnsafeClient { /// Creates new SigningUnsafeClient. pub fn new(accounts: &Option>, dispatcher: D) -> Self { SigningUnsafeClient { - accounts: accounts.as_ref().map(Arc::downgrade), + accounts: accounts.clone(), dispatcher: dispatcher, } } diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 466dbb88c..46a2ce9fd 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -16,7 +16,7 @@ //! Traces api implementation. -use std::sync::{Weak, Arc}; +use std::sync::Arc; use rlp::UntrustedRlp; use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId}; @@ -39,33 +39,33 @@ fn to_call_analytics(flags: Vec) -> CallAnalytics { /// Traces api implementation. pub struct TracesClient { - client: Weak, - miner: Weak, + client: Arc, + miner: Arc, } impl TracesClient { /// Creates new Traces client. pub fn new(client: &Arc, miner: &Arc) -> Self { TracesClient { - client: Arc::downgrade(client), - miner: Arc::downgrade(miner), + client: client.clone(), + miner: miner.clone(), } } } impl Traces for TracesClient where C: MiningBlockChainClient + 'static, M: MinerService + 'static { fn filter(&self, filter: TraceFilter) -> Result>, Error> { - Ok(take_weak!(self.client).filter_traces(filter.into()) + Ok(self.client.filter_traces(filter.into()) .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } fn block_traces(&self, block_number: BlockNumber) -> Result>, Error> { - Ok(take_weak!(self.client).block_traces(block_number.into()) + Ok(self.client.block_traces(block_number.into()) .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } fn transaction_traces(&self, transaction_hash: H256) -> Result>, Error> { - Ok(take_weak!(self.client).transaction_traces(TransactionId::Hash(transaction_hash.into())) + Ok(self.client.transaction_traces(TransactionId::Hash(transaction_hash.into())) .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } @@ -75,7 +75,7 @@ impl Traces for TracesClient where C: MiningBlockChainClient + 'stat address: address.into_iter().map(|i| i.value()).collect() }; - Ok(take_weak!(self.client).trace(id) + Ok(self.client.trace(id) .map(LocalizedTrace::from)) } @@ -85,7 +85,7 @@ impl Traces for TracesClient where C: MiningBlockChainClient + 'stat let request = CallRequest::into(request); let signed = fake_sign::sign_call(&self.client, &self.miner, request)?; - take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) + self.client.call(&signed, block.into(), to_call_analytics(flags)) .map(TraceResults::from) .map_err(errors::from_call_error) } @@ -96,13 +96,13 @@ impl Traces for TracesClient where C: MiningBlockChainClient + 'stat let tx = UntrustedRlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?; let signed = SignedTransaction::new(tx).map_err(errors::from_transaction_error)?; - take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) + self.client.call(&signed, block.into(), to_call_analytics(flags)) .map(TraceResults::from) .map_err(errors::from_call_error) } fn replay_transaction(&self, transaction_hash: H256, flags: Vec) -> Result { - take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) + self.client.replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) .map(TraceResults::from) .map_err(errors::from_call_error) } diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index a50b6ec90..8473d0f38 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -18,26 +18,6 @@ //! //! Compliant with ethereum rpc. -// Upgrade a weak pointer, returning an error on failure. -macro_rules! take_weak { - ($weak: expr) => { - match $weak.upgrade() { - Some(arc) => arc, - None => return Err(Error::internal_error()), - } - } -} - -// Upgrade a weak pointer, returning an error leaf-future on failure. -macro_rules! take_weakf { - ($weak: expr) => { - match $weak.upgrade() { - Some(arc) => arc, - None => return ::futures::future::err(Error::internal_error()).boxed(), - } - } -} - // short for "try_boxfuture" // unwrap a result, returning a BoxFuture<_, Err> on failure. macro_rules! try_bf { diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index cf5bdd88b..5f70271ee 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -141,7 +141,7 @@ impl EthTester { Default::default(), ); - let dispatcher = FullDispatcher::new(Arc::downgrade(&client), Arc::downgrade(&miner_service)); + let dispatcher = FullDispatcher::new(client.clone(), miner_service.clone()); let eth_sign = SigningUnsafeClient::new( &opt_account_provider, dispatcher, diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 3cb0626a1..701c57db4 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -92,7 +92,7 @@ impl EthTester { let eth = EthClient::new(&client, &snapshot, &sync, &opt_ap, &miner, &external_miner, options).to_delegate(); let filter = EthFilterClient::new(client.clone(), miner.clone()).to_delegate(); - let dispatcher = FullDispatcher::new(Arc::downgrade(&client), Arc::downgrade(&miner)); + let dispatcher = FullDispatcher::new(client.clone(), miner.clone()); let sign = SigningUnsafeClient::new(&opt_ap, dispatcher).to_delegate(); let mut io: IoHandler = IoHandler::default(); io.extend_with(eth); diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 8508eaacf..c7205d6ef 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -31,9 +31,6 @@ struct PersonalTester { accounts: Arc, io: IoHandler, miner: Arc, - // these unused fields are necessary to keep the data alive - // as the handler has only weak pointers. - _client: Arc, } fn blockchain_client() -> Arc { @@ -55,7 +52,7 @@ fn setup() -> PersonalTester { let client = blockchain_client(); let miner = miner_service(); - let dispatcher = FullDispatcher::new(Arc::downgrade(&client), Arc::downgrade(&miner)); + let dispatcher = FullDispatcher::new(client, miner.clone()); let personal = PersonalClient::new(&opt_accounts, dispatcher, false); let mut io = IoHandler::default(); @@ -65,7 +62,6 @@ fn setup() -> PersonalTester { accounts: accounts, io: io, miner: miner, - _client: client, }; tester @@ -220,4 +216,3 @@ fn should_unlock_account_permanently() { assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); assert!(tester.accounts.sign(address, None, Default::default()).is_ok(), "Should unlock account."); } - diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 90efe12e1..ebb113f3b 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -38,10 +38,6 @@ struct SignerTester { accounts: Arc, io: IoHandler, miner: Arc, - // these unused fields are necessary to keep the data alive - // as the handler has only weak pointers. - _client: Arc, - _event_loop: EventLoop, } fn blockchain_client() -> Arc { @@ -65,7 +61,7 @@ fn signer_tester() -> SignerTester { let miner = miner_service(); let event_loop = EventLoop::spawn(); - let dispatcher = FullDispatcher::new(Arc::downgrade(&client), Arc::downgrade(&miner)); + let dispatcher = FullDispatcher::new(client, miner.clone()); let mut io = IoHandler::default(); io.extend_with(SignerClient::new(&opt_accounts, dispatcher, &signer, event_loop.remote()).to_delegate()); @@ -74,8 +70,6 @@ fn signer_tester() -> SignerTester { accounts: accounts, io: io, miner: miner, - _client: client, - _event_loop: event_loop, } } diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index b3322da46..91d792253 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -54,7 +54,7 @@ impl Default for SigningTester { let opt_accounts = Some(accounts.clone()); let mut io = IoHandler::default(); - let dispatcher = FullDispatcher::new(Arc::downgrade(&client), Arc::downgrade(&miner)); + let dispatcher = FullDispatcher::new(client.clone(), miner.clone()); let rpc = SigningQueueClient::new(&signer, dispatcher.clone(), &opt_accounts); io.extend_with(EthSigning::to_delegate(rpc)); diff --git a/scripts/deb-build.sh b/scripts/deb-build.sh index 62fdb3cad..5682e2c29 100644 --- a/scripts/deb-build.sh +++ b/scripts/deb-build.sh @@ -27,6 +27,8 @@ echo "Vcs-Browser: https://github.com/paritytech/parity" >> $control echo "Architecture: $1" >> $control echo "Depends: libssl1.0.0 (>=1.0.0)" >> $control echo "Description: Ethereum network client by Parity Technologies" >> $control +size=`du deb/|awk 'END {print $1}'` +echo "Installed-Size: $size" >> $control #build .deb package exit diff --git a/util/src/memorydb.rs b/util/src/memorydb.rs index 7f52f0c38..ea625d227 100644 --- a/util/src/memorydb.rs +++ b/util/src/memorydb.rs @@ -28,7 +28,7 @@ use std::collections::hash_map::Entry; /// Reference-counted memory-based `HashDB` implementation. /// /// Use `new()` to create a new database. Insert items with `insert()`, remove items -/// with `remove()`, check for existence with `containce()` and lookup a hash to derive +/// with `remove()`, check for existence with `contains()` and lookup a hash to derive /// the data with `get()`. Clear with `clear()` and purge the portions of the data /// that have no references with `purge()`. ///