Merge branch 'master' into client-provider

This commit is contained in:
Robert Habermeier 2016-12-02 10:06:09 +01:00
commit 6e1a1f9dec
361 changed files with 10438 additions and 4056 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
@ -31,10 +30,12 @@ linux-stable:
- md5sum "parity_"$VER"_amd64.deb" > "parity_"$VER"_amd64.deb.md5" - md5sum "parity_"$VER"_amd64.deb" > "parity_"$VER"_amd64.deb.md5"
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
- aws configure set aws_secret_access_key $s3_secret - aws configure set aws_secret_access_key $s3_secret
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity --body target/release/parity - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity.md5 --body parity.md5 - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb" --body "parity_"$VER"_amd64.deb" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity --body target/release/parity
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb.md5" --body "parity_"$VER"_amd64.deb.md5" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity.md5 --body parity.md5
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb" --body "parity_"$VER"_amd64.deb"
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb.md5" --body "parity_"$VER"_amd64.deb.md5"
tags: tags:
- rust - rust
- rust-stable - rust-stable
@ -51,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
@ -70,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
@ -91,11 +92,13 @@ 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
- aws configure set aws_secret_access_key $s3_secret - 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/x86_64-unknown-centos-gnu
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity --body target/release/parity - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity --body target/release/parity
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity.md5 --body parity.md5 - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity.md5 --body parity.md5
tags: tags:
@ -116,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
@ -126,10 +129,12 @@ linux-i686:
- md5sum "parity_"$VER"_i386.deb" > "parity_"$VER"_i386.deb.md5" - md5sum "parity_"$VER"_i386.deb" > "parity_"$VER"_i386.deb.md5"
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
- aws configure set aws_secret_access_key $s3_secret - aws configure set aws_secret_access_key $s3_secret
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/parity --body target/i686-unknown-linux-gnu/release/parity - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/parity.md5 --body parity.md5 - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/i686-unknown-linux-gnu
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/"parity_"$VER"_i386.deb" --body "parity_"$VER"_i386.deb" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/parity --body target/i686-unknown-linux-gnu/release/parity
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/"parity_"$VER"_i386.deb.md5" --body "parity_"$VER"_i386.deb.md5" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/parity.md5 --body parity.md5
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/"parity_"$VER"_i386.deb" --body "parity_"$VER"_i386.deb"
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/"parity_"$VER"_i386.deb.md5" --body "parity_"$VER"_i386.deb.md5"
tags: tags:
- rust - rust
- rust-i686 - rust-i686
@ -156,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
@ -166,10 +171,12 @@ linux-armv7:
- md5sum "parity_"$VER"_armhf.deb" > "parity_"$VER"_armhf.deb.md5" - md5sum "parity_"$VER"_armhf.deb" > "parity_"$VER"_armhf.deb.md5"
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
- aws configure set aws_secret_access_key $s3_secret - aws configure set aws_secret_access_key $s3_secret
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/parity --body target/armv7-unknown-linux-gnueabihf/release/parity - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/parity.md5 --body parity.md5 - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/parity --body target/armv7-unknown-linux-gnueabihf/release/parity
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/parity.md5 --body parity.md5
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb"
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/armv7-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5"
tags: tags:
- rust - rust
- rust-arm - rust-arm
@ -196,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
@ -206,10 +213,12 @@ linux-arm:
- md5sum "parity_"$VER"_armhf.deb" > "parity_"$VER"_armhf.deb.md5" - md5sum "parity_"$VER"_armhf.deb" > "parity_"$VER"_armhf.deb.md5"
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
- aws configure set aws_secret_access_key $s3_secret - aws configure set aws_secret_access_key $s3_secret
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/parity --body target/arm-unknown-linux-gnueabihf/release/parity - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/parity.md5 --body parity.md5 - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/parity --body target/arm-unknown-linux-gnueabihf/release/parity
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/parity.md5 --body parity.md5
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb"
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabihf/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5"
tags: tags:
- rust - rust
- rust-arm - rust-arm
@ -222,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
@ -236,13 +245,15 @@ 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
- aws configure set aws_secret_access_key $s3_secret - aws configure set aws_secret_access_key $s3_secret
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabi/parity --body target/arm-unknown-linux-gnueabi/release/parity - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabi/parity.md5 --body parity.md5 - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/arm-unknown-linux-gnueabi
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabi/parity --body target/arm-unknown-linux-gnueabi/release/parity
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/arm-unknown-linux-gnueabi/parity.md5 --body parity.md5
tags: tags:
- rust - rust
- rust-arm - rust-arm
@ -269,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
@ -279,10 +290,12 @@ linux-aarch64:
- md5sum "parity_"$VER"_arm64.deb" > "parity_"$VER"_arm64.deb.md5" - md5sum "parity_"$VER"_arm64.deb" > "parity_"$VER"_arm64.deb.md5"
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
- aws configure set aws_secret_access_key $s3_secret - aws configure set aws_secret_access_key $s3_secret
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity --body target/aarch64-unknown-linux-gnu/release/parity - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity.md5 --body parity.md5 - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu
- aws s3api put-object --bucket builds-parity --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 --body target/aarch64-unknown-linux-gnu/release/parity
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/"parity_"$VER"_arm64.deb.md5" --body "parity_"$VER"_arm64.deb.md5" - 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: tags:
- rust - rust
- rust-arm - rust-arm
@ -299,13 +312,22 @@ darwin:
- stable - stable
- triggers - triggers
script: script:
- cargo build --release $CARGOFLAGS - cargo build -j 8 --release -p ethstore #$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
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
- mv target/release/Parity\ Ethereum.pkg "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg"
- md5sum "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg" >> "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5"
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
- aws configure set aws_secret_access_key $s3_secret - aws configure set aws_secret_access_key $s3_secret
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/parity --body target/release/parity - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/parity.md5 --body parity.md5 - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-apple-darwin
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/parity --body target/release/parity
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/parity.md5 --body parity.md5
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/"parity-"$VER"-osx-installer-EXPERIMENTAL.pkg" --body "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg"
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/"parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5" --body "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5"
tags: tags:
- osx - osx
artifacts: artifacts:
@ -328,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
@ -349,14 +371,20 @@ windows:
- cd ..\.. - cd ..\..
- aws configure set aws_access_key_id %s3_key% - aws configure set aws_access_key_id %s3_key%
- aws configure set aws_secret_access_key %s3_secret% - aws configure set aws_secret_access_key %s3_secret%
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.exe --body target\release\parity.exe - echo %CI_BUILD_REF_NAME%
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.exe.md5 --body target\release\parity.exe.md5 - echo %CI_BUILD_REF_NAME% | findstr /R "master" >nul 2>&1 && set S3_BUCKET=builds-parity-published || set S3_BUCKET=builds-parity
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.zip --body target\release\parity.zip - echo %CI_BUILD_REF_NAME% | findstr /R "beta" >nul 2>&1 && set S3_BUCKET=builds-parity-published || set S3_BUCKET=builds-parity
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.zip.md5 --body target\release\parity.zip.md5 - echo %CI_BUILD_REF_NAME% | findstr /R "stable" >nul 2>&1 && set S3_BUCKET=builds-parity-published || set S3_BUCKET=builds-parity
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe --body nsis\InstallParity.exe - echo %S3_BUCKET%
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5 - aws s3 rm --recursive s3://%S3_BUCKET%/%CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.exe --body target\release\parity.exe
- aws s3api put-object --bucket builds-parity --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5 - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.exe.md5 --body target\release\parity.exe.md5
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.zip --body target\release\parity.zip
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.zip.md5 --body target\release\parity.zip.md5
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe --body nsis\InstallParity.exe
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5
tags: tags:
- rust-windows - rust-windows
artifacts: artifacts:
@ -385,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
@ -394,13 +422,28 @@ test-rust-stable:
image: ethcore/rust:stable image: ethcore/rust:stable
before_script: before_script:
- git submodule update --init --recursive - git submodule update --init --recursive
- export JS_FILES_MODIFIED=$(git --no-pager diff --name-only CI_BUILD_REF CI_BUILD_REF@{1} | grep \.js | wc -l) - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep \.js | wc -l)
- echo $JS_FILES_MODIFIED - echo $JS_FILES_MODIFIED
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; fi - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"; else ./js/scripts/install-deps.sh;fi
script: script:
- export RUST_BACKTRACE=1 - export RUST_BACKTRACE=1
- echo $JS_FILES_MODIFIED - echo $JS_FILES_MODIFIED
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; else ./test.sh $CARGOFLAGS --no-release; fi - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"&./test.sh $CARGOFLAGS --no-release; else echo "skip rust test"&./js/scripts/lint.sh&./js/scripts/test.sh&./js/scripts/build.sh; fi
tags:
- rust
- rust-stable
js-test:
stage: test
image: ethcore/rust:stable
before_script:
- git submodule update --init --recursive
- export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep \.js | wc -l)
- echo $JS_FILES_MODIFIED
- if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"; else ./js/scripts/install-deps.sh;fi
script:
- export RUST_BACKTRACE=1
- echo $JS_FILES_MODIFIED
- if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js test"; else echo "skip rust test"&./js/scripts/lint.sh&./js/scripts/test.sh&./js/scripts/build.sh; fi
tags: tags:
- rust - rust
- rust-stable - rust-stable
@ -411,13 +454,10 @@ test-rust-beta:
image: ethcore/rust:beta image: ethcore/rust:beta
before_script: before_script:
- git submodule update --init --recursive - git submodule update --init --recursive
- export JS_FILES_MODIFIED=$(git --no-pager diff --name-only CI_BUILD_REF CI_BUILD_REF@{1} | grep \.js | wc -l)
- echo $JS_FILES_MODIFIED
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; fi
script: script:
- export RUST_BACKTRACE=1 - export RUST_BACKTRACE=1
- echo $JS_FILES_MODIFIED - echo $JS_FILES_MODIFIED
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; else ./test.sh $CARGOFLAGS --no-release; fi - ./test.sh $CARGOFLAGS --no-release
tags: tags:
- rust - rust
- rust-beta - rust-beta
@ -429,28 +469,13 @@ test-rust-nightly:
image: ethcore/rust:nightly image: ethcore/rust:nightly
before_script: before_script:
- git submodule update --init --recursive - git submodule update --init --recursive
- export JS_FILES_MODIFIED=$(git --no-pager diff --name-only CI_BUILD_REF CI_BUILD_REF@{1} | grep \.js | wc -l)
- echo $JS_FILES_MODIFIED
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; fi
script: script:
- export RUST_BACKTRACE=1 - export RUST_BACKTRACE=1
- echo $JS_FILES_MODIFIED - ./test.sh $CARGOFLAGS --no-release
- if [ -z $JS_FILES_MODIFIED ]; then echo "skip js test"; else ./test.sh $CARGOFLAGS --no-release; fi
tags: tags:
- rust - rust
- rust-nightly - rust-nightly
allow_failure: true allow_failure: true
js-tests:
stage: test
image: ethcore/rust:stable
before_script:
- ./js/scripts/install-deps.sh
script:
- ./js/scripts/lint.sh
- ./js/scripts/test.sh
- ./js/scripts/build.sh
tags:
- javascript-test
js-release: js-release:
stage: js-build stage: js-build
only: only:
@ -459,9 +484,11 @@ js-release:
- stable - stable
image: ethcore/rust:stable image: ethcore/rust:stable
before_script: before_script:
- if [[ $NIGHTLY != "master" ]]; then ./js/scripts/install-deps.sh; fi - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep \.js | wc -l)
- echo $JS_FILES_MODIFIED
- if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js build"; else ./js/scripts/install-deps.sh;fi
script: script:
- if [[ $NIGHTLY != "master" ]]; then ./js/scripts/build.sh; fi - echo $JS_FILES_MODIFIED
- if [[ $NIGHTLY != "master" ]]; then ./js/scripts/release.sh; fi - if [ "$JS_FILES_MODIFIED" = 0 ]; then echo "skip js build"; else ./js/scripts/build.sh&&./js/scripts/release.sh; fi
tags: tags:
- javascript - javascript

