Merge branch 'master' into lightsync

This commit is contained in:
Robert Habermeier 2016-12-23 13:39:06 +01:00
commit d0194f3ad3
314 changed files with 2576 additions and 7213 deletions

View File

@ -1,6 +1,7 @@
stages:
- test
- js-build
- push-release
- build
variables:
GIT_DEPTH: "3"
@ -20,7 +21,6 @@ linux-stable:
- stable
- triggers
script:
- curl --data "secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
- cargo build -j $(nproc) --release --features final $CARGOFLAGS
- strip target/release/parity
- export SHA3=$(target/release/parity tools hash target/release/parity)
@ -517,3 +517,15 @@ js-release:
- if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS rebuild since no JS files modified."; else ./js/scripts/build.sh && ./js/scripts/release.sh; fi
tags:
- javascript
push-release:
stage: push-release
only:
- beta
- tags
- stable
- triggers
image: ethcore/rust:stable
script:
- curl --data "secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
tags:
- curl

349
Cargo.lock generated
View File

@ -26,13 +26,14 @@ dependencies = [
"ethcore-util 1.5.0",
"ethsync 1.5.0",
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.5.0",
"parity-reactor 0.1.0",
"parity-rpc-client 1.4.0",
"parity-updater 1.5.0",
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
@ -42,13 +43,22 @@ dependencies = [
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "advapi32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.5.1"
@ -98,11 +108,6 @@ dependencies = [
"syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bit-set"
version = "0.4.0"
@ -126,6 +131,11 @@ name = "bitflags"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "blastfig"
version = "0.3.3"
@ -200,9 +210,35 @@ dependencies = [
]
[[package]]
name = "crossbeam"
version = "0.2.9"
name = "core-foundation"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core-foundation-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crypt32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ctrlc"
@ -281,7 +317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -305,7 +341,7 @@ dependencies = [
"bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.5.0",
@ -364,6 +400,7 @@ dependencies = [
"ethcore-rpc 1.5.0",
"ethcore-util 1.5.0",
"fetch 0.1.0",
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)",
@ -373,10 +410,11 @@ dependencies = [
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.5.0",
"parity-reactor 0.1.0",
"parity-ui 1.5.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -396,7 +434,7 @@ dependencies = [
name = "ethcore-io"
version = "1.5.0"
dependencies = [
"crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (git+https://github.com/ethcore/mio)",
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -532,16 +570,19 @@ dependencies = [
"ethstore 0.1.0",
"ethsync 1.5.0",
"fetch 0.1.0",
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0",
"parity-updater 1.5.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -638,7 +679,7 @@ version = "0.1.0"
dependencies = [
"ethcore-util 1.5.0",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -666,11 +707,12 @@ dependencies = [
"itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -721,10 +763,11 @@ dependencies = [
name = "fetch"
version = "0.1.0"
dependencies = [
"https-fetch 0.1.0",
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -744,6 +787,16 @@ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures-cpupool"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gcc"
version = "0.3.35"
@ -752,6 +805,15 @@ dependencies = [
"rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gdi32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glob"
version = "0.2.11"
@ -783,19 +845,9 @@ name = "httparse"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "https-fetch"
version = "0.1.0"
dependencies = [
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
"rustls 0.1.2 (git+https://github.com/ctz/rustls)",
]
[[package]]
name = "hyper"
version = "0.9.10"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -803,7 +855,7 @@ dependencies = [
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
@ -847,7 +899,7 @@ name = "igd"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -892,7 +944,7 @@ source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec33
dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -929,7 +981,7 @@ version = "0.1.0"
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
dependencies = [
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1103,6 +1155,22 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miow"
version = "0.1.3"
@ -1142,6 +1210,18 @@ dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "native-tls"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"openssl 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"schannel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net2"
version = "0.2.23"
@ -1276,6 +1356,14 @@ dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "number_prefix"
version = "0.2.5"
@ -1298,6 +1386,28 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl-sys"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "owning_ref"
version = "0.2.2"
@ -1324,11 +1434,23 @@ dependencies = [
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-util 1.5.0",
"fetch 0.1.0",
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parity-reactor"
version = "0.1.0"
dependencies = [
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parity-rpc-client"
version = "1.4.0"
@ -1342,7 +1464,7 @@ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1368,7 +1490,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.4.0"
source = "git+https://github.com/ethcore/js-precompiled.git#c8eb24c13e6fa57bf3b85b16209d281d89b31cbf"
source = "git+https://github.com/ethcore/js-precompiled.git#8d16476c138e94a643ad4624df9825f34b57e1b0"
dependencies = [
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1386,6 +1508,7 @@ dependencies = [
"ipc-common-types 1.5.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.5.0",
"parity-reactor 0.1.0",
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1444,6 +1567,11 @@ dependencies = [
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "podio"
version = "0.1.5"
@ -1574,12 +1702,17 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ring"
version = "0.4.3"
name = "reqwest"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1682,16 +1815,51 @@ dependencies = [
]
[[package]]
name = "rustls"
version = "0.1.2"
source = "git+https://github.com/ctz/rustls#3d2db624997004b7b18ba4463d6081f37598b2f5"
name = "schannel"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webpki 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scoped-tls"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "secur32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "security-framework"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "security-framework-sys"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1726,7 +1894,7 @@ dependencies = [
[[package]]
name = "serde"
version = "0.8.4"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -1759,7 +1927,16 @@ dependencies = [
"dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_urlencoded"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1983,6 +2160,18 @@ name = "tiny-keccak"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "tokio-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.1.28"
@ -2043,11 +2232,6 @@ name = "unicode-xid"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "untrusted"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.2.0"
@ -2057,6 +2241,15 @@ dependencies = [
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "user32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "using_queue"
version = "0.1.0"
@ -2089,17 +2282,6 @@ name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "webpki"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ring 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
@ -2167,17 +2349,18 @@ dependencies = [
]
[metadata]
"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a"
"checksum aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67077478f0a03952bed2e6786338d400d40c25e9836e08ad50af96607317fd03"
"checksum ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1f46cd5b1d660c938e3f92dfe7a73d832b3281479363dd0cd9c1c2fbf60f7962"
"checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4"
"checksum arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "16e3bdb2f54b3ace0285975d59a97cf8ed3855294b2b6bc651fcf22a9c352975"
"checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a"
"checksum aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df293303e8a52e1df7984ac1415e195f5fcbf51e4bb7bda54557861a3954a08"
"checksum base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2015e3793554aa5b6007e3a72959e84c1070039e74f13dde08fa64afe1ddd892"
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09640e0509d97d5cdff03a9f5daf087a8e04c735c3b113a75139634a19cfc7b2"
"checksum bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f421095d2a76fc24cd3fb3f912b90df06be7689912b1bdb423caefae59c258d"
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
@ -2188,7 +2371,10 @@ dependencies = [
"checksum clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "ce96ec05bfe018a0d5d43da115e54850ea2217981ff0f2e462780ab9d594651a"
"checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245"
"checksum cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d53b80dde876f47f03cda35303e368a79b91c70b0d65ecba5fd5280944a08591"
"checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc"
"checksum core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "20a6d0448d3a99d977ae4a2aa5a98d886a923e863e81ad9ff814645b6feb3bbd"
"checksum core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "05eed248dc504a5391c63794fe4fb64f46f071280afaa1b73308f3c0ce4574c5"
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
"checksum crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e34988f7e069e0b2f3bfc064295161e489b2d4e04a2e4248fb94360cdf00b4ec"
"checksum ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)" = "<none>"
"checksum daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "271ec51b7e0bee92f0d04601422c73eb76ececf197026711c97ad25038a010cf"
"checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
@ -2201,14 +2387,16 @@ dependencies = [
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
"checksum futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bad0a2ac64b227fdc10c254051ae5af542cf19c9328704fd4092f7914196897"
"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82"
"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312"
"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1"
"checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c"
"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58"
"checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae"
"checksum hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)" = "<none>"
"checksum hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "eb27e8a3e8f17ac43ffa41bbda9cf5ad3f9f13ef66fa4873409d4902310275f7"
"checksum hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb3fc65554155980167fb821d05c7c66177f92464976c0b676a19d9e03387a7"
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
"checksum igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8c12b1795b8b168f577c45fa10379b3814dcb11b7ab702406001f0d63f40484"
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
@ -2237,10 +2425,12 @@ dependencies = [
"checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e"
"checksum mio 0.6.0-dev (git+https://github.com/ethcore/mio?branch=timer-fix)" = "<none>"
"checksum mio 0.6.1 (git+https://github.com/ethcore/mio)" = "<none>"
"checksum mio 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "410a1a0ff76f5a226f1e4e3ff1756128e65cd30166e39c3892283e2ac09d5b67"
"checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a"
"checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8"
"checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
"checksum nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
"checksum native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4e52995154bb6f0b41e4379a279482c9387c1632e3798ba4e511ef8c54ee09"
"checksum net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a816012ca11cb47009693c1e0c6130e26d39e4d97ee2a13c50e868ec83e3204"
"checksum nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f05c2fc965fc1cd6b73fa57fa7b89f288178737f2f3ce9e63e4a6a141189000e"
"checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2"
@ -2255,9 +2445,12 @@ dependencies = [
"checksum num-rational 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "48cdcc9ff4ae2a8296805ac15af88b3d88ce62128ded0cb74ffb63a587502a84"
"checksum num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "51eab148f171aefad295f8cece636fc488b9b392ef544da31ea4b8ef6b9e9c39"
"checksum num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "51fedae97a05f7353612fe017ab705a37e6db8f4d67c5c6fe739a9e70d6eed09"
"checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3"
"checksum number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "084d05f4bf60621a9ac9bde941a410df548f4de9545f06e5ee9d3aef4b97cd77"
"checksum odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1"
"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c"
"checksum openssl 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "12be61c7eaa23228316ff02c39807e4c1b1af84ba81420f19fd58dade304b25c"
"checksum openssl-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d2845e841700e7b04282ceaa115407ea84e0db918ae689ad9ceb6f06fa6046bd"
"checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7"
"checksum parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98378dec0a185da2b7180308752f0bad73aaa949c3e0a3b0528d0e067945f7ab"
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "<none>"
@ -2267,6 +2460,7 @@ dependencies = [
"checksum phf_codegen 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8af7ae7c3f75a502292b491e5cc0a1f69e3407744abe6e57e2a3b712bb82f01d"
"checksum phf_generator 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "db005608fd99800c8c74106a7c894cf582055b689aa14a79462cefdcb7dc1cc3"
"checksum phf_shared 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "fee4d039930e4f45123c9b15976cf93a499847b6483dc09c42ea0ec4940f2aa6"
"checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa"
"checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
"checksum primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e31b86efadeaeb1235452171a66689682783149a6249ff334a2c5d8218d00a4"
"checksum primal-bit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "464a91febc06166783d4f5ba3577b5ed8dda8e421012df80bfe48a971ed7be8f"
@ -2283,7 +2477,7 @@ dependencies = [
"checksum rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "655df67c314c30fa3055a365eae276eb88aa4f3413a352a1ab32c1320eda41ea"
"checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29"
"checksum regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "841591b1e05609a643e3b4d0045fce04f701daba7151ddcd3ad47b080693d5a9"
"checksum ring 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2f6547bf9640f1d3cc4e771f82374ec8fd237c17eeb3ff5cd5ccbe22377a09"
"checksum reqwest 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83186fee0d4dbeb95e610b77b05b05cf5b31703dd375222acb74c3dff4be957c"
"checksum rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)" = "<none>"
"checksum rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)" = "<none>"
"checksum rotor 0.6.3 (git+https://github.com/ethcore/rotor)" = "<none>"
@ -2292,15 +2486,20 @@ dependencies = [
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
"checksum rustls 0.1.2 (git+https://github.com/ctz/rustls)" = "<none>"
"checksum schannel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "167852e03fcd0029c3ddebb5afb0715b2996f6e262b2c2aceaa7cd84edd4b158"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
"checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc"
"checksum security-framework 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52186fcf3b391c9f0ccdce9a2ac708f7cc81b3f89e149b34bd9279fb1b23f9fa"
"checksum security-framework-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c84067e6297c1f09514a8666d8bbc1268817ec4a6c0f30f12f6201e1f34bd2a1"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f"
"checksum semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5"
"checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9"
"checksum serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b1dfda9ebb31d29fa8b94d7eb3031a86a8dcec065f0fe268a30f98867bf45775"
"checksum serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)" = "58a19c0871c298847e6b68318484685cd51fa5478c0c905095647540031356e5"
"checksum serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e422ae53d7933f59c6ff57e7b5870b5c9094b1f473f78ec33d89f8a692c3ec02"
"checksum serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f877e2781ed0a323295d1c9f0e26556117b5a11489fc47b1848dfb98b3173d21"
"checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc"
"checksum serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53d4ebaa8d1d4f90d1b63dfca81ccd98ac20e1e479dbae393cbaf60f6fecd8d8"
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
"checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d"
"checksum siphasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c44e42fa187b5a8782489cf7740cc27c3125806be2bf33563cf5e02e9533fcd"
@ -2329,6 +2528,7 @@ dependencies = [
"checksum thread_local 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0694f51610ef7cfac7a1b81de7f1602ee5356e76541bcd62c40e71933338cab1"
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
"checksum tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aef43048292ca0bae4ab32180e85f6202cf2816c2a210c396a84b99dab9270"
"checksum tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "52416b3e937abac22a543a7f1c66bd37feb60137ff1ab42390fa02df85347e58"
"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6"
"checksum toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442dfc13508e603c3f763274361db7f79d7469a0e95c411cde53662ab30fc72"
"checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616"
@ -2338,13 +2538,12 @@ dependencies = [
"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
"checksum untrusted 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5d9bc0e6e73a10975d1fbff8ac3541e221181b0d8998351600fb5523de634c0d"
"checksum url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afe9ec54bc4db14bc8744b7fed060d785ac756791450959b2248443319d5b119"
"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0795a11576d29ae80525a3fda315bf7b534f8feb9d34101e5fe63fb95bb2fd24"
"checksum vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56b639f935488eb40f06d17c3e3bcc3054f6f75d264e187b1107c8d1cba8d31c"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum webpki 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "813503a5985585e0812d430cd1328ee322f47f66629c8ed4ecab939cf9e92f91"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum ws 0.5.3 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)" = "<none>"

View File

@ -52,6 +52,7 @@ parity-rpc-client = { path = "rpc_client" }
ethcore-light = { path = "ethcore/light" }
parity-hash-fetch = { path = "hash-fetch" }
parity-updater = { path = "updater" }
parity-reactor = { path = "util/reactor" }
[target.'cfg(windows)'.dependencies]
winapi = "0.2"

View File

@ -12,6 +12,7 @@ build = "build.rs"
rand = "0.3.14"
log = "0.3"
env_logger = "0.3"
futures = "0.1"
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" }
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
@ -33,6 +34,7 @@ ethcore-util = { path = "../util" }
fetch = { path = "../util/fetch" }
parity-ui = { path = "./ui" }
parity-hash-fetch = { path = "../hash-fetch" }
parity-reactor = { path = "../util/reactor" }
clippy = { version = "0.0.103", optional = true}

View File

@ -23,7 +23,7 @@ use hyper::header::AccessControlAllowOrigin;
use api::types::{App, ApiError};
use api::response;
use apps::fetcher::ContentFetcher;
use apps::fetcher::Fetcher;
use handlers::extract_url;
use endpoint::{Endpoint, Endpoints, Handler, EndpointPath};
@ -33,11 +33,11 @@ use jsonrpc_http_server::cors;
pub struct RestApi {
cors_domains: Option<Vec<AccessControlAllowOrigin>>,
endpoints: Arc<Endpoints>,
fetcher: Arc<ContentFetcher>,
fetcher: Arc<Fetcher>,
}
impl RestApi {
pub fn new(cors_domains: Vec<String>, endpoints: Arc<Endpoints>, fetcher: Arc<ContentFetcher>) -> Box<Endpoint> {
pub fn new(cors_domains: Vec<String>, endpoints: Arc<Endpoints>, fetcher: Arc<Fetcher>) -> Box<Endpoint> {
Box::new(RestApi {
cors_domains: Some(cors_domains.into_iter().map(AccessControlAllowOrigin::Value).collect()),
endpoints: endpoints,

View File

@ -1,445 +0,0 @@
// Copyright 2015, 2016 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 <http://www.gnu.org/licenses/>.
//! Fetchable Dapps support.
//! Manages downloaded (cached) Dapps and downloads them when necessary.
//! Uses `URLHint` to resolve addresses into Dapps bundle file location.
use zip;
use std::{fs, env, fmt};
use std::io::{self, Read, Write};
use std::path::PathBuf;
use std::sync::Arc;
use rustc_serialize::hex::FromHex;
use hash_fetch::urlhint::{URLHintContract, URLHint, URLHintResult};
use hyper;
use hyper::status::StatusCode;
use random_filename;
use SyncStatus;
use util::{Mutex, H256};
use util::sha3::sha3;
use page::{LocalPageEndpoint, PageCache};
use handlers::{ContentHandler, ContentFetcherHandler, ContentValidator};
use endpoint::{Endpoint, EndpointPath, Handler};
use apps::cache::{ContentCache, ContentStatus};
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
/// Limit of cached dapps/content
const MAX_CACHED_DAPPS: usize = 20;
pub struct ContentFetcher<R: URLHint = URLHintContract> {
dapps_path: PathBuf,
resolver: R,
cache: Arc<Mutex<ContentCache>>,
sync: Arc<SyncStatus>,
embeddable_on: Option<(String, u16)>,
}
impl<R: URLHint> Drop for ContentFetcher<R> {
fn drop(&mut self) {
// Clear cache path
let _ = fs::remove_dir_all(&self.dapps_path);
}
}
impl<R: URLHint> ContentFetcher<R> {
pub fn new(resolver: R, sync_status: Arc<SyncStatus>, embeddable_on: Option<(String, u16)>) -> Self {
let mut dapps_path = env::temp_dir();
dapps_path.push(random_filename());
ContentFetcher {
dapps_path: dapps_path,
resolver: resolver,
sync: sync_status,
cache: Arc::new(Mutex::new(ContentCache::default())),
embeddable_on: embeddable_on,
}
}
fn still_syncing(address: Option<(String, u16)>) -> Box<Handler> {
Box::new(ContentHandler::error(
StatusCode::ServiceUnavailable,
"Sync In Progress",
"Your node is still syncing. We cannot resolve any content before it's fully synced.",
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>"),
address,
))
}
#[cfg(test)]
fn set_status(&self, content_id: &str, status: ContentStatus) {
self.cache.lock().insert(content_id.to_owned(), status);
}
pub fn contains(&self, content_id: &str) -> bool {
{
let mut cache = self.cache.lock();
// Check if we already have the app
if cache.get(content_id).is_some() {
return true;
}
}
// fallback to resolver
if let Ok(content_id) = content_id.from_hex() {
// else try to resolve the app_id
let has_content = self.resolver.resolve(content_id).is_some();
// if there is content or we are syncing return true
has_content || self.sync.is_major_importing()
} else {
false
}
}
pub fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box<Handler> {
let mut cache = self.cache.lock();
let content_id = path.app_id.clone();
let (new_status, handler) = {
let status = cache.get(&content_id);
match status {
// Just serve the content
Some(&mut ContentStatus::Ready(ref endpoint)) => {
(None, endpoint.to_async_handler(path, control))
},
// Content is already being fetched
Some(&mut ContentStatus::Fetching(ref fetch_control)) => {
trace!(target: "dapps", "Content fetching in progress. Waiting...");
(None, fetch_control.to_async_handler(path, control))
},
// We need to start fetching the content
None => {
trace!(target: "dapps", "Content unavailable. Fetching... {:?}", content_id);
let content_hex = content_id.from_hex().expect("to_handler is called only when `contains` returns true.");
let content = self.resolver.resolve(content_hex);
let cache = self.cache.clone();
let id = content_id.clone();
let on_done = move |result: Option<LocalPageEndpoint>| {
let mut cache = cache.lock();
match result {
Some(endpoint) => {
cache.insert(id.clone(), ContentStatus::Ready(endpoint));
},
// In case of error
None => {
cache.remove(&id);
},
}
};
match content {
// Don't serve dapps if we are still syncing (but serve content)
Some(URLHintResult::Dapp(_)) if self.sync.is_major_importing() => {
(None, Self::still_syncing(self.embeddable_on.clone()))
},
Some(URLHintResult::Dapp(dapp)) => {
let (handler, fetch_control) = ContentFetcherHandler::new(
dapp.url(),
path,
control,
DappInstaller {
id: content_id.clone(),
dapps_path: self.dapps_path.clone(),
on_done: Box::new(on_done),
embeddable_on: self.embeddable_on.clone(),
},
self.embeddable_on.clone(),
);
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
},
Some(URLHintResult::Content(content)) => {
let (handler, fetch_control) = ContentFetcherHandler::new(
content.url,
path,
control,
ContentInstaller {
id: content_id.clone(),
mime: content.mime,
content_path: self.dapps_path.clone(),
on_done: Box::new(on_done),
},
self.embeddable_on.clone(),
);
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
},
None if self.sync.is_major_importing() => {
(None, Self::still_syncing(self.embeddable_on.clone()))
},
None => {
// This may happen when sync status changes in between
// `contains` and `to_handler`
(None, Box::new(ContentHandler::error(
StatusCode::NotFound,
"Resource Not Found",
"Requested resource was not found.",
None,
self.embeddable_on.clone(),
)) as Box<Handler>)
},
}
},
}
};
if let Some(status) = new_status {
cache.clear_garbage(MAX_CACHED_DAPPS);
cache.insert(content_id, status);
}
handler
}
}
#[derive(Debug)]
pub enum ValidationError {
Io(io::Error),
Zip(zip::result::ZipError),
InvalidContentId,
ManifestNotFound,
ManifestSerialization(String),
HashMismatch { expected: H256, got: H256, },
}
impl fmt::Display for ValidationError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
ValidationError::Io(ref io) => write!(f, "Unexpected IO error occured: {:?}", io),
ValidationError::Zip(ref zip) => write!(f, "Unable to read ZIP archive: {:?}", zip),
ValidationError::InvalidContentId => write!(f, "ID is invalid. It should be 256 bits keccak hash of content."),
ValidationError::ManifestNotFound => write!(f, "Downloaded Dapp bundle did not contain valid manifest.json file."),
ValidationError::ManifestSerialization(ref err) => {
write!(f, "There was an error during Dapp Manifest serialization: {:?}", err)
},
ValidationError::HashMismatch { ref expected, ref got } => {
write!(f, "Hash of downloaded content did not match. Expected:{:?}, Got:{:?}.", expected, got)
},
}
}
}
impl From<io::Error> for ValidationError {
fn from(err: io::Error) -> Self {
ValidationError::Io(err)
}
}
impl From<zip::result::ZipError> for ValidationError {
fn from(err: zip::result::ZipError) -> Self {
ValidationError::Zip(err)
}
}
struct ContentInstaller {
id: String,
mime: String,
content_path: PathBuf,
on_done: Box<Fn(Option<LocalPageEndpoint>) + Send>,
}
impl ContentValidator for ContentInstaller {
type Error = ValidationError;
fn validate_and_install(&self, path: PathBuf) -> Result<LocalPageEndpoint, ValidationError> {
let validate = || {
// Create dir
try!(fs::create_dir_all(&self.content_path));
// Validate hash
let mut file_reader = io::BufReader::new(try!(fs::File::open(&path)));
let hash = try!(sha3(&mut file_reader));
let id = try!(self.id.as_str().parse().map_err(|_| ValidationError::InvalidContentId));
if id != hash {
return Err(ValidationError::HashMismatch {
expected: id,
got: hash,
});
}
// And prepare path for a file
let filename = path.file_name().expect("We always fetch a file.");
let mut content_path = self.content_path.clone();
content_path.push(&filename);
if content_path.exists() {
try!(fs::remove_dir_all(&content_path))
}
try!(fs::copy(&path, &content_path));
Ok(LocalPageEndpoint::single_file(content_path, self.mime.clone(), PageCache::Enabled))
};
// Make sure to always call on_done (even in case of errors)!
let result = validate();
(self.on_done)(result.as_ref().ok().cloned());
result
}
}
struct DappInstaller {
id: String,
dapps_path: PathBuf,
on_done: Box<Fn(Option<LocalPageEndpoint>) + Send>,
embeddable_on: Option<(String, u16)>,
}
impl DappInstaller {
fn find_manifest(zip: &mut zip::ZipArchive<fs::File>) -> Result<(Manifest, PathBuf), ValidationError> {
for i in 0..zip.len() {
let mut file = try!(zip.by_index(i));
if !file.name().ends_with(MANIFEST_FILENAME) {
continue;
}
// try to read manifest
let mut manifest = String::new();
let manifest = file
.read_to_string(&mut manifest).ok()
.and_then(|_| deserialize_manifest(manifest).ok());
if let Some(manifest) = manifest {
let mut manifest_location = PathBuf::from(file.name());
manifest_location.pop(); // get rid of filename
return Ok((manifest, manifest_location));
}
}
Err(ValidationError::ManifestNotFound)
}
fn dapp_target_path(&self, manifest: &Manifest) -> PathBuf {
let mut target = self.dapps_path.clone();
target.push(&manifest.id);
target
}
}
impl ContentValidator for DappInstaller {
type Error = ValidationError;
fn validate_and_install(&self, path: PathBuf) -> Result<LocalPageEndpoint, ValidationError> {
trace!(target: "dapps", "Opening dapp bundle at {:?}", path);
let validate = || {
let mut file_reader = io::BufReader::new(try!(fs::File::open(path)));
let hash = try!(sha3(&mut file_reader));
let id = try!(self.id.as_str().parse().map_err(|_| ValidationError::InvalidContentId));
if id != hash {
return Err(ValidationError::HashMismatch {
expected: id,
got: hash,
});
}
let file = file_reader.into_inner();
// Unpack archive
let mut zip = try!(zip::ZipArchive::new(file));
// First find manifest file
let (mut manifest, manifest_dir) = try!(Self::find_manifest(&mut zip));
// Overwrite id to match hash
manifest.id = self.id.clone();
let target = self.dapp_target_path(&manifest);
// Remove old directory
if target.exists() {
warn!(target: "dapps", "Overwriting existing dapp: {}", manifest.id);
try!(fs::remove_dir_all(target.clone()));
}
// Unpack zip
for i in 0..zip.len() {
let mut file = try!(zip.by_index(i));
// TODO [todr] Check if it's consistent on windows.
let is_dir = file.name().chars().rev().next() == Some('/');
let file_path = PathBuf::from(file.name());
let location_in_manifest_base = file_path.strip_prefix(&manifest_dir);
// Create files that are inside manifest directory
if let Ok(location_in_manifest_base) = location_in_manifest_base {
let p = target.join(location_in_manifest_base);
// Check if it's a directory
if is_dir {
try!(fs::create_dir_all(p));
} else {
let mut target = try!(fs::File::create(p));
try!(io::copy(&mut file, &mut target));
}
}
}
// Write manifest
let manifest_str = try!(serialize_manifest(&manifest).map_err(ValidationError::ManifestSerialization));
let manifest_path = target.join(MANIFEST_FILENAME);
let mut manifest_file = try!(fs::File::create(manifest_path));
try!(manifest_file.write_all(manifest_str.as_bytes()));
// Create endpoint
let endpoint = LocalPageEndpoint::new(target, manifest.clone().into(), PageCache::Enabled, self.embeddable_on.clone());
Ok(endpoint)
};
let result = validate();
(self.on_done)(result.as_ref().ok().cloned());
result
}
}
#[cfg(test)]
mod tests {
use std::env;
use std::sync::Arc;
use util::Bytes;
use hash_fetch::urlhint::{URLHint, URLHintResult};
use apps::cache::ContentStatus;
use endpoint::EndpointInfo;
use page::LocalPageEndpoint;
use super::ContentFetcher;
struct FakeResolver;
impl URLHint for FakeResolver {
fn resolve(&self, _id: Bytes) -> Option<URLHintResult> {
None
}
}
#[test]
fn should_true_if_contains_the_app() {
// given
let path = env::temp_dir();
let fetcher = ContentFetcher::new(FakeResolver, Arc::new(|| false), None);
let handler = LocalPageEndpoint::new(path, EndpointInfo {
name: "fake".into(),
description: "".into(),
version: "".into(),
author: "".into(),
icon_url: "".into(),
}, Default::default(), None);
// when
fetcher.set_status("test", ContentStatus::Ready(handler));
fetcher.set_status("test2", ContentStatus::Fetching(Default::default()));
// then
assert_eq!(fetcher.contains("test"), true);
assert_eq!(fetcher.contains("test2"), true);
assert_eq!(fetcher.contains("test3"), false);
}
}

View File

@ -0,0 +1,255 @@
// Copyright 2015, 2016 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 <http://www.gnu.org/licenses/>.
use zip;
use std::{fs, fmt};
use std::io::{self, Read, Write};
use std::path::PathBuf;
use fetch::{self, Mime};
use util::H256;
use util::sha3::sha3;
use page::{LocalPageEndpoint, PageCache};
use handlers::ContentValidator;
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
type OnDone = Box<Fn(Option<LocalPageEndpoint>) + Send>;
fn write_response_and_check_hash(
id: &str,
mut content_path: PathBuf,
filename: &str,
response: fetch::Response
) -> Result<(fs::File, PathBuf), ValidationError> {
// try to parse id
let id = try!(id.parse().map_err(|_| ValidationError::InvalidContentId));
// check if content exists
if content_path.exists() {
warn!(target: "dapps", "Overwriting existing content at 0x{:?}", id);
try!(fs::remove_dir_all(&content_path))
}
// create directory
try!(fs::create_dir_all(&content_path));
// append filename
content_path.push(filename);
// Now write the response
let mut file = io::BufWriter::new(try!(fs::File::create(&content_path)));
let mut reader = io::BufReader::new(response);
try!(io::copy(&mut reader, &mut file));
try!(file.flush());
// Validate hash
// TODO [ToDr] calculate sha3 in-flight while reading the response
let mut file = io::BufReader::new(try!(fs::File::open(&content_path)));
let hash = try!(sha3(&mut file));
if id == hash {
Ok((file.into_inner(), content_path))
} else {
Err(ValidationError::HashMismatch {
expected: id,
got: hash,
})
}
}
pub struct Content {
id: String,
mime: Mime,
content_path: PathBuf,
on_done: OnDone,
}
impl Content {
pub fn new(id: String, mime: Mime, content_path: PathBuf, on_done: OnDone) -> Self {
Content {
id: id,
mime: mime,
content_path: content_path,
on_done: on_done,
}
}
}
impl ContentValidator for Content {
type Error = ValidationError;
fn validate_and_install(&self, response: fetch::Response) -> Result<LocalPageEndpoint, ValidationError> {
let validate = |content_path: PathBuf| {
// Create dir
let (_, content_path) = try!(write_response_and_check_hash(self.id.as_str(), content_path.clone(), self.id.as_str(), response));
Ok(LocalPageEndpoint::single_file(content_path, self.mime.clone(), PageCache::Enabled))
};
// Prepare path for a file
let content_path = self.content_path.join(&self.id);
// Make sure to always call on_done (even in case of errors)!
let result = validate(content_path.clone());
// remove the file if there was an error
if result.is_err() {
// Ignore errors since the file might not exist
let _ = fs::remove_dir_all(&content_path);
}
(self.on_done)(result.as_ref().ok().cloned());
result
}
}
pub struct Dapp {
id: String,
dapps_path: PathBuf,
on_done: OnDone,
embeddable_on: Option<(String, u16)>,
}
impl Dapp {
pub fn new(id: String, dapps_path: PathBuf, on_done: OnDone, embeddable_on: Option<(String, u16)>) -> Self {
Dapp {
id: id,
dapps_path: dapps_path,
on_done: on_done,
embeddable_on: embeddable_on,
}
}
fn find_manifest(zip: &mut zip::ZipArchive<fs::File>) -> Result<(Manifest, PathBuf), ValidationError> {
for i in 0..zip.len() {
let mut file = try!(zip.by_index(i));
if !file.name().ends_with(MANIFEST_FILENAME) {
continue;
}
// try to read manifest
let mut manifest = String::new();
let manifest = file
.read_to_string(&mut manifest).ok()
.and_then(|_| deserialize_manifest(manifest).ok());
if let Some(manifest) = manifest {
let mut manifest_location = PathBuf::from(file.name());
manifest_location.pop(); // get rid of filename
return Ok((manifest, manifest_location));
}
}
Err(ValidationError::ManifestNotFound)
}
}
impl ContentValidator for Dapp {
type Error = ValidationError;
fn validate_and_install(&self, response: fetch::Response) -> Result<LocalPageEndpoint, ValidationError> {
let validate = |dapp_path: PathBuf| {
let (file, zip_path) = try!(write_response_and_check_hash(self.id.as_str(), dapp_path.clone(), &format!("{}.zip", self.id), response));
trace!(target: "dapps", "Opening dapp bundle at {:?}", zip_path);
// Unpack archive
let mut zip = try!(zip::ZipArchive::new(file));
// First find manifest file
let (mut manifest, manifest_dir) = try!(Self::find_manifest(&mut zip));
// Overwrite id to match hash
manifest.id = self.id.clone();
// Unpack zip
for i in 0..zip.len() {
let mut file = try!(zip.by_index(i));
let is_dir = file.name().chars().rev().next() == Some('/');
let file_path = PathBuf::from(file.name());
let location_in_manifest_base = file_path.strip_prefix(&manifest_dir);
// Create files that are inside manifest directory
if let Ok(location_in_manifest_base) = location_in_manifest_base {
let p = dapp_path.join(location_in_manifest_base);
// Check if it's a directory
if is_dir {
try!(fs::create_dir_all(p));
} else {
let mut target = try!(fs::File::create(p));
try!(io::copy(&mut file, &mut target));
}
}
}
// Remove zip
try!(fs::remove_file(&zip_path));
// Write manifest
let manifest_str = try!(serialize_manifest(&manifest).map_err(ValidationError::ManifestSerialization));
let manifest_path = dapp_path.join(MANIFEST_FILENAME);
let mut manifest_file = try!(fs::File::create(manifest_path));
try!(manifest_file.write_all(manifest_str.as_bytes()));
// Create endpoint
let endpoint = LocalPageEndpoint::new(dapp_path, manifest.clone().into(), PageCache::Enabled, self.embeddable_on.clone());
Ok(endpoint)
};
// Prepare directory for dapp
let target = self.dapps_path.join(&self.id);
// Validate the dapp
let result = validate(target.clone());
// remove the file if there was an error
if result.is_err() {
// Ignore errors since the file might not exist
let _ = fs::remove_dir_all(&target);
}
(self.on_done)(result.as_ref().ok().cloned());
result
}
}
#[derive(Debug)]
pub enum ValidationError {
Io(io::Error),
Zip(zip::result::ZipError),
InvalidContentId,
ManifestNotFound,
ManifestSerialization(String),
HashMismatch { expected: H256, got: H256, },
}
impl fmt::Display for ValidationError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
ValidationError::Io(ref io) => write!(f, "Unexpected IO error occured: {:?}", io),
ValidationError::Zip(ref zip) => write!(f, "Unable to read ZIP archive: {:?}", zip),
ValidationError::InvalidContentId => write!(f, "ID is invalid. It should be 256 bits keccak hash of content."),
ValidationError::ManifestNotFound => write!(f, "Downloaded Dapp bundle did not contain valid manifest.json file."),
ValidationError::ManifestSerialization(ref err) => {
write!(f, "There was an error during Dapp Manifest serialization: {:?}", err)
},
ValidationError::HashMismatch { ref expected, ref got } => {
write!(f, "Hash of downloaded content did not match. Expected:{:?}, Got:{:?}.", expected, got)
},
}
}
}
impl From<io::Error> for ValidationError {
fn from(err: io::Error) -> Self {
ValidationError::Io(err)
}
}
impl From<zip::result::ZipError> for ValidationError {
fn from(err: zip::result::ZipError) -> Self {
ValidationError::Zip(err)
}
}

View File

@ -0,0 +1,265 @@
// Copyright 2015, 2016 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 <http://www.gnu.org/licenses/>.
//! Fetchable Dapps support.
//! Manages downloaded (cached) Dapps and downloads them when necessary.
//! Uses `URLHint` to resolve addresses into Dapps bundle file location.
mod installers;
use std::{fs, env};
use std::path::PathBuf;
use std::sync::Arc;
use rustc_serialize::hex::FromHex;
use fetch::{Client as FetchClient, Fetch};
use hash_fetch::urlhint::{URLHintContract, URLHint, URLHintResult};
use parity_reactor::Remote;
use hyper;
use hyper::status::StatusCode;
use {SyncStatus, random_filename};
use util::Mutex;
use page::LocalPageEndpoint;
use handlers::{ContentHandler, ContentFetcherHandler};
use endpoint::{Endpoint, EndpointPath, Handler};
use apps::cache::{ContentCache, ContentStatus};
/// Limit of cached dapps/content
const MAX_CACHED_DAPPS: usize = 20;
pub trait Fetcher: Send + Sync + 'static {
fn contains(&self, content_id: &str) -> bool;
fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box<Handler>;
}
pub struct ContentFetcher<F: Fetch = FetchClient, R: URLHint + Send + Sync + 'static = URLHintContract> {
dapps_path: PathBuf,
resolver: R,
cache: Arc<Mutex<ContentCache>>,
sync: Arc<SyncStatus>,
embeddable_on: Option<(String, u16)>,
remote: Remote,
fetch: F,
}
impl<R: URLHint + Send + Sync + 'static, F: Fetch> Drop for ContentFetcher<F, R> {
fn drop(&mut self) {
// Clear cache path
let _ = fs::remove_dir_all(&self.dapps_path);
}
}
impl<R: URLHint + Send + Sync + 'static, F: Fetch> ContentFetcher<F, R> {
pub fn new(resolver: R, sync_status: Arc<SyncStatus>, embeddable_on: Option<(String, u16)>, remote: Remote, fetch: F) -> Self {
let mut dapps_path = env::temp_dir();
dapps_path.push(random_filename());
ContentFetcher {
dapps_path: dapps_path,
resolver: resolver,
sync: sync_status,
cache: Arc::new(Mutex::new(ContentCache::default())),
embeddable_on: embeddable_on,
remote: remote,
fetch: fetch,
}
}
fn still_syncing(address: Option<(String, u16)>) -> Box<Handler> {
Box::new(ContentHandler::error(
StatusCode::ServiceUnavailable,
"Sync In Progress",
"Your node is still syncing. We cannot resolve any content before it's fully synced.",
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>"),
address,
))
}
#[cfg(test)]
fn set_status(&self, content_id: &str, status: ContentStatus) {
self.cache.lock().insert(content_id.to_owned(), status);
}
}
impl<R: URLHint + Send + Sync + 'static, F: Fetch> Fetcher for ContentFetcher<F, R> {
fn contains(&self, content_id: &str) -> bool {
{
let mut cache = self.cache.lock();
// Check if we already have the app
if cache.get(content_id).is_some() {
return true;
}
}
// fallback to resolver
if let Ok(content_id) = content_id.from_hex() {
// else try to resolve the app_id
let has_content = self.resolver.resolve(content_id).is_some();
// if there is content or we are syncing return true
has_content || self.sync.is_major_importing()
} else {
false
}
}
fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box<Handler> {
let mut cache = self.cache.lock();
let content_id = path.app_id.clone();
let (new_status, handler) = {
let status = cache.get(&content_id);
match status {
// Just serve the content
Some(&mut ContentStatus::Ready(ref endpoint)) => {
(None, endpoint.to_async_handler(path, control))
},
// Content is already being fetched
Some(&mut ContentStatus::Fetching(ref fetch_control)) => {
trace!(target: "dapps", "Content fetching in progress. Waiting...");
(None, fetch_control.to_async_handler(path, control))
},
// We need to start fetching the content
None => {
trace!(target: "dapps", "Content unavailable. Fetching... {:?}", content_id);
let content_hex = content_id.from_hex().expect("to_handler is called only when `contains` returns true.");
let content = self.resolver.resolve(content_hex);
let cache = self.cache.clone();
let id = content_id.clone();
let on_done = move |result: Option<LocalPageEndpoint>| {
let mut cache = cache.lock();
match result {
Some(endpoint) => cache.insert(id.clone(), ContentStatus::Ready(endpoint)),
// In case of error
None => cache.remove(&id),
};
};
match content {
// Don't serve dapps if we are still syncing (but serve content)
Some(URLHintResult::Dapp(_)) if self.sync.is_major_importing() => {
(None, Self::still_syncing(self.embeddable_on.clone()))
},
Some(URLHintResult::Dapp(dapp)) => {
let (handler, fetch_control) = ContentFetcherHandler::new(
dapp.url(),
path,
control,
installers::Dapp::new(
content_id.clone(),
self.dapps_path.clone(),
Box::new(on_done),
self.embeddable_on.clone(),
),
self.embeddable_on.clone(),
self.remote.clone(),
self.fetch.clone(),
);
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
},
Some(URLHintResult::Content(content)) => {
let (handler, fetch_control) = ContentFetcherHandler::new(
content.url,
path,
control,
installers::Content::new(
content_id.clone(),
content.mime,
self.dapps_path.clone(),
Box::new(on_done),
),
self.embeddable_on.clone(),
self.remote.clone(),
self.fetch.clone(),
);
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
},
None if self.sync.is_major_importing() => {
(None, Self::still_syncing(self.embeddable_on.clone()))
},
None => {
// This may happen when sync status changes in between
// `contains` and `to_handler`
(None, Box::new(ContentHandler::error(
StatusCode::NotFound,
"Resource Not Found",
"Requested resource was not found.",
None,
self.embeddable_on.clone(),
)) as Box<Handler>)
},
}
},
}
};
if let Some(status) = new_status {
cache.clear_garbage(MAX_CACHED_DAPPS);
cache.insert(content_id, status);
}
handler
}
}
#[cfg(test)]
mod tests {
use std::env;
use std::sync::Arc;
use util::Bytes;
use fetch::Client;
use hash_fetch::urlhint::{URLHint, URLHintResult};
use parity_reactor::Remote;
use apps::cache::ContentStatus;
use endpoint::EndpointInfo;
use page::LocalPageEndpoint;
use super::{ContentFetcher, Fetcher};
struct FakeResolver;
impl URLHint for FakeResolver {
fn resolve(&self, _id: Bytes) -> Option<URLHintResult> {
None
}
}
#[test]
fn should_true_if_contains_the_app() {
// given
let path = env::temp_dir();
let fetcher = ContentFetcher::new(FakeResolver, Arc::new(|| false), None, Remote::new_sync(), Client::new().unwrap());
let handler = LocalPageEndpoint::new(path, EndpointInfo {
name: "fake".into(),
description: "".into(),
version: "".into(),
author: "".into(),
icon_url: "".into(),
}, Default::default(), None);
// when
fetcher.set_status("test", ContentStatus::Ready(handler));
fetcher.set_status("test2", ContentStatus::Fetching(Default::default()));
// then
assert_eq!(fetcher.contains("test"), true);
assert_eq!(fetcher.contains("test2"), true);
assert_eq!(fetcher.contains("test3"), false);
}
}

View File

@ -17,7 +17,10 @@
use endpoint::{Endpoints, Endpoint};
use page::PageEndpoint;
use proxypac::ProxyPac;
use web::Web;
use fetch::Fetch;
use parity_dapps::WebApp;
use parity_reactor::Remote;
mod cache;
mod fs;
@ -27,22 +30,24 @@ pub mod manifest;
extern crate parity_ui;
pub const HOME_PAGE: &'static str = "home";
pub const DAPPS_DOMAIN : &'static str = ".parity";
pub const RPC_PATH : &'static str = "rpc";
pub const API_PATH : &'static str = "api";
pub const UTILS_PATH : &'static str = "parity-utils";
pub const DAPPS_DOMAIN: &'static str = ".parity";
pub const RPC_PATH: &'static str = "rpc";
pub const API_PATH: &'static str = "api";
pub const UTILS_PATH: &'static str = "parity-utils";
pub const WEB_PATH: &'static str = "web";
pub fn utils() -> Box<Endpoint> {
Box::new(PageEndpoint::with_prefix(parity_ui::App::default(), UTILS_PATH.to_owned()))
}
pub fn all_endpoints(dapps_path: String, signer_address: Option<(String, u16)>) -> Endpoints {
pub fn all_endpoints<F: Fetch>(dapps_path: String, signer_address: Option<(String, u16)>, remote: Remote, fetch: F) -> Endpoints {
// fetch fs dapps at first to avoid overwriting builtins
let mut pages = fs::local_endpoints(dapps_path, signer_address.clone());
// NOTE [ToDr] Dapps will be currently embeded on 8180
insert::<parity_ui::App>(&mut pages, "ui", Embeddable::Yes(signer_address.clone()));
pages.insert("proxy".into(), ProxyPac::boxed(signer_address));
pages.insert(WEB_PATH.into(), Web::boxed(remote, fetch));
pages
}

View File

@ -16,13 +16,14 @@
//! Hyper Server Handler that fetches a file during a request (proxy).
use std::{fs, fmt};
use std::path::PathBuf;
use std::fmt;
use std::sync::{mpsc, Arc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Instant, Duration};
use fetch::{self, Fetch};
use futures::Future;
use parity_reactor::Remote;
use util::Mutex;
use fetch::{Client, Fetch, FetchResult};
use hyper::{server, Decoder, Encoder, Next, Method, Control};
use hyper::net::HttpStream;
@ -39,7 +40,7 @@ enum FetchState {
Waiting,
NotStarted(String),
Error(ContentHandler),
InProgress(mpsc::Receiver<FetchResult>),
InProgress(mpsc::Receiver<FetchState>),
Done(LocalPageEndpoint, Box<PageHandlerWaiting>),
}
@ -48,10 +49,10 @@ enum WaitResult {
Done(LocalPageEndpoint),
}
pub trait ContentValidator {
pub trait ContentValidator: Send + 'static {
type Error: fmt::Debug + fmt::Display;
fn validate_and_install(&self, path: PathBuf) -> Result<LocalPageEndpoint, Self::Error>;
fn validate_and_install(&self, fetch::Response) -> Result<LocalPageEndpoint, Self::Error>;
}
pub struct FetchControl {
@ -160,33 +161,36 @@ impl server::Handler<HttpStream> for WaitingHandler {
}
}
pub struct ContentFetcherHandler<H: ContentValidator> {
pub struct ContentFetcherHandler<H: ContentValidator, F: Fetch> {
fetch_control: Arc<FetchControl>,
control: Option<Control>,
control: Control,
remote: Remote,
status: FetchState,
client: Option<Client>,
installer: H,
fetch: F,
installer: Option<H>,
path: EndpointPath,
uri: RequestUri,
embeddable_on: Option<(String, u16)>,
}
impl<H: ContentValidator> ContentFetcherHandler<H> {
impl<H: ContentValidator, F: Fetch> ContentFetcherHandler<H, F> {
pub fn new(
url: String,
path: EndpointPath,
control: Control,
handler: H,
embeddable_on: Option<(String, u16)>,
remote: Remote,
fetch: F,
) -> (Self, Arc<FetchControl>) {
let fetch_control = Arc::new(FetchControl::default());
let client = Client::default();
let handler = ContentFetcherHandler {
fetch_control: fetch_control.clone(),
control: Some(control),
client: Some(client),
control: control,
remote: remote,
fetch: fetch,
status: FetchState::NotStarted(url),
installer: handler,
installer: Some(handler),
path: path,
uri: RequestUri::default(),
embeddable_on: embeddable_on,
@ -195,41 +199,74 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
(handler, fetch_control)
}
fn close_client(client: &mut Option<Client>) {
client.take()
.expect("After client is closed we are going into write, hence we can never close it again")
.close();
}
fn fetch_content(&self, url: &str, installer: H) -> mpsc::Receiver<FetchState> {
let (tx, rx) = mpsc::channel();
let abort = self.fetch_control.abort.clone();
fn fetch_content(client: &mut Client, url: &str, abort: Arc<AtomicBool>, control: Control) -> Result<mpsc::Receiver<FetchResult>, String> {
client.request(url, abort, Box::new(move || {
trace!(target: "dapps", "Fetching finished.");
let control = self.control.clone();
let embeddable_on = self.embeddable_on.clone();
let uri = self.uri.clone();
let path = self.path.clone();
let future = self.fetch.fetch_with_abort(url, abort.into()).then(move |result| {
trace!(target: "dapps", "Fetching content finished. Starting validation: {:?}", result);
let new_state = match result {
Ok(response) => match installer.validate_and_install(response) {
Ok(endpoint) => {
trace!(target: "dapps", "Validation OK. Returning response.");
let mut handler = endpoint.to_page_handler(path);
handler.set_uri(&uri);
FetchState::Done(endpoint, handler)
},
Err(e) => {
trace!(target: "dapps", "Error while validating content: {:?}", e);
FetchState::Error(ContentHandler::error(
StatusCode::BadGateway,
"Invalid Dapp",
"Downloaded bundle does not contain a valid content.",
Some(&format!("{:?}", e)),
embeddable_on,
))
},
},
Err(e) => {
warn!(target: "dapps", "Unable to fetch content: {:?}", e);
FetchState::Error(ContentHandler::error(
StatusCode::BadGateway,
"Download Error",
"There was an error when fetching the content.",
Some(&format!("{:?}", e)),
embeddable_on,
))
},
};
// Content may be resolved when the connection is already dropped.
let _ = tx.send(new_state);
// Ignoring control errors
let _ = control.ready(Next::read());
})).map_err(|e| format!("{:?}", e))
Ok(()) as Result<(), ()>
});
// make sure to run within fetch thread pool.
let future = self.fetch.process(future);
// spawn to event loop
self.remote.spawn(future);
rx
}
}
impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<H> {
impl<H: ContentValidator, F: Fetch> server::Handler<HttpStream> for ContentFetcherHandler<H, F> {
fn on_request(&mut self, request: server::Request<HttpStream>) -> Next {
self.uri = request.uri().clone();
let installer = self.installer.take().expect("Installer always set initialy; installer used only in on_request; on_request invoked only once; qed");
let status = if let FetchState::NotStarted(ref url) = self.status {
Some(match *request.method() {
// Start fetching content
Method::Get => {
trace!(target: "dapps", "Fetching content from: {:?}", url);
let control = self.control.take().expect("on_request is called only once, thus control is always Some");
let client = self.client.as_mut().expect("on_request is called before client is closed.");
let fetch = Self::fetch_content(client, url, self.fetch_control.abort.clone(), control);
match fetch {
Ok(receiver) => FetchState::InProgress(receiver),
Err(e) => FetchState::Error(ContentHandler::error(
StatusCode::BadGateway,
"Unable To Start Content Download",
"Could not initialize download of the content. It might be a problem with the remote server.",
Some(&format!("{}", e)),
self.embeddable_on.clone(),
)),
}
let receiver = self.fetch_content(url, installer);
FetchState::InProgress(receiver)
},
// or return error
_ => FetchState::Error(ContentHandler::error(
@ -246,7 +283,6 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
self.fetch_control.set_status(&status);
self.status = status;
}
self.uri = request.uri().clone();
Next::read()
}
@ -263,50 +299,14 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
None,
self.embeddable_on.clone(),
);
Self::close_client(&mut self.client);
(Some(FetchState::Error(timeout)), Next::write())
},
FetchState::InProgress(ref receiver) => {
// Check if there is an answer
let rec = receiver.try_recv();
match rec {
// Unpack and validate
Ok(Ok(path)) => {
trace!(target: "dapps", "Fetching content finished. Starting validation ({:?})", path);
Self::close_client(&mut self.client);
// Unpack and verify
let state = match self.installer.validate_and_install(path.clone()) {
Err(e) => {
trace!(target: "dapps", "Error while validating content: {:?}", e);
FetchState::Error(ContentHandler::error(
StatusCode::BadGateway,
"Invalid Dapp",
"Downloaded bundle does not contain a valid content.",
Some(&format!("{:?}", e)),
self.embeddable_on.clone(),
))
},
Ok(endpoint) => {
let mut handler = endpoint.to_page_handler(self.path.clone());
handler.set_uri(&self.uri);
FetchState::Done(endpoint, handler)
},
};
// Remove temporary zip file
let _ = fs::remove_file(path);
(Some(state), Next::write())
},
Ok(Err(e)) => {
warn!(target: "dapps", "Unable to fetch content: {:?}", e);
let error = ContentHandler::error(
StatusCode::BadGateway,
"Download Error",
"There was an error when fetching the content.",
Some(&format!("{:?}", e)),
self.embeddable_on.clone(),
);
(Some(FetchState::Error(error)), Next::write())
},
// just return the new state
Ok(state) => (Some(state), Next::write()),
// wait some more
_ => (None, Next::wait())
}

View File

@ -61,6 +61,9 @@ extern crate parity_hash_fetch as hash_fetch;
extern crate linked_hash_map;
extern crate fetch;
extern crate parity_dapps_glue as parity_dapps;
extern crate futures;
extern crate parity_reactor;
#[macro_use]
extern crate log;
#[macro_use]
@ -81,6 +84,7 @@ mod rpc;
mod api;
mod proxypac;
mod url;
mod web;
#[cfg(test)]
mod tests;
@ -89,9 +93,11 @@ use std::net::SocketAddr;
use std::collections::HashMap;
use hash_fetch::urlhint::ContractClient;
use fetch::{Fetch, Client as FetchClient};
use jsonrpc_core::{IoHandler, IoDelegate};
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
use ethcore_rpc::Extendable;
use parity_reactor::Remote;
use self::apps::{HOME_PAGE, DAPPS_DOMAIN};
@ -112,6 +118,8 @@ pub struct ServerBuilder {
registrar: Arc<ContractClient>,
sync_status: Arc<SyncStatus>,
signer_address: Option<(String, u16)>,
remote: Remote,
fetch: Option<FetchClient>,
}
impl Extendable for ServerBuilder {
@ -122,16 +130,23 @@ impl Extendable for ServerBuilder {
impl ServerBuilder {
/// Construct new dapps server
pub fn new(dapps_path: String, registrar: Arc<ContractClient>) -> Self {
pub fn new(dapps_path: String, registrar: Arc<ContractClient>, remote: Remote) -> Self {
ServerBuilder {
dapps_path: dapps_path,
handler: Arc::new(IoHandler::new()),
registrar: registrar,
sync_status: Arc::new(|| false),
signer_address: None,
remote: remote,
fetch: None,
}
}
/// Set a fetch client to use.
pub fn with_fetch(&mut self, fetch: FetchClient) {
self.fetch = Some(fetch);
}
/// Change default sync status.
pub fn with_sync_status(&mut self, status: Arc<SyncStatus>) {
self.sync_status = status;
@ -154,6 +169,8 @@ impl ServerBuilder {
self.signer_address.clone(),
self.registrar.clone(),
self.sync_status.clone(),
self.remote.clone(),
try!(self.fetch()),
)
}
@ -169,8 +186,17 @@ impl ServerBuilder {
self.signer_address.clone(),
self.registrar.clone(),
self.sync_status.clone(),
self.remote.clone(),
try!(self.fetch()),
)
}
fn fetch(&self) -> Result<FetchClient, ServerError> {
match self.fetch.clone() {
Some(fetch) => Ok(fetch),
None => FetchClient::new().map_err(|_| ServerError::FetchInitialization),
}
}
}
/// Webapps HTTP server.
@ -206,7 +232,7 @@ impl Server {
}
}
fn start_http<A: Authorization + 'static>(
fn start_http<A: Authorization + 'static, F: Fetch>(
addr: &SocketAddr,
hosts: Option<Vec<String>>,
authorization: A,
@ -215,11 +241,19 @@ impl Server {
signer_address: Option<(String, u16)>,
registrar: Arc<ContractClient>,
sync_status: Arc<SyncStatus>,
remote: Remote,
fetch: F,
) -> Result<Server, ServerError> {
let panic_handler = Arc::new(Mutex::new(None));
let authorization = Arc::new(authorization);
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(hash_fetch::urlhint::URLHintContract::new(registrar), sync_status, signer_address.clone()));
let endpoints = Arc::new(apps::all_endpoints(dapps_path, signer_address.clone()));
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
hash_fetch::urlhint::URLHintContract::new(registrar),
sync_status,
signer_address.clone(),
remote.clone(),
fetch.clone(),
));
let endpoints = Arc::new(apps::all_endpoints(dapps_path, signer_address.clone(), remote.clone(), fetch.clone()));
let cors_domains = Self::cors_domains(signer_address.clone());
let special = Arc::new({
@ -287,6 +321,8 @@ pub enum ServerError {
IoError(std::io::Error),
/// Other `hyper` error
Other(hyper::error::Error),
/// Fetch service initialization error
FetchInitialization,
}
impl From<hyper::error::Error> for ServerError {
@ -299,7 +335,7 @@ impl From<hyper::error::Error> for ServerError {
}
/// Random filename
pub fn random_filename() -> String {
fn random_filename() -> String {
use ::rand::Rng;
let mut rng = ::rand::OsRng::new().unwrap();
rng.gen_ascii_chars().take(12).collect()

View File

@ -20,11 +20,12 @@ use std::fs;
use std::path::{Path, PathBuf};
use page::handler::{self, PageCache, PageHandlerWaiting};
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
use mime::Mime;
#[derive(Debug, Clone)]
pub struct LocalPageEndpoint {
path: PathBuf,
mime: Option<String>,
mime: Option<Mime>,
info: Option<EndpointInfo>,
cache: PageCache,
embeddable_on: Option<(String, u16)>,
@ -41,7 +42,7 @@ impl LocalPageEndpoint {
}
}
pub fn single_file(path: PathBuf, mime: String, cache: PageCache) -> Self {
pub fn single_file(path: PathBuf, mime: Mime, cache: PageCache) -> Self {
LocalPageEndpoint {
path: path,
mime: Some(mime),
@ -55,9 +56,9 @@ impl LocalPageEndpoint {
self.path.clone()
}
fn page_handler_with_mime(&self, path: EndpointPath, mime: &str) -> handler::PageHandler<LocalSingleFile> {
fn page_handler_with_mime(&self, path: EndpointPath, mime: &Mime) -> handler::PageHandler<LocalSingleFile> {
handler::PageHandler {
app: LocalSingleFile { path: self.path.clone(), mime: mime.into() },
app: LocalSingleFile { path: self.path.clone(), mime: format!("{}", mime) },
prefix: None,
path: path,
file: handler::ServedFile::new(None),

View File

@ -27,7 +27,7 @@ use url::{Url, Host};
use hyper::{self, server, Next, Encoder, Decoder, Control, StatusCode};
use hyper::net::HttpStream;
use apps::{self, DAPPS_DOMAIN};
use apps::fetcher::ContentFetcher;
use apps::fetcher::Fetcher;
use endpoint::{Endpoint, Endpoints, EndpointPath};
use handlers::{Redirection, extract_url, ContentHandler};
use self::auth::{Authorization, Authorized};
@ -45,7 +45,7 @@ pub struct Router<A: Authorization + 'static> {
control: Option<Control>,
signer_address: Option<(String, u16)>,
endpoints: Arc<Endpoints>,
fetch: Arc<ContentFetcher>,
fetch: Arc<Fetcher>,
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
authorization: Arc<A>,
allowed_hosts: Option<Vec<String>>,
@ -169,7 +169,7 @@ impl<A: Authorization> Router<A> {
pub fn new(
control: Control,
signer_address: Option<(String, u16)>,
content_fetcher: Arc<ContentFetcher>,
content_fetcher: Arc<Fetcher>,
endpoints: Arc<Endpoints>,
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
authorization: Arc<A>,

View File

@ -25,6 +25,7 @@ use Server;
use hash_fetch::urlhint::ContractClient;
use util::{Bytes, Address, Mutex, ToPretty};
use devtools::http_client;
use parity_reactor::Remote;
const REGISTRAR: &'static str = "8e4e9b13d4b45cb0befc93c3061b1408f67316b2";
const URLHINT: &'static str = "deadbeefcafe0000000000000000000000000000";
@ -74,7 +75,7 @@ pub fn init_server(hosts: Option<Vec<String>>, is_syncing: bool) -> (Server, Arc
let registrar = Arc::new(FakeRegistrar::new());
let mut dapps_path = env::temp_dir();
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar.clone());
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar.clone(), Remote::new_sync());
builder.with_sync_status(Arc::new(move || is_syncing));
builder.with_signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)));
(
@ -88,7 +89,7 @@ pub fn serve_with_auth(user: &str, pass: &str) -> Server {
let registrar = Arc::new(FakeRegistrar::new());
let mut dapps_path = env::temp_dir();
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar);
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar.clone(), Remote::new_sync());
builder.with_signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)));
builder.start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), None, user, pass).unwrap()
}

180
dapps/src/web.rs Normal file
View File

@ -0,0 +1,180 @@
// Copyright 2015, 2016 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 <http://www.gnu.org/licenses/>.
//! Serving web-based content (proxying)
use endpoint::{Endpoint, Handler, EndpointPath};
use handlers::{ContentFetcherHandler, ContentHandler, ContentValidator, Redirection, extract_url};
use page::{LocalPageEndpoint};
use fetch::{self, Fetch};
use url::Url;
use hyper::{self, server, net, Next, Encoder, Decoder};
use hyper::status::StatusCode;
use parity_reactor::Remote;
use apps::WEB_PATH;
pub struct Web<F> {
remote: Remote,
fetch: F,
}
impl<F: Fetch> Web<F> {
pub fn boxed(remote: Remote, fetch: F) -> Box<Endpoint> {
Box::new(Web {
remote: remote,
fetch: fetch,
})
}
}
impl<F: Fetch> Endpoint for Web<F> {
fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box<Handler> {
Box::new(WebHandler {
control: control,
state: State::Initial,
path: path,
remote: self.remote.clone(),
fetch: self.fetch.clone(),
})
}
}
pub struct WebInstaller;
impl ContentValidator for WebInstaller {
type Error = String;
fn validate_and_install(&self, _response: fetch::Response) -> Result<LocalPageEndpoint, String> {
// let path = unimplemented!();
// let mime = response.content_type().unwrap_or(mime!(Text/Html));
// Ok(LocalPageEndpoint::single_file(path, mime, PageCache::Enabled))
Err("unimplemented".into())
}
}
enum State<F: Fetch> {
Initial,
Error(ContentHandler),
Redirecting(Redirection),
Fetching(ContentFetcherHandler<WebInstaller, F>),
}
struct WebHandler<F: Fetch> {
control: hyper::Control,
state: State<F>,
path: EndpointPath,
remote: Remote,
fetch: F,
}
impl<F: Fetch> WebHandler<F> {
fn extract_target_url(url: Option<Url>) -> Result<String, State<F>> {
let path = match url {
Some(url) => url.path,
None => {
return Err(State::Error(
ContentHandler::error(StatusCode::BadRequest, "Invalid URL", "Couldn't parse URL", None, None)
));
}
};
// TODO [ToDr] Check if token supplied in URL is correct.
// Support domain based routing.
let idx = match path.get(0).map(|m| m.as_ref()) {
Some(WEB_PATH) => 1,
_ => 0,
};
// Validate protocol
let protocol = match path.get(idx).map(|a| a.as_str()) {
Some("http") => "http",
Some("https") => "https",
_ => {
return Err(State::Error(
ContentHandler::error(StatusCode::BadRequest, "Invalid Protocol", "Invalid protocol used", None, None)
));
}
};
// Redirect if address to main page does not end with /
if let None = path.get(idx + 2) {
return Err(State::Redirecting(
Redirection::new(&format!("/{}/", path.join("/")))
));
}
Ok(format!("{}://{}", protocol, path[2..].join("/")))
}
}
impl<F: Fetch> server::Handler<net::HttpStream> for WebHandler<F> {
fn on_request(&mut self, request: server::Request<net::HttpStream>) -> Next {
let url = extract_url(&request);
// First extract the URL (reject invalid URLs)
let target_url = match Self::extract_target_url(url) {
Ok(url) => url,
Err(error) => {
self.state = error;
return Next::write();
}
};
let (mut handler, _control) = ContentFetcherHandler::new(
target_url,
self.path.clone(),
self.control.clone(),
WebInstaller,
None,
self.remote.clone(),
self.fetch.clone(),
);
let res = handler.on_request(request);
self.state = State::Fetching(handler);
res
}
fn on_request_readable(&mut self, decoder: &mut Decoder<net::HttpStream>) -> Next {
match self.state {
State::Initial => Next::end(),
State::Error(ref mut handler) => handler.on_request_readable(decoder),
State::Redirecting(ref mut handler) => handler.on_request_readable(decoder),
State::Fetching(ref mut handler) => handler.on_request_readable(decoder),
}
}
fn on_response(&mut self, res: &mut server::Response) -> Next {
match self.state {
State::Initial => Next::end(),
State::Error(ref mut handler) => handler.on_response(res),
State::Redirecting(ref mut handler) => handler.on_response(res),
State::Fetching(ref mut handler) => handler.on_response(res),
}
}
fn on_response_writable(&mut self, encoder: &mut Encoder<net::HttpStream>) -> Next {
match self.state {
State::Initial => Next::end(),
State::Error(ref mut handler) => handler.on_response_writable(encoder),
State::Redirecting(ref mut handler) => handler.on_response_writable(encoder),
State::Fetching(ref mut handler) => handler.on_response_writable(encoder),
}
}
}

View File

@ -20,7 +20,7 @@ use util::H256;
/// Either a hash or a number.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub enum HashOrNumber {
/// Block hash variant.
Hash(H256),
@ -42,7 +42,7 @@ impl From<u64> for HashOrNumber {
/// A request for block headers.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct Headers {
/// Starting block number or hash.
pub start: HashOrNumber,
@ -56,7 +56,7 @@ pub struct Headers {
/// A request for specific block bodies.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct Bodies {
/// Hashes which bodies are being requested for.
pub block_hashes: Vec<H256>
@ -67,7 +67,7 @@ pub struct Bodies {
/// This request is answered with a list of transaction receipts for each block
/// requested.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct Receipts {
/// Block hashes to return receipts for.
pub block_hashes: Vec<H256>,
@ -75,7 +75,7 @@ pub struct Receipts {
/// A request for a state proof
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct StateProof {
/// Block hash to query state from.
pub block: H256,
@ -90,7 +90,7 @@ pub struct StateProof {
/// A request for state proofs.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct StateProofs {
/// All the proof requests.
pub requests: Vec<StateProof>,
@ -98,7 +98,7 @@ pub struct StateProofs {
/// A request for contract code.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct ContractCode {
/// Block hash
pub block_hash: H256,
@ -108,7 +108,7 @@ pub struct ContractCode {
/// A request for contract code.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct ContractCodes {
/// Block hash and account key (== sha3(address)) pairs to fetch code for.
pub code_requests: Vec<ContractCode>,
@ -116,7 +116,7 @@ pub struct ContractCodes {
/// A request for a header proof from the Canonical Hash Trie.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct HeaderProof {
/// Number of the CHT.
pub cht_number: u64,
@ -128,7 +128,7 @@ pub struct HeaderProof {
/// A request for header proofs from the CHT.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub struct HeaderProofs {
/// All the proof requests.
pub requests: Vec<HeaderProof>,
@ -136,7 +136,7 @@ pub struct HeaderProofs {
/// Kinds of requests.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub enum Kind {
/// Requesting headers.
Headers,
@ -154,7 +154,7 @@ pub enum Kind {
/// Encompasses all possible types of requests in a single structure.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", derive(Binary))]
#[cfg_attr(feature = "ipc", binary)]
pub enum Request {
/// Requesting headers.
Headers(Headers),

View File

@ -17,7 +17,6 @@
//! Types used in the public (IPC) api which require custom code generation.
#![cfg_attr(feature = "ipc", allow(dead_code, unused_assignments, unused_variables))] // codegen issues
#[cfg(feature = "ipc")]
include!(concat!(env!("OUT_DIR"), "/mod.rs.in"));

View File

@ -27,6 +27,7 @@
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x1",
"chainID": "0x3d",
"forkBlock": "0x1d4c00",
"forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f"
},

View File

@ -27,6 +27,7 @@
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2",
"chainID": "0x3e",
"forkBlock": "0x1b34d8",
"forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145"
},

View File

@ -167,7 +167,7 @@ impl Engine for Ethash {
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u64> {
if env_info.number >= self.ethash_params.eip155_transition {
Some(self.params().network_id)
Some(self.params().chain_id)
} else {
None
}
@ -316,7 +316,7 @@ impl Engine for Ethash {
}
if let Some(n) = t.network_id() {
if header.number() < self.ethash_params.eip155_transition || n != self.params().network_id {
if header.number() < self.ethash_params.eip155_transition || n != self.params().chain_id {
return Err(TransactionError::InvalidNetworkId.into())
}
}

View File

@ -38,6 +38,8 @@ pub struct CommonParams {
pub maximum_extra_data_size: usize,
/// Network id.
pub network_id: u64,
/// Chain id.
pub chain_id: u64,
/// Main subprotocol name.
pub subprotocol_name: String,
/// Minimum gas limit.
@ -52,6 +54,7 @@ impl From<ethjson::spec::Params> for CommonParams {
account_start_nonce: p.account_start_nonce.into(),
maximum_extra_data_size: p.maximum_extra_data_size.into(),
network_id: p.network_id.into(),
chain_id: if let Some(n) = p.chain_id { n.into() } else { p.network_id.into() },
subprotocol_name: p.subprotocol_name.unwrap_or_else(|| "eth".to_owned()),
min_gas_limit: p.min_gas_limit.into(),
fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },

View File

@ -22,7 +22,8 @@ use std::collections::BTreeMap;
use util::{U256, H256, Uint, Bytes};
use ipc::binary::BinaryConvertable;
#[derive(Debug, PartialEq, Eq, Clone, Binary)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
/// Diff type for specifying a change (or not).
pub enum Diff<T> where T: Eq + BinaryConvertable {
/// Both sides are the same.
@ -49,7 +50,8 @@ impl<T> Diff<T> where T: Eq + BinaryConvertable {
pub fn is_same(&self) -> bool { match *self { Diff::Same => true, _ => false }}
}
#[derive(Debug, PartialEq, Eq, Clone, Binary)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
/// Account diff.
pub struct AccountDiff {
/// Change in balance, allowed to be `Diff::Same`.
@ -62,7 +64,8 @@ pub struct AccountDiff {
pub storage: BTreeMap<H256, Diff<H256>>,
}
#[derive(Debug, PartialEq, Eq, Clone, Binary)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
/// Change in existance type.
// TODO: include other types of change.
pub enum Existance {

View File

@ -20,7 +20,8 @@ use error::{ImportError, BlockError, Error};
use std::convert::From;
/// Error dedicated to import block function
#[derive(Binary, Debug)]
#[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub enum BlockImportError {
/// Import error
Import(ImportError),

View File

@ -18,7 +18,8 @@
use verification::queue::Status as QueueStatus;
/// General block status
#[derive(Debug, Eq, PartialEq, Binary)]
#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum BlockStatus {
/// Part of the blockchain.
InChain,

View File

@ -21,7 +21,8 @@ use header::BlockNumber;
use types::security_level::SecurityLevel;
/// Information about the blockchain gathered together.
#[derive(Clone, Debug, Binary)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct BlockChainInfo {
/// Blockchain difficulty.
pub total_difficulty: U256,

View File

@ -17,7 +17,8 @@
//! Call analytics related types
/// Options concerning what analytics we run on the call.
#[derive(Eq, PartialEq, Default, Clone, Copy, Debug, Binary)]
#[derive(Eq, PartialEq, Default, Clone, Copy, Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CallAnalytics {
/// Make a transaction trace.
pub transaction_tracing: bool,

View File

@ -24,7 +24,8 @@ use types::state_diff::StateDiff;
use std::fmt;
/// The type of the call-like instruction.
#[derive(Debug, PartialEq, Clone, Binary)]
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum CallType {
/// Not a CALL.
None,
@ -61,7 +62,8 @@ impl Decodable for CallType {
}
/// Transaction execution receipt.
#[derive(Debug, PartialEq, Clone, Binary)]
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Executed {
/// Gas paid up front for execution of transaction.
pub gas: U256,
@ -101,7 +103,8 @@ pub struct Executed {
}
/// Result of executing the transaction.
#[derive(PartialEq, Debug, Clone, Binary)]
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum ExecutionError {
/// Returned when there gas paid for transaction execution is
/// lower than base gas required.
@ -168,7 +171,8 @@ impl fmt::Display for ExecutionError {
}
/// Result of executing the transaction.
#[derive(PartialEq, Debug, Clone, Binary)]
#[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum CallError {
/// Couldn't find the transaction in the chain.
TransactionNotFound,

View File

@ -22,7 +22,8 @@ use client::BlockId;
use log_entry::LogEntry;
/// Blockchain Filter.
#[derive(Binary, Debug, PartialEq)]
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Filter {
/// Blockchain will be searched from this block.
pub from_block: BlockId,

View File

@ -20,7 +20,8 @@ use util::hash::H256;
use header::BlockNumber;
/// Uniquely identifies block.
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq, Binary)]
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum BlockId {
/// Block's sha3.
/// Querying by hash is always faster.
@ -36,7 +37,8 @@ pub enum BlockId {
}
/// Uniquely identifies transaction.
#[derive(Debug, PartialEq, Clone, Hash, Eq, Binary)]
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum TransactionId {
/// Transaction's sha3.
Hash(H256),
@ -46,7 +48,7 @@ pub enum TransactionId {
}
/// Uniquely identifies Trace.
#[derive(Binary)]
#[cfg_attr(feature = "ipc", binary)]
pub struct TraceId {
/// Transaction
pub transaction: TransactionId,
@ -55,7 +57,8 @@ pub struct TraceId {
}
/// Uniquely identifies Uncle.
#[derive(Debug, PartialEq, Eq, Copy, Clone, Binary)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct UncleId {
/// Block id.
pub block: BlockId,

View File

@ -26,7 +26,8 @@ use header::BlockNumber;
use ethjson;
/// A record of execution for a `LOG` operation.
#[derive(Default, Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LogEntry {
/// The address of the contract executing at the point of the `LOG` operation.
pub address: Address,
@ -81,7 +82,8 @@ impl From<ethjson::state::Log> for LogEntry {
}
/// Log localized in a blockchain.
#[derive(Default, Debug, PartialEq, Clone, Binary)]
#[derive(Default, Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedLogEntry {
/// Plain log entry.
pub entry: LogEntry,

View File

@ -16,5 +16,10 @@
//! Types used in the public api
#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues
#![cfg_attr(feature = "ipc", allow(dead_code, unused_assignments, unused_variables))] // codegen issues
#[cfg(feature = "ipc")]
include!(concat!(env!("OUT_DIR"), "/mod.rs.in"));
#[cfg(not(feature = "ipc"))]
include!("mod.rs.in");

View File

@ -20,7 +20,8 @@ pub use std::time::Duration;
use client::Mode as ClientMode;
/// IPC-capable shadow-type for `client::config::Mode`
#[derive(Clone, Binary, Debug)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub enum Mode {
/// Same as `ClientMode::Off`.
Off,

View File

@ -21,7 +21,8 @@
//! of which portions of the ancient chain and current state trie are stored as well.
/// Client pruning info. See module-level docs for more details.
#[derive(Debug, Clone, Binary)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct PruningInfo {
/// The first block which everything can be served after.
pub earliest_chain: u64,

View File

@ -25,7 +25,8 @@ use header::BlockNumber;
use log_entry::{LogEntry, LocalizedLogEntry};
/// Information describing execution of a transaction.
#[derive(Default, Debug, Clone, Binary)]
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Receipt {
/// The state root after executing the transaction.
pub state_root: H256,
@ -79,7 +80,8 @@ impl HeapSizeOf for Receipt {
}
/// Receipt with additional info.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct RichReceipt {
/// Transaction hash.
pub transaction_hash: H256,
@ -100,7 +102,8 @@ pub struct RichReceipt {
}
/// Receipt with additional info.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedReceipt {
/// Transaction hash.
pub transaction_hash: H256,

View File

@ -17,7 +17,8 @@
//! Restoration status type definition
/// Statuses for restorations.
#[derive(PartialEq, Eq, Clone, Copy, Debug, Binary)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub enum RestorationStatus {
/// No restoration.
Inactive,

View File

@ -19,7 +19,8 @@
use header::BlockNumber;
/// Indication of how secure the chain is.
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq, Binary)]
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum SecurityLevel {
/// All blocks from genesis to chain head are known to have valid state transitions and PoW.
FullState,

View File

@ -21,7 +21,8 @@ use rlp::*;
use util::Bytes;
/// Manifest data.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct ManifestData {
/// List of state chunk hashes.
pub state_hashes: Vec<H256>,

View File

@ -22,7 +22,8 @@ use std::collections::BTreeMap;
use util::Address;
use account_diff::*;
#[derive(Debug, PartialEq, Eq, Clone, Binary)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
/// Expression for the delta between two system states. Encoded the
/// delta of every altered account.
pub struct StateDiff {

View File

@ -21,7 +21,7 @@ use util::{Address};
use types::ids::BlockId;
/// Easy to use trace filter.
#[derive(Binary)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Filter {
/// Range of filtering.
pub range: Range<BlockId>,

View File

@ -21,7 +21,8 @@ use rlp::{Encodable, RlpStream, Decodable, Decoder, DecoderError, Stream, View};
use evm::Error as EvmError;
/// Trace evm errors.
#[derive(Debug, PartialEq, Clone, Binary)]
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum Error {
/// `OutOfGas` is returned when transaction execution runs out of gas.
OutOfGas,

View File

@ -28,7 +28,8 @@ use types::trace_types::trace::{Action, Res};
/// Addresses filter.
///
/// Used to create bloom possibilities and match filters.
#[derive(Debug, Binary)]
#[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct AddressesFilter {
list: Vec<Address>
}
@ -74,7 +75,8 @@ impl AddressesFilter {
}
}
#[derive(Debug, Binary)]
#[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
/// Traces filter.
pub struct Filter {
/// Block range.

View File

@ -25,7 +25,8 @@ use super::trace::{Action, Res};
/// Trace localized in vector of traces produced by a single transaction.
///
/// Parent and children indexes refer to positions in this vector.
#[derive(Debug, PartialEq, Clone, Binary)]
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct FlatTrace {
/// Type of action performed by a transaction.
pub action: Action,

View File

@ -21,7 +21,8 @@ use super::trace::{Action, Res};
use header::BlockNumber;
/// Localized trace.
#[derive(Debug, PartialEq, Clone, Binary)]
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedTrace {
/// Type of action performed by a transaction.
pub action: Action,

View File

@ -27,7 +27,8 @@ use types::executed::CallType;
use super::error::Error;
/// `Call` result.
#[derive(Debug, Clone, PartialEq, Default, Binary)]
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CallResult {
/// Gas used by call.
pub gas_used: U256,
@ -56,7 +57,8 @@ impl Decodable for CallResult {
}
/// `Create` result.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CreateResult {
/// Gas used by create.
pub gas_used: U256,
@ -96,7 +98,8 @@ impl CreateResult {
}
/// Description of a _call_ action, either a `CALL` operation or a message transction.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Call {
/// The sending account.
pub from: Address,
@ -163,7 +166,8 @@ impl Call {
}
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Create {
/// The address of the creator.
pub from: Address,
@ -219,7 +223,8 @@ impl Create {
}
/// Suicide action.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Suicide {
/// Suicided address.
pub address: Address,
@ -261,7 +266,8 @@ impl Decodable for Suicide {
/// Description of an action that we trace; will be either a call or a create.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum Action {
/// It's a call action.
Call(Call),
@ -316,7 +322,8 @@ impl Action {
}
/// The result of the performed action.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum Res {
/// Successful call action result.
Call(CallResult),
@ -386,7 +393,8 @@ impl Res {
}
}
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
/// A diff of some chunk of memory.
pub struct MemoryDiff {
/// Offset into memory the change begins.
@ -413,7 +421,8 @@ impl Decodable for MemoryDiff {
}
}
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
/// A diff of some storage value.
pub struct StorageDiff {
/// Which key in storage is changed.
@ -440,7 +449,8 @@ impl Decodable for StorageDiff {
}
}
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of an executed VM operation.
pub struct VMExecutedOperation {
/// The total gas used.
@ -475,7 +485,8 @@ impl Decodable for VMExecutedOperation {
}
}
#[derive(Debug, Clone, PartialEq, Binary, Default)]
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of the execution of a single VM operation.
pub struct VMOperation {
/// The program counter.
@ -512,7 +523,8 @@ impl Decodable for VMOperation {
}
}
#[derive(Debug, Clone, PartialEq, Binary, Default)]
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of a full VM trace for a CALL/CREATE.
pub struct VMTrace {
/// The step (i.e. index into operations) at which this trace corresponds.

View File

@ -27,7 +27,8 @@ use evm::Schedule;
use header::BlockNumber;
use ethjson;
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
/// Transaction action type.
pub enum Action {
/// Create creates new contract.
@ -54,7 +55,8 @@ impl Decodable for Action {
/// A set of information describing an externally-originating message call
/// or contract creation operation.
#[derive(Default, Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Transaction {
/// Nonce.
pub nonce: U256,
@ -205,7 +207,8 @@ impl Transaction {
}
/// Signed transaction information.
#[derive(Debug, Clone, Eq, Binary)]
#[derive(Debug, Clone, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct SignedTransaction {
/// Plain Transaction.
unsigned: Transaction,
@ -370,7 +373,8 @@ impl SignedTransaction {
}
/// Signed Transaction that is a part of canon blockchain.
#[derive(Debug, PartialEq, Eq, Binary)]
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedTransaction {
/// Signed part.
pub signed: SignedTransaction,
@ -391,7 +395,8 @@ impl Deref for LocalizedTransaction {
}
/// Queued transaction with additional information.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct PendingTransaction {
/// Signed transaction data.
pub transaction: SignedTransaction,
@ -495,14 +500,14 @@ fn should_agree_with_vitalik() {
flushln!("networkid: {:?}", signed.network_id());
};
test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce")
test_vector("f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0x23ef145a395ea3fa3deb533b8a9e1b4c6c25d112")
test_vector("f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2e485e0c23b4c3c542628a5f672eeab0ad4888be")
test_vector("f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0x82a88539669a3fd524d669e858935de5e5410cf0")
test_vector("f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf9358f2538fd5ccfeb848b64a96b743fcc930554")
test_vector("f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xa8f7aba377317440bc5b26198a363ad22af1f3a4")
test_vector("f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xf1f571dc362a0e5b2696b8e775f8491d3e50de35")
test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332")
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029")
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f")
test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce");
test_vector("f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0x23ef145a395ea3fa3deb533b8a9e1b4c6c25d112");
test_vector("f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2e485e0c23b4c3c542628a5f672eeab0ad4888be");
test_vector("f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0x82a88539669a3fd524d669e858935de5e5410cf0");
test_vector("f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf9358f2538fd5ccfeb848b64a96b743fcc930554");
test_vector("f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xa8f7aba377317440bc5b26198a363ad22af1f3a4");
test_vector("f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xf1f571dc362a0e5b2696b8e775f8491d3e50de35");
test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332");
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029");
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f");
}

View File

@ -31,7 +31,8 @@ pub enum TransactionImportResult {
binary_fixed_size!(TransactionImportResult);
/// Api-level error for transaction import
#[derive(Debug, Clone, Binary)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum TransactionImportError {
/// Transaction error
Transaction(TransactionError),

View File

@ -19,7 +19,8 @@
use util::H256;
/// Represents a tree route between `from` block and `to` block:
#[derive(Debug, Binary)]
#[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct TreeRoute {
/// A vector of hashes of all blocks, ordered from `from` to `to`.
pub blocks: Vec<H256>,

View File

@ -17,7 +17,8 @@
//! Verification queue info types
/// Verification queue status
#[derive(Debug, Binary)]
#[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct VerificationQueueInfo {
/// Number of queued items pending verification
pub unverified_queue_size: usize,

View File

@ -5,6 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
[dependencies]
log = "0.3"
libc = "0.2.11"
rand = "0.3.14"
ethkey = { path = "../ethkey" }

View File

@ -22,7 +22,7 @@ use {json, SafeAccount, Error};
use json::Uuid;
use super::KeyDirectory;
const IGNORED_FILES: &'static [&'static str] = &["thumbs.db", "address_book.json"];
const IGNORED_FILES: &'static [&'static str] = &["thumbs.db", "address_book.json", "dapps_policy.json"];
#[cfg(not(windows))]
fn restrict_permissions_to_owner(file_path: &Path) -> Result<(), i32> {
@ -78,7 +78,7 @@ impl DiskDirectory {
.map(|entry| entry.path())
.collect::<Vec<PathBuf>>();
paths
Ok(paths
.iter()
.map(|p| (
fs::File::open(p)
@ -86,13 +86,17 @@ impl DiskDirectory {
.and_then(|r| json::KeyFile::load(r).map_err(|e| Error::Custom(format!("{:?}", e)))),
p
))
.map(|(file, path)| match file {
Ok(file) => Ok((path.clone(), SafeAccount::from_file(
.filter_map(|(file, path)| match file {
Ok(file) => Some((path.clone(), SafeAccount::from_file(
file, Some(path.file_name().and_then(|n| n.to_str()).expect("Keys have valid UTF8 names only.").to_owned())
))),
Err(err) => Err(Error::InvalidKeyFile(format!("{:?}: {}", path, err))),
Err(err) => {
warn!("Invalid key file: {:?} ({})", path, err);
None
},
})
.collect()
)
}
}

View File

@ -32,6 +32,9 @@ extern crate parking_lot;
extern crate ethkey as _ethkey;
extern crate ethcrypto as crypto;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;

View File

@ -7,9 +7,13 @@ version = "1.5.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
log = "0.3"
rustc-serialize = "0.3"
ethabi = "0.2.2"
futures = "0.1"
log = "0.3"
mime = "0.2"
mime_guess = "1.6.1"
rand = "0.3"
rustc-serialize = "0.3"
fetch = { path = "../util/fetch" }
ethcore-util = { path = "../util" }
parity-reactor = { path = "../util/reactor" }

View File

@ -17,13 +17,15 @@
//! Hash-addressed content resolver & fetcher.
use std::{io, fs};
use std::io::Write;
use std::sync::Arc;
use std::path::PathBuf;
use util::{Mutex, H256, sha3};
use fetch::{Fetch, FetchError, Client as FetchClient};
use fetch::{Fetch, Response, Error as FetchError, Client as FetchClient};
use futures::Future;
use parity_reactor::Remote;
use urlhint::{ContractClient, URLHintContract, URLHint, URLHintResult};
use util::{H256, sha3};
/// API for fetching by hash.
pub trait HashFetch: Send + Sync + 'static {
@ -33,7 +35,7 @@ pub trait HashFetch: Send + Sync + 'static {
/// 2. `on_done` - callback function invoked when the content is ready (or there was error during fetch)
///
/// This function may fail immediately when fetch cannot be initialized or content cannot be resolved.
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>) -> Result<(), Error>;
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>);
}
/// Hash-fetching error.
@ -67,53 +69,94 @@ impl From<io::Error> for Error {
}
/// Default Hash-fetching client using on-chain contract to resolve hashes to URLs.
pub struct Client {
pub struct Client<F: Fetch + 'static = FetchClient> {
contract: URLHintContract,
fetch: Mutex<FetchClient>,
fetch: F,
remote: Remote,
}
impl Client {
/// Creates new instance of the `Client` given on-chain contract client.
pub fn new(contract: Arc<ContractClient>) -> Self {
/// Creates new instance of the `Client` given on-chain contract client and task runner.
pub fn new(contract: Arc<ContractClient>, remote: Remote) -> Self {
Client::with_fetch(contract, FetchClient::new().unwrap(), remote)
}
}
impl<F: Fetch + 'static> Client<F> {
/// Creates new instance of the `Client` given on-chain contract client, fetch service and task runner.
pub fn with_fetch(contract: Arc<ContractClient>, fetch: F, remote: Remote) -> Self {
Client {
contract: URLHintContract::new(contract),
fetch: Mutex::new(FetchClient::default()),
fetch: fetch,
remote: remote,
}
}
}
impl HashFetch for Client {
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>) -> Result<(), Error> {
impl<F: Fetch + 'static> HashFetch for Client<F> {
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>) {
debug!(target: "fetch", "Fetching: {:?}", hash);
let url = try!(
self.contract.resolve(hash.to_vec()).map(|content| match content {
let url = self.contract.resolve(hash.to_vec()).map(|content| match content {
URLHintResult::Dapp(dapp) => {
dapp.url()
},
URLHintResult::Content(content) => {
content.url
},
}).ok_or_else(|| Error::NoResolution)
);
}).ok_or_else(|| Error::NoResolution);
debug!(target: "fetch", "Resolved {:?} to {:?}. Fetching...", hash, url);
self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
fn validate_hash(hash: H256, result: Result<PathBuf, FetchError>) -> Result<PathBuf, Error> {
let path = try!(result);
let mut file_reader = io::BufReader::new(try!(fs::File::open(&path)));
let content_hash = try!(sha3(&mut file_reader));
match url {
Err(err) => on_done(Err(err)),
Ok(url) => {
let future = self.fetch.fetch(&url).then(move |result| {
fn validate_hash(path: PathBuf, hash: H256, result: Result<Response, FetchError>) -> Result<PathBuf, Error> {
let response = try!(result);
// Read the response
let mut reader = io::BufReader::new(response);
let mut writer = io::BufWriter::new(try!(fs::File::create(&path)));
try!(io::copy(&mut reader, &mut writer));
try!(writer.flush());
if content_hash != hash {
Err(Error::HashMismatch{ got: content_hash, expected: hash })
} else {
Ok(path)
}
}
// And validate the hash
let mut file_reader = io::BufReader::new(try!(fs::File::open(&path)));
let content_hash = try!(sha3(&mut file_reader));
if content_hash != hash {
Err(Error::HashMismatch{ got: content_hash, expected: hash })
} else {
Ok(path)
}
}
debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash);
on_done(validate_hash(hash, result))
})).map_err(Into::into)
debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash);
let path = random_temp_path();
let res = validate_hash(path.clone(), hash, result);
if let Err(ref err) = res {
trace!(target: "fetch", "Error: {:?}", err);
// Remove temporary file in case of error
let _ = fs::remove_dir_all(&path);
}
on_done(res);
Ok(()) as Result<(), ()>
});
self.remote.spawn(self.fetch.process(future));
},
}
}
}
fn random_temp_path() -> PathBuf {
use ::rand::Rng;
use ::std::env;
let mut rng = ::rand::OsRng::new().expect("Reliable random source is required to work.");
let file: String = rng.gen_ascii_chars().take(12).collect();
let mut path = env::temp_dir();
path.push(file);
path
}

View File

@ -20,11 +20,17 @@
#[macro_use]
extern crate log;
extern crate rustc_serialize;
extern crate mime_guess;
#[macro_use]
extern crate mime;
extern crate ethabi;
extern crate ethcore_util as util;
extern crate fetch;
pub extern crate fetch;
extern crate futures;
extern crate mime_guess;
extern crate rand;
extern crate rustc_serialize;
extern crate parity_reactor;
mod client;

View File

@ -19,6 +19,7 @@
use std::fmt;
use std::sync::Arc;
use rustc_serialize::hex::ToHex;
use mime::Mime;
use mime_guess;
use ethabi::{Interface, Contract, Token};
@ -76,7 +77,7 @@ pub struct Content {
/// URL of the content
pub url: String,
/// MIME type of the content
pub mime: String,
pub mime: Mime,
/// Content owner address
pub owner: Address,
}
@ -183,7 +184,7 @@ impl URLHintContract {
let commit = GithubApp::commit(&commit);
if commit == Some(Default::default()) {
let mime = guess_mime_type(&account_slash_repo).unwrap_or("application/octet-stream".into());
let mime = guess_mime_type(&account_slash_repo).unwrap_or(mime!(Application/_));
return Some(URLHintResult::Content(Content {
url: account_slash_repo,
mime: mime,
@ -235,7 +236,7 @@ impl URLHint for URLHintContract {
}
}
fn guess_mime_type(url: &str) -> Option<String> {
fn guess_mime_type(url: &str) -> Option<Mime> {
const CONTENT_TYPE: &'static str = "content-type=";
let mut it = url.split('#');
@ -247,14 +248,14 @@ fn guess_mime_type(url: &str) -> Option<String> {
for meta in metas.split('&') {
let meta = meta.to_lowercase();
if meta.starts_with(CONTENT_TYPE) {
return Some(meta[CONTENT_TYPE.len()..].to_owned());
return meta[CONTENT_TYPE.len()..].parse().ok();
}
}
}
url.and_then(|url| {
url.split('.').last()
}).and_then(|extension| {
mime_guess::get_mime_type_str(extension).map(Into::into)
mime_guess::get_mime_type_opt(extension)
})
}
@ -369,7 +370,7 @@ mod tests {
// then
assert_eq!(res, Some(URLHintResult::Content(Content {
url: "https://ethcore.io/assets/images/ethcore-black-horizontal.png".into(),
mime: "image/png".into(),
mime: mime!(Image/Png),
owner: Address::from_str("deadcafebeefbeefcafedeaddeedfeedffffffff").unwrap(),
})))
}
@ -401,9 +402,9 @@ mod tests {
assert_eq!(guess_mime_type(url1), None);
assert_eq!(guess_mime_type(url2), Some("image/png".into()));
assert_eq!(guess_mime_type(url3), Some("image/png".into()));
assert_eq!(guess_mime_type(url4), Some("image/jpeg".into()));
assert_eq!(guess_mime_type(url5), Some("image/png".into()));
assert_eq!(guess_mime_type(url2), Some(mime!(Image/Png)));
assert_eq!(guess_mime_type(url3), Some(mime!(Image/Png)));
assert_eq!(guess_mime_type(url4), Some(mime!(Image/Jpeg)));
assert_eq!(guess_mime_type(url5), Some(mime!(Image/Png)));
}
}

View File

@ -19,7 +19,8 @@
use std::fmt;
/// A release's track.
#[derive(PartialEq, Eq, Clone, Copy, Debug, Binary)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[binary]
pub enum ReleaseTrack {
/// Stable track.
Stable,

View File

@ -23,7 +23,8 @@ use util::misc::raw_package_info;
use release_track::ReleaseTrack;
/// Version information of a particular release.
#[derive(Debug, Clone, PartialEq, Binary)]
#[derive(Debug, Clone, PartialEq)]
#[binary]
pub struct VersionInfo {
/// The track on which it was released.
pub track: ReleaseTrack,

View File

@ -111,7 +111,7 @@ fn push_invoke_signature_aster(
let arg_ty = &inputs[skip-1].ty;
let mut tree = builder.item()
.attr().word("derive(Binary)")
.attr().word("binary")
.attr().word("allow(non_camel_case_types)")
.struct_(name_str.as_str())
.field(arg_name.as_str())
@ -140,7 +140,7 @@ fn push_invoke_signature_aster(
FunctionRetTy::Ty(ref ty) => {
let name_str = format!("{}_output", named_signature.ident.name.as_str());
let tree = builder.item()
.attr().word("derive(Binary)")
.attr().word("binary")
.attr().word("allow(non_camel_case_types)")
.struct_(name_str.as_str())
.field(format!("payload")).ty().build(ty.clone());
@ -326,7 +326,7 @@ pub fn has_ptr(ty: &P<ast::Ty>) -> bool {
/// fn commit(&self, f: u32) -> u32
///
/// the expanded implementation will generate method for the client like that
/// #[derive(Serialize)]
/// #[binary]
/// struct Request<'a> {
/// f: &'a u32,
/// }
@ -358,7 +358,7 @@ fn implement_client_method_body(
.build(static_ty.clone());
let mut tree = builder.item()
.attr().word("derive(Binary)")
.attr().word("binary")
.struct_("Request")
.generics()
.lifetime_name("'a")

View File

@ -42,6 +42,10 @@ extern crate rustc_plugin;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
#[cfg(feature = "with-syntex")]
use syntax::{ast, fold};
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
@ -56,29 +60,44 @@ pub fn expand(src: &std::path::Path, dst: &std::path::Path) {
}
#[cfg(feature = "with-syntex")]
pub fn register_cleaner(reg: &mut syntex::Registry) {
use syntax::{ast, fold};
struct StripAttributeFolder<'a> {
attr_title: &'a str,
}
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"ipc" => { return None; }
ast::MetaItemKind::Word(ref n) if n == &"ipc" => { return None; }
_ => {}
}
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
#[cfg(feature = "with-syntex")]
impl<'a> fold::Folder for StripAttributeFolder<'a> {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == self.attr_title => { return None; }
ast::MetaItemKind::Word(ref n) if n == self.attr_title => { return None; }
_ => {}
}
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
#[cfg(feature = "with-syntex")]
pub fn register_cleaner_ipc(reg: &mut syntex::Registry) {
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
let mut folder = StripAttributeFolder { attr_title: "ipc" };
fold::Folder::fold_crate(&mut folder, krate)
}
reg.add_post_expansion_pass(strip_attributes);
}
#[cfg(feature = "with-syntex")]
pub fn register_cleaner_binary(reg: &mut syntex::Registry) {
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
let mut folder = StripAttributeFolder { attr_title: "binary" };
fold::Folder::fold_crate(&mut folder, krate)
}
reg.add_post_expansion_pass(strip_attributes);
@ -90,9 +109,10 @@ pub fn register(reg: &mut syntex::Registry) {
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("ipc", codegen::expand_ipc_implementation);
reg.add_decorator("derive_Binary", serialization::expand_serialization_implementation);
reg.add_decorator("binary", serialization::expand_serialization_implementation);
register_cleaner(reg);
register_cleaner_ipc(reg);
register_cleaner_binary(reg);
}
#[cfg(not(feature = "with-syntex"))]
@ -102,11 +122,12 @@ pub fn register(reg: &mut rustc_plugin::Registry) {
syntax::ext::base::MultiDecorator(
Box::new(codegen::expand_ipc_implementation)));
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Binary"),
syntax::parse::token::intern("binary"),
syntax::ext::base::MultiDecorator(
Box::new(serialization::expand_serialization_implementation)));
reg.register_attribute("ipc".to_owned(), AttributeType::Normal);
reg.register_attribute("binary".to_owned(), AttributeType::Normal);
}
#[derive(Debug)]
@ -124,13 +145,31 @@ pub fn derive_ipc_cond(src_path: &str, has_feature: bool) -> Result<(), Error> {
}
pub fn cleanup_ipc(src_path: &str) -> Result<(), Error> {
cleanup(src_path, AttributeKind::Ipc)
}
pub fn cleanup_binary(src_path: &str) -> Result<(), Error> {
cleanup(src_path, AttributeKind::Binary)
}
enum AttributeKind {
Ipc,
Binary,
}
fn cleanup(src_path: &str, attr: AttributeKind) -> Result<(), Error> {
use std::env;
use std::path::{Path, PathBuf};
let out_dir = env::var_os("OUT_DIR").unwrap();
let file_name = try!(PathBuf::from(src_path).file_name().ok_or(Error::InvalidFileName).map(|val| val.to_str().unwrap().to_owned()));
let mut registry = syntex::Registry::new();
register_cleaner(&mut registry);
match attr {
AttributeKind::Ipc => { register_cleaner_ipc(&mut registry); }
AttributeKind::Binary => { register_cleaner_binary(&mut registry); }
}
if let Err(_) = registry.expand("", &Path::new(src_path), &Path::new(&out_dir).join(&file_name))
{
// will be reported by compiler
@ -190,3 +229,8 @@ pub fn derive_binary(src_path: &str) -> Result<(), Error> {
Ok(())
}
pub fn derive_binary_cond(src_path: &str, has_feature: bool) -> Result<(), Error> {
if has_feature { derive_binary(src_path) }
else { cleanup_binary(src_path) }
}

View File

@ -17,37 +17,40 @@
use util::Bytes;
#[derive(Binary)]
#[binary]
pub enum Root {
Top,
Middle(u32, u64),
}
#[derive(Binary, PartialEq, Debug)]
#[derive(PartialEq, Debug)]
#[binary]
pub struct DoubleRoot {
pub x1: u32,
pub x2: u64,
pub x3: u32,
}
#[derive(Binary, PartialEq, Debug)]
#[derive(PartialEq, Debug)]
#[binary]
pub struct ReferenceStruct<'a> {
pub ref_data: &'a u64,
}
#[derive(Binary, PartialEq, Debug)]
#[derive(PartialEq, Debug)]
#[binary]
pub enum EnumWithStruct {
Left,
Right { how_much: u64 },
}
#[derive(Binary)]
#[binary]
pub struct TwoVec {
v1: Vec<u8>,
v2: Vec<u8>,
}
#[derive(Binary)]
#[binary]
struct ChunkSet {
items: Vec<Bytes>,
}

View File

@ -30,7 +30,7 @@ pub trait DBWriter {
impl IpcConfig for DBWriter {}
#[derive(Binary)]
#[binary]
pub enum DBError { Write, Read }
#[ipc]

View File

@ -22,7 +22,7 @@ pub struct Service {
pub rollbacks: RwLock<usize>,
}
#[derive(Binary)]
#[binary]
pub struct CustomData {
pub a: u64,
pub b: u64,

View File

@ -1,6 +1,6 @@
{
"name": "parity.js",
"version": "0.2.131",
"version": "0.2.141",
"main": "release/index.js",
"jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>",
@ -53,7 +53,7 @@
"babel-cli": "6.18.0",
"babel-core": "6.20.0",
"babel-eslint": "7.1.1",
"babel-loader": "6.2.8",
"babel-loader": "6.2.10",
"babel-plugin-lodash": "3.2.10",
"babel-plugin-react-intl": "2.2.0",
"babel-plugin-transform-class-properties": "6.18.0",
@ -117,6 +117,7 @@
"react-hot-loader": "3.0.0-beta.6",
"react-intl-aggregate-webpack-plugin": "0.0.1",
"rucksack-css": "0.9.1",
"script-ext-html-webpack-plugin": "1.3.4",
"serviceworker-webpack-plugin": "0.1.7",
"sinon": "1.17.6",
"sinon-as-promised": "4.0.2",
@ -125,7 +126,7 @@
"stylelint": "7.6.0",
"stylelint-config-standard": "15.0.0",
"url-loader": "0.5.7",
"webpack": "2.1.0-beta.27",
"webpack": "2.2.0-rc.2",
"webpack-dev-middleware": "1.8.4",
"webpack-error-notification": "0.1.6",
"webpack-hot-middleware": "2.13.2",

View File

@ -1 +1 @@
// test script 6
// test script 7

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify

View File

@ -66,6 +66,20 @@ export function outBlock (block) {
return block;
}
export function outChainStatus (status) {
if (status) {
Object.keys(status).forEach((key) => {
switch (key) {
case 'blockGap':
status[key] = status[key].map(outNumber);
break;
}
});
}
return status;
}
export function outDate (date) {
return new Date(outNumber(date).toNumber() * 1000);
}
@ -77,6 +91,7 @@ export function outHistogram (histogram) {
case 'bucketBounds':
case 'counts':
histogram[key] = histogram[key].map(outNumber);
break;
}
});
}

View File

@ -16,7 +16,7 @@
import BigNumber from 'bignumber.js';
import { outBlock, outAccountInfo, outAddress, outDate, outHistogram, outNumber, outPeers, outReceipt, outSyncing, outTransaction, outTrace } from './output';
import { outBlock, outAccountInfo, outAddress, outChainStatus, outDate, outHistogram, outNumber, outPeers, outReceipt, outSyncing, outTransaction, outTrace } from './output';
import { isAddress, isBigNumber, isInstanceOf } from '../../../test/types';
describe('api/format/output', () => {
@ -114,6 +114,18 @@ describe('api/format/output', () => {
});
});
describe('outChainStatus', () => {
it('formats blockGap values', () => {
const status = {
blockGap: [0x1234, '0x5678']
};
expect(outChainStatus(status)).to.deep.equal({
blockGap: [new BigNumber(0x1234), new BigNumber(0x5678)]
});
});
});
describe('outDate', () => {
it('converts a second date in unix timestamp', () => {
expect(outDate(0x57513668)).to.deep.equal(new Date('2016-06-03T07:48:56.000Z'));

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { inAddress, inData, inHex, inNumber16, inOptions } from '../../format/input';
import { outAccountInfo, outAddress, outHistogram, outNumber, outPeers, outTransaction } from '../../format/output';
import { outAccountInfo, outAddress, outChainStatus, outHistogram, outNumber, outPeers, outTransaction } from '../../format/output';
export default class Parity {
constructor (transport) {
@ -44,6 +44,12 @@ export default class Parity {
.execute('parity_addReservedPeer', encode);
}
chainStatus () {
return this._transport
.execute('parity_chainStatus')
.then(outChainStatus);
}
changePassword (account, password, newPassword) {
return this._transport
.execute('parity_changePassword', inAddress(account), password, newPassword);

View File

@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import BigNumber from 'bignumber.js';
import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc';
import { isBigNumber } from '../../../../test/types';
@ -45,6 +46,22 @@ describe('api/rpc/parity', () => {
});
});
describe('chainStatus', () => {
it('retrieves the chain status', () => {
mockHttp([{ method: 'parity_chainStatus', reply: {
result: {
'blockGap': [0x123, 0x456]
}
} }]);
return instance.chainStatus().then((result) => {
expect(result).to.deep.equal({
'blockGap': [new BigNumber(0x123), new BigNumber(0x456)]
});
});
});
});
describe('gasFloorTarget', () => {
it('returns the gasfloor, formatted', () => {
mockHttp([{ method: 'parity_gasFloorTarget', reply: { result: '0x123456' } }]);

View File

@ -22,7 +22,7 @@ import TransportError from '../error';
/* global WebSocket */
export default class Ws extends JsonRpcBase {
constructor (url, token) {
constructor (url, token, connect = true) {
super();
this._url = url;
@ -32,23 +32,34 @@ export default class Ws extends JsonRpcBase {
this._connecting = false;
this._connected = false;
this._lastError = null;
this._autoConnect = true;
this._autoConnect = false;
this._retries = 0;
this._reconnectTimeoutId = null;
this._connect();
this._connectPromise = null;
this._connectPromiseFunctions = {};
if (connect) {
this.connect();
}
}
updateToken (token) {
updateToken (token, connect = true) {
this._token = token;
this._autoConnect = true;
// this._autoConnect = true;
this._connect();
if (connect) {
this.connect();
}
}
_connect () {
connect () {
if (this._connected) {
return Promise.resolve();
}
if (this._connecting) {
return;
return this._connectPromise || Promise.resolve();
}
if (this._reconnectTimeoutId) {
@ -104,10 +115,17 @@ export default class Ws extends JsonRpcBase {
window._parityWS = this;
}
this._connectPromise = new Promise((resolve, reject) => {
this._connectPromiseFunctions = { resolve, reject };
});
return this._connectPromise;
}
_onOpen = (event) => {
console.log('ws:onOpen', event);
console.log('ws:onOpen');
this._connected = true;
this._connecting = false;
this._autoConnect = true;
@ -116,6 +134,11 @@ export default class Ws extends JsonRpcBase {
Object.keys(this._messages)
.filter((id) => this._messages[id].queued)
.forEach(this._send);
this._connectPromiseFunctions.resolve();
this._connectPromise = null;
this._connectPromiseFunctions = {};
}
_onClose = (event) => {
@ -135,13 +158,20 @@ export default class Ws extends JsonRpcBase {
console.log('ws:onClose', `trying again in ${time}...`);
this._reconnectTimeoutId = setTimeout(() => {
this._connect();
this.connect();
}, timeout);
return;
}
console.log('ws:onClose', event);
if (this._connectPromise) {
this._connectPromiseFunctions.reject(event);
this._connectPromise = null;
this._connectPromiseFunctions = {};
}
console.log('ws:onClose');
}
_onError = (event) => {
@ -149,10 +179,17 @@ export default class Ws extends JsonRpcBase {
// ie. don't print if error == closed
window.setTimeout(() => {
if (this._connected) {
console.error('ws:onError', event);
console.error('ws:onError');
event.timestamp = Date.now();
this._lastError = event;
if (this._connectPromise) {
this._connectPromiseFunctions.reject(event);
this._connectPromise = null;
this._connectPromiseFunctions = {};
}
}
}, 50);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

View File

@ -1,4 +1,4 @@
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify

Some files were not shown because too many files have changed in this diff Show More