Merge remote-tracking branch 'origin/master' into fix-tx-rpc

This commit is contained in:
Gav Wood 2016-11-30 17:15:05 -08:00
commit d3e684698a
No known key found for this signature in database
GPG Key ID: C49C1ACA1CC9B252
114 changed files with 1302 additions and 455 deletions

View File

@ -8,7 +8,6 @@ variables:
RUST_BACKTRACE: "1" RUST_BACKTRACE: "1"
RUSTFLAGS: "" RUSTFLAGS: ""
CARGOFLAGS: "" CARGOFLAGS: ""
NIGHTLY: "nigtly"
cache: cache:
key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME" key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
untracked: true untracked: true
@ -21,7 +20,7 @@ linux-stable:
- stable - stable
- triggers - triggers
script: script:
- cargo build --release $CARGOFLAGS - cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity - strip 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
@ -53,7 +52,7 @@ linux-beta:
- stable - stable
- triggers - triggers
script: script:
- cargo build --release $CARGOFLAGS - cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity - strip target/release/parity
tags: tags:
- rust - rust
@ -72,7 +71,7 @@ linux-nightly:
- stable - stable
- triggers - triggers
script: script:
- cargo build --release $CARGOFLAGS - cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity - strip target/release/parity
tags: tags:
- rust - rust
@ -93,7 +92,7 @@ linux-centos:
script: script:
- export CXX="g++" - export CXX="g++"
- export CC="gcc" - export CC="gcc"
- cargo build --release $CARGOFLAGS - cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity - strip target/release/parity
- md5sum target/release/parity > parity.md5 - md5sum target/release/parity > parity.md5
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
@ -120,7 +119,7 @@ linux-i686:
script: script:
- export HOST_CC=gcc - export HOST_CC=gcc
- export HOST_CXX=g++ - export HOST_CXX=g++
- cargo build --target i686-unknown-linux-gnu --release $CARGOFLAGS - cargo build -j $(nproc) --target i686-unknown-linux-gnu --release $CARGOFLAGS
- strip target/i686-unknown-linux-gnu/release/parity - strip target/i686-unknown-linux-gnu/release/parity
- md5sum target/i686-unknown-linux-gnu/release/parity > parity.md5 - md5sum target/i686-unknown-linux-gnu/release/parity > parity.md5
- sh scripts/deb-build.sh i386 - sh scripts/deb-build.sh i386
@ -162,7 +161,7 @@ linux-armv7:
- echo "[target.armv7-unknown-linux-gnueabihf]" >> .cargo/config - echo "[target.armv7-unknown-linux-gnueabihf]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS - cargo build -j $(nproc) --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS
- arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/parity - arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/parity
- md5sum target/armv7-unknown-linux-gnueabihf/release/parity > parity.md5 - md5sum target/armv7-unknown-linux-gnueabihf/release/parity > parity.md5
- sh scripts/deb-build.sh armhf - sh scripts/deb-build.sh armhf
@ -204,7 +203,7 @@ linux-arm:
- echo "[target.arm-unknown-linux-gnueabihf]" >> .cargo/config - echo "[target.arm-unknown-linux-gnueabihf]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS - cargo build -j $(nproc) --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS
- arm-linux-gnueabihf-strip target/arm-unknown-linux-gnueabihf/release/parity - arm-linux-gnueabihf-strip target/arm-unknown-linux-gnueabihf/release/parity
- md5sum target/arm-unknown-linux-gnueabihf/release/parity > parity.md5 - md5sum target/arm-unknown-linux-gnueabihf/release/parity > parity.md5
- sh scripts/deb-build.sh armhf - sh scripts/deb-build.sh armhf
@ -232,9 +231,9 @@ linux-armv6:
stage: build stage: build
image: ethcore/rust-armv6:latest image: ethcore/rust-armv6:latest
only: only:
- beta # - beta
- tags # - tags
- stable # - stable
- triggers - triggers
script: script:
- export CC=arm-linux-gnueabi-gcc - export CC=arm-linux-gnueabi-gcc
@ -246,7 +245,7 @@ linux-armv6:
- echo "[target.arm-unknown-linux-gnueabi]" >> .cargo/config - echo "[target.arm-unknown-linux-gnueabi]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabi-gcc\"" >> .cargo/config - echo "linker= \"arm-linux-gnueabi-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build --target arm-unknown-linux-gnueabi --release $CARGOFLAGS - cargo build -j $(nproc) --target arm-unknown-linux-gnueabi --release $CARGOFLAGS
- arm-linux-gnueabi-strip target/arm-unknown-linux-gnueabi/release/parity - arm-linux-gnueabi-strip target/arm-unknown-linux-gnueabi/release/parity
- md5sum target/arm-unknown-linux-gnueabi/release/parity > parity.md5 - md5sum target/arm-unknown-linux-gnueabi/release/parity > parity.md5
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
@ -281,7 +280,7 @@ linux-aarch64:
- echo "[target.aarch64-unknown-linux-gnu]" >> .cargo/config - echo "[target.aarch64-unknown-linux-gnu]" >> .cargo/config
- echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config - echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build --target aarch64-unknown-linux-gnu --release $CARGOFLAGS - cargo build -j $(nproc) --target aarch64-unknown-linux-gnu --release $CARGOFLAGS
- aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/parity - aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/parity
- md5sum target/aarch64-unknown-linux-gnu/release/parity > parity.md5 - md5sum target/aarch64-unknown-linux-gnu/release/parity > parity.md5
- sh scripts/deb-build.sh arm64 - sh scripts/deb-build.sh arm64
@ -305,41 +304,6 @@ linux-aarch64:
- target/aarch64-unknown-linux-gnu/release/parity - target/aarch64-unknown-linux-gnu/release/parity
name: "aarch64-unknown-linux-gnu_parity" name: "aarch64-unknown-linux-gnu_parity"
allow_failure: true allow_failure: true
#linux-alpine:
# stage: build
# image: ethcore/rust-alpine:latest
# only:
# - beta
# - tags
# - stable
# - triggers
# script:
# - export HOST_CC=gcc
# - export HOST_CXX=g++
# - cargo build --release $CARGOFLAGS
# - strip target/release/parity
# - md5sum target/release/parity > parity.md5
# - sh scripts/deb-build.sh arm64
# - cp target/aarch64-unknown-linux-gnu/release/parity deb/usr/bin/parity
# - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
# - dpkg-deb -b deb "parity_"$VER"_arm64.deb"
# - md5sum "parity_"$VER"_arm64.deb" > "parity_"$VER"_arm64.deb.md5"
# - aws configure set aws_access_key_id $s3_key
# - aws configure set aws_secret_access_key $s3_secret
# - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
# - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity --body target/aarch64-unknown-linux-gnu/release/parity
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity.md5 --body parity.md5
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/"parity_"$VER"_arm64.deb" --body "parity_"$VER"_arm64.deb"
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/"parity_"$VER"_arm64.deb.md5" --body "parity_"$VER"_arm64.deb.md5"
# tags:
# - rust
# - rust-alpine
# artifacts:
# paths:
# - target/aarch64-unknown-linux-gnu/release/parity
# name: "aarch64-unknown-linux-gnu_parity"
# allow_failure: true
darwin: darwin:
stage: build stage: build
only: only:
@ -348,8 +312,8 @@ darwin:
- stable - stable
- triggers - triggers
script: script:
- cargo build --release -p ethstore $CARGOFLAGS - cargo build -j 8 --release -p ethstore #$CARGOFLAGS
- cargo build --release $CARGOFLAGS - cargo build -j 8 --release #$CARGOFLAGS
- rm -rf parity.md5 - rm -rf parity.md5
- md5sum target/release/parity > parity.md5 - md5sum target/release/parity > parity.md5
- packagesbuild -v mac/Parity.pkgproj - packagesbuild -v mac/Parity.pkgproj
@ -386,7 +350,7 @@ windows:
- set RUST_BACKTRACE=1 - set RUST_BACKTRACE=1
- set RUSTFLAGS=%RUSTFLAGS% - set RUSTFLAGS=%RUSTFLAGS%
- rustup default stable-x86_64-pc-windows-msvc - rustup default stable-x86_64-pc-windows-msvc
- cargo build --release %CARGOFLAGS% - cargo build -j 8 --release #%CARGOFLAGS%
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll - curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe - curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe
- signtool sign /f %keyfile% /p %certpass% target\release\parity.exe - signtool sign /f %keyfile% /p %certpass% target\release\parity.exe
@ -449,7 +413,7 @@ test-windows:
- git submodule update --init --recursive - git submodule update --init --recursive
script: script:
- set RUST_BACKTRACE=1 - set RUST_BACKTRACE=1
- cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release - cargo -j 8 test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release
tags: tags:
- rust-windows - rust-windows
allow_failure: true allow_failure: true

28
Cargo.lock generated
View File