36
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",
@ -334,7 +334,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",
@ -386,7 +386,7 @@ version = "1.5.0"
dependencies = [ dependencies = [
"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)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (git+https://github.com/carllerche/mio)", "mio 0.6.1 (git+https://github.com/ethcore/mio)",
"parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -476,7 +476,7 @@ dependencies = [
"igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.1 (git+https://github.com/carllerche/mio)", "mio 0.6.1 (git+https://github.com/ethcore/mio)",
"parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0", "rlp 0.1.0",
@ -491,7 +491,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",
@ -521,7 +521,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",
@ -560,7 +560,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)",
@ -650,7 +650,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",
@ -1027,7 +1027,7 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.6.1" version = "0.6.1"
source = "git+https://github.com/carllerche/mio#56f8663510196fdca04bdf7c5f4d60b24297826f" source = "git+https://github.com/ethcore/mio#ef182bae193a9c7457cd2cf661fcaffb226e3eef"
dependencies = [ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1264,7 +1264,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#587684374a12bf715151dd987a552a3d61e42972" source = "git+https://github.com/ethcore/js-precompiled.git#a5a1c15f4d125654e1d1cdcb6b7f92a606f1d2d0"
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)",
] ]
@ -2006,8 +2006,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>"
@ -2054,7 +2054,7 @@ dependencies = [
"checksum mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)" = "<none>" "checksum mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)" = "<none>"
"checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e"
"checksum mio 0.6.0-dev (git+https://github.com/ethcore/mio?branch=timer-fix)" = "<none>" "checksum mio 0.6.0-dev (git+https://github.com/ethcore/mio?branch=timer-fix)" = "<none>"
"checksum mio 0.6.1 (git+https://github.com/carllerche/mio)" = "<none>" "checksum mio 0.6.1 (git+https://github.com/ethcore/mio)" = "<none>"
"checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a" "checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a"
"checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8" "checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8"
"checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>" "checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.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

@ -17,6 +17,7 @@
use endpoint::EndpointInfo; use endpoint::EndpointInfo;
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct App { pub struct App {
pub id: String, pub id: String,
pub name: String, pub name: String,
@ -54,6 +55,7 @@ impl Into<EndpointInfo> for App {
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ApiError { pub struct ApiError {
pub code: String, pub code: String,
pub title: String, pub title: String,

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

@ -3,6 +3,7 @@ WORKDIR /build
# install tools and dependencies # install tools and dependencies
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y \ apt-get install -y \
build-essential \
g++ \ g++ \
curl \ curl \
git \ git \

View File

@ -4,6 +4,7 @@ WORKDIR /build
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y \ apt-get install -y \
g++ \ g++ \
build-essential \
curl \ curl \
git \ git \
file \ file \

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

@ -21,8 +21,8 @@
"genesis": { "genesis": {
"seal": { "seal": {
"generic": { "generic": {
"fields": 1, "fields": 2,
"rlp": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" "rlp": "0x200"
} }
}, },
"difficulty": "0x20000", "difficulty": "0x20000",

View File

@ -8,7 +8,7 @@
"difficultyBoundDivisor": "0x0800", "difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d", "durationLimit": "0x0d",
"blockReward": "0x4563918244F40000", "blockReward": "0x4563918244F40000",
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d", "registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2",
"homesteadTransition": 0, "homesteadTransition": 0,
"eip150Transition": 0, "eip150Transition": 0,
"eip155Transition": 10, "eip155Transition": 10,

@ -1 +1 @@
Subproject commit 9028c4801fd39fbb71a9796979182549a24e81c8 Subproject commit d509c75936ec6cbba683ee1916aa0bca436bc376

View File

@ -11,9 +11,9 @@
}, },
"genesis": { "genesis": {
"seal": { "seal": {
"ethereum": { "generic": {
"nonce": "0x00006d6f7264656e", "fields": 0,
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" "rlp": "0x0"
} }
}, },
"difficulty": "0x20000", "difficulty": "0x20000",

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

@ -276,14 +276,20 @@ impl AccountProvider {
} }
/// Returns `true` if the password for `account` is `password`. `false` if not. /// Returns `true` if the password for `account` is `password`. `false` if not.
pub fn test_password(&self, account: &Address, password: String) -> Result<bool, Error> { pub fn test_password(&self, account: &Address, password: &str) -> Result<bool, Error> {
match self.sstore.sign(account, &password, &Default::default()) { match self.sstore.sign(account, password, &Default::default()) {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(SSError::InvalidPassword) => Ok(false), Err(SSError::InvalidPassword) => Ok(false),
Err(e) => Err(Error::SStore(e)), Err(e) => Err(Error::SStore(e)),
} }
} }
/// Permanently removes an account.
pub fn kill_account(&self, account: &Address, password: &str) -> Result<(), Error> {
try!(self.sstore.remove_account(account, &password));
Ok(())
}
/// Changes the password of `account` from `password` to `new_password`. Fails if incorrect `password` given. /// Changes the password of `account` from `password` to `new_password`. Fails if incorrect `password` given.
pub fn change_password(&self, account: &Address, password: String, new_password: String) -> Result<(), Error> { pub fn change_password(&self, account: &Address, password: String, new_password: String) -> Result<(), Error> {
self.sstore.change_password(account, &password, &new_password).map_err(Error::SStore) self.sstore.change_password(account, &password, &new_password).map_err(Error::SStore)

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

@ -140,7 +140,7 @@ pub trait BlockProvider {
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber>; fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber>;
/// Returns logs matching given filter. /// Returns logs matching given filter.
fn logs<F>(&self, mut blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry> fn logs<F>(&self, blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
where F: Fn(&LogEntry) -> bool, Self: Sized; where F: Fn(&LogEntry) -> bool, Self: Sized;
} }

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};
@ -173,9 +173,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));
@ -217,7 +218,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(),
}; };
@ -870,8 +871,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 {
@ -953,6 +954,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)
@ -970,7 +975,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;
@ -990,18 +995,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

@ -334,7 +334,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(
@ -386,6 +386,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()
} }
@ -417,10 +421,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

@ -69,6 +69,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)
@ -115,7 +119,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))
} }
@ -254,8 +254,8 @@ impl Engine for AuthorityRound {
/// Check if the signature belongs to the correct proposer. /// Check if the signature belongs to the correct proposer.
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
let header_step = try!(header_step(header)); let header_step = try!(header_step(header));
// Give one step slack if step is lagging, double vote is still not possible. // Give one step slack if step is lagging, double vote is still not possible.
if header_step <= self.step() + 1 { if header_step <= self.step() + 1 {
let proposer_signature = try!(header_signature(header)); let proposer_signature = try!(header_signature(header));
let ok_sig = try!(verify_address(self.step_proposer(header_step), &proposer_signature, &header.bare_hash())); let ok_sig = try!(verify_address(self.step_proposer(header_step), &proposer_signature, &header.bare_hash()));
@ -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();
@ -417,13 +418,13 @@ mod tests {
let engine = Spec::new_test_round().engine; let engine = Spec::new_test_round().engine;
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap(); let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
let mut step = UNIX_EPOCH.elapsed().unwrap().as_secs(); let time = UNIX_EPOCH.elapsed().unwrap().as_secs();
// Two authorities.
let mut step = time - time % 2;
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]); header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
let first_ok = engine.verify_block_seal(&header).is_ok(); assert!(engine.verify_block_seal(&header).is_err());
step = step + 1; step = step + 1;
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]); header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
let second_ok = engine.verify_block_seal(&header).is_ok(); assert!(engine.verify_block_seal(&header).is_ok());
assert!(first_ok ^ second_ok);
} }
} }

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

