Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b6588cb27 | ||
|
|
0e4a06d078 | ||
|
|
d470773fec | ||
|
|
8f0eb3e192 | ||
|
|
48c7e4ab8c | ||
|
|
8362bc7f2d | ||
|
|
284fc65c70 | ||
|
|
9882902f31 | ||
|
|
789c85561e | ||
|
|
18dff68278 | ||
|
|
d9a92c2bea | ||
|
|
2145388103 | ||
|
|
77d00e3dab | ||
|
|
aa6909ff99 | ||
|
|
0085d6a47b |
72
Cargo.lock
generated
72
Cargo.lock
generated
@@ -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.0",
|
||||
"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.0",
|
||||
"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)",
|
||||
@@ -542,7 +542,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethabi"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-hex 1.0.0 (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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"ethcore-util 1.8.2",
|
||||
"ethcrypto 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
"hash 0.1.0",
|
||||
@@ -827,7 +827,7 @@ name = "ethcore-secretstore"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.8.0",
|
||||
"ethcore-bigint 0.1.3",
|
||||
"ethcore-bytes 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.0",
|
||||
"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.0",
|
||||
"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.0"
|
||||
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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"ethcore-util 1.8.2",
|
||||
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1809,7 +1809,7 @@ dependencies = [
|
||||
name = "native-contract-generator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heck 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1818,7 +1818,7 @@ name = "native-contracts"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.1.3",
|
||||
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-contract-generator 0.1.0",
|
||||
@@ -1857,7 +1857,7 @@ dependencies = [
|
||||
"ethcore-bytes 0.1.0",
|
||||
"ethcore-io 1.8.0",
|
||||
"ethcore-network 1.8.0",
|
||||
"ethcore-util 1.8.0",
|
||||
"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.0"
|
||||
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.0",
|
||||
"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.0",
|
||||
"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)",
|
||||
@@ -2195,10 +2195,10 @@ dependencies = [
|
||||
name = "parity-hash-fetch"
|
||||
version = "1.8.0"
|
||||
dependencies = [
|
||||
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"ethcore-util 1.8.2",
|
||||
"ethcrypto 0.1.0",
|
||||
"ethjson 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
@@ -2358,7 +2358,7 @@ name = "parity-ui"
|
||||
version = "1.8.0"
|
||||
dependencies = [
|
||||
"parity-ui-dev 1.8.0",
|
||||
"parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)",
|
||||
"parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git?branch=beta)",
|
||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -2372,7 +2372,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "parity-ui-precompiled"
|
||||
version = "1.4.0"
|
||||
source = "git+https://github.com/paritytech/js-precompiled.git#7f18ddb380a06977d1028501d5930023b5cc9a26"
|
||||
source = "git+https://github.com/paritytech/js-precompiled.git?branch=beta#3fc3409a902f5c8dc1360592b228b05755f042a9"
|
||||
dependencies = [
|
||||
"parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -2381,13 +2381,13 @@ dependencies = [
|
||||
name = "parity-updater"
|
||||
version = "1.8.0"
|
||||
dependencies = [
|
||||
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.8.0",
|
||||
"ethcore-bigint 0.1.3",
|
||||
"ethcore-bytes 0.1.0",
|
||||
"ethcore-ipc 1.8.0",
|
||||
"ethcore-ipc-codegen 1.8.0",
|
||||
"ethcore-util 1.8.0",
|
||||
"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.0",
|
||||
"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.0",
|
||||
"ethcore-util 1.8.2",
|
||||
"ethjson 0.1.0",
|
||||
"evmjit 1.8.0",
|
||||
"hash 0.1.0",
|
||||
@@ -3721,7 +3721,7 @@ dependencies = [
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum error-chain 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5c82c815138e278b8dcdeffc49f27ea6ffb528403e9dea4194f2e3dd40b143"
|
||||
"checksum eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
|
||||
"checksum ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3d62319ee0f35abf20afe8859dd2668195912614346447bb2dee9fb8da7c62"
|
||||
"checksum ethabi 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6af84a622f9169efc6ead7f70043ca2058ef261c50e5e1e2ac60ccd381e386"
|
||||
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
|
||||
"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423"
|
||||
"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
|
||||
@@ -3814,7 +3814,7 @@ dependencies = [
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
"checksum parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddaeb8543c6823e93dae65a25eb8083ebfeee8f0000031119d7a0055b2e8fc63"
|
||||
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
|
||||
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)" = "<none>"
|
||||
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git?branch=beta)" = "<none>"
|
||||
"checksum parity-wasm 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4502e18417d96bd8e72fca9ea4cc18f4d80288ff565582d10aefe86f18b4fc3"
|
||||
"checksum parity-wordlist 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81451bfab101d186f8fc4a0aa13cb5539b31b02c4ed96425a0842e2a413daba6"
|
||||
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity"
|
||||
version = "1.8.0"
|
||||
version = "1.8.2"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
@@ -12,7 +12,7 @@ rustc_version = "0.1"
|
||||
[dependencies]
|
||||
parity-ui-dev = { path = "../../js", optional = true }
|
||||
# This is managed by the js/scripts/release.sh script on CI - keep it in a single line
|
||||
parity-ui-precompiled = { git = "https://github.com/paritytech/js-precompiled.git", optional = true, branch = "master" }
|
||||
parity-ui-precompiled = { git = "https://github.com/paritytech/js-precompiled.git", optional = true, branch = "beta" }
|
||||
|
||||
[features]
|
||||
no-precompiled-js = ["parity-ui-dev"]
|
||||
|
||||
@@ -322,20 +322,24 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
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<Cost: CostType> Interpreter<Cost> {
|
||||
stack.push(U256::zero());
|
||||
Ok(InstructionResult::Ok)
|
||||
},
|
||||
ContractCreateResult::FailedInStaticCall => {
|
||||
Err(vm::Error::MutableCallInStaticContext)
|
||||
},
|
||||
};
|
||||
},
|
||||
instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => {
|
||||
|
||||
@@ -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<T : Debug + Eq + PartialEq + Hash>(set: &HashSet<T>, val: &T) {
|
||||
let contains = set.contains(val);
|
||||
if !contains {
|
||||
|
||||
@@ -30,11 +30,14 @@
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x400",
|
||||
"registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x2A",
|
||||
"forkBlock": 4297256,
|
||||
"forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f",
|
||||
"validateReceiptsTransition" : 1000000,
|
||||
"eip155Transition": 1000000
|
||||
"eip155Transition": 1000000,
|
||||
"validateChainIdTransition": 1000000
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"eip160Transition": 1915000,
|
||||
"ecip1010PauseTransition": 1915000,
|
||||
"ecip1010ContinueTransition": 3415000,
|
||||
"ecip1017EraRounds": 2000000,
|
||||
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff"
|
||||
@@ -49,11 +50,13 @@
|
||||
"gasLimit": "0x2fefd8"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303",
|
||||
"enode://ceb5c0f85eb994dbe9693bf46d99b03f6b838d17cc74e68d5eb003171ff39e5f120b17f965b267c319303f94d80b9d994b77062fb1486d76ce95d9f3d8fe1cb4@46.101.122.141:30303",
|
||||
"enode://fb28713820e718066a2f5df6250ae9d07cff22f672dbf26be6c75d088f821a9ad230138ba492c533a80407d054b1436ef18e951bb65e6901553516c8dffe8ff0@104.155.176.151:30304",
|
||||
"enode://afdc6076b9bf3e7d3d01442d6841071e84c76c73a7016cb4f35c0437df219db38565766234448f1592a07ba5295a867f0ce87b359bf50311ed0b830a2361392d@104.154.136.117:30403",
|
||||
"enode://21101a9597b79e933e17bc94ef3506fe99a137808907aa8fefa67eea4b789792ad11fb391f38b00087f8800a2d3dff011572b62a31232133dd1591ac2d1502c8@104.198.71.200:30403"
|
||||
"enode://21101a9597b79e933e17bc94ef3506fe99a137808907aa8fefa67eea4b789792ad11fb391f38b00087f8800a2d3dff011572b62a31232133dd1591ac2d1502c8@104.198.71.200:30403",
|
||||
"enode://fd008499e9c4662f384b3cff23438879d31ced24e2d19504c6389bc6da6c882f9c2f8dbed972f7058d7650337f54e4ba17bb49c7d11882dd1731d26a6e62e3cb@35.187.57.94:30304",
|
||||
"enode://30a1fd71f28aa6f66fe662af9ecc75f0a6980f06b71598f2b19d3dda04223fc0e53b47e40c9171d5014e9f5b59d9954de125782da592f5d95ea39066e2591d5d@104.237.131.102:30304",
|
||||
"enode://7909d51011d8a153351169f21d3a7bbedb3be1e17d38c1f2fad06504dd5aa07a00f00845835d535fe702bf379c4d7209a51f4d1b723e0ca8b8732bd21fba3b30@139.162.133.42:30303",
|
||||
"enode://a088dfb2f5305be9232e8071c5535f13718a4017e247a0b35074b807d43d99e022880c27302cdb5b1e98ad34c083dbbb483f2b17bdc66149bad037154d6ace96@139.162.127.72:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
|
||||
@@ -269,7 +269,7 @@ impl AccountProvider {
|
||||
|
||||
/// Checks whether an account with a given address is present.
|
||||
pub fn has_account(&self, address: Address) -> Result<bool, Error> {
|
||||
Ok(self.accounts()?.iter().any(|&a| a == address))
|
||||
Ok(self.sstore.account_ref(&address).is_ok() && !self.blacklisted_accounts.contains(&address))
|
||||
}
|
||||
|
||||
/// Returns addresses of all accounts.
|
||||
|
||||
@@ -123,7 +123,11 @@ impl Pricer for ModexpPricer {
|
||||
|
||||
let adjusted_exp_len = Self::adjusted_exp_len(exp_len, exp_low);
|
||||
|
||||
(Self::mult_complexity(m) * max(adjusted_exp_len, 1) / self.divisor as u64).into()
|
||||
let (gas, overflow) = Self::mult_complexity(m).overflowing_mul(max(adjusted_exp_len, 1));
|
||||
if overflow {
|
||||
return U256::max_value();
|
||||
}
|
||||
(gas / self.divisor as u64).into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,6 +710,14 @@ mod tests {
|
||||
activate_at: 0,
|
||||
};
|
||||
|
||||
// test for potential gas cost multiplication overflow
|
||||
{
|
||||
let input = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b27bafd00000000000000000000000000000000000000000000000000000000503c8ac3").unwrap();
|
||||
let expected_cost = U256::max_value();
|
||||
assert_eq!(f.cost(&input[..]), expected_cost.into());
|
||||
}
|
||||
|
||||
|
||||
// test for potential exp len overflow
|
||||
{
|
||||
let input = FromHex::from_hex("\
|
||||
|
||||
@@ -31,7 +31,7 @@ use machine::EthereumMachine;
|
||||
use super::spec::*;
|
||||
|
||||
/// Most recent fork block that we support on Mainnet.
|
||||
pub const FORK_SUPPORTED_FOUNDATION: u64 = 2675000;
|
||||
pub const FORK_SUPPORTED_FOUNDATION: u64 = 4370000;
|
||||
|
||||
/// Most recent fork block that we support on Ropsten.
|
||||
pub const FORK_SUPPORTED_ROPSTEN: u64 = 10;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +351,9 @@ impl EthereumMachine {
|
||||
None => true,
|
||||
};
|
||||
|
||||
let chain_id = if header.number() >= self.params().eip155_transition {
|
||||
let chain_id = if header.number() < self.params().validate_chain_id_transition {
|
||||
t.chain_id()
|
||||
} else if header.number() >= self.params().eip155_transition {
|
||||
Some(self.params().chain_id)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -647,10 +647,6 @@ impl Miner {
|
||||
condition: Option<TransactionCondition>,
|
||||
transaction_queue: &mut BanningTransactionQueue,
|
||||
) -> Vec<Result<TransactionImportResult, Error>> {
|
||||
let accounts = self.accounts.as_ref()
|
||||
.and_then(|provider| provider.accounts().ok())
|
||||
.map(|accounts| accounts.into_iter().collect::<HashSet<_>>());
|
||||
|
||||
let best_block_header = client.best_block_header().decode();
|
||||
let insertion_time = client.chain_info().best_block_number;
|
||||
|
||||
@@ -669,8 +665,8 @@ impl Miner {
|
||||
Err(e)
|
||||
},
|
||||
Ok(transaction) => {
|
||||
let origin = accounts.as_ref().and_then(|accounts| {
|
||||
match accounts.contains(&transaction.sender()) {
|
||||
let origin = self.accounts.as_ref().and_then(|accounts| {
|
||||
match accounts.has_account(transaction.sender()).unwrap_or(false) {
|
||||
true => Some(TransactionOrigin::Local),
|
||||
false => None,
|
||||
}
|
||||
|
||||
@@ -85,6 +85,8 @@ pub struct CommonParams {
|
||||
pub eip155_transition: BlockNumber,
|
||||
/// Validate block receipts root.
|
||||
pub validate_receipts_transition: BlockNumber,
|
||||
/// Validate transaction chain id.
|
||||
pub validate_chain_id_transition: BlockNumber,
|
||||
/// Number of first block where EIP-86 (Metropolis) rules begin.
|
||||
pub eip86_transition: BlockNumber,
|
||||
/// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin.
|
||||
@@ -153,7 +155,7 @@ impl CommonParams {
|
||||
self.validate_receipts_transition != 0 && self.eip86_transition != 0 &&
|
||||
self.eip140_transition != 0 && self.eip210_transition != 0 &&
|
||||
self.eip211_transition != 0 && self.eip214_transition != 0 &&
|
||||
self.dust_protection_transition != 0
|
||||
self.validate_chain_id_transition != 0 && self.dust_protection_transition != 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +180,7 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
eip98_transition: p.eip98_transition.map_or(0, Into::into),
|
||||
eip155_transition: p.eip155_transition.map_or(0, Into::into),
|
||||
validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
|
||||
validate_chain_id_transition: p.validate_chain_id_transition.map_or(0, Into::into),
|
||||
eip86_transition: p.eip86_transition.map_or(
|
||||
BlockNumber::max_value(),
|
||||
Into::into,
|
||||
|
||||
@@ -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<Public>) {
|
||||
(self.transaction, self.sender, self.public)
|
||||
}
|
||||
}
|
||||
|
||||
/// Signed Transaction that is a part of canon blockchain.
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ pub struct FakeExt {
|
||||
pub schedule: Schedule,
|
||||
pub balances: HashMap<Address, U256>,
|
||||
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) {
|
||||
|
||||
@@ -221,8 +221,8 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
}
|
||||
|
||||
/// Charge gas according to closure
|
||||
pub fn charge<F>(&mut self, f: F) -> Result<(), InterpreterError>
|
||||
where F: FnOnce(&vm::Schedule) -> u64
|
||||
pub fn charge<F>(&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<Option<interpreter::RuntimeValue>, InterpreterError>
|
||||
@@ -640,7 +636,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
context.value_stack.pop_as::<i32>()? 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::<i32>()? 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::<i32>()? 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::<i32>()? as u32,
|
||||
gas_limit,
|
||||
)?;
|
||||
Ok(None)
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn return_i64(&mut self, val: i64) -> Result<Option<interpreter::RuntimeValue>, InterpreterError> {
|
||||
|
||||
@@ -122,6 +122,13 @@ impl<T> DiskDirectory<T> where T: KeyFileManager {
|
||||
Ok(hasher.finish())
|
||||
}
|
||||
|
||||
fn last_modification_date(&self) -> Result<u64, Error> {
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
let duration = fs::metadata(&self.path)?.modified()?.duration_since(UNIX_EPOCH).unwrap_or(Duration::default());
|
||||
let timestamp = duration.as_secs() ^ (duration.subsec_nanos() as u64);
|
||||
Ok(timestamp)
|
||||
}
|
||||
|
||||
/// all accounts found in keys directory
|
||||
fn files_content(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> {
|
||||
// it's not done using one iterator cause
|
||||
@@ -226,7 +233,7 @@ impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
|
||||
}
|
||||
|
||||
fn unique_repr(&self) -> Result<u64, Error> {
|
||||
self.files_hash()
|
||||
self.last_modification_date()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ use std::collections::{BTreeMap, HashMap};
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
use crypto::KEY_ITERATIONS;
|
||||
use random::Random;
|
||||
@@ -28,6 +29,8 @@ use presale::PresaleWallet;
|
||||
use json::{self, Uuid, OpaqueKeyFile};
|
||||
use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret};
|
||||
|
||||
const REFRESH_TIME_SEC: u64 = 5;
|
||||
|
||||
/// Accounts store.
|
||||
pub struct EthStore {
|
||||
store: EthMultiStore,
|
||||
@@ -245,7 +248,12 @@ pub struct EthMultiStore {
|
||||
// order lock: cache, then vaults
|
||||
cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>,
|
||||
vaults: Mutex<HashMap<String, Box<VaultKeyDirectory>>>,
|
||||
dir_hash: Mutex<Option<u64>>,
|
||||
timestamp: Mutex<Timestamp>,
|
||||
}
|
||||
|
||||
struct Timestamp {
|
||||
dir_hash: Option<u64>,
|
||||
last_checked: Instant,
|
||||
}
|
||||
|
||||
impl EthMultiStore {
|
||||
@@ -261,20 +269,27 @@ impl EthMultiStore {
|
||||
vaults: Mutex::new(HashMap::new()),
|
||||
iterations: iterations,
|
||||
cache: Default::default(),
|
||||
dir_hash: Default::default(),
|
||||
timestamp: Mutex::new(Timestamp {
|
||||
dir_hash: None,
|
||||
last_checked: Instant::now(),
|
||||
}),
|
||||
};
|
||||
store.reload_accounts()?;
|
||||
Ok(store)
|
||||
}
|
||||
|
||||
fn reload_if_changed(&self) -> Result<(), Error> {
|
||||
let mut last_dir_hash = self.dir_hash.lock();
|
||||
let dir_hash = Some(self.dir.unique_repr()?);
|
||||
if *last_dir_hash == dir_hash {
|
||||
return Ok(())
|
||||
let mut last_timestamp = self.timestamp.lock();
|
||||
let now = Instant::now();
|
||||
if (now - last_timestamp.last_checked) > Duration::from_secs(REFRESH_TIME_SEC) {
|
||||
let dir_hash = Some(self.dir.unique_repr()?);
|
||||
last_timestamp.last_checked = now;
|
||||
if last_timestamp.dir_hash == dir_hash {
|
||||
return Ok(())
|
||||
}
|
||||
self.reload_accounts()?;
|
||||
last_timestamp.dir_hash = dir_hash;
|
||||
}
|
||||
self.reload_accounts()?;
|
||||
*last_dir_hash = dir_hash;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -455,11 +470,11 @@ impl SimpleSecretStore for EthMultiStore {
|
||||
}
|
||||
|
||||
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error> {
|
||||
use std::collections::Bound;
|
||||
self.reload_if_changed()?;
|
||||
self.cache.read().keys()
|
||||
.find(|r| &r.address == address)
|
||||
.cloned()
|
||||
.ok_or(Error::InvalidAccount)
|
||||
let cache = self.cache.read();
|
||||
let mut r = cache.range((Bound::Included(*address), Bound::Included(*address)));
|
||||
r.next().ok_or(Error::InvalidAccount).map(|(k, _)| k.clone())
|
||||
}
|
||||
|
||||
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error> {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::path::PathBuf;
|
||||
use std::cmp::Ordering;
|
||||
use ethkey::{Address, Message, Signature, Secret, Public};
|
||||
use Error;
|
||||
use json::{Uuid, OpaqueKeyFile};
|
||||
@@ -32,12 +33,24 @@ pub enum SecretVaultRef {
|
||||
}
|
||||
|
||||
/// Stored account reference
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Ord)]
|
||||
pub struct StoreAccountRef {
|
||||
/// Vault reference
|
||||
pub vault: SecretVaultRef,
|
||||
/// Account address
|
||||
pub address: Address,
|
||||
/// Vault reference
|
||||
pub vault: SecretVaultRef,
|
||||
}
|
||||
|
||||
impl PartialOrd for StoreAccountRef {
|
||||
fn partial_cmp(&self, other: &StoreAccountRef) -> Option<Ordering> {
|
||||
Some(self.address.cmp(&other.address).then_with(|| self.vault.cmp(&other.vault)))
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::borrow::Borrow<Address> for StoreAccountRef {
|
||||
fn borrow(&self) -> &Address {
|
||||
&self.address
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple Secret Store API
|
||||
|
||||
@@ -37,8 +37,8 @@ use trezor_sys::messages::{EthereumAddress, PinMatrixAck, MessageType, EthereumT
|
||||
|
||||
const TREZOR_VID: u16 = 0x534c;
|
||||
const TREZOR_PIDS: [u16; 1] = [0x0001]; // Trezor v1, keeping this as an array to leave room for Trezor v2 which is in progress
|
||||
const ETH_DERIVATION_PATH: [u32; 4] = [0x8000002C, 0x8000003C, 0x80000000, 0]; // m/44'/60'/0'/0
|
||||
const ETC_DERIVATION_PATH: [u32; 4] = [0x8000002C, 0x8000003D, 0x80000000, 0]; // m/44'/61'/0'/0
|
||||
const ETH_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003C, 0x80000000, 0, 0]; // m/44'/60'/0'/0/0
|
||||
const ETC_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003D, 0x80000000, 0, 0]; // m/44'/61'/0'/0/0
|
||||
|
||||
|
||||
/// Hardware wallet error.
|
||||
|
||||
@@ -206,7 +206,7 @@ export default class CertifiersMonitor {
|
||||
// Fetch the address, name and owner in one batch
|
||||
return querier(this.api, { address: instance.address, from, limit }, instance.badge)
|
||||
.then((results) => {
|
||||
this.certifiers = results
|
||||
const certifiers = results
|
||||
.map(([ address, name, owner ], index) => ({
|
||||
address, owner,
|
||||
id: index + from,
|
||||
@@ -225,7 +225,7 @@ export default class CertifiersMonitor {
|
||||
}, {});
|
||||
|
||||
// Fetch the meta-data in serie
|
||||
return Object.values(this.certifiers).reduce((promise, certifier) => {
|
||||
return Object.values(certifiers).reduce((promise, certifier) => {
|
||||
return promise.then(() => badgeReg.fetchMeta(certifier.id))
|
||||
.then((meta) => {
|
||||
this.certifiers[certifier.id] = { ...certifier, ...meta };
|
||||
@@ -274,8 +274,6 @@ export default class CertifiersMonitor {
|
||||
.then((certified) => {
|
||||
const { id, title, icon, name } = certifier;
|
||||
|
||||
this.fetchedAccounts[address] = true;
|
||||
|
||||
if (!certified) {
|
||||
return this.store.dispatch(removeCertification(address, id));
|
||||
}
|
||||
@@ -283,7 +281,10 @@ export default class CertifiersMonitor {
|
||||
log.debug('seen as certified', { address, id, name, icon });
|
||||
this.store.dispatch(addCertification(address, id, name, title, icon));
|
||||
});
|
||||
}, Promise.resolve());
|
||||
}, Promise.resolve())
|
||||
.then(() => {
|
||||
this.fetchedAccounts[address] = true;
|
||||
});
|
||||
}
|
||||
|
||||
setCertifiersFilter () {
|
||||
|
||||
@@ -71,7 +71,6 @@ function loadCachedTokens (tokenRegContract) {
|
||||
// Check if we have data from the right contract
|
||||
if (cached.tokenreg === tokenRegContract.address && cached.tokens) {
|
||||
log.debug('found cached tokens', cached.tokens);
|
||||
dispatch(_setTokens(cached.tokens));
|
||||
|
||||
// Fetch all the tokens images on load
|
||||
// (it's the only thing that might have changed)
|
||||
@@ -105,22 +104,13 @@ export function loadTokens (options = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function loadTokensBasics (_tokenIndexes, options) {
|
||||
export function loadTokensBasics (tokenIndexes, options) {
|
||||
const limit = 64;
|
||||
|
||||
return (dispatch, getState) => {
|
||||
const { api, tokens } = getState();
|
||||
const { api } = getState();
|
||||
const { tokenReg } = Contracts.get();
|
||||
const nextTokens = {};
|
||||
const prevTokensIndexes = Object.values(tokens).map((t) => t.index);
|
||||
|
||||
// Only fetch tokens we don't have yet
|
||||
const tokenIndexes = _tokenIndexes
|
||||
.filter((tokenIndex) => {
|
||||
return !prevTokensIndexes.includes(tokenIndex);
|
||||
})
|
||||
.sort();
|
||||
|
||||
const count = tokenIndexes.length;
|
||||
|
||||
log.debug('loading basic tokens', tokenIndexes);
|
||||
@@ -240,6 +230,7 @@ function fetchTokensData (tokenRegContract, tokenIndexes) {
|
||||
log.debug('fetched', { fullResults, partialResults });
|
||||
|
||||
return [].concat(fullResults, partialResults)
|
||||
.filter(({ address }) => !/0x0*$/.test(address))
|
||||
.reduce((tokens, token) => {
|
||||
const { id, image, address } = token;
|
||||
|
||||
|
||||
@@ -32,14 +32,19 @@ class TokenImage extends Component {
|
||||
}).isRequired
|
||||
};
|
||||
|
||||
state = {
|
||||
error: false
|
||||
};
|
||||
|
||||
render () {
|
||||
const { error } = this.state;
|
||||
const { api } = this.context;
|
||||
const { image, token } = this.props;
|
||||
|
||||
const imageurl = token.image || image;
|
||||
let imagesrc = unknownImage;
|
||||
|
||||
if (imageurl) {
|
||||
if (imageurl && !error) {
|
||||
const host = /^(\/)?api/.test(imageurl)
|
||||
? api.dappsUrl
|
||||
: '';
|
||||
@@ -49,11 +54,16 @@ class TokenImage extends Component {
|
||||
|
||||
return (
|
||||
<img
|
||||
src={ imagesrc }
|
||||
alt={ token.name }
|
||||
onError={ this.handleError }
|
||||
src={ imagesrc }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
handleError = () => {
|
||||
this.setState({ error: true });
|
||||
};
|
||||
}
|
||||
|
||||
function mapStateToProps (iniState) {
|
||||
|
||||
@@ -55,9 +55,14 @@ export function fetchTokensBasics (api, tokenReg, start = 0, limit = 100) {
|
||||
return api.eth
|
||||
.call({ data: tokenAddressesBytcode + tokenAddressesCallData })
|
||||
.then((result) => {
|
||||
const tokenAddresses = decodeArray(api, 'address[]', result);
|
||||
|
||||
return decodeArray(api, 'address[]', result);
|
||||
})
|
||||
.then((tokenAddresses) => {
|
||||
return tokenAddresses.map((tokenAddress, index) => {
|
||||
if (/^0x0*$/.test(tokenAddress)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tokenIndex = start + index;
|
||||
|
||||
return {
|
||||
@@ -68,6 +73,17 @@ export function fetchTokensBasics (api, tokenReg, start = 0, limit = 100) {
|
||||
fetched: false
|
||||
};
|
||||
});
|
||||
})
|
||||
.then((tokens) => tokens.filter((token) => token))
|
||||
.then((tokens) => {
|
||||
const randomAddress = sha3(`${Date.now()}`).substr(0, 42);
|
||||
|
||||
return fetchTokensBalances(api, tokens, [randomAddress])
|
||||
.then((_balances) => {
|
||||
const balances = _balances[randomAddress];
|
||||
|
||||
return tokens.filter(({ id }) => balances[id].eq(0));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ pub struct Params {
|
||||
#[serde(rename="eip155Transition")]
|
||||
pub eip155_transition: Option<Uint>,
|
||||
/// See `CommonParams` docs.
|
||||
#[serde(rename="validateChainIdTransition")]
|
||||
pub validate_chain_id_transition: Option<Uint>,
|
||||
/// See `CommonParams` docs.
|
||||
#[serde(rename="validateReceiptsTransition")]
|
||||
pub validate_receipts_transition: Option<Uint>,
|
||||
/// See `CommonParams` docs.
|
||||
|
||||
@@ -462,7 +462,7 @@
|
||||
<key>OVERWRITE_PERMISSIONS</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>1.8.0</string>
|
||||
<string>1.8.2</string>
|
||||
</dict>
|
||||
<key>UUID</key>
|
||||
<string>2DCD5B81-7BAF-4DA1-9251-6274B089FD36</string>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
||||
!define VERSIONMAJOR 1
|
||||
!define VERSIONMINOR 8
|
||||
!define VERSIONBUILD 0
|
||||
!define ARGS "--warp"
|
||||
!define FIRST_START_ARGS "ui --warp --mode=passive"
|
||||
!define VERSIONBUILD 2
|
||||
!define ARGS ""
|
||||
!define FIRST_START_ARGS "ui --mode=passive"
|
||||
|
||||
!addplugindir .\
|
||||
|
||||
|
||||
@@ -1203,6 +1203,16 @@ mod tests {
|
||||
use toml;
|
||||
use clap::{ErrorKind as ClapErrorKind};
|
||||
|
||||
|
||||
#[test]
|
||||
fn should_reject_invalid_values() {
|
||||
let args = Args::parse(&["parity", "--cache=20"]);
|
||||
assert!(args.is_ok());
|
||||
|
||||
let args = Args::parse(&["parity", "--cache=asd"]);
|
||||
assert!(args.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_args_and_flags() {
|
||||
let args = Args::parse(&["parity", "--no-warp"]).unwrap();
|
||||
|
||||
@@ -32,6 +32,20 @@ macro_rules! otry {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! return_if_parse_error {
|
||||
($e:expr) => (
|
||||
match $e {
|
||||
Err(clap_error @ ClapError { kind: ClapErrorKind::ValueValidation, .. }) => {
|
||||
return Err(clap_error);
|
||||
},
|
||||
|
||||
// Otherwise, if $e is ClapErrorKind::ArgumentNotFound or Ok(),
|
||||
// then convert to Option
|
||||
_ => $e.ok()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! if_option {
|
||||
(Option<$type:ty>, THEN {$($then:tt)*} ELSE {$($otherwise:tt)*}) => (
|
||||
$($then)*
|
||||
@@ -139,7 +153,7 @@ macro_rules! usage {
|
||||
use std::{fs, io, process};
|
||||
use std::io::{Read, Write};
|
||||
use util::version;
|
||||
use clap::{Arg, App, SubCommand, AppSettings, Error as ClapError};
|
||||
use clap::{Arg, App, SubCommand, AppSettings, Error as ClapError, ErrorKind as ClapErrorKind};
|
||||
use helpers::replace_home;
|
||||
use std::ffi::OsStr;
|
||||
use std::collections::HashMap;
|
||||
@@ -563,23 +577,23 @@ macro_rules! usage {
|
||||
raw_args.$flag = matches.is_present(stringify!($flag));
|
||||
)*
|
||||
$(
|
||||
raw_args.$arg = if_option!(
|
||||
raw_args.$arg = return_if_parse_error!(if_option!(
|
||||
$($arg_type_tt)+,
|
||||
THEN {
|
||||
if_option_vec!(
|
||||
$($arg_type_tt)+,
|
||||
THEN { values_t!(matches, stringify!($arg), inner_option_vec_type!($($arg_type_tt)+)).ok() }
|
||||
ELSE { value_t!(matches, stringify!($arg), inner_option_type!($($arg_type_tt)+)).ok() }
|
||||
THEN { values_t!(matches, stringify!($arg), inner_option_vec_type!($($arg_type_tt)+)) }
|
||||
ELSE { value_t!(matches, stringify!($arg), inner_option_type!($($arg_type_tt)+)) }
|
||||
)
|
||||
}
|
||||
ELSE {
|
||||
if_vec!(
|
||||
$($arg_type_tt)+,
|
||||
THEN { values_t!(matches, stringify!($arg), inner_vec_type!($($arg_type_tt)+)).ok() }
|
||||
ELSE { value_t!(matches, stringify!($arg), $($arg_type_tt)+).ok() }
|
||||
THEN { values_t!(matches, stringify!($arg), inner_vec_type!($($arg_type_tt)+)) }
|
||||
ELSE { value_t!(matches, stringify!($arg), $($arg_type_tt)+) }
|
||||
)
|
||||
}
|
||||
);
|
||||
));
|
||||
)*
|
||||
)*
|
||||
|
||||
@@ -594,23 +608,23 @@ macro_rules! usage {
|
||||
)*
|
||||
// Subcommand arguments
|
||||
$(
|
||||
raw_args.$subc_arg = if_option!(
|
||||
raw_args.$subc_arg = return_if_parse_error!(if_option!(
|
||||
$($subc_arg_type_tt)+,
|
||||
THEN {
|
||||
if_option_vec!(
|
||||
$($subc_arg_type_tt)+,
|
||||
THEN { values_t!(submatches, stringify!($subc_arg), inner_option_vec_type!($($subc_arg_type_tt)+)).ok() }
|
||||
ELSE { value_t!(submatches, stringify!($subc_arg), inner_option_type!($($subc_arg_type_tt)+)).ok() }
|
||||
THEN { values_t!(submatches, stringify!($subc_arg), inner_option_vec_type!($($subc_arg_type_tt)+)) }
|
||||
ELSE { value_t!(submatches, stringify!($subc_arg), inner_option_type!($($subc_arg_type_tt)+)) }
|
||||
)
|
||||
}
|
||||
ELSE {
|
||||
if_vec!(
|
||||
$($subc_arg_type_tt)+,
|
||||
THEN { values_t!(submatches, stringify!($subc_arg), inner_vec_type!($($subc_arg_type_tt)+)).ok() }
|
||||
ELSE { value_t!(submatches, stringify!($subc_arg), $($subc_arg_type_tt)+).ok() }
|
||||
THEN { values_t!(submatches, stringify!($subc_arg), inner_vec_type!($($subc_arg_type_tt)+)) }
|
||||
ELSE { value_t!(submatches, stringify!($subc_arg), $($subc_arg_type_tt)+) }
|
||||
)
|
||||
}
|
||||
);
|
||||
));
|
||||
)*
|
||||
|
||||
// Sub-subcommands
|
||||
@@ -624,23 +638,23 @@ macro_rules! usage {
|
||||
)*
|
||||
// Sub-subcommand arguments
|
||||
$(
|
||||
raw_args.$subc_subc_arg = if_option!(
|
||||
raw_args.$subc_subc_arg = return_if_parse_error!(if_option!(
|
||||
$($subc_subc_arg_type_tt)+,
|
||||
THEN {
|
||||
if_option_vec!(
|
||||
$($subc_subc_arg_type_tt)+,
|
||||
THEN { values_t!(subsubmatches, stringify!($subc_subc_arg), inner_option_vec_type!($($subc_subc_arg_type_tt)+)).ok() }
|
||||
ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), inner_option_type!($($subc_subc_arg_type_tt)+)).ok() }
|
||||
THEN { values_t!(subsubmatches, stringify!($subc_subc_arg), inner_option_vec_type!($($subc_subc_arg_type_tt)+)) }
|
||||
ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), inner_option_type!($($subc_subc_arg_type_tt)+)) }
|
||||
)
|
||||
}
|
||||
ELSE {
|
||||
if_vec!(
|
||||
$($subc_subc_arg_type_tt)+,
|
||||
THEN { values_t!(subsubmatches, stringify!($subc_subc_arg), inner_vec_type!($($subc_subc_arg_type_tt)+)).ok() }
|
||||
ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), $($subc_subc_arg_type_tt)+).ok() }
|
||||
THEN { values_t!(subsubmatches, stringify!($subc_subc_arg), inner_vec_type!($($subc_subc_arg_type_tt)+)) }
|
||||
ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), $($subc_subc_arg_type_tt)+) }
|
||||
)
|
||||
}
|
||||
);
|
||||
));
|
||||
)*
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -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<SpecType, String> {
|
||||
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<MinerOptions, String> {
|
||||
if self.args.flag_force_sealing && reseal_min_period == 0 {
|
||||
fn miner_options(&self) -> Result<MinerOptions, String> {
|
||||
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(),
|
||||
|
||||
@@ -301,6 +301,12 @@ pub fn new_ipc<D: rpc_apis::Dependencies>(
|
||||
|
||||
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)),
|
||||
|
||||
@@ -71,6 +71,9 @@ pub trait Dispatcher: Send + Sync + Clone {
|
||||
fn sign(&self, accounts: Arc<AccountProvider>, filled: FilledTransactionRequest, password: SignWith)
|
||||
-> BoxFuture<WithToken<SignedTransaction>, Error>;
|
||||
|
||||
/// Converts a `SignedTransaction` into `RichRawTransaction`
|
||||
fn enrich(&self, SignedTransaction) -> RpcRichRawTransaction;
|
||||
|
||||
/// "Dispatch" a local transaction.
|
||||
fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result<H256, Error>;
|
||||
}
|
||||
@@ -163,6 +166,11 @@ impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C
|
||||
}))
|
||||
}
|
||||
|
||||
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<H256, Error> {
|
||||
let hash = signed_transaction.transaction.hash();
|
||||
|
||||
@@ -261,11 +269,11 @@ impl LightDispatcher {
|
||||
transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
||||
) -> 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<H256, Error> {
|
||||
let hash = signed_transaction.transaction.hash();
|
||||
|
||||
@@ -510,8 +523,8 @@ pub fn execute<D: Dispatcher + 'static>(
|
||||
},
|
||||
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)
|
||||
))
|
||||
},
|
||||
|
||||
@@ -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<Transaction> {
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ impl<D: Dispatcher + 'static> SignerClient<D> {
|
||||
SignerClient {
|
||||
signer: signer.clone(),
|
||||
accounts: store.clone(),
|
||||
dispatcher: dispatcher,
|
||||
subscribers: subscribers,
|
||||
dispatcher,
|
||||
subscribers,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +205,8 @@ impl<D: Dispatcher + 'static> Signer for SignerClient<D> {
|
||||
},
|
||||
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) => {
|
||||
|
||||
@@ -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) +
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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) +
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -158,11 +158,10 @@ pub struct RichRawTransaction {
|
||||
pub transaction: Transaction
|
||||
}
|
||||
|
||||
|
||||
impl From<SignedTransaction> 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 {
|
||||
|
||||
@@ -137,7 +137,7 @@ const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024;
|
||||
// Maximal number of transactions in sent in single packet.
|
||||
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
|
||||
// Min number of blocks to be behind for a snapshot sync
|
||||
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 10000;
|
||||
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000;
|
||||
const SNAPSHOT_MIN_PEERS: usize = 3;
|
||||
|
||||
const STATUS_PACKET: u8 = 0x00;
|
||||
|
||||
@@ -3,7 +3,7 @@ description = "Ethcore utility library"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-util"
|
||||
version = "1.8.0"
|
||||
version = "1.8.2"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ include!(concat!(env!("OUT_DIR"), "/version.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
|
||||
|
||||
#[cfg(feature = "final")]
|
||||
const THIS_TRACK: &'static str = "nightly";
|
||||
const THIS_TRACK: &'static str = "beta";
|
||||
// ^^^ should be reset to "stable" or "beta" according to the release branch.
|
||||
|
||||
#[cfg(not(feature = "final"))]
|
||||
|
||||
Reference in New Issue
Block a user