@ -3,7 +3,7 @@ name = "parity"
version = "1.5.0" version = "1.5.0"
dependencies = [ dependencies = [
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)", "ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)",
"daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
@ -146,15 +146,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "clippy" name = "clippy"
version = "0.0.96" version = "0.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"clippy_lints 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "clippy_lints" name = "clippy_lints"
version = "0.0.96" version = "0.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -224,7 +224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "elastic-array" name = "elastic-array"
version = "0.6.0" version = "0.6.0"
source = "git+https://github.com/ethcore/elastic-array#70e4012e691b732c7c4cb04e9232799e6aa268bc" source = "git+https://github.com/ethcore/elastic-array#346f1ba5982576dab9d0b8fa178b50e1db0a21cd"
dependencies = [ dependencies = [
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -280,7 +280,7 @@ dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.4.0", "ethash 1.4.0",
@ -333,7 +333,7 @@ dependencies = [
name = "ethcore-dapps" name = "ethcore-dapps"
version = "1.5.0" version = "1.5.0"
dependencies = [ dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-devtools 1.4.0", "ethcore-devtools 1.4.0",
"ethcore-hash-fetch 1.5.0", "ethcore-hash-fetch 1.5.0",
@ -490,7 +490,7 @@ dependencies = [
name = "ethcore-rpc" name = "ethcore-rpc"
version = "1.5.0" version = "1.5.0"
dependencies = [ dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.4.0", "ethash 1.4.0",
"ethcore 1.5.0", "ethcore 1.5.0",
"ethcore-devtools 1.4.0", "ethcore-devtools 1.4.0",
@ -520,7 +520,7 @@ dependencies = [
name = "ethcore-signer" name = "ethcore-signer"
version = "1.5.0" version = "1.5.0"
dependencies = [ dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-devtools 1.4.0", "ethcore-devtools 1.4.0",
"ethcore-io 1.5.0", "ethcore-io 1.5.0",
@ -559,7 +559,7 @@ version = "1.5.0"
dependencies = [ dependencies = [
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)", "elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)", "eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
@ -649,7 +649,7 @@ dependencies = [
name = "ethsync" name = "ethsync"
version = "1.5.0" version = "1.5.0"
dependencies = [ dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.5.0", "ethcore 1.5.0",
"ethcore-io 1.5.0", "ethcore-io 1.5.0",
@ -1263,7 +1263,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#cb6836dddf8c9951e056283dcd9e105e97923d07" source = "git+https://github.com/ethcore/js-precompiled.git#b3f0e3ddedf9afee35ca8384a74158df572973c7"
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)",
] ]
@ -2005,8 +2005,8 @@ dependencies = [
"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27"
"checksum bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)" = "<none>" "checksum bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)" = "<none>"
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
"checksum clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)" = "6eacf01b0aad84a0817703498f72d252df7c0faf6a5b86d0be4265f1829e459f" "checksum clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4fabf979ddf6419a313c1c0ada4a5b95cfd2049c56e8418d622d27b4b6ff32"
"checksum clippy_lints 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)" = "a49960c9aab544ce86b004dcb61620e8b898fea5fc0f697a028f460f48221ed6" "checksum clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "ce96ec05bfe018a0d5d43da115e54850ea2217981ff0f2e462780ab9d594651a"
"checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245" "checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245"
"checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc" "checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc"
"checksum ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)" = "<none>" "checksum ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)" = "<none>"

View File

@ -47,7 +47,7 @@ ethcore-hash-fetch = { path = "ethcore/hash-fetch" }
rlp = { path = "util/rlp" } rlp = { path = "util/rlp" }
ethcore-stratum = { path = "stratum" } ethcore-stratum = { path = "stratum" }
ethcore-dapps = { path = "dapps", optional = true } ethcore-dapps = { path = "dapps", optional = true }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = "0.2" winapi = "0.2"

View File

@ -34,7 +34,7 @@ ethcore-hash-fetch = { path = "../ethcore/hash-fetch" }
fetch = { path = "../util/fetch" } fetch = { path = "../util/fetch" }
parity-ui = { path = "./ui" } parity-ui = { path = "./ui" }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
[build-dependencies] [build-dependencies]
serde_codegen = { version = "0.8", optional = true } serde_codegen = { version = "0.8", optional = true }

View File

@ -11,7 +11,7 @@ build = "build.rs"
ethcore-ipc-codegen = { path = "../ipc/codegen" } ethcore-ipc-codegen = { path = "../ipc/codegen" }
[dependencies] [dependencies]
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
ethcore-devtools = { path = "../devtools" } ethcore-devtools = { path = "../devtools" }
ethcore-ipc = { path = "../ipc/rpc" } ethcore-ipc = { path = "../ipc/rpc" }
rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" } rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" }

View File

@ -29,7 +29,7 @@ byteorder = "0.5"
transient-hashmap = "0.1" transient-hashmap = "0.1"
linked-hash-map = "0.3.0" linked-hash-map = "0.3.0"
evmjit = { path = "../evmjit", optional = true } evmjit = { path = "../evmjit", optional = true }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
ethash = { path = "../ethash" } ethash = { path = "../ethash" }
ethcore-util = { path = "../util" } ethcore-util = { path = "../util" }
ethcore-io = { path = "../util/io" } ethcore-io = { path = "../util/io" }

View File

@ -121,10 +121,6 @@ impl<'db> HashDB for AccountDB<'db>{
fn remove(&mut self, _key: &H256) { fn remove(&mut self, _key: &H256) {
unimplemented!() unimplemented!()
} }
fn get_aux(&self, hash: &[u8]) -> Option<DBValue> {
self.db.get_aux(hash)
}
} }
/// DB backend wrapper for Account trie /// DB backend wrapper for Account trie
@ -197,18 +193,6 @@ impl<'db> HashDB for AccountDBMut<'db>{
let key = combine_key(&self.address_hash, key); let key = combine_key(&self.address_hash, key);
self.db.remove(&key) self.db.remove(&key)
} }
fn insert_aux(&mut self, hash: Vec<u8>, value: Vec<u8>) {
self.db.insert_aux(hash, value);
}
fn get_aux(&self, hash: &[u8]) -> Option<DBValue> {
self.db.get_aux(hash)
}
fn remove_aux(&mut self, hash: &[u8]) {
self.db.remove_aux(hash);
}
} }
struct Wrapping<'db>(&'db HashDB); struct Wrapping<'db>(&'db HashDB);

View File

@ -594,9 +594,9 @@ mod tests {
use factory::Factories; use factory::Factories;
use state_db::StateDB; use state_db::StateDB;
use views::BlockView; use views::BlockView;
use util::Address; use util::{Address, TrieFactory};
use util::hash::FixedHash; use util::hash::FixedHash;
use util::trie::TrieSpec;
use std::sync::Arc; use std::sync::Arc;
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
@ -637,7 +637,7 @@ mod tests {
let genesis_header = spec.genesis_header(); let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock(); let b = b.close_and_lock();
@ -653,7 +653,7 @@ mod tests {
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap() let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
.close_and_lock().seal(engine, vec![]).unwrap(); .close_and_lock().seal(engine, vec![]).unwrap();
@ -662,7 +662,7 @@ mod tests {
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap(); let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
assert_eq!(e.rlp_bytes(), orig_bytes); assert_eq!(e.rlp_bytes(), orig_bytes);
@ -681,7 +681,7 @@ mod tests {
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let mut uncle1_header = Header::new(); let mut uncle1_header = Header::new();
@ -697,7 +697,7 @@ mod tests {
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap(); let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
let bytes = e.rlp_bytes(); let bytes = e.rlp_bytes();

View File

@ -22,7 +22,7 @@ use std::time::{Instant};
use time::precise_time_ns; use time::precise_time_ns;
// util // util
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock}; use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, Hashable};
use util::{journaldb, TrieFactory, Trie}; use util::{journaldb, TrieFactory, Trie};
use util::trie::TrieSpec; use util::trie::TrieSpec;
use util::{U256, H256, Address, H2048, Uint, FixedHash}; use util::{U256, H256, Address, H2048, Uint, FixedHash};
@ -172,9 +172,10 @@ impl Client {
false => TrieSpec::Secure, false => TrieSpec::Secure,
}; };
let trie_factory = TrieFactory::new(trie_spec);
let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE); let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE);
let mut state_db = StateDB::new(journal_db, config.state_cache_size); let mut state_db = StateDB::new(journal_db, config.state_cache_size);
if state_db.journal_db().is_empty() && try!(spec.ensure_db_good(&mut state_db)) { if state_db.journal_db().is_empty() && try!(spec.ensure_db_good(&mut state_db, &trie_factory)) {
let mut batch = DBTransaction::new(&db); let mut batch = DBTransaction::new(&db);
try!(state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash())); try!(state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash()));
try!(db.write(batch).map_err(ClientError::Database)); try!(db.write(batch).map_err(ClientError::Database));
@ -216,7 +217,7 @@ impl Client {
let factories = Factories { let factories = Factories {
vm: EvmFactory::new(config.vm_type.clone(), config.jump_table_size), vm: EvmFactory::new(config.vm_type.clone(), config.jump_table_size),
trie: TrieFactory::new(trie_spec), trie: trie_factory,
accountdb: Default::default(), accountdb: Default::default(),
}; };
@ -869,8 +870,8 @@ impl BlockChainClient for Client {
} }
fn keep_alive(&self) { fn keep_alive(&self) {
let should_wake = match &*self.mode.lock() { let should_wake = match *self.mode.lock() {
&Mode::Dark(..) | &Mode::Passive(..) => true, Mode::Dark(..) | Mode::Passive(..) => true,
_ => false, _ => false,
}; };
if should_wake { if should_wake {
@ -952,6 +953,10 @@ impl BlockChainClient for Client {
self.state_at(id).map(|s| s.nonce(address)) self.state_at(id).map(|s| s.nonce(address))
} }
fn storage_root(&self, address: &Address, id: BlockID) -> Option<H256> {
self.state_at(id).and_then(|s| s.storage_root(address))
}
fn block_hash(&self, id: BlockID) -> Option<H256> { fn block_hash(&self, id: BlockID) -> Option<H256> {
let chain = self.chain.read(); let chain = self.chain.read();
Self::block_hash(&chain, id) Self::block_hash(&chain, id)
@ -969,7 +974,7 @@ impl BlockChainClient for Client {
self.state_at(id).map(|s| s.storage_at(address, position)) self.state_at(id).map(|s| s.storage_at(address, position))
} }
fn list_accounts(&self, id: BlockID) -> Option<Vec<Address>> { fn list_accounts(&self, id: BlockID, after: Option<&Address>, count: u64) -> Option<Vec<Address>> {
if !self.factories.trie.is_fat() { if !self.factories.trie.is_fat() {
trace!(target: "fatdb", "list_accounts: Not a fat DB"); trace!(target: "fatdb", "list_accounts: Not a fat DB");
return None; return None;
@ -989,18 +994,68 @@ impl BlockChainClient for Client {
} }
}; };
let iter = match trie.iter() { let mut iter = match trie.iter() {
Ok(iter) => iter, Ok(iter) => iter,
_ => return None, _ => return None,
}; };
if let Some(after) = after {
if let Err(e) = iter.seek(after) {
trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e);
}
}
let accounts = iter.filter_map(|item| { let accounts = iter.filter_map(|item| {
item.ok().map(|(addr, _)| Address::from_slice(&addr)) item.ok().map(|(addr, _)| Address::from_slice(&addr))
}).collect(); }).take(count as usize).collect();
Some(accounts) Some(accounts)
} }
fn list_storage(&self, id: BlockID, account: &Address, after: Option<&H256>, count: u64) -> Option<Vec<H256>> {
if !self.factories.trie.is_fat() {
trace!(target: "fatdb", "list_stroage: Not a fat DB");
return None;
}
let state = match self.state_at(id) {
Some(state) => state,
_ => return None,
};
let root = match state.storage_root(account) {
Some(root) => root,
_ => return None,
};
let (_, db) = state.drop();
let account_db = self.factories.accountdb.readonly(db.as_hashdb(), account.sha3());
let trie = match self.factories.trie.readonly(account_db.as_hashdb(), &root) {
Ok(trie) => trie,
_ => {
trace!(target: "fatdb", "list_storage: Couldn't open the DB");
return None;
}
};
let mut iter = match trie.iter() {
Ok(iter) => iter,
_ => return None,
};
if let Some(after) = after {
if let Err(e) = iter.seek(after) {
trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e);
}
}
let keys = iter.filter_map(|item| {
item.ok().map(|(key, _)| H256::from_slice(&key))
}).take(count as usize).collect();
Some(keys)
}
fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction> { fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction> {
self.transaction_address(id).and_then(|address| self.chain.read().transaction(&address)) self.transaction_address(id).and_then(|address| self.chain.read().transaction(&address))
} }

View File

@ -333,7 +333,7 @@ impl MiningBlockChainClient for TestBlockChainClient {
let genesis_header = self.spec.genesis_header(); let genesis_header = self.spec.genesis_header();
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
self.spec.ensure_db_good(&mut db).unwrap(); self.spec.ensure_db_good(&mut db, &TrieFactory::default()).unwrap();
let last_hashes = vec![genesis_header.hash()]; let last_hashes = vec![genesis_header.hash()];
let mut open_block = OpenBlock::new( let mut open_block = OpenBlock::new(
@ -385,6 +385,10 @@ impl BlockChainClient for TestBlockChainClient {
} }
} }
fn storage_root(&self, _address: &Address, _id: BlockID) -> Option<H256> {
None
}
fn latest_nonce(&self, address: &Address) -> U256 { fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockID::Latest).unwrap() self.nonce(address, BlockID::Latest).unwrap()
} }
@ -416,10 +420,13 @@ impl BlockChainClient for TestBlockChainClient {
} }
} }
fn list_accounts(&self, _id: BlockID) -> Option<Vec<Address>> { fn list_accounts(&self, _id: BlockID, _after: Option<&Address>, _count: u64) -> Option<Vec<Address>> {
None None
} }
fn list_storage(&self, _id: BlockID, _account: &Address, _after: Option<&H256>, _count: u64) -> Option<Vec<H256>> {
None
}
fn transaction(&self, _id: TransactionID) -> Option<LocalizedTransaction> { fn transaction(&self, _id: TransactionID) -> Option<LocalizedTransaction> {
None // Simple default. None // Simple default.
} }

View File

@ -68,6 +68,10 @@ pub trait BlockChainClient : Sync + Send {
/// May not fail on BlockID::Latest. /// May not fail on BlockID::Latest.
fn nonce(&self, address: &Address, id: BlockID) -> Option<U256>; fn nonce(&self, address: &Address, id: BlockID) -> Option<U256>;
/// Attempt to get address storage root at given block.
/// May not fail on BlockID::Latest.
fn storage_root(&self, address: &Address, id: BlockID) -> Option<H256>;
/// Get address nonce at the latest block's state. /// Get address nonce at the latest block's state.
fn latest_nonce(&self, address: &Address) -> U256 { fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockID::Latest) self.nonce(address, BlockID::Latest)
@ -114,7 +118,12 @@ pub trait BlockChainClient : Sync + Send {
} }
/// Get a list of all accounts in the block `id`, if fat DB is in operation, otherwise `None`. /// Get a list of all accounts in the block `id`, if fat DB is in operation, otherwise `None`.
fn list_accounts(&self, id: BlockID) -> Option<Vec<Address>>; /// If `after` is set the list starts with the following item.
fn list_accounts(&self, id: BlockID, after: Option<&Address>, count: u64) -> Option<Vec<Address>>;
/// Get a list of all storage keys in the block `id`, if fat DB is in operation, otherwise `None`.
/// If `after` is set the list starts with the following item.
fn list_storage(&self, id: BlockID, account: &Address, after: Option<&H256>, count: u64) -> Option<Vec<H256>>;
/// Get transaction with given hash. /// Get transaction with given hash.
fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction>; fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction>;

View File

