Merge branch 'master' into new-jsonrpc

This commit is contained in:
Tomasz Drwięga 2017-03-16 15:51:00 +01:00
commit 44052e7d8d
No known key found for this signature in database
GPG Key ID: D066F497E62CAF66
67 changed files with 832 additions and 336 deletions

View File

@ -26,14 +26,14 @@ linux-stable:
- cargo build -j $(nproc) --release -p ethstore - cargo build -j $(nproc) --release -p ethstore
- cargo build -j $(nproc) --release -p ethkey - cargo build -j $(nproc) --release -p ethkey
- strip target/release/parity - strip target/release/parity
- strip target/release/evm - strip target/release/parity-evm
- strip target/release/ethstore - strip target/release/ethstore
- strip target/release/ethkey - strip target/release/ethkey
- export SHA3=$(target/release/parity tools hash target/release/parity) - export SHA3=$(target/release/parity tools hash target/release/parity)
- md5sum target/release/parity > parity.md5 - md5sum target/release/parity > parity.md5
- sh scripts/deb-build.sh amd64 - sh scripts/deb-build.sh amd64
- cp target/release/parity deb/usr/bin/parity - cp target/release/parity deb/usr/bin/parity
- cp target/release/evm deb/usr/bin/evm - cp target/release/parity-evm deb/usr/bin/parity-evm
- cp target/release/ethstore deb/usr/bin/ethstore - cp target/release/ethstore deb/usr/bin/ethstore
- cp target/release/ethkey deb/usr/bin/ethkey - cp target/release/ethkey deb/usr/bin/ethkey
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
@ -55,9 +55,9 @@ linux-stable:
artifacts: artifacts:
paths: paths:
- target/release/parity - target/release/parity
- target/release/parity/evmbin - target/release/parity-evm
- target/release/parity/ethstore - target/release/ethstore
- target/release/parity/ethkey - target/release/ethkey
name: "stable-x86_64-unknown-linux-gnu_parity" name: "stable-x86_64-unknown-linux-gnu_parity"
linux-stable-debian: linux-stable-debian:
stage: build stage: build
@ -73,14 +73,14 @@ linux-stable-debian:
- cargo build -j $(nproc) --release -p ethstore - cargo build -j $(nproc) --release -p ethstore
- cargo build -j $(nproc) --release -p ethkey - cargo build -j $(nproc) --release -p ethkey
- strip target/release/parity - strip target/release/parity
- strip target/release/evm - strip target/release/parity-evm
- strip target/release/ethstore - strip target/release/ethstore
- strip target/release/ethkey - strip target/release/ethkey
- export SHA3=$(target/release/parity tools hash target/release/parity) - export SHA3=$(target/release/parity tools hash target/release/parity)
- md5sum target/release/parity > parity.md5 - md5sum target/release/parity > parity.md5
- sh scripts/deb-build.sh amd64 - sh scripts/deb-build.sh amd64
- cp target/release/parity deb/usr/bin/parity - cp target/release/parity deb/usr/bin/parity
- cp target/release/evm deb/usr/bin/evm - cp target/release/parity-evm deb/usr/bin/parity-evm
- cp target/release/ethstore deb/usr/bin/ethstore - cp target/release/ethstore deb/usr/bin/ethstore
- cp target/release/ethkey deb/usr/bin/ethkey - cp target/release/ethkey deb/usr/bin/ethkey
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
@ -506,15 +506,16 @@ docker-build:
test-coverage: test-coverage:
stage: test stage: test
only: only:
- coverage - master
script: script:
- git submodule update --init --recursive - git submodule update --init --recursive
- rm -rf target/*
- rm -rf js/.coverage
- scripts/cov.sh - scripts/cov.sh
- COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/kcov/index.json | grep "[0-9]*\.[0-9]" -o) # - COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/cov/index.json | grep "[0-9]*\.[0-9]" -o)
- echo "Coverage:" $COVERAGE # - echo "Coverage:" $COVERAGE
tags: tags:
- kcov - kcov
allow_failure: true
test-darwin: test-darwin:
stage: test stage: test
only: only:

69
Cargo.lock generated
View File

@ -31,7 +31,7 @@ dependencies = [
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (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)", "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (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.7.0", "parity-hash-fetch 1.7.0",
"parity-ipfs-api 1.7.0", "parity-ipfs-api 1.7.0",
@ -44,6 +44,7 @@ dependencies = [
"rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rpc-cli 1.4.0", "rpc-cli 1.4.0",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -356,7 +357,7 @@ version = "0.5.6"
source = "git+https://github.com/ethcore/rust-secp256k1#98ad9b9ecae44a563efdd64273bcebc6b4ed81c6" source = "git+https://github.com/ethcore/rust-secp256k1#98ad9b9ecae44a563efdd64273bcebc6b4ed81c6"
dependencies = [ dependencies = [
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@ -414,7 +415,7 @@ dependencies = [
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.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)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0", "rlp 0.1.0",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
@ -892,10 +893,10 @@ dependencies = [
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.35" version = "0.3.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -942,7 +943,7 @@ name = "hidapi"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/ethcore/hidapi-rs#9a127c1dca7e327e4fdd428406a76c9f5ef48563" source = "git+https://github.com/ethcore/hidapi-rs#9a127c1dca7e327e4fdd428406a76c9f5ef48563"
dependencies = [ dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1245,7 +1246,7 @@ name = "libusb-sys"
version = "0.2.3" version = "0.2.3"
source = "git+https://github.com/ethcore/libusb-sys#c10b1180646c9dc3f23a9b6bb825abcd3b7487ce" source = "git+https://github.com/ethcore/libusb-sys#c10b1180646c9dc3f23a9b6bb825abcd3b7487ce"
dependencies = [ dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1309,7 +1310,7 @@ name = "miniz-sys"
version = "0.1.7" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1445,7 +1446,7 @@ name = "nanomsg-sys"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00" source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00"
dependencies = [ dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1578,14 +1579,6 @@ name = "num-traits"
version = "0.1.32" version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "0.2.11"
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]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.2.0" version = "1.2.0"
@ -1768,7 +1761,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-ui-precompiled" name = "parity-ui-precompiled"
version = "1.4.0" version = "1.4.0"
source = "git+https://github.com/ethcore/js-precompiled.git#24514f56ade650f54b97c2cff4e27d798b274e41" source = "git+https://github.com/ethcore/js-precompiled.git#547a5352d779bc7821a7a2ec14c6d480833aeabb"
dependencies = [ dependencies = [
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1939,11 +1932,12 @@ dependencies = [
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "0.4.2" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2011,7 +2005,7 @@ name = "rocksdb-sys"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58" source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
dependencies = [ dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2066,7 +2060,7 @@ name = "rust-crypto"
version = "0.2.36" version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2086,6 +2080,14 @@ dependencies = [
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "rustc_version"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "schannel" name = "schannel"
version = "0.1.1" version = "0.1.1"
@ -2155,6 +2157,14 @@ dependencies = [
"semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "semver"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "semver-parser" name = "semver-parser"
version = "0.6.1" version = "0.6.1"
@ -2164,6 +2174,11 @@ dependencies = [
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "0.9.6" version = "0.9.6"
@ -2218,7 +2233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "sha3" name = "sha3"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2714,7 +2729,7 @@ dependencies = [
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb" "checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
"checksum futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51e7f9c150ba7fd4cee9df8bf6ea3dea5b63b68955ddad19ccd35b71dcfb4d" "checksum futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51e7f9c150ba7fd4cee9df8bf6ea3dea5b63b68955ddad19ccd35b71dcfb4d"
"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82" "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 gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" "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 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 hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1"
@ -2783,7 +2798,6 @@ dependencies = [
"checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c" "checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c"
"checksum num-rational 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "48cdcc9ff4ae2a8296805ac15af88b3d88ce62128ded0cb74ffb63a587502a84" "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-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 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 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 odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1"
@ -2814,7 +2828,7 @@ dependencies = [
"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a" "checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a"
"checksum quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6732e32663c9c271bfc7c1823486b471f18c47a2dbf87c066897b7b51afc83be" "checksum quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6732e32663c9c271bfc7c1823486b471f18c47a2dbf87c066897b7b51afc83be"
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5" "checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
"checksum rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "655df67c314c30fa3055a365eae276eb88aa4f3413a352a1ab32c1320eda41ea" "checksum rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50c575b58c2b109e2fbc181820cbe177474f35610ff9e357dc75f6bac854ffbf"
"checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29" "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 regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "841591b1e05609a643e3b4d0045fce04f701daba7151ddcd3ad47b080693d5a9"
"checksum reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bef9ed8fdfcc30947d6b774938dc0c3f369a474efe440df2c7f278180b2d2e6" "checksum reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bef9ed8fdfcc30947d6b774938dc0c3f369a474efe440df2c7f278180b2d2e6"
@ -2827,6 +2841,7 @@ dependencies = [
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "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-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 rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
"checksum rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e114e275f7c9b5d50bb52b28f9aac1921209f02aa6077c8b255e21eefaf8ffa"
"checksum schannel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "167852e03fcd0029c3ddebb5afb0715b2996f6e262b2c2aceaa7cd84edd4b158" "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 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 secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc"
@ -2835,7 +2850,9 @@ dependencies = [
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "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.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 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9" "checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae9a3c8b07c09dbe43022486d55a18c629a0618d2241e49829aaef9b6d862f9" "checksum serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae9a3c8b07c09dbe43022486d55a18c629a0618d2241e49829aaef9b6d862f9"
"checksum serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3172bf2940b975c0e4f6ab42a511c0a4407d4f46ccef87a9d3615db5c26fa96" "checksum serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3172bf2940b975c0e4f6ab42a511c0a4407d4f46ccef87a9d3615db5c26fa96"
"checksum serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc6e0379ca933ece58302d2d3034443f06fbf38fd535857c1dc516195cbc3bf" "checksum serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc6e0379ca933ece58302d2d3034443f06fbf38fd535857c1dc516195cbc3bf"

View File

@ -4,6 +4,7 @@ name = "parity"
version = "1.7.0" version = "1.7.0"
license = "GPL-3.0" license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
[dependencies] [dependencies]
log = "0.3" log = "0.3"
@ -11,7 +12,7 @@ env_logger = "0.3"
rustc-serialize = "0.3" rustc-serialize = "0.3"
docopt = "0.6" docopt = "0.6"
time = "0.1" time = "0.1"
num_cpus = "0.2" num_cpus = "1.2"
number_prefix = "0.2" number_prefix = "0.2"
rpassword = "0.2.1" rpassword = "0.2.1"
semver = "0.5" semver = "0.5"
@ -52,6 +53,9 @@ ethcore-dapps = { path = "dapps", optional = true }
clippy = { version = "0.0.103", optional = true} clippy = { version = "0.0.103", optional = true}
ethcore-secretstore = { path = "secret_store", optional = true } ethcore-secretstore = { path = "secret_store", optional = true }
[build-dependencies]
rustc_version = "0.2"
[dev-dependencies] [dev-dependencies]
ethcore-ipc-tests = { path = "ipc/tests" } ethcore-ipc-tests = { path = "ipc/tests" }

View File

@ -14,28 +14,22 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! `TraceDB` errors. extern crate rustc_version;
use std::fmt::{Display, Formatter, Error as FmtError}; const MIN_RUSTC_VERSION: &'static str = "1.15.1";
const RESYNC_ERR: &'static str = fn main() {
"Your current parity installation has synced without transaction tracing. let is = rustc_version::version().unwrap();
To use Parity with transaction tracing, you'll need to resync with tracing. let required = MIN_RUSTC_VERSION.parse().unwrap();
To do this, remove or move away your current database and restart parity. e.g.: assert!(is >= required, format!("
> mv ~/.parity/906a34e69aec8c0d /tmp It looks like you are compiling Parity with an old rustc compiler {}.
> parity"; Parity requires version {}. Please update your compiler.
If you use rustup, try this:
/// `TraceDB` errors. rustup update stable
#[derive(Debug)]
pub enum Error { and try building Parity again.
/// Returned when tracing is enabled,
/// but database does not contain traces of old transactions. ", is, required));
ResyncRequired,
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
write!(f, "{}", RESYNC_ERR)
}
} }

View File

@ -15,7 +15,7 @@ log = "0.3"
env_logger = "0.3" env_logger = "0.3"
rustc-serialize = "0.3" rustc-serialize = "0.3"
rust-crypto = "0.2.34" rust-crypto = "0.2.34"
num_cpus = "0.2" num_cpus = "1.2"
crossbeam = "0.2.9" crossbeam = "0.2.9"
lazy_static = "0.2" lazy_static = "0.2"
bloomchain = "0.1" bloomchain = "0.1"

View File

@ -30,7 +30,8 @@
"params": { "params": {
"maximumExtraDataSize": "0x20", "maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388", "minGasLimit": "0x1388",
"networkID" : "0x2A" "networkID" : "0x2A",
"validateReceipts" : false
}, },
"genesis": { "genesis": {
"seal": { "seal": {

View File

@ -139,6 +139,7 @@
} }
}, },
"params": { "params": {
"eip98Transition": "0x7fffffffffffffff",
"accountStartNonce": "0x00", "accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20", "maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388", "minGasLimit": "0x1388",

View File

@ -553,7 +553,6 @@ pub fn enact(
b.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e)); b.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e));
b.set_uncles_hash(header.uncles_hash().clone()); b.set_uncles_hash(header.uncles_hash().clone());
b.set_transactions_root(header.transactions_root().clone()); b.set_transactions_root(header.transactions_root().clone());
b.set_receipts_root(header.receipts_root().clone());
push_transactions(&mut b, transactions)?; push_transactions(&mut b, transactions)?;
for u in uncles { for u in uncles {

View File

@ -393,7 +393,7 @@ impl Client {
})?; })?;
// Final Verification // Final Verification
if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header()) { if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts) {
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
return Err(()); return Err(());
} }

View File

@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use trace::Error as TraceError;
use util::UtilError; use util::UtilError;
use std::fmt::{Display, Formatter, Error as FmtError}; use std::fmt::{Display, Formatter, Error as FmtError};
@ -23,8 +22,6 @@ use util::trie::TrieError;
/// Client configuration errors. /// Client configuration errors.
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
/// TraceDB configuration error.
Trace(TraceError),
/// TrieDB-related error. /// TrieDB-related error.
Trie(TrieError), Trie(TrieError),
/// Database error /// Database error
@ -33,12 +30,6 @@ pub enum Error {
Util(UtilError), Util(UtilError),
} }
impl From<TraceError> for Error {
fn from(err: TraceError) -> Self {
Error::Trace(err)
}
}
impl From<TrieError> for Error { impl From<TrieError> for Error {
fn from(err: TrieError) -> Self { fn from(err: TrieError) -> Self {
Error::Trie(err) Error::Trie(err)
@ -60,7 +51,6 @@ impl<E> From<Box<E>> for Error where Error: From<E> {
impl Display for Error { impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match *self { match *self {
Error::Trace(ref err) => write!(f, "{}", err),
Error::Trie(ref err) => write!(f, "{}", err), Error::Trie(ref err) => write!(f, "{}", err),
Error::Util(ref err) => write!(f, "{}", err), Error::Util(ref err) => write!(f, "{}", err),
Error::Database(ref s) => write!(f, "Database error: {}", s), Error::Database(ref s) => write!(f, "Database error: {}", s),

View File

@ -90,6 +90,8 @@ pub struct MinerOptions {
pub reseal_on_own_tx: bool, pub reseal_on_own_tx: bool,
/// Minimum period between transaction-inspired reseals. /// Minimum period between transaction-inspired reseals.
pub reseal_min_period: Duration, pub reseal_min_period: Duration,
/// Maximum period between blocks (enables force sealing after that).
pub reseal_max_period: Duration,
/// Maximum amount of gas to bother considering for block insertion. /// Maximum amount of gas to bother considering for block insertion.
pub tx_gas_limit: U256, pub tx_gas_limit: U256,
/// Maximum size of the transaction queue. /// Maximum size of the transaction queue.
@ -123,6 +125,7 @@ impl Default for MinerOptions {
tx_queue_strategy: PrioritizationStrategy::GasPriceOnly, tx_queue_strategy: PrioritizationStrategy::GasPriceOnly,
pending_set: PendingSet::AlwaysQueue, pending_set: PendingSet::AlwaysQueue,
reseal_min_period: Duration::from_secs(2), reseal_min_period: Duration::from_secs(2),
reseal_max_period: Duration::from_secs(120),
work_queue_size: 20, work_queue_size: 20,
enable_resubmission: true, enable_resubmission: true,
tx_queue_banning: Banning::Disabled, tx_queue_banning: Banning::Disabled,
@ -212,6 +215,7 @@ pub struct Miner {
transaction_queue: Arc<Mutex<BanningTransactionQueue>>, transaction_queue: Arc<Mutex<BanningTransactionQueue>>,
sealing_work: Mutex<SealingWork>, sealing_work: Mutex<SealingWork>,
next_allowed_reseal: Mutex<Instant>, next_allowed_reseal: Mutex<Instant>,
next_mandatory_reseal: RwLock<Instant>,
sealing_block_last_request: Mutex<u64>, sealing_block_last_request: Mutex<u64>,
// for sealing... // for sealing...
options: MinerOptions, options: MinerOptions,
@ -268,6 +272,7 @@ impl Miner {
Miner { Miner {
transaction_queue: Arc::new(Mutex::new(txq)), transaction_queue: Arc::new(Mutex::new(txq)),
next_allowed_reseal: Mutex::new(Instant::now()), next_allowed_reseal: Mutex::new(Instant::now()),
next_mandatory_reseal: RwLock::new(Instant::now() + options.reseal_max_period),
sealing_block_last_request: Mutex::new(0), sealing_block_last_request: Mutex::new(0),
sealing_work: Mutex::new(SealingWork{ sealing_work: Mutex::new(SealingWork{
queue: UsingQueue::new(options.work_queue_size), queue: UsingQueue::new(options.work_queue_size),
@ -298,7 +303,9 @@ impl Miner {
} }
fn forced_sealing(&self) -> bool { fn forced_sealing(&self) -> bool {
self.options.force_sealing || !self.options.new_work_notify.is_empty() self.options.force_sealing
|| !self.options.new_work_notify.is_empty()
|| Instant::now() > *self.next_mandatory_reseal.read()
} }
/// Clear all pending block states /// Clear all pending block states
@ -482,6 +489,7 @@ impl Miner {
// Save proposal for later seal submission and broadcast it. // Save proposal for later seal submission and broadcast it.
Seal::Proposal(seal) => { Seal::Proposal(seal) => {
trace!(target: "miner", "Received a Proposal seal."); trace!(target: "miner", "Received a Proposal seal.");
*self.next_mandatory_reseal.write() = Instant::now() + self.options.reseal_max_period;
{ {
let mut sealing_work = self.sealing_work.lock(); let mut sealing_work = self.sealing_work.lock();
sealing_work.queue.push(block.clone()); sealing_work.queue.push(block.clone());
@ -497,7 +505,8 @@ impl Miner {
}) })
}, },
// Directly import a regular sealed block. // Directly import a regular sealed block.
Seal::Regular(seal) => Seal::Regular(seal) => {
*self.next_mandatory_reseal.write() = Instant::now() + self.options.reseal_max_period;
block block
.lock() .lock()
.seal(&*self.engine, seal) .seal(&*self.engine, seal)
@ -505,7 +514,8 @@ impl Miner {
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
warn!("ERROR: seal failed when given internally generated seal: {}", e); warn!("ERROR: seal failed when given internally generated seal: {}", e);
false false
}), })
},
Seal::None => false, Seal::None => false,
} }
} else { } else {
@ -1290,6 +1300,7 @@ mod tests {
reseal_on_external_tx: false, reseal_on_external_tx: false,
reseal_on_own_tx: true, reseal_on_own_tx: true,
reseal_min_period: Duration::from_secs(5), reseal_min_period: Duration::from_secs(5),
reseal_max_period: Duration::from_secs(120),
tx_gas_limit: !U256::zero(), tx_gas_limit: !U256::zero(),
tx_queue_size: 1024, tx_queue_size: 1024,
tx_queue_gas_limit: GasLimit::None, tx_queue_gas_limit: GasLimit::None,

View File

@ -55,6 +55,8 @@ pub struct CommonParams {
pub fork_block: Option<(BlockNumber, H256)>, pub fork_block: Option<(BlockNumber, H256)>,
/// Number of first block where EIP-98 rules begin. /// Number of first block where EIP-98 rules begin.
pub eip98_transition: BlockNumber, pub eip98_transition: BlockNumber,
/// Validate block receipts root.
pub validate_receipts: bool,
} }
impl From<ethjson::spec::Params> for CommonParams { impl From<ethjson::spec::Params> for CommonParams {
@ -68,6 +70,7 @@ impl From<ethjson::spec::Params> for CommonParams {
min_gas_limit: p.min_gas_limit.into(), 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 }, fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
eip98_transition: p.eip98_transition.map_or(0, Into::into), eip98_transition: p.eip98_transition.map_or(0, Into::into),
validate_receipts: p.validate_receipts.unwrap_or(true),
} }
} }
} }

View File

@ -19,7 +19,6 @@
mod bloom; mod bloom;
mod config; mod config;
mod db; mod db;
mod error;
mod executive_tracer; mod executive_tracer;
mod import; mod import;
mod noop_tracer; mod noop_tracer;
@ -28,7 +27,6 @@ pub use types::trace_types::{filter, flat, localized, trace};
pub use types::trace_types::error::Error as TraceError; pub use types::trace_types::error::Error as TraceError;
pub use self::config::Config; pub use self::config::Config;
pub use self::db::TraceDB; pub use self::db::TraceDB;
pub use self::error::Error;
pub use types::trace_types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff}; pub use types::trace_types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff};
pub use types::trace_types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces}; pub use types::trace_types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces};
pub use self::noop_tracer::{NoopTracer, NoopVMTracer}; pub use self::noop_tracer::{NoopTracer, NoopVMTracer};

View File

@ -31,7 +31,7 @@ impl Verifier for CanonVerifier {
verification::verify_block_family(header, bytes, engine, bc) verification::verify_block_family(header, bytes, engine, bc)
} }
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> { fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error> {
verification::verify_block_final(expected, got) verification::verify_block_final(expected, got, receipts)
} }
} }

View File

@ -31,7 +31,7 @@ impl Verifier for NoopVerifier {
Ok(()) Ok(())
} }
fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> { fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: bool) -> Result<(), Error> {
Ok(()) Ok(())
} }
} }

View File

@ -178,7 +178,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
} }
/// Phase 4 verification. Check block information against transaction enactment results, /// Phase 4 verification. Check block information against transaction enactment results,
pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> { pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: bool) -> Result<(), Error> {
if expected.gas_used() != got.gas_used() { if expected.gas_used() != got.gas_used() {
return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() }))) return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() })))
} }
@ -188,7 +188,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>
if expected.state_root() != got.state_root() { if expected.state_root() != got.state_root() {
return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() }))) return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() })))
} }
if expected.receipts_root() != got.receipts_root() { if check_receipts && expected.receipts_root() != got.receipts_root() {
return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() }))) return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() })))
} }
Ok(()) Ok(())

View File

@ -26,5 +26,5 @@ pub trait Verifier: Send + Sync {
/// Verify a block relative to its parent and uncles. /// Verify a block relative to its parent and uncles.
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>; fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
/// Do a final verification check for an enacted header vs its expected counterpart. /// Do a final verification check for an enacted header vs its expected counterpart.
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>; fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error>;
} }

View File

@ -5,11 +5,11 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[lib] [lib]
name = "evm" name = "evmbin"
path = "./src/main.rs" path = "./src/main.rs"
[[bin]] [[bin]]
name = "evm" name = "parity-evm"
path = "./src/main.rs" path = "./src/main.rs"
[dependencies] [dependencies]

View File

@ -1,6 +1,6 @@
{ {
"name": "parity.js", "name": "parity.js",
"version": "1.7.12", "version": "1.7.18",
"main": "release/index.js", "main": "release/index.js",
"jsnext:main": "src/index.js", "jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>", "author": "Parity Team <admin@parity.io>",

View File

@ -1 +1,2 @@
// test script 7 // test script 8
// trigger rebuild on master 15 Mar 2017, 11:19

View File

@ -107,13 +107,25 @@ export default class Contract {
}); });
} }
deploy (options, values, statecb = () => {}) { deploy (options, values, statecb = () => {}, skipGasEstimate = false) {
statecb(null, { state: 'estimateGas' }); let gasEstPromise;
return this if (skipGasEstimate) {
.deployEstimateGas(options, values) gasEstPromise = Promise.resolve(null);
.then(([gasEst, gas]) => { } else {
options.gas = gas.toFixed(0); statecb(null, { state: 'estimateGas' });
gasEstPromise = this.deployEstimateGas(options, values)
.then(([gasEst, gas]) => gas);
}
return gasEstPromise
.then((_gas) => {
if (_gas) {
options.gas = _gas.toFixed(0);
}
const gas = _gas || options.gas;
statecb(null, { state: 'postTransaction', gas }); statecb(null, { state: 'postTransaction', gas });

View File

@ -253,23 +253,28 @@ export default class Deployment extends Component {
onDeploy = () => { onDeploy = () => {
const { managerInstance, registryInstance, tokenregInstance } = this.context; const { managerInstance, registryInstance, tokenregInstance } = this.context;
const { base, deployBusy, globalReg, globalFee, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state; const { base, deployBusy, globalReg, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state;
const hasError = !!(nameError || tlaError || totalSupplyError); const hasError = !!(nameError || tlaError || totalSupplyError);
if (hasError || deployBusy) { if (hasError || deployBusy) {
return; return;
} }
const tokenreg = (globalReg ? tokenregInstance : registryInstance).address; const registry = globalReg ? tokenregInstance : registryInstance;
const tokenreg = registry.address;
const values = [base.mul(totalSupply), tla, name, tokenreg]; const values = [base.mul(totalSupply), tla, name, tokenreg];
const options = { const options = {};
value: globalReg ? globalFee : 0
};
this.setState({ deployBusy: true, deployState: 'Estimating gas for the transaction' }); this.setState({ deployBusy: true, deployState: 'Estimating gas for the transaction' });
return api.parity return registry.fee.call({}, [])
.defaultAccount() .then((fee) => {
console.log('deploying with fee of', fee.toFixed());
options.value = fee;
return api.parity.defaultAccount();
})
.then((defaultAddress) => { .then((defaultAddress) => {
options.from = defaultAddress; options.from = defaultAddress;

View File

@ -19,7 +19,7 @@ import { Dialog, RaisedButton, FlatButton, SelectField, MenuItem } from 'materia
import AddIcon from 'material-ui/svg-icons/content/add'; import AddIcon from 'material-ui/svg-icons/content/add';
import InputText from '../../Inputs/Text'; import InputText from '../../Inputs/Text';
import { ADDRESS_TYPE } from '../../Inputs/validation'; import { ADDRESS_TYPE, URL_TYPE } from '../../Inputs/validation';
import styles from './token.css'; import styles from './token.css';
@ -128,6 +128,22 @@ export default class AddMeta extends Component {
renderForm () { renderForm () {
const selectedMeta = metaDataKeys[this.state.metaKeyIndex]; const selectedMeta = metaDataKeys[this.state.metaKeyIndex];
const metaLabel = selectedMeta.label.toLowerCase();
let metaType;
switch (selectedMeta.validation) {
case ADDRESS_TYPE:
metaType = 'Address';
break;
case URL_TYPE:
metaType = 'URL';
break;
default:
metaType = 'URL Hint';
break;
}
return ( return (
<div> <div>
@ -145,7 +161,7 @@ export default class AddMeta extends Component {
<InputText <InputText
key={ selectedMeta.value } key={ selectedMeta.value }
floatingLabelText={ `${selectedMeta.label} value` } floatingLabelText={ `${selectedMeta.label} value` }
hintText={ `The value of the ${selectedMeta.label.toLowerCase()} (${selectedMeta.validation === ADDRESS_TYPE ? 'Address' : 'Url Hint'})` } hintText={ `The value of the ${metaLabel} (${metaType})` }
validationType={ selectedMeta.validation } validationType={ selectedMeta.validation }
onChange={ this.onChange } onChange={ this.onChange }
@ -174,14 +190,20 @@ export default class AddMeta extends Component {
onAdd = () => { onAdd = () => {
const { index } = this.props; const { index } = this.props;
const { form, metaKeyIndex } = this.state;
const selectedMeta = metaDataKeys[metaKeyIndex];
const keyIndex = this.state.metaKeyIndex; const keyIndex = this.state.metaKeyIndex;
const key = metaDataKeys[keyIndex].value; const key = metaDataKeys[keyIndex].value;
const value = form.value;
const validationType = selectedMeta.validation;
this.props.handleAddMeta( this.props.handleAddMeta(
index, index,
key, key,
this.state.form.value value,
validationType
); );
this.setState({ complete: true }); this.setState({ complete: true });

View File

@ -61,8 +61,8 @@ const mapDispatchToProps = (dispatch) => {
dispatch(unregisterToken(index)); dispatch(unregisterToken(index));
}, },
handleAddMeta: (index, key, value) => { handleAddMeta: (index, key, value, validationType) => {
dispatch(addTokenMeta(index, key, value)); dispatch(addTokenMeta(index, key, value, validationType));
} }
}; };
}; };

View File

@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { getTokenTotalSupply } from '../utils'; import { URL_TYPE } from '../Inputs/validation';
import { getTokenTotalSupply, urlToHash } from '../utils';
const { bytesToHex } = window.parity.api.util; const { bytesToHex } = window.parity.api.util;
@ -178,40 +179,63 @@ export const queryTokenMeta = (index, query) => (dispatch, getState) => {
}); });
}; };
export const addTokenMeta = (index, key, value) => (dispatch, getState) => { export const addTokenMeta = (index, key, value, validationType) => (dispatch, getState) => {
const state = getState(); const state = getState();
const contractInstance = state.status.contract.instance; const contractInstance = state.status.contract.instance;
const ghhInstance = state.status.githubhint.instance;
const token = state.tokens.tokens.find(t => t.index === index); const token = state.tokens.tokens.find(t => t.index === index);
const options = { from: token.owner }; const options = { from: token.owner };
const values = [ index, key, value ]; let valuesPromise;
contractInstance // Get the right values (could be a hashed URL from GHH)
.setMeta if (validationType === URL_TYPE) {
.estimateGas(options, values) valuesPromise = addGithubhintURL(ghhInstance, options, value)
.then((gasEstimate) => { .then((hash) => [ index, key, hash ]);
options.gas = gasEstimate.mul(1.2).toFixed(0); } else {
return contractInstance.setMeta.postTransaction(options, values); valuesPromise = Promise.resolve([ index, key, value ]);
}
return valuesPromise
.then((values) => {
return contractInstance
.setMeta
.estimateGas(options, values)
.then((gasEstimate) => {
options.gas = gasEstimate.mul(1.2).toFixed(0);
return contractInstance.setMeta.postTransaction(options, values);
});
}) })
.catch((e) => { .catch((e) => {
console.error(`addTokenMeta: #${index} error`, e); console.error(`addTokenMeta: #${index} error`, e);
}); });
}; };
export const addGithubhintURL = (from, key, url) => (dispatch, getState) => { export const addGithubhintURL = (ghhInstance, _options, url) => {
const state = getState(); return urlToHash(ghhInstance, url)
const contractInstance = state.status.githubhint.instance; .then((result) => {
const options = { from }; const { hash, registered } = result;
const values = [ key, url ];
contractInstance if (registered) {
.hintURL return hash;
.estimateGas(options, values) }
.then((gasEstimate) => {
options.gas = gasEstimate.mul(1.2).toFixed(0); const options = { from: _options.from };
return contractInstance.hintURL.postTransaction(options, values); const values = [ hash, url ];
})
.catch((e) => { ghhInstance
console.error('addGithubhintURL error', e); .hintURL
.estimateGas(options, values)
.then((gasEstimate) => {
options.gas = gasEstimate.mul(1.2).toFixed(0);
return ghhInstance.hintURL.postTransaction(options, values);
})
.catch((error) => {
console.error(`registering "${url}" to GHH`, error);
});
return hash;
}); });
}; };

View File

@ -14,13 +14,13 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { HEX_TYPE, ADDRESS_TYPE } from './Inputs/validation'; import { URL_TYPE, ADDRESS_TYPE } from './Inputs/validation';
export const metaDataKeys = [ export const metaDataKeys = [
{ {
label: 'Image', label: 'Image',
value: 'IMG', value: 'IMG',
validation: HEX_TYPE validation: URL_TYPE
}, },
{ {
label: 'Address', label: 'Address',

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const { api } = window.parity; const api = window.parent.secureApi;
export { export {
api api

View File

@ -18,6 +18,45 @@ import { api } from './parity';
import { eip20 as eip20Abi } from '~/contracts/abi'; import { eip20 as eip20Abi } from '~/contracts/abi';
export const INVALID_URL_HASH = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470';
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
/**
* Convert the given URL to a content hash,
* and checks if it is already registered in GHH
*/
export const urlToHash = (ghhInstance, url) => {
if (!url || !url.length) {
return Promise.resolve(null);
}
return api.parity
.hashContent(url)
.catch((error) => {
const message = error.text || error.message || error.toString();
throw new Error(`${message} (${url})`);
})
.then((contentHash) => {
console.log('lookupHash', url, contentHash);
if (contentHash === INVALID_URL_HASH) {
throw new Error(`"${url}" is not a valid URL`);
}
return ghhInstance.entries
.call({}, [contentHash])
.then(([accountSlashRepo, commit, contentHashOwner]) => {
const registered = (contentHashOwner !== ZERO_ADDRESS);
return {
hash: contentHash,
registered
};
});
});
};
export const getTokenTotalSupply = (tokenAddress) => { export const getTokenTotalSupply = (tokenAddress) => {
return api return api
.eth .eth

View File

@ -130,7 +130,7 @@ export default class CreationType extends Component {
<div className={ styles.summary }> <div className={ styles.summary }>
<FormattedMessage <FormattedMessage
id='createAccount.creationType.info' id='createAccount.creationType.info'
defaultMessage='Please select the type of account you want to create. Either create an account via name & password, or import it from a variety of existing sources. From here the wizard will guid you through the process of completing your account creation.' defaultMessage='Please select the type of account you want to create. Either create an account via name & password, or import it from a variety of existing sources. From here the wizard will guide you through the process of completing your account creation.'
/> />
</div> </div>
{ this.renderList(createType) } { this.renderList(createType) }

View File

@ -16,12 +16,16 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { MenuItem } from 'material-ui'; import { Checkbox, MenuItem } from 'material-ui';
import { AddressSelect, Form, Input, Select } from '~/ui'; import { AddressSelect, Form, Input, Select } from '~/ui';
import { validateAbi } from '~/util/validation'; import { validateAbi } from '~/util/validation';
import { parseAbiType } from '~/util/abi'; import { parseAbiType } from '~/util/abi';
const CHECK_STYLE = {
marginTop: '1em'
};
export default class DetailsStep extends Component { export default class DetailsStep extends Component {
static contextTypes = { static contextTypes = {
api: PropTypes.object.isRequired api: PropTypes.object.isRequired
@ -30,8 +34,10 @@ export default class DetailsStep extends Component {
static propTypes = { static propTypes = {
accounts: PropTypes.object.isRequired, accounts: PropTypes.object.isRequired,
onAbiChange: PropTypes.func.isRequired, onAbiChange: PropTypes.func.isRequired,
onAmountChange: PropTypes.func.isRequired,
onCodeChange: PropTypes.func.isRequired, onCodeChange: PropTypes.func.isRequired,
onDescriptionChange: PropTypes.func.isRequired, onDescriptionChange: PropTypes.func.isRequired,
onExtrasChange: PropTypes.func.isRequired,
onFromAddressChange: PropTypes.func.isRequired, onFromAddressChange: PropTypes.func.isRequired,
onInputsChange: PropTypes.func.isRequired, onInputsChange: PropTypes.func.isRequired,
onNameChange: PropTypes.func.isRequired, onNameChange: PropTypes.func.isRequired,
@ -39,11 +45,14 @@ export default class DetailsStep extends Component {
abi: PropTypes.string, abi: PropTypes.string,
abiError: PropTypes.string, abiError: PropTypes.string,
amount: PropTypes.string,
amountError: PropTypes.string,
balances: PropTypes.object, balances: PropTypes.object,
code: PropTypes.string, code: PropTypes.string,
codeError: PropTypes.string, codeError: PropTypes.string,
description: PropTypes.string, description: PropTypes.string,
descriptionError: PropTypes.string, descriptionError: PropTypes.string,
extras: PropTypes.bool,
fromAddress: PropTypes.string, fromAddress: PropTypes.string,
fromAddressError: PropTypes.string, fromAddressError: PropTypes.string,
name: PropTypes.string, name: PropTypes.string,
@ -52,6 +61,7 @@ export default class DetailsStep extends Component {
}; };
static defaultProps = { static defaultProps = {
extras: false,
readOnly: false readOnly: false
}; };
@ -83,7 +93,7 @@ export default class DetailsStep extends Component {
fromAddress, fromAddressError, fromAddress, fromAddressError,
name, nameError, name, nameError,
description, descriptionError, description, descriptionError,
abiError, abiError, extras,
code, codeError code, codeError
} = this.props; } = this.props;
@ -189,10 +199,70 @@ export default class DetailsStep extends Component {
value={ code } value={ code }
/> />
{ this.renderValueInput() }
<div>
<Checkbox
checked={ extras }
label={
<FormattedMessage
id='deployContract.details.advanced.label'
defaultMessage='advanced sending options'
/>
}
onCheck={ this.onCheckExtras }
style={ CHECK_STYLE }
/>
</div>
</Form> </Form>
); );
} }
renderValueInput () {
const { abi, amount, amountError } = this.props;
let payable = false;
try {
const parsedAbi = JSON.parse(abi);
payable = parsedAbi.find((method) => method.type === 'constructor' && method.payable);
} catch (error) {
return null;
}
if (!payable) {
return null;
}
return (
<Input
error={ amountError }
hint={
<FormattedMessage
id='deployContract.details.amount.hint'
defaultMessage='the amount to transfer to the contract'
/>
}
label={
<FormattedMessage
id='deployContract.details.amount.label'
defaultMessage='amount to transfer (in {tag})'
values={ {
tag: 'ETH'
} }
/>
}
min={ 0 }
step={ 0.1 }
type='number'
onChange={ this.onAmountChange }
value={ amount }
/>
);
}
renderContractSelect () { renderContractSelect () {
const { contracts } = this.state; const { contracts } = this.state;
@ -295,6 +365,16 @@ export default class DetailsStep extends Component {
onDescriptionChange(description); onDescriptionChange(description);
} }
onAmountChange = (event, value) => {
const { onAmountChange } = this.props;
onAmountChange(value);
}
onCheckExtras = () => {
this.props.onExtrasChange(!this.props.extras);
}
onAbiChange = (abi) => { onAbiChange = (abi) => {
const { api } = this.context; const { api } = this.context;
const { onAbiChange, onParamsChange, onInputsChange } = this.props; const { onAbiChange, onParamsChange, onInputsChange } = this.props;

View File

@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import BigNumber from 'bignumber.js';
import { pick } from 'lodash'; import { pick } from 'lodash';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
@ -22,12 +23,13 @@ import { connect } from 'react-redux';
import { BusyStep, Button, CompletedStep, CopyToClipboard, GasPriceEditor, IdentityIcon, Portal, TxHash, Warning } from '~/ui'; import { BusyStep, Button, CompletedStep, CopyToClipboard, GasPriceEditor, IdentityIcon, Portal, TxHash, Warning } from '~/ui';
import { CancelIcon, DoneIcon } from '~/ui/Icons'; import { CancelIcon, DoneIcon } from '~/ui/Icons';
import { ERRORS, validateAbi, validateCode, validateName } from '~/util/validation'; import { ERRORS, validateAbi, validateCode, validateName, validatePositiveNumber } from '~/util/validation';
import { deploy, deployEstimateGas } from '~/util/tx'; import { deploy, deployEstimateGas } from '~/util/tx';
import DetailsStep from './DetailsStep'; import DetailsStep from './DetailsStep';
import ParametersStep from './ParametersStep'; import ParametersStep from './ParametersStep';
import ErrorStep from './ErrorStep'; import ErrorStep from './ErrorStep';
import Extras from '../Transfer/Extras';
import styles from './deployContract.css'; import styles from './deployContract.css';
@ -50,6 +52,14 @@ const STEPS = {
/> />
) )
}, },
EXTRAS: {
title: (
<FormattedMessage
id='deployContract.title.extras'
defaultMessage='extra information'
/>
)
},
DEPLOYMENT: { DEPLOYMENT: {
waiting: true, waiting: true,
title: ( title: (
@ -97,12 +107,16 @@ class DeployContract extends Component {
state = { state = {
abi: '', abi: '',
abiError: ERRORS.invalidAbi, abiError: ERRORS.invalidAbi,
amount: '0',
amountValue: new BigNumber(0),
amountError: '',
code: '', code: '',
codeError: ERRORS.invalidCode, codeError: ERRORS.invalidCode,
deployState: '', deployState: '',
deployError: null, deployError: null,
description: '', description: '',
descriptionError: null, descriptionError: null,
extras: false,
fromAddress: Object.keys(this.props.accounts)[0], fromAddress: Object.keys(this.props.accounts)[0],
fromAddressError: null, fromAddressError: null,
name: '', name: '',
@ -144,7 +158,19 @@ class DeployContract extends Component {
const realStepKeys = deployError || rejected const realStepKeys = deployError || rejected
? [] ? []
: Object.keys(STEPS).filter((k) => k !== 'CONTRACT_PARAMETERS' || inputs.length > 0); : Object.keys(STEPS)
.filter((k) => {
if (k === 'CONTRACT_PARAMETERS') {
return inputs.length > 0;
}
if (k === 'EXTRAS') {
return this.state.extras;
}
return true;
});
const realStep = realStepKeys.findIndex((k) => k === step); const realStep = realStepKeys.findIndex((k) => k === step);
const realSteps = realStepKeys.length const realSteps = realStepKeys.length
? realStepKeys.map((k) => STEPS[k]) ? realStepKeys.map((k) => STEPS[k])
@ -207,8 +233,8 @@ class DeployContract extends Component {
} }
renderDialogActions () { renderDialogActions () {
const { deployError, abiError, codeError, nameError, descriptionError, fromAddressError, fromAddress, step } = this.state; const { deployError, abiError, amountError, codeError, nameError, descriptionError, fromAddressError, fromAddress, step } = this.state;
const isValid = !nameError && !fromAddressError && !descriptionError && !abiError && !codeError; const isValid = !nameError && !fromAddressError && !descriptionError && !abiError && !codeError && !amountError;
const cancelBtn = ( const cancelBtn = (
<Button <Button
@ -256,48 +282,69 @@ class DeployContract extends Component {
return closeBtn; return closeBtn;
} }
const createButton = (
<Button
icon={
<IdentityIcon
address={ fromAddress }
button
/>
}
key='create'
label={
<FormattedMessage
id='deployContract.button.create'
defaultMessage='Create'
/>
}
onClick={ this.onDeployStart }
/>
);
const nextButton = (
<Button
disabled={ !isValid }
key='next'
icon={
<IdentityIcon
address={ fromAddress }
button
/>
}
label={
<FormattedMessage
id='deployContract.button.next'
defaultMessage='Next'
/>
}
onClick={ this.onNextStep }
/>
);
const hasParameters = this.state.inputs.length > 0;
const showExtras = this.state.extras;
switch (step) { switch (step) {
case 'CONTRACT_DETAILS': case 'CONTRACT_DETAILS':
return [ return [
cancelBtn, cancelBtn,
<Button hasParameters || showExtras
disabled={ !isValid } ? nextButton
key='next' : createButton
icon={
<IdentityIcon
address={ fromAddress }
button
/>
}
label={
<FormattedMessage
id='deployContract.button.next'
defaultMessage='Next'
/>
}
onClick={ this.onParametersStep }
/>
]; ];
case 'CONTRACT_PARAMETERS': case 'CONTRACT_PARAMETERS':
return [ return [
cancelBtn, cancelBtn,
<Button showExtras
icon={ ? nextButton
<IdentityIcon : createButton
address={ fromAddress } ];
button
/> case 'EXTRAS':
} return [
key='create' cancelBtn,
label={ createButton
<FormattedMessage
id='deployContract.button.create'
defaultMessage='Create'
/>
}
onClick={ this.onDeployStart }
/>
]; ];
case 'DEPLOYMENT': case 'DEPLOYMENT':
@ -344,6 +391,8 @@ class DeployContract extends Component {
{ ...this.state } { ...this.state }
accounts={ accounts } accounts={ accounts }
balances={ balances } balances={ balances }
onAmountChange={ this.onAmountChange }
onExtrasChange={ this.onExtrasChange }
onFromAddressChange={ this.onFromAddressChange } onFromAddressChange={ this.onFromAddressChange }
onDescriptionChange={ this.onDescriptionChange } onDescriptionChange={ this.onDescriptionChange }
onNameChange={ this.onNameChange } onNameChange={ this.onNameChange }
@ -365,6 +414,9 @@ class DeployContract extends Component {
/> />
); );
case 'EXTRAS':
return this.renderExtrasPage();
case 'DEPLOYMENT': case 'DEPLOYMENT':
const body = txhash const body = txhash
? <TxHash hash={ txhash } /> ? <TxHash hash={ txhash } />
@ -411,17 +463,32 @@ class DeployContract extends Component {
} }
} }
renderExtrasPage () {
if (!this.gasStore.histogram) {
return null;
}
return (
<Extras
gasStore={ this.gasStore }
hideData
isEth
/>
);
}
estimateGas = () => { estimateGas = () => {
const { api } = this.context; const { api } = this.context;
const { abiError, abiParsed, code, codeError, fromAddress, fromAddressError, params } = this.state; const { abiError, abiParsed, amountValue, amountError, code, codeError, fromAddress, fromAddressError, params } = this.state;
if (abiError || codeError || fromAddressError) { if (abiError || codeError || fromAddressError || amountError) {
return; return;
} }
const options = { const options = {
data: code, data: code,
from: fromAddress from: fromAddress,
value: amountValue
}; };
const contract = api.newContract(abiParsed); const contract = api.newContract(abiParsed);
@ -437,6 +504,19 @@ class DeployContract extends Component {
}); });
} }
onNextStep = () => {
switch (this.state.step) {
case 'CONTRACT_DETAILS':
return this.onParametersStep();
case 'CONTRACT_PARAMETERS':
return this.onExtrasStep();
default:
console.warn('wrong call of "onNextStep" from', this.state.step);
}
}
onParametersStep = () => { onParametersStep = () => {
const { inputs } = this.state; const { inputs } = this.state;
@ -444,6 +524,14 @@ class DeployContract extends Component {
return this.setState({ step: 'CONTRACT_PARAMETERS' }); return this.setState({ step: 'CONTRACT_PARAMETERS' });
} }
return this.onExtrasStep();
}
onExtrasStep = () => {
if (this.state.extras) {
return this.setState({ step: 'EXTRAS' });
}
return this.onDeployStart(); return this.onDeployStart();
} }
@ -488,10 +576,24 @@ class DeployContract extends Component {
this.setState(validateCode(code), this.estimateGas); this.setState(validateCode(code), this.estimateGas);
} }
onAmountChange = (amount) => {
const { numberError } = validatePositiveNumber(amount);
const nextAmountValue = numberError
? new BigNumber(0)
: this.context.api.util.toWei(amount);
this.gasStore.setEthValue(nextAmountValue);
this.setState({ amount, amountValue: nextAmountValue, amountError: numberError }, this.estimateGas);
}
onExtrasChange = (extras) => {
this.setState({ extras });
}
onDeployStart = () => { onDeployStart = () => {
const { api, store } = this.context; const { api, store } = this.context;
const { source } = this.props; const { source } = this.props;
const { abiParsed, code, description, name, params, fromAddress } = this.state; const { abiParsed, amountValue, code, description, name, params, fromAddress } = this.state;
const metadata = { const metadata = {
abi: abiParsed, abi: abiParsed,
@ -503,16 +605,17 @@ class DeployContract extends Component {
source source
}; };
const options = { const options = this.gasStore.overrideTransaction({
data: code, data: code,
from: fromAddress from: fromAddress,
}; value: amountValue
});
this.setState({ step: 'DEPLOYMENT' }); this.setState({ step: 'DEPLOYMENT' });
const contract = api.newContract(abiParsed); const contract = api.newContract(abiParsed);
deploy(contract, options, params, metadata, this.onDeploymentState) deploy(contract, options, params, metadata, this.onDeploymentState, true)
.then((address) => { .then((address) => {
// No contract address given, might need some confirmations // No contract address given, might need some confirmations
// from the wallet owners... // from the wallet owners...

View File

@ -49,7 +49,7 @@ export default class FirstRun extends Component {
defaultMessage='As part of a new installation, the next few steps will guide you through the process of setting up you Parity instance and your associated accounts. Our aim is to make it as simple as possible and to get you up and running in record-time, so please bear with us. Once completed you will have -' defaultMessage='As part of a new installation, the next few steps will guide you through the process of setting up you Parity instance and your associated accounts. Our aim is to make it as simple as possible and to get you up and running in record-time, so please bear with us. Once completed you will have -'
/> />
</p> </p>
<p> <div>
<ul> <ul>
<li> <li>
<FormattedMessage <FormattedMessage
@ -70,7 +70,7 @@ export default class FirstRun extends Component {
/> />
</li> </li>
</ul> </ul>
</p> </div>
<p> <p>
<FormattedMessage <FormattedMessage
id='firstRun.welcome.next' id='firstRun.welcome.next'

View File

@ -24,7 +24,7 @@ import { nullableProptype } from '~/util/proptypes';
import TokenSelect from './tokenSelect'; import TokenSelect from './tokenSelect';
import styles from '../transfer.css'; import styles from '../transfer.css';
const CHECK_STYLE = { export const CHECK_STYLE = {
position: 'absolute', position: 'absolute',
top: '38px', top: '38px',
left: '1em' left: '1em'

View File

@ -25,12 +25,17 @@ export default class Extras extends Component {
static propTypes = { static propTypes = {
data: PropTypes.string, data: PropTypes.string,
dataError: PropTypes.string, dataError: PropTypes.string,
hideData: PropTypes.bool,
gasStore: PropTypes.object.isRequired, gasStore: PropTypes.object.isRequired,
isEth: PropTypes.bool, isEth: PropTypes.bool,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func,
total: PropTypes.string, total: PropTypes.string,
totalError: PropTypes.string totalError: PropTypes.string
} };
static defaultProps = {
hideData: false
};
render () { render () {
const { gasStore, onChange } = this.props; const { gasStore, onChange } = this.props;
@ -49,9 +54,9 @@ export default class Extras extends Component {
} }
renderData () { renderData () {
const { isEth, data, dataError } = this.props; const { isEth, data, dataError, hideData } = this.props;
if (!isEth) { if (!isEth || hideData) {
return null; return null;
} }

View File

@ -92,6 +92,26 @@ export default class SecureApi extends Api {
return this._transport.token; return this._transport.token;
} }
/**
* Configure the current API with the given values
* (`signerPort`, `dappsInterface`, `dappsPort`, ...)
*/
configure (configuration) {
const { dappsInterface, dappsPort, signerPort } = configuration;
if (dappsInterface) {
this._dappsInterface = dappsInterface;
}
if (dappsPort) {
this._dappsPort = dappsPort;
}
if (signerPort) {
this._signerPort = signerPort;
}
}
connect () { connect () {
if (this._isConnecting) { if (this._isConnecting) {
return; return;

View File

@ -81,6 +81,7 @@ export default class Input extends Component {
tabIndex: PropTypes.number, tabIndex: PropTypes.number,
type: PropTypes.string, type: PropTypes.string,
submitOnBlur: PropTypes.bool, submitOnBlur: PropTypes.bool,
step: PropTypes.number,
style: PropTypes.object, style: PropTypes.object,
value: PropTypes.oneOfType([ value: PropTypes.oneOfType([
PropTypes.number, PropTypes.number,
@ -124,7 +125,7 @@ export default class Input extends Component {
render () { render () {
const { value } = this.state; const { value } = this.state;
const { autoFocus, children, className, hideUnderline, disabled, error, focused, label } = this.props; const { autoFocus, children, className, hideUnderline, disabled, error, focused, label } = this.props;
const { hint, onClick, multiLine, rows, type, min, max, style, tabIndex } = this.props; const { hint, onClick, multiLine, rows, type, min, max, step, style, tabIndex } = this.props;
const readOnly = this.props.readOnly || disabled; const readOnly = this.props.readOnly || disabled;
@ -179,6 +180,7 @@ export default class Input extends Component {
readOnly={ readOnly } readOnly={ readOnly }
ref='input' ref='input'
rows={ rows } rows={ rows }
step={ step }
style={ textFieldStyle } style={ textFieldStyle }
tabIndex={ tabIndex } tabIndex={ tabIndex }
type={ type || 'text' } type={ type || 'text' }

View File

@ -107,7 +107,7 @@ class MethodDecoding extends Component {
renderGas () { renderGas () {
const { historic, transaction } = this.props; const { historic, transaction } = this.props;
const { gas, gasPrice } = transaction; const { gas, gasPrice, value } = transaction;
if (!gas || !gasPrice) { if (!gas || !gasPrice) {
return null; return null;
@ -126,9 +126,9 @@ class MethodDecoding extends Component {
/> />
</span> </span>
); );
const gasProvidedEth = ( const totalEthValue = (
<span className={ styles.highlight }> <span className={ styles.highlight }>
{ this.renderEtherValue(gas.mul(gasPrice)) } { this.renderEtherValue(gas.mul(gasPrice).plus(value || 0)) }
</span> </span>
); );
const gasUsed = transaction.gasUsed const gasUsed = transaction.gasUsed
@ -149,12 +149,12 @@ class MethodDecoding extends Component {
<div className={ styles.gasDetails }> <div className={ styles.gasDetails }>
<FormattedMessage <FormattedMessage
id='ui.methodDecoding.txValues' id='ui.methodDecoding.txValues'
defaultMessage='{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} for a total transaction value of {gasProvidedEth}' defaultMessage='{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} for a total transaction value of {totalEthValue}'
values={ { values={ {
historic, historic,
gasProvided, gasProvided,
gasProvidedEth, gasUsed,
gasUsed totalEthValue
} } } }
/> />
{ this.renderMinBlock() } { this.renderMinBlock() }
@ -349,6 +349,7 @@ class MethodDecoding extends Component {
renderDeploy () { renderDeploy () {
const { historic, transaction } = this.props; const { historic, transaction } = this.props;
const { methodInputs } = this.state; const { methodInputs } = this.state;
const { value } = transaction;
if (!historic) { if (!historic) {
return ( return (
@ -357,6 +358,19 @@ class MethodDecoding extends Component {
id='ui.methodDecoding.deploy.willDeploy' id='ui.methodDecoding.deploy.willDeploy'
defaultMessage='Will deploy a contract' defaultMessage='Will deploy a contract'
/> />
{
value && value.gt(0)
? (
<FormattedMessage
id='ui.methodDecoding.deploy.withValue'
defaultMessage=', sending {value}'
values={ {
value: this.renderEtherValue(value)
} }
/>
)
: null
}
</div> </div>
); );
} }

View File

@ -51,7 +51,7 @@ $popoverZ: 3600;
left: 0; left: 0;
right: 0; right: 0;
opacity: 0.25; opacity: 0.25;
z-index: 0; z-index: -1;
} }
.overlay { .overlay {

View File

@ -18,6 +18,7 @@ import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import ReactPortal from 'react-portal'; import ReactPortal from 'react-portal';
import keycode from 'keycode'; import keycode from 'keycode';
import { noop } from 'lodash';
import { nodeOrStringProptype } from '~/util/proptypes'; import { nodeOrStringProptype } from '~/util/proptypes';
import { CloseIcon } from '~/ui/Icons'; import { CloseIcon } from '~/ui/Icons';
@ -29,7 +30,6 @@ import styles from './portal.css';
export default class Portal extends Component { export default class Portal extends Component {
static propTypes = { static propTypes = {
onClose: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired, open: PropTypes.bool.isRequired,
activeStep: PropTypes.number, activeStep: PropTypes.number,
busy: PropTypes.bool, busy: PropTypes.bool,
@ -45,11 +45,16 @@ export default class Portal extends Component {
isChildModal: PropTypes.bool, isChildModal: PropTypes.bool,
isSmallModal: PropTypes.bool, isSmallModal: PropTypes.bool,
onClick: PropTypes.func, onClick: PropTypes.func,
onClose: PropTypes.func,
onKeyDown: PropTypes.func, onKeyDown: PropTypes.func,
steps: PropTypes.array, steps: PropTypes.array,
title: nodeOrStringProptype() title: nodeOrStringProptype()
}; };
static defaultProps = {
onClose: noop
};
componentDidMount () { componentDidMount () {
this.setBodyOverflow(this.props.open); this.setBodyOverflow(this.props.open);
} }

View File

@ -44,6 +44,7 @@ $widthExpanded: 42%;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
flex: 0 1 $widthNormal; flex: 0 1 $widthNormal;
max-width: $widthNormal;
opacity: 0.85; opacity: 0.85;
padding: 0.25em; padding: 0.25em;

View File

@ -73,7 +73,7 @@ export function postTransaction (_func, _options, _values = []) {
}); });
} }
export function deploy (contract, _options, values, metadata = {}, statecb = () => {}) { export function deploy (contract, _options, values, metadata = {}, statecb = () => {}, skipGasEstimate = false) {
const options = { ..._options }; const options = { ..._options };
const { api } = contract; const { api } = contract;
const address = options.from; const address = options.from;
@ -82,16 +82,27 @@ export function deploy (contract, _options, values, metadata = {}, statecb = ()
.isWallet(api, address) .isWallet(api, address)
.then((isWallet) => { .then((isWallet) => {
if (!isWallet) { if (!isWallet) {
return contract.deploy(options, values, statecb); return contract.deploy(options, values, statecb, skipGasEstimate);
} }
statecb(null, { state: 'estimateGas' }); let gasEstPromise;
return deployEstimateGas(contract, options, values) if (skipGasEstimate) {
.then(([gasEst, gas]) => { gasEstPromise = Promise.resolve(null);
options.gas = gas.toFixed(0); } else {
statecb(null, { state: 'estimateGas' });
statecb(null, { state: 'postTransaction', gas }); gasEstPromise = deployEstimateGas(contract, options, values)
.then(([gasEst, gas]) => gas);
}
return gasEstPromise
.then((gas) => {
if (gas) {
options.gas = gas.toFixed(0);
}
statecb(null, { state: 'postTransaction', gas: options.gas });
return WalletsUtils.getDeployArgs(contract, options, values); return WalletsUtils.getDeployArgs(contract, options, values);
}) })

View File

@ -17,12 +17,20 @@
import { action, observable } from 'mobx'; import { action, observable } from 'mobx';
import store from 'store'; import store from 'store';
const OLD_LS_FIRST_RUN_KEY = 'showFirstRun';
const LS_FIRST_RUN_KEY = '_parity::showFirstRun';
export default class Store { export default class Store {
@observable firstrunVisible = false; @observable firstrunVisible = false;
constructor (api) { constructor (api) {
// Migrate the old key to the new one
this._migrateStore();
this._api = api; this._api = api;
this.firstrunVisible = store.get('showFirstRun'); // Show the first run if it hasn't been shown before
// (thus an undefined value)
this.firstrunVisible = store.get(LS_FIRST_RUN_KEY) === undefined;
this._checkAccounts(); this._checkAccounts();
} }
@ -33,16 +41,41 @@ export default class Store {
@action toggleFirstrun = (visible = false) => { @action toggleFirstrun = (visible = false) => {
this.firstrunVisible = visible; this.firstrunVisible = visible;
store.set('showFirstRun', !!visible);
// There's no need to write to storage that the
// First Run should be visible
if (!visible) {
store.set(LS_FIRST_RUN_KEY, !!visible);
}
}
/**
* Migrate the old LocalStorage ket format
* to the new one
*/
_migrateStore () {
const oldValue = store.get(OLD_LS_FIRST_RUN_KEY);
const newValue = store.get(LS_FIRST_RUN_KEY);
if (newValue === undefined && oldValue !== undefined) {
store.set(LS_FIRST_RUN_KEY, oldValue);
store.remove(OLD_LS_FIRST_RUN_KEY);
}
} }
_checkAccounts () { _checkAccounts () {
this._api.parity return Promise
.allAccountsInfo() .all([
.then((info) => { this._api.parity.listVaults(),
this._api.parity.allAccountsInfo()
])
.then(([ vaults, info ]) => {
const accounts = Object.keys(info).filter((address) => info[address].uuid); const accounts = Object.keys(info).filter((address) => info[address].uuid);
// Has accounts if any vaults or accounts
const hasAccounts = (accounts && accounts.length > 0) || (vaults && vaults.length > 0);
this.toggleFirstrun(this.firstrunVisible || !accounts || !accounts.length); // Show First Run if no accounts and no vaults
this.toggleFirstrun(this.firstrunVisible || !hasAccounts);
}) })
.catch((error) => { .catch((error) => {
console.error('checkAccounts', error); console.error('checkAccounts', error);

View File

@ -32,7 +32,8 @@
"description": "A registry of transactable tokens on the network", "description": "A registry of transactable tokens on the network",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "1.0.0", "version": "1.0.0",
"visible": true "visible": true,
"secure": true
}, },
{ {
"id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46", "id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46",

View File

@ -105,7 +105,7 @@ class WriteContract extends Component {
className={ styles.editor } className={ styles.editor }
style={ { flex: `${size}%` } } style={ { flex: `${size}%` } }
> >
<h2>asd{ this.renderTitle() }</h2> <h2>{ this.renderTitle() }</h2>
<Editor <Editor
ref='editor' ref='editor'

View File

@ -53,6 +53,9 @@ pub struct Params {
/// See `CommonParams` docs. /// See `CommonParams` docs.
#[serde(rename="eip98Transition")] #[serde(rename="eip98Transition")]
pub eip98_transition: Option<Uint>, pub eip98_transition: Option<Uint>,
/// See `CommonParams` docs.
#[serde(rename="validateReceipts")]
pub validate_receipts: Option<bool>,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -85,6 +85,7 @@ engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
force_sealing = true force_sealing = true
reseal_on_txs = "all" reseal_on_txs = "all"
reseal_min_period = 4000 reseal_min_period = 4000
reseal_max_period = 60000
work_queue_size = 20 work_queue_size = 20
relay_set = "cheap" relay_set = "cheap"
usd_per_tx = "0.0025" usd_per_tx = "0.0025"

View File

@ -50,6 +50,7 @@ engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
force_sealing = true force_sealing = true
reseal_on_txs = "all" reseal_on_txs = "all"
reseal_min_period = 4000 reseal_min_period = 4000
reseal_max_period = 60000
price_update_period = "hourly" price_update_period = "hourly"
tx_queue_size = 1024 tx_queue_size = 1024
tx_queue_gas = "auto" tx_queue_gas = "auto"

View File

@ -224,6 +224,8 @@ usage! {
or |c: &Config| otry!(c.mining).reseal_on_txs.clone(), or |c: &Config| otry!(c.mining).reseal_on_txs.clone(),
flag_reseal_min_period: u64 = 2000u64, flag_reseal_min_period: u64 = 2000u64,
or |c: &Config| otry!(c.mining).reseal_min_period.clone(), or |c: &Config| otry!(c.mining).reseal_min_period.clone(),
flag_reseal_max_period: u64 = 120000u64,
or |c: &Config| otry!(c.mining).reseal_max_period.clone(),
flag_work_queue_size: usize = 20usize, flag_work_queue_size: usize = 20usize,
or |c: &Config| otry!(c.mining).work_queue_size.clone(), or |c: &Config| otry!(c.mining).work_queue_size.clone(),
flag_tx_gas_limit: Option<String> = None, flag_tx_gas_limit: Option<String> = None,
@ -460,6 +462,7 @@ struct Mining {
force_sealing: Option<bool>, force_sealing: Option<bool>,
reseal_on_txs: Option<String>, reseal_on_txs: Option<String>,
reseal_min_period: Option<u64>, reseal_min_period: Option<u64>,
reseal_max_period: Option<u64>,
work_queue_size: Option<usize>, work_queue_size: Option<usize>,
tx_gas_limit: Option<String>, tx_gas_limit: Option<String>,
tx_time_limit: Option<u64>, tx_time_limit: Option<u64>,
@ -701,6 +704,7 @@ mod tests {
flag_force_sealing: true, flag_force_sealing: true,
flag_reseal_on_txs: "all".into(), flag_reseal_on_txs: "all".into(),
flag_reseal_min_period: 4000u64, flag_reseal_min_period: 4000u64,
flag_reseal_max_period: 60000u64,
flag_work_queue_size: 20usize, flag_work_queue_size: 20usize,
flag_tx_gas_limit: Some("6283184".into()), flag_tx_gas_limit: Some("6283184".into()),
flag_tx_time_limit: Some(100u64), flag_tx_time_limit: Some(100u64),
@ -900,6 +904,7 @@ mod tests {
force_sealing: Some(true), force_sealing: Some(true),
reseal_on_txs: Some("all".into()), reseal_on_txs: Some("all".into()),
reseal_min_period: Some(4000), reseal_min_period: Some(4000),
reseal_max_period: Some(60000),
work_queue_size: None, work_queue_size: None,
relay_set: None, relay_set: None,
usd_per_tx: None, usd_per_tx: None,

View File

@ -224,6 +224,9 @@ Sealing/Mining Options:
--reseal-min-period MS Specify the minimum time between reseals from --reseal-min-period MS Specify the minimum time between reseals from
incoming transactions. MS is time measured in incoming transactions. MS is time measured in
milliseconds (default: {flag_reseal_min_period}). milliseconds (default: {flag_reseal_min_period}).
--reseal-max-period MS Specify the maximum time since last block to enable
force-sealing. MS is time measured in
milliseconds (default: {flag_reseal_max_period}).
--work-queue-size ITEMS Specify the number of historical work packages --work-queue-size ITEMS Specify the number of historical work packages
which are kept cached lest a solution is found for which are kept cached lest a solution is found for
them later. High values take more memory but result them later. High values take more memory but result

View File

@ -522,6 +522,7 @@ impl Configuration {
tx_queue_strategy: to_queue_strategy(&self.args.flag_tx_queue_strategy)?, tx_queue_strategy: to_queue_strategy(&self.args.flag_tx_queue_strategy)?,
pending_set: to_pending_set(&self.args.flag_relay_set)?, pending_set: to_pending_set(&self.args.flag_relay_set)?,
reseal_min_period: Duration::from_millis(reseal_min_period), reseal_min_period: Duration::from_millis(reseal_min_period),
reseal_max_period: Duration::from_millis(self.args.flag_reseal_max_period),
work_queue_size: self.args.flag_work_queue_size, work_queue_size: self.args.flag_work_queue_size,
enable_resubmission: !self.args.flag_remove_solved, enable_resubmission: !self.args.flag_remove_solved,
tx_queue_banning: match self.args.flag_tx_time_limit { tx_queue_banning: match self.args.flag_tx_time_limit {

View File

@ -32,7 +32,6 @@ mod codes {
pub const NO_WORK: i64 = -32001; pub const NO_WORK: i64 = -32001;
pub const NO_AUTHOR: i64 = -32002; pub const NO_AUTHOR: i64 = -32002;
pub const NO_NEW_WORK: i64 = -32003; pub const NO_NEW_WORK: i64 = -32003;
pub const NOT_ENOUGH_DATA: i64 = -32006;
pub const UNKNOWN_ERROR: i64 = -32009; pub const UNKNOWN_ERROR: i64 = -32009;
pub const TRANSACTION_ERROR: i64 = -32010; pub const TRANSACTION_ERROR: i64 = -32010;
pub const EXECUTION_ERROR: i64 = -32015; pub const EXECUTION_ERROR: i64 = -32015;
@ -41,9 +40,6 @@ mod codes {
pub const ACCOUNT_LOCKED: i64 = -32020; pub const ACCOUNT_LOCKED: i64 = -32020;
pub const PASSWORD_INVALID: i64 = -32021; pub const PASSWORD_INVALID: i64 = -32021;
pub const ACCOUNT_ERROR: i64 = -32023; pub const ACCOUNT_ERROR: i64 = -32023;
pub const SIGNER_DISABLED: i64 = -32030;
pub const DAPPS_DISABLED: i64 = -32031;
pub const NETWORK_DISABLED: i64 = -32035;
pub const REQUEST_REJECTED: i64 = -32040; pub const REQUEST_REJECTED: i64 = -32040;
pub const REQUEST_REJECTED_LIMIT: i64 = -32041; pub const REQUEST_REJECTED_LIMIT: i64 = -32041;
pub const REQUEST_NOT_FOUND: i64 = -32042; pub const REQUEST_NOT_FOUND: i64 = -32042;
@ -174,9 +170,9 @@ pub fn no_author() -> Error {
pub fn not_enough_data() -> Error { pub fn not_enough_data() -> Error {
Error { Error {
code: ErrorCode::ServerError(codes::NOT_ENOUGH_DATA), code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "The node does not have enough data to compute the given statistic.".into(), message: "The node does not have enough data to compute the given statistic.".into(),
data: None data: None,
} }
} }
@ -190,25 +186,25 @@ pub fn token(e: String) -> Error {
pub fn signer_disabled() -> Error { pub fn signer_disabled() -> Error {
Error { Error {
code: ErrorCode::ServerError(codes::SIGNER_DISABLED), code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "Trusted Signer is disabled. This API is not available.".into(), message: "Trusted Signer is disabled. This API is not available.".into(),
data: None data: None,
} }
} }
pub fn dapps_disabled() -> Error { pub fn dapps_disabled() -> Error {
Error { Error {
code: ErrorCode::ServerError(codes::DAPPS_DISABLED), code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "Dapps Server is disabled. This API is not available.".into(), message: "Dapps Server is disabled. This API is not available.".into(),
data: None data: None,
} }
} }
pub fn network_disabled() -> Error { pub fn network_disabled() -> Error {
Error { Error {
code: ErrorCode::ServerError(codes::NETWORK_DISABLED), code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "Network is disabled or not yet up.".into(), message: "Network is disabled or not yet up.".into(),
data: None data: None,
} }
} }
@ -321,7 +317,7 @@ pub fn from_call_error(error: CallError) -> Error {
pub fn unknown_block() -> Error { pub fn unknown_block() -> Error {
Error { Error {
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), code: ErrorCode::InvalidParams,
message: "Unknown block number".into(), message: "Unknown block number".into(),
data: None, data: None,
} }

View File

@ -0,0 +1,43 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Weak;
use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
use ethcore::transaction::{Transaction, SignedTransaction, Action};
use jsonrpc_core::Error;
use v1::helpers::CallRequest;
use v1::helpers::dispatch::default_gas_price;
pub fn sign_call<B: MiningBlockChainClient, M: MinerService>(
client: &Weak<B>,
miner: &Weak<M>,
request: CallRequest,
) -> Result<SignedTransaction, Error> {
let client = take_weak!(client);
let miner = take_weak!(miner);
let from = request.from.unwrap_or(0.into());
Ok(Transaction {
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
action: request.to.map_or(Action::Create, Action::Call),
gas: request.gas.unwrap_or(50_000_000.into()),
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)),
value: request.value.unwrap_or(0.into()),
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
}.fake_sign(from))
}

View File

@ -19,6 +19,7 @@ pub mod errors;
pub mod block_import; pub mod block_import;
pub mod dispatch; pub mod dispatch;
pub mod fake_sign;
pub mod informant; pub mod informant;
pub mod oneshot; pub mod oneshot;

View File

@ -23,7 +23,7 @@ use std::sync::{Arc, Weak};
use futures::{self, future, BoxFuture, Future}; use futures::{self, future, BoxFuture, Future};
use rlp::{self, UntrustedRlp, View}; use rlp::{self, UntrustedRlp, View};
use time::get_time; use time::get_time;
use util::{H160, H256, Address, U256, H64, Uint}; use util::{H160, H256, Address, U256, H64};
use util::sha3::Hashable; use util::sha3::Hashable;
use util::Mutex; use util::Mutex;
@ -36,14 +36,14 @@ use ethcore::filter::Filter as EthcoreFilter;
use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber};
use ethcore::log_entry::LogEntry; use ethcore::log_entry::LogEntry;
use ethcore::miner::{MinerService, ExternalMinerService}; use ethcore::miner::{MinerService, ExternalMinerService};
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; use ethcore::transaction::SignedTransaction;
use ethcore::snapshot::SnapshotService; use ethcore::snapshot::SnapshotService;
use ethsync::{SyncProvider}; use ethsync::{SyncProvider};
use jsonrpc_core::Error; use jsonrpc_core::Error;
use jsonrpc_macros::Trailing; use jsonrpc_macros::Trailing;
use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; use v1::helpers::{errors, limit_logs, fake_sign};
use v1::helpers::dispatch::{Dispatcher, FullDispatcher, default_gas_price}; use v1::helpers::dispatch::{Dispatcher, FullDispatcher, default_gas_price};
use v1::helpers::block_import::is_major_importing; use v1::helpers::block_import::is_major_importing;
use v1::traits::Eth; use v1::traits::Eth;
@ -222,19 +222,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
Ok(Some(block)) Ok(Some(block))
} }
fn sign_call(&self, request: CRequest) -> Result<SignedTransaction, Error> {
let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
let from = request.from.unwrap_or(Address::zero());
Ok(EthTransaction {
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
action: request.to.map_or(Action::Create, Action::Call),
gas: request.gas.unwrap_or(U256::from(50_000_000)),
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)),
value: request.value.unwrap_or_else(U256::zero),
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
}.fake_sign(from))
}
fn dapp_accounts(&self, dapp: DappId) -> Result<Vec<H160>, Error> { fn dapp_accounts(&self, dapp: DappId) -> Result<Vec<H160>, Error> {
let store = take_weak!(self.accounts); let store = take_weak!(self.accounts);
store store
@ -654,7 +641,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
fn call(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes, Error> { fn call(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes, Error> {
let request = CallRequest::into(request); let request = CallRequest::into(request);
let signed = match self.sign_call(request) { let signed = match fake_sign::sign_call(&self.client, &self.miner, request) {
Ok(signed) => signed, Ok(signed) => signed,
Err(e) => return future::err(e).boxed(), Err(e) => return future::err(e).boxed(),
}; };
@ -672,7 +659,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
fn estimate_gas(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> { fn estimate_gas(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
let request = CallRequest::into(request); let request = CallRequest::into(request);
let signed = match self.sign_call(request) { let signed = match fake_sign::sign_call(&self.client, &self.miner, request) {
Ok(signed) => signed, Ok(signed) => signed,
Err(e) => return future::err(e).boxed(), Err(e) => return future::err(e).boxed(),
}; };

View File

@ -27,15 +27,15 @@ use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, By
pub struct TracesClient; pub struct TracesClient;
impl Traces for TracesClient { impl Traces for TracesClient {
fn filter(&self, _filter: TraceFilter) -> Result<Vec<LocalizedTrace>, Error> { fn filter(&self, _filter: TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Err(errors::light_unimplemented(None)) Err(errors::light_unimplemented(None))
} }
fn block_traces(&self, _block_number: BlockNumber) -> Result<Vec<LocalizedTrace>, Error> { fn block_traces(&self, _block_number: BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Err(errors::light_unimplemented(None)) Err(errors::light_unimplemented(None))
} }
fn transaction_traces(&self, _transaction_hash: H256) -> Result<Vec<LocalizedTrace>, Error> { fn transaction_traces(&self, _transaction_hash: H256) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Err(errors::light_unimplemented(None)) Err(errors::light_unimplemented(None))
} }
@ -43,15 +43,15 @@ impl Traces for TracesClient {
Err(errors::light_unimplemented(None)) Err(errors::light_unimplemented(None))
} }
fn call(&self, _request: CallRequest, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> { fn call(&self, _request: CallRequest, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
Err(errors::light_unimplemented(None)) Err(errors::light_unimplemented(None))
} }
fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> { fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
Err(errors::light_unimplemented(None)) Err(errors::light_unimplemented(None))
} }
fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec<String>) -> Result<Option<TraceResults>, Error> { fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec<String>) -> Result<TraceResults, Error> {
Err(errors::light_unimplemented(None)) Err(errors::light_unimplemented(None))
} }
} }

View File

@ -19,14 +19,14 @@
use std::sync::{Weak, Arc}; use std::sync::{Weak, Arc};
use rlp::{UntrustedRlp, View}; use rlp::{UntrustedRlp, View};
use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId}; use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId};
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; use ethcore::transaction::SignedTransaction;
use jsonrpc_core::Error; use jsonrpc_core::Error;
use jsonrpc_macros::Trailing; use jsonrpc_macros::Trailing;
use v1::traits::Traces; use v1::traits::Traces;
use v1::helpers::{errors, CallRequest as CRequest}; use v1::helpers::{errors, fake_sign};
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256}; use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics { fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
@ -38,12 +38,12 @@ fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
} }
/// Traces api implementation. /// Traces api implementation.
pub struct TracesClient<C, M> where C: BlockChainClient, M: MinerService { pub struct TracesClient<C, M> {
client: Weak<C>, client: Weak<C>,
miner: Weak<M>, miner: Weak<M>,
} }
impl<C, M> TracesClient<C, M> where C: BlockChainClient, M: MinerService { impl<C, M> TracesClient<C, M> {
/// Creates new Traces client. /// Creates new Traces client.
pub fn new(client: &Arc<C>, miner: &Arc<M>) -> Self { pub fn new(client: &Arc<C>, miner: &Arc<M>) -> Self {
TracesClient { TracesClient {
@ -51,86 +51,59 @@ impl<C, M> TracesClient<C, M> where C: BlockChainClient, M: MinerService {
miner: Arc::downgrade(miner), miner: Arc::downgrade(miner),
} }
} }
// TODO: share with eth.rs
fn sign_call(&self, request: CRequest) -> Result<SignedTransaction, Error> {
let client = take_weak!(self.client);
let miner = take_weak!(self.miner);
let from = request.from.unwrap_or(0.into());
Ok(EthTransaction {
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
action: request.to.map_or(Action::Create, Action::Call),
gas: request.gas.unwrap_or(50_000_000.into()),
gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()),
value: request.value.unwrap_or(0.into()),
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
}.fake_sign(from))
}
} }
impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M: MinerService + 'static { impl<C, M> Traces for TracesClient<C, M> where C: MiningBlockChainClient + 'static, M: MinerService + 'static {
fn filter(&self, filter: TraceFilter) -> Result<Vec<LocalizedTrace>, Error> { fn filter(&self, filter: TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, Error> {
let client = take_weak!(self.client); Ok(take_weak!(self.client).filter_traces(filter.into())
let traces = client.filter_traces(filter.into()); .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect()))
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
Ok(traces)
} }
fn block_traces(&self, block_number: BlockNumber) -> Result<Vec<LocalizedTrace>, Error> { fn block_traces(&self, block_number: BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error> {
let client = take_weak!(self.client); Ok(take_weak!(self.client).block_traces(block_number.into())
let traces = client.block_traces(block_number.into()); .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect()))
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
Ok(traces)
} }
fn transaction_traces(&self, transaction_hash: H256) -> Result<Vec<LocalizedTrace>, Error> { fn transaction_traces(&self, transaction_hash: H256) -> Result<Option<Vec<LocalizedTrace>>, Error> {
let client = take_weak!(self.client); Ok(take_weak!(self.client).transaction_traces(TransactionId::Hash(transaction_hash.into()))
let traces = client.transaction_traces(TransactionId::Hash(transaction_hash.into())); .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect()))
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
Ok(traces)
} }
fn trace(&self, transaction_hash: H256, address: Vec<Index>) -> Result<Option<LocalizedTrace>, Error> { fn trace(&self, transaction_hash: H256, address: Vec<Index>) -> Result<Option<LocalizedTrace>, Error> {
let client = take_weak!(self.client);
let id = TraceId { let id = TraceId {
transaction: TransactionId::Hash(transaction_hash.into()), transaction: TransactionId::Hash(transaction_hash.into()),
address: address.into_iter().map(|i| i.value()).collect() address: address.into_iter().map(|i| i.value()).collect()
}; };
let trace = client.trace(id);
let trace = trace.map(LocalizedTrace::from);
Ok(trace) Ok(take_weak!(self.client).trace(id)
.map(LocalizedTrace::from))
} }
fn call(&self, request: CallRequest, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> { fn call(&self, request: CallRequest, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
let block = block.0; let block = block.0;
let request = CallRequest::into(request); let request = CallRequest::into(request);
let signed = self.sign_call(request)?; let signed = fake_sign::sign_call(&self.client, &self.miner, request)?;
Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) {
Ok(e) => Some(TraceResults::from(e)), take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags))
_ => None, .map(TraceResults::from)
}) .map_err(errors::from_call_error)
} }
fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> { fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
let block = block.0; let block = block.0;
UntrustedRlp::new(&raw_transaction.into_vec()).as_val() let tx = UntrustedRlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?;
.map_err(|e| errors::invalid_params("Transaction is not valid RLP", e)) let signed = SignedTransaction::new(tx).map_err(errors::from_transaction_error)?;
.and_then(|tx| SignedTransaction::new(tx).map_err(errors::from_transaction_error))
.and_then(|signed| { take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags))
Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) { .map(TraceResults::from)
Ok(e) => Some(TraceResults::from(e)), .map_err(errors::from_call_error)
_ => None,
})
})
} }
fn replay_transaction(&self, transaction_hash: H256, flags: Vec<String>) -> Result<Option<TraceResults>, Error> { fn replay_transaction(&self, transaction_hash: H256, flags: Vec<String>) -> Result<TraceResults, Error> {
Ok(match take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) { take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags))
Ok(e) => Some(TraceResults::from(e)), .map(TraceResults::from)
_ => None, .map_err(errors::from_call_error)
})
} }
} }

View File

@ -64,6 +64,7 @@ fn miner_service(spec: &Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
tx_queue_banning: Banning::Disabled, tx_queue_banning: Banning::Disabled,
pending_set: PendingSet::SealingOrElseQueue, pending_set: PendingSet::SealingOrElseQueue,
reseal_min_period: Duration::from_secs(0), reseal_min_period: Duration::from_secs(0),
reseal_max_period: Duration::from_secs(120),
work_queue_size: 50, work_queue_size: 50,
enable_resubmission: true, enable_resubmission: true,
refuse_service_transactions: false, refuse_service_transactions: false,

View File

@ -901,7 +901,7 @@ fn rpc_eth_send_transaction_with_bad_to() {
"id": 1 "id": 1
}"#; }"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid length."},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: expected a hex-encoded hash with 0x prefix."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
} }

View File

@ -357,7 +357,7 @@ fn rpc_parity_unsigned_transactions_count_when_signer_disabled() {
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
@ -393,7 +393,7 @@ fn rpc_parity_signer_port() {
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
// then // then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));
@ -411,7 +411,7 @@ fn rpc_parity_dapps_port() {
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
// then // then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));
@ -429,7 +429,7 @@ fn rpc_parity_dapps_interface() {
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
// then // then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));

View File

@ -230,7 +230,7 @@ fn should_be_able_to_kill_account() {
let address = accounts[0]; let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_killAccount", "params": ["0xf00baba2f00baba2f00baba2f00baba2f00baba2"], "id": 1}}"#); let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_killAccount", "params": ["0xf00baba2f00baba2f00baba2f00baba2f00baba2"], "id": 1}}"#);
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid length 1, expected a tuple of size 2"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: invalid length 1, expected a tuple of size 2."},"id":1}"#;
let res = tester.io.handle_request_sync(&request); let res = tester.io.handle_request_sync(&request);
assert_eq!(res, Some(response.into())); assert_eq!(res, Some(response.into()));

View File

@ -16,17 +16,17 @@
use std::sync::Arc; use std::sync::Arc;
use ethcore::executed::{CallType, Executed}; use ethcore::executed::{CallType, Executed, CallError};
use ethcore::trace::trace::{Action, Res, Call}; use ethcore::trace::trace::{Action, Res, Call};
use ethcore::trace::LocalizedTrace; use ethcore::trace::LocalizedTrace;
use ethcore::client::{TestBlockChainClient}; use ethcore::client::TestBlockChainClient;
use jsonrpc_core::IoHandler; use jsonrpc_core::IoHandler;
use v1::tests::helpers::{TestMinerService}; use v1::tests::helpers::{TestMinerService};
use v1::{Traces, TracesClient}; use v1::{Traces, TracesClient};
struct Tester { struct Tester {
_client: Arc<TestBlockChainClient>, client: Arc<TestBlockChainClient>,
_miner: Arc<TestMinerService>, _miner: Arc<TestMinerService>,
io: IoHandler, io: IoHandler,
} }
@ -69,7 +69,7 @@ fn io() -> Tester {
io.extend_with(traces.to_delegate()); io.extend_with(traces.to_delegate());
Tester { Tester {
_client: client, client: client,
_miner: miner, _miner: miner,
io: io, io: io,
} }
@ -85,6 +85,17 @@ fn rpc_trace_filter() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test]
fn rpc_trace_filter_missing_trace() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_filter","params": [{}],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test] #[test]
fn rpc_trace_block() { fn rpc_trace_block() {
let tester = io(); let tester = io();
@ -95,6 +106,17 @@ fn rpc_trace_block() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test]
fn rpc_trace_block_missing_traces() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_block","params": ["0x10"],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test] #[test]
fn rpc_trace_transaction() { fn rpc_trace_transaction() {
let tester = io(); let tester = io();
@ -105,6 +127,17 @@ fn rpc_trace_transaction() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test]
fn rpc_trace_transaction_missing_trace() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_transaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005"],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test] #[test]
fn rpc_trace_get() { fn rpc_trace_get() {
let tester = io(); let tester = io();
@ -115,6 +148,16 @@ fn rpc_trace_get() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test]
fn rpc_trace_get_missing_trace() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_get","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["0","0","0"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test] #[test]
fn rpc_trace_call() { fn rpc_trace_call() {
let tester = io(); let tester = io();
@ -125,6 +168,17 @@ fn rpc_trace_call() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test]
fn rpc_trace_call_state_pruned() {
let tester = io();
*tester.client.execution_result.write() = Some(Err(CallError::StatePruned));
let request = r#"{"jsonrpc":"2.0","method":"trace_call","params":[{}, ["stateDiff", "vmTrace", "trace"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test] #[test]
fn rpc_trace_raw_transaction() { fn rpc_trace_raw_transaction() {
let tester = io(); let tester = io();
@ -135,6 +189,17 @@ fn rpc_trace_raw_transaction() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test]
fn rpc_trace_raw_transaction_state_pruned() {
let tester = io();
*tester.client.execution_result.write() = Some(Err(CallError::StatePruned));
let request = r#"{"jsonrpc":"2.0","method":"trace_rawTransaction","params":["0xf869018609184e72a0008276c094d46e8dd67c5d32be8058bb8eb970870f07244567849184e72a801ba0617f39c1a107b63302449c476d96a6cb17a5842fc98ff0c5bcf4d5c4d8166b95a009fdb6097c6196b9bbafc3a59f02f38d91baeef23d0c60a8e4f23c7714cea3a9", ["stateDiff", "vmTrace", "trace"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test] #[test]
fn rpc_trace_replay_transaction() { fn rpc_trace_replay_transaction() {
let tester = io(); let tester = io();
@ -144,3 +209,14 @@ fn rpc_trace_replay_transaction() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test]
fn rpc_trace_replay_transaction_state_pruned() {
let tester = io();
*tester.client.execution_result.write() = Some(Err(CallError::StatePruned));
let request = r#"{"jsonrpc":"2.0","method":"trace_replayTransaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["trace", "stateDiff", "vmTrace"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}

View File

@ -25,7 +25,7 @@ build_rpc_trait! {
pub trait Traces { pub trait Traces {
/// Returns traces matching given filter. /// Returns traces matching given filter.
#[rpc(name = "trace_filter")] #[rpc(name = "trace_filter")]
fn filter(&self, TraceFilter) -> Result<Vec<LocalizedTrace>, Error>; fn filter(&self, TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, Error>;
/// Returns transaction trace at given index. /// Returns transaction trace at given index.
#[rpc(name = "trace_get")] #[rpc(name = "trace_get")]
@ -33,22 +33,22 @@ build_rpc_trait! {
/// Returns all traces of given transaction. /// Returns all traces of given transaction.
#[rpc(name = "trace_transaction")] #[rpc(name = "trace_transaction")]
fn transaction_traces(&self, H256) -> Result<Vec<LocalizedTrace>, Error>; fn transaction_traces(&self, H256) -> Result<Option<Vec<LocalizedTrace>>, Error>;
/// Returns all traces produced at given block. /// Returns all traces produced at given block.
#[rpc(name = "trace_block")] #[rpc(name = "trace_block")]
fn block_traces(&self, BlockNumber) -> Result<Vec<LocalizedTrace>, Error>; fn block_traces(&self, BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error>;
/// Executes the given call and returns a number of possible traces for it. /// Executes the given call and returns a number of possible traces for it.
#[rpc(name = "trace_call")] #[rpc(name = "trace_call")]
fn call(&self, CallRequest, Vec<String>, Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error>; fn call(&self, CallRequest, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
/// Executes the given raw transaction and returns a number of possible traces for it. /// Executes the given raw transaction and returns a number of possible traces for it.
#[rpc(name = "trace_rawTransaction")] #[rpc(name = "trace_rawTransaction")]
fn raw_transaction(&self, Bytes, Vec<String>, Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error>; fn raw_transaction(&self, Bytes, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
/// Executes the transaction with the given hash and returns a number of possible traces for it. /// Executes the transaction with the given hash and returns a number of possible traces for it.
#[rpc(name = "trace_replayTransaction")] #[rpc(name = "trace_replayTransaction")]
fn replay_transaction(&self, H256, Vec<String>) -> Result<Option<TraceResults>, Error>; fn replay_transaction(&self, H256, Vec<String>) -> Result<TraceResults, Error>;
} }
} }

View File

@ -130,7 +130,7 @@ macro_rules! impl_hash {
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error { fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error {
if value.len() < 2 || &value[0..2] != "0x" { if value.len() < 2 || &value[0..2] != "0x" {
return Err(E::custom("Expected hex-encoded hash with 0x prefix.")); return Err(E::custom("expected a hex-encoded hash with 0x prefix"));
} }
if value.len() != 2 + $size * 2 { if value.len() != 2 + $size * 2 {
return Err(E::invalid_length(value.len() - 2, &self)); return Err(E::invalid_length(value.len() - 2, &self));
@ -142,7 +142,7 @@ macro_rules! impl_hash {
result.copy_from_slice(v); result.copy_from_slice(v);
Ok($name(result)) Ok($name(result))
}, },
Err(e) => Err(E::custom(format!("Invalid hex value: {:?}", e))), Err(e) => Err(E::custom(format!("invalid hex value: {:?}", e))),
} }
} }

View File

@ -79,7 +79,7 @@ macro_rules! impl_uint {
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error { fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error {
if value.len() < 2 || &value[0..2] != "0x" { if value.len() < 2 || &value[0..2] != "0x" {
return Err(E::custom("Use hex-encoded numbers with 0x prefix.")) return Err(E::custom("expected a hex-encoded numbers with 0x prefix"))
} }
// 0x + len // 0x + len
@ -87,7 +87,7 @@ macro_rules! impl_uint {
return Err(E::invalid_length(value.len() - 2, &self)); return Err(E::invalid_length(value.len() - 2, &self));
} }
$other::from_str(&value[2..]).map($name).map_err(|e| E::custom(&format!("Invalid hex value: {:?}", e))) $other::from_str(&value[2..]).map($name).map_err(|e| E::custom(&format!("invalid hex value: {:?}", e)))
} }
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: serde::de::Error { fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: serde::de::Error {

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/bash
# Installing KCOV under ubuntu # Installing KCOV under ubuntu
# https://users.rust-lang.org/t/tutorial-how-to-collect-test-coverages-for-rust-project/650# # https://users.rust-lang.org/t/tutorial-how-to-collect-test-coverages-for-rust-project/650#
### Install deps ### Install deps
@ -24,8 +24,7 @@ fi
cargo test $TARGETS --no-run || exit $? cargo test $TARGETS --no-run || exit $?
KCOV_TARGET="target/cov"
KCOV_TARGET="target/kcov"
KCOV_FLAGS="--verify" KCOV_FLAGS="--verify"
EXCLUDE="/usr/lib,\ EXCLUDE="/usr/lib,\
/usr/include,\ /usr/include,\
@ -39,17 +38,25 @@ util/src/network/tests,\
ethcore/src/evm/tests,\ ethcore/src/evm/tests,\
ethstore/tests,\ ethstore/tests,\
target/debug/build,\ target/debug/build,\
target/release/build\ target/release/build,\
*.db
" "
rm -rf $KCOV_TARGET rm -rf $KCOV_TARGET
mkdir -p $KCOV_TARGET mkdir -p $KCOV_TARGET
echo "Cover RUST"
for FILE in `find target/debug/deps ! -name "*.*"` for FILE in `find target/debug/deps ! -name "*.*"`
do do
$KCOV --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET $FILE $KCOV --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET $FILE
done done
$KCOV --coveralls-id=${CI_BUILD_ID} --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET target/debug/parity-* $KCOV --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET target/debug/parity-*
echo "Cover JS"
cd js
npm install&&npm run test:coverage
cd ..
codecov
bash <(curl -s https://codecov.io/bash)&&
echo "Uploaded code coverage"
exit 0 exit 0

View File

@ -25,7 +25,7 @@ echo "Homepage: https://ethcore.io" >> $control
echo "Vcs-Git: git://github.com/ethcore/parity.git" >> $control echo "Vcs-Git: git://github.com/ethcore/parity.git" >> $control
echo "Vcs-Browser: https://github.com/ethcore/parity" >> $control echo "Vcs-Browser: https://github.com/ethcore/parity" >> $control
echo "Architecture: $1" >> $control echo "Architecture: $1" >> $control
echo "Depends: libssl1.0.0 (>=1.0.0), libudev-dev" >> $control echo "Depends: libssl1.0.0 (>=1.0.0)" >> $control
echo "Description: Ethereum network client by Ethcore" >> $control echo "Description: Ethereum network client by Ethcore" >> $control
#build .deb package #build .deb package

View File

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
cd docker/hub cd docker/hub
docker build --build-arg BUILD_TAG=$1 --no-cache=true --tag ethcore/parity:$1 . if [ "$1" == "latest" ]; then DOCKER_BUILD_TAG="beta-release"; fi
docker build --build-arg BUILD_TAG=$DOCKER_BUILD_TAG --no-cache=true --tag ethcore/parity:$1 .
docker push ethcore/parity:$1 docker push ethcore/parity:$1