diff --git a/Cargo.lock b/Cargo.lock index 68dce57ce..29655346e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", "ethcore-logger 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", @@ -374,7 +374,7 @@ dependencies = [ "bloomable 0.1.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethjson 0.1.0", "hash 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -588,7 +588,7 @@ dependencies = [ "ethcore-ipc-nano 1.8.0", "ethcore-logger 1.8.0", "ethcore-stratum 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethjson 0.1.0", "ethkey 0.2.0", "ethstore 0.1.0", @@ -682,7 +682,7 @@ version = "1.8.0" dependencies = [ "ethcore-bigint 0.1.3", "ethcore-devtools 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -732,7 +732,7 @@ dependencies = [ "ethcore-ipc 1.8.0", "ethcore-ipc-codegen 1.8.0", "ethcore-ipc-nano 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -751,7 +751,7 @@ dependencies = [ "ethcore-ipc 1.8.0", "ethcore-ipc-codegen 1.8.0", "ethcore-network 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "evm 0.1.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", @@ -801,7 +801,7 @@ dependencies = [ "ethcore-devtools 1.8.0", "ethcore-io 1.8.0", "ethcore-logger 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethcrypto 0.1.0", "ethkey 0.2.0", "hash 0.1.0", @@ -836,7 +836,7 @@ dependencies = [ "ethcore-ipc-codegen 1.8.0", "ethcore-ipc-nano 1.8.0", "ethcore-logger 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethcrypto 0.1.0", "ethkey 0.2.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -871,7 +871,7 @@ dependencies = [ "ethcore-ipc-codegen 1.8.0", "ethcore-ipc-nano 1.8.0", "ethcore-logger 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "hash 0.1.0", "jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)", "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)", @@ -884,7 +884,7 @@ dependencies = [ [[package]] name = "ethcore-util" -version = "1.8.1" +version = "1.8.2" dependencies = [ "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1018,7 +1018,7 @@ dependencies = [ "ethcore-ipc-nano 1.8.0", "ethcore-light 1.8.0", "ethcore-network 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethkey 0.2.0", "hash 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1044,7 +1044,7 @@ dependencies = [ "common-types 0.1.0", "ethcore-bigint 0.1.3", "ethcore-logger 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethjson 0.1.0", "evmjit 1.8.0", "hash 0.1.0", @@ -1066,7 +1066,7 @@ dependencies = [ "ethcore 1.8.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethjson 0.1.0", "evm 0.1.0", "panic_hook 0.1.0", @@ -1364,7 +1364,7 @@ dependencies = [ "ethcore-bigint 0.1.3", "ethcore-ipc 1.8.0", "ethcore-ipc-codegen 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1857,7 +1857,7 @@ dependencies = [ "ethcore-bytes 0.1.0", "ethcore-io 1.8.0", "ethcore-network 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2056,7 +2056,7 @@ dependencies = [ [[package]] name = "parity" -version = "1.8.1" +version = "1.8.2" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2080,7 +2080,7 @@ dependencies = [ "ethcore-network 1.8.0", "ethcore-secretstore 1.0.0", "ethcore-stratum 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethkey 0.2.0", "ethsync 1.8.0", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2136,7 +2136,7 @@ dependencies = [ "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "fetch 0.1.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2198,7 +2198,7 @@ dependencies = [ "ethabi 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "fetch 0.1.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", @@ -2220,7 +2220,7 @@ dependencies = [ "ethcore 1.8.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)", "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)", "multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2234,7 +2234,7 @@ version = "0.1.0" dependencies = [ "ethcore 1.8.0", "ethcore-io 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethkey 0.2.0", "kvdb 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2249,7 +2249,7 @@ name = "parity-machine" version = "0.1.0" dependencies = [ "ethcore-bigint 0.1.3", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", ] [[package]] @@ -2277,7 +2277,7 @@ dependencies = [ "ethcore-light 1.8.0", "ethcore-logger 1.8.0", "ethcore-network 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethcrypto 0.1.0", "ethjson 0.1.0", "ethkey 0.2.0", @@ -2387,7 +2387,7 @@ dependencies = [ "ethcore-bytes 0.1.0", "ethcore-ipc 1.8.0", "ethcore-ipc-codegen 1.8.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethsync 1.8.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-common-types 1.8.0", @@ -2849,7 +2849,7 @@ name = "rpc-cli" version = "1.4.0" dependencies = [ "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rpc 1.8.0", "parity-rpc-client 1.4.0", @@ -3565,7 +3565,7 @@ dependencies = [ "common-types 0.1.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.1", + "ethcore-util 1.8.2", "ethjson 0.1.0", "evmjit 1.8.0", "hash 0.1.0", diff --git a/Cargo.toml b/Cargo.toml index 0f07dc802..68cb241c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity Ethereum client" name = "parity" -version = "1.8.1" +version = "1.8.2" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 0d3a64956..2042bbb1d 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -322,20 +322,24 @@ impl Interpreter { let init_off = stack.pop_back(); let init_size = stack.pop_back(); - let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash }; let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed"); - let contract_code = self.mem.read_slice(init_off, init_size); - let can_create = ext.balance(¶ms.address)? >= endowment && ext.depth() < ext.schedule().max_depth; + if ext.is_static() { + return Err(vm::Error::MutableCallInStaticContext); + } // clear return data buffer before creating new call frame. self.return_data = ReturnData::empty(); + let can_create = ext.balance(¶ms.address)? >= endowment && ext.depth() < ext.schedule().max_depth; if !can_create { stack.push(U256::zero()); return Ok(InstructionResult::UnusedGas(create_gas)); } + let contract_code = self.mem.read_slice(init_off, init_size); + let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash }; + let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme); return match create_result { ContractCreateResult::Created(address, gas_left) => { @@ -351,9 +355,6 @@ impl Interpreter { stack.push(U256::zero()); Ok(InstructionResult::Ok) }, - ContractCreateResult::FailedInStaticCall => { - Err(vm::Error::MutableCallInStaticContext) - }, }; }, instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => { diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index 3eb10bc6a..6e85e1803 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -724,7 +724,6 @@ fn test_jumps(factory: super::Factory) { assert_eq!(gas_left, U256::from(54_117)); } - evm_test!{test_calls: test_calls_jit, test_calls_int} fn test_calls(factory: super::Factory) { let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap(); @@ -769,6 +768,27 @@ fn test_calls(factory: super::Factory) { assert_eq!(ext.calls.len(), 2); } +evm_test!{test_create_in_staticcall: test_create_in_staticcall_jit, test_create_in_staticcall_int} +fn test_create_in_staticcall(factory: super::Factory) { + let code = "600060006064f000".from_hex().unwrap(); + + let address = Address::from(0x155); + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.address = address.clone(); + let mut ext = FakeExt::new_byzantium(); + ext.is_static = true; + + let err = { + let mut vm = factory.create(params.gas); + test_finalize(vm.exec(params, &mut ext)).unwrap_err() + }; + + assert_eq!(err, vm::Error::MutableCallInStaticContext); + assert_eq!(ext.calls.len(), 0); +} + fn assert_set_contains(set: &HashSet, val: &T) { let contains = set.contains(val); if !contains { diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index caf14967b..c7cf62276 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -240,7 +240,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> Ok(FinalizationResult{ gas_left, apply_state: false, return_data }) => { ContractCreateResult::Reverted(gas_left, return_data) }, - Err(vm::Error::MutableCallInStaticContext) => ContractCreateResult::FailedInStaticCall, _ => ContractCreateResult::Failed, } } diff --git a/ethcore/src/transaction.rs b/ethcore/src/transaction.rs index 02f77d5f3..3596f6c21 100644 --- a/ethcore/src/transaction.rs +++ b/ethcore/src/transaction.rs @@ -469,6 +469,11 @@ impl SignedTransaction { pub fn is_unsigned(&self) -> bool { self.transaction.is_unsigned() } + + /// Deconstructs this transaction back into `UnverifiedTransaction` + pub fn deconstruct(self) -> (UnverifiedTransaction, Address, Option) { + (self.transaction, self.sender, self.public) + } } /// Signed Transaction that is a part of canon blockchain. diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 574af9e82..3f5004586 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -35,9 +35,6 @@ pub enum ContractCreateResult { /// Returned when contract creation failed. /// VM doesn't have to know the reason. Failed, - /// Returned when contract creation failed. - /// VM doesn't have to know the reason. - FailedInStaticCall, /// Reverted with REVERT. Reverted(U256, ReturnData), } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index 0d7ca1f82..222578afd 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -65,6 +65,7 @@ pub struct FakeExt { pub schedule: Schedule, pub balances: HashMap, pub tracing: bool, + pub is_static: bool, } // similar to the normal `finalize` function, but ignoring NeedsReturn. @@ -192,7 +193,7 @@ impl Ext for FakeExt { } fn is_static(&self) -> bool { - false + self.is_static } fn inc_sstore_clears(&mut self) { diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index 1f8bf428a..d26346a3e 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -221,8 +221,8 @@ impl<'a, 'b> Runtime<'a, 'b> { } /// Charge gas according to closure - pub fn charge(&mut self, f: F) -> Result<(), InterpreterError> - where F: FnOnce(&vm::Schedule) -> u64 + pub fn charge(&mut self, f: F) -> Result<(), InterpreterError> + where F: FnOnce(&vm::Schedule) -> u64 { let amount = f(self.ext.schedule()); if !self.charge_gas(amount as u64) { @@ -277,10 +277,6 @@ impl<'a, 'b> Runtime<'a, 'b> { self.gas_counter = self.gas_limit - gas_left.low_u64(); Ok(Some((-1i32).into())) }, - vm::ContractCreateResult::FailedInStaticCall => { - trace!(target: "wasm", "runtime: create contract called in static context"); - Err(interpreter::Error::Trap("CREATE in static context".to_owned())) - }, } } @@ -615,11 +611,11 @@ impl<'a, 'b> Runtime<'a, 'b> { } fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<(), InterpreterError> { - let value: H256 = val.into(); + let value: H256 = val.into(); self.charge(|schedule| schedule.wasm.static_u256 as u64)?; self.memory.set(ptr, &*value)?; Ok(()) - } + } fn coinbase(&mut self, context: InterpreterCallerContext) -> Result, InterpreterError> @@ -640,7 +636,7 @@ impl<'a, 'b> Runtime<'a, 'b> { context.value_stack.pop_as::()? as u32, sender, )?; - Ok(None) + Ok(None) } fn address(&mut self, context: InterpreterCallerContext) @@ -651,7 +647,7 @@ impl<'a, 'b> Runtime<'a, 'b> { context.value_stack.pop_as::()? as u32, addr, )?; - Ok(None) + Ok(None) } fn origin(&mut self, context: InterpreterCallerContext) @@ -662,7 +658,7 @@ impl<'a, 'b> Runtime<'a, 'b> { context.value_stack.pop_as::()? as u32, origin, )?; - Ok(None) + Ok(None) } fn value(&mut self, context: InterpreterCallerContext) @@ -709,7 +705,7 @@ impl<'a, 'b> Runtime<'a, 'b> { context.value_stack.pop_as::()? as u32, gas_limit, )?; - Ok(None) + Ok(None) } fn return_i64(&mut self, val: i64) -> Result, InterpreterError> { diff --git a/mac/Parity.pkgproj b/mac/Parity.pkgproj index 111756a2f..40700589b 100755 --- a/mac/Parity.pkgproj +++ b/mac/Parity.pkgproj @@ -462,7 +462,7 @@ OVERWRITE_PERMISSIONS VERSION - 1.8.1 + 1.8.2 UUID 2DCD5B81-7BAF-4DA1-9251-6274B089FD36 diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 4bea3b740..39a5969c3 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -10,7 +10,7 @@ !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 !define VERSIONMINOR 8 -!define VERSIONBUILD 1 +!define VERSIONBUILD 2 !define ARGS "" !define FIRST_START_ARGS "ui --mode=passive" diff --git a/parity/configuration.rs b/parity/configuration.rs index a9c776c39..83b71f05d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -40,7 +40,7 @@ use parity_rpc::NetworkSettings; use cache::CacheConfig; use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, replace_home, replace_home_and_local, geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit, to_queue_strategy}; -use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras}; +use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras, SpecType}; use ethcore_logger::Config as LogConfig; use dir::{self, Directories, default_hypervisor_path, default_local_path, default_data_path}; use dapps::Configuration as DappsConfiguration; @@ -109,7 +109,7 @@ impl Configuration { let pruning = self.args.arg_pruning.parse()?; let pruning_history = self.args.arg_pruning_history; let vm_type = self.vm_type()?; - let spec = self.chain().parse()?; + let spec = self.chain()?; let mode = match self.args.arg_mode.as_ref() { "last" => None, mode => Some(to_mode(&mode, self.args.arg_mode_timeout, self.args.arg_mode_alarm)?), @@ -336,7 +336,7 @@ impl Configuration { pruning_memory: self.args.arg_pruning_memory, daemon: daemon, logger_config: logger_config.clone(), - miner_options: self.miner_options(self.args.arg_reseal_min_period)?, + miner_options: self.miner_options()?, ntp_servers: self.ntp_servers(), ws_conf: ws_conf, http_conf: http_conf, @@ -441,15 +441,16 @@ impl Configuration { } } - fn chain(&self) -> String { - if let Some(ref s) = self.spec_name_override { + fn chain(&self) -> Result { + let name = if let Some(ref s) = self.spec_name_override { s.clone() - } - else if self.args.flag_testnet { + } else if self.args.flag_testnet { "testnet".to_owned() } else { self.args.arg_chain.clone() - } + }; + + Ok(name.parse()?) } fn max_peers(&self) -> u32 { @@ -504,8 +505,9 @@ impl Configuration { } else { Ok(None) } } - fn miner_options(&self, reseal_min_period: u64) -> Result { - if self.args.flag_force_sealing && reseal_min_period == 0 { + fn miner_options(&self) -> Result { + let is_dev_chain = self.chain()? == SpecType::Dev; + if is_dev_chain && self.args.flag_force_sealing && self.args.arg_reseal_min_period == 0 { return Err("Force sealing can't be used with reseal_min_period = 0".into()); } @@ -528,7 +530,7 @@ impl Configuration { tx_queue_gas_limit: to_gas_limit(&self.args.arg_tx_queue_gas)?, tx_queue_strategy: to_queue_strategy(&self.args.arg_tx_queue_strategy)?, pending_set: to_pending_set(&self.args.arg_relay_set)?, - reseal_min_period: Duration::from_millis(reseal_min_period), + reseal_min_period: Duration::from_millis(self.args.arg_reseal_min_period), reseal_max_period: Duration::from_millis(self.args.arg_reseal_max_period), work_queue_size: self.args.arg_work_queue_size, enable_resubmission: !self.args.flag_remove_solved, @@ -883,7 +885,7 @@ impl Configuration { let net_addresses = self.net_addresses()?; Ok(NetworkSettings { name: self.args.arg_identity.clone(), - chain: self.chain(), + chain: format!("{}", self.chain()?), network_port: net_addresses.0.port(), rpc_enabled: http_conf.enabled, rpc_interface: http_conf.interface, @@ -914,8 +916,6 @@ impl Configuration { } fn directories(&self) -> Directories { - use path; - let local_path = default_local_path(); let base_path = self.args.arg_base_path.as_ref().or_else(|| self.args.arg_datadir.as_ref()).map_or_else(|| default_data_path(), |s| s.clone()); let data_path = replace_home("", &base_path); @@ -935,21 +935,6 @@ impl Configuration { let secretstore_path = replace_home(&data_path, &self.args.arg_secretstore_path); let ui_path = replace_home(&data_path, &self.args.arg_ui_path); - if self.args.flag_geth && !cfg!(windows) { - let geth_root = if self.chain() == "testnet".to_owned() { path::ethereum::test() } else { path::ethereum::default() }; - ::std::fs::create_dir_all(geth_root.as_path()).unwrap_or_else( - |e| warn!("Failed to create '{}' for geth mode: {}", &geth_root.to_str().unwrap(), e)); - } - - if cfg!(feature = "ipc") && !cfg!(feature = "windows") { - let mut path_buf = PathBuf::from(data_path.clone()); - path_buf.push("ipc"); - let ipc_path = path_buf.to_str().unwrap(); - ::std::fs::create_dir_all(ipc_path).unwrap_or_else( - |e| warn!("Failed to directory '{}' for ipc sockets: {}", ipc_path, e) - ); - } - Directories { keys: keys_path, base: data_path, @@ -1401,21 +1386,20 @@ mod tests { let conf3 = parse(&["parity", "--tx-queue-strategy", "gas"]); // then - let min_period = conf0.args.arg_reseal_min_period; - assert_eq!(conf0.miner_options(min_period).unwrap(), mining_options); + assert_eq!(conf0.miner_options().unwrap(), mining_options); mining_options.tx_queue_strategy = PrioritizationStrategy::GasFactorAndGasPrice; - assert_eq!(conf1.miner_options(min_period).unwrap(), mining_options); + assert_eq!(conf1.miner_options().unwrap(), mining_options); mining_options.tx_queue_strategy = PrioritizationStrategy::GasPriceOnly; - assert_eq!(conf2.miner_options(min_period).unwrap(), mining_options); + assert_eq!(conf2.miner_options().unwrap(), mining_options); mining_options.tx_queue_strategy = PrioritizationStrategy::GasAndGasPrice; - assert_eq!(conf3.miner_options(min_period).unwrap(), mining_options); + assert_eq!(conf3.miner_options().unwrap(), mining_options); } #[test] fn should_fail_on_force_reseal_and_reseal_min_period() { - let conf = parse(&["parity", "--chain", "dev", "--force-sealing"]); + let conf = parse(&["parity", "--chain", "dev", "--force-sealing", "--reseal-min-period", "0"]); - assert!(conf.miner_options(0).is_err()); + assert!(conf.miner_options().is_err()); } #[test] @@ -1443,7 +1427,7 @@ mod tests { // then assert_eq!(conf.network_settings(), Ok(NetworkSettings { name: "testname".to_owned(), - chain: "testnet".to_owned(), + chain: "kovan".to_owned(), network_port: 30303, rpc_enabled: true, rpc_interface: "127.0.0.1".to_owned(), diff --git a/parity/rpc.rs b/parity/rpc.rs index 12667d3ae..d0f92cf38 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -301,6 +301,12 @@ pub fn new_ipc( let handler = setup_apis(conf.apis, dependencies); let remote = dependencies.remote.clone(); + let path = PathBuf::from(&conf.socket_addr); + if let Some(dir) = path.parent() { + ::std::fs::create_dir_all(&dir) + .map_err(|err| format!("Unable to create IPC directory at {}: {}", dir.display(), err))?; + } + match rpc::start_ipc(&conf.socket_addr, handler, remote, rpc::RpcExtractor) { Ok(server) => Ok(Some(server)), Err(io_error) => Err(format!("IPC error: {}", io_error)), diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 0da257035..d84bd6cad 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -71,6 +71,9 @@ pub trait Dispatcher: Send + Sync + Clone { fn sign(&self, accounts: Arc, filled: FilledTransactionRequest, password: SignWith) -> BoxFuture, Error>; + /// Converts a `SignedTransaction` into `RichRawTransaction` + fn enrich(&self, SignedTransaction) -> RpcRichRawTransaction; + /// "Dispatch" a local transaction. fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result; } @@ -163,6 +166,11 @@ impl Dispatcher for FullDispatcher RpcRichRawTransaction { + let block_number = self.client.best_block_header().number(); + RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition()) + } + fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { let hash = signed_transaction.transaction.hash(); @@ -261,11 +269,11 @@ impl LightDispatcher { transaction_queue: Arc>, ) -> Self { LightDispatcher { - sync: sync, - client: client, - on_demand: on_demand, - cache: cache, - transaction_queue: transaction_queue, + sync, + client, + on_demand, + cache, + transaction_queue, } } @@ -399,6 +407,11 @@ impl Dispatcher for LightDispatcher { .and_then(move |nonce| with_nonce(filled, nonce))) } + fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { + let block_number = self.client.best_block_header().number(); + RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition()) + } + fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { let hash = signed_transaction.transaction.hash(); @@ -510,8 +523,8 @@ pub fn execute( }, ConfirmationPayload::SignTransaction(request) => { Box::new(dispatcher.sign(accounts, request, pass) - .map(|result| result - .map(RpcRichRawTransaction::from) + .map(move |result| result + .map(move |tx| dispatcher.enrich(tx)) .map(ConfirmationResponse::SignTransaction) )) }, diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index ac5902b51..2544f66b0 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -23,7 +23,7 @@ use ethcore::encoded; use ethcore::executed::{Executed, ExecutionError}; use ethcore::ids::BlockId; use ethcore::filter::Filter as EthcoreFilter; -use ethcore::transaction::{Action, Transaction as EthTransaction, SignedTransaction}; +use ethcore::transaction::{Action, Transaction as EthTransaction, SignedTransaction, LocalizedTransaction}; use ethcore::receipt::Receipt; use jsonrpc_core::{BoxFuture, Error}; @@ -65,13 +65,24 @@ pub struct LightFetch { /// Extract a transaction at given index. pub fn extract_transaction_at_index(block: encoded::Block, index: usize, eip86_transition: u64) -> Option { block.transactions().into_iter().nth(index) + // Verify if transaction signature is correct. .and_then(|tx| SignedTransaction::new(tx).ok()) - .map(|tx| Transaction::from_signed(tx, block.number(), eip86_transition)) - .map(|mut tx| { - tx.block_hash = Some(block.hash().into()); - tx.transaction_index = Some(index.into()); - tx + .map(|signed_tx| { + let (signed, sender, _) = signed_tx.deconstruct(); + let block_hash = block.hash(); + let block_number = block.number(); + let transaction_index = index; + let cached_sender = Some(sender); + + LocalizedTransaction { + signed, + block_number, + block_hash, + transaction_index, + cached_sender, + } }) + .map(|tx| Transaction::from_localized(tx, eip86_transition)) } diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index c864134fb..cecd1f2db 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -73,8 +73,8 @@ impl SignerClient { SignerClient { signer: signer.clone(), accounts: store.clone(), - dispatcher: dispatcher, - subscribers: subscribers, + dispatcher, + subscribers, } } @@ -205,7 +205,8 @@ impl Signer for SignerClient { }, ConfirmationPayload::SignTransaction(request) => { Self::verify_transaction(bytes, request, |pending_transaction| { - Ok(ConfirmationResponse::SignTransaction(pending_transaction.transaction.into())) + let rich = self.dispatcher.enrich(pending_transaction.transaction); + Ok(ConfirmationResponse::SignTransaction(rich)) }) }, ConfirmationPayload::EthSignMessage(address, data) => { diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 96329d18c..8bd97108c 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -547,7 +547,7 @@ fn rpc_eth_pending_transaction_by_hash() { tester.miner.pending_transactions.lock().insert(H256::zero(), tx); } - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":"0x0","chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; let request = r#"{ "jsonrpc": "2.0", "method": "eth_getTransactionByHash", @@ -863,7 +863,7 @@ fn rpc_eth_sign_transaction() { let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() + r#""raw":"0x"# + &rlp.to_hex() + r#"","# + r#""tx":{"# + - r#""blockHash":null,"blockNumber":"0x0","# + + r#""blockHash":null,"blockNumber":null,"# + &format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) + r#""condition":null,"creates":null,"# + &format!("\"from\":\"0x{:?}\",", &address) + diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index 1653a1908..ed27862ac 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -234,7 +234,7 @@ fn rpc_parity_remove_transaction() { let hash = signed.hash(); let request = r#"{"jsonrpc": "2.0", "method": "parity_removeTransaction", "params":[""#.to_owned() + &format!("0x{:?}", hash) + r#""], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":"0x0","chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0xa2e0da8a8064e0b9f93e95a53c2db6d01280efb8ac72a708d25487e67dd0f8fc","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80800101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0xa2e0da8a8064e0b9f93e95a53c2db6d01280efb8ac72a708d25487e67dd0f8fc","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80800101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#; miner.pending_transactions.lock().insert(hash, signed); assert_eq!(io.handle_request_sync(&request), Some(response.to_owned())); diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 95095cb72..af84d336a 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -456,7 +456,7 @@ fn should_confirm_sign_transaction_with_rlp() { let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() + r#""raw":"0x"# + &rlp.to_hex() + r#"","# + r#""tx":{"# + - r#""blockHash":null,"blockNumber":"0x0","# + + r#""blockHash":null,"blockNumber":null,"# + &format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) + r#""condition":null,"creates":null,"# + &format!("\"from\":\"0x{:?}\",", &address) + diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index a767bfb77..20400db52 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -25,7 +25,7 @@ use v1::impls::SigningQueueClient; use v1::metadata::Metadata; use v1::traits::{EthSigning, ParitySigning, Parity}; use v1::helpers::{SignerService, SigningQueue, FullDispatcher}; -use v1::types::ConfirmationResponse; +use v1::types::{ConfirmationResponse, RichRawTransaction}; use v1::tests::helpers::TestMinerService; use v1::tests::mocked::parity; @@ -299,7 +299,7 @@ fn should_add_sign_transaction_to_the_queue() { let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() + r#""raw":"0x"# + &rlp.to_hex() + r#"","# + r#""tx":{"# + - r#""blockHash":null,"blockNumber":"0x0","# + + r#""blockHash":null,"blockNumber":null,"# + &format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) + r#""condition":null,"creates":null,"# + &format!("\"from\":\"0x{:?}\",", &address) + @@ -326,7 +326,9 @@ fn should_add_sign_transaction_to_the_queue() { ::std::thread::spawn(move || loop { if signer.requests().len() == 1 { // respond - signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into()))); + signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction( + RichRawTransaction::from_signed(t.into(), 0x0, u64::max_value()) + ))); break } ::std::thread::sleep(Duration::from_millis(100)) diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 570c21120..dbd326488 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -158,11 +158,10 @@ pub struct RichRawTransaction { pub transaction: Transaction } - -impl From for RichRawTransaction { - fn from(t: SignedTransaction) -> Self { - // TODO: change transition to 0 when EIP-86 is commonly used. - let tx: Transaction = Transaction::from_signed(t, 0, u64::max_value()); +impl RichRawTransaction { + /// Creates new `RichRawTransaction` from `SignedTransaction`. + pub fn from_signed(tx: SignedTransaction, block_number: u64, eip86_transition: u64) -> Self { + let tx = Transaction::from_signed(tx, block_number, eip86_transition); RichRawTransaction { raw: tx.raw.clone(), transaction: tx, @@ -213,7 +212,7 @@ impl Transaction { hash: t.hash().into(), nonce: t.nonce.into(), block_hash: None, - block_number: Some(block_number.into()), + block_number: None, transaction_index: None, from: t.sender().into(), to: match t.action { diff --git a/util/Cargo.toml b/util/Cargo.toml index 8b5a7e476..349c48980 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore utility library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-util" -version = "1.8.1" +version = "1.8.2" authors = ["Parity Technologies "] build = "build.rs"