@ -124,7 +124,7 @@ impl AuthorityRound {
} }
fn step_proposer(&self, step: usize) -> &Address { fn step_proposer(&self, step: usize) -> &Address {
let ref p = self.our_params; let p = &self.our_params;
p.authorities.get(step % p.authority_n).expect("There are authority_n authorities; taking number modulo authority_n gives number in authority_n range; qed") p.authorities.get(step % p.authority_n).expect("There are authority_n authorities; taking number modulo authority_n gives number in authority_n range; qed")
} }
@ -211,7 +211,7 @@ impl Engine for AuthorityRound {
fn on_close_block(&self, _block: &mut ExecutedBlock) {} fn on_close_block(&self, _block: &mut ExecutedBlock) {}
fn is_sealer(&self, author: &Address) -> Option<bool> { fn is_sealer(&self, author: &Address) -> Option<bool> {
let ref p = self.our_params; let p = &self.our_params;
Some(p.authorities.contains(author)) Some(p.authorities.contains(author))
} }
@ -315,6 +315,7 @@ impl Engine for AuthorityRound {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use util::*; use util::*;
use util::trie::TrieSpec;
use env_info::EnvInfo; use env_info::EnvInfo;
use header::Header; use header::Header;
use error::{Error, BlockError}; use error::{Error, BlockError};
@ -384,9 +385,9 @@ mod tests {
let engine = &*spec.engine; let engine = &*spec.engine;
let genesis_header = spec.genesis_header(); let genesis_header = spec.genesis_header();
let mut db1 = get_temp_state_db().take(); let mut db1 = get_temp_state_db().take();
spec.ensure_db_good(&mut db1).unwrap(); spec.ensure_db_good(&mut db1, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let mut db2 = get_temp_state_db().take(); let mut db2 = get_temp_state_db().take();
spec.ensure_db_good(&mut db2).unwrap(); spec.ensure_db_good(&mut db2, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b1 = b1.close_and_lock(); let b1 = b1.close_and_lock();

View File

@ -184,6 +184,7 @@ impl Engine for BasicAuthority {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use util::*; use util::*;
use util::trie::TrieSpec;
use block::*; use block::*;
use env_info::EnvInfo; use env_info::EnvInfo;
use error::{BlockError, Error}; use error::{BlockError, Error};
@ -256,7 +257,7 @@ mod tests {
let genesis_header = spec.genesis_header(); let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock(); let b = b.close_and_lock();

View File

@ -68,6 +68,7 @@ impl Engine for InstantSeal {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use util::*; use util::*;
use util::trie::TrieSpec;
use tests::helpers::*; use tests::helpers::*;
use account_provider::AccountProvider; use account_provider::AccountProvider;
use spec::Spec; use spec::Spec;
@ -84,7 +85,7 @@ mod tests {
let genesis_header = spec.genesis_header(); let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock(); let b = b.close_and_lock();

View File

@ -422,6 +422,7 @@ impl Header {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use util::*; use util::*;
use util::trie::TrieSpec;
use block::*; use block::*;
use tests::helpers::*; use tests::helpers::*;
use env_info::EnvInfo; use env_info::EnvInfo;
@ -438,7 +439,7 @@ mod tests {
let genesis_header = spec.genesis_header(); let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close(); let b = b.close();
@ -452,7 +453,7 @@ mod tests {
let genesis_header = spec.genesis_header(); let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]); let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let mut uncle = Header::new(); let mut uncle = Header::new();

View File

@ -72,6 +72,7 @@ pub fn new_morden() -> Spec { load(include_bytes!("../../res/ethereum/morden.jso
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use util::*; use util::*;
use util::trie::TrieSpec;
use state::*; use state::*;
use super::*; use super::*;
use tests::helpers::*; use tests::helpers::*;
@ -84,7 +85,7 @@ mod tests {
let genesis_header = spec.genesis_header(); let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap(); spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let s = State::from_existing(db, genesis_header.state_root().clone(), engine.account_start_nonce(), Default::default()).unwrap(); let s = State::from_existing(db, genesis_header.state_root().clone(), engine.account_start_nonce(), Default::default()).unwrap();
assert_eq!(s.balance(&"0000000000000000000000000000000000000001".into()), 1u64.into()); assert_eq!(s.balance(&"0000000000000000000000000000000000000001".into()), 1u64.into());
assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()), 1u64.into()); assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()), 1u64.into());

View File

@ -197,19 +197,17 @@ impl<Gas: CostType> Gasometer<Gas> {
let address = u256_to_address(stack.peek(1)); let address = u256_to_address(stack.peek(1));
let is_value_transfer = !stack.peek(2).is_zero(); let is_value_transfer = !stack.peek(2).is_zero();
if instruction == instructions::CALL { if instruction == instructions::CALL && (
if ( (!schedule.no_empty && !ext.exists(&address))
!schedule.no_empty && !ext.exists(&address) ||
) || ( (schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address))
schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address) ) {
) { gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into())); }
}
};
if is_value_transfer { if is_value_transfer {
gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into())); gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
}; }
let requested = *stack.peek(0); let requested = *stack.peek(0);
@ -347,7 +345,7 @@ fn test_mem_gas_cost() {
let result = gasometer.mem_gas_cost(&schedule, current_mem_size, &mem_size); let result = gasometer.mem_gas_cost(&schedule, current_mem_size, &mem_size);
// then // then
if let Ok(_) = result { if result.is_ok() {
assert!(false, "Should fail with OutOfGas"); assert!(false, "Should fail with OutOfGas");
} }
} }

View File

@ -103,7 +103,7 @@ impl Ext for FakeExt {
} }
fn balance(&self, address: &Address) -> U256 { fn balance(&self, address: &Address) -> U256 {
*self.balances.get(address).unwrap() self.balances[address]
} }
fn blockhash(&self, number: &U256) -> H256 { fn blockhash(&self, number: &U256) -> H256 {

View File

@ -514,9 +514,11 @@ impl<'a> Executive<'a> {
#[cfg(test)] #[cfg(test)]
#[allow(dead_code)] #[allow(dead_code)]
mod tests { mod tests {
use std::sync::Arc;
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use super::*; use super::*;
use util::*; use util::{H256, U256, U512, Address, Uint, FixedHash, FromHex, FromStr};
use util::bytes::BytesRef;
use action_params::{ActionParams, ActionValue}; use action_params::{ActionParams, ActionValue};
use env_info::EnvInfo; use env_info::EnvInfo;
use evm::{Factory, VMType}; use evm::{Factory, VMType};

View File

@ -151,7 +151,7 @@ impl GasPriceCalibrator {
if Instant::now() >= self.next_calibration { if Instant::now() >= self.next_calibration {
let usd_per_tx = self.options.usd_per_tx; let usd_per_tx = self.options.usd_per_tx;
trace!(target: "miner", "Getting price info"); trace!(target: "miner", "Getting price info");
if let Ok(_) = PriceInfo::get(move |price: PriceInfo| { let price_info = PriceInfo::get(move |price: PriceInfo| {
trace!(target: "miner", "Price info arrived: {:?}", price); trace!(target: "miner", "Price info arrived: {:?}", price);
let usd_per_eth = price.ethusd; let usd_per_eth = price.ethusd;
let wei_per_usd: f32 = 1.0e18 / usd_per_eth; let wei_per_usd: f32 = 1.0e18 / usd_per_eth;
@ -159,7 +159,9 @@ impl GasPriceCalibrator {
let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx; let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx;
info!(target: "miner", "Updated conversion rate to Ξ1 = {} ({} wei/gas)", Colour::White.bold().paint(format!("US${}", usd_per_eth)), Colour::Yellow.bold().paint(format!("{}", wei_per_gas))); info!(target: "miner", "Updated conversion rate to Ξ1 = {} ({} wei/gas)", Colour::White.bold().paint(format!("US${}", usd_per_eth)), Colour::Yellow.bold().paint(format!("{}", wei_per_gas)));
set_price(U256::from(wei_per_gas as u64)); set_price(U256::from(wei_per_gas as u64));
}) { });
if price_info.is_ok() {
self.next_calibration = Instant::now() + self.options.recalibration_period; self.next_calibration = Instant::now() + self.options.recalibration_period;
} else { } else {
warn!(target: "miner", "Unable to update Ether price."); warn!(target: "miner", "Unable to update Ether price.");
@ -1139,15 +1141,16 @@ impl MinerService for Miner {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use super::super::{MinerService, PrioritizationStrategy}; use super::super::{MinerService, PrioritizationStrategy};
use super::*; use super::*;
use util::*; use block::IsBlock;
use util::{U256, Uint, FromHex};
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult}; use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult};
use header::BlockNumber; use header::BlockNumber;
use types::transaction::{Transaction, SignedTransaction, Action}; use types::transaction::{Transaction, SignedTransaction, Action};
use block::*;
use spec::Spec; use spec::Spec;
use tests::helpers::{generate_dummy_client}; use tests::helpers::{generate_dummy_client};

View File

@ -990,7 +990,7 @@ impl TransactionQueue {
let mut update_last_nonce_to = None; let mut update_last_nonce_to = None;
{ {
let by_nonce = self.future.by_address.row_mut(&address); let by_nonce = self.future.by_address.row_mut(&address);
if let None = by_nonce { if by_nonce.is_none() {
return; return;
} }
let mut by_nonce = by_nonce.expect("None is tested in early-exit condition above; qed"); let mut by_nonce = by_nonce.expect("None is tested in early-exit condition above; qed");
@ -1212,12 +1212,12 @@ mod test {
use util::table::*; use util::table::*;
use util::*; use util::*;
use ethkey::{Random, Generator}; use ethkey::{Random, Generator};
use transaction::*;
use error::{Error, TransactionError}; use error::{Error, TransactionError};
use super::*; use super::*;
use super::{TransactionSet, TransactionOrder, VerifiedTransaction}; use super::{TransactionSet, TransactionOrder, VerifiedTransaction};
use miner::local_transactions::LocalTransactionsList; use miner::local_transactions::LocalTransactionsList;
use client::TransactionImportResult; use client::TransactionImportResult;
use transaction::{SignedTransaction, Transaction, Action};
fn unwrap_tx_err(err: Result<TransactionImportResult, Error>) -> TransactionError { fn unwrap_tx_err(err: Result<TransactionImportResult, Error>) -> TransactionError {
match err.unwrap_err() { match err.unwrap_err() {

View File

@ -64,13 +64,13 @@ impl PodAccount {
} }
/// Place additional data into given hash DB. /// Place additional data into given hash DB.
pub fn insert_additional(&self, db: &mut AccountDBMut) { pub fn insert_additional(&self, db: &mut AccountDBMut, factory: &TrieFactory) {
match self.code { match self.code {
Some(ref c) if !c.is_empty() => { db.insert(c); } Some(ref c) if !c.is_empty() => { db.insert(c); }
_ => {} _ => {}
} }
let mut r = H256::new(); let mut r = H256::new();
let mut t = SecTrieDBMut::new(db, &mut r); let mut t = factory.create(db, &mut r);
for (k, v) in &self.storage { for (k, v) in &self.storage {
if let Err(e) = t.insert(k, &rlp::encode(&U256::from(&**v))) { if let Err(e) = t.insert(k, &rlp::encode(&U256::from(&**v))) {
warn!("Encountered potential DB corruption: {}", e); warn!("Encountered potential DB corruption: {}", e);

View File

@ -552,11 +552,11 @@ const POW_VERIFY_RATE: f32 = 0.02;
pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &Engine, chain: &BlockChain, body: Option<&[u8]>, always: bool) -> Result<(), ::error::Error> { pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &Engine, chain: &BlockChain, body: Option<&[u8]>, always: bool) -> Result<(), ::error::Error> {
if always || rng.gen::<f32>() <= POW_VERIFY_RATE { if always || rng.gen::<f32>() <= POW_VERIFY_RATE {
match chain.block_header(header.parent_hash()) { match chain.block_header(header.parent_hash()) {
Some(parent) => engine.verify_block_family(&header, &parent, body), Some(parent) => engine.verify_block_family(header, &parent, body),
None => engine.verify_block_seal(&header), None => engine.verify_block_seal(header),
} }
} else { } else {
engine.verify_block_basic(&header, body) engine.verify_block_basic(header, body)
} }
} }

View File

@ -244,13 +244,13 @@ impl Spec {
} }
/// Ensure that the given state DB has the trie nodes in for the genesis state. /// Ensure that the given state DB has the trie nodes in for the genesis state.
pub fn ensure_db_good(&self, db: &mut StateDB) -> Result<bool, Box<TrieError>> { pub fn ensure_db_good(&self, db: &mut StateDB, factory: &TrieFactory) -> Result<bool, Box<TrieError>> {
if !db.as_hashdb().contains(&self.state_root()) { if !db.as_hashdb().contains(&self.state_root()) {
trace!(target: "spec", "ensure_db_good: Fresh database? Cannot find state root {}", self.state_root()); trace!(target: "spec", "ensure_db_good: Fresh database? Cannot find state root {}", self.state_root());
let mut root = H256::new(); let mut root = H256::new();
{ {
let mut t = SecTrieDBMut::new(db.as_hashdb_mut(), &mut root); let mut t = factory.create(db.as_hashdb_mut(), &mut root);
for (address, account) in self.genesis_state.get().iter() { for (address, account) in self.genesis_state.get().iter() {
try!(t.insert(&**address, &account.rlp())); try!(t.insert(&**address, &account.rlp()));
} }
@ -258,7 +258,7 @@ impl Spec {
trace!(target: "spec", "ensure_db_good: Populated sec trie; root is {}", root); trace!(target: "spec", "ensure_db_good: Populated sec trie; root is {}", root);
for (address, account) in self.genesis_state.get().iter() { for (address, account) in self.genesis_state.get().iter() {
db.note_non_null_account(address); db.note_non_null_account(address);
account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address)); account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address), factory);
} }
assert!(db.as_hashdb().contains(&self.state_root())); assert!(db.as_hashdb().contains(&self.state_root()));
Ok(true) Ok(true)

View File

@ -314,11 +314,10 @@ impl Account {
self.code_hash == SHA3_EMPTY self.code_hash == SHA3_EMPTY
} }
#[cfg(test)] /// Return the storage root associated with this account or None if it has been altered via the overlay.
/// return the storage root associated with this account or None if it has been altered via the overlay.
pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} } pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} }
/// return the storage overlay. /// Return the storage overlay.
pub fn storage_changes(&self) -> &HashMap<H256, H256> { &self.storage_changes } pub fn storage_changes(&self) -> &HashMap<H256, H256> { &self.storage_changes }
/// Increment the nonce of the account by one. /// Increment the nonce of the account by one.
@ -445,11 +444,10 @@ impl fmt::Debug for Account {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rlp::{UntrustedRlp, RlpType, View, Compressible};
use util::*; use util::*;
use super::*; use super::*;
use account_db::*; use account_db::*;
use rlp::*;
#[test] #[test]
fn account_compress() { fn account_compress() {

View File

@ -369,6 +369,12 @@ impl State {
|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce())) |a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce()))
} }
/// Get the storage root of account `a`.
pub fn storage_root(&self, a: &Address) -> Option<H256> {
self.ensure_cached(a, RequireCache::None, true,
|a| a.as_ref().and_then(|account| account.storage_root().cloned()))
}
/// Mutate storage of account `address` so that it is `value` for `key`. /// Mutate storage of account `address` so that it is `value` for `key`.
pub fn storage_at(&self, address: &Address, key: &H256) -> H256 { pub fn storage_at(&self, address: &Address, key: &H256) -> H256 {
// Storage key search and update works like this: // Storage key search and update works like this:
@ -445,6 +451,7 @@ impl State {
} }
/// Add `incr` to the balance of account `a`. /// Add `incr` to the balance of account `a`.
#[cfg_attr(feature="dev", allow(single_match))]
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) { pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) {
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a)); trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a));
let is_value_transfer = !incr.is_zero(); let is_value_transfer = !incr.is_zero();

View File

@ -57,6 +57,7 @@ impl Substate {
} }
/// Get the cleanup mode object from this. /// Get the cleanup mode object from this.
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode { pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
match (schedule.no_empty, schedule.kill_empty) { match (schedule.no_empty, schedule.kill_empty) {
(false, _) => CleanupMode::ForceCreate, (false, _) => CleanupMode::ForceCreate,

View File

@ -397,6 +397,7 @@ impl StateDB {
} }
/// Get cached code based on hash. /// Get cached code based on hash.
#[cfg_attr(feature="dev", allow(map_clone))]
pub fn get_cached_code(&self, hash: &H256) -> Option<Arc<Vec<u8>>> { pub fn get_cached_code(&self, hash: &H256) -> Option<Arc<Vec<u8>>> {
let mut cache = self.code_cache.lock(); let mut cache = self.code_cache.lock();

View File

@ -62,7 +62,7 @@ fn should_return_registrar() {
&db_config &db_config
).unwrap(); ).unwrap();
let params = client.additional_params(); let params = client.additional_params();
let address = params.get("registrar").unwrap(); let address = &params["registrar"];
assert_eq!(address.len(), 40); assert_eq!(address.len(), 40);
assert!(U256::from_str(address).is_ok()); assert!(U256::from_str(address).is_ok());
@ -93,7 +93,7 @@ fn imports_good_block() {
&db_config &db_config
).unwrap(); ).unwrap();
let good_block = get_good_dummy_block(); let good_block = get_good_dummy_block();
if let Err(_) = client.import_block(good_block) { if client.import_block(good_block).is_err() {
panic!("error importing block being good by definition"); panic!("error importing block being good by definition");
} }
client.flush_queue(); client.flush_queue();
@ -203,18 +203,18 @@ fn can_collect_garbage() {
#[test] #[test]
fn can_generate_gas_price_median() { fn can_generate_gas_price_median() {
let client_result = generate_dummy_client_with_data(3, 1, &vec_into![1, 2, 3]); let client_result = generate_dummy_client_with_data(3, 1, slice_into![1, 2, 3]);
let client = client_result.reference(); let client = client_result.reference();
assert_eq!(Some(U256::from(2)), client.gas_price_median(3)); assert_eq!(Some(U256::from(2)), client.gas_price_median(3));
let client_result = generate_dummy_client_with_data(4, 1, &vec_into![1, 4, 3, 2]); let client_result = generate_dummy_client_with_data(4, 1, slice_into![1, 4, 3, 2]);
let client = client_result.reference(); let client = client_result.reference();
assert_eq!(Some(U256::from(3)), client.gas_price_median(4)); assert_eq!(Some(U256::from(3)), client.gas_price_median(4));
} }
#[test] #[test]
fn can_generate_gas_price_histogram() { fn can_generate_gas_price_histogram() {
let client_result = generate_dummy_client_with_data(20, 1, &vec_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]); let client_result = generate_dummy_client_with_data(20, 1, slice_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]);
let client = client_result.reference(); let client = client_result.reference();
let hist = client.gas_price_histogram(20, 5).unwrap(); let hist = client.gas_price_histogram(20, 5).unwrap();
@ -224,7 +224,7 @@ fn can_generate_gas_price_histogram() {
#[test] #[test]
fn empty_gas_price_histogram() { fn empty_gas_price_histogram() {
let client_result = generate_dummy_client_with_data(20, 0, &vec_into![]); let client_result = generate_dummy_client_with_data(20, 0, slice_into![]);
let client = client_result.reference(); let client = client_result.reference();
assert!(client.gas_price_histogram(20, 5).is_none()); assert!(client.gas_price_histogram(20, 5).is_none());

View File

@ -18,6 +18,7 @@ use ethkey::KeyPair;
use io::*; use io::*;
use client::{BlockChainClient, Client, ClientConfig}; use client::{BlockChainClient, Client, ClientConfig};
use util::*; use util::*;
use util::trie::TrieSpec;
use spec::*; use spec::*;
use state_db::StateDB; use state_db::StateDB;
use block::{OpenBlock, Drain}; use block::{OpenBlock, Drain};
@ -157,7 +158,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
let mut db_result = get_temp_state_db(); let mut db_result = get_temp_state_db();
let mut db = db_result.take(); let mut db = db_result.take();
test_spec.ensure_db_good(&mut db).unwrap(); test_spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let genesis_header = test_spec.genesis_header(); let genesis_header = test_spec.genesis_header();
let mut rolling_timestamp = 40; let mut rolling_timestamp = 40;
@ -262,7 +263,7 @@ pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<
).unwrap(); ).unwrap();
for block in &blocks { for block in &blocks {
if let Err(_) = client.import_block(block.clone()) { if client.import_block(block.clone()).is_err() {
panic!("panic importing block which is well-formed"); panic!("panic importing block which is well-formed");
} }
} }

View File

@ -19,16 +19,16 @@
pub use std::time::Duration; pub use std::time::Duration;
use client::Mode as ClientMode; use client::Mode as ClientMode;
/// IPC-capable shadow-type for client::config::Mode /// IPC-capable shadow-type for `client::config::Mode`
#[derive(Clone, Binary, Debug)] #[derive(Clone, Binary, Debug)]
pub enum Mode { pub enum Mode {
/// Same as ClientMode::Off. /// Same as `ClientMode::Off`.
Off, Off,
/// Same as ClientMode::Dark; values in seconds. /// Same as `ClientMode::Dark`; values in seconds.
Dark(u64), Dark(u64),
/// Same as ClientMode::Passive; values in seconds. /// Same as `ClientMode::Passive`; values in seconds.
Passive(u64, u64), Passive(u64, u64),
/// Same as ClientMode::Active. /// Same as `ClientMode::Active`.
Active, Active,
} }

View File

@ -73,7 +73,7 @@ pub struct Transaction {
impl Transaction { impl Transaction {
/// Append object with a without signature into RLP stream /// Append object with a without signature into RLP stream
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u8>) { pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u8>) {
s.begin_list(if let None = network_id { 6 } else { 9 }); s.begin_list(if network_id.is_none() { 6 } else { 9 });
s.append(&self.nonce); s.append(&self.nonce);
s.append(&self.gas_price); s.append(&self.gas_price);
s.append(&self.gas); s.append(&self.gas);

View File

@ -29,6 +29,7 @@ use header::{BlockNumber, Header};
use rlp::{UntrustedRlp, View}; use rlp::{UntrustedRlp, View};
use transaction::SignedTransaction; use transaction::SignedTransaction;
use views::BlockView; use views::BlockView;
use time::get_time;
/// Preprocessed block data gathered in `verify_block_unordered` call /// Preprocessed block data gathered in `verify_block_unordered` call
pub struct PreverifiedBlock { pub struct PreverifiedBlock {
@ -209,6 +210,10 @@ pub fn verify_header_params(header: &Header, engine: &Engine) -> Result<(), Erro
if header.number() != 0 && header.extra_data().len() > maximum_extra_data_size { if header.number() != 0 && header.extra_data().len() > maximum_extra_data_size {
return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data().len() }))); return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data().len() })));
} }
let max_time = get_time().sec as u64 + 30;
if header.timestamp() > max_time {
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: header.timestamp() })))
}
Ok(()) Ok(())
} }
@ -258,6 +263,7 @@ mod tests {
use tests::helpers::*; use tests::helpers::*;
use types::log_entry::{LogEntry, LocalizedLogEntry}; use types::log_entry::{LogEntry, LocalizedLogEntry};
use rlp::View; use rlp::View;
use time::get_time;
fn check_ok(result: Result<(), Error>) { fn check_ok(result: Result<(), Error>) {
result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e)); result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e));
@ -271,6 +277,14 @@ mod tests {
} }
} }
fn check_fail_timestamp(result: Result<(), Error>) {
match result {
Err(Error::Block(BlockError::InvalidTimestamp(_))) => (),
Err(other) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: {:?}", other),
Ok(_) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: Ok"),
}
}
struct TestBlockChain { struct TestBlockChain {
blocks: HashMap<H256, Bytes>, blocks: HashMap<H256, Bytes>,
numbers: HashMap<BlockNumber, H256>, numbers: HashMap<BlockNumber, H256>,
@ -515,6 +529,14 @@ mod tests {
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc), check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),
InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() })); InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() }));
header = good.clone();
header.set_timestamp(2450000000);
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
header = good.clone();
header.set_timestamp(get_time().sec as u64 + 40);
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
header = good.clone(); header = good.clone();
header.set_number(9); header.set_number(9);
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc), check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),