@ -34,7 +34,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
Some(x) if x < 1_150_000 => &old_schedule, Some(x) if x < 1_150_000 => &old_schedule,
Some(_) => &new_schedule Some(_) => &new_schedule
}; };
let allow_network_id_of_one = number.map_or(false, |n| n >= 3_500_000); let allow_network_id_of_one = number.map_or(false, |n| n >= 2_675_000);
let rlp: Vec<u8> = test.rlp.into(); let rlp: Vec<u8> = test.rlp.into();
let res = UntrustedRlp::new(&rlp) let res = UntrustedRlp::new(&rlp)

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.");
@ -580,29 +582,29 @@ impl Miner {
let gas_required = |tx: &SignedTransaction| tx.gas_required(&schedule).into(); let gas_required = |tx: &SignedTransaction| tx.gas_required(&schedule).into();
let best_block_header: Header = ::rlp::decode(&chain.best_block_header()); let best_block_header: Header = ::rlp::decode(&chain.best_block_header());
transactions.into_iter() transactions.into_iter()
.filter(|tx| match self.engine.verify_transaction_basic(tx, &best_block_header) { .map(|tx| {
Ok(()) => true, match self.engine.verify_transaction_basic(&tx, &best_block_header) {
Err(e) => { Err(e) => {
debug!(target: "miner", "Rejected tx {:?} with invalid signature: {:?}", tx.hash(), e); debug!(target: "miner", "Rejected tx {:?} with invalid signature: {:?}", tx.hash(), e);
false Err(e)
} },
} Ok(()) => {
) let origin = accounts.as_ref().and_then(|accounts| {
.map(|tx| { tx.sender().ok().and_then(|sender| match accounts.contains(&sender) {
let origin = accounts.as_ref().and_then(|accounts| { true => Some(TransactionOrigin::Local),
tx.sender().ok().and_then(|sender| match accounts.contains(&sender) { false => None,
true => Some(TransactionOrigin::Local), })
false => None, }).unwrap_or(default_origin);
})
}).unwrap_or(default_origin); match origin {
TransactionOrigin::Local | TransactionOrigin::RetractedBlock => {
match origin { transaction_queue.add(tx, origin, &fetch_account, &gas_required)
TransactionOrigin::Local | TransactionOrigin::RetractedBlock => { },
transaction_queue.add(tx, origin, &fetch_account, &gas_required) TransactionOrigin::External => {
transaction_queue.add_with_banlist(tx, &fetch_account, &gas_required)
}
}
}, },
TransactionOrigin::External => {
transaction_queue.add_with_banlist(tx, &fetch_account, &gas_required)
}
} }
}) })
.collect() .collect()
@ -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.
@ -466,11 +465,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() {

File diff suppressed because it is too large Load Diff

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

@ -128,6 +128,9 @@ impl<T> TraceDB<T> where T: DatabaseExtras {
/// Creates new instance of `TraceDB`. /// Creates new instance of `TraceDB`.
pub fn new(config: Config, tracesdb: Arc<Database>, extras: Arc<T>) -> Self { pub fn new(config: Config, tracesdb: Arc<Database>, extras: Arc<T>) -> Self {
let mut batch = DBTransaction::new(&tracesdb); let mut batch = DBTransaction::new(&tracesdb);
let genesis = extras.block_hash(0)
.expect("Genesis block is always inserted upon extras db creation qed");
batch.write(db::COL_TRACE, &genesis, &FlatBlockTraces::default());
batch.put(db::COL_TRACE, b"version", TRACE_DB_VER); batch.put(db::COL_TRACE, b"version", TRACE_DB_VER);
tracesdb.write(batch).expect("failed to update version"); tracesdb.write(batch).expect("failed to update version");
@ -413,8 +416,12 @@ mod tests {
struct NoopExtras; struct NoopExtras;
impl DatabaseExtras for NoopExtras { impl DatabaseExtras for NoopExtras {
fn block_hash(&self, _block_number: BlockNumber) -> Option<H256> { fn block_hash(&self, block_number: BlockNumber) -> Option<H256> {
unimplemented!(); if block_number == 0 {
Some(H256::default())
} else {
unimplemented!()
}
} }
fn transaction_hash(&self, _block_number: BlockNumber, _tx_position: usize) -> Option<H256> { fn transaction_hash(&self, _block_number: BlockNumber, _tx_position: usize) -> Option<H256> {
@ -581,35 +588,21 @@ mod tests {
let db = Arc::new(Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), temp.as_str()).unwrap()); let db = Arc::new(Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), temp.as_str()).unwrap());
let mut config = Config::default(); let mut config = Config::default();
config.enabled = true; config.enabled = true;
let block_0 = H256::from(0xa1); let block_1 = H256::from(0xa1);
let block_1 = H256::from(0xa2); let block_2 = H256::from(0xa2);
let tx_0 = H256::from(0xff); let tx_1 = H256::from(0xff);
let tx_1 = H256::from(0xaf); let tx_2 = H256::from(0xaf);
let mut extras = Extras::default(); let mut extras = Extras::default();
extras.block_hashes.insert(0, block_0.clone()); extras.block_hashes.insert(0, H256::default());
extras.block_hashes.insert(1, block_1.clone()); extras.block_hashes.insert(1, block_1.clone());
extras.transaction_hashes.insert(0, vec![tx_0.clone()]); extras.block_hashes.insert(2, block_2.clone());
extras.transaction_hashes.insert(1, vec![tx_1.clone()]); extras.transaction_hashes.insert(1, vec![tx_1.clone()]);
extras.transaction_hashes.insert(2, vec![tx_2.clone()]);
let tracedb = TraceDB::new(config, db.clone(), Arc::new(extras)); let tracedb = TraceDB::new(config, db.clone(), Arc::new(extras));
// import block 0
let request = create_simple_import_request(0, block_0.clone());
let mut batch = DBTransaction::new(&db);
tracedb.import(&mut batch, request);
db.write(batch).unwrap();
let filter = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![]),
};
let traces = tracedb.filter(&filter);
assert_eq!(traces.len(), 1);
assert_eq!(traces[0], create_simple_localized_trace(0, block_0.clone(), tx_0.clone()));
// import block 1 // import block 1
let request = create_simple_import_request(1, block_1.clone()); let request = create_simple_import_request(1, block_1.clone());
let mut batch = DBTransaction::new(&db); let mut batch = DBTransaction::new(&db);
@ -617,38 +610,56 @@ mod tests {
db.write(batch).unwrap(); db.write(batch).unwrap();
let filter = Filter { let filter = Filter {
range: (0..1), range: (1..1),
from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![]),
};
let traces = tracedb.filter(&filter);
assert_eq!(traces.len(), 1);
assert_eq!(traces[0], create_simple_localized_trace(1, block_1.clone(), tx_1.clone()));
// import block 2
let request = create_simple_import_request(2, block_2.clone());
let mut batch = DBTransaction::new(&db);
tracedb.import(&mut batch, request);
db.write(batch).unwrap();
let filter = Filter {
range: (1..2),
from_address: AddressesFilter::from(vec![Address::from(1)]), from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![]), to_address: AddressesFilter::from(vec![]),
}; };
let traces = tracedb.filter(&filter); let traces = tracedb.filter(&filter);
assert_eq!(traces.len(), 2); assert_eq!(traces.len(), 2);
assert_eq!(traces[0], create_simple_localized_trace(0, block_0.clone(), tx_0.clone())); assert_eq!(traces[0], create_simple_localized_trace(1, block_1.clone(), tx_1.clone()));
assert_eq!(traces[1], create_simple_localized_trace(1, block_1.clone(), tx_1.clone())); assert_eq!(traces[1], create_simple_localized_trace(2, block_2.clone(), tx_2.clone()));
let traces = tracedb.block_traces(0).unwrap(); assert!(tracedb.block_traces(0).is_some(), "Genesis trace should be always present.");
assert_eq!(traces.len(), 1);
assert_eq!(traces[0], create_simple_localized_trace(0, block_0.clone(), tx_0.clone()));
let traces = tracedb.block_traces(1).unwrap(); let traces = tracedb.block_traces(1).unwrap();
assert_eq!(traces.len(), 1); assert_eq!(traces.len(), 1);
assert_eq!(traces[0], create_simple_localized_trace(1, block_1.clone(), tx_1.clone())); assert_eq!(traces[0], create_simple_localized_trace(1, block_1.clone(), tx_1.clone()));
assert_eq!(None, tracedb.block_traces(2)); let traces = tracedb.block_traces(2).unwrap();
let traces = tracedb.transaction_traces(0, 0).unwrap();
assert_eq!(traces.len(), 1); assert_eq!(traces.len(), 1);
assert_eq!(traces[0], create_simple_localized_trace(0, block_0.clone(), tx_0.clone())); assert_eq!(traces[0], create_simple_localized_trace(2, block_2.clone(), tx_2.clone()));
assert_eq!(None, tracedb.block_traces(3));
let traces = tracedb.transaction_traces(1, 0).unwrap(); let traces = tracedb.transaction_traces(1, 0).unwrap();
assert_eq!(traces.len(), 1); assert_eq!(traces.len(), 1);
assert_eq!(traces[0], create_simple_localized_trace(1, block_1.clone(), tx_1.clone())); assert_eq!(traces[0], create_simple_localized_trace(1, block_1.clone(), tx_1.clone()));
assert_eq!(None, tracedb.transaction_traces(1, 1)); let traces = tracedb.transaction_traces(2, 0).unwrap();
assert_eq!(traces.len(), 1);
assert_eq!(traces[0], create_simple_localized_trace(2, block_2.clone(), tx_2.clone()));
assert_eq!(None, tracedb.transaction_traces(2, 1));
assert_eq!(tracedb.trace(0, 0, vec![]).unwrap(), create_simple_localized_trace(0, block_0.clone(), tx_0.clone()));
assert_eq!(tracedb.trace(1, 0, vec![]).unwrap(), create_simple_localized_trace(1, block_1.clone(), tx_1.clone())); assert_eq!(tracedb.trace(1, 0, vec![]).unwrap(), create_simple_localized_trace(1, block_1.clone(), tx_1.clone()));
assert_eq!(tracedb.trace(2, 0, vec![]).unwrap(), create_simple_localized_trace(2, block_2.clone(), tx_2.clone()));
} }
#[test] #[test]
@ -660,8 +671,10 @@ mod tests {
let block_0 = H256::from(0xa1); let block_0 = H256::from(0xa1);
let tx_0 = H256::from(0xff); let tx_0 = H256::from(0xff);
extras.block_hashes.insert(0, block_0.clone()); extras.block_hashes.insert(0, H256::default());
extras.transaction_hashes.insert(0, vec![tx_0.clone()]); extras.transaction_hashes.insert(0, vec![]);
extras.block_hashes.insert(1, block_0.clone());
extras.transaction_hashes.insert(1, vec![tx_0.clone()]);
// set tracing on // set tracing on
config.enabled = true; config.enabled = true;
@ -669,8 +682,8 @@ mod tests {
{ {
let tracedb = TraceDB::new(config.clone(), db.clone(), Arc::new(extras.clone())); let tracedb = TraceDB::new(config.clone(), db.clone(), Arc::new(extras.clone()));
// import block 0 // import block 1
let request = create_simple_import_request(0, block_0.clone()); let request = create_simple_import_request(1, block_0.clone());
let mut batch = DBTransaction::new(&db); let mut batch = DBTransaction::new(&db);
tracedb.import(&mut batch, request); tracedb.import(&mut batch, request);
db.write(batch).unwrap(); db.write(batch).unwrap();
@ -678,8 +691,28 @@ mod tests {
{ {
let tracedb = TraceDB::new(config.clone(), db.clone(), Arc::new(extras)); let tracedb = TraceDB::new(config.clone(), db.clone(), Arc::new(extras));
let traces = tracedb.transaction_traces(0, 0); let traces = tracedb.transaction_traces(1, 0);
assert_eq!(traces.unwrap(), vec![create_simple_localized_trace(0, block_0, tx_0)]); assert_eq!(traces.unwrap(), vec![create_simple_localized_trace(1, block_0, tx_0)]);
} }
} }
#[test]
fn query_genesis() {
let temp = RandomTempPath::new();
let db = new_db(temp.as_str());
let mut config = Config::default();
let mut extras = Extras::default();
let block_0 = H256::from(0xa1);
extras.block_hashes.insert(0, block_0.clone());
extras.transaction_hashes.insert(0, vec![]);
// set tracing on
config.enabled = true;
let tracedb = TraceDB::new(config.clone(), db.clone(), Arc::new(extras.clone()));
let traces = tracedb.block_traces(0).unwrap();
assert_eq!(traces.len(), 0);
}
} }

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

@ -119,7 +119,7 @@ impl Into<Vec<FlatTrace>> for FlatTransactionTraces {
} }
/// Represents all traces produced by transactions in a single block. /// Represents all traces produced by transactions in a single block.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone, Default)]
pub struct FlatBlockTraces(Vec<FlatTransactionTraces>); pub struct FlatBlockTraces(Vec<FlatTransactionTraces>);
impl HeapSizeOf for FlatBlockTraces { impl HeapSizeOf for FlatBlockTraces {

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

@ -35,6 +35,9 @@ pub mod kind;
const MIN_MEM_LIMIT: usize = 16384; const MIN_MEM_LIMIT: usize = 16384;
const MIN_QUEUE_LIMIT: usize = 512; const MIN_QUEUE_LIMIT: usize = 512;
// maximum possible number of verification threads.
const MAX_VERIFIERS: usize = 8;
/// Type alias for block queue convenience. /// Type alias for block queue convenience.
pub type BlockQueue = VerificationQueue<self::kind::Blocks>; pub type BlockQueue = VerificationQueue<self::kind::Blocks>;
@ -61,6 +64,37 @@ impl Default for Config {
} }
} }
struct VerifierHandle {
deleting: Arc<AtomicBool>,
sleep: Arc<AtomicBool>,
thread: JoinHandle<()>,
}
impl VerifierHandle {
// signal to the verifier thread that it should sleep.
fn sleep(&self) {
self.sleep.store(true, AtomicOrdering::SeqCst);
}
// signal to the verifier thread that it should wake up.
fn wake_up(&self) {
self.sleep.store(false, AtomicOrdering::SeqCst);
self.thread.thread().unpark();
}
// signal to the verifier thread that it should conclude its
// operations.
fn conclude(&self) {
self.wake_up();
self.deleting.store(true, AtomicOrdering::Release);
}
// join the verifier thread.
fn join(self) {
self.thread.join().expect("Verifier thread panicked");
}
}
/// An item which is in the process of being verified. /// An item which is in the process of being verified.
pub struct Verifying<K: Kind> { pub struct Verifying<K: Kind> {
hash: H256, hash: H256,
@ -97,11 +131,12 @@ pub struct VerificationQueue<K: Kind> {
engine: Arc<Engine>, engine: Arc<Engine>,
more_to_verify: Arc<SCondvar>, more_to_verify: Arc<SCondvar>,
verification: Arc<Verification<K>>, verification: Arc<Verification<K>>,
verifiers: Vec<JoinHandle<()>>, verifiers: Mutex<(Vec<VerifierHandle>, usize)>,
deleting: Arc<AtomicBool>, deleting: Arc<AtomicBool>,
ready_signal: Arc<QueueSignal>, ready_signal: Arc<QueueSignal>,
empty: Arc<SCondvar>, empty: Arc<SCondvar>,
processing: RwLock<HashSet<H256>>, processing: RwLock<HashSet<H256>>,
ticks_since_adjustment: AtomicUsize,
max_queue_size: usize, max_queue_size: usize,
max_mem_use: usize, max_mem_use: usize,
} }
@ -157,6 +192,7 @@ struct Verification<K: Kind> {
more_to_verify: SMutex<()>, more_to_verify: SMutex<()>,
empty: SMutex<()>, empty: SMutex<()>,
sizes: Sizes, sizes: Sizes,
check_seal: bool,
} }
impl<K: Kind> VerificationQueue<K> { impl<K: Kind> VerificationQueue<K> {
@ -173,7 +209,8 @@ impl<K: Kind> VerificationQueue<K> {
unverified: AtomicUsize::new(0), unverified: AtomicUsize::new(0),
verifying: AtomicUsize::new(0), verifying: AtomicUsize::new(0),
verified: AtomicUsize::new(0), verified: AtomicUsize::new(0),
} },
check_seal: check_seal,
}); });
let more_to_verify = Arc::new(SCondvar::new()); let more_to_verify = Arc::new(SCondvar::new());
let deleting = Arc::new(AtomicBool::new(false)); let deleting = Arc::new(AtomicBool::new(false));
@ -185,44 +222,82 @@ impl<K: Kind> VerificationQueue<K> {
let empty = Arc::new(SCondvar::new()); let empty = Arc::new(SCondvar::new());
let panic_handler = PanicHandler::new_in_arc(); let panic_handler = PanicHandler::new_in_arc();
let mut verifiers: Vec<JoinHandle<()>> = Vec::new(); let max_verifiers = min(::num_cpus::get(), MAX_VERIFIERS);
let thread_count = max(::num_cpus::get(), 3) - 2; let default_amount = max(::num_cpus::get(), 3) - 2;
for i in 0..thread_count { let mut verifiers = Vec::with_capacity(max_verifiers);
let verification = verification.clone();
let engine = engine.clone(); debug!(target: "verification", "Allocating {} verifiers, {} initially active", max_verifiers, default_amount);
let more_to_verify = more_to_verify.clone();
let ready_signal = ready_signal.clone(); for i in 0..max_verifiers {
let empty = empty.clone(); debug!(target: "verification", "Adding verification thread #{}", i);
let deleting = deleting.clone(); let deleting = deleting.clone();
let panic_handler = panic_handler.clone(); let panic_handler = panic_handler.clone();
verifiers.push( let verification = verification.clone();
thread::Builder::new() let engine = engine.clone();
.name(format!("Verifier #{}", i)) let wait = more_to_verify.clone();
.spawn(move || { let ready = ready_signal.clone();
panic_handler.catch_panic(move || { let empty = empty.clone();
VerificationQueue::verify(verification, engine, more_to_verify, ready_signal, deleting, empty, check_seal)
}).unwrap() // enable only the first few verifiers.
}) let sleep = if i < default_amount {
.expect("Error starting block verification thread") Arc::new(AtomicBool::new(false))
); } else {
Arc::new(AtomicBool::new(true))
};
verifiers.push(VerifierHandle {
deleting: deleting.clone(),
sleep: sleep.clone(),
thread: thread::Builder::new()
.name(format!("Verifier #{}", i))
.spawn(move || {
panic_handler.catch_panic(move || {
VerificationQueue::verify(verification, engine, wait, ready, deleting, empty, sleep)
}).unwrap()
})
.expect("Failed to create verifier thread.")
});
} }
VerificationQueue { VerificationQueue {
engine: engine, engine: engine,
panic_handler: panic_handler, panic_handler: panic_handler,
ready_signal: ready_signal.clone(), ready_signal: ready_signal,
more_to_verify: more_to_verify.clone(), more_to_verify: more_to_verify,
verification: verification.clone(), verification: verification,
verifiers: verifiers, verifiers: Mutex::new((verifiers, default_amount)),
deleting: deleting.clone(), deleting: deleting,
processing: RwLock::new(HashSet::new()), processing: RwLock::new(HashSet::new()),
empty: empty.clone(), empty: empty,
ticks_since_adjustment: AtomicUsize::new(0),
max_queue_size: max(config.max_queue_size, MIN_QUEUE_LIMIT), max_queue_size: max(config.max_queue_size, MIN_QUEUE_LIMIT),
max_mem_use: max(config.max_mem_use, MIN_MEM_LIMIT), max_mem_use: max(config.max_mem_use, MIN_MEM_LIMIT),
} }
} }
fn verify(verification: Arc<Verification<K>>, engine: Arc<Engine>, wait: Arc<SCondvar>, ready: Arc<QueueSignal>, deleting: Arc<AtomicBool>, empty: Arc<SCondvar>, check_seal: bool) { fn verify(
verification: Arc<Verification<K>>,
engine: Arc<Engine>,
wait: Arc<SCondvar>,
ready: Arc<QueueSignal>,
deleting: Arc<AtomicBool>,
empty: Arc<SCondvar>,
sleep: Arc<AtomicBool>,
) {
while !deleting.load(AtomicOrdering::Acquire) { while !deleting.load(AtomicOrdering::Acquire) {
{
while sleep.load(AtomicOrdering::SeqCst) {
trace!(target: "verification", "Verifier sleeping");
::std::thread::park();
trace!(target: "verification", "Verifier waking up");
if deleting.load(AtomicOrdering::Acquire) {
return;
}
}
}
{ {
let mut more_to_verify = verification.more_to_verify.lock().unwrap(); let mut more_to_verify = verification.more_to_verify.lock().unwrap();
@ -255,7 +330,7 @@ impl<K: Kind> VerificationQueue<K> {
}; };
let hash = item.hash(); let hash = item.hash();
let is_ready = match K::verify(item, &*engine, check_seal) { let is_ready = match K::verify(item, &*engine, verification.check_seal) {
Ok(verified) => { Ok(verified) => {
let mut verifying = verification.verifying.lock(); let mut verifying = verification.verifying.lock();
let mut idx = None; let mut idx = None;
@ -302,9 +377,15 @@ impl<K: Kind> VerificationQueue<K> {
} }
} }
fn drain_verifying(verifying: &mut VecDeque<Verifying<K>>, verified: &mut VecDeque<K::Verified>, bad: &mut HashSet<H256>, sizes: &Sizes) { fn drain_verifying(
verifying: &mut VecDeque<Verifying<K>>,
verified: &mut VecDeque<K::Verified>,
bad: &mut HashSet<H256>,
sizes: &Sizes,
) {
let mut removed_size = 0; let mut removed_size = 0;
let mut inserted_size = 0; let mut inserted_size = 0;
while let Some(output) = verifying.front_mut().and_then(|x| x.output.take()) { while let Some(output) = verifying.front_mut().and_then(|x| x.output.take()) {
assert!(verifying.pop_front().is_some()); assert!(verifying.pop_front().is_some());
let size = output.heap_size_of_children(); let size = output.heap_size_of_children();
@ -487,14 +568,85 @@ impl<K: Kind> VerificationQueue<K> {
} }
} }
/// Optimise memory footprint of the heap fields. /// Optimise memory footprint of the heap fields, and adjust the number of threads
/// to better suit the workload.
pub fn collect_garbage(&self) { pub fn collect_garbage(&self) {
{ // number of ticks to average queue stats over
self.verification.unverified.lock().shrink_to_fit(); // when deciding whether to change the number of verifiers.
#[cfg(not(test))]
const READJUSTMENT_PERIOD: usize = 12;
#[cfg(test)]
const READJUSTMENT_PERIOD: usize = 1;
let (u_len, v_len) = {
let u_len = {
let mut q = self.verification.unverified.lock();
q.shrink_to_fit();
q.len()
};
self.verification.verifying.lock().shrink_to_fit(); self.verification.verifying.lock().shrink_to_fit();
self.verification.verified.lock().shrink_to_fit();
} let v_len = {
let mut q = self.verification.verified.lock();
q.shrink_to_fit();
q.len()
};
(u_len as isize, v_len as isize)
};
self.processing.write().shrink_to_fit(); self.processing.write().shrink_to_fit();
if self.ticks_since_adjustment.fetch_add(1, AtomicOrdering::SeqCst) + 1 >= READJUSTMENT_PERIOD {
self.ticks_since_adjustment.store(0, AtomicOrdering::SeqCst);
} else {
return;
}
let current = self.verifiers.lock().1;
let diff = (v_len - u_len).abs();
let total = v_len + u_len;
self.scale_verifiers(
if u_len < 20 {
1
} else if diff <= total / 10 {
current
} else if v_len > u_len {
current - 1
} else {
current + 1
}
);
}
// wake up or sleep verifiers to get as close to the target as
// possible, never going over the amount of initially allocated threads
// or below 1.
fn scale_verifiers(&self, target: usize) {
let mut verifiers = self.verifiers.lock();
let &mut (ref mut verifiers, ref mut verifier_count) = &mut *verifiers;
let target = min(verifiers.len(), target);
let target = max(1, target);
debug!(target: "verification", "Scaling from {} to {} verifiers", verifier_count, target);
// scaling up
for i in *verifier_count..target {
debug!(target: "verification", "Waking up verifier {}", i);
verifiers[i].wake_up();
}
// scaling down.
for i in target..*verifier_count {
debug!(target: "verification", "Putting verifier {} to sleep", i);
verifiers[i].sleep();
}
*verifier_count = target;
} }
} }
@ -509,10 +661,23 @@ impl<K: Kind> Drop for VerificationQueue<K> {
trace!(target: "shutdown", "[VerificationQueue] Closing..."); trace!(target: "shutdown", "[VerificationQueue] Closing...");
self.clear(); self.clear();
self.deleting.store(true, AtomicOrdering::Release); self.deleting.store(true, AtomicOrdering::Release);
self.more_to_verify.notify_all();
for t in self.verifiers.drain(..) { let mut verifiers = self.verifiers.get_mut();
t.join().unwrap(); let mut verifiers = &mut verifiers.0;
// first pass to signal conclusion. must be done before
// notify or deadlock possible.
for handle in verifiers.iter() {
handle.conclude();
} }
self.more_to_verify.notify_all();
// second pass to join.
for handle in verifiers.drain(..) {
handle.join();
}
trace!(target: "shutdown", "[VerificationQueue] Closed."); trace!(target: "shutdown", "[VerificationQueue] Closed.");
} }
} }
@ -611,4 +776,56 @@ mod tests {
} }
assert!(queue.queue_info().is_full()); assert!(queue.queue_info().is_full());
} }
#[test]
fn scaling_limits() {
use super::MAX_VERIFIERS;
let queue = get_test_queue();
queue.scale_verifiers(MAX_VERIFIERS + 1);
assert!(queue.verifiers.lock().1 < MAX_VERIFIERS + 1);
queue.scale_verifiers(0);
assert!(queue.verifiers.lock().1 == 1);
}
#[test]
fn readjust_verifiers() {
let queue = get_test_queue();
// put all the verifiers to sleep to ensure
// the test isn't timing sensitive.
let num_verifiers = {
let verifiers = queue.verifiers.lock();
for i in 0..verifiers.1 {
verifiers.0[i].sleep();
}
verifiers.1
};
for block in get_good_dummy_block_seq(5000) {
queue.import(Unverified::new(block)).expect("Block good by definition; qed");
}
// almost all unverified == bump verifier count.
queue.collect_garbage();
assert_eq!(queue.verifiers.lock().1, num_verifiers + 1);
// wake them up again and verify everything.
{
let verifiers = queue.verifiers.lock();
for i in 0..verifiers.1 {
verifiers.0[i].wake_up();
}
}
queue.flush();
// nothing to verify == use minimum number of verifiers.
queue.collect_garbage();
assert_eq!(queue.verifiers.lock().1, 1);
}
} }

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

