diff --git a/Cargo.lock b/Cargo.lock index ee95bb81f..e5df7a02c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,8 +4,8 @@ version = "0.1.0" 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-logger 1.9.0", + "ethcore-util 1.9.0", "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.9.0", "ethjson 0.1.0", "hash 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -554,7 +554,7 @@ dependencies = [ [[package]] name = "ethash" -version = "1.8.0" +version = "1.9.0" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -567,7 +567,7 @@ dependencies = [ [[package]] name = "ethcore" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bloomable 0.1.0", @@ -577,24 +577,24 @@ dependencies = [ "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.8.0", + "ethash 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bloom-journal 0.1.0", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-stratum 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-io 1.9.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-ipc-nano 1.9.0", + "ethcore-logger 1.9.0", + "ethcore-stratum 1.9.0", + "ethcore-util 1.9.0", "ethjson 0.1.0", "ethkey 0.2.0", "ethstore 0.1.0", "evm 0.1.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "hardware-wallet 1.8.0", + "hardware-wallet 1.9.0", "hash 0.1.0", "hashdb 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -662,14 +662,14 @@ version = "0.1.0" [[package]] name = "ethcore-devtools" -version = "1.8.0" +version = "1.9.0" dependencies = [ "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-io" -version = "1.8.0" +version = "1.9.0" dependencies = [ "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -680,18 +680,18 @@ dependencies = [ [[package]] name = "ethcore-ipc" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ethcore-bigint 0.1.3", - "ethcore-devtools 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-util 1.9.0", "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)", ] [[package]] name = "ethcore-ipc-codegen" -version = "1.8.0" +version = "1.9.0" dependencies = [ "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.163 (registry+https://github.com/rust-lang/crates.io-index)", @@ -706,9 +706,9 @@ dependencies = [ name = "ethcore-ipc-hypervisor" version = "1.2.0" dependencies = [ - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-ipc-nano 1.9.0", "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)", @@ -717,9 +717,9 @@ dependencies = [ [[package]] name = "ethcore-ipc-nano" -version = "1.8.0" +version = "1.9.0" dependencies = [ - "ethcore-ipc 1.8.0", + "ethcore-ipc 1.9.0", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -730,11 +730,11 @@ name = "ethcore-ipc-tests" version = "0.1.0" dependencies = [ "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-ipc-nano 1.9.0", + "ethcore-util 1.9.0", "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)", @@ -742,18 +742,18 @@ dependencies = [ [[package]] name = "ethcore-light" -version = "1.8.0" +version = "1.9.0" dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-network 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-io 1.9.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-network 1.9.0", + "ethcore-util 1.9.0", "evm 0.1.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", @@ -780,7 +780,7 @@ dependencies = [ [[package]] name = "ethcore-logger" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -795,17 +795,17 @@ dependencies = [ [[package]] name = "ethcore-network" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-io 1.9.0", + "ethcore-logger 1.9.0", + "ethcore-util 1.9.0", "ethcrypto 0.1.0", "ethkey 0.2.0", "hash 0.1.0", @@ -832,15 +832,15 @@ 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)", - "ethcore 1.8.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-ipc-nano 1.9.0", + "ethcore-logger 1.9.0", + "ethcore-util 1.9.0", "ethcrypto 0.1.0", "ethkey 0.2.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -867,16 +867,16 @@ dependencies = [ [[package]] name = "ethcore-stratum" -version = "1.8.0" +version = "1.9.0" dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", - "ethcore-devtools 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-ipc-nano 1.9.0", + "ethcore-logger 1.9.0", + "ethcore-util 1.9.0", "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)", @@ -889,7 +889,7 @@ dependencies = [ [[package]] name = "ethcore-util" -version = "1.8.0" +version = "1.9.0" 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)", @@ -898,8 +898,8 @@ dependencies = [ "eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-logger 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-logger 1.9.0", "hash 0.1.0", "hashdb 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1011,21 +1011,21 @@ dependencies = [ [[package]] name = "ethsync" -version = "1.8.0" +version = "1.9.0" dependencies = [ "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-light 1.8.0", - "ethcore-network 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-io 1.9.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-ipc-nano 1.9.0", + "ethcore-light 1.9.0", + "ethcore-network 1.9.0", + "ethcore-util 1.9.0", "ethkey 0.2.0", "hash 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1051,10 +1051,10 @@ dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "ethcore-bigint 0.1.3", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", + "ethcore-logger 1.9.0", + "ethcore-util 1.9.0", "ethjson 0.1.0", - "evmjit 1.8.0", + "evmjit 1.9.0", "hash 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1071,10 +1071,10 @@ name = "evmbin" version = "0.1.0" dependencies = [ "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.0", + "ethcore-util 1.9.0", "ethjson 0.1.0", "evm 0.1.0", "panic_hook 0.1.0", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "evmjit" -version = "1.8.0" +version = "1.9.0" dependencies = [ "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1190,7 +1190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hardware-wallet" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ethcore-bigint 0.1.3", "ethkey 0.2.0", @@ -1367,12 +1367,12 @@ dependencies = [ [[package]] name = "ipc-common-types" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ethcore-bigint 0.1.3", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-util 1.8.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-util 1.9.0", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1540,7 +1540,7 @@ version = "0.1.0" dependencies = [ "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", - "ethcore-devtools 1.8.0", + "ethcore-devtools 1.9.0", "kvdb 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1692,7 +1692,7 @@ dependencies = [ name = "migration" version = "0.1.0" dependencies = [ - "ethcore-devtools 1.8.0", + "ethcore-devtools 1.9.0", "kvdb 0.1.0", "kvdb-rocksdb 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1875,14 +1875,14 @@ dependencies = [ [[package]] name = "node-filter" -version = "1.8.0" +version = "1.9.0" dependencies = [ - "ethcore 1.8.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-io 1.8.0", - "ethcore-network 1.8.0", - "ethcore-util 1.8.0", + "ethcore-io 1.9.0", + "ethcore-network 1.9.0", + "ethcore-util 1.9.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb-memorydb 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2091,23 +2091,23 @@ dependencies = [ "daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-io 1.9.0", + "ethcore-ipc 1.9.0", "ethcore-ipc-hypervisor 1.2.0", - "ethcore-ipc-nano 1.8.0", + "ethcore-ipc-nano 1.9.0", "ethcore-ipc-tests 0.1.0", - "ethcore-light 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-network 1.8.0", + "ethcore-light 1.9.0", + "ethcore-logger 1.9.0", + "ethcore-network 1.9.0", "ethcore-secretstore 1.0.0", - "ethcore-stratum 1.8.0", - "ethcore-util 1.8.0", + "ethcore-stratum 1.9.0", + "ethcore-util 1.9.0", "ethkey 0.2.0", - "ethsync 1.8.0", + "ethsync 1.9.0", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -2118,19 +2118,19 @@ dependencies = [ "kvdb-rocksdb 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "migration 0.1.0", - "node-filter 1.8.0", + "node-filter 1.9.0", "node-health 0.1.0", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", - "parity-dapps 1.8.0", - "parity-hash-fetch 1.8.0", - "parity-ipfs-api 1.8.0", + "parity-dapps 1.9.0", + "parity-hash-fetch 1.9.0", + "parity-ipfs-api 1.9.0", "parity-local-store 0.1.0", "parity-reactor 0.1.0", - "parity-rpc 1.8.0", + "parity-rpc 1.9.0", "parity-rpc-client 1.4.0", - "parity-updater 1.8.0", + "parity-updater 1.9.0", "parity-whisper 0.1.0", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "path 0.1.0", @@ -2153,15 +2153,15 @@ dependencies = [ [[package]] name = "parity-dapps" -version = "1.8.0" +version = "1.9.0" dependencies = [ "base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-util 1.9.0", "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)", @@ -2174,9 +2174,9 @@ dependencies = [ "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-health 0.1.0", "parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.8.0", + "parity-hash-fetch 1.9.0", "parity-reactor 0.1.0", - "parity-ui 1.8.0", + "parity-ui 1.9.0", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2187,21 +2187,6 @@ dependencies = [ "zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parity-dapps-glue" -version = "1.8.0" -dependencies = [ - "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parity-dapps-glue" version = "1.8.0" @@ -2216,14 +2201,29 @@ dependencies = [ "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parity-dapps-glue" +version = "1.9.0" +dependencies = [ + "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parity-hash-fetch" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ethabi 2.0.0 (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.9.0", "fetch 0.1.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", @@ -2239,13 +2239,13 @@ dependencies = [ [[package]] name = "parity-ipfs-api" -version = "1.8.0" +version = "1.9.0" dependencies = [ "cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.0", + "ethcore-util 1.9.0", "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)", @@ -2257,9 +2257,9 @@ dependencies = [ name = "parity-local-store" version = "0.1.0" dependencies = [ - "ethcore 1.8.0", - "ethcore-io 1.8.0", - "ethcore-util 1.8.0", + "ethcore 1.9.0", + "ethcore-io 1.9.0", + "ethcore-util 1.9.0", "ethkey 0.2.0", "kvdb 0.1.0", "kvdb-memorydb 0.1.0", @@ -2275,7 +2275,7 @@ name = "parity-machine" version = "0.1.0" dependencies = [ "ethcore-bigint 0.1.3", - "ethcore-util 1.8.0", + "ethcore-util 1.9.0", ] [[package]] @@ -2288,30 +2288,30 @@ dependencies = [ [[package]] name = "parity-rpc" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.8.0", - "ethcore 1.8.0", + "ethash 1.9.0", + "ethcore 1.9.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-light 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-network 1.8.0", - "ethcore-util 1.8.0", + "ethcore-devtools 1.9.0", + "ethcore-io 1.9.0", + "ethcore-ipc 1.9.0", + "ethcore-light 1.9.0", + "ethcore-logger 1.9.0", + "ethcore-network 1.9.0", + "ethcore-util 1.9.0", "ethcrypto 0.1.0", "ethjson 0.1.0", "ethkey 0.2.0", "ethstore 0.1.0", - "ethsync 1.8.0", + "ethsync 1.9.0", "fetch 0.1.0", "futures-cpupool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hardware-wallet 1.8.0", + "hardware-wallet 1.9.0", "hash 0.1.0", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)", @@ -2327,7 +2327,7 @@ dependencies = [ "node-health 0.1.0", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", - "parity-updater 1.8.0", + "parity-updater 1.9.0", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2355,7 +2355,7 @@ dependencies = [ "jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-rpc 1.8.0", + "parity-rpc 1.9.0", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2381,16 +2381,16 @@ dependencies = [ [[package]] name = "parity-ui" -version = "1.8.0" +version = "1.9.0" dependencies = [ - "parity-ui-dev 1.8.0", + "parity-ui-dev 1.9.0", "parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-ui-dev" -version = "1.8.0" +version = "1.9.0" dependencies = [ "parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2398,27 +2398,27 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#87ee470b6f0b4a39ad6cefac21cc5b112ba0348d" +source = "git+https://github.com/paritytech/js-precompiled.git#4b77a23c3e55aed45725f43cd2a499676375b995" dependencies = [ "parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-updater" -version = "1.8.0" +version = "1.9.0" dependencies = [ "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", + "ethcore 1.9.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", - "ethsync 1.8.0", + "ethcore-ipc 1.9.0", + "ethcore-ipc-codegen 1.9.0", + "ethcore-util 1.9.0", + "ethsync 1.9.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-common-types 1.8.0", + "ipc-common-types 1.9.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.8.0", + "parity-hash-fetch 1.9.0", "parity-reactor 0.1.0", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "path 0.1.0", @@ -2442,7 +2442,7 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", - "ethcore-network 1.8.0", + "ethcore-network 1.9.0", "ethcrypto 0.1.0", "ethkey 0.2.0", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2506,7 +2506,7 @@ dependencies = [ "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-logger 1.8.0", + "ethcore-logger 1.9.0", "hash 0.1.0", "hashdb 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2875,9 +2875,9 @@ 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.9.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-rpc 1.8.0", + "parity-rpc 1.9.0", "parity-rpc-client 1.4.0", "rpassword 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3591,9 +3591,9 @@ dependencies = [ "common-types 0.1.0", "ethcore-bigint 0.1.3", "ethcore-bytes 0.1.0", - "ethcore-util 1.8.0", + "ethcore-util 1.9.0", "ethjson 0.1.0", - "evmjit 1.8.0", + "evmjit 1.9.0", "hash 0.1.0", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index ae3216ba3..f3e38a085 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity Dapps crate" name = "parity-dapps" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/dapps/js-glue/Cargo.toml b/dapps/js-glue/Cargo.toml index 126bca143..843168fb7 100644 --- a/dapps/js-glue/Cargo.toml +++ b/dapps/js-glue/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Base Package for all Parity built-in dapps" name = "parity-dapps-glue" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/dapps/ui/Cargo.toml b/dapps/ui/Cargo.toml index 41763b14d..fe4629a36 100644 --- a/dapps/ui/Cargo.toml +++ b/dapps/ui/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore Parity UI" homepage = "http://parity.io" license = "GPL-3.0" name = "parity-ui" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [build-dependencies] diff --git a/devtools/Cargo.toml b/devtools/Cargo.toml index faae03731..ab0049983 100644 --- a/devtools/Cargo.toml +++ b/devtools/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore development/test/build tools" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-devtools" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [dependencies] diff --git a/ethash/Cargo.toml b/ethash/Cargo.toml index f2d6f2790..e60d63c22 100644 --- a/ethash/Cargo.toml +++ b/ethash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethash" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [lib] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index a12083b56..b0c0c195e 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 11959ee8e..0d3a64956 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -574,7 +574,7 @@ impl Interpreter { let source_offset = stack.peek(1); let size = stack.peek(2); let return_data_len = U256::from(self.return_data.len()); - if source_offset.overflow_add(*size).0 > return_data_len { + if source_offset.saturating_add(*size) > return_data_len { return Err(vm::Error::OutOfBounds); } } @@ -940,4 +940,25 @@ mod tests { assert_eq!(ext.calls.len(), 1); assert_eq!(gas_left, 248_212.into()); } + + #[test] + fn should_not_overflow_returndata() { + let code = "6001600160000360003e00".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.address = 5.into(); + params.gas = 300_000.into(); + params.gas_price = 1.into(); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_byzantium(); + ext.balances.insert(5.into(), 1_000_000_000.into()); + ext.tracing = true; + + let err = { + let mut vm = Factory::new(VMType::Interpreter, 1).create(params.gas); + test_finalize(vm.exec(params, &mut ext)).err().unwrap() + }; + + assert_eq!(err, ::vm::Error::OutOfBounds); + } } diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index 69a58270c..ed372ce24 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -3,7 +3,7 @@ description = "Parity Light Client Implementation" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-light" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/ethcore/node_filter/Cargo.toml b/ethcore/node_filter/Cargo.toml index dc8797d8e..7879074ff 100644 --- a/ethcore/node_filter/Cargo.toml +++ b/ethcore/node_filter/Cargo.toml @@ -3,7 +3,7 @@ description = "Parity smart network connections" homepage = "http://parity.io" license = "GPL-3.0" name = "node-filter" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [dependencies] diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 263145e88..1b954b347 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -988,9 +988,11 @@ impl Client { /// Tick the client. // TODO: manage by real events. - pub fn tick(&self) { + pub fn tick(&self, prevent_sleep: bool) { self.check_garbage(); - self.check_snooze(); + if !prevent_sleep { + self.check_snooze(); + } } fn check_garbage(&self) { @@ -1098,7 +1100,7 @@ impl Client { if !self.liveness.load(AtomicOrdering::Relaxed) { self.liveness.store(true, AtomicOrdering::Relaxed); self.notify(|n| n.start()); - trace!(target: "mode", "wake_up: Waking."); + info!(target: "mode", "wake_up: Waking."); } } @@ -1108,11 +1110,11 @@ impl Client { if self.queue_info().total_queue_size() <= MAX_QUEUE_SIZE_TO_SLEEP_ON { self.liveness.store(false, AtomicOrdering::Relaxed); self.notify(|n| n.stop()); - trace!(target: "mode", "sleep: Sleeping."); + info!(target: "mode", "sleep: Sleeping."); } else { - trace!(target: "mode", "sleep: Cannot sleep - syncing ongoing."); + info!(target: "mode", "sleep: Cannot sleep - syncing ongoing."); // TODO: Consider uncommenting. - //*self.last_activity.lock() = Some(Instant::now()); + //(*self.sleep_state.lock()).last_activity = Some(Instant::now()); } } } diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 8d67166be..0ceabce84 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -28,7 +28,7 @@ use error::*; use client::{Client, ClientConfig, ChainNotify}; use miner::Miner; -use snapshot::ManifestData; +use snapshot::{ManifestData, RestorationStatus}; use snapshot::service::{Service as SnapshotService, ServiceParams as SnapServiceParams}; use std::sync::atomic::AtomicBool; use ansi_term::Colour; @@ -181,7 +181,11 @@ impl IoHandler for ClientIoHandler { fn timeout(&self, _io: &IoContext, timer: TimerToken) { match timer { - CLIENT_TICK_TIMER => self.client.tick(), + CLIENT_TICK_TIMER => { + use snapshot::SnapshotService; + let snapshot_restoration = if let RestorationStatus::Ongoing{..} = self.snapshot.status() { true } else { false }; + self.client.tick(snapshot_restoration) + }, SNAPSHOT_TICK_TIMER => self.snapshot.tick(), _ => warn!("IO service triggered unregistered timer '{}'", timer), } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 69e48a9df..b75f0863a 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -195,7 +195,7 @@ fn imports_block_sequence() { #[test] fn can_collect_garbage() { let client = generate_dummy_client(100); - client.tick(); + client.tick(true); assert!(client.blockchain_cache_info().blocks < 100 * 1024); } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index 40c23f40c..0d7ca1f82 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -80,6 +80,12 @@ impl FakeExt { pub fn new() -> Self { FakeExt::default() } + + pub fn new_byzantium() -> Self { + let mut ext = FakeExt::default(); + ext.schedule = Schedule::new_byzantium(); + ext + } } impl Ext for FakeExt { diff --git a/evmjit/Cargo.toml b/evmjit/Cargo.toml index dbc0cd51a..8020d89c0 100644 --- a/evmjit/Cargo.toml +++ b/evmjit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "evmjit" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [lib] diff --git a/hash-fetch/Cargo.toml b/hash-fetch/Cargo.toml index eca590a23..c52f1e232 100644 --- a/hash-fetch/Cargo.toml +++ b/hash-fetch/Cargo.toml @@ -3,7 +3,7 @@ description = "Fetching hash-addressed content." homepage = "http://parity.io" license = "GPL-3.0" name = "parity-hash-fetch" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [dependencies] diff --git a/hw/Cargo.toml b/hw/Cargo.toml index b762d697c..c1bf057b0 100644 --- a/hw/Cargo.toml +++ b/hw/Cargo.toml @@ -3,7 +3,7 @@ description = "Hardware wallet support." homepage = "http://parity.io" license = "GPL-3.0" name = "hardware-wallet" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [dependencies] diff --git a/ipc-common-types/Cargo.toml b/ipc-common-types/Cargo.toml index a9efe1439..e00949adc 100644 --- a/ipc-common-types/Cargo.toml +++ b/ipc-common-types/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Types that implement IPC and are common to multiple modules." name = "ipc-common-types" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/ipc/codegen/Cargo.toml b/ipc/codegen/Cargo.toml index 69580e08d..7b204869a 100644 --- a/ipc/codegen/Cargo.toml +++ b/ipc/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethcore-ipc-codegen" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] license = "GPL-3.0" description = "Macros to auto-generate implementations for ipc call" diff --git a/ipc/nano/Cargo.toml b/ipc/nano/Cargo.toml index a714e1d00..bb6fbb0b2 100644 --- a/ipc/nano/Cargo.toml +++ b/ipc/nano/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethcore-ipc-nano" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] license = "GPL-3.0" diff --git a/ipc/rpc/Cargo.toml b/ipc/rpc/Cargo.toml index 12d73a118..bd33ab618 100644 --- a/ipc/rpc/Cargo.toml +++ b/ipc/rpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethcore-ipc" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] license = "GPL-3.0" diff --git a/ipfs/Cargo.toml b/ipfs/Cargo.toml index db76ddaa9..c34e0d521 100644 --- a/ipfs/Cargo.toml +++ b/ipfs/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity IPFS-compatible API" name = "parity-ipfs-api" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/js/Cargo.toml b/js/Cargo.toml index 1ff166cca..1f47ffd9d 100644 --- a/js/Cargo.toml +++ b/js/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity built-in dapps." name = "parity-ui-dev" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/js/package-lock.json b/js/package-lock.json index ba479c529..4624dceb6 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.8.30", + "version": "1.8.36", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -428,7 +428,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -716,7 +716,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -4140,7 +4140,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -11654,7 +11654,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -12611,7 +12611,7 @@ "async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "integrity": "sha1-hDGQ/WtzV6C54clW7d3V7IRitU0=", "dev": true, "requires": { "lodash": "4.17.2" @@ -13016,7 +13016,7 @@ "commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=" }, "detect-indent": { "version": "5.0.0", diff --git a/js/package.json b/js/package.json index 42bd5de5a..45d1b567d 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.8.30", + "version": "1.8.36", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", diff --git a/js/scripts/test.js b/js/scripts/test.js index e426642db..e60e3cb6c 100644 --- a/js/scripts/test.js +++ b/js/scripts/test.js @@ -1 +1 @@ -// test script 10 +// test script 11 diff --git a/js/src/api/api.js b/js/src/api/api.js index a1a7dbbb5..5ba401c33 100644 --- a/js/src/api/api.js +++ b/js/src/api/api.js @@ -47,13 +47,6 @@ export default class Api extends EventEmitter { this._trace = new Trace(transport); this._web3 = new Web3(transport); - if (isFunction(transport.subscribe)) { - this._pubsub = new Pubsub(transport); - } - - if (allowSubscriptions) { - this._subscriptions = new Subscriptions(this); - } // Doing a request here in test env would cause an error if (LocalAccountsMiddleware && process.env.NODE_ENV !== 'test') { const middleware = this.parity @@ -69,6 +62,14 @@ export default class Api extends EventEmitter { transport.addMiddleware(middleware); } + + if (isFunction(transport.subscribe)) { + this._pubsub = new Pubsub(transport); + } + + if (allowSubscriptions) { + this._subscriptions = new Subscriptions(this); + } } get isPubSub () { diff --git a/js/src/api/local/accounts/accounts.js b/js/src/api/local/accounts/accounts.js index d11ea2bad..ec117e25d 100644 --- a/js/src/api/local/accounts/accounts.js +++ b/js/src/api/local/accounts/accounts.js @@ -18,11 +18,12 @@ import Account from './account'; import localStore from 'store'; import { debounce } from 'lodash'; import { decryptPrivateKey } from '../ethkey'; +import EventEmitter from 'eventemitter3'; const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; const LS_STORE_KEY = '_parity::localAccounts'; -export default class Accounts { +export default class Accounts extends EventEmitter { persist = debounce(() => { this._lastState = JSON.stringify(this); @@ -30,6 +31,8 @@ export default class Accounts { }, 100); constructor (data = localStore.get(LS_STORE_KEY) || {}) { + super(); + this._lastState = JSON.stringify(data); window.addEventListener('storage', ({ key, newValue }) => { @@ -130,6 +133,8 @@ export default class Accounts { set dappsDefaultAddress (value) { this._dappsDefaultAddress = value.toLowerCase(); + this.emit('dappsDefaultAddressChange', this._dappsDefaultAddress); + this.persist(); } diff --git a/js/src/api/local/localAccountsMiddleware.js b/js/src/api/local/localAccountsMiddleware.js index adfe8f50d..bc18f21b1 100644 --- a/js/src/api/local/localAccountsMiddleware.js +++ b/js/src/api/local/localAccountsMiddleware.js @@ -26,7 +26,9 @@ export default class LocalAccountsMiddleware extends Middleware { constructor (transport) { super(transport); + const NOOP = () => {}; const register = this.register.bind(this); + const registerSubscribe = this.registerSubscribe.bind(this); register('eth_accounts', () => { return accounts.accountAddresses(); @@ -76,6 +78,14 @@ export default class LocalAccountsMiddleware extends Middleware { return accounts.dappsDefaultAddress; }); + registerSubscribe('parity_defaultAccount', (_, callback) => { + callback(null, accounts.dappsDefaultAddress); + + accounts.on('dappsDefaultAddressChange', (address) => { + callback(null, accounts.dappsDefaultAddress); + }); + }); + register('parity_exportAccount', ([address, password]) => { const account = accounts.get(address); @@ -109,6 +119,8 @@ export default class LocalAccountsMiddleware extends Middleware { return {}; }); + registerSubscribe('parity_hardwareAccountsInfo', NOOP); + register('parity_newAccountFromPhrase', ([phrase, password]) => { return phraseToWallet(phrase) .then((wallet) => { @@ -278,5 +290,15 @@ export default class LocalAccountsMiddleware extends Middleware { register('signer_requestsToConfirm', () => { return transactions.requestsToConfirm(); }); + + registerSubscribe('signer_subscribePending', (_, callback) => { + callback(null, transactions.requestsToConfirm()); + + transactions.on('update', () => { + callback(null, transactions.requestsToConfirm()); + }); + + return false; + }); } } diff --git a/js/src/api/local/transactions.js b/js/src/api/local/transactions.js index 421e73012..44cf61f69 100644 --- a/js/src/api/local/transactions.js +++ b/js/src/api/local/transactions.js @@ -16,14 +16,17 @@ import { toHex } from '../util/format'; import { TransportError } from '../transport'; +import EventEmitter from 'eventemitter3'; const AWAITING = Symbol('awaiting'); const LOCKED = Symbol('locked'); const CONFIRMED = Symbol('confirmed'); const REJECTED = Symbol('rejected'); -class Transactions { +class Transactions extends EventEmitter { constructor () { + super(); + this.reset(); } @@ -45,6 +48,8 @@ class Transactions { transaction: tx }; + this.emit('update'); + return id; } @@ -66,6 +71,8 @@ class Transactions { } state.status = LOCKED; + + this.emit('update'); } unlock (id) { @@ -76,6 +83,8 @@ class Transactions { } state.status = AWAITING; + + this.emit('update'); } hash (id) { @@ -107,6 +116,8 @@ class Transactions { state.hash = hash; state.status = CONFIRMED; + + this.emit('update'); } reject (id) { @@ -118,6 +129,8 @@ class Transactions { state.status = REJECTED; + this.emit('update'); + return true; } diff --git a/js/src/api/pubsub/signer/signer.js b/js/src/api/pubsub/signer/signer.js index 266da6b8a..25db34bdd 100644 --- a/js/src/api/pubsub/signer/signer.js +++ b/js/src/api/pubsub/signer/signer.js @@ -17,7 +17,7 @@ import PubsubBase from '../pubsubBase'; import { outSignerRequest } from '../../format/output'; -export default class Net extends PubsubBase { +export default class Signer extends PubsubBase { constructor (transport) { super(transport); this._api = { diff --git a/js/src/api/subscriptions/signer.js b/js/src/api/subscriptions/signer.js index a0c202c1b..30342cfa7 100644 --- a/js/src/api/subscriptions/signer.js +++ b/js/src/api/subscriptions/signer.js @@ -38,26 +38,32 @@ export default class Signer { start () { this._started = true; - if (this._api.isPubSub) { - const subscription = this._api.pubsub - .subscribeAndGetResult( - callback => this._api.pubsub.signer.pendingRequests(callback), - requests => { - this.updateSubscriptions(requests); - return requests; - } - ); + return this + ._api + .transport + .ready + .then(() => { + if (this._api.isPubSub) { + const subscription = this._api.pubsub + .subscribeAndGetResult( + callback => this._api.pubsub.signer.pendingRequests(callback), + requests => { + this.updateSubscriptions(requests); + return requests; + } + ); - return Promise.all([ - this._listRequests(false), - subscription - ]); - } + return Promise.all([ + this._listRequests(false), + subscription + ]); + } - return Promise.all([ - this._listRequests(true), - this._loggingSubscribe() - ]); + return Promise.all([ + this._listRequests(true), + this._loggingSubscribe() + ]); + }); } updateSubscriptions (requests) { diff --git a/js/src/api/transport/jsonRpcBase.js b/js/src/api/transport/jsonRpcBase.js index 1b96347d3..9e5e18bfe 100644 --- a/js/src/api/transport/jsonRpcBase.js +++ b/js/src/api/transport/jsonRpcBase.js @@ -31,6 +31,10 @@ export default class JsonRpcBase extends EventEmitter { this._middlewareList = Promise.resolve([]); } + get ready () { + return this._middlewareList.then(() => true); + } + encode (method, params) { const json = JSON.stringify({ jsonrpc: '2.0', diff --git a/js/src/api/transport/middleware.js b/js/src/api/transport/middleware.js index ef029b1cb..ccdf732a0 100644 --- a/js/src/api/transport/middleware.js +++ b/js/src/api/transport/middleware.js @@ -17,7 +17,20 @@ export default class Middleware { constructor (transport) { this._transport = transport; + this._subscribe = transport.subscribe; + + transport.subscribe = this.handleSubscribe.bind(this); + this._handlers = {}; + this._subHandlers = {}; + } + + registerSubscribe (method, handler) { + if (method in this._subHandlers) { + throw new Error(`${method} is already defined in the middleware!`); + } + + this._subHandlers[method] = handler; } register (method, handler) { @@ -28,10 +41,24 @@ export default class Middleware { this._handlers[method] = handler; } + handleSubscribe (api, callback, event) { + // Don't ask + const method = api.subscribe ? api.subscribe : event[0]; + const params = event.length === 2 ? event[1] : event; + + const handler = this._subHandlers[method]; + + if (handler) { + return handler(params, callback); + } + + this._subscribe.call(this._transport, api, callback, event); + } + handle (method, params) { const handler = this._handlers[method]; - if (handler != null) { + if (handler) { return handler(params); } diff --git a/js/src/contracts/abi/index.js b/js/src/contracts/abi/index.js index f475cce07..eac825820 100644 --- a/js/src/contracts/abi/index.js +++ b/js/src/contracts/abi/index.js @@ -29,3 +29,4 @@ export signaturereg from './signaturereg.json'; export smsverification from './sms-verification.json'; export tokenreg from './tokenreg.json'; export foundationWallet from './foundation-multisig-wallet.json'; +export vouchfor from './vouchfor.json'; diff --git a/js/src/contracts/abi/vouchfor.json b/js/src/contracts/abi/vouchfor.json new file mode 100644 index 000000000..362eb0c8b --- /dev/null +++ b/js/src/contracts/abi/vouchfor.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[],"name":"certifier","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_what","type":"bytes32"}],"name":"vouch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_what","type":"bytes32"},{"name":"_index","type":"uint256"}],"name":"vouched","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_what","type":"bytes32"},{"name":"_index","type":"uint256"}],"name":"unvouch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"name":"vouchers","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_certifier","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"who","type":"address"},{"indexed":false,"name":"what","type":"bytes32"}],"name":"Vouched","type":"event"}] diff --git a/js/src/contracts/badgereg.js b/js/src/contracts/badgereg.js index a1782cb30..07e740e6d 100644 --- a/js/src/contracts/badgereg.js +++ b/js/src/contracts/badgereg.js @@ -105,7 +105,7 @@ export default class BadgeReg { ]); }) .then(([ title, icon ]) => { - title = bytesToHex(title); + title = bytesToHex(title).replace(/(00)+$/, ''); title = title === ZERO32 ? null : hexToAscii(title); if (bytesToHex(icon) === ZERO32) { diff --git a/js/src/dapps/tokenreg/Application/application.css b/js/src/dapps/tokenreg/Application/application.css index b1eef22e4..d855b6388 100644 --- a/js/src/dapps/tokenreg/Application/application.css +++ b/js/src/dapps/tokenreg/Application/application.css @@ -29,6 +29,7 @@ left: 0; opacity: 1; padding: 1.5em; + cursor: pointer; position: fixed; right: 50%; z-index: 100; diff --git a/js/src/dapps/tokenreg/Application/application.js b/js/src/dapps/tokenreg/Application/application.js index 71081c7ee..df4a53ff1 100644 --- a/js/src/dapps/tokenreg/Application/application.js +++ b/js/src/dapps/tokenreg/Application/application.js @@ -43,8 +43,13 @@ export default class Application extends Component { contract: PropTypes.object }; + state = { + hideWarning: false + }; + render () { const { isLoading, contract } = this.props; + const { hideWarning } = this.state; if (isLoading) { return ( @@ -62,9 +67,15 @@ export default class Application extends Component { -
- WARNING: The token registry is experimental. Please ensure that you understand the steps, risks, benefits & consequences of registering a token before doing so. A non-refundable fee of { api.util.fromWei(contract.fee).toFormat(3) }ETH is required for all registrations. -
+ { + hideWarning + ? null + : ( +
+ WARNING: The token registry is experimental. Please ensure that you understand the steps, risks, benefits & consequences of registering a token before doing so. A non-refundable fee of { api.util.fromWei(contract.fee).toFormat(3) }ETH is required for all registrations. +
+ ) + } ); } @@ -74,4 +85,8 @@ export default class Application extends Component { muiTheme }; } + + handleHideWarning = () => { + this.setState({ hideWarning: true }); + } } diff --git a/js/src/redux/providers/certifications/actions.js b/js/src/redux/providers/certifications/actions.js index 8dede1c53..1eed6caea 100644 --- a/js/src/redux/providers/certifications/actions.js +++ b/js/src/redux/providers/certifications/actions.js @@ -14,14 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export const fetchCertifiers = () => ({ - type: 'fetchCertifiers' -}); - -export const fetchCertifications = (address) => ({ - type: 'fetchCertifications', address -}); - export const addCertification = (address, id, name, title, icon) => ({ type: 'addCertification', address, id, name, title, icon }); diff --git a/js/src/redux/providers/certifications/certifiers.monitor.js b/js/src/redux/providers/certifications/certifiers.monitor.js new file mode 100644 index 000000000..d8ea5e451 --- /dev/null +++ b/js/src/redux/providers/certifications/certifiers.monitor.js @@ -0,0 +1,343 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { range } from 'lodash'; + +import { addCertification, removeCertification } from './actions'; + +import { getLogger, LOG_KEYS } from '~/config'; +import Contract from '~/api/contract'; +import { bytesToHex, hexToAscii } from '~/api/util/format'; +import Contracts from '~/contracts'; +import CertifierABI from '~/contracts/abi/certifier.json'; +import { querier } from './enhanced-querier'; + +const log = getLogger(LOG_KEYS.CertificationsMiddleware); + +let self = null; + +export default class CertifiersMonitor { + constructor (api, store) { + this._api = api; + this._name = 'Certifiers'; + this._store = store; + + this._contract = new Contract(this.api, CertifierABI); + this._contractEvents = [ 'Confirmed', 'Revoked' ] + .map((name) => this.contract.events.find((e) => e.name === name)); + + this.certifiers = {}; + this.fetchedAccounts = {}; + + this.load(); + } + + static get () { + if (self) { + return self; + } + + self = new CertifiersMonitor(); + return self; + } + + static init (api, store) { + if (!self) { + self = new CertifiersMonitor(api, store); + } + } + + get api () { + return this._api; + } + + get contract () { + return this._contract; + } + + get contractEvents () { + return this._contractEvents; + } + + get name () { + return this._name; + } + + get store () { + return this._store; + } + + get registry () { + return this._registry; + } + + get registryEvents () { + return this._registryEvents; + } + + checkFilters () { + this.checkCertifiersFilter(); + this.checkRegistryFilter(); + } + + checkCertifiersFilter () { + if (!this.certifiersFilter) { + return; + } + + this.api.eth.getFilterChanges(this.certifiersFilter) + .then((logs) => { + if (logs.length === 0) { + return; + } + + const parsedLogs = this.contract.parseEventLogs(logs).filter((log) => log.params); + + log.debug('received certifiers logs', parsedLogs); + + const promises = parsedLogs.map((log) => { + const account = log.params.who.value; + const certifier = Object.values(this.certifiers).find((c) => c.address === log.address); + + if (!certifier) { + log.warn('could not find the certifier', { certifiers: this.certifiers, log }); + return Promise.resolve(); + } + + return this.fetchAccount(account, { ids: [ certifier.id ] }); + }); + + return Promise.all(promises); + }) + .catch((error) => { + console.error(error); + }); + } + + checkRegistryFilter () { + if (!this.registryFilter) { + return; + } + + this.api.eth.getFilterChanges(this.registryFilter) + .then((logs) => { + if (logs.length === 0) { + return; + } + + const parsedLogs = this.contract.parseEventLogs(logs).filter((log) => log.params); + const indexes = parsedLogs.map((log) => log.params && log.params.id.value.toNumber()); + + log.debug('received registry logs', parsedLogs); + return this.fetchElements(indexes); + }) + .catch((error) => { + console.error(error); + }); + } + + /** + * Initial load of the Monitor. + * Fetch the contract from the Registry, and + * load the elements addresses + */ + load () { + const badgeReg = Contracts.get().badgeReg; + + log.debug(`loading the ${this.name} monitor...`); + return badgeReg.getContract() + .then((registryContract) => { + this._registry = registryContract; + this._registryEvents = [ 'Registered', 'Unregistered', 'MetaChanged', 'AddressChanged' ] + .map((name) => this.registry.events.find((e) => e.name === name)); + + return this.registry.instance.badgeCount.call({}); + }) + .then((count) => { + log.debug(`found ${count.toFormat()} registered contracts for ${this.name}`); + return this.fetchElements(range(count.toNumber())); + }) + .then(() => { + return this.setRegistryFilter(); + }) + .then(() => { + // Listen for new blocks + return this.api.subscribe('eth_blockNumber', (err) => { + if (err) { + return; + } + + this.checkFilters(); + }); + }) + .then(() => { + log.debug(`loaded the ${this.name} monitor!`, this.certifiers); + }) + .catch((error) => { + log.error(error); + }); + } + + /** + * Fetch the given registered element + */ + fetchElements (indexes) { + const badgeReg = Contracts.get().badgeReg; + const { instance } = this.registry; + + const sorted = indexes.sort(); + const from = sorted[0]; + const last = sorted[sorted.length - 1]; + const limit = last - from + 1; + + // Fetch the address, name and owner in one batch + return querier(this.api, { address: instance.address, from, limit }, instance.badge) + .then((results) => { + const certifiers = results + .map(([ address, name, owner ], index) => ({ + address, owner, + id: index + from, + name: hexToAscii(bytesToHex(name).replace(/(00)+$/, '')) + })) + .reduce((certifiers, certifier) => { + const { id } = certifier; + + if (!/^(0x)?0+$/.test(certifier.address)) { + certifiers[id] = certifier; + } else if (certifiers[id]) { + delete certifiers[id]; + } + + return certifiers; + }, {}); + + // Fetch the meta-data in serie + return Object.values(certifiers).reduce((promise, certifier) => { + return promise.then(() => badgeReg.fetchMeta(certifier.id)) + .then((meta) => { + this.certifiers[certifier.id] = { ...certifier, ...meta }; + }); + }, Promise.resolve()); + }) + .then(() => log.debug('fetched certifiers', { certifiers: this.certifiers })) + // Fetch the know accounts in case it's an update of the certifiers + .then(() => this.fetchAccounts(Object.keys(this.fetchedAccounts), { ids: indexes, force: true })); + } + + fetchAccounts (addresses, { ids = null, force = false } = {}) { + const newAddresses = force + ? addresses + : addresses.filter((address) => !this.fetchedAccounts[address]); + + if (newAddresses.length === 0) { + return Promise.resolve(); + } + + log.debug(`fetching values for "${addresses.join(' ; ')}" in ${this.name}...`); + return newAddresses + .reduce((promise, address) => { + return promise.then(() => this.fetchAccount(address, { ids })); + }, Promise.resolve()) + .then(() => { + log.debug(`fetched values for "${addresses.join(' ; ')}" in ${this.name}!`); + }) + .then(() => this.setCertifiersFilter()); + } + + fetchAccount (address, { ids = null } = {}) { + let certifiers = Object.values(this.certifiers); + + // Only fetch values for the givens ids, if any + if (ids) { + certifiers = certifiers.filter((certifier) => ids.includes(certifier.id)); + } + + certifiers + .reduce((promise, certifier) => { + return promise + .then(() => { + return this.contract.at(certifier.address).instance.certified.call({}, [ address ]); + }) + .then((certified) => { + const { id, title, icon, name } = certifier; + + if (!certified) { + return this.store.dispatch(removeCertification(address, id)); + } + + log.debug('seen as certified', { address, id, name, icon }); + this.store.dispatch(addCertification(address, id, name, title, icon)); + }); + }, Promise.resolve()) + .then(() => { + this.fetchedAccounts[address] = true; + }); + } + + setCertifiersFilter () { + const accounts = Object.keys(this.fetchedAccounts); + const addresses = Object.values(this.certifiers).map((c) => c.address); + // The events have as first indexed data the account address + const topics = [ + this.contractEvents.map((event) => '0x' + event.signature), + accounts + ]; + + if (accounts.length === 0 || addresses.length === 0) { + return; + } + + const promise = this.certifiersFilter + ? this.api.eth.uninstallFilter(this.certifiersFilter) + : Promise.resolve(); + + log.debug('setting up registry filter', { topics, accounts, addresses }); + + return promise + .then(() => this.api.eth.newFilter({ + fromBlock: 'latest', + toBlock: 'latest', + address: addresses, + topics + })) + .then((filterId) => { + this.certifiersFilter = filterId; + }) + .catch((error) => { + console.error(error); + }); + } + + setRegistryFilter () { + const { address } = this.registry.instance; + const topics = [ this.registryEvents.map((event) => '0x' + event.signature) ]; + + log.debug('setting up registry filter', { topics, address }); + + return this.api.eth + .newFilter({ + fromBlock: 'latest', + toBlock: 'latest', + address, topics + }) + .then((filterId) => { + this.registryFilter = filterId; + }) + .catch((error) => { + console.error(error); + }); + } +} diff --git a/js/src/redux/providers/certifications/enhanced-querier.js b/js/src/redux/providers/certifications/enhanced-querier.js new file mode 100644 index 000000000..9da42f1bf --- /dev/null +++ b/js/src/redux/providers/certifications/enhanced-querier.js @@ -0,0 +1,96 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { padRight, padLeft } from '~/api/util/format'; + +/** + * Bytecode of this contract: + * + * +pragma solidity ^0.4.10; + +contract Querier { + function Querier + (address addr, bytes32 sign, uint out_size, uint from, uint limit) + public + { + // The size is 32 bytes for each + // value, plus 32 bytes for the count + uint m_size = out_size * limit + 32; + + bytes32 p_return; + uint p_in; + uint p_out; + + assembly { + p_return := mload(0x40) + mstore(0x40, add(p_return, m_size)) + + mstore(p_return, limit) + + p_in := mload(0x40) + mstore(0x40, add(p_in, 0x24)) + + mstore(p_in, sign) + + p_out := add(p_return, 0x20) + } + + for (uint i = from; i < from + limit; i++) { + assembly { + mstore(add(p_in, 0x4), i) + call(gas, addr, 0x0, p_in, 0x24, p_out, out_size) + p_out := add(p_out, out_size) + pop + } + } + + assembly { + return (p_return, m_size) + } + } +} + */ + +export const bytecode = '0x60606040523415600e57600080fd5b60405160a0806099833981016040528080519190602001805191906020018051919060200180519190602001805191505082810260200160008080806040519350848401604052858452604051602481016040528981529250505060208201855b858701811015609457806004840152878260248560008e5af15090870190600101606f565b8484f300'; + +export const querier = (api, { address, from, limit }, method) => { + const { outputs, signature } = method; + const outLength = 32 * outputs.length; + const callargs = [ + padLeft(address, 32), + padRight(signature, 32), + padLeft(outLength, 32), + padLeft(from, 32), + padLeft(limit, 32) + ].map((v) => v.slice(2)).join(''); + const calldata = bytecode + callargs; + + return api.eth.call({ data: calldata }) + .then((result) => { + const data = result.slice(2); + const results = []; + + for (let i = 0; i < limit; i++) { + const datum = data.substr(2 * (32 + i * outLength), 2 * outLength); + const decoded = method.decodeOutput('0x' + datum).map((t) => t.value); + + results.push(decoded); + } + + return results; + }); +}; diff --git a/js/src/redux/providers/certifications/middleware.js b/js/src/redux/providers/certifications/middleware.js index 5965ec679..73178882a 100644 --- a/js/src/redux/providers/certifications/middleware.js +++ b/js/src/redux/providers/certifications/middleware.js @@ -14,222 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { uniq, range, debounce } from 'lodash'; - -import { addCertification, removeCertification } from './actions'; - -import { getLogger, LOG_KEYS } from '~/config'; -import Contract from '~/api/contract'; import Contracts from '~/contracts'; -import CertifierABI from '~/contracts/abi/certifier.json'; - -const log = getLogger(LOG_KEYS.CertificationsMiddleware); - -// TODO: move this to a more general place -const updatableFilter = (api, onFilter) => { - let filter = null; - - const update = (address, topics) => { - if (filter) { - filter = filter.then((filterId) => { - api.eth.uninstallFilter(filterId); - }); - } - - filter = (filter || Promise.resolve()) - .then(() => api.eth.newFilter({ - fromBlock: 'latest', - toBlock: 'latest', - address, - topics - })) - .then((filterId) => { - onFilter(filterId); - return filterId; - }) - .catch((err) => { - console.error('Failed to create certifications filter:', err); - }); - - return filter; - }; - - return update; -}; +import Monitor from './certifiers.monitor'; export default class CertificationsMiddleware { toMiddleware () { const api = Contracts.get()._api; - const badgeReg = Contracts.get().badgeReg; - - const contract = new Contract(api, CertifierABI); - const Confirmed = contract.events.find((e) => e.name === 'Confirmed'); - const Revoked = contract.events.find((e) => e.name === 'Revoked'); return (store) => { - let certifiers = []; - let addresses = []; - let filterChanged = false; - let filter = null; - let badgeRegFilter = null; - let fetchCertifiersPromise = null; - - const updateFilter = updatableFilter(api, (filterId) => { - filterChanged = true; - filter = filterId; - }); - - const badgeRegUpdateFilter = updatableFilter(api, (filterId) => { - filterChanged = true; - badgeRegFilter = filterId; - }); - - badgeReg - .getContract() - .then((badgeRegContract) => { - return badgeRegUpdateFilter(badgeRegContract.address, [ [ - badgeRegContract.instance.Registered.signature, - badgeRegContract.instance.Unregistered.signature, - badgeRegContract.instance.MetaChanged.signature, - badgeRegContract.instance.AddressChanged.signature - ] ]); - }) - .then(() => { - shortFetchChanges(); - - api.subscribe('eth_blockNumber', (err) => { - if (err) { - return; - } - - fetchChanges(); - }); - }); - - function onLogs (logs) { - logs = contract.parseEventLogs(logs); - logs.forEach((log) => { - const certifier = certifiers.find((c) => c.address === log.address); - - if (!certifier) { - throw new Error(`Could not find certifier at ${log.address}.`); - } - const { id, name, title, icon } = certifier; - - if (log.event === 'Revoked') { - store.dispatch(removeCertification(log.params.who.value, id)); - } else { - store.dispatch(addCertification(log.params.who.value, id, name, title, icon)); - } - }); - } - - function onBadgeRegLogs (logs) { - return badgeReg.getContract() - .then((badgeRegContract) => { - logs = badgeRegContract.parseEventLogs(logs); - - const ids = logs.map((log) => log.params && log.params.id.value.toNumber()); - - return fetchCertifiers(uniq(ids)); - }); - } - - function _fetchChanges () { - const method = filterChanged - ? 'getFilterLogs' - : 'getFilterChanges'; - - filterChanged = false; - - api.eth[method](badgeRegFilter) - .then(onBadgeRegLogs) - .catch((err) => { - console.error('Failed to fetch badge reg events:', err); - }) - .then(() => api.eth[method](filter)) - .then(onLogs) - .catch((err) => { - console.error('Failed to fetch new certifier events:', err); - }); - } - - const shortFetchChanges = debounce(_fetchChanges, 0.5 * 1000, { leading: true }); - const fetchChanges = debounce(shortFetchChanges, 10 * 1000, { leading: true }); - - function fetchConfirmedEvents () { - return updateFilter(certifiers.map((c) => c.address), [ - [ Confirmed.signature, Revoked.signature ], - addresses - ]).then(() => shortFetchChanges()); - } - - function fetchCertifiers (ids = []) { - if (fetchCertifiersPromise) { - return fetchCertifiersPromise; - } - - let fetchEvents = false; - - const idsPromise = (certifiers.length === 0) - ? badgeReg.certifierCount().then((count) => { - return range(count); - }) - : Promise.resolve(ids); - - fetchCertifiersPromise = idsPromise - .then((ids) => { - const promises = ids.map((id) => { - return badgeReg.fetchCertifier(id) - .then((cert) => { - if (!certifiers.some((c) => c.id === cert.id)) { - certifiers = certifiers.concat(cert); - fetchEvents = true; - } - }) - .catch((err) => { - if (/does not exist/.test(err.toString())) { - return log.info(err.toString()); - } - - log.warn(`Could not fetch certifier ${id}:`, err); - }); - }); - - return Promise - .all(promises) - .then(() => { - fetchCertifiersPromise = null; - - if (fetchEvents) { - return fetchConfirmedEvents(); - } - }); - }); - - return fetchCertifiersPromise; - } + Monitor.init(api, store); return (next) => (action) => { switch (action.type) { - case 'fetchCertifiers': - fetchConfirmedEvents(); - - break; - case 'fetchCertifications': - const { address } = action; - - if (!addresses.includes(address)) { - addresses = addresses.concat(address); - fetchConfirmedEvents(); - } - - break; case 'setVisibleAccounts': - const _addresses = action.addresses || []; + const { addresses = [] } = action; - addresses = uniq(addresses.concat(_addresses)); - fetchConfirmedEvents(); + Monitor.get().fetchAccounts(addresses); next(action); break; diff --git a/js/src/redux/providers/certifications/reducer.js b/js/src/redux/providers/certifications/reducer.js index 0f94239c6..7be0fb15b 100644 --- a/js/src/redux/providers/certifications/reducer.js +++ b/js/src/redux/providers/certifications/reducer.js @@ -20,24 +20,32 @@ export default (state = initialState, action) => { if (action.type === 'addCertification') { const { address, id, name, icon, title } = action; const certifications = state[address] || []; + const certifierIndex = certifications.findIndex((c) => c.id === id); + const data = { id, name, icon, title }; + const nextCertifications = certifications.slice(); - if (certifications.some((c) => c.id === id)) { - return state; + if (certifierIndex >= 0) { + nextCertifications[certifierIndex] = data; + } else { + nextCertifications.push(data); } - const newCertifications = certifications.concat({ - id, name, icon, title - }); - - return { ...state, [address]: newCertifications }; + return { ...state, [address]: nextCertifications }; } if (action.type === 'removeCertification') { const { address, id } = action; const certifications = state[address] || []; + const certifierIndex = certifications.findIndex((c) => c.id === id); - const newCertifications = certifications.filter((c) => c.id !== id); + // Don't remove if not there + if (certifierIndex < 0) { + return state; + } + const newCertifications = certifications.slice(); + + newCertifications.splice(certifierIndex, 1); return { ...state, [address]: newCertifications }; } diff --git a/js/src/redux/providers/requestsActions.js b/js/src/redux/providers/requestsActions.js index fe3be2e43..b968b1c06 100644 --- a/js/src/redux/providers/requestsActions.js +++ b/js/src/redux/providers/requestsActions.js @@ -54,13 +54,24 @@ export const watchRequest = (request) => (dispatch, getState) => { dispatch(trackRequest(requestId, request)); }; -export const trackRequest = (requestId, { transactionHash = null } = {}) => (dispatch, getState) => { +export const trackRequest = (requestId, { transactionHash = null, retries = 0 } = {}) => (dispatch, getState) => { const { api } = getState(); trackRequestUtil(api, { requestId, transactionHash }, (error, _data = {}) => { const data = { ..._data }; if (error) { + // Retry in 500ms if request not found, max 5 times + if (error.type === 'REQUEST_NOT_FOUND') { + if (retries > 5) { + return dispatch(deleteRequest(requestId)); + } + + return setTimeout(() => { + trackRequest(requestId, { transactionHash, retries: retries + 1 })(dispatch, getState); + }, 500); + } + console.error(error); return dispatch(setRequest(requestId, { error })); } diff --git a/js/src/redux/providers/tokensActions.js b/js/src/redux/providers/tokensActions.js index a9de46667..df1374dd7 100644 --- a/js/src/redux/providers/tokensActions.js +++ b/js/src/redux/providers/tokensActions.js @@ -115,9 +115,11 @@ export function loadTokensBasics (_tokenIndexes, options) { 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); - }); + const tokenIndexes = _tokenIndexes + .filter((tokenIndex) => { + return !prevTokensIndexes.includes(tokenIndex); + }) + .sort(); const count = tokenIndexes.length; @@ -130,10 +132,15 @@ export function loadTokensBasics (_tokenIndexes, options) { return tokenReg.getContract() .then((tokenRegContract) => { let promise = Promise.resolve(); + const first = tokenIndexes[0]; + const last = tokenIndexes[tokenIndexes.length - 1]; + + for (let from = first; from <= last; from += limit) { + // No need to fetch `limit` elements + const lowerLimit = Math.min(limit, last - from + 1); - for (let start = 0; start < count; start += limit) { promise = promise - .then(() => fetchTokensBasics(api, tokenRegContract, start, limit)) + .then(() => fetchTokensBasics(api, tokenRegContract, from, lowerLimit)) .then((results) => { results .forEach((token) => { diff --git a/js/src/ui/AccountCard/accountCard.css b/js/src/ui/AccountCard/accountCard.css index e6cafe656..d260b78b7 100644 --- a/js/src/ui/AccountCard/accountCard.css +++ b/js/src/ui/AccountCard/accountCard.css @@ -20,7 +20,6 @@ background-color: rgba(0, 0, 0, 0.8); display: flex; flex-direction: row; - height: 100%; overflow: hidden; transition: transform ease-out 0.1s; transform: scale(1); diff --git a/js/src/ui/Balance/balance.js b/js/src/ui/Balance/balance.js index 72ccd0f14..4116f6eb9 100644 --- a/js/src/ui/Balance/balance.js +++ b/js/src/ui/Balance/balance.js @@ -15,11 +15,12 @@ // along with Parity. If not, see . import BigNumber from 'bignumber.js'; +import { pick } from 'lodash'; import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import TokenImage from '~/ui/TokenImage'; +import TokenValue from './tokenValue'; import styles from './balance.css'; @@ -69,58 +70,19 @@ export class Balance extends Component { const balanceValue = balance[tokenId]; const isEthToken = token.native; - const isFullToken = !showOnlyEth || isEthToken; const hasBalance = (balanceValue instanceof BigNumber) && balanceValue.gt(0); if (!hasBalance && !isEthToken) { return null; } - const bnf = new BigNumber(token.format || 1); - let decimals = 0; - - if (bnf.gte(1000)) { - decimals = 3; - } else if (bnf.gte(100)) { - decimals = 2; - } else if (bnf.gte(10)) { - decimals = 1; - } - - const rawValue = new BigNumber(balanceValue).div(bnf); - const value = rawValue.toFormat(decimals); - - const classNames = [styles.balance]; - let details = null; - - if (isFullToken) { - classNames.push(styles.full); - details = [ -
- - { value } - -
, -
- { token.tag } -
- ]; - } - return ( -
- - { details } -
+ showOnlyEth={ showOnlyEth } + token={ token } + value={ balanceValue } + /> ); }) .filter((node) => node); @@ -155,11 +117,15 @@ export class Balance extends Component { } function mapStateToProps (state, props) { - const { balances, tokens } = state; + const { balances, tokens: allTokens } = state; const { address } = props; + const balance = balances[address] || props.balance || {}; + + const tokenIds = Object.keys(balance); + const tokens = pick(allTokens, tokenIds); return { - balance: balances[address] || props.balance || {}, + balance, tokens }; } diff --git a/js/src/ui/Balance/balance.spec.js b/js/src/ui/Balance/balance.spec.js index d5601a489..c1637329b 100644 --- a/js/src/ui/Balance/balance.spec.js +++ b/js/src/ui/Balance/balance.spec.js @@ -84,13 +84,13 @@ describe('ui/Balance', () => { }); it('renders all the non-zero balances', () => { - expect(component.find('Connect(TokenImage)')).to.have.length(2); + expect(component.find('Connect(TokenValue)')).to.have.length(2); }); describe('render specifiers', () => { it('renders all the tokens with showZeroValues', () => { render({ showZeroValues: true }); - expect(component.find('Connect(TokenImage)')).to.have.length(2); + expect(component.find('Connect(TokenValue)')).to.have.length(2); }); }); }); diff --git a/js/src/ui/Balance/tokenValue.js b/js/src/ui/Balance/tokenValue.js new file mode 100644 index 000000000..12f750ef5 --- /dev/null +++ b/js/src/ui/Balance/tokenValue.js @@ -0,0 +1,109 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import BigNumber from 'bignumber.js'; +import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; + +import { fetchTokens } from '~/redux/providers/tokensActions'; +import TokenImage from '~/ui/TokenImage'; + +import styles from './balance.css'; + +class TokenValue extends Component { + static propTypes = { + token: PropTypes.object.isRequired, + value: PropTypes.object.isRequired, + + // Redux injection + fetchTokens: PropTypes.func.isRequired, + + showOnlyEth: PropTypes.bool + }; + + componentWillMount () { + const { token } = this.props; + + if (token.native) { + return; + } + + if (!token.fetched) { + if (!Number.isFinite(token.index)) { + return console.warn('no token index', token); + } + + this.props.fetchTokens([ token.index ]); + } + } + + render () { + const { token, showOnlyEth, value } = this.props; + + const isEthToken = token.native; + const isFullToken = !showOnlyEth || isEthToken; + + const bnf = new BigNumber(token.format || 1); + let decimals = 0; + + if (bnf.gte(1000)) { + decimals = 3; + } else if (bnf.gte(100)) { + decimals = 2; + } else if (bnf.gte(10)) { + decimals = 1; + } + + const rawValue = new BigNumber(value).div(bnf); + const classNames = [styles.balance]; + + if (isFullToken) { + classNames.push(styles.full); + } + + return ( +
+ + { + isFullToken + ? [ +
+ + { rawValue.toFormat(decimals) } + +
, +
+ { token.tag } +
+ ] + : null + } +
+ ); + } +} + +function mapDispatchToProps (dispatch) { + return bindActionCreators({ + fetchTokens + }, dispatch); +} + +export default connect( + null, + mapDispatchToProps +)(TokenValue); diff --git a/js/src/ui/DappCard/dappCard.js b/js/src/ui/DappCard/dappCard.js index cc0faf47d..0e3f65fcc 100644 --- a/js/src/ui/DappCard/dappCard.js +++ b/js/src/ui/DappCard/dappCard.js @@ -19,6 +19,7 @@ import React, { Component, PropTypes } from 'react'; import Container, { Title as ContainerTitle } from '~/ui/Container'; import DappIcon from '~/ui/DappIcon'; import Tags from '~/ui/Tags'; +import DappVouchFor from '../DappVouchFor'; import styles from './dappCard.css'; @@ -61,6 +62,7 @@ export default class DappCard extends Component { app={ app } className={ styles.image } /> + . +*/ + +.tag { + color: inherit; + position: absolute; + top: 1em; + right: 1em; + + .image { + position: absolute; + right: 0; + top: 0; + width: 32px; + height: 32px; + } + + .bubble { + background: red; + border-radius: 0.25em; + color: white; + font-size: 0.75em; + padding: 0.1em 0.5em; + position: absolute; + right: 0; + top: 0; + z-index: 100; + } +} diff --git a/js/src/ui/DappVouchFor/dappVouchFor.js b/js/src/ui/DappVouchFor/dappVouchFor.js new file mode 100644 index 000000000..426c881cd --- /dev/null +++ b/js/src/ui/DappVouchFor/dappVouchFor.js @@ -0,0 +1,57 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import React, { Component, PropTypes } from 'react'; +import { observer } from 'mobx-react'; + +import IdentityIcon from '../IdentityIcon'; + +import Store from './store'; +import styles from './dappVouchFor.css'; + +@observer +export default class DappVouchFor extends Component { + static contextTypes = { + api: PropTypes.object.isRequired + }; + + static propTypes = { + app: PropTypes.object.isRequired + }; + + store = new Store(this.context.api, this.props.app); + + render () { + const count = this.store.vouchers.length; + + if (!count) { + return null; + } + + return ( +
+ +
+ { count } +
+
+ ); + } +} diff --git a/js/src/ui/DappVouchFor/index.js b/js/src/ui/DappVouchFor/index.js new file mode 100644 index 000000000..be61d5029 --- /dev/null +++ b/js/src/ui/DappVouchFor/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default from './dappVouchFor'; diff --git a/js/src/ui/DappVouchFor/store.js b/js/src/ui/DappVouchFor/store.js new file mode 100644 index 000000000..60c615eb8 --- /dev/null +++ b/js/src/ui/DappVouchFor/store.js @@ -0,0 +1,87 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { action, observable } from 'mobx'; +import { uniq } from 'lodash'; + +import Contracts from '~/contracts'; +import { vouchfor as vouchForAbi } from '~/contracts/abi'; + +let contractPromise = null; + +export default class Store { + @observable vouchers = []; + + constructor (api, app) { + this._api = api; + + this.findVouchers(app); + } + + async attachContract () { + const address = await Contracts.get().registry.lookupAddress('vouchfor'); + + if (!address || /^0x0*$/.test(address)) { + return null; + } + + const contract = await this._api.newContract(vouchForAbi, address); + + return contract; + } + + async findVouchers ({ contentHash, id }) { + if (!contentHash) { + return; + } + + if (!contractPromise) { + contractPromise = this.attachContract(); + } + + const contract = await contractPromise; + + if (!contract) { + return; + } + + const vouchHash = await this.lookupHash(contract, `0x${contentHash}`); + const vouchId = await this.lookupHash(contract, id); + + this.addVouchers(vouchHash, vouchId); + } + + async lookupHash (contract, hash) { + const vouchers = []; + let lastItem = false; + + for (let index = 0; !lastItem; index++) { + const voucher = await contract.instance.vouched.call({}, [hash, index]); + + if (/^0x0*$/.test(voucher)) { + lastItem = true; + } else { + vouchers.push(voucher); + } + } + + return vouchers; + } + + @action addVouchers = (vouchHash, vouchId) => { + this.vouchers = uniq([].concat(this.vouchers.peek(), vouchHash, vouchId)); + } +} diff --git a/js/src/ui/IdentityIcon/identityIcon.js b/js/src/ui/IdentityIcon/identityIcon.js index 3db1bc763..0d31b6bb5 100644 --- a/js/src/ui/IdentityIcon/identityIcon.js +++ b/js/src/ui/IdentityIcon/identityIcon.js @@ -30,6 +30,7 @@ class IdentityIcon extends Component { static propTypes = { address: PropTypes.string, + alt: PropTypes.string, button: PropTypes.bool, center: PropTypes.bool, className: PropTypes.string, @@ -84,7 +85,7 @@ class IdentityIcon extends Component { } render () { - const { address, button, className, center, disabled, inline, padded, tiny } = this.props; + const { address, alt, button, className, center, disabled, inline, padded, tiny } = this.props; const { iconsrc } = this.state; const classes = [ styles.icon, @@ -135,6 +136,7 @@ class IdentityIcon extends Component { return ( { { if (!isWallet) { return { func, options, values }; diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js index a475e3a6b..50ad70164 100644 --- a/js/src/views/Account/account.js +++ b/js/src/views/Account/account.js @@ -26,7 +26,6 @@ import HardwareStore from '~/mobx/hardwareStore'; import ExportStore from '~/modals/ExportAccount/exportStore'; import { DeleteAccount, EditMeta, Faucet, PasswordManager, Shapeshift, Transfer, Verification } from '~/modals'; import { setVisibleAccounts } from '~/redux/providers/personalActions'; -import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions'; import { Actionbar, Button, ConfirmDialog, Input, Page, Portal } from '~/ui'; import { DeleteIcon, DialIcon, EditIcon, LockedIcon, SendIcon, VerifyIcon, FileDownloadIcon } from '~/ui/Icons'; @@ -45,8 +44,6 @@ class Account extends Component { static propTypes = { accounts: PropTypes.object.isRequired, - fetchCertifiers: PropTypes.func.isRequired, - fetchCertifications: PropTypes.func.isRequired, setVisibleAccounts: PropTypes.func.isRequired, account: PropTypes.object, @@ -67,7 +64,6 @@ class Account extends Component { } componentDidMount () { - this.props.fetchCertifiers(); this.setVisibleAccounts(); } @@ -90,11 +86,10 @@ class Account extends Component { } setVisibleAccounts (props = this.props) { - const { params, setVisibleAccounts, fetchCertifications } = props; + const { params, setVisibleAccounts } = props; const addresses = [params.address]; setVisibleAccounts(addresses); - fetchCertifications(params.address); } render () { @@ -524,8 +519,6 @@ function mapStateToProps (state, props) { function mapDispatchToProps (dispatch) { return bindActionCreators({ - fetchCertifiers, - fetchCertifications, newError, setVisibleAccounts }, dispatch); diff --git a/js/src/views/Accounts/List/list.js b/js/src/views/Accounts/List/list.js index 2fa3be70b..7ff04ab30 100644 --- a/js/src/views/Accounts/List/list.js +++ b/js/src/views/Accounts/List/list.js @@ -17,10 +17,8 @@ import { pick } from 'lodash'; import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; import { Container, SectionList } from '~/ui'; -import { fetchCertifiers, fetchCertifications } from '~/redux/providers/certifications/actions'; import { ETH_TOKEN } from '~/util/tokens'; import Summary from '../Summary'; @@ -38,20 +36,9 @@ class List extends Component { orderFallback: PropTypes.string, search: PropTypes.array, - fetchCertifiers: PropTypes.func.isRequired, - fetchCertifications: PropTypes.func.isRequired, handleAddSearchToken: PropTypes.func }; - componentWillMount () { - const { accounts, fetchCertifiers, fetchCertifications } = this.props; - - fetchCertifiers(); - for (let address in accounts) { - fetchCertifications(address); - } - } - render () { const { accounts, disabled, empty } = this.props; @@ -264,14 +251,7 @@ function mapStateToProps (state, props) { return { balances, certifications }; } -function mapDispatchToProps (dispatch) { - return bindActionCreators({ - fetchCertifiers, - fetchCertifications - }, dispatch); -} - export default connect( mapStateToProps, - mapDispatchToProps + null )(List); diff --git a/js/src/views/Signer/components/SignRequest/signRequest.spec.js b/js/src/views/Signer/components/SignRequest/signRequest.spec.js index 62732807e..3cd9a33de 100644 --- a/js/src/views/Signer/components/SignRequest/signRequest.spec.js +++ b/js/src/views/Signer/components/SignRequest/signRequest.spec.js @@ -84,7 +84,7 @@ describe('views/Signer/components/SignRequest', () => { expect(component).to.be.ok; }); - describe.only('isMarkdown', () => { + describe('isMarkdown', () => { it('returns true for markdown', () => { const testMd = '# this is some\n\n*markdown*'; const encodedMd = asciiToHex(unescape(encodeURIComponent(testMd))); @@ -99,7 +99,7 @@ describe('views/Signer/components/SignRequest', () => { expect(isMarkdown(encodedMd)).to.be.true; }); - it('returns false for randow data', () => { + it('returns false for random data', () => { expect(isMarkdown('0x1234')).to.be.false; }); }); diff --git a/js/wasm/ethkey/Cargo.toml b/js/wasm/ethkey/Cargo.toml index 8eb9159e9..22e5bf553 100644 --- a/js/wasm/ethkey/Cargo.toml +++ b/js/wasm/ethkey/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity ethkey WASM module." name = "parity-ethkey-wasm" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/logger/Cargo.toml b/logger/Cargo.toml index 8b9a8dea2..fc63701c4 100644 --- a/logger/Cargo.toml +++ b/logger/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore client." name = "ethcore-logger" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/mac/Parity.pkgproj b/mac/Parity.pkgproj index 1c87af629..560f8b022 100755 --- a/mac/Parity.pkgproj +++ b/mac/Parity.pkgproj @@ -462,7 +462,7 @@ OVERWRITE_PERMISSIONS VERSION - 1.8.0 + 1.9.0 UUID 2DCD5B81-7BAF-4DA1-9251-6274B089FD36 diff --git a/mac/Parity/Info.plist b/mac/Parity/Info.plist index dba951778..24cba2646 100644 --- a/mac/Parity/Info.plist +++ b/mac/Parity/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.8 + 1.9 CFBundleVersion 1 LSApplicationCategoryType diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 25ba98863..f4a180bf9 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -9,7 +9,7 @@ !define COMPANYNAME "Parity" !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 -!define VERSIONMINOR 8 +!define VERSIONMINOR 9 !define VERSIONBUILD 0 !define ARGS "--warp" !define FIRST_START_ARGS "ui --warp --mode=passive" diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index dc6c2fe7b..18d800546 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -1201,6 +1201,7 @@ mod tests { Snapshots, VM, Misc, Whisper, SecretStore, }; use toml; + use clap::{ErrorKind as ClapErrorKind}; #[test] fn should_parse_args_and_flags() { @@ -1217,6 +1218,17 @@ mod tests { assert_eq!(args.arg_export_state_min_balance, Some("123".to_string())); } + #[test] + fn should_exit_gracefully_on_unknown_argument() { + let result = Args::parse(&["parity", "--please-exit-gracefully"]); + assert!( + match result { + Err(ArgsError::Clap(ref clap_error)) if clap_error.kind == ClapErrorKind::UnknownArgument => true, + _ => false + } + ); + } + #[test] fn should_use_subcommand_arg_default() { let args = Args::parse(&["parity", "export", "state", "--at", "123"]).unwrap(); diff --git a/parity/cli/presets/config.dev-insecure.toml b/parity/cli/presets/config.dev-insecure.toml index 3a9956f8e..e4c2c9f47 100644 --- a/parity/cli/presets/config.dev-insecure.toml +++ b/parity/cli/presets/config.dev-insecure.toml @@ -13,4 +13,4 @@ hosts = ["all"] [ipfs] enable = false # this is the default -hosts = ["all"] \ No newline at end of file +hosts = ["all"] diff --git a/parity/cli/presets/config.dev.toml b/parity/cli/presets/config.dev.toml index f38e17348..4fc0874c5 100644 --- a/parity/cli/presets/config.dev.toml +++ b/parity/cli/presets/config.dev.toml @@ -3,4 +3,4 @@ chain = "dev" [mining] reseal_min_period = 0 -min_gas_price = 0 \ No newline at end of file +min_gas_price = 0 diff --git a/parity/cli/presets/config.insecure.toml b/parity/cli/presets/config.insecure.toml index 6e67db3d7..18859c9cc 100644 --- a/parity/cli/presets/config.insecure.toml +++ b/parity/cli/presets/config.insecure.toml @@ -8,4 +8,4 @@ hosts = ["all"] [ipfs] enable = false # this is the default -hosts = ["all"] \ No newline at end of file +hosts = ["all"] diff --git a/parity/cli/presets/config.mining.toml b/parity/cli/presets/config.mining.toml index 52e004942..f6c39bdd6 100644 --- a/parity/cli/presets/config.mining.toml +++ b/parity/cli/presets/config.mining.toml @@ -28,4 +28,4 @@ cache_size = 256 [misc] # Logging pattern (`=`, e.g. `own_tx=trace`). -logging = "miner=trace,own_tx=trace" \ No newline at end of file +logging = "miner=trace,own_tx=trace" diff --git a/parity/cli/presets/config.non-standard-ports.toml b/parity/cli/presets/config.non-standard-ports.toml index e4013ff94..5c522d867 100644 --- a/parity/cli/presets/config.non-standard-ports.toml +++ b/parity/cli/presets/config.non-standard-ports.toml @@ -4,4 +4,4 @@ port = 30305 [rpc] # JSON-RPC over HTTP will be accessible on port 8645. -port = 8645 \ No newline at end of file +port = 8645 diff --git a/parity/cli/usage.rs b/parity/cli/usage.rs index b6a4b723e..dd370bdbc 100644 --- a/parity/cli/usage.rs +++ b/parity/cli/usage.rs @@ -537,21 +537,20 @@ macro_rules! usage { let matches = App::new("Parity") .global_setting(AppSettings::VersionlessSubcommands) - .global_setting(AppSettings::AllowLeadingHyphen) // allow for example --allow-ips -10.0.0.0/8 .global_setting(AppSettings::DisableHelpSubcommand) .help(Args::print_help().as_ref()) - .args(&usages.iter().map(|u| Arg::from_usage(u).use_delimiter(false)).collect::>()) + .args(&usages.iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::>()) $( .subcommand( SubCommand::with_name(&underscore_to_hyphen!(&stringify!($subc)[4..])) .about($subc_help) - .args(&subc_usages.get(stringify!($subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false)).collect::>()) + .args(&subc_usages.get(stringify!($subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::>()) $( .setting(AppSettings::SubcommandRequired) // prevent from running `parity account` .subcommand( SubCommand::with_name(&underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..])) .about($subc_subc_help) - .args(&subc_usages.get(stringify!($subc_subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false)).collect::>()) + .args(&subc_usages.get(stringify!($subc_subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::>()) ) )* ) diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index ceb57639c..73df98ece 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity JSON-RPC servers." name = "parity-rpc" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/rpc/src/v1/types/block_number.rs b/rpc/src/v1/types/block_number.rs index 334bf360d..9570f4420 100644 --- a/rpc/src/v1/types/block_number.rs +++ b/rpc/src/v1/types/block_number.rs @@ -82,9 +82,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { _ if value.starts_with("0x") => u64::from_str_radix(&value[2..], 16).map(BlockNumber::Num).map_err(|e| { Error::custom(format!("Invalid block number: {}", e)) }), - _ => value.parse::().map(BlockNumber::Num).map_err(|e| { - Error::custom(format!("Invalid block number: {}", e)) - }), + _ => Err(Error::custom(format!("Invalid block number: missing 0x prefix"))), } } @@ -112,9 +110,15 @@ mod tests { #[test] fn block_number_deserialization() { - let s = r#"["0xa", "10", "latest", "earliest", "pending"]"#; + let s = r#"["0xa", "latest", "earliest", "pending"]"#; let deserialized: Vec = serde_json::from_str(s).unwrap(); - assert_eq!(deserialized, vec![BlockNumber::Num(10), BlockNumber::Num(10), BlockNumber::Latest, BlockNumber::Earliest, BlockNumber::Pending]) + assert_eq!(deserialized, vec![BlockNumber::Num(10), BlockNumber::Latest, BlockNumber::Earliest, BlockNumber::Pending]) + } + + #[test] + fn should_not_deserialize_decimal() { + let s = r#""10""#; + assert!(serde_json::from_str::(s).is_err()); } #[test] diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs index 4bd10af44..fdbcb729b 100644 --- a/rpc/src/v1/types/bytes.rs +++ b/rpc/src/v1/types/bytes.rs @@ -74,13 +74,7 @@ impl<'a> Visitor<'a> for BytesVisitor { } fn visit_str(self, value: &str) -> Result where E: Error { - if value.is_empty() { - warn!( - target: "deprecated", - "Deserializing empty string as empty bytes. This is a non-standard behaviour that will be removed in future versions. Please update your code to send `0x` instead!" - ); - Ok(Bytes::new(Vec::new())) - } else if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { + if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { Ok(Bytes::new(FromHex::from_hex(&value[2..]).map_err(|e| Error::custom(format!("Invalid hex: {}", e)))?)) } else { Err(Error::custom("Invalid bytes format. Expected a 0x-prefixed hex string with even length")) @@ -108,8 +102,7 @@ mod tests { #[test] fn test_bytes_deserialize() { - // TODO [ToDr] Uncomment when Mist starts sending correct data - // let bytes1: Result = serde_json::from_str(r#""""#); + let bytes1: Result = serde_json::from_str(r#""""#); let bytes2: Result = serde_json::from_str(r#""0x123""#); let bytes3: Result = serde_json::from_str(r#""0xgg""#); @@ -117,19 +110,12 @@ mod tests { let bytes5: Bytes = serde_json::from_str(r#""0x12""#).unwrap(); let bytes6: Bytes = serde_json::from_str(r#""0x0123""#).unwrap(); - // assert!(bytes1.is_err()); + assert!(bytes1.is_err()); assert!(bytes2.is_err()); assert!(bytes3.is_err()); assert_eq!(bytes4, Bytes(vec![])); assert_eq!(bytes5, Bytes(vec![0x12])); assert_eq!(bytes6, Bytes(vec![0x1, 0x23])); } - - // TODO [ToDr] Remove when Mist starts sending correct data - #[test] - fn test_bytes_lenient_against_the_spec_deserialize_for_empty_string_for_mist_compatibility() { - let deserialized: Bytes = serde_json::from_str(r#""""#).unwrap(); - assert_eq!(deserialized, Bytes(Vec::new())); - } } diff --git a/stratum/Cargo.toml b/stratum/Cargo.toml index 47f2c0447..8e60854e2 100644 --- a/stratum/Cargo.toml +++ b/stratum/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore stratum lib" name = "ethcore-stratum" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 8f1e08093..105aa82c6 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore blockchain sync" name = "ethsync" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/updater/Cargo.toml b/updater/Cargo.toml index 0d4b29025..9897bf7d0 100644 --- a/updater/Cargo.toml +++ b/updater/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity Updater Service." name = "parity-updater" -version = "1.8.0" +version = "1.9.0" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/util/Cargo.toml b/util/Cargo.toml index 1877c7466..2bd3654a1 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.0" +version = "1.9.0" authors = ["Parity Technologies "] build = "build.rs" diff --git a/util/io/Cargo.toml b/util/io/Cargo.toml index 654ac1978..c6fd21b9a 100644 --- a/util/io/Cargo.toml +++ b/util/io/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore IO library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-io" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [dependencies] diff --git a/util/network/Cargo.toml b/util/network/Cargo.toml index e99df9024..0960715bf 100644 --- a/util/network/Cargo.toml +++ b/util/network/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore network library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-network" -version = "1.8.0" +version = "1.9.0" authors = ["Parity Technologies "] [dependencies]