View File

@ -0,0 +1,4 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle fill="#4A90E2" cx="50" cy="50" r="50"/>
<path d="M20 45 L10 55 L35 85 L90 35 L80 25 L36 65 z" fill="#FFF"/>
</svg>

After

Width:  |  Height:  |  Size: 213 B

View File

@ -1,6 +1,6 @@
{ {
"name": "parity.js", "name": "parity.js",
"version": "0.2.78", "version": "0.2.80",
"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>",
@ -72,6 +72,7 @@
"core-js": "~2.4.1", "core-js": "~2.4.1",
"coveralls": "~2.11.11", "coveralls": "~2.11.11",
"css-loader": "~0.26.0", "css-loader": "~0.26.0",
"ejs-loader": "~0.3.0",
"enzyme": "2.3.0", "enzyme": "2.3.0",
"eslint": "~3.10.2", "eslint": "~3.10.2",
"eslint-config-semistandard": "~7.0.0", "eslint-config-semistandard": "~7.0.0",

View File

@ -144,7 +144,8 @@ export function outSignerRequest (request) {
break; break;
case 'payload': case 'payload':
request[key].transaction = outTransaction(request[key].transaction); request[key].signTransaction = outTransaction(request[key].signTransaction);
request[key].sendTransaction = outTransaction(request[key].sendTransaction);
break; break;
} }
}); });

View File

@ -0,0 +1 @@
[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"fromName","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"badgeCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"badge","outputs":[{"name":"addr","type":"address"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}]

View File

@ -0,0 +1 @@
[{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"}]

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 badgereg from './badgereg.json';
import basiccoin from './basiccoin.json'; import basiccoin from './basiccoin.json';
import basiccoinmanager from './basiccoinmanager.json'; import basiccoinmanager from './basiccoinmanager.json';
import dappreg from './dappreg.json'; import dappreg from './dappreg.json';
@ -28,6 +29,7 @@ import tokenreg from './tokenreg.json';
import wallet from './wallet.json'; import wallet from './wallet.json';
export { export {
badgereg,
basiccoin, basiccoin,
basiccoinmanager, basiccoinmanager,
dappreg, dappreg,

View File

@ -0,0 +1,66 @@
// Copyright 2015, 2016 Ethcore (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/>.
import { bytesToHex, hex2Ascii } from '../api/util/format';
import ABI from './abi/certifier.json';
const ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000';
export default class BadgeReg {
constructor (api, registry) {
this._api = api;
this._registry = registry;
registry.getContract('badgereg');
this.certifiers = {}; // by name
this.contracts = {}; // by name
}
fetchCertifier (name) {
if (this.certifiers[name]) {
return Promise.resolve(this.certifiers[name]);
}
return this._registry.getContract('badgereg')
.then((badgeReg) => {
return badgeReg.instance.fromName.call({}, [name])
.then(([ id, address ]) => {
return Promise.all([
badgeReg.instance.meta.call({}, [id, 'TITLE']),
badgeReg.instance.meta.call({}, [id, 'IMG'])
])
.then(([ title, img ]) => {
title = bytesToHex(title);
title = title === ZERO ? null : hex2Ascii(title);
if (bytesToHex(img) === ZERO) img = null;
const data = { address, name, title, icon: img };
this.certifiers[name] = data;
return data;
});
});
});
}
checkIfCertified (certifier, address) {
if (!this.contracts[certifier]) {
this.contracts[certifier] = this._api.newContract(ABI, certifier);
}
const contract = this.contracts[certifier];
return contract.instance.certified.call({}, [address]);
}
}

View File

@ -20,6 +20,7 @@ import SignatureReg from './signaturereg';
import TokenReg from './tokenreg'; import TokenReg from './tokenreg';
import GithubHint from './githubhint'; import GithubHint from './githubhint';
import * as smsVerification from './sms-verification'; import * as smsVerification from './sms-verification';
import BadgeReg from './badgereg';
let instance = null; let instance = null;
@ -33,6 +34,7 @@ export default class Contracts {
this._signaturereg = new SignatureReg(api, this._registry); this._signaturereg = new SignatureReg(api, this._registry);
this._tokenreg = new TokenReg(api, this._registry); this._tokenreg = new TokenReg(api, this._registry);
this._githubhint = new GithubHint(api, this._registry); this._githubhint = new GithubHint(api, this._registry);
this.badgeReg = new BadgeReg(api, this._registry);
} }
get registry () { get registry () {

View File

@ -17,10 +17,8 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin'; import injectTapEventPlugin from 'react-tap-event-plugin';
import { useStrict } from 'mobx';
injectTapEventPlugin(); injectTapEventPlugin();
useStrict(true);
import Application from './dappreg/Application'; import Application from './dappreg/Application';

View File

@ -11,28 +11,23 @@
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
} background: white;
font-family: 'Roboto', sans-serif;
.loading-container { font-size: 16px;
display: flex; font-weight: 300;
align-items: center;
justify-content: center;
height: 100%;
font-family: Roboto;
background-color: rgba(0, 0, 0, 0.8);
color: #ddd;
} }
.loading { .loading {
font-size: 4em; text-align: center;
padding-top: 5em;
font-size: 2em;
color: #999;
} }
</style> </style>
</head> </head>
<body> <body>
<div id="container"> <div id="container">
<div class="loading-container"> <div class="loading">Loading</div>
<span class="loading">Loading...</span>
</div>
</div> </div>
<script src="vendor.js"></script> <script src="vendor.js"></script>
<% if (!htmlWebpackPlugin.options.secure) { %> <% if (!htmlWebpackPlugin.options.secure) { %>

View File

@ -11,28 +11,23 @@
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
} background: white;
font-family: 'Roboto', sans-serif;
.loading-container { font-size: 16px;
display: flex; font-weight: 300;
align-items: center;
justify-content: center;
height: 100%;
font-family: Roboto;
background-color: rgba(0, 0, 0, 0.8);
color: #ddd;
} }
.loading { .loading {
font-size: 4em; text-align: center;
padding-top: 5em;
font-size: 2em;
color: #999;
} }
</style> </style>
</head> </head>
<body> <body>
<div id="container"> <div id="container">
<div class="loading-container"> <div class="loading">Loading</span>
<span class="loading">Loading...</span>
</div>
</div> </div>
<script src="vendor.js"></script> <script src="vendor.js"></script>
</body> </body>

View File

@ -15,8 +15,15 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import PrintIcon from 'material-ui/svg-icons/action/print';
import { Form, Input, InputAddress } from '../../../ui'; import { Form, Input, InputAddress } from '../../../ui';
import Button from '../../../ui/Button';
import { createIdentityImg } from '../../../api/util/identity';
import print from './print';
import recoveryPage from './recovery-page.ejs';
import ParityLogo from '../../../../assets/images/parity-logo-black-no-text.svg';
export default class AccountDetails extends Component { export default class AccountDetails extends Component {
static propTypes = { static propTypes = {
@ -42,6 +49,7 @@ export default class AccountDetails extends Component {
label='address' label='address'
value={ address } /> value={ address } />
{ this.renderPhrase() } { this.renderPhrase() }
{ this.renderPhraseCopyButton() }
</Form> </Form>
); );
} }
@ -62,4 +70,26 @@ export default class AccountDetails extends Component {
value={ phrase } /> value={ phrase } />
); );
} }
renderPhraseCopyButton () {
const { phrase } = this.props;
if (!phrase) {
return null;
}
return (
<Button
icon={ <PrintIcon /> }
label={ 'print recovery phrase' }
onClick={ this.printPhrase }
/>
);
}
printPhrase = () => {
const { address, phrase, name } = this.props;
const identity = createIdentityImg(address);
print(recoveryPage({ phrase, name, identity, address, logo: ParityLogo }));
}
} }

View File

@ -0,0 +1,63 @@
// Copyright 2015, 2016 Ethcore (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/>.
export const onPrint = (window, cb) => {
let called = false; let query, queryFn;
const onPrint = () => {
if (queryFn) {
query.removeListener(queryFn);
}
window.removeEventListener('afterprint', onPrint, false);
if (!called) {
called = true;
cb();
}
};
if (window.matchMedia) {
queryFn = (query) => {
if (!query.matches) {
onPrint();
}
};
query = window.matchMedia('print');
query.addListener(queryFn);
}
window.addEventListener('afterprint', onPrint, false);
};
export default (html) => {
const iframe = document.createElement('iframe');
iframe.setAttribute('sandbox', 'allow-modals allow-same-origin allow-scripts');
iframe.setAttribute('src', '/');
iframe.setAttribute('style', 'display: none');
document.body.appendChild(iframe);
const teardown = () => {
// Safari crashes without a timeout.
setTimeout(() => document.body.removeChild(iframe), 0);
};
setTimeout(() => {
iframe.contentDocument.write(html);
setTimeout(() => {
onPrint(iframe.contentWindow, teardown);
iframe.contentWindow.focus();
iframe.contentWindow.print();
}, 20);
}, 0);
};

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Recovery phrase for <%= name %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
body {
margin: 2em auto;
max-width: 30em;
padding: 1em;
text-align: center;
font-size: 110%;
font-family: sans-serif;
font-weight: 300;
}
#logo {
max-width: 4rem;
margin-bottom: 3rem;
}
p {
margin-bottom: 1rem;
}
figure {
margin-bottom: 1rem;
}
figure.address img {
border-radius: 100%;
}
pre code {
display: inline-block;
text-align: center;
white-space: normal;
line-height: 1.3;
}
</style>
</head>
<body>
<img id="logo" src="<%= logo %>" alt="Parity Logo" />
<p>This is your account <em><%= name %></em>:</p>
<figure class="address">
<img src="<%= identity %>" alt="symbol for the address of the account" />
<figcaption><code><%= address %></code></figcaption>
</figure>
<p>This is the recovery phrase:</p>
<pre><code><%= phrase %></code></pre>
</body>
</html>

View File