@ -47,7 +47,7 @@ impl Random for [u8; 32] {
pub fn random_phrase(words: usize) -> String { pub fn random_phrase(words: usize) -> String {
lazy_static! { lazy_static! {
static ref WORDS: Vec<String> = String::from_utf8_lossy(include_bytes!("../res/wordlist.txt")) static ref WORDS: Vec<String> = String::from_utf8_lossy(include_bytes!("../res/wordlist.txt"))
.split("\n") .lines()
.map(|s| s.to_owned()) .map(|s| s.to_owned())
.collect(); .collect();
} }
@ -55,8 +55,19 @@ pub fn random_phrase(words: usize) -> String {
(0..words).map(|_| rng.choose(&WORDS).unwrap()).join(" ") (0..words).map(|_| rng.choose(&WORDS).unwrap()).join(" ")
} }
#[test] #[cfg(test)]
fn should_produce_right_number_of_words() { mod tests {
let p = random_phrase(10); use super::random_phrase;
assert_eq!(p.split(" ").count(), 10);
#[test]
fn should_produce_right_number_of_words() {
let p = random_phrase(10);
assert_eq!(p.split(" ").count(), 10);
}
#[test]
fn should_not_include_carriage_return() {
let p = random_phrase(10);
assert!(!p.contains('\r'), "Carriage return should be trimmed.");
}
} }

View File

@ -1,5 +1,8 @@
{ {
"presets": ["es2017", "es2016", "es2015", "stage-0", "react"], "presets": [
"es2017", "es2016", "es2015",
"stage-0", "react"
],
"plugins": [ "plugins": [
"transform-runtime", "transform-runtime",
"transform-decorators-legacy", "transform-decorators-legacy",
@ -10,6 +13,9 @@
"env": { "env": {
"production": { "production": {
"plugins": ["transform-react-remove-prop-types"] "plugins": ["transform-react-remove-prop-types"]
},
"development": {
"plugins": ["react-hot-loader/babel"]
} }
} }
} }

View File

@ -15,6 +15,7 @@
"no-debugger": "error", "no-debugger": "error",
"no-alert": "error", "no-alert": "error",
"jsx-quotes": ["error", "prefer-single"], "jsx-quotes": ["error", "prefer-single"],
"react/jsx-curly-spacing": ["error", "always"] "react/jsx-curly-spacing": ["error", "always"],
"object-property-newline": 0
} }
} }

1
js/.npmrc Normal file
View File

@ -0,0 +1 @@
save-prefix='~'

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.58", "version": "0.2.84",
"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>",
@ -26,16 +26,16 @@
], ],
"scripts": { "scripts": {
"build": "npm run build:lib && npm run build:dll && npm run build:app", "build": "npm run build:lib && npm run build:dll && npm run build:app",
"build:app": "webpack --progress", "build:app": "webpack --config webpack/app --progress",
"build:lib": "webpack --config webpack.libraries --progress", "build:lib": "webpack --config webpack/libraries --progress",
"build:dll": "webpack --config webpack.vendor --progress", "build:dll": "webpack --config webpack/vendor --progress",
"ci:build": "npm run ci:build:lib && npm run ci:build:dll && npm run ci:build:app", "ci:build": "npm run ci:build:lib && npm run ci:build:dll && npm run ci:build:app",
"ci:build:app": "NODE_ENV=production webpack", "ci:build:app": "NODE_ENV=production webpack --config webpack/app",
"ci:build:lib": "NODE_ENV=production webpack --config webpack.libraries", "ci:build:lib": "NODE_ENV=production webpack --config webpack/libraries",
"ci:build:dll": "NODE_ENV=production webpack --config webpack.vendor", "ci:build:dll": "NODE_ENV=production webpack --config webpack/vendor",
"ci:build:npm": "NODE_ENV=production webpack --config webpack.npm", "ci:build:npm": "NODE_ENV=production webpack --config webpack/npm",
"start": "npm install && npm run build:lib && npm run build:dll && npm run start:app", "start": "npm install && npm run build:lib && npm run build:dll && npm run start:app",
"start:app": "webpack-dev-server -d --history-api-fallback --open --hot --inline --progress --colors --port 3000", "start:app": "node webpack/dev.server",
"clean": "rm -rf ./build ./coverage", "clean": "rm -rf ./build ./coverage",
"coveralls": "npm run testCoverage && coveralls < coverage/lcov.info", "coveralls": "npm run testCoverage && coveralls < coverage/lcov.info",
"lint": "eslint --ignore-path .gitignore ./src/", "lint": "eslint --ignore-path .gitignore ./src/",
@ -47,126 +47,133 @@
"prepush": "npm run lint:cached" "prepush": "npm run lint:cached"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.10.1", "babel-cli": "~6.18.0",
"babel-core": "^6.10.4", "babel-core": "~6.18.2",
"babel-eslint": "^7.1.0", "babel-eslint": "~7.1.0",
"babel-loader": "^6.2.3", "babel-loader": "~6.2.3",
"babel-plugin-lodash": "^3.2.2", "babel-plugin-lodash": "~3.2.2",
"babel-plugin-transform-class-properties": "^6.11.5", "babel-plugin-transform-class-properties": "~6.19.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-plugin-transform-decorators-legacy": "~1.3.4",
"babel-plugin-transform-react-remove-prop-types": "^0.2.9", "babel-plugin-transform-react-remove-prop-types": "~0.2.9",
"babel-plugin-transform-runtime": "^6.9.0", "babel-plugin-transform-runtime": "~6.15.0",
"babel-polyfill": "^6.13.0", "babel-polyfill": "~6.16.0",
"babel-preset-es2015": "^6.9.0", "babel-preset-es2015": "~6.18.0",
"babel-preset-es2015-rollup": "^1.1.1", "babel-preset-es2015-rollup": "~1.2.0",
"babel-preset-es2016": "^6.11.3", "babel-preset-es2016": "~6.16.0",
"babel-preset-es2017": "^6.14.0", "babel-preset-es2017": "~6.16.0",
"babel-preset-react": "^6.5.0", "babel-preset-react": "~6.16.0",
"babel-preset-stage-0": "^6.5.0", "babel-preset-stage-0": "~6.16.0",
"babel-register": "6.9.0", "babel-register": "6.18.0",
"babel-runtime": "^6.9.2", "babel-runtime": "~6.18.0",
"chai": "^3.5.0", "chai": "~3.5.0",
"chai-enzyme": "0.4.2", "chai-enzyme": "0.4.2",
"cheerio": "0.20.0", "cheerio": "0.20.0",
"copy-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "~4.0.0",
"core-js": "^2.4.1", "core-js": "~2.4.1",
"coveralls": "^2.11.11", "coveralls": "~2.11.11",
"css-loader": "^0.23.1", "css-loader": "~0.26.0",
"ejs-loader": "~0.3.0",
"enzyme": "2.3.0", "enzyme": "2.3.0",
"eslint": "^3.1.0", "eslint": "~3.10.2",
"eslint-config-semistandard": "^6.0.2", "eslint-config-semistandard": "~7.0.0",
"eslint-config-standard": "^5.3.5", "eslint-config-standard": "~6.2.1",
"eslint-config-standard-react": "^3.0.0", "eslint-config-standard-react": "~4.2.0",
"eslint-plugin-promise": "^2.0.0", "eslint-plugin-promise": "~3.4.0",
"eslint-plugin-react": "^5.1.1", "eslint-plugin-react": "~6.7.1",
"eslint-plugin-standard": "^2.0.0", "eslint-plugin-standard": "~2.0.0",
"extract-loader": "0.0.2", "express": "~4.14.0",
"extract-text-webpack-plugin": "^1.0.1", "extract-loader": "0.1.0",
"file-loader": "^0.8.5", "extract-text-webpack-plugin": "~2.0.0-beta.4",
"fs-extra": "^0.30.0", "file-loader": "~0.9.0",
"happypack": "^2.2.1", "fs-extra": "~0.30.0",
"history": "^2.0.0", "happypack": "~3.0.0",
"html-loader": "^0.4.4", "history": "~2.0.0",
"husky": "^0.11.9", "html-loader": "~0.4.4",
"html-webpack-plugin": "~2.24.1",
"http-proxy-middleware": "~0.17.2",
"husky": "~0.11.9",
"ignore-styles": "2.0.0", "ignore-styles": "2.0.0",
"image-webpack-loader": "^1.8.0", "image-webpack-loader": "~3.0.0",
"istanbul": "^1.0.0-alpha.2", "istanbul": "~1.0.0-alpha.2",
"jsdom": "9.2.1", "jsdom": "9.2.1",
"json-loader": "^0.5.4", "json-loader": "~0.5.4",
"mocha": "^3.0.0-1", "mocha": "~3.0.0-1",
"mock-local-storage": "1.0.2", "mock-local-storage": "1.0.2",
"mock-socket": "^3.0.1", "mock-socket": "~3.0.1",
"nock": "^8.0.0", "nock": "~8.0.0",
"postcss-import": "^8.1.2", "postcss-import": "8.1.0",
"postcss-loader": "^0.8.1", "postcss-loader": "~1.1.1",
"postcss-nested": "^1.0.0", "postcss-nested": "~1.0.0",
"postcss-simple-vars": "^3.0.0", "postcss-simple-vars": "~3.0.0",
"raw-loader": "^0.5.1", "progress": "~1.1.8",
"raw-loader": "~0.5.1",
"react-addons-perf": "~15.3.2",
"react-addons-test-utils": "~15.3.2", "react-addons-test-utils": "~15.3.2",
"react-copy-to-clipboard": "^4.2.3",
"react-dom": "~15.3.2", "react-dom": "~15.3.2",
"react-hot-loader": "~1.3.0", "react-hot-loader": "~3.0.0-beta.6",
"rucksack-css": "^0.8.6", "rucksack-css": "~0.8.6",
"sinon": "^1.17.4", "sinon": "~1.17.4",
"sinon-as-promised": "^4.0.2", "sinon-as-promised": "~4.0.2",
"sinon-chai": "^2.8.0", "sinon-chai": "~2.8.0",
"style-loader": "^0.13.0", "style-loader": "~0.13.0",
"url-loader": "^0.5.7", "url-loader": "~0.5.7",
"webpack": "^1.13.2", "webpack": "~2.1.0-beta.27",
"webpack-dev-server": "^1.15.2", "webpack-dev-middleware": "~1.8.4",
"webpack-error-notification": "0.1.6", "webpack-error-notification": "0.1.6",
"webpack-hot-middleware": "~2.13.2", "webpack-hot-middleware": "~2.13.2",
"websocket": "^1.0.23" "websocket": "~1.0.23"
}, },
"dependencies": { "dependencies": {
"bignumber.js": "^2.3.0", "bignumber.js": "~2.3.0",
"blockies": "0.0.2", "blockies": "0.0.2",
"brace": "^0.9.0", "brace": "~0.9.0",
"bytes": "^2.4.0", "bytes": "~2.4.0",
"chart.js": "^2.3.0", "chart.js": "~2.3.0",
"es6-error": "^4.0.0", "es6-error": "~4.0.0",
"es6-promise": "^3.2.1", "es6-promise": "~3.2.1",
"ethereumjs-tx": "^1.1.2", "ethereumjs-tx": "~1.1.2",
"file-saver": "^1.3.3", "eventemitter3": "~2.0.2",
"format-json": "^1.0.3", "file-saver": "~1.3.3",
"format-number": "^2.0.1", "format-json": "~1.0.3",
"geopattern": "^1.2.3", "format-number": "~2.0.1",
"isomorphic-fetch": "^2.2.1", "geopattern": "~1.2.3",
"js-sha3": "^0.5.2", "isomorphic-fetch": "~2.2.1",
"lodash": "^4.11.1", "js-sha3": "~0.5.2",
"marked": "^0.3.6", "lodash": "~4.11.1",
"marked": "~0.3.6",
"material-ui": "0.16.1", "material-ui": "0.16.1",
"material-ui-chip-input": "^0.8.0", "material-ui-chip-input": "~0.8.0",
"mobx": "^2.6.1", "mobx": "~2.6.1",
"mobx-react": "^3.5.8", "mobx-react": "~3.5.8",
"mobx-react-devtools": "^4.2.9", "mobx-react-devtools": "~4.2.9",
"moment": "^2.14.1", "moment": "~2.14.1",
"phoneformat.js": "^1.0.3", "phoneformat.js": "~1.0.3",
"qs": "^6.3.0", "qs": "~6.3.0",
"react": "~15.3.2", "react": "~15.3.2",
"react-ace": "^4.0.0", "react-ace": "~4.0.0",
"react-addons-css-transition-group": "~15.3.2", "react-addons-css-transition-group": "~15.3.2",
"react-chartjs-2": "^1.5.0", "react-chartjs-2": "~1.5.0",
"react-copy-to-clipboard": "~4.2.3",
"react-dom": "~15.3.2", "react-dom": "~15.3.2",
"react-dropzone": "^3.7.3", "react-dropzone": "~3.7.3",
"react-redux": "^4.4.5", "react-redux": "~4.4.5",
"react-router": "^2.6.1", "react-router": "~2.6.1",
"react-router-redux": "^4.0.5", "react-router-redux": "~4.0.5",
"react-tap-event-plugin": "~1.0.0", "react-tap-event-plugin": "~1.0.0",
"react-tooltip": "^2.0.3", "react-tooltip": "~2.0.3",
"recharts": "^0.15.2", "recharts": "~0.15.2",
"redux": "^3.5.2", "redux": "~3.5.2",
"redux-actions": "^0.10.1", "redux-actions": "~0.10.1",
"redux-thunk": "^2.1.0", "redux-thunk": "~2.1.0",
"rlp": "^2.0.0", "rlp": "~2.0.0",
"scryptsy": "^2.0.0", "scryptsy": "~2.0.0",
"solc": "ngotchac/solc-js", "solc": "ngotchac/solc-js",
"store": "^1.3.20", "store": "~1.3.20",
"utf8": "^2.1.1", "utf8": "~2.1.1",
"valid-url": "^1.0.9", "valid-url": "~1.0.9",
"validator": "^5.7.0", "validator": "~5.7.0",
"web3": "^0.17.0-beta", "web3": "~0.17.0-beta",
"whatwg-fetch": "^1.0.0", "whatwg-fetch": "~1.0.0",
"worker-loader": "^0.7.1" "worker-loader": "~0.7.1"
} }
} }

View File

@ -15,7 +15,8 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default function (rpc) { export default function (rpc) {
const subscriptions = []; let subscriptions = [];
let pollStatusIntervalId = null;
function getCoins () { function getCoins () {
return rpc.get('getcoins'); return rpc.get('getcoins');
@ -45,6 +46,24 @@ export default function (rpc) {
callback, callback,
idx idx
}); });
// Only poll if there are subscriptions...
if (!pollStatusIntervalId) {
pollStatusIntervalId = setInterval(_pollStatus, 2000);
}
}
function unsubscribe (depositAddress) {
const newSubscriptions = []
.concat(subscriptions)
.filter((sub) => sub.depositAddress !== depositAddress);
subscriptions = newSubscriptions;
if (subscriptions.length === 0) {
clearInterval(pollStatusIntervalId);
pollStatusIntervalId = null;
}
} }
function _getSubscriptionStatus (subscription) { function _getSubscriptionStatus (subscription) {
@ -81,13 +100,12 @@ export default function (rpc) {
subscriptions.forEach(_getSubscriptionStatus); subscriptions.forEach(_getSubscriptionStatus);
} }
setInterval(_pollStatus, 2000);
return { return {
getCoins, getCoins,
getMarketInfo, getMarketInfo,
getStatus, getStatus,
shift, shift,
subscribe subscribe,
unsubscribe
}; };
} }

View File

@ -14,9 +14,10 @@
// 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 { stringify } from 'querystring';
import React from 'react'; import React from 'react';
export default ( export const termsOfService = (
<ul> <ul>
<li>This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.</li> <li>This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.</li>
<li>We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.</li> <li>We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.</li>
@ -25,3 +26,19 @@ export default (
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li> <li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li>
</ul> </ul>
); );
export const postToServer = (query, isTestnet = false) => {
const port = isTestnet ? 8443 : 443;
query = stringify(query);
return fetch(`https://sms-verification.parity.io:${port}/?` + query, {
method: 'POST', mode: 'cors', cache: 'no-store'
})
.then((res) => {
return res.json().then((data) => {
if (res.ok) {
return data.message;
}
throw new Error(data.message || 'unknown error');
});
});
};

View File

@ -15,16 +15,16 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import Abi from '../../abi'; import Abi from '../../abi';
import Api from '../api';
import { isInstanceOf } from '../util/types';
let nextSubscriptionId = 0; let nextSubscriptionId = 0;
export default class Contract { export default class Contract {
constructor (api, abi) { constructor (api, abi) {
if (!isInstanceOf(api, Api)) { if (!api) {
throw new Error('API instance needs to be provided to Contract'); throw new Error('API instance needs to be provided to Contract');
} else if (!abi) { }
if (!abi) {
throw new Error('ABI needs to be provided to Contract instance'); throw new Error('ABI needs to be provided to Contract instance');
} }
@ -48,7 +48,11 @@ export default class Contract {
this._instance[fn.signature] = fn; this._instance[fn.signature] = fn;
}); });
this._sendSubscriptionChanges(); this._subscribedToPendings = false;
this._pendingsSubscriptionId = null;
this._subscribedToBlock = false;
this._blockSubscriptionId = null;
} }
get address () { get address () {
@ -239,44 +243,71 @@ export default class Contract {
return event; return event;
} }
subscribe (eventName = null, options = {}, callback) { _findEvent (eventName = null) {
return new Promise((resolve, reject) => { const event = eventName
let event = null; ? this._events.find((evt) => evt.name === eventName)
: null;
if (eventName) { if (eventName && !event) {
event = this._events.find((evt) => evt.name === eventName); const events = this._events.map((evt) => evt.name).join(', ');
throw new Error(`${eventName} is not a valid eventName, subscribe using one of ${events} (or null to include all)`);
}
if (!event) { return event;
const events = this._events.map((evt) => evt.name).join(', '); }
reject(new Error(`${eventName} is not a valid eventName, subscribe using one of ${events} (or null to include all)`));
return;
}
}
return this._subscribe(event, options, callback).then(resolve).catch(reject); _createEthFilter (event = null, _options) {
const optionTopics = _options.topics || [];
const signature = event && event.signature || null;
// If event provided, remove the potential event signature
// as the first element of the topics
const topics = signature
? [ signature ].concat(optionTopics.filter((t, idx) => idx > 0 || t !== signature))
: optionTopics;
const options = Object.assign({}, _options, {
address: this._address,
topics
}); });
return this._api.eth.newFilter(options);
}
subscribe (eventName = null, options = {}, callback) {
try {
const event = this._findEvent(eventName);
return this._subscribe(event, options, callback);
} catch (e) {
return Promise.reject(e);
}
} }
_subscribe (event = null, _options, callback) { _subscribe (event = null, _options, callback) {
const subscriptionId = nextSubscriptionId++; const subscriptionId = nextSubscriptionId++;
const options = Object.assign({}, _options, { const { skipInitFetch } = _options;
address: this._address, delete _options['skipInitFetch'];
topics: [event ? event.signature : null]
});
return this._api.eth return this
.newFilter(options) ._createEthFilter(event, _options)
.then((filterId) => { .then((filterId) => {
this._subscriptions[subscriptionId] = {
options: _options,
callback,
filterId
};
if (skipInitFetch) {
this._subscribeToChanges();
return subscriptionId;
}
return this._api.eth return this._api.eth
.getFilterLogs(filterId) .getFilterLogs(filterId)
.then((logs) => { .then((logs) => {
callback(null, this.parseEventLogs(logs)); callback(null, this.parseEventLogs(logs));
this._subscriptions[subscriptionId] = {
options,
callback,
filterId
};
this._subscribeToChanges();
return subscriptionId; return subscriptionId;
}); });
}); });
@ -285,19 +316,89 @@ export default class Contract {
unsubscribe (subscriptionId) { unsubscribe (subscriptionId) {
return this._api.eth return this._api.eth
.uninstallFilter(this._subscriptions[subscriptionId].filterId) .uninstallFilter(this._subscriptions[subscriptionId].filterId)
.then(() => {
delete this._subscriptions[subscriptionId];
})
.catch((error) => { .catch((error) => {
console.error('unsubscribe', error); console.error('unsubscribe', error);
})
.then(() => {
delete this._subscriptions[subscriptionId];
this._unsubscribeFromChanges();
}); });
} }
_sendSubscriptionChanges = () => { _subscribeToChanges = () => {
const subscriptions = Object.values(this._subscriptions); const subscriptions = Object.values(this._subscriptions);
const timeout = () => setTimeout(this._sendSubscriptionChanges, 1000);
Promise const pendingSubscriptions = subscriptions
.filter((s) => s.options.toBlock && s.options.toBlock === 'pending');
const otherSubscriptions = subscriptions
.filter((s) => !(s.options.toBlock && s.options.toBlock === 'pending'));
if (pendingSubscriptions.length > 0 && !this._subscribedToPendings) {
this._subscribedToPendings = true;
this._subscribeToPendings();
}
if (otherSubscriptions.length > 0 && !this._subscribedToBlock) {
this._subscribedToBlock = true;
this._subscribeToBlock();
}
}
_unsubscribeFromChanges = () => {
const subscriptions = Object.values(this._subscriptions);
const pendingSubscriptions = subscriptions
.filter((s) => s.options.toBlock && s.options.toBlock === 'pending');
const otherSubscriptions = subscriptions
.filter((s) => !(s.options.toBlock && s.options.toBlock === 'pending'));
if (pendingSubscriptions.length === 0 && this._subscribedToPendings) {
this._subscribedToPendings = false;
clearTimeout(this._pendingsSubscriptionId);
}
if (otherSubscriptions.length === 0 && this._subscribedToBlock) {
this._subscribedToBlock = false;
this._api.unsubscribe(this._blockSubscriptionId);
}
}
_subscribeToBlock = () => {
this._api
.subscribe('eth_blockNumber', (error) => {
if (error) {
console.error('::_subscribeToBlock', error, error && error.stack);
}
const subscriptions = Object.values(this._subscriptions)
.filter((s) => !(s.options.toBlock && s.options.toBlock === 'pending'));
this._sendSubscriptionChanges(subscriptions);
})
.then((blockSubId) => {
this._blockSubscriptionId = blockSubId;
})
.catch((e) => {
console.error('::_subscribeToBlock', e, e && e.stack);
});
}
_subscribeToPendings = () => {
const subscriptions = Object.values(this._subscriptions)
.filter((s) => s.options.toBlock && s.options.toBlock === 'pending');
const timeout = () => setTimeout(() => this._subscribeToPendings(), 1000);
this._sendSubscriptionChanges(subscriptions)
.then(() => {
this._pendingsSubscriptionId = timeout();
});
}
_sendSubscriptionChanges = (subscriptions) => {
return Promise
.all( .all(
subscriptions.map((subscription) => { subscriptions.map((subscription) => {
return this._api.eth.getFilterChanges(subscription.filterId); return this._api.eth.getFilterChanges(subscription.filterId);
@ -315,12 +416,9 @@ export default class Contract {
console.error('_sendSubscriptionChanges', error); console.error('_sendSubscriptionChanges', error);
} }
}); });
timeout();
}) })
.catch((error) => { .catch((error) => {
console.error('_sendSubscriptionChanges', error); console.error('_sendSubscriptionChanges', error);
timeout();
}); });
} }
} }

View File