@ -20,17 +20,20 @@ import SettingsMiddleware from '../views/Settings/middleware';
import SignerMiddleware from './providers/signerMiddleware'; import SignerMiddleware from './providers/signerMiddleware';
import statusMiddleware from '../views/Status/middleware'; import statusMiddleware from '../views/Status/middleware';
import CertificationsMiddleware from './providers/certifications/middleware';
export default function (api) { export default function (api) {
const errors = new ErrorsMiddleware(); const errors = new ErrorsMiddleware();
const signer = new SignerMiddleware(api); const signer = new SignerMiddleware(api);
const settings = new SettingsMiddleware(); const settings = new SettingsMiddleware();
const status = statusMiddleware(); const status = statusMiddleware();
const certifications = new CertificationsMiddleware();
const middleware = [ const middleware = [
settings.toMiddleware(), settings.toMiddleware(),
signer.toMiddleware(), signer.toMiddleware(),
errors.toMiddleware() errors.toMiddleware(),
certifications.toMiddleware()
]; ];
return middleware.concat(status, thunk); return middleware.concat(status, thunk);

View File

@ -0,0 +1,23 @@
// Copyright 2015, 2016 Ethcore (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/>.
export const fetchCertifications = (address) => ({
type: 'fetchCertifications', address
});
export const addCertification = (address, name, title, icon) => ({
type: 'addCertification', address, name, title, icon
});

View File

@ -0,0 +1,51 @@
// Copyright 2015, 2016 Ethcore (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/>.
import Contracts from '../../../contracts';
import { addCertification } from './actions';
const knownCertifiers = [ 'smsverification' ];
export default class CertificationsMiddleware {
toMiddleware () {
return (store) => (next) => (action) => {
if (action.type !== 'fetchCertifications') {
return next(action);
}
const { address } = action;
const badgeReg = Contracts.get().badgeReg;
knownCertifiers.forEach((name) => {
badgeReg.fetchCertifier(name)
.then((cert) => {
return badgeReg.checkIfCertified(cert.address, address)
.then((isCertified) => {
if (isCertified) {
const { name, title, icon } = cert;
store.dispatch(addCertification(address, name, title, icon));
}
});
})
.catch((err) => {
if (err) {
console.error(`Failed to check if ${address} certified by ${name}:`, err);
}
});
});
};
}
}

View File

@ -0,0 +1,33 @@
// Copyright 2015, 2016 Ethcore (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/>.
const initialState = {};
export default (state = initialState, action) => {
if (action.type !== 'addCertification') {
return state;
}
const { address, name, icon, title } = action;
const certifications = state[address] || [];
if (certifications.some((c) => c.name === name)) {
return state;
}
const newCertifications = certifications.concat({ name, icon, title });
return { ...state, [address]: newCertifications };
};

View File

@ -72,9 +72,8 @@ export default class SignerMiddleware {
}; };
// Sign request in-browser // Sign request in-browser
if (wallet && payload.transaction) { const transaction = payload.sendTransaction || payload.signTransaction;
const { transaction } = payload; if (wallet && transaction) {
(transaction.nonce.isZero() (transaction.nonce.isZero()
? this._api.parity.nextNonce(transaction.from) ? this._api.parity.nextNonce(transaction.from)
: Promise.resolve(transaction.nonce) : Promise.resolve(transaction.nonce)

View File

@ -18,6 +18,7 @@ import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux'; import { routerReducer } from 'react-router-redux';
import { apiReducer, balancesReducer, blockchainReducer, compilerReducer, imagesReducer, personalReducer, signerReducer, statusReducer as nodeStatusReducer, snackbarReducer } from './providers'; import { apiReducer, balancesReducer, blockchainReducer, compilerReducer, imagesReducer, personalReducer, signerReducer, statusReducer as nodeStatusReducer, snackbarReducer } from './providers';
import certificationsReducer from './providers/certifications/reducer';
import errorReducer from '../ui/Errors/reducers'; import errorReducer from '../ui/Errors/reducers';
import settingsReducer from '../views/Settings/reducers'; import settingsReducer from '../views/Settings/reducers';
@ -32,6 +33,7 @@ export default function () {
settings: settingsReducer, settings: settingsReducer,
balances: balancesReducer, balances: balancesReducer,
certifications: certificationsReducer,
blockchain: blockchainReducer, blockchain: blockchainReducer,
compiler: compilerReducer, compiler: compilerReducer,
images: imagesReducer, images: imagesReducer,

View File

@ -0,0 +1,46 @@
/* Copyright 2015, 2016 Ethcore (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/>.
*/
.certifications {
margin-top: 1em;
}
.certification {
display: inline-block;
position: relative;
margin-right: .5em;
padding: .3em .6em .2em 2.6em;
border-radius: 1em;
line-height: 1em;
text-transform: uppercase;
background-color: rgba(255, 255, 255, 0.07);
}
.certification:last-child {
margin-right: 0;
}
.icon {
position: absolute;
top: -.25em;
left: 0;
width: 2em;
height: 2em;
margin: 0;
padding: 0;
border-radius: 1em;
}

View File

@ -0,0 +1,87 @@
// Copyright 2015, 2016 Ethcore (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/>.
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { hashToImageUrl } from '../../redux/providers/imagesReducer';
import { fetchCertifications } from '../../redux/providers/certifications/actions';
import defaultIcon from '../../../assets/images/certifications/unknown.svg';
import styles from './certifications.css';
class Certifications extends Component {
static propTypes = {
account: PropTypes.string.isRequired,
certifications: PropTypes.array.isRequired,
dappsUrl: PropTypes.string.isRequired,
fetchCertifications: PropTypes.func.isRequired
}
componentWillMount () {
const { account, fetchCertifications } = this.props;
fetchCertifications(account);
}
render () {
const { certifications } = this.props;
if (certifications.length === 0) {
return null;
}
return (
<div className={ styles.certifications }>
{ certifications.map(this.renderCertification) }
</div>
);
}
renderCertification = (certification) => {
const { name, title, icon } = certification;
const { dappsUrl } = this.props;
const classNames = `${styles.certification} ${!icon ? styles.noIcon : ''}`;
const img = icon ? dappsUrl + hashToImageUrl(icon) : defaultIcon;
return (
<div className={ classNames } key={ name }>
<img className={ styles.icon } src={ img } />
<div className={ styles.text }>{ title || name }</div>
</div>
);
}
}
function mapStateToProps (_, initProps) {
const { account } = initProps;
return (state) => {
const certifications = state.certifications[account] || [];
return { certifications };
};
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({ fetchCertifications }, dispatch);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Certifications);

View File

@ -0,0 +1,17 @@
// Copyright 2015, 2016 Ethcore (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/>.
export default from './certifications';

View File

@ -23,6 +23,7 @@ import Badge from './Badge';
import Balance from './Balance'; import Balance from './Balance';
import BlockStatus from './BlockStatus'; import BlockStatus from './BlockStatus';
import Button from './Button'; import Button from './Button';
import Certifications from './Certifications';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
import Container, { Title as ContainerTitle } from './Container'; import Container, { Title as ContainerTitle } from './Container';
import ContextProvider from './ContextProvider'; import ContextProvider from './ContextProvider';
@ -55,6 +56,7 @@ export {
Balance, Balance,
BlockStatus, BlockStatus,
Button, Button,
Certifications,
ConfirmDialog, ConfirmDialog,
Container, Container,
ContainerTitle, ContainerTitle,

View File

@ -18,6 +18,7 @@ import React, { Component, PropTypes } from 'react';
import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags } from '../../../ui'; import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags } from '../../../ui';
import CopyToClipboard from '../../../ui/CopyToClipboard'; import CopyToClipboard from '../../../ui/CopyToClipboard';
import Certifications from '../../../ui/Certifications';
import styles from './header.css'; import styles from './header.css';
@ -32,6 +33,7 @@ export default class Header extends Component {
} }
render () { render () {
const { api } = this.context;
const { account, balance } = this.props; const { account, balance } = this.props;
const { address, meta, uuid } = account; const { address, meta, uuid } = account;
@ -67,6 +69,10 @@ export default class Header extends Component {
<Balance <Balance
account={ account } account={ account }
balance={ balance } /> balance={ balance } />
<Certifications
account={ account.address }
dappsUrl={ api.dappsUrl }
/>
</div> </div>
</Container> </Container>
</div> </div>

View File

@ -64,12 +64,6 @@ class Account extends Component {
} }
componentDidMount () { componentDidMount () {
const { api } = this.context;
const { address } = this.props.params;
const { isTestnet } = this.props;
const verificationStore = new VerificationStore(api, address, isTestnet);
this.setState({ verificationStore });
this.setVisibleAccounts(); this.setVisibleAccounts();
} }
@ -80,6 +74,15 @@ class Account extends Component {
if (prevAddress !== nextAddress) { if (prevAddress !== nextAddress) {
this.setVisibleAccounts(nextProps); this.setVisibleAccounts(nextProps);
} }
const { isTestnet } = nextProps;
if (typeof isTestnet === 'boolean' && !this.state.verificationStore) {
const { api } = this.context;
const { address } = nextProps.params;
this.setState({
verificationStore: new VerificationStore(api, address, isTestnet)
});
}
} }
componentWillUnmount () { componentWillUnmount () {
@ -115,7 +118,8 @@ class Account extends Component {
<Page> <Page>
<Header <Header
account={ account } account={ account }
balance={ balance } /> balance={ balance }
/>
<Transactions <Transactions
accounts={ accounts } accounts={ accounts }
address={ address } /> address={ address } />

View File

@ -19,10 +19,17 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { Snackbar as SnackbarMUI } from 'material-ui'; import { Snackbar as SnackbarMUI } from 'material-ui';
import { darkBlack } from 'material-ui/styles/colors'; import { darkBlack, grey800 } from 'material-ui/styles/colors';
import { closeSnackbar } from '../../../redux/providers/snackbarActions'; import { closeSnackbar } from '../../../redux/providers/snackbarActions';
const bodyStyle = {
backgroundColor: darkBlack,
borderStyle: 'solid',
borderColor: grey800,
borderWidth: '1px 1px 0 1px'
};
class Snackbar extends Component { class Snackbar extends Component {
static propTypes = { static propTypes = {
closeSnackbar: PropTypes.func.isRequired, closeSnackbar: PropTypes.func.isRequired,
@ -40,7 +47,7 @@ class Snackbar extends Component {
open={ open } open={ open }
message={ message } message={ message }
autoHideDuration={ cooldown } autoHideDuration={ cooldown }
bodyStyle={ { backgroundColor: darkBlack } } bodyStyle={ bodyStyle }
onRequestClose={ this.handleClose } onRequestClose={ this.handleClose }
/> />
); );

View File

@ -15,45 +15,46 @@
/* along with Parity. If not, see <http://www.gnu.org/licenses/>. /* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/ */
.status { .status {
padding: 0.5em; position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1000;
display: flex;
align-items: center;
padding: .4em .5em;
font-size: x-small; font-size: x-small;
color: #ccc; color: #ccc;
background-color: rgba(0, 0, 0, 0.2) background-color: rgba(0, 0, 0, 0.8);
}
.title {
margin: 0 0.5em 0 2em;
} }
.enode { .enode {
word-wrap: break-word; word-wrap: break-word;
float: right;
} }
.enode > * { .enode > * {
display: inline-block; display: inline-block;
margin: 0.25em 0.5em; margin: 0 .25em;
vertical-align: top; vertical-align: middle;
} }
.enode > :last-child {
.block { margin-right: 0;
} }
.netinfo { .netinfo {
display: flex; display: flex;
flex-grow: 1;
align-items: center; align-items: center;
color: #ddd; color: #ddd;
} }
.netinfo > * { .netinfo > * {
display: inline-block;
margin-left: 1em; margin-left: 1em;
} }
.network { .network {
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
display: inline-block; border-radius: .4em;
border-radius: 4px;
line-height: 1.2; line-height: 1.2;
text-transform: uppercase; text-transform: uppercase;
} }
@ -65,14 +66,3 @@
.networktest { .networktest {
background: rgb(136, 0, 0); background: rgb(136, 0, 0);
} }
.peers {
}
.version {
padding: 0.25em 0.5em;
float: left;
}
.syncing {
}

View File

@ -46,7 +46,6 @@ class Status extends Component {
<div className={ styles.version }> <div className={ styles.version }>
{ clientVersion } { clientVersion }
</div> </div>
{ this.renderEnode() }
<div className={ styles.netinfo }> <div className={ styles.netinfo }>
<BlockStatus /> <BlockStatus />
<div className={ netStyle }> <div className={ netStyle }>
@ -56,6 +55,7 @@ class Status extends Component {
{ netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers { netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
</div> </div>
</div> </div>
{ this.renderEnode() }
</div> </div>
); );
} }
@ -73,7 +73,7 @@ class Status extends Component {
return ( return (
<div className={ styles.enode }> <div className={ styles.enode }>
<CopyToClipboard data={ enode } /> <CopyToClipboard data={ enode } size={ 12 } />
<div>{ abbreviated }</div> <div>{ abbreviated }</div>
</div> </div>
); );

View File

@ -59,7 +59,7 @@ class Tab extends Component {
selected={ active } selected={ active }
icon={ view.icon } icon={ view.icon }
label={ label } label={ label }
onClick={ this.handleClick } onTouchTap={ this.handleClick }
> >
{ children } { children }
</MUITab> </MUITab>

View File

@ -16,7 +16,7 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { Container, ContainerTitle } from '../../../ui'; import { Container } from '../../../ui';
import Event from './Event'; import Event from './Event';
import styles from '../contract.css'; import styles from '../contract.css';
@ -48,8 +48,7 @@ export default class Events extends Component {
}); });
return ( return (
<Container> <Container title='events'>
<ContainerTitle title='events' />
<table className={ styles.events }> <table className={ styles.events }>
<tbody>{ list }</tbody> <tbody>{ list }</tbody>
</table> </table>

View File

@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react';
import { Card, CardTitle, CardText } from 'material-ui/Card'; import { Card, CardTitle, CardText } from 'material-ui/Card';
import InputQuery from './inputQuery'; import InputQuery from './inputQuery';
import { Container, ContainerTitle, Input, InputAddress } from '../../../ui'; import { Container, Input, InputAddress } from '../../../ui';
import styles from './queries.css'; import styles from './queries.css';
@ -55,8 +55,7 @@ export default class Queries extends Component {
.map((fn) => this.renderInputQuery(fn)); .map((fn) => this.renderInputQuery(fn));
return ( return (
<Container> <Container title='queries'>
<ContainerTitle title='queries' />
<div className={ styles.methods }> <div className={ styles.methods }>
<div className={ styles.vMethods }> <div className={ styles.vMethods }>
{ noInputQueries } { noInputQueries }

View File

@ -132,7 +132,8 @@ class Contract extends Component {
<Page> <Page>
<Header <Header
account={ account } account={ account }
balance={ balance } /> balance={ balance }
/>
<Queries <Queries
contract={ contract } contract={ contract }
values={ queryValues } /> values={ queryValues } />
@ -447,7 +448,10 @@ function mapStateToProps (state) {
} }
function mapDispatchToProps (dispatch) { function mapDispatchToProps (dispatch) {
return bindActionCreators({ newError, setVisibleAccounts }, dispatch); return bindActionCreators({
newError,
setVisibleAccounts
}, dispatch);
} }
export default connect( export default connect(

View File

@ -42,25 +42,26 @@
} }
.expanded { .expanded {
right: 16px; right: 1em;
max-height: 300px;
border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0;
overflow-y: auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
max-height: 19em;
} }
.expanded .content { .expanded .content {
flex: 1; flex: 1;
overflow: auto; overflow-y: auto;
overflow-x: hidden;
display: flex; display: flex;
background: rgba(0, 0, 0, 0.8); background: rgba(0, 0, 0, 0.8);
min-height: 16em;
} }
.corner { .corner {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 16px; right: 1em;
border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0;
} }
@ -118,7 +119,7 @@
} }
.header { .header {
height: 36px; height: 2em;
padding: 0.5em 1em; padding: 0.5em 1em;
background: rgba(0, 0, 0, 0.25); background: rgba(0, 0, 0, 0.25);
margin-bottom: 0; margin-bottom: 0;
@ -148,6 +149,7 @@
.actions { .actions {
float: right; float: right;
margin-top: -2px;
} }
.actions div { .actions div {

View File

@ -19,7 +19,7 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import NavigationRefresh from 'material-ui/svg-icons/navigation/refresh'; import NavigationRefresh from 'material-ui/svg-icons/navigation/refresh';
import { Button, Container, ContainerTitle, ParityBackground } from '../../../ui'; import { Button, Container, ParityBackground } from '../../../ui';
import { updateBackground } from '../actions'; import { updateBackground } from '../actions';
@ -55,8 +55,7 @@ class Background extends Component {
render () { render () {
return ( return (
<Container> <Container title='Background Pattern'>
<ContainerTitle title='Background Pattern' />
<div className={ layout.layout }> <div className={ layout.layout }>
<div className={ layout.overview }> <div className={ layout.overview }>
<div>The background pattern you can see right now is unique to your Parity installation. It will change every time you create a new Signer token. This is so that decentralized applications cannot pretend to be trustworthy.</div> <div>The background pattern you can see right now is unique to your Parity installation. It will change every time you create a new Signer token. This is so that decentralized applications cannot pretend to be trustworthy.</div>

View File

@ -17,7 +17,7 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { MenuItem } from 'material-ui'; import { MenuItem } from 'material-ui';
import { Select, Container, ContainerTitle } from '../../../ui'; import { Select, Container } from '../../../ui';
import layout from '../layout.css'; import layout from '../layout.css';
@ -43,8 +43,7 @@ export default class Parity extends Component {
render () { render () {
return ( return (
<Container> <Container title='Parity'>
<ContainerTitle title='Parity' />
<div className={ layout.layout }> <div className={ layout.layout }>
<div className={ layout.overview }> <div className={ layout.overview }>
<div>Control the Parity node settings and mode of operation via this interface.</div> <div>Control the Parity node settings and mode of operation via this interface.</div>

View File

@ -16,7 +16,7 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { Container, ContainerTitle } from '../../../ui'; import { Container } from '../../../ui';
import layout from '../layout.css'; import layout from '../layout.css';
import styles from './proxy.css'; import styles from './proxy.css';
@ -31,8 +31,7 @@ export default class Proxy extends Component {
const proxyurl = `${dappsUrl}/proxy/proxy.pac`; const proxyurl = `${dappsUrl}/proxy/proxy.pac`;
return ( return (
<Container> <Container title='Proxy'>
<ContainerTitle title='Proxy' />
<div className={ layout.layout }> <div className={ layout.layout }>
<div className={ layout.overview }> <div className={ layout.overview }>
<div>The proxy setup allows you to access Parity and all associated decentralized applications via memorable addresses.</div> <div>The proxy setup allows you to access Parity and all associated decentralized applications via memorable addresses.</div>

View File

@ -19,7 +19,7 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { Checkbox } from 'material-ui'; import { Checkbox } from 'material-ui';
import { Container, ContainerTitle } from '../../../ui'; import { Container } from '../../../ui';
import { toggleView } from '../actions'; import { toggleView } from '../actions';
@ -34,8 +34,7 @@ class Views extends Component {
render () { render () {
return ( return (
<Container> <Container title='Views'>
<ContainerTitle title='Views' />
<div className={ layout.layout }> <div className={ layout.layout }>
<div className={ layout.overview }> <div className={ layout.overview }>
<div>Manage the available application views, using only the parts of the application that is applicable to you.</div> <div>Manage the available application views, using only the parts of the application that is applicable to you.</div>

View File

@ -25,7 +25,8 @@ export default class RequestFinished extends Component {
result: PropTypes.any.isRequired, result: PropTypes.any.isRequired,
date: PropTypes.instanceOf(Date).isRequired, date: PropTypes.instanceOf(Date).isRequired,
payload: PropTypes.oneOfType([ payload: PropTypes.oneOfType([
PropTypes.shape({ transaction: PropTypes.object.isRequired }), PropTypes.shape({ signTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sign: PropTypes.object.isRequired }) PropTypes.shape({ sign: PropTypes.object.isRequired })
]).isRequired, ]).isRequired,
msg: PropTypes.string, msg: PropTypes.string,
@ -58,9 +59,8 @@ export default class RequestFinished extends Component {
); );
} }
if (payload.transaction) { const transaction = payload.sendTransaction || payload.signTransaction;
const { transaction } = payload; if (transaction) {
return ( return (
<TransactionFinished <TransactionFinished
className={ className } className={ className }

View File

@ -27,7 +27,8 @@ export default class RequestPending extends Component {
isSending: PropTypes.bool.isRequired, isSending: PropTypes.bool.isRequired,
date: PropTypes.instanceOf(Date).isRequired, date: PropTypes.instanceOf(Date).isRequired,
payload: PropTypes.oneOfType([ payload: PropTypes.oneOfType([
PropTypes.shape({ transaction: PropTypes.object.isRequired }), PropTypes.shape({ signTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sign: PropTypes.object.isRequired }) PropTypes.shape({ sign: PropTypes.object.isRequired })
]).isRequired, ]).isRequired,
className: PropTypes.string, className: PropTypes.string,
@ -64,9 +65,8 @@ export default class RequestPending extends Component {
); );
} }
if (payload.transaction) { const transaction = payload.sendTransaction || payload.signTransaction;
const { transaction } = payload; if (transaction) {
return ( return (
<TransactionPending <TransactionPending
className={ className } className={ className }

View File

@ -20,7 +20,7 @@ import AvPlay from 'material-ui/svg-icons/av/play-arrow';
import AvReplay from 'material-ui/svg-icons/av/replay'; import AvReplay from 'material-ui/svg-icons/av/replay';
import ReorderIcon from 'material-ui/svg-icons/action/reorder'; import ReorderIcon from 'material-ui/svg-icons/action/reorder';
import { Container, ContainerTitle } from '../../../../ui'; import { Container } from '../../../../ui';
import styles from './Debug.css'; import styles from './Debug.css';
@ -42,9 +42,7 @@ export default class Debug extends Component {
const { devLogsLevels } = nodeStatus; const { devLogsLevels } = nodeStatus;
return ( return (
<Container> <Container title='Node Logs'>
<ContainerTitle
title='Node Logs' />
{ this.renderActions() } { this.renderActions() }
<h2 className={ styles.subheader }> <h2 className={ styles.subheader }>
{ devLogsLevels || '-' } { devLogsLevels || '-' }

View File

@ -64,6 +64,10 @@ module.exports = {
test: /\.json$/, test: /\.json$/,
use: [ 'json-loader' ] use: [ 'json-loader' ]
}, },
{
test: /\.ejs$/,
use: [ 'ejs-loader' ]
},
{ {
test: /\.html$/, test: /\.html$/,
use: [ use: [

View File

@ -10,7 +10,7 @@ rustc-serialize = "0.3"
serde = "0.8" serde = "0.8"
serde_json = "0.8" serde_json = "0.8"
serde_macros = { version = "0.8", optional = true } serde_macros = { version = "0.8", optional = true }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
[build-dependencies] [build-dependencies]
serde_codegen = { version = "0.8", optional = true } serde_codegen = { version = "0.8", optional = true }

View File

@ -22,7 +22,7 @@ use std::thread::sleep;
use std::sync::Arc; use std::sync::Arc;
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use io::{PanicHandler, ForwardPanic}; use io::{PanicHandler, ForwardPanic};
use util::{ToPretty, Uint}; use util::{ToPretty, Uint, U256, H256, Address, Hashable};
use rlp::PayloadInfo; use rlp::PayloadInfo;
use ethcore::service::ClientService; use ethcore::service::ClientService;
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockImportError, BlockChainClient, BlockID}; use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockImportError, BlockChainClient, BlockID};
@ -65,6 +65,7 @@ impl FromStr for DataFormat {
pub enum BlockchainCmd { pub enum BlockchainCmd {
Import(ImportBlockchain), Import(ImportBlockchain),
Export(ExportBlockchain), Export(ExportBlockchain),
ExportState(ExportState),
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -103,10 +104,31 @@ pub struct ExportBlockchain {
pub check_seal: bool, pub check_seal: bool,
} }
#[derive(Debug, PartialEq)]
pub struct ExportState {
pub spec: SpecType,
pub cache_config: CacheConfig,
pub dirs: Directories,
pub file_path: Option<String>,
pub format: Option<DataFormat>,
pub pruning: Pruning,
pub pruning_history: u64,
pub compaction: DatabaseCompactionProfile,
pub wal: bool,
pub fat_db: Switch,
pub tracing: Switch,
pub at: BlockID,
pub storage: bool,
pub code: bool,
pub min_balance: Option<U256>,
pub max_balance: Option<U256>,
}
pub fn execute(cmd: BlockchainCmd) -> Result<String, String> { pub fn execute(cmd: BlockchainCmd) -> Result<String, String> {
match cmd { match cmd {
BlockchainCmd::Import(import_cmd) => execute_import(import_cmd), BlockchainCmd::Import(import_cmd) => execute_import(import_cmd),
BlockchainCmd::Export(export_cmd) => execute_export(export_cmd), BlockchainCmd::Export(export_cmd) => execute_export(export_cmd),
BlockchainCmd::ExportState(export_cmd) => execute_export_state(export_cmd),
} }
} }
@ -245,6 +267,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
// save user defaults // save user defaults
user_defaults.pruning = algorithm; user_defaults.pruning = algorithm;
user_defaults.tracing = tracing; user_defaults.tracing = tracing;
user_defaults.fat_db = fat_db;
try!(user_defaults.save(&user_defaults_path)); try!(user_defaults.save(&user_defaults_path));
let report = client.report(); let report = client.report();
@ -261,23 +284,28 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
).into()) ).into())
} }
fn execute_export(cmd: ExportBlockchain) -> Result<String, String> { fn start_client(
// Setup panic handler dirs: Directories,
let panic_handler = PanicHandler::new_in_arc(); spec: SpecType,
pruning: Pruning,
pruning_history: u64,
tracing: Switch,
fat_db: Switch,
compaction: DatabaseCompactionProfile,
wal: bool,
cache_config: CacheConfig) -> Result<ClientService, String> {
// create dirs used by parity // create dirs used by parity
try!(cmd.dirs.create_dirs(false, false)); try!(dirs.create_dirs(false, false));
let format = cmd.format.unwrap_or_default();
// load spec file // load spec file
let spec = try!(cmd.spec.spec()); let spec = try!(spec.spec());
// load genesis hash // load genesis hash
let genesis_hash = spec.genesis_header().hash(); let genesis_hash = spec.genesis_header().hash();
// database paths // database paths
let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone()); let db_dirs = dirs.database(genesis_hash, spec.fork_name.clone());
// user defaults path // user defaults path
let user_defaults_path = db_dirs.user_defaults_path(); let user_defaults_path = db_dirs.user_defaults_path();
@ -288,34 +316,42 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
fdlimit::raise_fd_limit(); fdlimit::raise_fd_limit();
// select pruning algorithm // select pruning algorithm
let algorithm = cmd.pruning.to_algorithm(&user_defaults); let algorithm = pruning.to_algorithm(&user_defaults);
// check if tracing is on // check if tracing is on
let tracing = try!(tracing_switch_to_bool(cmd.tracing, &user_defaults)); let tracing = try!(tracing_switch_to_bool(tracing, &user_defaults));
// check if fatdb is on // check if fatdb is on
let fat_db = try!(fatdb_switch_to_bool(cmd.fat_db, &user_defaults, algorithm)); let fat_db = try!(fatdb_switch_to_bool(fat_db, &user_defaults, algorithm));
// prepare client and snapshot paths. // prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm); let client_path = db_dirs.client_path(algorithm);
let snapshot_path = db_dirs.snapshot_path(); let snapshot_path = db_dirs.snapshot_path();
// execute upgrades // execute upgrades
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path()))); try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.fork_path().as_path())));
// prepare client config // prepare client config
let client_config = to_client_config(&cmd.cache_config, Mode::Active, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm, cmd.pruning_history, cmd.check_seal); let client_config = to_client_config(&cache_config, Mode::Active, tracing, fat_db, compaction, wal, VMType::default(), "".into(), algorithm, pruning_history, true);
let service = try!(ClientService::start( let service = try!(ClientService::start(
client_config, client_config,
&spec, &spec,
&client_path, &client_path,
&snapshot_path, &snapshot_path,
&cmd.dirs.ipc_path(), &dirs.ipc_path(),
Arc::new(Miner::with_spec(&spec)), Arc::new(Miner::with_spec(&spec)),
).map_err(|e| format!("Client service error: {:?}", e))); ).map_err(|e| format!("Client service error: {:?}", e)));
drop(spec); drop(spec);
Ok(service)
}
fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
// Setup panic handler
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
let panic_handler = PanicHandler::new_in_arc();
let format = cmd.format.unwrap_or_default();
panic_handler.forward_from(&service); panic_handler.forward_from(&service);
let client = service.client(); let client = service.client();
@ -329,6 +365,9 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
let to = try!(client.block_number(cmd.to_block).ok_or("To block could not be found")); let to = try!(client.block_number(cmd.to_block).ok_or("To block could not be found"));
for i in from..(to + 1) { for i in from..(to + 1) {
if i % 10000 == 0 {
info!("#{}", i);
}
let b = try!(client.block(BlockID::Number(i)).ok_or("Error exporting incomplete chain")); let b = try!(client.block(BlockID::Number(i)).ok_or("Error exporting incomplete chain"));
match format { match format {
DataFormat::Binary => { out.write(&b).expect("Couldn't write to stream."); } DataFormat::Binary => { out.write(&b).expect("Couldn't write to stream."); }
@ -339,6 +378,85 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
Ok("Export completed.".into()) Ok("Export completed.".into())
} }
fn execute_export_state(cmd: ExportState) -> Result<String, String> {
// Setup panic handler
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
let panic_handler = PanicHandler::new_in_arc();
panic_handler.forward_from(&service);
let client = service.client();
let mut out: Box<io::Write> = match cmd.file_path {
Some(f) => Box::new(try!(fs::File::create(&f).map_err(|_| format!("Cannot write to file given: {}", f)))),
None => Box::new(io::stdout()),
};
let mut last: Option<Address> = None;
let at = cmd.at;
let mut i = 0usize;
out.write_fmt(format_args!("{{ \"state\": [", )).expect("Couldn't write to stream.");
loop {
let accounts = try!(client.list_accounts(at, last.as_ref(), 1000).ok_or("Specified block not found"));
if accounts.is_empty() {
break;
}
for account in accounts.into_iter() {
let balance = client.balance(&account, at).unwrap_or_else(U256::zero);
if cmd.min_balance.map_or(false, |m| balance < m) || cmd.max_balance.map_or(false, |m| balance > m) {
last = Some(account);
continue; //filtered out
}
if i != 0 {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!("\n\"0x{}\": {{\"balance\": \"{:x}\", \"nonce\": \"{:x}\"", account.hex(), balance, client.nonce(&account, at).unwrap_or_else(U256::zero))).expect("Write error");
let code = client.code(&account, at).unwrap_or(None).unwrap_or_else(Vec::new);
if !code.is_empty() {
out.write_fmt(format_args!(", \"code_hash\": \"0x{}\"", code.sha3().hex())).expect("Write error");
if cmd.code {
out.write_fmt(format_args!(", \"code\": \"{}\"", code.to_hex())).expect("Write error");
}
}
let storage_root = client.storage_root(&account, at).unwrap_or(::util::SHA3_NULL_RLP);
if storage_root != ::util::SHA3_NULL_RLP {
out.write_fmt(format_args!(", \"storage_root\": \"0x{}\"", storage_root.hex())).expect("Write error");
if cmd.storage {
out.write_fmt(format_args!(", \"storage\": {{")).expect("Write error");
let mut last_storage: Option<H256> = None;
loop {
let keys = try!(client.list_storage(at, &account, last_storage.as_ref(), 1000).ok_or("Specified block not found"));
if keys.is_empty() {
break;
}
let mut si = 0;
for key in keys.into_iter() {
if si != 0 {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!("\n\t\"0x{}\": \"0x{}\"", key.hex(), client.storage_at(&account, &key, at).unwrap_or_else(Default::default).hex())).expect("Write error");
si += 1;
last_storage = Some(key);
}
}
out.write(b"\n}").expect("Write error");
}
}
out.write(b"}").expect("Write error");
i += 1;
if i % 10000 == 0 {
info!("Account #{}", i);
}
last = Some(account);
}
}
out.write_fmt(format_args!("\n]}}")).expect("Write error");
Ok("Export completed.".into())
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::DataFormat; use super::DataFormat;

View File

@ -26,6 +26,8 @@ usage! {
cmd_new: bool, cmd_new: bool,
cmd_list: bool, cmd_list: bool,
cmd_export: bool, cmd_export: bool,
cmd_blocks: bool,
cmd_state: bool,
cmd_import: bool, cmd_import: bool,
cmd_signer: bool, cmd_signer: bool,
cmd_new_token: bool, cmd_new_token: bool,
@ -246,6 +248,10 @@ usage! {
flag_to: String = "latest", or |_| None, flag_to: String = "latest", or |_| None,
flag_format: Option<String> = None, or |_| None, flag_format: Option<String> = None, or |_| None,
flag_no_seal_check: bool = false, or |_| None, flag_no_seal_check: bool = false, or |_| None,
flag_no_storage: bool = false, or |_| None,
flag_no_code: bool = false, or |_| None,
flag_min_balance: Option<String> = None, or |_| None,
flag_max_balance: Option<String> = None, or |_| None,
// -- Snapshot Optons // -- Snapshot Optons
flag_at: String = "latest", or |_| None, flag_at: String = "latest", or |_| None,
@ -484,6 +490,8 @@ mod tests {
cmd_new: false, cmd_new: false,
cmd_list: false, cmd_list: false,
cmd_export: false, cmd_export: false,
cmd_state: false,
cmd_blocks: false,
cmd_import: false, cmd_import: false,
cmd_signer: false, cmd_signer: false,
cmd_new_token: false, cmd_new_token: false,
@ -600,6 +608,10 @@ mod tests {
flag_to: "latest".into(), flag_to: "latest".into(),
flag_format: None, flag_format: None,
flag_no_seal_check: false, flag_no_seal_check: false,
flag_no_code: false,
flag_no_storage: false,
flag_min_balance: None,
flag_max_balance: None,
// -- Snapshot Optons // -- Snapshot Optons
flag_at: "latest".into(), flag_at: "latest".into(),

View File

@ -10,7 +10,7 @@ Usage:
parity account import <path>... [options] parity account import <path>... [options]
parity wallet import <path> --password FILE [options] parity wallet import <path> --password FILE [options]
parity import [ <file> ] [options] parity import [ <file> ] [options]
parity export [ <file> ] [options] parity export (blocks | state) [ <file> ] [options]
parity signer new-token [options] parity signer new-token [options]
parity snapshot <file> [options] parity snapshot <file> [options]
parity restore [ <file> ] [options] parity restore [ <file> ] [options]
@ -271,6 +271,16 @@ Import/Export Options:
one of 'hex' and 'binary'. one of 'hex' and 'binary'.
(default: {flag_format:?} = Import: auto, Export: binary) (default: {flag_format:?} = Import: auto, Export: binary)
--no-seal-check Skip block seal check. (default: {flag_no_seal_check}) --no-seal-check Skip block seal check. (default: {flag_no_seal_check})
--at BLOCK Export state at the given block, which may be an
index, hash, or 'latest'. Note that taking snapshots at
non-recent blocks will only work with --pruning archive
(default: {flag_at})
--no-storage Don't export account storge. (default: {flag_no_storage})
--no-code Don't export account code. (default: {flag_no_code})
--min-balance WEI Don't export accounts with balance less than specified.
(default: {flag_min_balance:?})
--max-balance WEI Don't export accounts with balance greater than specified.
(default: {flag_max_balance:?})
Snapshot Options: Snapshot Options:
--at BLOCK Take a snapshot at the given block, which may be an --at BLOCK Take a snapshot at the given block, which may be an

View File

@ -37,7 +37,7 @@ use dir::Directories;
use dapps::Configuration as DappsConfiguration; use dapps::Configuration as DappsConfiguration;
use signer::{Configuration as SignerConfiguration}; use signer::{Configuration as SignerConfiguration};
use run::RunCmd; use run::RunCmd;
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat}; use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState, DataFormat};
use presale::ImportWallet; use presale::ImportWallet;
use account::{AccountCmd, NewAccount, ImportAccounts, ImportFromGethAccounts}; use account::{AccountCmd, NewAccount, ImportAccounts, ImportFromGethAccounts};
use snapshot::{self, SnapshotCommand}; use snapshot::{self, SnapshotCommand};
@ -161,23 +161,47 @@ impl Configuration {
}; };
Cmd::Blockchain(BlockchainCmd::Import(import_cmd)) Cmd::Blockchain(BlockchainCmd::Import(import_cmd))
} else if self.args.cmd_export { } else if self.args.cmd_export {
let export_cmd = ExportBlockchain { if self.args.cmd_blocks {
spec: spec, let export_cmd = ExportBlockchain {
cache_config: cache_config, spec: spec,
dirs: dirs, cache_config: cache_config,
file_path: self.args.arg_file.clone(), dirs: dirs,
format: format, file_path: self.args.arg_file.clone(),
pruning: pruning, format: format,
pruning_history: pruning_history, pruning: pruning,
compaction: compaction, pruning_history: pruning_history,
wal: wal, compaction: compaction,
tracing: tracing, wal: wal,
fat_db: fat_db, tracing: tracing,
from_block: try!(to_block_id(&self.args.flag_from)), fat_db: fat_db,
to_block: try!(to_block_id(&self.args.flag_to)), from_block: try!(to_block_id(&self.args.flag_from)),
check_seal: !self.args.flag_no_seal_check, to_block: try!(to_block_id(&self.args.flag_to)),
}; check_seal: !self.args.flag_no_seal_check,
Cmd::Blockchain(BlockchainCmd::Export(export_cmd)) };
Cmd::Blockchain(BlockchainCmd::Export(export_cmd))
} else if self.args.cmd_state {
let export_cmd = ExportState {
spec: spec,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
format: format,
pruning: pruning,
pruning_history: pruning_history,
compaction: compaction,
wal: wal,
tracing: tracing,
fat_db: fat_db,
at: try!(to_block_id(&self.args.flag_at)),
storage: !self.args.flag_no_storage,
code: !self.args.flag_no_code,
min_balance: self.args.flag_min_balance.and_then(|s| to_u256(&s).ok()),
max_balance: self.args.flag_max_balance.and_then(|s| to_u256(&s).ok()),
};
Cmd::Blockchain(BlockchainCmd::ExportState(export_cmd))
} else {
unreachable!();
}
} else if self.args.cmd_snapshot { } else if self.args.cmd_snapshot {
let snapshot_cmd = SnapshotCommand { let snapshot_cmd = SnapshotCommand {
cache_config: cache_config, cache_config: cache_config,
@ -690,7 +714,7 @@ mod tests {
use helpers::{replace_home, default_network_config}; use helpers::{replace_home, default_network_config};
use run::RunCmd; use run::RunCmd;
use signer::{Configuration as SignerConfiguration}; use signer::{Configuration as SignerConfiguration};
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat}; use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat, ExportState};
use presale::ImportWallet; use presale::ImportWallet;
use account::{AccountCmd, NewAccount, ImportAccounts}; use account::{AccountCmd, NewAccount, ImportAccounts};
use devtools::{RandomTempPath}; use devtools::{RandomTempPath};
@ -779,7 +803,7 @@ mod tests {
#[test] #[test]
fn test_command_blockchain_export() { fn test_command_blockchain_export() {
let args = vec!["parity", "export", "blockchain.json"]; let args = vec!["parity", "export", "blocks", "blockchain.json"];
let conf = parse(&args); let conf = parse(&args);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
spec: Default::default(), spec: Default::default(),
@ -799,9 +823,33 @@ mod tests {
}))); })));
} }
#[test]
fn test_command_state_export() {
let args = vec!["parity", "export", "state", "state.json"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::ExportState(ExportState {
spec: Default::default(),
cache_config: Default::default(),
dirs: Default::default(),
file_path: Some("state.json".into()),
pruning: Default::default(),
pruning_history: 64,
format: Default::default(),
compaction: Default::default(),
wal: true,
tracing: Default::default(),
fat_db: Default::default(),
at: BlockID::Latest,
storage: true,
code: true,
min_balance: None,
max_balance: None,
})));
}
#[test] #[test]
fn test_command_blockchain_export_with_custom_format() { fn test_command_blockchain_export_with_custom_format() {
let args = vec!["parity", "export", "--format", "hex", "blockchain.json"]; let args = vec!["parity", "export", "blocks", "--format", "hex", "blockchain.json"];
let conf = parse(&args); let conf = parse(&args);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain { assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
spec: Default::default(), spec: Default::default(),

View File

@ -257,17 +257,13 @@ pub fn tracing_switch_to_bool(switch: Switch, user_defaults: &UserDefaults) -> R
} }
} }
pub fn fatdb_switch_to_bool(switch: Switch, user_defaults: &UserDefaults, algorithm: Algorithm) -> Result<bool, String> { pub fn fatdb_switch_to_bool(switch: Switch, user_defaults: &UserDefaults, _algorithm: Algorithm) -> Result<bool, String> {
let result = match (user_defaults.is_first_launch, switch, user_defaults.fat_db) { let result = match (user_defaults.is_first_launch, switch, user_defaults.fat_db) {
(false, Switch::On, false) => Err("FatDB resync required".into()), (false, Switch::On, false) => Err("FatDB resync required".into()),
(_, Switch::On, _) => Ok(true), (_, Switch::On, _) => Ok(true),
(_, Switch::Off, _) => Ok(false), (_, Switch::Off, _) => Ok(false),
(_, Switch::Auto, def) => Ok(def), (_, Switch::Auto, def) => Ok(def),
}; };
if result.clone().unwrap_or(false) && algorithm != Algorithm::Archive {
return Err("Fat DB is not supported with the chosen pruning option. Please rerun with `--pruning=archive`".into());
}
result result
} }

View File

@ -156,7 +156,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
// get the mode // get the mode
let mode = try!(mode_switch_to_bool(cmd.mode, &user_defaults)); let mode = try!(mode_switch_to_bool(cmd.mode, &user_defaults));
trace!(target: "mode", "mode is {:?}", mode); trace!(target: "mode", "mode is {:?}", mode);
let network_enabled = match &mode { &Mode::Dark(_) | &Mode::Off => false, _ => true, }; let network_enabled = match mode { Mode::Dark(_) | Mode::Off => false, _ => true, };
// prepare client and snapshot paths. // prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm); let client_path = db_dirs.client_path(algorithm);
@ -219,7 +219,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
// create client config // create client config
let client_config = to_client_config( let client_config = to_client_config(
&cmd.cache_config, &cmd.cache_config,
mode, mode.clone(),
tracing, tracing,
fat_db, fat_db,
cmd.compaction, cmd.compaction,
@ -354,6 +354,8 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
// save user defaults // save user defaults
user_defaults.pruning = algorithm; user_defaults.pruning = algorithm;
user_defaults.tracing = tracing; user_defaults.tracing = tracing;
user_defaults.fat_db = fat_db;
user_defaults.mode = mode;
try!(user_defaults.save(&user_defaults_path)); try!(user_defaults.save(&user_defaults_path));
let on_mode_change = move |mode: &Mode| { let on_mode_change = move |mode: &Mode| {

View File

@ -29,7 +29,7 @@ fetch = { path = "../util/fetch" }
rustc-serialize = "0.3" rustc-serialize = "0.3"
transient-hashmap = "0.1" transient-hashmap = "0.1"
serde_macros = { version = "0.8.0", optional = true } serde_macros = { version = "0.8.0", optional = true }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" }
ethcore-ipc = { path = "../ipc/rpc" } ethcore-ipc = { path = "../ipc/rpc" }
time = "0.1" time = "0.1"

View File

@ -28,7 +28,6 @@ use ethstore::random_phrase;
use ethsync::{SyncProvider, ManageNetwork}; use ethsync::{SyncProvider, ManageNetwork};
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use ethcore::client::{MiningBlockChainClient}; use ethcore::client::{MiningBlockChainClient};
use ethcore::ids::BlockID;
use ethcore::mode::Mode; use ethcore::mode::Mode;
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
@ -38,9 +37,11 @@ use v1::types::{
Bytes, U256, H160, H256, H512, Bytes, U256, H160, H256, H512,
Peers, Transaction, RpcSettings, Histogram, Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus, TransactionStats, LocalTransactionStatus,
BlockNumber,
}; };
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
use v1::helpers::dispatch::DEFAULT_MAC; use v1::helpers::dispatch::DEFAULT_MAC;
use v1::helpers::auto_args::Trailing;
/// Parity implementation. /// Parity implementation.
pub struct ParityClient<C, M, S: ?Sized> where pub struct ParityClient<C, M, S: ?Sized> where
@ -234,19 +235,20 @@ impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
Ok(Brain::new(phrase).generate().unwrap().address().into()) Ok(Brain::new(phrase).generate().unwrap().address().into())
} }
fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error> { fn list_accounts(&self, count: u64, after: Option<H160>, block_number: Trailing<BlockNumber>) -> Result<Option<Vec<H160>>, Error> {
try!(self.active()); try!(self.active());
Ok(take_weak!(self.client) Ok(take_weak!(self.client)
.list_accounts(BlockID::Latest) .list_accounts(block_number.0.into(), after.map(Into::into).as_ref(), count)
.map(|a| a.into_iter().map(Into::into).collect())) .map(|a| a.into_iter().map(Into::into).collect()))
} }
fn list_storage_keys(&self, _address: H160) -> Result<Option<Vec<H256>>, Error> { fn list_storage_keys(&self, address: H160, count: u64, after: Option<H256>, block_number: Trailing<BlockNumber>) -> Result<Option<Vec<H256>>, Error> {
try!(self.active()); try!(self.active());
// TODO: implement this Ok(take_weak!(self.client)
Ok(None) .list_storage(block_number.0.into(), &address.into(), after.map(Into::into).as_ref(), count)
.map(|a| a.into_iter().map(Into::into).collect()))
} }
fn encrypt_message(&self, key: H512, phrase: Bytes) -> Result<Bytes, Error> { fn encrypt_message(&self, key: H512, phrase: Bytes) -> Result<Bytes, Error> {

View File

@ -89,7 +89,7 @@ fn should_return_list_of_items_to_confirm() {
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
let response = concat!( let response = concat!(
r#"{"jsonrpc":"2.0","result":["#, r#"{"jsonrpc":"2.0","result":["#,
r#"{"id":"0x1","payload":{"transaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#, r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#,
r#"],"id":1}"# r#"],"id":1}"#
); );

View File

@ -18,11 +18,12 @@
use jsonrpc_core::Error; use jsonrpc_core::Error;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use v1::helpers::auto_args::Wrap; use v1::helpers::auto_args::{Wrap, Trailing};
use v1::types::{ use v1::types::{
H160, H256, H512, U256, Bytes, H160, H256, H512, U256, Bytes,
Peers, Transaction, RpcSettings, Histogram, Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus, TransactionStats, LocalTransactionStatus,
BlockNumber
}; };
build_rpc_trait! { build_rpc_trait! {
@ -103,12 +104,12 @@ build_rpc_trait! {
/// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not. /// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not.
#[rpc(name = "parity_listAccounts")] #[rpc(name = "parity_listAccounts")]
fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error>; fn list_accounts(&self, u64, Option<H160>, Trailing<BlockNumber>) -> Result<Option<Vec<H160>>, Error>;
/// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`), /// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`),
/// or null if not. /// or null if not.
#[rpc(name = "parity_listStorageKeys")] #[rpc(name = "parity_listStorageKeys")]
fn list_storage_keys(&self, H160) -> Result<Option<Vec<H256>>, Error>; fn list_storage_keys(&self, H160, u64, Option<H256>, Trailing<BlockNumber>) -> Result<Option<Vec<H256>>, Error>;
/// Encrypt some data with a public key under ECIES. /// Encrypt some data with a public key under ECIES.
/// First parameter is the 512-byte destination public key, second is the message. /// First parameter is the 512-byte destination public key, second is the message.

View File

@ -105,10 +105,10 @@ impl Serialize for ConfirmationResponse {
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)] #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)]
pub enum ConfirmationPayload { pub enum ConfirmationPayload {
/// Send Transaction /// Send Transaction
#[serde(rename="transaction")] #[serde(rename="sendTransaction")]
SendTransaction(TransactionRequest), SendTransaction(TransactionRequest),
/// Sign Transaction /// Sign Transaction
#[serde(rename="transaction")] #[serde(rename="signTransaction")]
SignTransaction(TransactionRequest), SignTransaction(TransactionRequest),
/// Signature /// Signature
#[serde(rename="sign")] #[serde(rename="sign")]
@ -221,7 +221,49 @@ mod tests {
// when // when
let res = serde_json::to_string(&ConfirmationRequest::from(request)); let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"transaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
// then
assert_eq!(res.unwrap(), expected.to_owned());
}
#[test]
fn should_serialize_sign_transaction_confirmation() {
// given
let request = helpers::ConfirmationRequest {
id: 15.into(),
payload: helpers::ConfirmationPayload::SignTransaction(helpers::FilledTransactionRequest {
from: 0.into(),
to: None,
gas: 15_000.into(),
gas_price: 10_000.into(),
value: 100_000.into(),
data: vec![1, 2, 3],
nonce: Some(1.into()),
}),
};
// when
let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
// then
assert_eq!(res.unwrap(), expected.to_owned());
}
#[test]
fn should_serialize_decrypt_confirmation() {
// given
let request = helpers::ConfirmationRequest {
id: 15.into(),
payload: helpers::ConfirmationPayload::Decrypt(
10.into(), vec![1, 2, 3].into(),
),
};
// when
let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"decrypt":{"address":"0x000000000000000000000000000000000000000a","msg":"0x010203"}}}"#;
// then // then
assert_eq!(res.unwrap(), expected.to_owned()); assert_eq!(res.unwrap(), expected.to_owned());

View File

@ -23,7 +23,7 @@ ethcore-rpc = { path = "../rpc" }
ethcore-devtools = { path = "../devtools" } ethcore-devtools = { path = "../devtools" }
parity-ui = { path = "../dapps/ui", version = "1.4", optional = true } parity-ui = { path = "../dapps/ui", version = "1.4", optional = true }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
[features] [features]
dev = ["clippy"] dev = ["clippy"]

View File

@ -80,6 +80,7 @@ pub struct AuthCodes<T: TimeProvider = DefaultTimeProvider> {
impl AuthCodes<DefaultTimeProvider> { impl AuthCodes<DefaultTimeProvider> {
/// Reads `AuthCodes` from file and creates new instance using `DefaultTimeProvider`. /// Reads `AuthCodes` from file and creates new instance using `DefaultTimeProvider`.
#[cfg_attr(feature="dev", allow(single_char_pattern))]
pub fn from_file(file: &Path) -> io::Result<AuthCodes> { pub fn from_file(file: &Path) -> io::Result<AuthCodes> {
let content = { let content = {
if let Ok(mut file) = fs::File::open(file) { if let Ok(mut file) = fs::File::open(file) {
@ -128,7 +129,7 @@ impl<T: TimeProvider> AuthCodes<T> {
let mut file = try!(fs::File::create(file)); let mut file = try!(fs::File::create(file));
let content = self.codes.iter().map(|code| { let content = self.codes.iter().map(|code| {
let mut data = vec![code.code.clone(), encode_time(code.created_at.clone())]; let mut data = vec![code.code.clone(), encode_time(code.created_at.clone())];
if let Some(used_at) = code.last_used_at.clone() { if let Some(used_at) = code.last_used_at {
data.push(encode_time(used_at)); data.push(encode_time(used_at));
} }
data.join(SEPARATOR) data.join(SEPARATOR)

View File

@ -99,7 +99,7 @@ fn auth_is_valid(codes_path: &Path, protocols: ws::Result<Vec<&str>>) -> bool {
let res = codes.is_valid(&auth, time); let res = codes.is_valid(&auth, time);
// make sure to save back authcodes - it might have been modified // make sure to save back authcodes - it might have been modified
if let Err(_) = codes.to_file(codes_path) { if codes.to_file(codes_path).is_err() {
warn!(target: "signer", "Couldn't save authorization codes to file."); warn!(target: "signer", "Couldn't save authorization codes to file.");
} }
res res

View File

@ -17,7 +17,7 @@ ethcore-network = { path = "../util/network" }
ethcore-io = { path = "../util/io" } ethcore-io = { path = "../util/io" }
ethcore = { path = "../ethcore" } ethcore = { path = "../ethcore" }
rlp = { path = "../util/rlp" } rlp = { path = "../util/rlp" }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
log = "0.3" log = "0.3"
env_logger = "0.3" env_logger = "0.3"
time = "0.1.34" time = "0.1.34"

View File

@ -625,7 +625,7 @@ impl ChainSync {
Ok(()) Ok(())
} }
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))] #[cfg_attr(feature="dev", allow(cyclomatic_complexity, needless_borrow))]
/// Called by peer once it has new block headers during sync /// Called by peer once it has new block headers during sync
fn on_peer_block_headers(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { fn on_peer_block_headers(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> {
let confirmed = match self.peers.get_mut(&peer_id) { let confirmed = match self.peers.get_mut(&peer_id) {
@ -1174,7 +1174,7 @@ impl ChainSync {
} }
}, },
SyncState::SnapshotData => { SyncState::SnapshotData => {
if let RestorationStatus::Ongoing { state_chunks: _, block_chunks: _, state_chunks_done, block_chunks_done, } = io.snapshot_service().status() { if let RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } = io.snapshot_service().status() {
if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD {
trace!(target: "sync", "Snapshot queue full, pausing sync"); trace!(target: "sync", "Snapshot queue full, pausing sync");
self.state = SyncState::SnapshotWaiting; self.state = SyncState::SnapshotWaiting;
@ -1426,7 +1426,10 @@ impl ChainSync {
packet.append(&chain.best_block_hash); packet.append(&chain.best_block_hash);
packet.append(&chain.genesis_hash); packet.append(&chain.genesis_hash);
if warp_protocol { if warp_protocol {
let manifest = io.snapshot_service().manifest(); let manifest = match self.old_blocks.is_some() {
true => None,
false => io.snapshot_service().manifest(),
};
let block_number = manifest.as_ref().map_or(0, |m| m.block_number); let block_number = manifest.as_ref().map_or(0, |m| m.block_number);
let manifest_hash = manifest.map_or(H256::new(), |m| m.into_rlp().sha3()); let manifest_hash = manifest.map_or(H256::new(), |m| m.into_rlp().sha3());
packet.append(&manifest_hash); packet.append(&manifest_hash);
@ -1745,7 +1748,7 @@ impl ChainSync {
self.restart(io); self.restart(io);
self.continue_sync(io); self.continue_sync(io);
}, },
RestorationStatus::Ongoing { state_chunks: _, block_chunks: _, state_chunks_done, block_chunks_done, } => { RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } => {
if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD {
trace!(target:"sync", "Resuming snapshot sync"); trace!(target:"sync", "Resuming snapshot sync");
self.state = SyncState::SnapshotData; self.state = SyncState::SnapshotData;
@ -1999,12 +2002,16 @@ impl ChainSync {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::{HashSet, VecDeque};
use tests::helpers::*; use tests::helpers::*;
use tests::snapshot::TestSnapshotService; use tests::snapshot::TestSnapshotService;
use util::{U256, RwLock};
use util::sha3::Hashable;
use util::hash::{H256, FixedHash};
use util::bytes::Bytes;
use rlp::{Rlp, RlpStream, UntrustedRlp, View, Stream};
use super::*; use super::*;
use ::SyncConfig; use ::SyncConfig;
use util::*;
use rlp::*;
use super::{PeerInfo, PeerAsking}; use super::{PeerInfo, PeerAsking};
use ethcore::views::BlockView; use ethcore::views::BlockView;
use ethcore::header::*; use ethcore::header::*;

View File

@ -158,19 +158,19 @@ impl TestNet {
} }
pub fn peer(&self, i: usize) -> &TestPeer { pub fn peer(&self, i: usize) -> &TestPeer {
self.peers.get(i).unwrap() &self.peers[i]
} }
pub fn peer_mut(&mut self, i: usize) -> &mut TestPeer { pub fn peer_mut(&mut self, i: usize) -> &mut TestPeer {
self.peers.get_mut(i).unwrap() &mut self.peers[i]
} }
pub fn start(&mut self) { pub fn start(&mut self) {
for peer in 0..self.peers.len() { for peer in 0..self.peers.len() {
for client in 0..self.peers.len() { for client in 0..self.peers.len() {
if peer != client { if peer != client {
let mut p = self.peers.get_mut(peer).unwrap(); let mut p = &mut self.peers[peer];
p.sync.write().update_targets(&mut p.chain); p.sync.write().update_targets(&p.chain);
p.sync.write().on_peer_connected(&mut TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(client as PeerId)), client as PeerId); p.sync.write().on_peer_connected(&mut TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(client as PeerId)), client as PeerId);
} }
} }
@ -181,7 +181,7 @@ impl TestNet {
for peer in 0..self.peers.len() { for peer in 0..self.peers.len() {
if let Some(packet) = self.peers[peer].queue.pop_front() { if let Some(packet) = self.peers[peer].queue.pop_front() {
let disconnecting = { let disconnecting = {
let mut p = self.peers.get_mut(packet.recipient).unwrap(); let mut p = &mut self.peers[packet.recipient];
trace!("--- {} -> {} ---", peer, packet.recipient); trace!("--- {} -> {} ---", peer, packet.recipient);
let to_disconnect = { let to_disconnect = {
let mut io = TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(peer as PeerId)); let mut io = TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(peer as PeerId));
@ -198,7 +198,7 @@ impl TestNet {
}; };
for d in &disconnecting { for d in &disconnecting {
// notify other peers that this peer is disconnecting // notify other peers that this peer is disconnecting
let mut p = self.peers.get_mut(*d).unwrap(); let mut p = &mut self.peers[*d];
let mut io = TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(peer as PeerId)); let mut io = TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(peer as PeerId));
p.sync.write().on_peer_aborting(&mut io, peer as PeerId); p.sync.write().on_peer_aborting(&mut io, peer as PeerId);
} }

View File

@ -19,5 +19,5 @@ case $1 in
esac esac
. ./scripts/targets.sh . ./scripts/targets.sh
cargo test $OPTIONS --features "$FEATURES" $TARGETS $1 \ cargo test -j 8 $OPTIONS --features "$FEATURES" $TARGETS $1 \

View File

@ -23,7 +23,7 @@ rlp = { path = "rlp" }
heapsize = { version = "0.3", features = ["unstable"] } heapsize = { version = "0.3", features = ["unstable"] }
itertools = "0.4" itertools = "0.4"
sha3 = { path = "sha3" } sha3 = { path = "sha3" }
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
ethcore-devtools = { path = "../devtools" } ethcore-devtools = { path = "../devtools" }
libc = "0.2.7" libc = "0.2.7"
vergen = "0.1" vergen = "0.1"

View File

@ -15,7 +15,7 @@ time = "0.1.34"
tiny-keccak = "1.0" tiny-keccak = "1.0"
rust-crypto = "0.2.34" rust-crypto = "0.2.34"
slab = "0.2" slab = "0.2"
clippy = { version = "0.0.96", optional = true} clippy = { version = "0.0.103", optional = true}
igd = "0.5.0" igd = "0.5.0"
libc = "0.2.7" libc = "0.2.7"
parking_lot = "0.3" parking_lot = "0.3"

View File

@ -507,7 +507,7 @@ mod tests {
use std::io::{Read, Write, Error, Cursor, ErrorKind}; use std::io::{Read, Write, Error, Cursor, ErrorKind};
use mio::{Ready}; use mio::{Ready};
use std::collections::VecDeque; use std::collections::VecDeque;
use util::bytes::*; use util::bytes::Bytes;
use devtools::*; use devtools::*;
use io::*; use io::*;

View File

@ -555,10 +555,11 @@ impl Discovery {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use util::hash::*; use std::net::{SocketAddr};
use util::sha3::*; use util::sha3::Hashable;
use std::net::*; use util::FixedHash;
use node_table::*; use node_table::{Node, NodeId, NodeEndpoint};
use std::str::FromStr; use std::str::FromStr;
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use ethkey::{Random, Generator}; use ethkey::{Random, Generator};

View File

@ -333,7 +333,7 @@ mod test {
use std::sync::Arc; use std::sync::Arc;
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use super::*; use super::*;
use util::hash::*; use util::hash::{H256, FixedHash};
use io::*; use io::*;
use mio::tcp::TcpStream; use mio::tcp::TcpStream;
use stats::NetworkStats; use stats::NetworkStats;

View File

@ -357,9 +357,9 @@ pub fn is_valid_node_url(url: &str) -> bool {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use util::H512;
use std::str::FromStr; use std::str::FromStr;
use std::net::*;
use util::hash::*;
use devtools::*; use devtools::*;
use AllowIP; use AllowIP;

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