@ -437,6 +437,7 @@ describe('api/contract/Contract', () => {
] ]
} }
]; ];
const logs = [{ const logs = [{
address: '0x22bff18ec62281850546a664bb63a5c06ac5f76c', address: '0x22bff18ec62281850546a664bb63a5c06ac5f76c',
blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b', blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b',
@ -450,6 +451,7 @@ describe('api/contract/Contract', () => {
transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917', transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917',
transactionIndex: '0x0' transactionIndex: '0x0'
}]; }];
const parsed = [{ const parsed = [{
address: '0x22bfF18ec62281850546a664bb63a5C06AC5F76C', address: '0x22bfF18ec62281850546a664bb63a5C06AC5F76C',
blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b', blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b',
@ -466,11 +468,13 @@ describe('api/contract/Contract', () => {
sender: { type: 'address', value: '0x63Cf90D3f0410092FC0fca41846f596223979195' } sender: { type: 'address', value: '0x63Cf90D3f0410092FC0fca41846f596223979195' }
}, },
topics: [ topics: [
'0x954ba6c157daf8a26539574ffa64203c044691aa57251af95f4b48d85ec00dd5', '0x0000000000000000000000000000000000000000000000000001000000004fe0' '0x954ba6c157daf8a26539574ffa64203c044691aa57251af95f4b48d85ec00dd5',
'0x0000000000000000000000000000000000000000000000000001000000004fe0'
], ],
transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917', transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917',
transactionIndex: new BigNumber(0) transactionIndex: new BigNumber(0)
}]; }];
let contract; let contract;
beforeEach(() => { beforeEach(() => {
@ -496,18 +500,19 @@ describe('api/contract/Contract', () => {
scope = mockHttp([ scope = mockHttp([
{ method: 'eth_newFilter', reply: { result: '0x123' } }, { method: 'eth_newFilter', reply: { result: '0x123' } },
{ method: 'eth_getFilterLogs', reply: { result: logs } }, { method: 'eth_getFilterLogs', reply: { result: logs } },
{ method: 'eth_getFilterChanges', reply: { result: logs } },
{ method: 'eth_newFilter', reply: { result: '0x123' } }, { method: 'eth_newFilter', reply: { result: '0x123' } },
{ method: 'eth_getFilterLogs', reply: { result: logs } } { method: 'eth_getFilterLogs', reply: { result: logs } }
]); ]);
cbb = sinon.stub(); cbb = sinon.stub();
cbe = sinon.stub(); cbe = sinon.stub();
return contract.subscribe('Message', {}, cbb); return contract.subscribe('Message', { toBlock: 'pending' }, cbb);
}); });
it('sets the subscriptionId returned', () => { it('sets the subscriptionId returned', () => {
return contract return contract
.subscribe('Message', {}, cbe) .subscribe('Message', { toBlock: 'pending' }, cbe)
.then((subscriptionId) => { .then((subscriptionId) => {
expect(subscriptionId).to.equal(1); expect(subscriptionId).to.equal(1);
}); });
@ -515,7 +520,7 @@ describe('api/contract/Contract', () => {
it('creates a new filter and retrieves the logs on it', () => { it('creates a new filter and retrieves the logs on it', () => {
return contract return contract
.subscribe('Message', {}, cbe) .subscribe('Message', { toBlock: 'pending' }, cbe)
.then((subscriptionId) => { .then((subscriptionId) => {
expect(scope.isDone()).to.be.true; expect(scope.isDone()).to.be.true;
}); });
@ -523,7 +528,7 @@ describe('api/contract/Contract', () => {
it('returns the logs to the callback', () => { it('returns the logs to the callback', () => {
return contract return contract
.subscribe('Message', {}, cbe) .subscribe('Message', { toBlock: 'pending' }, cbe)
.then((subscriptionId) => { .then((subscriptionId) => {
expect(cbe).to.have.been.calledWith(null, parsed); expect(cbe).to.have.been.calledWith(null, parsed);
}); });

View File

@ -17,6 +17,7 @@
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { isArray, isHex, isInstanceOf, isString } from '../util/types'; import { isArray, isHex, isInstanceOf, isString } from '../util/types';
import { padLeft, toHex } from '../util/format';
export function inAddress (address) { export function inAddress (address) {
// TODO: address validation if we have upper-lower addresses // TODO: address validation if we have upper-lower addresses
@ -52,12 +53,18 @@ export function inHash (hash) {
export function inTopics (_topics) { export function inTopics (_topics) {
let topics = (_topics || []) let topics = (_topics || [])
.filter((topic) => topic) .filter((topic) => topic === null || topic)
.map(inHex); .map((topic) => {
if (topic === null) {
return null;
}
while (topics.length < 4) { if (Array.isArray(topic)) {
topics.push(null); return inTopics(topic);
} }
return padLeft(topic, 32);
});
return topics; return topics;
} }
@ -93,15 +100,7 @@ export function inFilter (options) {
} }
export function inHex (str) { export function inHex (str) {
if (str && str.toString) { return toHex(str);
str = str.toString(16);
}
if (str && str.substr(0, 2) === '0x') {
return str.toLowerCase();
}
return `0x${(str || '').toLowerCase()}`;
} }
export function inNumber10 (number) { export function inNumber10 (number) {

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

@ -123,6 +123,11 @@ export default class Parity {
.then((accounts) => (accounts || []).map(outAddress)); .then((accounts) => (accounts || []).map(outAddress));
} }
killAccount (account, password) {
return this._transport
.execute('parity_killAccount', inAddress(account), password);
}
listGethAccounts () { listGethAccounts () {
return this._transport return this._transport
.execute('parity_listGethAccounts') .execute('parity_listGethAccounts')

View File

@ -59,6 +59,7 @@ export default class Personal {
} }
switch (data.method) { switch (data.method) {
case 'parity_killAccount':
case 'parity_importGethAccounts': case 'parity_importGethAccounts':
case 'personal_newAccount': case 'personal_newAccount':
case 'parity_newAccountFromPhrase': case 'parity_newAccountFromPhrase':

View File

@ -36,7 +36,8 @@ export const ERROR_CODES = {
REQUEST_NOT_FOUND: -32042, REQUEST_NOT_FOUND: -32042,
COMPILATION_ERROR: -32050, COMPILATION_ERROR: -32050,
ENCRYPTION_ERROR: -32055, ENCRYPTION_ERROR: -32055,
FETCH_ERROR: -32060 FETCH_ERROR: -32060,
INVALID_PARAMS: -32602
}; };
export default class TransportError extends ExtendableError { export default class TransportError extends ExtendableError {

View File

@ -29,21 +29,33 @@ export default class Ws extends JsonRpcBase {
this._token = token; this._token = token;
this._messages = {}; this._messages = {};
this._connecting = true; this._connecting = false;
this._connected = false;
this._lastError = null; this._lastError = null;
this._autoConnect = false; this._autoConnect = true;
this._retries = 0;
this._reconnectTimeoutId = null;
this._connect(); this._connect();
} }
updateToken (token) { updateToken (token) {
this._token = token; this._token = token;
this._autoConnect = false; this._autoConnect = true;
this._connect(); this._connect();
} }
_connect () { _connect () {
if (this._connecting) {
return;
}
if (this._reconnectTimeoutId) {
window.clearTimeout(this._reconnectTimeoutId);
this._reconnectTimeoutId = null;
}
const time = parseInt(new Date().getTime() / 1000, 10); const time = parseInt(new Date().getTime() / 1000, 10);
const sha3 = keccak_256(`${this._token}:${time}`); const sha3 = keccak_256(`${this._token}:${time}`);
const hash = `${sha3}_${time}`; const hash = `${sha3}_${time}`;
@ -53,6 +65,7 @@ export default class Ws extends JsonRpcBase {
this._ws.onopen = null; this._ws.onopen = null;
this._ws.onclose = null; this._ws.onclose = null;
this._ws.onmessage = null; this._ws.onmessage = null;
this._ws.close();
this._ws = null; this._ws = null;
} }
@ -65,6 +78,32 @@ export default class Ws extends JsonRpcBase {
this._ws.onopen = this._onOpen; this._ws.onopen = this._onOpen;
this._ws.onclose = this._onClose; this._ws.onclose = this._onClose;
this._ws.onmessage = this._onMessage; this._ws.onmessage = this._onMessage;
// Get counts in dev mode only
if (process.env.NODE_ENV === 'development') {
this._count = 0;
this._lastCount = {
timestamp: Date.now(),
count: 0
};
window.setInterval(() => {
const n = this._count - this._lastCount.count;
const t = (Date.now() - this._lastCount.timestamp) / 1000;
const s = Math.round(1000 * n / t) / 1000;
if (this._debug) {
console.log('::parityWS', `speed: ${s} req/s`, `count: ${this._count}`, `(+${n})`);
}
this._lastCount = {
timestamp: Date.now(),
count: this._count
};
}, 5000);
window._parityWS = this;
}
} }
_onOpen = (event) => { _onOpen = (event) => {
@ -72,6 +111,7 @@ export default class Ws extends JsonRpcBase {
this._connected = true; this._connected = true;
this._connecting = false; this._connecting = false;
this._autoConnect = true; this._autoConnect = true;
this._retries = 0;
Object.keys(this._messages) Object.keys(this._messages)
.filter((id) => this._messages[id].queued) .filter((id) => this._messages[id].queued)
@ -79,18 +119,42 @@ export default class Ws extends JsonRpcBase {
} }
_onClose = (event) => { _onClose = (event) => {
console.log('ws:onClose', event);
this._connected = false; this._connected = false;
this._connecting = false; this._connecting = false;
event.timestamp = Date.now();
this._lastError = event;
if (this._autoConnect) { if (this._autoConnect) {
setTimeout(() => this._connect(), 500); const timeout = this.retryTimeout;
const time = timeout < 1000
? Math.round(timeout) + 'ms'
: (Math.round(timeout / 10) / 100) + 's';
console.log('ws:onClose', `trying again in ${time}...`);
this._reconnectTimeoutId = setTimeout(() => {
this._connect();
}, timeout);
return;
} }
console.log('ws:onClose', event);
} }
_onError = (event) => { _onError = (event) => {
console.error('ws:onError', event); // Only print error if the WS is connected
this._lastError = event; // ie. don't print if error == closed
window.setTimeout(() => {
if (this._connected) {
console.error('ws:onError', event);
event.timestamp = Date.now();
this._lastError = event;
}
}, 50);
} }
_onMessage = (event) => { _onMessage = (event) => {
@ -127,11 +191,16 @@ export default class Ws extends JsonRpcBase {
_send = (id) => { _send = (id) => {
const message = this._messages[id]; const message = this._messages[id];
message.queued = !this._connected;
if (this._connected) { if (this._connected) {
this._ws.send(message.json); if (process.env.NODE_ENV === 'development') {
this._count++;
}
return this._ws.send(message.json);
} }
message.queued = !this._connected;
message.timestamp = Date.now();
} }
execute (method, ...params) { execute (method, ...params) {
@ -159,4 +228,27 @@ export default class Ws extends JsonRpcBase {
get lastError () { get lastError () {
return this._lastError; return this._lastError;
} }
/**
* Exponential Timeout for Retries
*
* @see http://dthain.blogspot.de/2009/02/exponential-backoff-in-distributed.html
*/
get retryTimeout () {
// R between 1 and 2
const R = Math.random() + 1;
// Initial timeout (100ms)
const T = 100;
// Exponential Factor
const F = 2;
// Max timeout (4s)
const M = 4000;
// Current number of retries
const N = this._retries;
// Increase retries number
this._retries++;
return Math.min(R * T * Math.pow(F, N), M);
}
} }

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { range } from 'lodash';
export function bytesToHex (bytes) { export function bytesToHex (bytes) {
return '0x' + bytes.map((b) => ('0' + b.toString(16)).slice(-2)).join(''); return '0x' + bytes.map((b) => ('0' + b.toString(16)).slice(-2)).join('');
} }
@ -29,3 +31,29 @@ export function hex2Ascii (_hex) {
return str; return str;
} }
export function asciiToHex (string) {
return '0x' + string.split('').map((s) => s.charCodeAt(0).toString(16)).join('');
}
export function padRight (input, length) {
const value = toHex(input).substr(2, length * 2);
return '0x' + value + range(length * 2 - value.length).map(() => '0').join('');
}
export function padLeft (input, length) {
const value = toHex(input).substr(2, length * 2);
return '0x' + range(length * 2 - value.length).map(() => '0').join('') + value;
}
export function toHex (str) {
if (str && str.toString) {
str = str.toString(16);
}
if (str && str.substr(0, 2) === '0x') {
return str.toLowerCase();
}
return `0x${(str || '').toLowerCase()}`;
}

View File

@ -16,7 +16,7 @@
import { isAddress as isAddressValid, toChecksumAddress } from '../../abi/util/address'; import { isAddress as isAddressValid, toChecksumAddress } from '../../abi/util/address';
import { decodeCallData, decodeMethodInput, methodToAbi } from './decode'; import { decodeCallData, decodeMethodInput, methodToAbi } from './decode';
import { bytesToHex, hex2Ascii } from './format'; import { bytesToHex, hex2Ascii, asciiToHex } from './format';
import { fromWei, toWei } from './wei'; import { fromWei, toWei } from './wei';
import { sha3 } from './sha3'; import { sha3 } from './sha3';
import { isArray, isFunction, isHex, isInstanceOf, isString } from './types'; import { isArray, isFunction, isHex, isInstanceOf, isString } from './types';
@ -31,6 +31,7 @@ export default {
isString, isString,
bytesToHex, bytesToHex,
hex2Ascii, hex2Ascii,
asciiToHex,
createIdentityImg, createIdentityImg,
decodeCallData, decodeCallData,
decodeMethodInput, decodeMethodInput,

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

@ -1 +1 @@
[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[],"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":true,"inputs":[],"name":"delegate","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":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"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":"fee","outputs":[{"name":"","type":"uint256"}],"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":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"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"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] [{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[{"name":"","type":"bool"}],"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":true,"inputs":[],"name":"delegate","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":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"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":"fee","outputs":[{"name":"","type":"uint256"}],"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":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"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"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}]

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

@ -19,7 +19,8 @@ import Registry from './registry';
import SignatureReg from './signaturereg'; import SignatureReg from './signaturereg';
import TokenReg from './tokenreg'; import TokenReg from './tokenreg';
import GithubHint from './githubhint'; import GithubHint from './githubhint';
import 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

@ -21,25 +21,39 @@ export default class Registry {
this._api = api; this._api = api;
this._contracts = []; this._contracts = [];
this._instance = null; this._instance = null;
this._fetching = false;
this._queue = [];
this.getInstance(); this.getInstance();
} }
getInstance () { getInstance () {
return new Promise((resolve, reject) => { if (this._instance) {
if (this._instance) { return Promise.resolve(this._instance);
resolve(this._instance); }
return;
}
this._api.parity if (this._fetching) {
.registryAddress() return new Promise((resolve) => {
.then((address) => { this._queue.push({ resolve });
this._instance = this._api.newContract(abis.registry, address).instance; });
resolve(this._instance); }
})
.catch(reject); this._fetching = true;
});
return this._api.parity
.registryAddress()
.then((address) => {
this._fetching = false;
this._instance = this._api.newContract(abis.registry, address).instance;
this._queue.forEach((queued) => {
queued.resolve(this._instance);
});
this._queue = [];
return this._instance;
});
} }
getContract (_name) { getContract (_name) {

View File

@ -14,39 +14,74 @@
// 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 { stringify } from 'querystring'; import subscribeToEvent from '../util/subscribe-to-event';
export const checkIfVerified = (contract, account) => { export const checkIfVerified = (contract, account) => {
return contract.instance.certified.call({}, [account]); return contract.instance.certified.call({}, [account]);
}; };
export const checkIfRequested = (contract, account) => { export const checkIfRequested = (contract, account) => {
let subId = null;
let resolved = false;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
contract.subscribe('Requested', { contract
fromBlock: 0, toBlock: 'pending' .subscribe('Requested', {
}, (err, logs) => { fromBlock: 0, toBlock: 'pending'
if (err) { }, (err, logs) => {
return reject(err); if (err) {
} return reject(err);
const e = logs.find((l) => { }
return l.type === 'mined' && l.params.who && l.params.who.value === account; const e = logs.find((l) => {
return l.type === 'mined' && l.params.who && l.params.who.value === account;
});
resolve(e ? e.transactionHash : false);
resolved = true;
if (subId) {
contract.unsubscribe(subId);
}
})
.then((_subId) => {
subId = _subId;
if (resolved) {
contract.unsubscribe(subId);
}
}); });
resolve(e ? e.transactionHash : false);
});
}); });
}; };
export const postToServer = (query) => { const blockNumber = (api) => {
query = stringify(query); return new Promise((resolve, reject) => {
return fetch('https://sms-verification.parity.io/?' + query, { api.subscribe('eth_blockNumber', (err, block) => {
method: 'POST', mode: 'cors', cache: 'no-store' if (err) {
}) return reject(err);
.then((res) => {
return res.json().then((data) => {
if (res.ok) {
return data.message;
} }
throw new Error(data.message || 'unknown error'); resolve(block);
}); })
.then((subscription) => {
api.unsubscribe(subscription);
})
.catch(reject);
}); });
}; };
export const awaitPuzzle = (api, contract, account) => {
return blockNumber(api)
.then((block) => {
return new Promise((resolve, reject) => {
const subscription = subscribeToEvent(contract, 'Puzzled', {
from: block.toNumber(),
filter: (log) => log.params.who.value === account
});
subscription.once('error', reject);
subscription.once('log', subscription.unsubscribe);
subscription.once('log', resolve);
subscription.once('timeout', () => {
reject(new Error('Timed out waiting for the puzzle.'));
});
});
});
};

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" href="/parity-logo-black-no-text.png" type="image/png">
<title>Basic Token Deployment</title>
</head>
<body>
<div id="container"></div>
<script src="vendor.js"></script>
<script src="commons.js"></script>
<script src="/parity-utils/parity.js"></script>
<script src="basiccoin.js"></script>
</body>
</html>

View File

@ -32,7 +32,6 @@ const routerHistory = useRouterHistory(createHashHistory)({});
import '../../assets/fonts/Roboto/font.css'; import '../../assets/fonts/Roboto/font.css';
import '../../assets/fonts/RobotoMono/font.css'; import '../../assets/fonts/RobotoMono/font.css';
import './style.css'; import './style.css';
import './basiccoin.html';
ReactDOM.render( ReactDOM.render(
<Router history={ routerHistory }> <Router history={ routerHistory }>

View File

@ -105,7 +105,7 @@ export function attachInstances () {
]) ])
.then(([registryAddress, netChain]) => { .then(([registryAddress, netChain]) => {
const registry = api.newContract(abis.registry, registryAddress).instance; const registry = api.newContract(abis.registry, registryAddress).instance;
isTest = netChain === 'morden' || netChain === 'testnet'; isTest = ['morden', 'ropsten', 'testnet'].includes(netChain);
console.log(`contract was found at registry=${registryAddress}`); console.log(`contract was found at registry=${registryAddress}`);
console.log(`running on ${netChain}, isTest=${isTest}`); console.log(`running on ${netChain}, isTest=${isTest}`);

32
js/src/dapps/dappreg.js Normal file
View File

@ -0,0 +1,32 @@
// 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 from 'react';
import ReactDOM from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
import Application from './dappreg/Application';
import '../../assets/fonts/Roboto/font.css';
import '../../assets/fonts/RobotoMono/font.css';
import './style.css';
ReactDOM.render(
<Application />,
document.querySelector('#container')
);

View File

@ -0,0 +1,58 @@
/* 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/>.
*/
.body {
color: #333;
background: #eee;
padding: 4.5em 0;
text-align: center;
}
.apps {
background: #fff;
border-radius: 0.5em;
margin: 0 auto;
max-width: 980px;
padding: 1.5em;
text-align: left;
}
.footer {
font-size: 0.75em;
margin: 1em;
padding: 1.5em;
text-align: center;
}
.header {
background: #44e;
border-radius: 0 0 0.25em 0.25em;
color: #fff;
left: 0;
padding: 1em;
position: fixed;
right: 0;
top: 0;
z-index: 25;
}
.loading {
text-align: center;
padding-top: 5em;
font-size: 2em;
color: #999;
}

View File

@ -0,0 +1,64 @@
// 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 } from 'react';
import { observer } from 'mobx-react';
import DappsStore from '../dappsStore';
import ButtonBar from '../ButtonBar';
import Dapp from '../Dapp';
import ModalDelete from '../ModalDelete';
import ModalRegister from '../ModalRegister';
import ModalUpdate from '../ModalUpdate';
import SelectDapp from '../SelectDapp';
import Warning from '../Warning';
import styles from './application.css';
@observer
export default class Application extends Component {
dappsStore = DappsStore.instance();
render () {
if (this.dappsStore.isLoading) {
return (
<div className={ styles.loading }>
Loading application
</div>
);
}
return (
<div className={ styles.body }>
<div className={ styles.header }>
DAPP REGISTRY, a global view of distributed applications available on the network. Putting the puzzle together.
</div>
<div className={ styles.apps }>
<SelectDapp />
<ButtonBar />
<Dapp />
</div>
<div className={ styles.footer }>
{ this.dappsStore.count } applications registered, { this.dappsStore.ownedCount } owned by user
</div>
<Warning />
<ModalDelete />
<ModalRegister />
<ModalUpdate />
</div>
);
}
}

View File

@ -14,4 +14,4 @@
// 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/>.
export default from './transaction'; export default from './application';

View File

@ -0,0 +1,38 @@
/* 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/>.
*/
.button {
background: #44e;
border: none;
border-radius: 0.25em;
color: #fff;
cursor: pointer;
font-size: 1em;
margin: 1em 0.375em;
opacity: 0.85;
padding: 0.75em 2em;
&[disabled] {
opacity: 0.5;
cursor: default;
background: #aaa;
}
&[data-warning="true"] {
background: #e44;
}
}

View File

@ -0,0 +1,52 @@
// 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 styles from './button.css';
export default class Button extends Component {
static propTypes = {
className: PropTypes.string,
disabled: PropTypes.bool,
label: PropTypes.string.isRequired,
warning: PropTypes.bool,
onClick: PropTypes.func.isRequired
}
render () {
const { className, disabled, label, warning } = this.props;
const classes = `${styles.button} ${className}`;
return (
<button
className={ classes }
data-warning={ warning }
disabled={ disabled }
onClick={ this.onClick }>
{ label }
</button>
);
}
onClick = (event) => {
if (this.props.disabled) {
return;
}
this.props.onClick(event);
}
}

View File

@ -14,4 +14,4 @@
// 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/>.
export default from './RequestPendingWeb3'; export default from './button';

View File

@ -0,0 +1,21 @@
/* 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/>.
*/
.buttonbar {
text-align: center;
margin: 1em 0 0 0;
}

View File

@ -0,0 +1,101 @@
// 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 } from 'react';
import { observer } from 'mobx-react';
import DappsStore from '../dappsStore';
import ModalStore from '../modalStore';
import Button from '../Button';
import styles from './buttonBar.css';
@observer
export default class ButtonBar extends Component {
dappsStore = DappsStore.instance();
modalStore = ModalStore.instance();
render () {
let buttons = [];
if (this.dappsStore.isEditing || this.dappsStore.isNew) {
buttons = [
<Button
key='cancel'
label='Cancel'
warning
onClick={ this.onCancelClick } />,
<Button
key='save'
label={ this.dappsStore.isNew ? 'Register' : 'Update' }
disabled={ !this.dappsStore.canSave }
onClick={ this.onSaveClick } />
];
} else {
buttons = [
<Button
key='delete'
label='Delete'
warning
disabled={ !this.dappsStore.currentApp || (!this.dappsStore.currentApp.isOwner && !this.dappsStore.isContractOwner) }
onClick={ this.onDeleteClick } />,
<Button
key='edit'
label='Edit'
disabled={ !this.dappsStore.currentApp || !this.dappsStore.currentApp.isOwner }
onClick={ this.onEditClick } />,
<Button
key='new'
label='New'
onClick={ this.onNewClick } />
];
}
return (
<div className={ styles.buttonbar }>
{ buttons }
</div>
);
}
onCancelClick = () => {
if (this.dappsStore.isEditing) {
this.dappsStore.setEditing(false);
} else {
this.dappsStore.setNew(false);
}
}
onDeleteClick = () => {
this.modalStore.showDelete();
}
onEditClick = () => {
this.dappsStore.setEditing(true);
}
onNewClick = () => {
this.dappsStore.setNew(true);
}
onSaveClick = () => {
if (this.dappsStore.isEditing) {
this.modalStore.showUpdate();
} else {
this.modalStore.showRegister();
}
}
}

View File

@ -14,4 +14,4 @@
// 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/>.
export default from './RequestFinishedWeb3'; export default from './buttonBar';

View File

@ -0,0 +1,19 @@
/* 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/>.
*/
.app {
}

View File

@ -0,0 +1,166 @@
// 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 } from 'react';
import { observer } from 'mobx-react';
import { api } from '../parity';
import DappsStore from '../dappsStore';
import Input from '../Input';
import SelectAccount from '../SelectAccount';
import styles from './dapp.css';
@observer
export default class Dapp extends Component {
dappsStore = DappsStore.instance();
render () {
const app = this.dappsStore.isNew || this.dappsStore.isEditing
? this.dappsStore.wipApp
: this.dappsStore.currentApp;
if (!app) {
return null;
}
return (
<div className={ styles.app }>
{ this.dappsStore.isNew ? this.renderOwnerSelect(app) : this.renderOwnerStatic(app) }
{ this.renderInputs(app) }
</div>
);
}
renderInputs (app) {
if (this.dappsStore.isNew) {
return null;
}
return [
this.renderHashInput(app, 'image', 'Image hash, as generated by Githubhint', true),
this.renderHashInput(app, 'manifest', 'Manifest hash, as generated by Githubhint'),
this.renderHashInput(app, 'content', 'Content hash, as generated by Githubhint')
];
}
renderOwnerSelect (app) {
const overlayImage = (
<img
className={ styles.overlayImage }
src={ api.util.createIdentityImg(this.dappsStore.currentAccount.address, 4) } />
);
return (
<Input
hint={ this.dappsStore.currentAccount.address }
label='Owner, select the application owner and editor'
overlay={ overlayImage }>
<SelectAccount />
</Input>
);
}
renderOwnerStatic (app) {
const overlayImage = (
<img
className={ styles.overlayImage }
src={ api.util.createIdentityImg(app.owner, 4) } />
);
return (
<Input
hint={ app.owner }
label='Owner, the application owner and editor'
overlay={ overlayImage }>
<input value={ app.ownerName } readOnly />
</Input>
);
}
renderHashInput (app, type, label, withImage = false) {
const onChange = (event) => this.onChangeHash(event, type);
const hash = app[`${type}Hash`];
let overlayImage = null;
if (withImage && hash) {
overlayImage = (
<img
className={ styles.overlayImage }
src={ `/api/content/${hash.substr(2)}` } />
);
}
return (
<Input
hint={ app[`${type}Error`] || app[`${type}Url`] || '...' }
label={ label }
key={ `${type}Edit` }
overlay={ overlayImage }>
<input
value={ app[`${type}Hash`] || '' }
data-dirty={ app[`${type}Changed`] }
data-error={ !!app[`${type}Error`] }
readOnly={ !this.dappsStore.isEditing && !this.dappsStore.isNew }
onChange={ onChange } />
</Input>
);
}
onChangeHash (event, type) {
if (!this.dappsStore.isNew && !this.dappsStore.isEditing) {
return;
}
const hash = event.target.value;
let changed = false;
let url = null;
if (this.dappsStore.isNew) {
if (hash && hash.length) {
changed = true;
}
} else {
if (this.dappsStore.currentApp[`${type}Hash`] !== hash) {
changed = true;
} else {
url = this.dappsStore.currentApp[`${type}Url`];
}
}
this.dappsStore.editWip({
[`${type}Changed`]: changed,
[`${type}Error`]: null,
[`${type}Hash`]: hash,
[`${type}Url`]: changed ? 'Resolving url from hash' : url
});
if (changed) {
if (hash.length) {
this.dappsStore
.lookupHash(hash)
.then((url) => {
this.dappsStore.editWip({
[`${type}Error`]: url ? null : 'Unable to resolve url',
[`${type}Url`]: url
});
});
} else {
this.dappsStore.editWip({ [`${type}Url`]: null });
}
}
}
}

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 './dapp';

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 './input';

View File

@ -0,0 +1,92 @@
/* 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/>.
*/
.input {
position: relative;
input, select {
background: rgba(255, 255, 255, 0.85);
border: 4px solid rgba(223, 223, 223, 0.85);
border-radius: 0.25em;
box-sizing: border-box;
color: #333;
font-size: 1em;
margin: 0.25em 0 0.25em 0;
padding: 0.5em 0.5em 1.5em 0.5em;
width: 100%;
}
input {
padding-bottom: 1.5em;
&[data-dirty="true"] {
background: rgba(255, 255, 203, 0.85);
border-color: rgba(203, 203, 151, 0.85);
}
&[data-error="true"] {
background: rgba(255, 223, 223, 0.85) !important;
border-color: rgba(223, 191, 191, 0.85) !important;
}
&[readonly] {
background: rgba(239, 239, 239, 0.85);
border-color: rgba(223, 223, 223, 0.85);
}
}
label {
color: #888;
display: block;
font-size: 0.75em;
margin-top: 1.5em;
}
select {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
height: 58px;
&[disabled] {
background: rgba(239, 239, 239, 0.85);
border-color: rgba(223, 223, 223, 0.85);
}
}
.hint {
color: #888;
display: block;
font-size: 0.75em;
position: absolute;
right: 52px;
text-align: right;
top: 52px;
}
.overlay {
right: 10px;
position: absolute;
top: 30px;
img {
border-radius: 50%;
height: 32px;
width: 32px;
}
}
}

View File

@ -0,0 +1,47 @@
// 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 styles from './input.css';
export default class Input extends Component {
static propTypes = {
children: PropTypes.node.isRequired,
hint: PropTypes.string,
label: PropTypes.string.isRequired,
overlay: PropTypes.node
}
render () {
const { children, hint, label, overlay } = this.props;
return (
<div className={ styles.input }>
<label>
{ label }
</label>
{ children }
<div className={ styles.hint }>
{ hint }
</div>
<div className={ styles.overlay }>
{ overlay }
</div>
</div>
);
}
}

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 './modal';

View File

@ -0,0 +1,116 @@
/* 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/>.
*/
.modal {
.body {
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: 0;
text-align: center;
z-index: 50;
.dialog {
background: #fff;
border-radius: 0 0 0.25em 0.25em;
margin: 0 auto;
max-width: 840px;
text-align: left;
.content {
line-height: 1.5em;
padding: 2em;
text-align: center;
.section {
margin: 0;
padding: 0;
&.error {
color: #f44;
}
}
.section+.section {
margin-top: 1em;
}
}
.footer {
padding: 0.5em 1.625em;
text-align: right;
}
.header {
background: #44e;
color: #fff;
opacity: 0.85;
padding: 1em;
&.error {
background: #e44;
}
}
}
}
.overlay {
background: rgba(204, 204, 204, 0.7);
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: 0;
z-index: 49;
}
}
.account {
div {
display: inline-block;
vertical-align: top;
}
img {
border-radius: 50%;
margin-right: 0.5em;
}
}
.hint {
display: block !important;
color: #888;
font-size: 0.75em;
margin-top: -0.5em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.center {
text-align: center;
}
.heading {
color: #888;
font-size: 0.75em;
}
.light {
color: #888;
}

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 React, { Component, PropTypes } from 'react';
import styles from './modal.css';
export default class Modal extends Component {
static propTypes = {
buttons: PropTypes.node,
children: PropTypes.node,
error: PropTypes.object,
header: PropTypes.string
}
render () {
const { children, buttons, error, header } = this.props;
return (
<div className={ styles.modal }>
<div className={ styles.overlay } />
<div className={ styles.body }>
<div className={ styles.dialog }>
<div className={ `${styles.header} ${error ? styles.error : ''}` }>
{ header }
</div>
<div className={ styles.content }>
{ error ? this.renderError() : children }
</div>
<div className={ styles.footer }>
{ buttons }
</div>
</div>
</div>
</div>
);
}
renderError () {
const { error } = this.props;
return (
<div>
<div className={ styles.section }>
Your operation failed to complete sucessfully. The following error was returned:
</div>
<div className={ `${styles.section} ${styles.error}` }>
{ error.toString() }
</div>
</div>
);
}
}

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 './modalDelete';

View File

@ -0,0 +1,159 @@
// 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 } from 'react';
import { observer } from 'mobx-react';
import { api } from '../parity';
import DappsStore from '../dappsStore';
import ModalStore from '../modalStore';
import Button from '../Button';
import Modal from '../Modal';
import styles from '../Modal/modal.css';
const HEADERS = [
'Error During Deletion',
'Confirm Application Deletion',
'Waiting for Signer Confirmation',
'Waiting for Transaction Receipt',
'Deletion Completed'
];
const STEP_ERROR = 0;
const STEP_CONFIRM = 1;
const STEP_SIGNER = 2;
const STEP_TXRECEIPT = 3;
const STEP_DONE = 4;
@observer
export default class ModalDelete extends Component {
dappsStore = DappsStore.instance();
modalStore = ModalStore.instance();
render () {
if (!this.modalStore.showingDelete) {
return null;
}
return (
<Modal
buttons={ this.renderButtons() }
error={ this.modalStore.errorDelete }
header={ HEADERS[this.modalStore.stepDelete] }>
{ this.renderStep() }
</Modal>
);
}
renderButtons () {
switch (this.modalStore.stepDelete) {
case STEP_ERROR:
case STEP_DONE:
return [
<Button
key='close'
label='Close'
onClick={ this.onClickClose } />
];
case STEP_CONFIRM:
return [
<Button
key='cancel'
label='No, Cancel'
onClick={ this.onClickClose } />,
<Button
key='delete'
label='Yes, Delete'
warning
onClick={ this.onClickYes } />
];
default:
return null;
}
}
renderStep () {
switch (this.modalStore.stepDelete) {
case STEP_CONFIRM:
return this.renderStepConfirm();
case STEP_SIGNER:
return this.renderStepWait('Waiting for transaction confirmation in the Parity secure signer');
case STEP_TXRECEIPT:
return this.renderStepWait('Waiting for the transaction receipt from the network');
case STEP_DONE:
return this.renderStepCompleted();
default:
return null;
}
}
renderStepCompleted () {
return (
<div>
<div className={ styles.section }>
Your application has been removed from the registry.
</div>
</div>
);
}
renderStepConfirm () {
return (
<div>
<div className={ styles.section }>
You are about to remove a distributed application from the registry, the details of this application is given below. Removal does not return any fees, however the application will not be available to users anymore.
</div>
<div className={ styles.section }>
<div className={ styles.heading }>
Owner account
</div>
<div className={ styles.account }>
<img src={ api.util.createIdentityImg(this.dappsStore.currentApp.owner, 3) } />
<div>{ this.dappsStore.currentApp.ownerName }</div>
<div className={ styles.address }>{ this.dappsStore.currentApp.owner }</div>
</div>
</div>
<div className={ styles.section }>
<div className={ styles.heading }>
Application identifier
</div>
<div>
{ this.dappsStore.currentApp.id }
</div>
</div>
</div>
);
}
renderStepWait (waitingFor) {
return (
<div>
<div className={ styles.section }>
{ waitingFor }
</div>
</div>
);
}
onClickClose = () => {
this.modalStore.hideDelete();
}
onClickYes = () => {
this.modalStore.doDelete();
}
}

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 './modalRegister';

View File

@ -0,0 +1,159 @@
// 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 } from 'react';
import { observer } from 'mobx-react';
import { api } from '../parity';
import DappsStore from '../dappsStore';
import ModalStore from '../modalStore';
import Button from '../Button';
import Modal from '../Modal';
import styles from '../Modal/modal.css';
const HEADERS = [
'Error During Registration',
'Confirm Application Registration',
'Waiting for Signer Confirmation',
'Waiting for Transaction Receipt',
'Registration Completed'
];
const STEP_ERROR = 0;
const STEP_CONFIRM = 1;
const STEP_SIGNER = 2;
const STEP_TXRECEIPT = 3;
const STEP_DONE = 4;
@observer
export default class ModalRegister extends Component {
dappsStore = DappsStore.instance();
modalStore = ModalStore.instance();
render () {
if (!this.modalStore.showingRegister) {
return null;
}
return (
<Modal
buttons={ this.renderButtons() }
error={ this.modalStore.errorRegister }
header={ HEADERS[this.modalStore.stepRegister] }>
{ this.renderStep() }
</Modal>
);
}
renderButtons () {
switch (this.modalStore.stepRegister) {
case STEP_ERROR:
case STEP_DONE:
return [
<Button
key='close'
label='Close'
onClick={ this.onClickClose } />
];
case STEP_CONFIRM:
return [
<Button
key='cancel'
label='No, Cancel'
onClick={ this.onClickClose } />,
<Button
key='register'
label='Yes, Register'
warning
onClick={ this.onClickConfirmYes } />
];
default:
return null;
}
}
renderStep () {
switch (this.modalStore.stepRegister) {
case STEP_CONFIRM:
return this.renderStepConfirm();
case STEP_SIGNER:
return this.renderStepWait('Waiting for transaction confirmation in the Parity secure signer');
case STEP_TXRECEIPT:
return this.renderStepWait('Waiting for the transaction receipt from the network');
case STEP_DONE:
return this.renderStepCompleted();
default:
return null;
}
}
renderStepCompleted () {
return (
<div>
<div className={ styles.section }>
Your application has been registered in the registry.
</div>
</div>
);
}
renderStepConfirm () {
return (
<div>
<div className={ styles.section }>
You are about to register a new distributed application on the network, the details of this application is given below. This will require a non-refundable fee of { api.util.fromWei(this.dappsStore.fee).toFormat(3) }<small>ETH</small>.
</div>
<div className={ styles.section }>
<div className={ styles.heading }>
Selected owner account
</div>
<div className={ styles.account }>
<img src={ api.util.createIdentityImg(this.dappsStore.currentAccount.address, 3) } />
<div>{ this.dappsStore.currentAccount.name }</div>
<div className={ styles.hint }>{ this.dappsStore.currentAccount.address }</div>
</div>
</div>
<div className={ styles.section }>
<div className={ styles.heading }>
Unique assigned application identifier
</div>
<div>
{ this.dappsStore.wipApp.id }
</div>
</div>
</div>
);
}
renderStepWait (waitingFor) {
return (
<div>
<div className={ styles.section }>
{ waitingFor }
</div>
</div>
);
}
onClickClose = () => {
this.modalStore.hideRegister();
}
onClickConfirmYes = () => {
this.modalStore.doRegister();
}
}

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 './modalUpdate';

View File

@ -0,0 +1,169 @@
// 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 } from 'react';
import { observer } from 'mobx-react';
import DappsStore from '../dappsStore';
import ModalStore from '../modalStore';
import Button from '../Button';
import Modal from '../Modal';
import styles from '../Modal/modal.css';
const HEADERS = [
'Error During Update',
'Confirm Application Update',
'Waiting for Signer Confirmation',
'Waiting for Transaction Receipt',
'Update Completed'
];
const STEP_ERROR = 0;
const STEP_CONFIRM = 1;
const STEP_SIGNER = 2;
const STEP_TXRECEIPT = 3;
const STEP_DONE = 4;
@observer
export default class ModalUpdate extends Component {
dappsStore = DappsStore.instance();
modalStore = ModalStore.instance();
render () {
if (!this.modalStore.showingUpdate) {
return null;
}
return (
<Modal
buttons={ this.renderButtons() }
error={ this.modalStore.errorUpdate }
header={ HEADERS[this.modalStore.stepUpdate] }>
{ this.renderStep() }
</Modal>
);
}
renderButtons () {
switch (this.modalStore.stepUpdate) {
case STEP_ERROR:
case STEP_DONE:
return [
<Button
key='close'
label='Close'
onClick={ this.onClickClose } />
];
case STEP_CONFIRM:
return [
<Button
key='cancel'
label='No, Cancel'
onClick={ this.onClickClose } />,
<Button
key='delete'
label='Yes, Update'
warning
onClick={ this.onClickYes } />
];
default:
return null;
}
}
renderStep () {
switch (this.modalStore.stepUpdate) {
case STEP_CONFIRM:
return this.renderStepConfirm();
case STEP_SIGNER:
return this.renderStepWait('Waiting for transaction confirmation in the Parity secure signer');
case STEP_TXRECEIPT:
return this.renderStepWait('Waiting for the transaction receipt from the network');
case STEP_DONE:
return this.renderStepCompleted();
default:
return null;
}
}
renderStepCompleted () {
return (
<div>
<div className={ styles.section }>
Your application metadata has been updated in the registry.
</div>
</div>
);
}
renderStepConfirm () {
return (
<div>
<div className={ styles.section }>
You are about to update the application details in the registry, the details of these updates are given below. Please note that each update will generate a seperate transaction.
</div>
<div className={ styles.section }>
<div className={ styles.heading }>
Application identifier
</div>
<div>
{ this.dappsStore.wipApp.id }
</div>
</div>
{ this.renderChanges() }
</div>
);
}
renderChanges () {
return ['content', 'image', 'manifest']
.filter((type) => this.dappsStore.wipApp[`${type}Changed`])
.map((type) => {
return (
<div className={ styles.section } key={ `${type}Update` }>
<div className={ styles.heading }>
Updates to { type } hash
</div>
<div>
<div>{ this.dappsStore.wipApp[`${type}Hash`] || '(removed)' }</div>
<div className={ styles.hint }>
{ this.dappsStore.wipApp[`${type}Url`] || 'current url to be removed from registry' }
</div>
</div>
</div>
);
});
}
renderStepWait (waitingFor) {
return (
<div>
<div className={ styles.section }>
{ waitingFor }
</div>
</div>
);
}
onClickClose = () => {
this.modalStore.hideUpdate();
}
onClickYes = () => {
this.modalStore.doUpdate();
}
}

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