Merge branch 'master' of github.com:ethcore/parity into tx-block
This commit is contained in:
commit
6c9de9e6f8
2
.gitignore
vendored
2
.gitignore
vendored
@ -32,3 +32,5 @@
|
|||||||
out/
|
out/
|
||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
/parity.*
|
||||||
|
@ -20,8 +20,10 @@ linux-stable:
|
|||||||
- stable
|
- stable
|
||||||
- triggers
|
- triggers
|
||||||
script:
|
script:
|
||||||
|
- curl --data "secret=$RELEASES_SECRET" http://icarus.parity.io/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
|
||||||
- cargo build -j $(nproc) --release $CARGOFLAGS
|
- cargo build -j $(nproc) --release $CARGOFLAGS
|
||||||
- strip target/release/parity
|
- strip target/release/parity
|
||||||
|
- export SHA3=$(target/release/parity tools hash target/release/parity)
|
||||||
- md5sum target/release/parity > parity.md5
|
- md5sum target/release/parity > parity.md5
|
||||||
- sh scripts/deb-build.sh amd64
|
- sh scripts/deb-build.sh amd64
|
||||||
- cp target/release/parity deb/usr/bin/parity
|
- cp target/release/parity deb/usr/bin/parity
|
||||||
@ -36,6 +38,7 @@ linux-stable:
|
|||||||
- 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.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" --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"
|
- 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"
|
||||||
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
- rust-stable
|
- rust-stable
|
||||||
@ -92,15 +95,18 @@ linux-centos:
|
|||||||
script:
|
script:
|
||||||
- export CXX="g++"
|
- export CXX="g++"
|
||||||
- export CC="gcc"
|
- export CC="gcc"
|
||||||
|
- export PLATFORM=x86_64-unknown-centos-gnu
|
||||||
- cargo build -j $(nproc) --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
|
||||||
|
- export SHA3=$(target/release/parity tools hash target/release/parity)
|
||||||
- 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
|
- 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 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
|
||||||
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
- rust-centos
|
- rust-centos
|
||||||
@ -119,22 +125,26 @@ linux-i686:
|
|||||||
script:
|
script:
|
||||||
- export HOST_CC=gcc
|
- export HOST_CC=gcc
|
||||||
- export HOST_CXX=g++
|
- export HOST_CXX=g++
|
||||||
|
- export COMMIT=$(git rev-parse HEAD)
|
||||||
|
- export PLATFORM=i686-unknown-linux-gnu
|
||||||
- cargo build -j $(nproc) --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/$PLATFORM/release/parity
|
||||||
- md5sum target/i686-unknown-linux-gnu/release/parity > parity.md5
|
- md5sum target/$PLATFORM/release/parity > parity.md5
|
||||||
|
- export SHA3=$(target/$PLATFORM/release/parity tools hash target/$PLATFORM/release/parity)
|
||||||
- sh scripts/deb-build.sh i386
|
- sh scripts/deb-build.sh i386
|
||||||
- cp target/i686-unknown-linux-gnu/release/parity deb/usr/bin/parity
|
- cp target/$PLATFORM/release/parity deb/usr/bin/parity
|
||||||
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
|
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
|
||||||
- dpkg-deb -b deb "parity_"$VER"_i386.deb"
|
- dpkg-deb -b deb "parity_"$VER"_i386.deb"
|
||||||
- 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
|
||||||
- if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
|
- 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/i686-unknown-linux-gnu
|
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- 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 $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity --body target/$PLATFORM/release/parity
|
||||||
- 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/$PLATFORM/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/$PLATFORM/"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"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_i386.deb.md5" --body "parity_"$VER"_i386.deb.md5"
|
||||||
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
- rust-i686
|
- rust-i686
|
||||||
@ -292,7 +302,6 @@ linux-aarch64:
|
|||||||
- 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
|
- if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
|
||||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu
|
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity --body target/aarch64-unknown-linux-gnu/release/parity
|
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity.md5 --body parity.md5
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity.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" --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"
|
- 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"
|
||||||
@ -312,10 +321,13 @@ darwin:
|
|||||||
- stable
|
- stable
|
||||||
- triggers
|
- triggers
|
||||||
script:
|
script:
|
||||||
|
- export COMMIT=$(git rev-parse HEAD)
|
||||||
|
- export PLATFORM=x86_64-apple-darwin
|
||||||
- cargo build -j 8 --release #$CARGOFLAGS
|
- cargo build -j 8 --release #$CARGOFLAGS
|
||||||
- cargo build -j 8 --release -p ethstore #$CARGOFLAGS
|
- cargo build -j 8 --release -p ethstore #$CARGOFLAGS
|
||||||
- rm -rf parity.md5
|
- rm -rf parity.md5
|
||||||
- md5sum target/release/parity > parity.md5
|
- md5sum target/release/parity > parity.md5
|
||||||
|
- export SHA3=$(target/release/parity tools hash target/release/parity)
|
||||||
- packagesbuild -v mac/Parity.pkgproj
|
- packagesbuild -v mac/Parity.pkgproj
|
||||||
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
|
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
|
||||||
- mv target/release/Parity\ Ethereum.pkg "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg"
|
- mv target/release/Parity\ Ethereum.pkg "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg"
|
||||||
@ -323,11 +335,12 @@ darwin:
|
|||||||
- 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
|
- 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-apple-darwin
|
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- 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/$PLATFORM/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/$PLATFORM/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/$PLATFORM/"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"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5" --body "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5"
|
||||||
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- osx
|
- osx
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -345,12 +358,14 @@ windows:
|
|||||||
- stable
|
- stable
|
||||||
- triggers
|
- triggers
|
||||||
script:
|
script:
|
||||||
|
- set PLATFORM=x86_64-pc-windows-msvc
|
||||||
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include;C:\vs2015\VC\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt
|
- set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include;C:\vs2015\VC\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt
|
||||||
- set LIB=C:\vs2015\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64
|
- set LIB=C:\vs2015\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64
|
||||||
- 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 --release #%CARGOFLAGS%
|
||||||
|
- FOR /F "tokens=* USEBACKQ" %%i IN ('target\release\parity.exe tools hash target\release\parity.exe') DO set SHA3=%%i
|
||||||
- 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
|
||||||
@ -385,6 +400,7 @@ windows:
|
|||||||
- 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/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 --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
|
- 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
|
||||||
|
- curl --data "commit=$CI_BUILD_REF&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/%PLATFORM%
|
||||||
tags:
|
tags:
|
||||||
- rust-windows
|
- rust-windows
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -399,9 +415,10 @@ test-darwin:
|
|||||||
- triggers
|
- triggers
|
||||||
before_script:
|
before_script:
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
|
- export RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v -e ^js -e ^\\. -e ^LICENSE -e ^README.md -e ^appveyor.yml -e ^test.sh -e ^windows/ -e ^scripts/ -e^mac/ -e ^nsis/ | wc -l)
|
||||||
script:
|
script:
|
||||||
- export RUST_BACKTRACE=1
|
- export RUST_BACKTRACE=1
|
||||||
- ./test.sh $CARGOFLAGS
|
- if [ $RUST_FILES_MODIFIED -eq 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi
|
||||||
tags:
|
tags:
|
||||||
- osx
|
- osx
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
@ -413,7 +430,7 @@ test-windows:
|
|||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
script:
|
script:
|
||||||
- set RUST_BACKTRACE=1
|
- set RUST_BACKTRACE=1
|
||||||
- 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
|
- echo 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
|
||||||
tags:
|
tags:
|
||||||
- rust-windows
|
- rust-windows
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
@ -448,10 +465,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 RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v -e ^js -e ^\\. -e ^LICENSE -e ^README.md -e ^appveyor.yml -e ^test.sh -e ^windows/ -e ^scripts/ -e^mac/ -e ^nsis/ | wc -l)
|
||||||
script:
|
script:
|
||||||
- export RUST_BACKTRACE=1
|
- export RUST_BACKTRACE=1
|
||||||
- echo $JS_FILES_MODIFIED
|
- if [ $RUST_FILES_MODIFIED -eq 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi
|
||||||
- ./test.sh $CARGOFLAGS
|
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
- rust-beta
|
- rust-beta
|
||||||
@ -463,9 +480,10 @@ 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 RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v -e ^js -e ^\\. -e ^LICENSE -e ^README.md -e ^appveyor.yml -e ^test.sh -e ^windows/ -e ^scripts/ -e^mac/ -e ^nsis/ | wc -l)
|
||||||
script:
|
script:
|
||||||
- export RUST_BACKTRACE=1
|
- export RUST_BACKTRACE=1
|
||||||
- ./test.sh $CARGOFLAGS
|
- if [ $RUST_FILES_MODIFIED -eq 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
- rust-nightly
|
- rust-nightly
|
||||||
|
94
Cargo.lock
generated
94
Cargo.lock
generated
@ -12,7 +12,6 @@ dependencies = [
|
|||||||
"ethcore 1.5.0",
|
"ethcore 1.5.0",
|
||||||
"ethcore-dapps 1.5.0",
|
"ethcore-dapps 1.5.0",
|
||||||
"ethcore-devtools 1.5.0",
|
"ethcore-devtools 1.5.0",
|
||||||
"ethcore-hash-fetch 1.5.0",
|
|
||||||
"ethcore-io 1.5.0",
|
"ethcore-io 1.5.0",
|
||||||
"ethcore-ipc 1.5.0",
|
"ethcore-ipc 1.5.0",
|
||||||
"ethcore-ipc-codegen 1.5.0",
|
"ethcore-ipc-codegen 1.5.0",
|
||||||
@ -33,14 +32,16 @@ dependencies = [
|
|||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-hash-fetch 1.5.0",
|
||||||
"parity-rpc-client 1.4.0",
|
"parity-rpc-client 1.4.0",
|
||||||
|
"parity-updater 1.5.0",
|
||||||
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
"rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rpc-cli 1.4.0",
|
"rpc-cli 1.4.0",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -306,6 +307,7 @@ dependencies = [
|
|||||||
"clippy 0.0.103 (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)",
|
||||||
|
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethash 1.5.0",
|
"ethash 1.5.0",
|
||||||
"ethcore-bloom-journal 0.1.0",
|
"ethcore-bloom-journal 0.1.0",
|
||||||
"ethcore-devtools 1.5.0",
|
"ethcore-devtools 1.5.0",
|
||||||
@ -330,7 +332,7 @@ dependencies = [
|
|||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -359,7 +361,6 @@ dependencies = [
|
|||||||
"clippy 0.0.103 (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.5.0",
|
"ethcore-devtools 1.5.0",
|
||||||
"ethcore-hash-fetch 1.5.0",
|
|
||||||
"ethcore-rpc 1.5.0",
|
"ethcore-rpc 1.5.0",
|
||||||
"ethcore-util 1.5.0",
|
"ethcore-util 1.5.0",
|
||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
@ -371,6 +372,7 @@ dependencies = [
|
|||||||
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-hash-fetch 1.5.0",
|
||||||
"parity-ui 1.5.0",
|
"parity-ui 1.5.0",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -390,18 +392,6 @@ dependencies = [
|
|||||||
"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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ethcore-hash-fetch"
|
|
||||||
version = "1.5.0"
|
|
||||||
dependencies = [
|
|
||||||
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"ethcore-util 1.5.0",
|
|
||||||
"fetch 0.1.0",
|
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ethcore-io"
|
name = "ethcore-io"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@ -420,7 +410,7 @@ dependencies = [
|
|||||||
"ethcore-devtools 1.5.0",
|
"ethcore-devtools 1.5.0",
|
||||||
"ethcore-util 1.5.0",
|
"ethcore-util 1.5.0",
|
||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -443,7 +433,7 @@ dependencies = [
|
|||||||
"ethcore-ipc-nano 1.5.0",
|
"ethcore-ipc-nano 1.5.0",
|
||||||
"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)",
|
||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -468,7 +458,7 @@ dependencies = [
|
|||||||
"ethcore-util 1.5.0",
|
"ethcore-util 1.5.0",
|
||||||
"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)",
|
||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -546,8 +536,10 @@ dependencies = [
|
|||||||
"jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-updater 1.5.0",
|
||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -589,7 +581,7 @@ dependencies = [
|
|||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -705,7 +697,7 @@ dependencies = [
|
|||||||
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -794,6 +786,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
name = "https-fetch"
|
name = "https-fetch"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
||||||
"rustls 0.1.2 (git+https://github.com/ctz/rustls)",
|
"rustls 0.1.2 (git+https://github.com/ctz/rustls)",
|
||||||
@ -860,6 +853,17 @@ dependencies = [
|
|||||||
"xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipc-common-types"
|
||||||
|
version = "1.5.0"
|
||||||
|
dependencies = [
|
||||||
|
"ethcore-ipc 1.5.0",
|
||||||
|
"ethcore-ipc-codegen 1.5.0",
|
||||||
|
"ethcore-util 1.5.0",
|
||||||
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "isatty"
|
name = "isatty"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1312,6 +1316,18 @@ dependencies = [
|
|||||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parity-hash-fetch"
|
||||||
|
version = "1.5.0"
|
||||||
|
dependencies = [
|
||||||
|
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethcore-util 1.5.0",
|
||||||
|
"fetch 0.1.0",
|
||||||
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-rpc-client"
|
name = "parity-rpc-client"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -1351,11 +1367,26 @@ 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#2d07c405453bcf1e603c3965387b7f920565b6d8"
|
source = "git+https://github.com/ethcore/js-precompiled.git#3d390b35737ce212d358f26b5ec8d9644b252a88"
|
||||||
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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parity-updater"
|
||||||
|
version = "1.5.0"
|
||||||
|
dependencies = [
|
||||||
|
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethcore 1.5.0",
|
||||||
|
"ethcore-ipc 1.5.0",
|
||||||
|
"ethcore-ipc-codegen 1.5.0",
|
||||||
|
"ethcore-util 1.5.0",
|
||||||
|
"ethsync 1.5.0",
|
||||||
|
"ipc-common-types 1.5.0",
|
||||||
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-hash-fetch 1.5.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -1674,6 +1705,23 @@ dependencies = [
|
|||||||
"nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver-parser"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@ -2240,6 +2288,8 @@ dependencies = [
|
|||||||
"checksum rustls 0.1.2 (git+https://github.com/ctz/rustls)" = "<none>"
|
"checksum rustls 0.1.2 (git+https://github.com/ctz/rustls)" = "<none>"
|
||||||
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
||||||
"checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f"
|
"checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f"
|
||||||
|
"checksum semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5"
|
||||||
|
"checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9"
|
||||||
"checksum serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b1dfda9ebb31d29fa8b94d7eb3031a86a8dcec065f0fe268a30f98867bf45775"
|
"checksum serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b1dfda9ebb31d29fa8b94d7eb3031a86a8dcec065f0fe268a30f98867bf45775"
|
||||||
"checksum serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e422ae53d7933f59c6ff57e7b5870b5c9094b1f473f78ec33d89f8a692c3ec02"
|
"checksum serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e422ae53d7933f59c6ff57e7b5870b5c9094b1f473f78ec33d89f8a692c3ec02"
|
||||||
"checksum serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f877e2781ed0a323295d1c9f0e26556117b5a11489fc47b1848dfb98b3173d21"
|
"checksum serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f877e2781ed0a323295d1c9f0e26556117b5a11489fc47b1848dfb98b3173d21"
|
||||||
|
15
Cargo.toml
15
Cargo.toml
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
description = "Ethcore client."
|
description = "Parity Ethereum client"
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
@ -20,7 +20,7 @@ time = "0.1"
|
|||||||
num_cpus = "0.2"
|
num_cpus = "0.2"
|
||||||
number_prefix = "0.2"
|
number_prefix = "0.2"
|
||||||
rpassword = "0.2.1"
|
rpassword = "0.2.1"
|
||||||
semver = "0.2"
|
semver = "0.5"
|
||||||
ansi_term = "0.7"
|
ansi_term = "0.7"
|
||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
regex = "0.1"
|
regex = "0.1"
|
||||||
@ -32,25 +32,26 @@ app_dirs = "1.1.1"
|
|||||||
hyper = { version = "0.9", default-features = false }
|
hyper = { version = "0.9", default-features = false }
|
||||||
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
|
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
|
||||||
fdlimit = "0.1"
|
fdlimit = "0.1"
|
||||||
|
clippy = { version = "0.0.103", optional = true}
|
||||||
|
rlp = { path = "util/rlp" }
|
||||||
|
ethsync = { path = "sync" }
|
||||||
ethcore = { path = "ethcore" }
|
ethcore = { path = "ethcore" }
|
||||||
ethcore-util = { path = "util" }
|
ethcore-util = { path = "util" }
|
||||||
ethsync = { path = "sync" }
|
|
||||||
ethcore-io = { path = "util/io" }
|
ethcore-io = { path = "util/io" }
|
||||||
ethcore-devtools = { path = "devtools" }
|
ethcore-devtools = { path = "devtools" }
|
||||||
ethcore-rpc = { path = "rpc" }
|
ethcore-rpc = { path = "rpc" }
|
||||||
ethcore-signer = { path = "signer" }
|
ethcore-signer = { path = "signer" }
|
||||||
ethcore-ipc-nano = { path = "ipc/nano" }
|
|
||||||
ethcore-ipc = { path = "ipc/rpc" }
|
ethcore-ipc = { path = "ipc/rpc" }
|
||||||
|
ethcore-ipc-nano = { path = "ipc/nano" }
|
||||||
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
||||||
ethcore-logger = { path = "logger" }
|
ethcore-logger = { path = "logger" }
|
||||||
ethcore-hash-fetch = { path = "ethcore/hash-fetch" }
|
|
||||||
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.103", optional = true}
|
|
||||||
rpc-cli = { path = "rpc_cli" }
|
rpc-cli = { path = "rpc_cli" }
|
||||||
parity-rpc-client = { path = "rpc_client" }
|
parity-rpc-client = { path = "rpc_client" }
|
||||||
ethcore-light = { path = "ethcore/light" }
|
ethcore-light = { path = "ethcore/light" }
|
||||||
|
parity-hash-fetch = { path = "hash-fetch" }
|
||||||
|
parity-updater = { path = "updater" }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = "0.2"
|
winapi = "0.2"
|
||||||
|
@ -30,9 +30,9 @@ zip = { version = "0.1", default-features = false }
|
|||||||
ethcore-devtools = { path = "../devtools" }
|
ethcore-devtools = { path = "../devtools" }
|
||||||
ethcore-rpc = { path = "../rpc" }
|
ethcore-rpc = { path = "../rpc" }
|
||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
ethcore-hash-fetch = { path = "../ethcore/hash-fetch" }
|
|
||||||
fetch = { path = "../util/fetch" }
|
fetch = { path = "../util/fetch" }
|
||||||
parity-ui = { path = "./ui" }
|
parity-ui = { path = "./ui" }
|
||||||
|
parity-hash-fetch = { path = "../hash-fetch" }
|
||||||
|
|
||||||
clippy = { version = "0.0.103", optional = true}
|
clippy = { version = "0.0.103", optional = true}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
// Content is already being fetched
|
// Content is already being fetched
|
||||||
Some(&mut ContentStatus::Fetching(ref fetch_control)) => {
|
Some(&mut ContentStatus::Fetching(ref fetch_control)) => {
|
||||||
trace!(target: "dapps", "Content fetching in progress. Waiting...");
|
trace!(target: "dapps", "Content fetching in progress. Waiting...");
|
||||||
(None, fetch_control.to_handler(control))
|
(None, fetch_control.to_async_handler(path, control))
|
||||||
},
|
},
|
||||||
// We need to start fetching the content
|
// We need to start fetching the content
|
||||||
None => {
|
None => {
|
||||||
@ -129,11 +129,12 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
let content = self.resolver.resolve(content_hex);
|
let content = self.resolver.resolve(content_hex);
|
||||||
|
|
||||||
let cache = self.cache.clone();
|
let cache = self.cache.clone();
|
||||||
let on_done = move |id: String, result: Option<LocalPageEndpoint>| {
|
let id = content_id.clone();
|
||||||
|
let on_done = move |result: Option<LocalPageEndpoint>| {
|
||||||
let mut cache = cache.lock();
|
let mut cache = cache.lock();
|
||||||
match result {
|
match result {
|
||||||
Some(endpoint) => {
|
Some(endpoint) => {
|
||||||
cache.insert(id, ContentStatus::Ready(endpoint));
|
cache.insert(id.clone(), ContentStatus::Ready(endpoint));
|
||||||
},
|
},
|
||||||
// In case of error
|
// In case of error
|
||||||
None => {
|
None => {
|
||||||
@ -150,6 +151,7 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
Some(URLHintResult::Dapp(dapp)) => {
|
Some(URLHintResult::Dapp(dapp)) => {
|
||||||
let (handler, fetch_control) = ContentFetcherHandler::new(
|
let (handler, fetch_control) = ContentFetcherHandler::new(
|
||||||
dapp.url(),
|
dapp.url(),
|
||||||
|
path,
|
||||||
control,
|
control,
|
||||||
DappInstaller {
|
DappInstaller {
|
||||||
id: content_id.clone(),
|
id: content_id.clone(),
|
||||||
@ -165,6 +167,7 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
Some(URLHintResult::Content(content)) => {
|
Some(URLHintResult::Content(content)) => {
|
||||||
let (handler, fetch_control) = ContentFetcherHandler::new(
|
let (handler, fetch_control) = ContentFetcherHandler::new(
|
||||||
content.url,
|
content.url,
|
||||||
|
path,
|
||||||
control,
|
control,
|
||||||
ContentInstaller {
|
ContentInstaller {
|
||||||
id: content_id.clone(),
|
id: content_id.clone(),
|
||||||
@ -248,43 +251,45 @@ struct ContentInstaller {
|
|||||||
id: String,
|
id: String,
|
||||||
mime: String,
|
mime: String,
|
||||||
content_path: PathBuf,
|
content_path: PathBuf,
|
||||||
on_done: Box<Fn(String, Option<LocalPageEndpoint>) + Send>,
|
on_done: Box<Fn(Option<LocalPageEndpoint>) + Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentValidator for ContentInstaller {
|
impl ContentValidator for ContentInstaller {
|
||||||
type Error = ValidationError;
|
type Error = ValidationError;
|
||||||
|
|
||||||
fn validate_and_install(&self, path: PathBuf) -> Result<(String, LocalPageEndpoint), ValidationError> {
|
fn validate_and_install(&self, path: PathBuf) -> Result<LocalPageEndpoint, ValidationError> {
|
||||||
// Create dir
|
let validate = || {
|
||||||
try!(fs::create_dir_all(&self.content_path));
|
// Create dir
|
||||||
|
try!(fs::create_dir_all(&self.content_path));
|
||||||
|
|
||||||
// Validate hash
|
// Validate hash
|
||||||
let mut file_reader = io::BufReader::new(try!(fs::File::open(&path)));
|
let mut file_reader = io::BufReader::new(try!(fs::File::open(&path)));
|
||||||
let hash = try!(sha3(&mut file_reader));
|
let hash = try!(sha3(&mut file_reader));
|
||||||
let id = try!(self.id.as_str().parse().map_err(|_| ValidationError::InvalidContentId));
|
let id = try!(self.id.as_str().parse().map_err(|_| ValidationError::InvalidContentId));
|
||||||
if id != hash {
|
if id != hash {
|
||||||
return Err(ValidationError::HashMismatch {
|
return Err(ValidationError::HashMismatch {
|
||||||
expected: id,
|
expected: id,
|
||||||
got: hash,
|
got: hash,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// And prepare path for a file
|
// And prepare path for a file
|
||||||
let filename = path.file_name().expect("We always fetch a file.");
|
let filename = path.file_name().expect("We always fetch a file.");
|
||||||
let mut content_path = self.content_path.clone();
|
let mut content_path = self.content_path.clone();
|
||||||
content_path.push(&filename);
|
content_path.push(&filename);
|
||||||
|
|
||||||
if content_path.exists() {
|
if content_path.exists() {
|
||||||
try!(fs::remove_dir_all(&content_path))
|
try!(fs::remove_dir_all(&content_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(fs::copy(&path, &content_path));
|
try!(fs::copy(&path, &content_path));
|
||||||
|
Ok(LocalPageEndpoint::single_file(content_path, self.mime.clone(), PageCache::Enabled))
|
||||||
|
};
|
||||||
|
|
||||||
Ok((self.id.clone(), LocalPageEndpoint::single_file(content_path, self.mime.clone(), PageCache::Enabled)))
|
// Make sure to always call on_done (even in case of errors)!
|
||||||
}
|
let result = validate();
|
||||||
|
(self.on_done)(result.as_ref().ok().cloned());
|
||||||
fn done(&self, endpoint: Option<LocalPageEndpoint>) {
|
result
|
||||||
(self.on_done)(self.id.clone(), endpoint)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +297,7 @@ impl ContentValidator for ContentInstaller {
|
|||||||
struct DappInstaller {
|
struct DappInstaller {
|
||||||
id: String,
|
id: String,
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
on_done: Box<Fn(String, Option<LocalPageEndpoint>) + Send>,
|
on_done: Box<Fn(Option<LocalPageEndpoint>) + Send>,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,69 +336,68 @@ impl DappInstaller {
|
|||||||
impl ContentValidator for DappInstaller {
|
impl ContentValidator for DappInstaller {
|
||||||
type Error = ValidationError;
|
type Error = ValidationError;
|
||||||
|
|
||||||
fn validate_and_install(&self, app_path: PathBuf) -> Result<(String, LocalPageEndpoint), ValidationError> {
|
fn validate_and_install(&self, path: PathBuf) -> Result<LocalPageEndpoint, ValidationError> {
|
||||||
trace!(target: "dapps", "Opening dapp bundle at {:?}", app_path);
|
trace!(target: "dapps", "Opening dapp bundle at {:?}", path);
|
||||||
let mut file_reader = io::BufReader::new(try!(fs::File::open(app_path)));
|
let validate = || {
|
||||||
let hash = try!(sha3(&mut file_reader));
|
let mut file_reader = io::BufReader::new(try!(fs::File::open(path)));
|
||||||
let id = try!(self.id.as_str().parse().map_err(|_| ValidationError::InvalidContentId));
|
let hash = try!(sha3(&mut file_reader));
|
||||||
if id != hash {
|
let id = try!(self.id.as_str().parse().map_err(|_| ValidationError::InvalidContentId));
|
||||||
return Err(ValidationError::HashMismatch {
|
if id != hash {
|
||||||
expected: id,
|
return Err(ValidationError::HashMismatch {
|
||||||
got: hash,
|
expected: id,
|
||||||
});
|
got: hash,
|
||||||
}
|
});
|
||||||
let file = file_reader.into_inner();
|
}
|
||||||
// Unpack archive
|
let file = file_reader.into_inner();
|
||||||
let mut zip = try!(zip::ZipArchive::new(file));
|
// Unpack archive
|
||||||
// First find manifest file
|
let mut zip = try!(zip::ZipArchive::new(file));
|
||||||
let (mut manifest, manifest_dir) = try!(Self::find_manifest(&mut zip));
|
// First find manifest file
|
||||||
// Overwrite id to match hash
|
let (mut manifest, manifest_dir) = try!(Self::find_manifest(&mut zip));
|
||||||
manifest.id = self.id.clone();
|
// Overwrite id to match hash
|
||||||
|
manifest.id = self.id.clone();
|
||||||
|
|
||||||
let target = self.dapp_target_path(&manifest);
|
let target = self.dapp_target_path(&manifest);
|
||||||
|
|
||||||
// Remove old directory
|
// Remove old directory
|
||||||
if target.exists() {
|
if target.exists() {
|
||||||
warn!(target: "dapps", "Overwriting existing dapp: {}", manifest.id);
|
warn!(target: "dapps", "Overwriting existing dapp: {}", manifest.id);
|
||||||
try!(fs::remove_dir_all(target.clone()));
|
try!(fs::remove_dir_all(target.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack zip
|
// Unpack zip
|
||||||
for i in 0..zip.len() {
|
for i in 0..zip.len() {
|
||||||
let mut file = try!(zip.by_index(i));
|
let mut file = try!(zip.by_index(i));
|
||||||
// TODO [todr] Check if it's consistent on windows.
|
// TODO [todr] Check if it's consistent on windows.
|
||||||
let is_dir = file.name().chars().rev().next() == Some('/');
|
let is_dir = file.name().chars().rev().next() == Some('/');
|
||||||
|
|
||||||
let file_path = PathBuf::from(file.name());
|
let file_path = PathBuf::from(file.name());
|
||||||
let location_in_manifest_base = file_path.strip_prefix(&manifest_dir);
|
let location_in_manifest_base = file_path.strip_prefix(&manifest_dir);
|
||||||
// Create files that are inside manifest directory
|
// Create files that are inside manifest directory
|
||||||
if let Ok(location_in_manifest_base) = location_in_manifest_base {
|
if let Ok(location_in_manifest_base) = location_in_manifest_base {
|
||||||
let p = target.join(location_in_manifest_base);
|
let p = target.join(location_in_manifest_base);
|
||||||
// Check if it's a directory
|
// Check if it's a directory
|
||||||
if is_dir {
|
if is_dir {
|
||||||
try!(fs::create_dir_all(p));
|
try!(fs::create_dir_all(p));
|
||||||
} else {
|
} else {
|
||||||
let mut target = try!(fs::File::create(p));
|
let mut target = try!(fs::File::create(p));
|
||||||
try!(io::copy(&mut file, &mut target));
|
try!(io::copy(&mut file, &mut target));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Write manifest
|
// Write manifest
|
||||||
let manifest_str = try!(serialize_manifest(&manifest).map_err(ValidationError::ManifestSerialization));
|
let manifest_str = try!(serialize_manifest(&manifest).map_err(ValidationError::ManifestSerialization));
|
||||||
let manifest_path = target.join(MANIFEST_FILENAME);
|
let manifest_path = target.join(MANIFEST_FILENAME);
|
||||||
let mut manifest_file = try!(fs::File::create(manifest_path));
|
let mut manifest_file = try!(fs::File::create(manifest_path));
|
||||||
try!(manifest_file.write_all(manifest_str.as_bytes()));
|
try!(manifest_file.write_all(manifest_str.as_bytes()));
|
||||||
|
// Create endpoint
|
||||||
|
let endpoint = LocalPageEndpoint::new(target, manifest.clone().into(), PageCache::Enabled, self.embeddable_on.clone());
|
||||||
|
Ok(endpoint)
|
||||||
|
};
|
||||||
|
|
||||||
// Create endpoint
|
let result = validate();
|
||||||
let app = LocalPageEndpoint::new(target, manifest.clone().into(), PageCache::Enabled, self.embeddable_on.clone());
|
(self.on_done)(result.as_ref().ok().cloned());
|
||||||
|
result
|
||||||
// Return modified app manifest
|
|
||||||
Ok((manifest.id.clone(), app))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn done(&self, endpoint: Option<LocalPageEndpoint>) {
|
|
||||||
(self.on_done)(self.id.clone(), endpoint)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,35 +22,41 @@ use std::sync::{mpsc, Arc};
|
|||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
use util::Mutex;
|
use util::Mutex;
|
||||||
use url::Url;
|
|
||||||
use fetch::{Client, Fetch, FetchResult};
|
use fetch::{Client, Fetch, FetchResult};
|
||||||
|
|
||||||
use hyper::{server, Decoder, Encoder, Next, Method, Control};
|
use hyper::{server, Decoder, Encoder, Next, Method, Control};
|
||||||
use hyper::net::HttpStream;
|
use hyper::net::HttpStream;
|
||||||
|
use hyper::uri::RequestUri;
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
|
|
||||||
use handlers::{ContentHandler, Redirection, extract_url};
|
use endpoint::EndpointPath;
|
||||||
use page::LocalPageEndpoint;
|
use handlers::ContentHandler;
|
||||||
|
use page::{LocalPageEndpoint, PageHandlerWaiting};
|
||||||
|
|
||||||
const FETCH_TIMEOUT: u64 = 30;
|
const FETCH_TIMEOUT: u64 = 30;
|
||||||
|
|
||||||
enum FetchState {
|
enum FetchState {
|
||||||
|
Waiting,
|
||||||
NotStarted(String),
|
NotStarted(String),
|
||||||
Error(ContentHandler),
|
Error(ContentHandler),
|
||||||
InProgress(mpsc::Receiver<FetchResult>),
|
InProgress(mpsc::Receiver<FetchResult>),
|
||||||
Done(String, LocalPageEndpoint, Redirection),
|
Done(LocalPageEndpoint, Box<PageHandlerWaiting>),
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WaitResult {
|
||||||
|
Error(ContentHandler),
|
||||||
|
Done(LocalPageEndpoint),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ContentValidator {
|
pub trait ContentValidator {
|
||||||
type Error: fmt::Debug + fmt::Display;
|
type Error: fmt::Debug + fmt::Display;
|
||||||
|
|
||||||
fn validate_and_install(&self, app: PathBuf) -> Result<(String, LocalPageEndpoint), Self::Error>;
|
fn validate_and_install(&self, path: PathBuf) -> Result<LocalPageEndpoint, Self::Error>;
|
||||||
fn done(&self, Option<LocalPageEndpoint>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FetchControl {
|
pub struct FetchControl {
|
||||||
abort: Arc<AtomicBool>,
|
abort: Arc<AtomicBool>,
|
||||||
listeners: Mutex<Vec<(Control, mpsc::Sender<FetchState>)>>,
|
listeners: Mutex<Vec<(Control, mpsc::Sender<WaitResult>)>>,
|
||||||
deadline: Instant,
|
deadline: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,9 +71,10 @@ impl Default for FetchControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FetchControl {
|
impl FetchControl {
|
||||||
fn notify<F: Fn() -> FetchState>(&self, status: F) {
|
fn notify<F: Fn() -> WaitResult>(&self, status: F) {
|
||||||
let mut listeners = self.listeners.lock();
|
let mut listeners = self.listeners.lock();
|
||||||
for (control, sender) in listeners.drain(..) {
|
for (control, sender) in listeners.drain(..) {
|
||||||
|
trace!(target: "dapps", "Resuming request waiting for content...");
|
||||||
if let Err(e) = sender.send(status()) {
|
if let Err(e) = sender.send(status()) {
|
||||||
trace!(target: "dapps", "Waiting listener notification failed: {:?}", e);
|
trace!(target: "dapps", "Waiting listener notification failed: {:?}", e);
|
||||||
} else {
|
} else {
|
||||||
@ -78,9 +85,9 @@ impl FetchControl {
|
|||||||
|
|
||||||
fn set_status(&self, status: &FetchState) {
|
fn set_status(&self, status: &FetchState) {
|
||||||
match *status {
|
match *status {
|
||||||
FetchState::Error(ref handler) => self.notify(|| FetchState::Error(handler.clone())),
|
FetchState::Error(ref handler) => self.notify(|| WaitResult::Error(handler.clone())),
|
||||||
FetchState::Done(ref id, ref endpoint, ref handler) => self.notify(|| FetchState::Done(id.clone(), endpoint.clone(), handler.clone())),
|
FetchState::Done(ref endpoint, _) => self.notify(|| WaitResult::Done(endpoint.clone())),
|
||||||
FetchState::NotStarted(_) | FetchState::InProgress(_) => {},
|
FetchState::NotStarted(_) | FetchState::InProgress(_) | FetchState::Waiting => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,44 +95,66 @@ impl FetchControl {
|
|||||||
self.abort.store(true, Ordering::SeqCst);
|
self.abort.store(true, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_handler(&self, control: Control) -> Box<server::Handler<HttpStream> + Send> {
|
pub fn to_async_handler(&self, path: EndpointPath, control: Control) -> Box<server::Handler<HttpStream> + Send> {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
self.listeners.lock().push((control, tx));
|
self.listeners.lock().push((control, tx));
|
||||||
|
|
||||||
Box::new(WaitingHandler {
|
Box::new(WaitingHandler {
|
||||||
receiver: rx,
|
receiver: rx,
|
||||||
state: None,
|
state: FetchState::Waiting,
|
||||||
|
uri: RequestUri::default(),
|
||||||
|
path: path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WaitingHandler {
|
pub struct WaitingHandler {
|
||||||
receiver: mpsc::Receiver<FetchState>,
|
receiver: mpsc::Receiver<WaitResult>,
|
||||||
state: Option<FetchState>,
|
state: FetchState,
|
||||||
|
uri: RequestUri,
|
||||||
|
path: EndpointPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl server::Handler<HttpStream> for WaitingHandler {
|
impl server::Handler<HttpStream> for WaitingHandler {
|
||||||
fn on_request(&mut self, _request: server::Request<HttpStream>) -> Next {
|
fn on_request(&mut self, request: server::Request<HttpStream>) -> Next {
|
||||||
|
self.uri = request.uri().clone();
|
||||||
Next::wait()
|
Next::wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_request_readable(&mut self, _decoder: &mut Decoder<HttpStream>) -> Next {
|
fn on_request_readable(&mut self, decoder: &mut Decoder<HttpStream>) -> Next {
|
||||||
self.state = self.receiver.try_recv().ok();
|
let result = self.receiver.try_recv().ok();
|
||||||
Next::write()
|
self.state = match result {
|
||||||
|
Some(WaitResult::Error(handler)) => FetchState::Error(handler),
|
||||||
|
Some(WaitResult::Done(endpoint)) => {
|
||||||
|
let mut page_handler = endpoint.to_page_handler(self.path.clone());
|
||||||
|
page_handler.set_uri(&self.uri);
|
||||||
|
FetchState::Done(endpoint, page_handler)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
warn!("A result for waiting request was not received.");
|
||||||
|
FetchState::Waiting
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.state {
|
||||||
|
FetchState::Done(_, ref mut handler) => handler.on_request_readable(decoder),
|
||||||
|
FetchState::Error(ref mut handler) => handler.on_request_readable(decoder),
|
||||||
|
_ => Next::write(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
||||||
match self.state {
|
match self.state {
|
||||||
Some(FetchState::Done(_, _, ref mut handler)) => handler.on_response(res),
|
FetchState::Done(_, ref mut handler) => handler.on_response(res),
|
||||||
Some(FetchState::Error(ref mut handler)) => handler.on_response(res),
|
FetchState::Error(ref mut handler) => handler.on_response(res),
|
||||||
_ => Next::end(),
|
_ => Next::end(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_response_writable(&mut self, encoder: &mut Encoder<HttpStream>) -> Next {
|
fn on_response_writable(&mut self, encoder: &mut Encoder<HttpStream>) -> Next {
|
||||||
match self.state {
|
match self.state {
|
||||||
Some(FetchState::Done(_, _, ref mut handler)) => handler.on_response_writable(encoder),
|
FetchState::Done(_, ref mut handler) => handler.on_response_writable(encoder),
|
||||||
Some(FetchState::Error(ref mut handler)) => handler.on_response_writable(encoder),
|
FetchState::Error(ref mut handler) => handler.on_response_writable(encoder),
|
||||||
_ => Next::end(),
|
_ => Next::end(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,29 +166,19 @@ pub struct ContentFetcherHandler<H: ContentValidator> {
|
|||||||
status: FetchState,
|
status: FetchState,
|
||||||
client: Option<Client>,
|
client: Option<Client>,
|
||||||
installer: H,
|
installer: H,
|
||||||
request_url: Option<Url>,
|
path: EndpointPath,
|
||||||
|
uri: RequestUri,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: ContentValidator> Drop for ContentFetcherHandler<H> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let result = match self.status {
|
|
||||||
FetchState::Done(_, ref result, _) => Some(result.clone()),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
self.installer.done(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H: ContentValidator> ContentFetcherHandler<H> {
|
impl<H: ContentValidator> ContentFetcherHandler<H> {
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
url: String,
|
url: String,
|
||||||
|
path: EndpointPath,
|
||||||
control: Control,
|
control: Control,
|
||||||
handler: H,
|
handler: H,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
) -> (Self, Arc<FetchControl>) {
|
) -> (Self, Arc<FetchControl>) {
|
||||||
|
|
||||||
let fetch_control = Arc::new(FetchControl::default());
|
let fetch_control = Arc::new(FetchControl::default());
|
||||||
let client = Client::default();
|
let client = Client::default();
|
||||||
let handler = ContentFetcherHandler {
|
let handler = ContentFetcherHandler {
|
||||||
@ -168,7 +187,8 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
|
|||||||
client: Some(client),
|
client: Some(client),
|
||||||
status: FetchState::NotStarted(url),
|
status: FetchState::NotStarted(url),
|
||||||
installer: handler,
|
installer: handler,
|
||||||
request_url: None,
|
path: path,
|
||||||
|
uri: RequestUri::default(),
|
||||||
embeddable_on: embeddable_on,
|
embeddable_on: embeddable_on,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -192,7 +212,6 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
|
|||||||
|
|
||||||
impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<H> {
|
impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<H> {
|
||||||
fn on_request(&mut self, request: server::Request<HttpStream>) -> Next {
|
fn on_request(&mut self, request: server::Request<HttpStream>) -> Next {
|
||||||
self.request_url = extract_url(&request);
|
|
||||||
let status = if let FetchState::NotStarted(ref url) = self.status {
|
let status = if let FetchState::NotStarted(ref url) = self.status {
|
||||||
Some(match *request.method() {
|
Some(match *request.method() {
|
||||||
// Start fetching content
|
// Start fetching content
|
||||||
@ -205,8 +224,8 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
Ok(receiver) => FetchState::InProgress(receiver),
|
Ok(receiver) => FetchState::InProgress(receiver),
|
||||||
Err(e) => FetchState::Error(ContentHandler::error(
|
Err(e) => FetchState::Error(ContentHandler::error(
|
||||||
StatusCode::BadGateway,
|
StatusCode::BadGateway,
|
||||||
"Unable To Start Dapp Download",
|
"Unable To Start Content Download",
|
||||||
"Could not initialize download of the dapp. It might be a problem with the remote server.",
|
"Could not initialize download of the content. It might be a problem with the remote server.",
|
||||||
Some(&format!("{}", e)),
|
Some(&format!("{}", e)),
|
||||||
self.embeddable_on.clone(),
|
self.embeddable_on.clone(),
|
||||||
)),
|
)),
|
||||||
@ -227,6 +246,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
self.fetch_control.set_status(&status);
|
self.fetch_control.set_status(&status);
|
||||||
self.status = status;
|
self.status = status;
|
||||||
}
|
}
|
||||||
|
self.uri = request.uri().clone();
|
||||||
|
|
||||||
Next::read()
|
Next::read()
|
||||||
}
|
}
|
||||||
@ -266,11 +286,10 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
self.embeddable_on.clone(),
|
self.embeddable_on.clone(),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
Ok((id, result)) => {
|
Ok(endpoint) => {
|
||||||
let url: String = self.request_url.take()
|
let mut handler = endpoint.to_page_handler(self.path.clone());
|
||||||
.map(|url| url.raw.into_string())
|
handler.set_uri(&self.uri);
|
||||||
.expect("Request URL always read in on_request; qed");
|
FetchState::Done(endpoint, handler)
|
||||||
FetchState::Done(id, result, Redirection::new(&url))
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Remove temporary zip file
|
// Remove temporary zip file
|
||||||
@ -306,7 +325,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
|
|
||||||
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
||||||
match self.status {
|
match self.status {
|
||||||
FetchState::Done(_, _, ref mut handler) => handler.on_response(res),
|
FetchState::Done(_, ref mut handler) => handler.on_response(res),
|
||||||
FetchState::Error(ref mut handler) => handler.on_response(res),
|
FetchState::Error(ref mut handler) => handler.on_response(res),
|
||||||
_ => Next::end(),
|
_ => Next::end(),
|
||||||
}
|
}
|
||||||
@ -314,7 +333,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
|
|
||||||
fn on_response_writable(&mut self, encoder: &mut Encoder<HttpStream>) -> Next {
|
fn on_response_writable(&mut self, encoder: &mut Encoder<HttpStream>) -> Next {
|
||||||
match self.status {
|
match self.status {
|
||||||
FetchState::Done(_, _, ref mut handler) => handler.on_response_writable(encoder),
|
FetchState::Done(_, ref mut handler) => handler.on_response_writable(encoder),
|
||||||
FetchState::Error(ref mut handler) => handler.on_response_writable(encoder),
|
FetchState::Error(ref mut handler) => handler.on_response_writable(encoder),
|
||||||
_ => Next::end(),
|
_ => Next::end(),
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ extern crate mime_guess;
|
|||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate ethcore_rpc;
|
extern crate ethcore_rpc;
|
||||||
extern crate ethcore_util as util;
|
extern crate ethcore_util as util;
|
||||||
extern crate ethcore_hash_fetch as hash_fetch;
|
extern crate parity_hash_fetch as hash_fetch;
|
||||||
extern crate linked_hash_map;
|
extern crate linked_hash_map;
|
||||||
extern crate fetch;
|
extern crate fetch;
|
||||||
extern crate parity_dapps_glue as parity_dapps;
|
extern crate parity_dapps_glue as parity_dapps;
|
||||||
|
@ -83,13 +83,19 @@ impl Default for PageCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A generic type for `PageHandler` allowing to set the URL.
|
||||||
|
/// Used by dapps fetching to set the URL after the content was downloaded.
|
||||||
|
pub trait PageHandlerWaiting: server::Handler<HttpStream> + Send {
|
||||||
|
fn set_uri(&mut self, uri: &RequestUri);
|
||||||
|
}
|
||||||
|
|
||||||
/// A handler for a single webapp.
|
/// A handler for a single webapp.
|
||||||
/// Resolves correct paths and serves as a plumbing code between
|
/// Resolves correct paths and serves as a plumbing code between
|
||||||
/// hyper server and dapp.
|
/// hyper server and dapp.
|
||||||
pub struct PageHandler<T: Dapp> {
|
pub struct PageHandler<T: Dapp> {
|
||||||
/// A Dapp.
|
/// A Dapp.
|
||||||
pub app: T,
|
pub app: T,
|
||||||
/// File currently being served (or `None` if file does not exist).
|
/// File currently being served
|
||||||
pub file: ServedFile<T>,
|
pub file: ServedFile<T>,
|
||||||
/// Optional prefix to strip from path.
|
/// Optional prefix to strip from path.
|
||||||
pub prefix: Option<String>,
|
pub prefix: Option<String>,
|
||||||
@ -101,6 +107,21 @@ pub struct PageHandler<T: Dapp> {
|
|||||||
pub cache: PageCache,
|
pub cache: PageCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Dapp> PageHandlerWaiting for PageHandler<T> {
|
||||||
|
fn set_uri(&mut self, uri: &RequestUri) {
|
||||||
|
trace!(target: "dapps", "Setting URI: {:?}", uri);
|
||||||
|
self.file = match *uri {
|
||||||
|
RequestUri::AbsolutePath { ref path, .. } => {
|
||||||
|
self.app.file(&self.extract_path(path))
|
||||||
|
},
|
||||||
|
RequestUri::AbsoluteUri(ref url) => {
|
||||||
|
self.app.file(&self.extract_path(url.path()))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}.map_or_else(|| ServedFile::new(self.safe_to_embed_on.clone()), |f| ServedFile::File(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Dapp> PageHandler<T> {
|
impl<T: Dapp> PageHandler<T> {
|
||||||
fn extract_path(&self, path: &str) -> String {
|
fn extract_path(&self, path: &str) -> String {
|
||||||
let app_id = &self.path.app_id;
|
let app_id = &self.path.app_id;
|
||||||
@ -124,15 +145,7 @@ impl<T: Dapp> PageHandler<T> {
|
|||||||
|
|
||||||
impl<T: Dapp> server::Handler<HttpStream> for PageHandler<T> {
|
impl<T: Dapp> server::Handler<HttpStream> for PageHandler<T> {
|
||||||
fn on_request(&mut self, req: server::Request<HttpStream>) -> Next {
|
fn on_request(&mut self, req: server::Request<HttpStream>) -> Next {
|
||||||
self.file = match *req.uri() {
|
self.set_uri(req.uri());
|
||||||
RequestUri::AbsolutePath { ref path, .. } => {
|
|
||||||
self.app.file(&self.extract_path(path))
|
|
||||||
},
|
|
||||||
RequestUri::AbsoluteUri(ref url) => {
|
|
||||||
self.app.file(&self.extract_path(url.path()))
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}.map_or_else(|| ServedFile::new(self.safe_to_embed_on.clone()), |f| ServedFile::File(f));
|
|
||||||
Next::write()
|
Next::write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ use mime_guess;
|
|||||||
use std::io::{Seek, Read, SeekFrom};
|
use std::io::{Seek, Read, SeekFrom};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use page::handler::{self, PageCache};
|
use page::handler::{self, PageCache, PageHandlerWaiting};
|
||||||
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -54,6 +54,36 @@ impl LocalPageEndpoint {
|
|||||||
pub fn path(&self) -> PathBuf {
|
pub fn path(&self) -> PathBuf {
|
||||||
self.path.clone()
|
self.path.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn page_handler_with_mime(&self, path: EndpointPath, mime: &str) -> handler::PageHandler<LocalSingleFile> {
|
||||||
|
handler::PageHandler {
|
||||||
|
app: LocalSingleFile { path: self.path.clone(), mime: mime.into() },
|
||||||
|
prefix: None,
|
||||||
|
path: path,
|
||||||
|
file: handler::ServedFile::new(None),
|
||||||
|
safe_to_embed_on: self.embeddable_on.clone(),
|
||||||
|
cache: self.cache,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page_handler(&self, path: EndpointPath) -> handler::PageHandler<LocalDapp> {
|
||||||
|
handler::PageHandler {
|
||||||
|
app: LocalDapp { path: self.path.clone() },
|
||||||
|
prefix: None,
|
||||||
|
path: path,
|
||||||
|
file: handler::ServedFile::new(None),
|
||||||
|
safe_to_embed_on: self.embeddable_on.clone(),
|
||||||
|
cache: self.cache,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_page_handler(&self, path: EndpointPath) -> Box<PageHandlerWaiting> {
|
||||||
|
if let Some(ref mime) = self.mime {
|
||||||
|
Box::new(self.page_handler_with_mime(path, mime))
|
||||||
|
} else {
|
||||||
|
Box::new(self.page_handler(path))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Endpoint for LocalPageEndpoint {
|
impl Endpoint for LocalPageEndpoint {
|
||||||
@ -63,23 +93,9 @@ impl Endpoint for LocalPageEndpoint {
|
|||||||
|
|
||||||
fn to_handler(&self, path: EndpointPath) -> Box<Handler> {
|
fn to_handler(&self, path: EndpointPath) -> Box<Handler> {
|
||||||
if let Some(ref mime) = self.mime {
|
if let Some(ref mime) = self.mime {
|
||||||
Box::new(handler::PageHandler {
|
Box::new(self.page_handler_with_mime(path, mime))
|
||||||
app: LocalSingleFile { path: self.path.clone(), mime: mime.clone() },
|
|
||||||
prefix: None,
|
|
||||||
path: path,
|
|
||||||
file: handler::ServedFile::new(None),
|
|
||||||
safe_to_embed_on: self.embeddable_on.clone(),
|
|
||||||
cache: self.cache,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
Box::new(handler::PageHandler {
|
Box::new(self.page_handler(path))
|
||||||
app: LocalDapp { path: self.path.clone() },
|
|
||||||
prefix: None,
|
|
||||||
path: path,
|
|
||||||
file: handler::ServedFile::new(None),
|
|
||||||
safe_to_embed_on: self.embeddable_on.clone(),
|
|
||||||
cache: self.cache,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,5 @@ mod handler;
|
|||||||
|
|
||||||
pub use self::local::LocalPageEndpoint;
|
pub use self::local::LocalPageEndpoint;
|
||||||
pub use self::builtin::PageEndpoint;
|
pub use self::builtin::PageEndpoint;
|
||||||
pub use self::handler::PageCache;
|
pub use self::handler::{PageCache, PageHandlerWaiting};
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ fn init_logger() {
|
|||||||
if let Ok(log) = env::var("RUST_LOG") {
|
if let Ok(log) = env::var("RUST_LOG") {
|
||||||
let mut builder = LogBuilder::new();
|
let mut builder = LogBuilder::new();
|
||||||
builder.parse(&log);
|
builder.parse(&log);
|
||||||
builder.init().expect("Logger is initialized only once.");
|
let _ = builder.init(); // ignore errors since ./test.sh will call this multiple times.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ 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" }
|
||||||
semver = "0.2"
|
semver = "0.5"
|
||||||
ethcore-ipc-nano = { path = "../ipc/nano" }
|
ethcore-ipc-nano = { path = "../ipc/nano" }
|
||||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||||
crossbeam = "0.2"
|
crossbeam = "0.2"
|
||||||
|
@ -270,8 +270,7 @@ impl DatabaseService for Database {
|
|||||||
Ok(next_iterator)
|
Ok(next_iterator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_next(&self, handle: IteratorHandle) -> Option<KeyValue>
|
fn iter_next(&self, handle: IteratorHandle) -> Option<KeyValue> {
|
||||||
{
|
|
||||||
let mut iterators = self.iterators.write();
|
let mut iterators = self.iterators.write();
|
||||||
let mut iterator = match iterators.get_mut(&handle) {
|
let mut iterator = match iterators.get_mut(&handle) {
|
||||||
Some(some_iterator) => some_iterator,
|
Some(some_iterator) => some_iterator,
|
||||||
|
@ -21,7 +21,7 @@ crossbeam = "0.2.9"
|
|||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
bloomchain = "0.1"
|
bloomchain = "0.1"
|
||||||
rayon = "0.4.2"
|
rayon = "0.4.2"
|
||||||
semver = "0.2"
|
semver = "0.5"
|
||||||
bit-set = "0.4"
|
bit-set = "0.4"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
rand = "0.3"
|
rand = "0.3"
|
||||||
@ -42,6 +42,7 @@ ethcore-ipc-nano = { path = "../ipc/nano" }
|
|||||||
rlp = { path = "../util/rlp" }
|
rlp = { path = "../util/rlp" }
|
||||||
lru-cache = "0.1.0"
|
lru-cache = "0.1.0"
|
||||||
ethcore-bloom-journal = { path = "../util/bloom" }
|
ethcore-bloom-journal = { path = "../util/bloom" }
|
||||||
|
ethabi = "0.2.2"
|
||||||
|
|
||||||
[dependencies.hyper]
|
[dependencies.hyper]
|
||||||
git = "https://github.com/ethcore/hyper"
|
git = "https://github.com/ethcore/hyper"
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
"eip155Transition": 10,
|
"eip155Transition": 10,
|
||||||
"eip160Transition": 10,
|
"eip160Transition": 10,
|
||||||
"eip161abcTransition": 10,
|
"eip161abcTransition": 10,
|
||||||
"eip161dTransition": 10
|
"eip161dTransition": 10,
|
||||||
|
"maxCodeSize": 24576
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit e8f4624b7f1a15c63674eecf577c7ab76c3b16be
|
Subproject commit 9028c4801fd39fbb71a9796979182549a24e81c8
|
@ -13,7 +13,9 @@
|
|||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
|
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::path::{Path};
|
use std::path::{Path};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -22,7 +24,7 @@ use std::time::{Instant};
|
|||||||
use time::precise_time_ns;
|
use time::precise_time_ns;
|
||||||
|
|
||||||
// util
|
// util
|
||||||
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, Hashable};
|
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, MutexGuard, Hashable};
|
||||||
use util::{journaldb, TrieFactory, Trie};
|
use util::{journaldb, TrieFactory, Trie};
|
||||||
use util::{U256, H256, Address, H2048, Uint, FixedHash};
|
use util::{U256, H256, Address, H2048, Uint, FixedHash};
|
||||||
use util::trie::TrieSpec;
|
use util::trie::TrieSpec;
|
||||||
@ -42,7 +44,7 @@ use env_info::LastHashes;
|
|||||||
use verification;
|
use verification;
|
||||||
use verification::{PreverifiedBlock, Verifier};
|
use verification::{PreverifiedBlock, Verifier};
|
||||||
use block::*;
|
use block::*;
|
||||||
use transaction::{LocalizedTransaction, SignedTransaction, PendingTransaction, Action};
|
use transaction::{LocalizedTransaction, SignedTransaction, Transaction, PendingTransaction, Action};
|
||||||
use blockchain::extras::TransactionAddress;
|
use blockchain::extras::TransactionAddress;
|
||||||
use types::filter::Filter;
|
use types::filter::Filter;
|
||||||
use types::mode::Mode as IpcMode;
|
use types::mode::Mode as IpcMode;
|
||||||
@ -68,6 +70,7 @@ use factory::Factories;
|
|||||||
use rlp::{decode, View, UntrustedRlp};
|
use rlp::{decode, View, UntrustedRlp};
|
||||||
use state_db::StateDB;
|
use state_db::StateDB;
|
||||||
use rand::OsRng;
|
use rand::OsRng;
|
||||||
|
use client::registry::Registry;
|
||||||
|
|
||||||
// re-export
|
// re-export
|
||||||
pub use types::blockchain_info::BlockChainInfo;
|
pub use types::blockchain_info::BlockChainInfo;
|
||||||
@ -124,6 +127,7 @@ impl SleepState {
|
|||||||
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
||||||
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
|
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
|
enabled: AtomicBool,
|
||||||
mode: Mutex<Mode>,
|
mode: Mutex<Mode>,
|
||||||
chain: RwLock<Arc<BlockChain>>,
|
chain: RwLock<Arc<BlockChain>>,
|
||||||
tracedb: RwLock<TraceDB<BlockChain>>,
|
tracedb: RwLock<TraceDB<BlockChain>>,
|
||||||
@ -148,6 +152,7 @@ pub struct Client {
|
|||||||
history: u64,
|
history: u64,
|
||||||
rng: Mutex<OsRng>,
|
rng: Mutex<OsRng>,
|
||||||
on_mode_change: Mutex<Option<Box<FnMut(&Mode) + 'static + Send>>>,
|
on_mode_change: Mutex<Option<Box<FnMut(&Mode) + 'static + Send>>>,
|
||||||
|
registrar: Mutex<Option<Registry>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -160,6 +165,7 @@ impl Client {
|
|||||||
message_channel: IoChannel<ClientIoMessage>,
|
message_channel: IoChannel<ClientIoMessage>,
|
||||||
db_config: &DatabaseConfig,
|
db_config: &DatabaseConfig,
|
||||||
) -> Result<Arc<Client>, ClientError> {
|
) -> Result<Arc<Client>, ClientError> {
|
||||||
|
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
let gb = spec.genesis_block();
|
let gb = spec.genesis_block();
|
||||||
|
|
||||||
@ -221,7 +227,8 @@ impl Client {
|
|||||||
accountdb: Default::default(),
|
accountdb: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let client = Client {
|
let client = Arc::new(Client {
|
||||||
|
enabled: AtomicBool::new(true),
|
||||||
sleep_state: Mutex::new(SleepState::new(awake)),
|
sleep_state: Mutex::new(SleepState::new(awake)),
|
||||||
liveness: AtomicBool::new(awake),
|
liveness: AtomicBool::new(awake),
|
||||||
mode: Mutex::new(config.mode.clone()),
|
mode: Mutex::new(config.mode.clone()),
|
||||||
@ -246,8 +253,15 @@ impl Client {
|
|||||||
history: history,
|
history: history,
|
||||||
rng: Mutex::new(try!(OsRng::new().map_err(::util::UtilError::StdIo))),
|
rng: Mutex::new(try!(OsRng::new().map_err(::util::UtilError::StdIo))),
|
||||||
on_mode_change: Mutex::new(None),
|
on_mode_change: Mutex::new(None),
|
||||||
};
|
registrar: Mutex::new(None),
|
||||||
Ok(Arc::new(client))
|
});
|
||||||
|
if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) {
|
||||||
|
trace!(target: "client", "Found registrar at {}", reg_addr);
|
||||||
|
let weak = Arc::downgrade(&client);
|
||||||
|
let registrar = Registry::new(reg_addr, move |a, d| weak.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d)));
|
||||||
|
*client.registrar.lock() = Some(registrar);
|
||||||
|
}
|
||||||
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an actor to be notified on certain events
|
/// Adds an actor to be notified on certain events
|
||||||
@ -268,6 +282,11 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the Registry object - useful for looking up names.
|
||||||
|
pub fn registrar(&self) -> MutexGuard<Option<Registry>> {
|
||||||
|
self.registrar.lock()
|
||||||
|
}
|
||||||
|
|
||||||
/// Register an action to be done if a mode change happens.
|
/// Register an action to be done if a mode change happens.
|
||||||
pub fn on_mode_change<F>(&self, f: F) where F: 'static + FnMut(&Mode) + Send {
|
pub fn on_mode_change<F>(&self, f: F) where F: 'static + FnMut(&Mode) + Send {
|
||||||
*self.on_mode_change.lock() = Some(Box::new(f));
|
*self.on_mode_change.lock() = Some(Box::new(f));
|
||||||
@ -395,6 +414,12 @@ impl Client {
|
|||||||
|
|
||||||
/// This is triggered by a message coming from a block queue when the block is ready for insertion
|
/// This is triggered by a message coming from a block queue when the block is ready for insertion
|
||||||
pub fn import_verified_blocks(&self) -> usize {
|
pub fn import_verified_blocks(&self) -> usize {
|
||||||
|
|
||||||
|
// Shortcut out if we know we're incapable of syncing the chain.
|
||||||
|
if !self.enabled.load(AtomicOrdering::Relaxed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
let max_blocks_to_import = 4;
|
let max_blocks_to_import = 4;
|
||||||
let (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, is_empty) = {
|
let (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, is_empty) = {
|
||||||
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
|
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
|
||||||
@ -663,10 +688,17 @@ impl Client {
|
|||||||
/// Tick the client.
|
/// Tick the client.
|
||||||
// TODO: manage by real events.
|
// TODO: manage by real events.
|
||||||
pub fn tick(&self) {
|
pub fn tick(&self) {
|
||||||
|
self.check_garbage();
|
||||||
|
self.check_snooze();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_garbage(&self) {
|
||||||
self.chain.read().collect_garbage();
|
self.chain.read().collect_garbage();
|
||||||
self.block_queue.collect_garbage();
|
self.block_queue.collect_garbage();
|
||||||
self.tracedb.read().collect_garbage();
|
self.tracedb.read().collect_garbage();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_snooze(&self) {
|
||||||
let mode = self.mode.lock().clone();
|
let mode = self.mode.lock().clone();
|
||||||
match mode {
|
match mode {
|
||||||
Mode::Dark(timeout) => {
|
Mode::Dark(timeout) => {
|
||||||
@ -700,16 +732,6 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look up the block number for the given block ID.
|
|
||||||
pub fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
|
|
||||||
match id {
|
|
||||||
BlockId::Number(number) => Some(number),
|
|
||||||
BlockId::Hash(ref hash) => self.chain.read().block_number(hash),
|
|
||||||
BlockId::Earliest => Some(0),
|
|
||||||
BlockId::Latest | BlockId::Pending => Some(self.chain.read().best_block_number()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Take a snapshot at the given block.
|
/// Take a snapshot at the given block.
|
||||||
/// If the ID given is "latest", this will default to 1000 blocks behind.
|
/// If the ID given is "latest", this will default to 1000 blocks behind.
|
||||||
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> {
|
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> {
|
||||||
@ -908,8 +930,17 @@ impl BlockChainClient for Client {
|
|||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn disable(&self) {
|
||||||
|
self.set_mode(IpcMode::Off);
|
||||||
|
self.enabled.store(false, AtomicOrdering::Relaxed);
|
||||||
|
self.clear_queue();
|
||||||
|
}
|
||||||
|
|
||||||
fn set_mode(&self, new_mode: IpcMode) {
|
fn set_mode(&self, new_mode: IpcMode) {
|
||||||
trace!(target: "mode", "Client::set_mode({:?})", new_mode);
|
trace!(target: "mode", "Client::set_mode({:?})", new_mode);
|
||||||
|
if !self.enabled.load(AtomicOrdering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
let mut mode = self.mode.lock();
|
let mut mode = self.mode.lock();
|
||||||
*mode = new_mode.clone().into();
|
*mode = new_mode.clone().into();
|
||||||
@ -935,6 +966,15 @@ impl BlockChainClient for Client {
|
|||||||
Self::block_hash(&chain, id).and_then(|hash| chain.block_header_data(&hash))
|
Self::block_hash(&chain, id).and_then(|hash| chain.block_header_data(&hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
|
||||||
|
match id {
|
||||||
|
BlockId::Number(number) => Some(number),
|
||||||
|
BlockId::Hash(ref hash) => self.chain.read().block_number(hash),
|
||||||
|
BlockId::Earliest => Some(0),
|
||||||
|
BlockId::Latest | BlockId::Pending => Some(self.chain.read().best_block_number()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn block_body(&self, id: BlockId) -> Option<Bytes> {
|
fn block_body(&self, id: BlockId) -> Option<Bytes> {
|
||||||
let chain = self.chain.read();
|
let chain = self.chain.read();
|
||||||
Self::block_hash(&chain, id).and_then(|hash| chain.block_body(&hash))
|
Self::block_hash(&chain, id).and_then(|hash| chain.block_body(&hash))
|
||||||
@ -1331,6 +1371,34 @@ impl BlockChainClient for Client {
|
|||||||
earliest_state: self.state_db.lock().journal_db().earliest_era().unwrap_or(0),
|
earliest_state: self.state_db.lock().journal_db().earliest_era().unwrap_or(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String> {
|
||||||
|
let from = Address::default();
|
||||||
|
let transaction = Transaction {
|
||||||
|
nonce: self.latest_nonce(&from),
|
||||||
|
action: Action::Call(address),
|
||||||
|
gas: U256::from(50_000_000),
|
||||||
|
gas_price: U256::default(),
|
||||||
|
value: U256::default(),
|
||||||
|
data: data,
|
||||||
|
}.fake_sign(from);
|
||||||
|
|
||||||
|
self.call(&transaction, BlockId::Latest, Default::default())
|
||||||
|
.map_err(|e| format!("{:?}", e))
|
||||||
|
.map(|executed| {
|
||||||
|
executed.output
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn registrar_address(&self) -> Option<Address> {
|
||||||
|
self.registrar.lock().as_ref().map(|r| r.address.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn registry_address(&self, name: String) -> Option<Address> {
|
||||||
|
self.registrar.lock().as_ref()
|
||||||
|
.and_then(|r| r.get_address(&(name.as_bytes().sha3()), "A").ok())
|
||||||
|
.and_then(|a| if a.is_zero() { None } else { Some(a) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MiningBlockChainClient for Client {
|
impl MiningBlockChainClient for Client {
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use trace::Error as TraceError;
|
use trace::Error as TraceError;
|
||||||
use util::UtilError;
|
use util::UtilError;
|
||||||
use std::fmt::{Display, Formatter, Error as FmtError};
|
use std::fmt::{Display, Formatter, Error as FmtError};
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
//! Blockchain database client.
|
//! Blockchain database client.
|
||||||
|
|
||||||
|
mod registry;
|
||||||
mod config;
|
mod config;
|
||||||
mod error;
|
mod error;
|
||||||
mod test_client;
|
mod test_client;
|
||||||
|
264
ethcore/src/client/registry.rs
Normal file
264
ethcore/src/client/registry.rs
Normal file
File diff suppressed because one or more lines are too long
@ -488,6 +488,10 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec()))
|
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn block_number(&self, _id: BlockId) -> Option<BlockNumber> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn block_body(&self, id: BlockId) -> Option<Bytes> {
|
fn block_body(&self, id: BlockId) -> Option<Bytes> {
|
||||||
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| {
|
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| {
|
||||||
let mut stream = RlpStream::new_list(2);
|
let mut stream = RlpStream::new_list(2);
|
||||||
@ -694,10 +698,18 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
|
|
||||||
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
||||||
|
|
||||||
|
fn disable(&self) { unimplemented!(); }
|
||||||
|
|
||||||
fn pruning_info(&self) -> PruningInfo {
|
fn pruning_info(&self) -> PruningInfo {
|
||||||
PruningInfo {
|
PruningInfo {
|
||||||
earliest_chain: 1,
|
earliest_chain: 1,
|
||||||
earliest_state: 1,
|
earliest_state: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn call_contract(&self, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
|
||||||
|
|
||||||
|
fn registrar_address(&self) -> Option<Address> { None }
|
||||||
|
|
||||||
|
fn registry_address(&self, _name: String) -> Option<Address> { None }
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,9 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
/// Get raw block header data by block id.
|
/// Get raw block header data by block id.
|
||||||
fn block_header(&self, id: BlockId) -> Option<Bytes>;
|
fn block_header(&self, id: BlockId) -> Option<Bytes>;
|
||||||
|
|
||||||
|
/// Look up the block number for the given block ID.
|
||||||
|
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
|
||||||
|
|
||||||
/// Get raw block body data by block id.
|
/// Get raw block body data by block id.
|
||||||
/// Block body is an RLP list of two items: uncles and transactions.
|
/// Block body is an RLP list of two items: uncles and transactions.
|
||||||
fn block_body(&self, id: BlockId) -> Option<Bytes>;
|
fn block_body(&self, id: BlockId) -> Option<Bytes>;
|
||||||
@ -255,6 +258,10 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
/// Set the mode.
|
/// Set the mode.
|
||||||
fn set_mode(&self, mode: Mode);
|
fn set_mode(&self, mode: Mode);
|
||||||
|
|
||||||
|
/// Disable the client from importing blocks. This cannot be undone in this session and indicates
|
||||||
|
/// that a subsystem has reason to believe this executable incapable of syncing the chain.
|
||||||
|
fn disable(&self);
|
||||||
|
|
||||||
/// Returns engine-related extra info for `BlockId`.
|
/// Returns engine-related extra info for `BlockId`.
|
||||||
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>>;
|
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>>;
|
||||||
|
|
||||||
@ -263,6 +270,15 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
|
|
||||||
/// Returns information about pruning/data availability.
|
/// Returns information about pruning/data availability.
|
||||||
fn pruning_info(&self) -> PruningInfo;
|
fn pruning_info(&self) -> PruningInfo;
|
||||||
|
|
||||||
|
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
|
||||||
|
fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String>;
|
||||||
|
|
||||||
|
/// Get the address of the registry itself.
|
||||||
|
fn registrar_address(&self) -> Option<Address>;
|
||||||
|
|
||||||
|
/// Get the address of a particular blockchain service, if available.
|
||||||
|
fn registry_address(&self, name: String) -> Option<Address>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IpcConfig for BlockChainClient { }
|
impl IpcConfig for BlockChainClient { }
|
||||||
|
@ -100,6 +100,7 @@ impl AsMillis for Duration {
|
|||||||
impl AuthorityRound {
|
impl AuthorityRound {
|
||||||
/// Create a new instance of AuthorityRound engine.
|
/// Create a new instance of AuthorityRound engine.
|
||||||
pub fn new(params: CommonParams, our_params: AuthorityRoundParams, builtins: BTreeMap<Address, Builtin>) -> Result<Arc<Self>, Error> {
|
pub fn new(params: CommonParams, our_params: AuthorityRoundParams, builtins: BTreeMap<Address, Builtin>) -> Result<Arc<Self>, Error> {
|
||||||
|
let should_timeout = our_params.start_step.is_none();
|
||||||
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / our_params.step_duration.as_secs())) as usize;
|
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / our_params.step_duration.as_secs())) as usize;
|
||||||
let engine = Arc::new(
|
let engine = Arc::new(
|
||||||
AuthorityRound {
|
AuthorityRound {
|
||||||
@ -113,18 +114,17 @@ impl AuthorityRound {
|
|||||||
account_provider: Mutex::new(None),
|
account_provider: Mutex::new(None),
|
||||||
password: RwLock::new(None),
|
password: RwLock::new(None),
|
||||||
});
|
});
|
||||||
let handler = TransitionHandler { engine: Arc::downgrade(&engine) };
|
// Do not initialize timeouts for tests.
|
||||||
try!(engine.transition_service.register_handler(Arc::new(handler)));
|
if should_timeout {
|
||||||
|
let handler = TransitionHandler { engine: Arc::downgrade(&engine) };
|
||||||
|
try!(engine.transition_service.register_handler(Arc::new(handler)));
|
||||||
|
}
|
||||||
Ok(engine)
|
Ok(engine)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&self) -> usize {
|
|
||||||
self.step.load(AtomicOrdering::SeqCst)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remaining_step_duration(&self) -> Duration {
|
fn remaining_step_duration(&self) -> Duration {
|
||||||
let now = unix_now();
|
let now = unix_now();
|
||||||
let step_end = self.our_params.step_duration * (self.step() as u32 + 1);
|
let step_end = self.our_params.step_duration * (self.step.load(AtomicOrdering::SeqCst) as u32 + 1);
|
||||||
if step_end > now {
|
if step_end > now {
|
||||||
step_end - now
|
step_end - now
|
||||||
} else {
|
} else {
|
||||||
@ -228,7 +228,7 @@ impl Engine for AuthorityRound {
|
|||||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||||
if self.proposed.load(AtomicOrdering::SeqCst) { return Seal::None; }
|
if self.proposed.load(AtomicOrdering::SeqCst) { return Seal::None; }
|
||||||
let header = block.header();
|
let header = block.header();
|
||||||
let step = self.step();
|
let step = self.step.load(AtomicOrdering::SeqCst);
|
||||||
if self.is_step_proposer(step, header.author()) {
|
if self.is_step_proposer(step, header.author()) {
|
||||||
if let Some(ref ap) = *self.account_provider.lock() {
|
if let Some(ref ap) = *self.account_provider.lock() {
|
||||||
// Account should be permanently unlocked, otherwise sealing will fail.
|
// Account should be permanently unlocked, otherwise sealing will fail.
|
||||||
@ -265,7 +265,7 @@ impl Engine for AuthorityRound {
|
|||||||
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.load(AtomicOrdering::SeqCst) + 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()));
|
||||||
if ok_sig {
|
if ok_sig {
|
||||||
|
@ -29,6 +29,12 @@ pub use self::denominations::*;
|
|||||||
|
|
||||||
use super::spec::*;
|
use super::spec::*;
|
||||||
|
|
||||||
|
/// Most recent fork block that we support on Mainnet.
|
||||||
|
pub const FORK_SUPPORTED_FRONTIER: u64 = 2675000;
|
||||||
|
|
||||||
|
/// Most recent fork block that we support on Ropsten.
|
||||||
|
pub const FORK_SUPPORTED_ROPSTEN: u64 = 10;
|
||||||
|
|
||||||
fn load(b: &[u8]) -> Spec {
|
fn load(b: &[u8]) -> Spec {
|
||||||
Spec::load(b).expect("chain spec is invalid")
|
Spec::load(b).expect("chain spec is invalid")
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ extern crate lru_cache;
|
|||||||
|
|
||||||
#[cfg(feature = "jit" )]
|
#[cfg(feature = "jit" )]
|
||||||
extern crate evmjit;
|
extern crate evmjit;
|
||||||
|
extern crate ethabi;
|
||||||
|
|
||||||
pub extern crate ethstore;
|
pub extern crate ethstore;
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
use util::{U256, H256};
|
use util::{U256, H256};
|
||||||
use header::BlockNumber;
|
use header::BlockNumber;
|
||||||
|
use types::security_level::SecurityLevel;
|
||||||
|
|
||||||
/// Information about the blockchain gathered together.
|
/// Information about the blockchain gathered together.
|
||||||
#[derive(Clone, Debug, Binary)]
|
#[derive(Clone, Debug, Binary)]
|
||||||
@ -41,3 +42,15 @@ pub struct BlockChainInfo {
|
|||||||
/// Number of the first block on the best sequence.
|
/// Number of the first block on the best sequence.
|
||||||
pub first_block_number: Option<BlockNumber>,
|
pub first_block_number: Option<BlockNumber>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockChainInfo {
|
||||||
|
/// Determine the security model for the current state.
|
||||||
|
pub fn security_level(&self) -> SecurityLevel {
|
||||||
|
// TODO: Detect SecurityLevel::FullState : https://github.com/ethcore/parity/issues/3834
|
||||||
|
if self.ancient_block_number.is_none() || self.first_block_number.is_none() {
|
||||||
|
SecurityLevel::FullProofOfWork
|
||||||
|
} else {
|
||||||
|
SecurityLevel::PartialProofOfWork(self.best_block_number - self.first_block_number.expect("Guard condition means this is not none"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,4 +34,5 @@ pub mod block_import_error;
|
|||||||
pub mod restoration_status;
|
pub mod restoration_status;
|
||||||
pub mod snapshot_manifest;
|
pub mod snapshot_manifest;
|
||||||
pub mod mode;
|
pub mod mode;
|
||||||
pub mod pruning_info;
|
pub mod pruning_info;
|
||||||
|
pub mod security_level;
|
40
ethcore/src/types/security_level.rs
Normal file
40
ethcore/src/types/security_level.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Indication of how secure the chain is.
|
||||||
|
|
||||||
|
use header::BlockNumber;
|
||||||
|
|
||||||
|
/// Indication of how secure the chain is.
|
||||||
|
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq, Binary)]
|
||||||
|
pub enum SecurityLevel {
|
||||||
|
/// All blocks from genesis to chain head are known to have valid state transitions and PoW.
|
||||||
|
FullState,
|
||||||
|
/// All blocks from genesis to chain head are known to have a valid PoW.
|
||||||
|
FullProofOfWork,
|
||||||
|
/// Some recent headers (the argument) are known to have a valid PoW.
|
||||||
|
PartialProofOfWork(BlockNumber),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SecurityLevel {
|
||||||
|
/// `true` for `FullPoW`/`FullState`.
|
||||||
|
pub fn is_full(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
SecurityLevel::FullState | SecurityLevel::FullProofOfWork => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
description = "Fetching hash-addressed content."
|
description = "Fetching hash-addressed content."
|
||||||
homepage = "http://parity.io"
|
homepage = "http://parity.io"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
name = "ethcore-hash-fetch"
|
name = "parity-hash-fetch"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
@ -11,5 +11,5 @@ log = "0.3"
|
|||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
ethabi = "0.2.2"
|
ethabi = "0.2.2"
|
||||||
mime_guess = "1.6.1"
|
mime_guess = "1.6.1"
|
||||||
fetch = { path = "../../util/fetch" }
|
fetch = { path = "../util/fetch" }
|
||||||
ethcore-util = { path = "../../util" }
|
ethcore-util = { path = "../util" }
|
@ -26,7 +26,7 @@ use fetch::{Fetch, FetchError, Client as FetchClient};
|
|||||||
use urlhint::{ContractClient, URLHintContract, URLHint, URLHintResult};
|
use urlhint::{ContractClient, URLHintContract, URLHint, URLHintResult};
|
||||||
|
|
||||||
/// API for fetching by hash.
|
/// API for fetching by hash.
|
||||||
pub trait HashFetch {
|
pub trait HashFetch: Send + Sync + 'static {
|
||||||
/// Fetch hash-addressed content.
|
/// Fetch hash-addressed content.
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
/// 1. `hash` - content hash
|
/// 1. `hash` - content hash
|
||||||
@ -42,7 +42,12 @@ pub enum Error {
|
|||||||
/// Hash could not be resolved to a valid content address.
|
/// Hash could not be resolved to a valid content address.
|
||||||
NoResolution,
|
NoResolution,
|
||||||
/// Downloaded content hash does not match.
|
/// Downloaded content hash does not match.
|
||||||
HashMismatch { expected: H256, got: H256 },
|
HashMismatch {
|
||||||
|
/// Expected hash
|
||||||
|
expected: H256,
|
||||||
|
/// Computed hash
|
||||||
|
got: H256,
|
||||||
|
},
|
||||||
/// IO Error while validating hash.
|
/// IO Error while validating hash.
|
||||||
IO(io::Error),
|
IO(io::Error),
|
||||||
/// Error during fetch.
|
/// Error during fetch.
|
||||||
@ -79,7 +84,7 @@ impl Client {
|
|||||||
|
|
||||||
impl HashFetch for Client {
|
impl HashFetch for Client {
|
||||||
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>) -> Result<(), Error> {
|
fn fetch(&self, hash: H256, on_done: Box<Fn(Result<PathBuf, Error>) + Send>) -> Result<(), Error> {
|
||||||
debug!(target: "dapps", "Fetching: {:?}", hash);
|
debug!(target: "fetch", "Fetching: {:?}", hash);
|
||||||
|
|
||||||
let url = try!(
|
let url = try!(
|
||||||
self.contract.resolve(hash.to_vec()).map(|content| match content {
|
self.contract.resolve(hash.to_vec()).map(|content| match content {
|
||||||
@ -92,7 +97,7 @@ impl HashFetch for Client {
|
|||||||
}).ok_or_else(|| Error::NoResolution)
|
}).ok_or_else(|| Error::NoResolution)
|
||||||
);
|
);
|
||||||
|
|
||||||
debug!(target: "dapps", "Resolved {:?} to {:?}. Fetching...", hash, url);
|
debug!(target: "fetch", "Resolved {:?} to {:?}. Fetching...", hash, url);
|
||||||
|
|
||||||
self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
|
self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
|
||||||
fn validate_hash(hash: H256, result: Result<PathBuf, FetchError>) -> Result<PathBuf, Error> {
|
fn validate_hash(hash: H256, result: Result<PathBuf, FetchError>) -> Result<PathBuf, Error> {
|
||||||
@ -107,7 +112,7 @@ impl HashFetch for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(target: "dapps", "Content fetched, validating hash ({:?})", hash);
|
debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash);
|
||||||
on_done(validate_hash(hash, result))
|
on_done(validate_hash(hash, result))
|
||||||
})).map_err(Into::into)
|
})).map_err(Into::into)
|
||||||
}
|
}
|
@ -30,4 +30,4 @@ mod client;
|
|||||||
|
|
||||||
pub mod urlhint;
|
pub mod urlhint;
|
||||||
|
|
||||||
pub use client::{HashFetch, Client};
|
pub use client::{HashFetch, Client, Error};
|
20
ipc-common-types/Cargo.toml
Normal file
20
ipc-common-types/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
description = "Types that implement IPC and are common to multiple modules."
|
||||||
|
name = "ipc-common-types"
|
||||||
|
version = "1.5.0"
|
||||||
|
license = "GPL-3.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
ethcore-ipc-codegen = { path = "../ipc/codegen" }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.3"
|
||||||
|
semver = "0.5"
|
||||||
|
ethcore-ipc = { path = "../ipc/rpc" }
|
||||||
|
ethcore-util = { path = "../util" }
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
lto = false
|
21
ipc-common-types/build.rs
Normal file
21
ipc-common-types/build.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
extern crate ethcore_ipc_codegen;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
ethcore_ipc_codegen::derive_binary("src/types/mod.rs.in").unwrap();
|
||||||
|
}
|
26
ipc-common-types/src/lib.rs
Normal file
26
ipc-common-types/src/lib.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Updater for Parity executables
|
||||||
|
|
||||||
|
#[macro_use] extern crate log;
|
||||||
|
extern crate semver;
|
||||||
|
extern crate ethcore_util as util;
|
||||||
|
extern crate ethcore_ipc as ipc;
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
|
||||||
|
pub use types::*;
|
21
ipc-common-types/src/types/mod.rs
Normal file
21
ipc-common-types/src/types/mod.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Types used in the public api
|
||||||
|
|
||||||
|
#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/mod.rs.in"));
|
||||||
|
|
21
ipc-common-types/src/types/mod.rs.in
Normal file
21
ipc-common-types/src/types/mod.rs.in
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
pub mod release_track;
|
||||||
|
pub mod version_info;
|
||||||
|
|
||||||
|
pub use release_track::{ReleaseTrack};
|
||||||
|
pub use version_info::{VersionInfo};
|
82
ipc-common-types/src/types/release_track.rs
Normal file
82
ipc-common-types/src/types/release_track.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Types used in the public API
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// A release's track.
|
||||||
|
#[derive(PartialEq, Eq, Clone, Copy, Debug, Binary)]
|
||||||
|
pub enum ReleaseTrack {
|
||||||
|
/// Stable track.
|
||||||
|
Stable,
|
||||||
|
/// Beta track.
|
||||||
|
Beta,
|
||||||
|
/// Nightly track.
|
||||||
|
Nightly,
|
||||||
|
/// Testing track.
|
||||||
|
Testing,
|
||||||
|
/// No known track, also "current executable's track" when it's not yet known.
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ReleaseTrack {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(f, "{}", match *self {
|
||||||
|
ReleaseTrack::Stable => "stable",
|
||||||
|
ReleaseTrack::Beta => "beta",
|
||||||
|
ReleaseTrack::Nightly => "nightly",
|
||||||
|
ReleaseTrack::Testing => "testing",
|
||||||
|
ReleaseTrack::Unknown => "unknown",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for ReleaseTrack {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"stable" => ReleaseTrack::Stable,
|
||||||
|
"beta" => ReleaseTrack::Beta,
|
||||||
|
"nightly" => ReleaseTrack::Nightly,
|
||||||
|
"testing" => ReleaseTrack::Testing,
|
||||||
|
_ => ReleaseTrack::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for ReleaseTrack {
|
||||||
|
fn from(i: u8) -> Self {
|
||||||
|
match i {
|
||||||
|
1 => ReleaseTrack::Stable,
|
||||||
|
2 => ReleaseTrack::Beta,
|
||||||
|
3 => ReleaseTrack::Nightly,
|
||||||
|
4 => ReleaseTrack::Testing,
|
||||||
|
_ => ReleaseTrack::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u8> for ReleaseTrack {
|
||||||
|
fn into(self) -> u8 {
|
||||||
|
match self {
|
||||||
|
ReleaseTrack::Stable => 1,
|
||||||
|
ReleaseTrack::Beta => 2,
|
||||||
|
ReleaseTrack::Nightly => 3,
|
||||||
|
ReleaseTrack::Testing => 4,
|
||||||
|
ReleaseTrack::Unknown => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
ipc-common-types/src/types/version_info.rs
Normal file
68
ipc-common-types/src/types/version_info.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Types used in the public API
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use semver::{Version};
|
||||||
|
use util::{H160};
|
||||||
|
use util::misc::raw_package_info;
|
||||||
|
use release_track::ReleaseTrack;
|
||||||
|
|
||||||
|
/// Version information of a particular release.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Binary)]
|
||||||
|
pub struct VersionInfo {
|
||||||
|
/// The track on which it was released.
|
||||||
|
pub track: ReleaseTrack,
|
||||||
|
/// The version.
|
||||||
|
pub version: Version,
|
||||||
|
/// The (SHA1?) 160-bit hash of this build's code base.
|
||||||
|
pub hash: H160,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for VersionInfo {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(f, "{}.{}.{}-{}-{}", self.version.major, self.version.minor, self.version.patch, self.track, self.hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VersionInfo {
|
||||||
|
/// Get information for this (currently running) binary.
|
||||||
|
pub fn this() -> Self {
|
||||||
|
let raw = raw_package_info();
|
||||||
|
VersionInfo {
|
||||||
|
track: raw.0.into(),
|
||||||
|
version: { let mut v = Version::parse(raw.1).expect("Environment variables are known to be valid; qed"); v.build = vec![]; v.pre = vec![]; v },
|
||||||
|
hash: raw.2.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compose the information from the provided raw fields.
|
||||||
|
pub fn from_raw(semver: u32, track: u8, hash: H160) -> Self {
|
||||||
|
let t = track.into();
|
||||||
|
VersionInfo {
|
||||||
|
version: Version {
|
||||||
|
major: (semver >> 16) as u64,
|
||||||
|
minor: ((semver >> 8) & 0xff) as u64,
|
||||||
|
patch: (semver & 0xff) as u64,
|
||||||
|
build: vec![],
|
||||||
|
pre: vec![],
|
||||||
|
},
|
||||||
|
track: t,
|
||||||
|
hash: hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -263,7 +263,7 @@ fn binary_expr_struct(
|
|||||||
let range_ident = builder.id(format!("r{}", index));
|
let range_ident = builder.id(format!("r{}", index));
|
||||||
|
|
||||||
let error_message = "Error serializing member: ".to_owned() + &::syntax::print::pprust::expr_to_string(&member_expr);
|
let error_message = "Error serializing member: ".to_owned() + &::syntax::print::pprust::expr_to_string(&member_expr);
|
||||||
let error_message_literal = builder.expr().lit().str::<&str>(&error_message);
|
let _error_message_literal = builder.expr().lit().str::<&str>(&error_message);
|
||||||
|
|
||||||
match raw_ident.as_ref() {
|
match raw_ident.as_ref() {
|
||||||
"u8" => {
|
"u8" => {
|
||||||
@ -286,7 +286,6 @@ fn binary_expr_struct(
|
|||||||
post_write_stmts.push(quote_stmt!(cx,
|
post_write_stmts.push(quote_stmt!(cx,
|
||||||
if $range_ident.end - $range_ident.start > 0 {
|
if $range_ident.end - $range_ident.start > 0 {
|
||||||
if let Err(e) = $member_expr .to_bytes(&mut buffer[$range_ident], length_stack) {
|
if let Err(e) = $member_expr .to_bytes(&mut buffer[$range_ident], length_stack) {
|
||||||
warn!(target: "ipc", $error_message_literal);
|
|
||||||
return Err(e)
|
return Err(e)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ build = "build.rs"
|
|||||||
ethcore-ipc = { path = "../rpc" }
|
ethcore-ipc = { path = "../rpc" }
|
||||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||||
ethcore-ipc-nano = { path = "../nano" }
|
ethcore-ipc-nano = { path = "../nano" }
|
||||||
semver = "0.2"
|
semver = "0.5"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
|
|
||||||
|
@ -10,4 +10,4 @@ license = "GPL-3.0"
|
|||||||
ethcore-devtools = { path = "../../devtools" }
|
ethcore-devtools = { path = "../../devtools" }
|
||||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||||
ethcore-util = { path = "../../util" }
|
ethcore-util = { path = "../../util" }
|
||||||
semver = "0.2"
|
semver = "0.5"
|
||||||
|
@ -804,6 +804,17 @@ binary_fixed_size!(H512);
|
|||||||
binary_fixed_size!(H2048);
|
binary_fixed_size!(H2048);
|
||||||
binary_fixed_size!(Address);
|
binary_fixed_size!(Address);
|
||||||
binary_fixed_size!(BinHandshake);
|
binary_fixed_size!(BinHandshake);
|
||||||
|
binary_fixed_size!(BinVersion);
|
||||||
|
|
||||||
|
impl BinaryConvertable for ::semver::Version {
|
||||||
|
fn from_bytes(bytes: &[u8], length_stack: &mut ::std::collections::VecDeque<usize>) -> Result<Self, BinaryConvertError> {
|
||||||
|
BinVersion::from_bytes(bytes, length_stack).map(BinVersion::to_semver)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut ::std::collections::VecDeque<usize>) -> Result<(), BinaryConvertError> {
|
||||||
|
BinVersion::from(self.clone()).to_bytes(buffer, length_stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn vec_serialize() {
|
fn vec_serialize() {
|
||||||
|
@ -24,4 +24,4 @@ extern crate ethcore_util as util;
|
|||||||
pub mod interface;
|
pub mod interface;
|
||||||
pub mod binary;
|
pub mod binary;
|
||||||
pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket};
|
pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket};
|
||||||
pub use binary::{BinaryConvertable, BinaryConvertError, BinHandshake};
|
pub use binary::{BinaryConvertable, BinaryConvertError, BinVersion, BinHandshake};
|
||||||
|
@ -10,7 +10,7 @@ path = "run.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
ethcore-ipc = { path = "../rpc" }
|
ethcore-ipc = { path = "../rpc" }
|
||||||
ethcore-devtools = { path = "../../devtools" }
|
ethcore-devtools = { path = "../../devtools" }
|
||||||
semver = "0.2"
|
semver = "0.5"
|
||||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||||
ethcore-ipc-nano = { path = "../nano" }
|
ethcore-ipc-nano = { path = "../nano" }
|
||||||
ethcore-util = { path = "../../util" }
|
ethcore-util = { path = "../../util" }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "parity.js",
|
"name": "parity.js",
|
||||||
"version": "0.2.126",
|
"version": "0.2.128",
|
||||||
"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>",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"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": "node webpack/dev.server",
|
"start:app": "node webpack/dev.server",
|
||||||
"clean": "rm -rf ./build ./coverage",
|
"clean": "rm -rf ./.build ./.coverage ./.happypack ./.npmjs ./build",
|
||||||
"coveralls": "npm run testCoverage && coveralls < coverage/lcov.info",
|
"coveralls": "npm run testCoverage && coveralls < coverage/lcov.info",
|
||||||
"lint": "npm run lint:css && npm run lint:js",
|
"lint": "npm run lint:css && npm run lint:js",
|
||||||
"lint:cached": "npm run lint:css && npm run lint:js:cached",
|
"lint:cached": "npm run lint:css && npm run lint:js:cached",
|
||||||
|
@ -110,7 +110,8 @@ export function outPeers (peers) {
|
|||||||
return {
|
return {
|
||||||
active: outNumber(peers.active),
|
active: outNumber(peers.active),
|
||||||
connected: outNumber(peers.connected),
|
connected: outNumber(peers.connected),
|
||||||
max: outNumber(peers.max)
|
max: outNumber(peers.max),
|
||||||
|
peers: peers.peers.map(p => { Object.keys(p.protocols).forEach(k => { p.protocols[k].difficulty = outNumber(p.protocols[k].difficulty); }); return p; })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,10 +147,50 @@ describe('api/format/output', () => {
|
|||||||
|
|
||||||
describe('outPeers', () => {
|
describe('outPeers', () => {
|
||||||
it('converts all internal numbers to BigNumbers', () => {
|
it('converts all internal numbers to BigNumbers', () => {
|
||||||
expect(outPeers({ active: 789, connected: '456', max: 0x7b })).to.deep.equal({
|
expect(outPeers({
|
||||||
|
active: 789,
|
||||||
|
connected: '456',
|
||||||
|
max: 0x7b,
|
||||||
|
peers: [
|
||||||
|
{
|
||||||
|
caps: ['par/1'],
|
||||||
|
id: '0x01',
|
||||||
|
name: 'Parity',
|
||||||
|
network: {
|
||||||
|
localAddress: '10.0.0.1',
|
||||||
|
remoteAddress: '10.0.0.1'
|
||||||
|
},
|
||||||
|
protocols: {
|
||||||
|
par: {
|
||||||
|
difficulty: '0x0f',
|
||||||
|
head: '0x02',
|
||||||
|
version: 63
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})).to.deep.equal({
|
||||||
active: new BigNumber(789),
|
active: new BigNumber(789),
|
||||||
connected: new BigNumber(456),
|
connected: new BigNumber(456),
|
||||||
max: new BigNumber(123)
|
max: new BigNumber(123),
|
||||||
|
peers: [
|
||||||
|
{
|
||||||
|
caps: ['par/1'],
|
||||||
|
id: '0x01',
|
||||||
|
name: 'Parity',
|
||||||
|
network: {
|
||||||
|
localAddress: '10.0.0.1',
|
||||||
|
remoteAddress: '10.0.0.1'
|
||||||
|
},
|
||||||
|
protocols: {
|
||||||
|
par: {
|
||||||
|
difficulty: new BigNumber(15),
|
||||||
|
head: '0x02',
|
||||||
|
version: 63
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -54,6 +54,11 @@ export default class Parity {
|
|||||||
.execute('parity_checkRequest', inNumber16(requestId));
|
.execute('parity_checkRequest', inNumber16(requestId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consensusCapability () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_consensusCapability');
|
||||||
|
}
|
||||||
|
|
||||||
dappsPort () {
|
dappsPort () {
|
||||||
return this._transport
|
return this._transport
|
||||||
.execute('parity_dappsPort')
|
.execute('parity_dappsPort')
|
||||||
@ -90,6 +95,11 @@ export default class Parity {
|
|||||||
.execute('parity_enode');
|
.execute('parity_enode');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
executeUpgrade () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_executeUpgrade');
|
||||||
|
}
|
||||||
|
|
||||||
extraData () {
|
extraData () {
|
||||||
return this._transport
|
return this._transport
|
||||||
.execute('parity_extraData');
|
.execute('parity_extraData');
|
||||||
@ -243,6 +253,11 @@ export default class Parity {
|
|||||||
.then(outAddress);
|
.then(outAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
releasesInfo () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_releasesInfo');
|
||||||
|
}
|
||||||
|
|
||||||
removeReservedPeer (encode) {
|
removeReservedPeer (encode) {
|
||||||
return this._transport
|
return this._transport
|
||||||
.execute('parity_removeReservedPeer', encode);
|
.execute('parity_removeReservedPeer', encode);
|
||||||
@ -315,4 +330,14 @@ export default class Parity {
|
|||||||
.execute('parity_unsignedTransactionsCount')
|
.execute('parity_unsignedTransactionsCount')
|
||||||
.then(outNumber);
|
.then(outNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upgradeReady () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_upgradeReady');
|
||||||
|
}
|
||||||
|
|
||||||
|
versionInfo () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_versionInfo');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ describe('api/rpc/parity', () => {
|
|||||||
|
|
||||||
describe('newPeers', () => {
|
describe('newPeers', () => {
|
||||||
it('returns the peer structure, formatted', () => {
|
it('returns the peer structure, formatted', () => {
|
||||||
mockHttp([{ method: 'parity_netPeers', reply: { result: { active: 123, connected: 456, max: 789 } } }]);
|
mockHttp([{ method: 'parity_netPeers', reply: { result: { active: 123, connected: 456, max: 789, peers: [] } } }]);
|
||||||
|
|
||||||
return instance.netPeers().then((peers) => {
|
return instance.netPeers().then((peers) => {
|
||||||
expect(peers.active.eq(123)).to.be.true;
|
expect(peers.active.eq(123)).to.be.true;
|
||||||
|
@ -100,6 +100,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
consensusCapability: {
|
||||||
|
desc: 'Returns an object or string detailing the state of parity capability of maintaining consensus',
|
||||||
|
params: [],
|
||||||
|
returns: {
|
||||||
|
type: Object,
|
||||||
|
desc: 'Either "capable", {"capableUntil":N}, {"incapableSince":N} or "unknown" (N is a block number)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
dappsPort: {
|
dappsPort: {
|
||||||
desc: 'Returns the port the dapps are running on, error if not enabled',
|
desc: 'Returns the port the dapps are running on, error if not enabled',
|
||||||
params: [],
|
params: [],
|
||||||
@ -163,6 +172,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
executeUpgrade: {
|
||||||
|
desc: 'Performs an upgrade',
|
||||||
|
params: [],
|
||||||
|
returns: {
|
||||||
|
type: Boolean,
|
||||||
|
desc: 'returns true if the upgrade to the release specified in parity_upgradeReady was successfully executed, false if not'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
extraData: {
|
extraData: {
|
||||||
desc: 'Returns currently set extra data',
|
desc: 'Returns currently set extra data',
|
||||||
params: [],
|
params: [],
|
||||||
@ -468,6 +486,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
releasesInfo: {
|
||||||
|
desc: 'returns a ReleasesInfo object describing the current status of releases',
|
||||||
|
params: [],
|
||||||
|
returns: {
|
||||||
|
type: Object,
|
||||||
|
desc: '"fork":N,"minor":null,"this_fork":MN,"track":R} (N is a block number representing the latest known fork of this chain which may be in the future, MN is a block number representing the latest known fork that the currently running binary can sync past or null if not known, R is a ReleaseInfo object describing the latest release in this release track)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
removeReservedPeer: {
|
removeReservedPeer: {
|
||||||
desc: '?',
|
desc: '?',
|
||||||
params: [
|
params: [
|
||||||
@ -651,5 +678,23 @@ export default {
|
|||||||
type: Quantity,
|
type: Quantity,
|
||||||
desc: 'Number of unsigned transactions'
|
desc: 'Number of unsigned transactions'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
upgradeReady: {
|
||||||
|
desc: 'returns a ReleaseInfo object describing the release which is available for upgrade or null if none is available',
|
||||||
|
params: [],
|
||||||
|
returns: {
|
||||||
|
type: Object,
|
||||||
|
desc: '{"binary":H,"fork":15100,"is_critical":true,"version":V} where H is the Keccak-256 checksum of the release parity binary and V is a VersionInfo object describing the release'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
versionInfo: {
|
||||||
|
desc: 'returns a VersionInfo object describing our current version',
|
||||||
|
params: [],
|
||||||
|
returns: {
|
||||||
|
type: Object,
|
||||||
|
desc: '{"hash":H,"track":T,"version":{"major":N,"minor":N,"patch":N}} (H is a 160-bit Git commit hash, T is a ReleaseTrack, either "stable", "beta", "nightly" or "unknown" and N is a version number)'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
17
js/src/modals/UpgradeParity/index.js
Normal file
17
js/src/modals/UpgradeParity/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './upgradeParity';
|
146
js/src/modals/UpgradeParity/store.js
Normal file
146
js/src/modals/UpgradeParity/store.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { action, computed, observable, transaction } from 'mobx';
|
||||||
|
import store from 'store';
|
||||||
|
|
||||||
|
const LS_UPDATE = '_parity::update';
|
||||||
|
|
||||||
|
const A_MINUTE = 60 * 1000;
|
||||||
|
const A_DAY = 24 * 60 * A_MINUTE;
|
||||||
|
|
||||||
|
const STEP_INFO = 0;
|
||||||
|
const STEP_UPDATING = 1;
|
||||||
|
const STEP_COMPLETED = 2;
|
||||||
|
const STEP_ERROR = 2;
|
||||||
|
|
||||||
|
const CHECK_INTERVAL = 1 * A_MINUTE;
|
||||||
|
|
||||||
|
export default class Store {
|
||||||
|
@observable available = null;
|
||||||
|
@observable consensusCapability = null;
|
||||||
|
@observable closed = true;
|
||||||
|
@observable error = null;
|
||||||
|
@observable remindAt = 0;
|
||||||
|
@observable step = 0;
|
||||||
|
@observable upgrading = null;
|
||||||
|
@observable version = null;
|
||||||
|
|
||||||
|
constructor (api) {
|
||||||
|
this._api = api;
|
||||||
|
|
||||||
|
this.loadStorage();
|
||||||
|
this.checkUpgrade();
|
||||||
|
|
||||||
|
setInterval(this.checkUpgrade, CHECK_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get isVisible () {
|
||||||
|
return !this.closed && Date.now() >= this.remindAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action closeModal = () => {
|
||||||
|
transaction(() => {
|
||||||
|
this.closed = true;
|
||||||
|
this.setStep(0, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@action loadStorage = () => {
|
||||||
|
const values = store.get(LS_UPDATE) || {};
|
||||||
|
|
||||||
|
this.remindAt = values.remindAt ? values.remindAt : 0;
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action openModal = () => {
|
||||||
|
this.closed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action setStep = (step, error = null) => {
|
||||||
|
transaction(() => {
|
||||||
|
this.error = error;
|
||||||
|
this.step = step;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@action setUpgrading () {
|
||||||
|
transaction(() => {
|
||||||
|
this.upgrading = this.available;
|
||||||
|
this.setStep(STEP_UPDATING, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@action setVersions (available, version, consensusCapability) {
|
||||||
|
transaction(() => {
|
||||||
|
this.available = available;
|
||||||
|
this.consensusCapability = consensusCapability;
|
||||||
|
this.version = version;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@action snoozeTillTomorrow = () => {
|
||||||
|
this.remindAt = Date.now() + A_DAY;
|
||||||
|
store.set(LS_UPDATE, Object.assign(this.loadStorage(), { remindAt: this.remindAt }));
|
||||||
|
}
|
||||||
|
|
||||||
|
@action upgradeNow = () => {
|
||||||
|
this.setUpgrading();
|
||||||
|
|
||||||
|
return this._api.parity
|
||||||
|
.executeUpgrade()
|
||||||
|
.then((result) => {
|
||||||
|
if (!result) {
|
||||||
|
throw new Error('Unable to complete update');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setStep(STEP_COMPLETED, null);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('upgradeNow', error);
|
||||||
|
|
||||||
|
this.setStep(STEP_ERROR, error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkUpgrade = () => {
|
||||||
|
if (!this._api) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise
|
||||||
|
.all([
|
||||||
|
this._api.parity.upgradeReady(),
|
||||||
|
this._api.parity.consensusCapability(),
|
||||||
|
this._api.parity.versionInfo()
|
||||||
|
])
|
||||||
|
.then(([available, consensusCapability, version]) => {
|
||||||
|
console.log('[checkUpgrade]', 'available:', available, 'version:', version, 'consensusCapability:', consensusCapability);
|
||||||
|
this.setVersions(available, version, consensusCapability);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('checkUpgrade', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
STEP_COMPLETED,
|
||||||
|
STEP_ERROR,
|
||||||
|
STEP_INFO,
|
||||||
|
STEP_UPDATING
|
||||||
|
};
|
58
js/src/modals/UpgradeParity/store.spec.js
Normal file
58
js/src/modals/UpgradeParity/store.spec.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import Store from './store';
|
||||||
|
|
||||||
|
let store;
|
||||||
|
|
||||||
|
describe('modals/UpgradeParity/store', () => {
|
||||||
|
describe('@actions', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
store = new Store();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('openModal & closeModal', () => {
|
||||||
|
it('toggles between the closed states', () => {
|
||||||
|
expect(store.closed).to.be.true;
|
||||||
|
store.openModal();
|
||||||
|
expect(store.closed).to.be.false;
|
||||||
|
store.closeModal();
|
||||||
|
expect(store.closed).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resets the step state upon closing', () => {
|
||||||
|
store.setStep(5, 'soem error');
|
||||||
|
store.closeModal();
|
||||||
|
expect(store.step).to.equal(0);
|
||||||
|
expect(store.error).to.be.null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setStep', () => {
|
||||||
|
it('sets the step as provided', () => {
|
||||||
|
expect(store.step).to.equal(0);
|
||||||
|
store.setStep(3);
|
||||||
|
expect(store.step).to.equal(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the error when provided', () => {
|
||||||
|
expect(store.error).to.be.null;
|
||||||
|
store.setStep(3, new Error('some error'));
|
||||||
|
expect(store.error).to.match(/some error/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
32
js/src/modals/UpgradeParity/upgradeParity.css
Normal file
32
js/src/modals/UpgradeParity/upgradeParity.css
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
/* This file is part of Parity.
|
||||||
|
/*
|
||||||
|
/* Parity is free software: you can redistribute it and/or modify
|
||||||
|
/* it under the terms of the GNU General Public License as published by
|
||||||
|
/* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
/* (at your option) any later version.
|
||||||
|
/*
|
||||||
|
/* Parity is distributed in the hope that it will be useful,
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
/* GNU General Public License for more details.
|
||||||
|
/*
|
||||||
|
/* You should have received a copy of the GNU General Public License
|
||||||
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.error {
|
||||||
|
padding-top: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoStep {
|
||||||
|
div+div {
|
||||||
|
padding-top: 1.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
display: inline;
|
||||||
|
opacity: 0.5;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
257
js/src/modals/UpgradeParity/upgradeParity.js
Normal file
257
js/src/modals/UpgradeParity/upgradeParity.js
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { Button } from '~/ui';
|
||||||
|
import { CancelIcon, DoneIcon, NextIcon } from '~/ui/Icons';
|
||||||
|
import Modal, { Busy, Completed } from '~/ui/Modal';
|
||||||
|
|
||||||
|
import { STEP_COMPLETED, STEP_ERROR, STEP_INFO, STEP_UPDATING } from './store';
|
||||||
|
import styles from './upgradeParity.css';
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class UpgradeParity extends Component {
|
||||||
|
static contextTypes = {
|
||||||
|
api: PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
store: PropTypes.object.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { store } = this.props;
|
||||||
|
|
||||||
|
if (!store.isVisible) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
actions={ this.renderActions() }
|
||||||
|
current={ store.step }
|
||||||
|
steps={ [
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.step.info'
|
||||||
|
key='info'
|
||||||
|
defaultMessage='upgrade available' />,
|
||||||
|
<FormattedMessage
|
||||||
|
key='updating'
|
||||||
|
id='upgradeParity.step.updating'
|
||||||
|
defaultMessage='upgrading parity' />,
|
||||||
|
store.step === STEP_ERROR
|
||||||
|
? <FormattedMessage
|
||||||
|
id='upgradeParity.step.error'
|
||||||
|
key='error'
|
||||||
|
defaultMessage='error' />
|
||||||
|
: <FormattedMessage
|
||||||
|
id='upgradeParity.step.completed'
|
||||||
|
key='completed'
|
||||||
|
defaultMessage='upgrade completed' />
|
||||||
|
] }
|
||||||
|
visible>
|
||||||
|
{ this.renderStep() }
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderActions () {
|
||||||
|
const { store } = this.props;
|
||||||
|
|
||||||
|
const closeButton =
|
||||||
|
<Button
|
||||||
|
icon={ <CancelIcon /> }
|
||||||
|
key='close'
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.button.close'
|
||||||
|
defaultMessage='close' />
|
||||||
|
}
|
||||||
|
onClick={ store.closeModal } />;
|
||||||
|
const doneButton =
|
||||||
|
<Button
|
||||||
|
icon={ <DoneIcon /> }
|
||||||
|
key='done'
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.button.done'
|
||||||
|
defaultMessage='done' />
|
||||||
|
}
|
||||||
|
onClick={ store.closeModal } />;
|
||||||
|
|
||||||
|
switch (store.step) {
|
||||||
|
case STEP_INFO:
|
||||||
|
return [
|
||||||
|
<Button
|
||||||
|
icon={ <NextIcon /> }
|
||||||
|
key='upgrade'
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.button.upgrade'
|
||||||
|
defaultMessage='upgrade now' />
|
||||||
|
}
|
||||||
|
onClick={ store.upgradeNow } />,
|
||||||
|
closeButton
|
||||||
|
];
|
||||||
|
|
||||||
|
case STEP_UPDATING:
|
||||||
|
return [
|
||||||
|
closeButton
|
||||||
|
];
|
||||||
|
|
||||||
|
case STEP_COMPLETED:
|
||||||
|
case STEP_ERROR:
|
||||||
|
return [
|
||||||
|
doneButton
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStep () {
|
||||||
|
const { store } = this.props;
|
||||||
|
|
||||||
|
const currentversion = this.formatVersion(store);
|
||||||
|
const newversion = store.upgrading
|
||||||
|
? this.formatVersion(store.upgrading)
|
||||||
|
: this.formatVersion(store.available);
|
||||||
|
|
||||||
|
switch (store.step) {
|
||||||
|
case STEP_INFO:
|
||||||
|
return (
|
||||||
|
<div className={ styles.infoStep }>
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.info.upgrade'
|
||||||
|
defaultMessage='A new version of Parity, version {newversion} is available as an upgrade from your current version {currentversion}'
|
||||||
|
values={ {
|
||||||
|
currentversion: <div className={ styles.version }>{ currentversion }</div>,
|
||||||
|
newversion: <div className={ styles.version }>{ newversion }</div>
|
||||||
|
} } />
|
||||||
|
</div>
|
||||||
|
{ this.renderConsensusInfo() }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
case STEP_UPDATING:
|
||||||
|
return (
|
||||||
|
<Busy
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.busy'
|
||||||
|
defaultMessage='Your upgrade to Parity {newversion} is currently in progress'
|
||||||
|
values={ {
|
||||||
|
newversion: <div className={ styles.version }>{ newversion }</div>
|
||||||
|
} } />
|
||||||
|
} />
|
||||||
|
);
|
||||||
|
|
||||||
|
case STEP_COMPLETED:
|
||||||
|
case STEP_ERROR:
|
||||||
|
if (store.error) {
|
||||||
|
return (
|
||||||
|
<Completed>
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.failed'
|
||||||
|
defaultMessage='Your upgrade to Parity {newversion} has failed with an error.'
|
||||||
|
values={ {
|
||||||
|
newversion: <div className={ styles.version }>{ newversion }</div>
|
||||||
|
} } />
|
||||||
|
</div>
|
||||||
|
<div className={ styles.error }>
|
||||||
|
{ store.error.message }
|
||||||
|
</div>
|
||||||
|
</Completed>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Completed>
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.completed'
|
||||||
|
defaultMessage='Your upgrade to Parity {newversion} has been successfully completed.'
|
||||||
|
values={ {
|
||||||
|
newversion: <div className={ styles.version }>{ newversion }</div>
|
||||||
|
} } />
|
||||||
|
</Completed>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderConsensusInfo () {
|
||||||
|
const { store } = this.props;
|
||||||
|
const { consensusCapability } = store;
|
||||||
|
|
||||||
|
if (consensusCapability) {
|
||||||
|
if (consensusCapability === 'capable') {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.consensus.capable'
|
||||||
|
defaultMessage='Your current Parity version is capable of handling the network requirements.' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (consensusCapability.capableUntil) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.consensus.capableUntil'
|
||||||
|
defaultMessage='Your current Parity version is capable of handling the network requirements until block {blockNumber}'
|
||||||
|
values={ {
|
||||||
|
blockNumber: consensusCapability.capableUntil
|
||||||
|
} } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (consensusCapability.incapableSince) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.consensus.incapableSince'
|
||||||
|
defaultMessage='Your current Parity version is incapable of handling the network requirements since block {blockNumber}'
|
||||||
|
values={ {
|
||||||
|
blockNumber: consensusCapability.incapableSince
|
||||||
|
} } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.consensus.unknown'
|
||||||
|
defaultMessage='Your current Parity version is capable of handling the network requirements.' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
formatVersion (struct) {
|
||||||
|
if (!struct || !struct.version) {
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='upgradeParity.version.unknown'
|
||||||
|
defaultMessage='unknown' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { track, version } = struct.version;
|
||||||
|
|
||||||
|
return `${version.major}.${version.minor}.${version.patch}-${track}`;
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,8 @@ import VerificationStore, {
|
|||||||
} from './store';
|
} from './store';
|
||||||
import { postToServer } from '../../3rdparty/email-verification';
|
import { postToServer } from '../../3rdparty/email-verification';
|
||||||
|
|
||||||
|
const EMAIL_VERIFICATION = 4; // id in the `BadgeReg.sol` contract
|
||||||
|
|
||||||
export default class EmailVerificationStore extends VerificationStore {
|
export default class EmailVerificationStore extends VerificationStore {
|
||||||
@observable email = '';
|
@observable email = '';
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ export default class EmailVerificationStore extends VerificationStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor (api, account, isTestnet) {
|
constructor (api, account, isTestnet) {
|
||||||
super(api, EmailVerificationABI, 'emailverification3', account, isTestnet);
|
super(api, EmailVerificationABI, EMAIL_VERIFICATION, account, isTestnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestValues = () => [ sha3(this.email) ]
|
requestValues = () => [ sha3(this.email) ]
|
||||||
|
@ -23,6 +23,8 @@ import VerificationStore, {
|
|||||||
} from './store';
|
} from './store';
|
||||||
import { postToServer } from '../../3rdparty/sms-verification';
|
import { postToServer } from '../../3rdparty/sms-verification';
|
||||||
|
|
||||||
|
const SMS_VERIFICATION = 0; // id in the `BadgeReg.sol` contract
|
||||||
|
|
||||||
export default class SMSVerificationStore extends VerificationStore {
|
export default class SMSVerificationStore extends VerificationStore {
|
||||||
@observable number = '';
|
@observable number = '';
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ export default class SMSVerificationStore extends VerificationStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor (api, account, isTestnet) {
|
constructor (api, account, isTestnet) {
|
||||||
super(api, SMSVerificationABI, 'smsverification', account, isTestnet);
|
super(api, SMSVerificationABI, SMS_VERIFICATION, account, isTestnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action setNumber = (number) => {
|
@action setNumber = (number) => {
|
||||||
|
@ -46,13 +46,13 @@ export default class VerificationStore {
|
|||||||
@observable isCodeValid = null;
|
@observable isCodeValid = null;
|
||||||
@observable confirmationTx = null;
|
@observable confirmationTx = null;
|
||||||
|
|
||||||
constructor (api, abi, name, account, isTestnet) {
|
constructor (api, abi, certifierId, account, isTestnet) {
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.isTestnet = isTestnet;
|
this.isTestnet = isTestnet;
|
||||||
|
|
||||||
this.step = LOADING;
|
this.step = LOADING;
|
||||||
Contracts.get().badgeReg.fetchCertifier(name)
|
Contracts.get().badgeReg.fetchCertifier(certifierId)
|
||||||
.then(({ address }) => {
|
.then(({ address }) => {
|
||||||
this.contract = new Contract(api, abi).at(address);
|
this.contract = new Contract(api, abi).at(address);
|
||||||
this.load();
|
this.load();
|
||||||
|
@ -23,12 +23,13 @@ import DeployContract from './DeployContract';
|
|||||||
import EditMeta from './EditMeta';
|
import EditMeta from './EditMeta';
|
||||||
import ExecuteContract from './ExecuteContract';
|
import ExecuteContract from './ExecuteContract';
|
||||||
import FirstRun from './FirstRun';
|
import FirstRun from './FirstRun';
|
||||||
|
import LoadContract from './LoadContract';
|
||||||
|
import SaveContract from './SaveContract';
|
||||||
import Shapeshift from './Shapeshift';
|
import Shapeshift from './Shapeshift';
|
||||||
import Verification from './Verification';
|
import Verification from './Verification';
|
||||||
import Transfer from './Transfer';
|
import Transfer from './Transfer';
|
||||||
import PasswordManager from './PasswordManager';
|
import PasswordManager from './PasswordManager';
|
||||||
import SaveContract from './SaveContract';
|
import UpgradeParity from './UpgradeParity';
|
||||||
import LoadContract from './LoadContract';
|
|
||||||
import WalletSettings from './WalletSettings';
|
import WalletSettings from './WalletSettings';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -41,11 +42,12 @@ export {
|
|||||||
EditMeta,
|
EditMeta,
|
||||||
ExecuteContract,
|
ExecuteContract,
|
||||||
FirstRun,
|
FirstRun,
|
||||||
|
LoadContract,
|
||||||
|
SaveContract,
|
||||||
Shapeshift,
|
Shapeshift,
|
||||||
Verification,
|
Verification,
|
||||||
Transfer,
|
Transfer,
|
||||||
PasswordManager,
|
PasswordManager,
|
||||||
LoadContract,
|
UpgradeParity,
|
||||||
SaveContract,
|
|
||||||
WalletSettings
|
WalletSettings
|
||||||
};
|
};
|
||||||
|
31
js/src/ui/Icons/index.js
Normal file
31
js/src/ui/Icons/index.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import AddIcon from 'material-ui/svg-icons/content/add';
|
||||||
|
import CancelIcon from 'material-ui/svg-icons/content/clear';
|
||||||
|
import DoneIcon from 'material-ui/svg-icons/action/done-all';
|
||||||
|
import PrevIcon from 'material-ui/svg-icons/navigation/arrow-back';
|
||||||
|
import NextIcon from 'material-ui/svg-icons/navigation/arrow-forward';
|
||||||
|
import SnoozeIcon from 'material-ui/svg-icons/av/snooze';
|
||||||
|
|
||||||
|
export {
|
||||||
|
AddIcon,
|
||||||
|
CancelIcon,
|
||||||
|
DoneIcon,
|
||||||
|
PrevIcon,
|
||||||
|
NextIcon,
|
||||||
|
SnoozeIcon
|
||||||
|
};
|
@ -16,17 +16,19 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
|
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
import styles from './busy.css';
|
import styles from './busy.css';
|
||||||
|
|
||||||
export default class Busy extends Component {
|
export default class Busy extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
title: PropTypes.string,
|
children: PropTypes.node,
|
||||||
state: PropTypes.string,
|
state: nodeOrStringProptype(),
|
||||||
children: PropTypes.node
|
title: nodeOrStringProptype()
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { children, title, state } = this.props;
|
const { children, state, title } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.center }>
|
<div className={ styles.center }>
|
||||||
|
@ -36,7 +36,13 @@ export default class Title extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.title }>
|
<div className={ styles.title }>
|
||||||
<h3>{ steps ? steps[current] : title }</h3>
|
<h3>
|
||||||
|
{
|
||||||
|
steps
|
||||||
|
? steps[current]
|
||||||
|
: title
|
||||||
|
}
|
||||||
|
</h3>
|
||||||
{ this.renderSteps() }
|
{ this.renderSteps() }
|
||||||
{ this.renderWaiting() }
|
{ this.renderWaiting() }
|
||||||
</div>
|
</div>
|
||||||
@ -63,10 +69,10 @@ export default class Title extends Component {
|
|||||||
renderTimeline () {
|
renderTimeline () {
|
||||||
const { steps } = this.props;
|
const { steps } = this.props;
|
||||||
|
|
||||||
return steps.map((label) => {
|
return steps.map((label, index) => {
|
||||||
return (
|
return (
|
||||||
<Step
|
<Step
|
||||||
key={ label }>
|
key={ label.key || index }>
|
||||||
<StepLabel>
|
<StepLabel>
|
||||||
{ label }
|
{ label }
|
||||||
</StepLabel>
|
</StepLabel>
|
||||||
|
@ -14,16 +14,17 @@
|
|||||||
/* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
background: rgba(0, 0, 0, 0.25) !important;
|
background: rgba(0, 0, 0, 0.25) !important;
|
||||||
}
|
|
||||||
|
|
||||||
.actions button:not([disabled]) {
|
button:not([disabled]) {
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
|
||||||
|
|
||||||
.actions button:not([disabled]) svg {
|
svg {
|
||||||
fill: white !important;
|
fill: white !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
@ -36,26 +37,26 @@
|
|||||||
.content {
|
.content {
|
||||||
transform: translate(0px, 0px) !important;
|
transform: translate(0px, 0px) !important;
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
|
||||||
|
|
||||||
.content>div {
|
&>div {
|
||||||
background: rgba(0, 0, 0, 0.5) !important;
|
background: rgba(0, 0, 0, 0.5) !important;
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
background: rgba(0, 0, 0, 0.25) !important;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.25) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title h3 {
|
h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title .steps {
|
.steps {
|
||||||
margin-bottom: -1em;
|
margin-bottom: -1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.waiting {
|
.waiting {
|
||||||
|
@ -14,10 +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 { Dialog } from 'material-ui';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { Dialog } from 'material-ui';
|
|
||||||
|
|
||||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class Modal extends Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { muiTheme } = this.context;
|
const { muiTheme } = this.context;
|
||||||
const { actions, busy, className, current, children, compact, steps, waiting, title, visible, settings } = this.props;
|
const { actions, busy, children, className, current, compact, settings, steps, title, visible, waiting } = this.props;
|
||||||
const contentStyle = muiTheme.parity.getBackgroundStyle(null, settings.backgroundSeed);
|
const contentStyle = muiTheme.parity.getBackgroundStyle(null, settings.backgroundSeed);
|
||||||
const header = (
|
const header = (
|
||||||
<Title
|
<Title
|
||||||
|
@ -33,6 +33,7 @@ import Errors from './Errors';
|
|||||||
import Form, { AddressSelect, FormWrap, TypedInput, Input, InputAddress, InputAddressSelect, InputChip, InputInline, Select, RadioButtons } from './Form';
|
import Form, { AddressSelect, FormWrap, TypedInput, Input, InputAddress, InputAddressSelect, InputChip, InputInline, Select, RadioButtons } from './Form';
|
||||||
import GasPriceEditor from './GasPriceEditor';
|
import GasPriceEditor from './GasPriceEditor';
|
||||||
import GasPriceSelector from './GasPriceSelector';
|
import GasPriceSelector from './GasPriceSelector';
|
||||||
|
import Icons from './Icons';
|
||||||
import IdentityIcon from './IdentityIcon';
|
import IdentityIcon from './IdentityIcon';
|
||||||
import IdentityName from './IdentityName';
|
import IdentityName from './IdentityName';
|
||||||
import LanguageSelector from './LanguageSelector';
|
import LanguageSelector from './LanguageSelector';
|
||||||
@ -72,6 +73,7 @@ export {
|
|||||||
FormWrap,
|
FormWrap,
|
||||||
GasPriceEditor,
|
GasPriceEditor,
|
||||||
GasPriceSelector,
|
GasPriceSelector,
|
||||||
|
Icons,
|
||||||
Input,
|
Input,
|
||||||
InputAddress,
|
InputAddress,
|
||||||
InputAddressSelect,
|
InputAddressSelect,
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
import { FirstRun } from '~/modals';
|
import { FirstRun, UpgradeParity } from '~/modals';
|
||||||
import { Errors, ParityBackground, Tooltips } from '~/ui';
|
import { Errors, ParityBackground, Tooltips } from '~/ui';
|
||||||
|
|
||||||
import styles from '../application.css';
|
import styles from '../application.css';
|
||||||
@ -28,20 +28,24 @@ export default class Container extends Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
|
onCloseFirstRun: PropTypes.func,
|
||||||
showFirstRun: PropTypes.bool,
|
showFirstRun: PropTypes.bool,
|
||||||
onCloseFirstRun: PropTypes.func
|
upgradeStore: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { children, showFirstRun, onCloseFirstRun } = this.props;
|
|
||||||
const { muiTheme } = this.context;
|
const { muiTheme } = this.context;
|
||||||
|
const { children, onCloseFirstRun, showFirstRun, upgradeStore } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ParityBackground className={ styles.container } muiTheme={ muiTheme }>
|
<ParityBackground
|
||||||
|
className={ styles.container }
|
||||||
|
muiTheme={ muiTheme }>
|
||||||
<FirstRun
|
<FirstRun
|
||||||
visible={ showFirstRun }
|
onClose={ onCloseFirstRun }
|
||||||
onClose={ onCloseFirstRun } />
|
visible={ showFirstRun } />
|
||||||
<Tooltips />
|
<Tooltips />
|
||||||
|
<UpgradeParity store={ upgradeStore } />
|
||||||
<Errors />
|
<Errors />
|
||||||
{ children }
|
{ children }
|
||||||
</ParityBackground>
|
</ParityBackground>
|
||||||
|
@ -14,55 +14,52 @@
|
|||||||
/* 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
position: fixed;
|
align-items: center;
|
||||||
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
color: #ccc;
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.75em;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
padding: .4em .5em;
|
||||||
|
position: fixed;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: .4em .5em;
|
|
||||||
font-size: x-small;
|
|
||||||
color: #ccc;
|
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.enode {
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.enode > * {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 .25em;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.enode > :last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.netinfo {
|
.netinfo {
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
align-items: center;
|
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
}
|
flex-grow: 1;
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
.netinfo > * {
|
div {
|
||||||
margin-left: 1em;
|
display: inline-block;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.network {
|
.network {
|
||||||
padding: 0.25em 0.5em;
|
border-radius: 0.4em;
|
||||||
border-radius: .4em;
|
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&.live {
|
||||||
|
background: rgb(0, 136, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.test {
|
||||||
|
background: rgb(136, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.networklive {
|
.upgrade {
|
||||||
background: rgb(0, 136, 0);
|
div {
|
||||||
}
|
display: inline-block;
|
||||||
|
margin-left: 1em;
|
||||||
.networktest {
|
}
|
||||||
background: rgb(136, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
@ -15,78 +15,118 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
import { BlockStatus } from '~/ui';
|
import { BlockStatus } from '~/ui';
|
||||||
import CopyToClipboard from '~/ui/CopyToClipboard';
|
|
||||||
|
|
||||||
import styles from './status.css';
|
import styles from './status.css';
|
||||||
|
|
||||||
class Status extends Component {
|
class Status extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
blockNumber: PropTypes.object.isRequired,
|
|
||||||
clientVersion: PropTypes.string,
|
clientVersion: PropTypes.string,
|
||||||
enode: PropTypes.string,
|
isTest: PropTypes.bool,
|
||||||
netPeers: PropTypes.object,
|
|
||||||
netChain: PropTypes.string,
|
netChain: PropTypes.string,
|
||||||
isTest: PropTypes.bool
|
netPeers: PropTypes.object,
|
||||||
|
upgradeStore: PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { blockNumber, clientVersion, netChain, netPeers, isTest } = this.props;
|
const { clientVersion, isTest, netChain, netPeers } = this.props;
|
||||||
const netStyle = `${styles.network} ${styles[isTest ? 'networktest' : 'networklive']}`;
|
|
||||||
|
|
||||||
if (!blockNumber) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.status }>
|
<div className={ styles.status }>
|
||||||
<div className={ styles.version }>
|
<div className={ styles.version }>
|
||||||
{ clientVersion }
|
{ clientVersion }
|
||||||
</div>
|
</div>
|
||||||
|
<div className={ styles.upgrade }>
|
||||||
|
{ this.renderConsensus() }
|
||||||
|
{ this.renderUpgradeButton() }
|
||||||
|
</div>
|
||||||
<div className={ styles.netinfo }>
|
<div className={ styles.netinfo }>
|
||||||
<BlockStatus />
|
<BlockStatus />
|
||||||
<div className={ netStyle }>
|
<div className={ `${styles.network} ${styles[isTest ? 'test' : 'live']}` }>
|
||||||
{ isTest ? 'test' : netChain }
|
{ netChain }
|
||||||
</div>
|
</div>
|
||||||
<div className={ styles.peers }>
|
<div className={ styles.peers }>
|
||||||
{ netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
|
{ netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ this.renderEnode() }
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEnode () {
|
renderConsensus () {
|
||||||
const { enode } = this.props;
|
const { upgradeStore } = this.props;
|
||||||
|
|
||||||
if (!enode) {
|
if (upgradeStore.consensusCapability === 'capable') {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='application.status.consensus.capable'
|
||||||
|
defaultMessage='Capable' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (upgradeStore.consensusCapability.capableUntil) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='application.status.consensus.capableUntil'
|
||||||
|
defaultMessage='Capable until #{blockNumber}'
|
||||||
|
values={ {
|
||||||
|
blockNumber: upgradeStore.consensusCapability.capableUntil
|
||||||
|
} } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (upgradeStore.consensusCapability.incapableSince) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='application.status.consensus.incapableSince'
|
||||||
|
defaultMessage='Incapable since #{blockNumber}'
|
||||||
|
values={ {
|
||||||
|
blockNumber: upgradeStore.consensusCapability.incapableSince
|
||||||
|
} } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='application.status.consensus.unknown'
|
||||||
|
defaultMessage='Unknown capability' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUpgradeButton () {
|
||||||
|
const { upgradeStore } = this.props;
|
||||||
|
|
||||||
|
if (!upgradeStore.available) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [protocol, rest] = enode.split('://');
|
|
||||||
const [id, host] = rest.split('@');
|
|
||||||
const abbreviated = `${protocol}://${id.slice(0, 3)}…${id.slice(-3)}@${host}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.enode }>
|
<div>
|
||||||
<CopyToClipboard data={ enode } size={ 12 } />
|
<a
|
||||||
<div>{ abbreviated }</div>
|
href='javascript:void(0)'
|
||||||
|
onClick={ upgradeStore.openModal }>
|
||||||
|
<FormattedMessage
|
||||||
|
id='application.status.upgrade'
|
||||||
|
defaultMessage='Upgrade' />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const { blockNumber, clientVersion, enode, netPeers, netChain, isTest } = state.nodeStatus;
|
const { clientVersion, netPeers, netChain, isTest } = state.nodeStatus;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
blockNumber,
|
|
||||||
clientVersion,
|
clientVersion,
|
||||||
enode,
|
|
||||||
netPeers,
|
netPeers,
|
||||||
netChain,
|
netChain,
|
||||||
isTest
|
isTest
|
||||||
|
@ -22,5 +22,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
padding-bottom: 1em;
|
padding-bottom: 1.25em;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ import { connect } from 'react-redux';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
|
||||||
|
import UpgradeStore from '~/modals/UpgradeParity/store';
|
||||||
|
|
||||||
import Connection from '../Connection';
|
import Connection from '../Connection';
|
||||||
import ParityBar from '../ParityBar';
|
import ParityBar from '../ParityBar';
|
||||||
|
|
||||||
@ -42,14 +44,15 @@ class Application extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
blockNumber: PropTypes.object,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
netChain: PropTypes.string,
|
|
||||||
isTest: PropTypes.bool,
|
isTest: PropTypes.bool,
|
||||||
pending: PropTypes.array,
|
netChain: PropTypes.string,
|
||||||
blockNumber: PropTypes.object
|
pending: PropTypes.array
|
||||||
}
|
}
|
||||||
|
|
||||||
store = new Store(this.context.api);
|
store = new Store(this.context.api);
|
||||||
|
upgradeStore = new UpgradeStore(this.context.api);
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const [root] = (window.location.hash || '').replace('#/', '').split('/');
|
const [root] = (window.location.hash || '').replace('#/', '').split('/');
|
||||||
@ -71,12 +74,13 @@ class Application extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderApp () {
|
renderApp () {
|
||||||
const { children, pending, netChain, isTest, blockNumber } = this.props;
|
const { blockNumber, children, pending, netChain, isTest } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
showFirstRun={ this.store.firstrunVisible }
|
upgradeStore={ this.upgradeStore }
|
||||||
onCloseFirstRun={ this.store.closeFirstrun }>
|
onCloseFirstRun={ this.store.closeFirstrun }
|
||||||
|
showFirstRun={ this.store.firstrunVisible }>
|
||||||
<TabBar
|
<TabBar
|
||||||
netChain={ netChain }
|
netChain={ netChain }
|
||||||
isTest={ isTest }
|
isTest={ isTest }
|
||||||
@ -84,7 +88,11 @@ class Application extends Component {
|
|||||||
<div className={ styles.content }>
|
<div className={ styles.content }>
|
||||||
{ children }
|
{ children }
|
||||||
</div>
|
</div>
|
||||||
{ blockNumber ? (<Status />) : null }
|
{
|
||||||
|
blockNumber
|
||||||
|
? <Status upgradeStore={ this.upgradeStore } />
|
||||||
|
: null
|
||||||
|
}
|
||||||
<Snackbar />
|
<Snackbar />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
@ -102,16 +110,16 @@ class Application extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const { netChain, isTest, blockNumber } = state.nodeStatus;
|
const { blockNumber, netChain, isTest } = state.nodeStatus;
|
||||||
const { hasAccounts } = state.personal;
|
const { hasAccounts } = state.personal;
|
||||||
const { pending } = state.signer;
|
const { pending } = state.signer;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
blockNumber,
|
||||||
hasAccounts,
|
hasAccounts,
|
||||||
netChain,
|
|
||||||
isTest,
|
isTest,
|
||||||
pending,
|
netChain,
|
||||||
blockNumber
|
pending
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
|
|
||||||
.row {
|
.row {
|
||||||
margin: 0 -1em;
|
margin: 0 -1em;
|
||||||
}
|
|
||||||
|
|
||||||
.row::after {
|
&::after {
|
||||||
display: table;
|
display: table;
|
||||||
clear: both;
|
clear: both;
|
||||||
content: '';
|
content: '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.blockInfo {
|
.blockInfo {
|
||||||
@ -44,7 +44,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.col,
|
.col,
|
||||||
.col1, .col2, .col3, .col4, .col5, .col6, .col7, .col8, .col9, .col10, .col11, .col12 {
|
.col3, .col4_5, .col6, .col12 {
|
||||||
float: left;
|
float: left;
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -57,18 +57,11 @@
|
|||||||
width: calc(100% / 12 * 3);
|
width: calc(100% / 12 * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.col4 {
|
.col4_5 {
|
||||||
width: 33.33333%;
|
width: 37.5%;
|
||||||
width: -webkit-calc(100% / 12 * 4);
|
width: -webkit-calc(100% / 12 * 4.5);
|
||||||
width: -moz-calc(100% / 12 * 4);
|
width: -moz-calc(100% / 12 * 4.5);
|
||||||
width: calc(100% / 12 * 4);
|
width: calc(100% / 12 * 4.5);
|
||||||
}
|
|
||||||
|
|
||||||
.col5 {
|
|
||||||
width: 41.66665%;
|
|
||||||
width: -webkit-calc(100% / 12 * 5);
|
|
||||||
width: -moz-calc(100% / 12 * 5);
|
|
||||||
width: calc(100% / 12 * 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.col6 {
|
.col6 {
|
||||||
|
@ -68,13 +68,13 @@ export default class Status extends Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={ styles.col5 }>
|
<div className={ styles.col4_5 }>
|
||||||
<MiningSettings
|
<MiningSettings
|
||||||
{ ...this._test('mining') }
|
{ ...this._test('mining') }
|
||||||
nodeStatus={ nodeStatus }
|
nodeStatus={ nodeStatus }
|
||||||
actions={ this.props.actions } />
|
actions={ this.props.actions } />
|
||||||
</div>
|
</div>
|
||||||
<div className={ styles.col4 }>
|
<div className={ styles.col4_5 }>
|
||||||
{ this.renderSettings() }
|
{ this.renderSettings() }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -102,6 +102,7 @@ export default class Status extends Component {
|
|||||||
<div { ...this._test('settings') }>
|
<div { ...this._test('settings') }>
|
||||||
<ContainerTitle title='network settings' />
|
<ContainerTitle title='network settings' />
|
||||||
<Input
|
<Input
|
||||||
|
allowCopy
|
||||||
readOnly
|
readOnly
|
||||||
label='chain'
|
label='chain'
|
||||||
value={ nodeStatus.netChain }
|
value={ nodeStatus.netChain }
|
||||||
@ -109,6 +110,7 @@ export default class Status extends Component {
|
|||||||
<div className={ styles.row }>
|
<div className={ styles.row }>
|
||||||
<div className={ styles.col6 }>
|
<div className={ styles.col6 }>
|
||||||
<Input
|
<Input
|
||||||
|
allowCopy
|
||||||
readOnly
|
readOnly
|
||||||
label='peers'
|
label='peers'
|
||||||
value={ peers }
|
value={ peers }
|
||||||
@ -116,6 +118,7 @@ export default class Status extends Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className={ styles.col6 }>
|
<div className={ styles.col6 }>
|
||||||
<Input
|
<Input
|
||||||
|
allowCopy
|
||||||
readOnly
|
readOnly
|
||||||
label='network port'
|
label='network port'
|
||||||
value={ nodeStatus.netPort.toString() }
|
value={ nodeStatus.netPort.toString() }
|
||||||
@ -124,6 +127,7 @@ export default class Status extends Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
allowCopy
|
||||||
readOnly
|
readOnly
|
||||||
label='rpc enabled'
|
label='rpc enabled'
|
||||||
value={ rpcSettings.enabled ? 'yes' : 'no' }
|
value={ rpcSettings.enabled ? 'yes' : 'no' }
|
||||||
@ -131,6 +135,7 @@ export default class Status extends Component {
|
|||||||
<div className={ styles.row }>
|
<div className={ styles.row }>
|
||||||
<div className={ styles.col6 }>
|
<div className={ styles.col6 }>
|
||||||
<Input
|
<Input
|
||||||
|
allowCopy
|
||||||
readOnly
|
readOnly
|
||||||
label='rpc interface'
|
label='rpc interface'
|
||||||
value={ rpcSettings.interface }
|
value={ rpcSettings.interface }
|
||||||
@ -138,12 +143,24 @@ export default class Status extends Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className={ styles.col6 }>
|
<div className={ styles.col6 }>
|
||||||
<Input
|
<Input
|
||||||
|
allowCopy
|
||||||
readOnly
|
readOnly
|
||||||
label='rpc port'
|
label='rpc port'
|
||||||
value={ rpcSettings.port.toString() }
|
value={ rpcSettings.port.toString() }
|
||||||
{ ...this._test('rpc-port') } />
|
{ ...this._test('rpc-port') } />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={ styles.row }>
|
||||||
|
<div className={ styles.col12 }>
|
||||||
|
<Input
|
||||||
|
allowCopy
|
||||||
|
readOnly
|
||||||
|
label='enode'
|
||||||
|
value={ nodeStatus.enode }
|
||||||
|
{ ...this._test('node-enode') } />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,12 @@ extern crate time;
|
|||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
use std::{env, thread, fs};
|
use std::{env, thread, fs};
|
||||||
use std::sync::Arc;
|
use std::sync::{Weak, Arc};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use isatty::{stderr_isatty, stdout_isatty};
|
use isatty::{stderr_isatty, stdout_isatty};
|
||||||
use env_logger::LogBuilder;
|
use env_logger::LogBuilder;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use util::RotatingLogger;
|
use util::{Mutex, RotatingLogger} ;
|
||||||
use util::log::Colour;
|
use util::log::Colour;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -52,6 +52,10 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref ROTATING_LOGGER : Mutex<Weak<RotatingLogger>> = Mutex::new(Default::default());
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets up the logger
|
/// Sets up the logger
|
||||||
pub fn setup_log(config: &Config) -> Result<Arc<RotatingLogger>, String> {
|
pub fn setup_log(config: &Config) -> Result<Arc<RotatingLogger>, String> {
|
||||||
use rlog::*;
|
use rlog::*;
|
||||||
@ -121,9 +125,17 @@ pub fn setup_log(config: &Config) -> Result<Arc<RotatingLogger>, String> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
builder.format(format);
|
builder.format(format);
|
||||||
builder.init().expect("Logger initialized only once.");
|
builder.init()
|
||||||
|
.and_then(|_| {
|
||||||
Ok(logs)
|
*ROTATING_LOGGER.lock() = Arc::downgrade(&logs);
|
||||||
|
Ok(logs)
|
||||||
|
})
|
||||||
|
// couldn't create new logger - try to fall back on previous logger.
|
||||||
|
.or_else(|err| match ROTATING_LOGGER.lock().upgrade() {
|
||||||
|
Some(l) => Ok(l),
|
||||||
|
// no previous logger. fatal.
|
||||||
|
None => Err(format!("{:?}", err)),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill_color(s: &str) -> String {
|
fn kill_color(s: &str) -> String {
|
||||||
|
@ -32,7 +32,6 @@ use ethcore::verification::queue::VerifierSettings;
|
|||||||
use cache::CacheConfig;
|
use cache::CacheConfig;
|
||||||
use informant::{Informant, MillisecondDuration};
|
use informant::{Informant, MillisecondDuration};
|
||||||
use params::{SpecType, Pruning, Switch, tracing_switch_to_bool, fatdb_switch_to_bool};
|
use params::{SpecType, Pruning, Switch, tracing_switch_to_bool, fatdb_switch_to_bool};
|
||||||
use io_handler::ImportIoHandler;
|
|
||||||
use helpers::{to_client_config, execute_upgrades};
|
use helpers::{to_client_config, execute_upgrades};
|
||||||
use dir::Directories;
|
use dir::Directories;
|
||||||
use user_defaults::UserDefaults;
|
use user_defaults::UserDefaults;
|
||||||
@ -134,7 +133,7 @@ pub struct ExportState {
|
|||||||
pub max_balance: Option<U256>,
|
pub max_balance: Option<U256>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(cmd: BlockchainCmd) -> Result<String, String> {
|
pub fn execute(cmd: BlockchainCmd) -> Result<(), String> {
|
||||||
match cmd {
|
match cmd {
|
||||||
BlockchainCmd::Kill(kill_cmd) => kill_db(kill_cmd),
|
BlockchainCmd::Kill(kill_cmd) => kill_db(kill_cmd),
|
||||||
BlockchainCmd::Import(import_cmd) => execute_import(import_cmd),
|
BlockchainCmd::Import(import_cmd) => execute_import(import_cmd),
|
||||||
@ -143,7 +142,7 @@ pub fn execute(cmd: BlockchainCmd) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
|
||||||
let timer = Instant::now();
|
let timer = Instant::now();
|
||||||
|
|
||||||
// Setup panic handler
|
// Setup panic handler
|
||||||
@ -180,7 +179,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
|||||||
let snapshot_path = db_dirs.snapshot_path();
|
let snapshot_path = db_dirs.snapshot_path();
|
||||||
|
|
||||||
// execute upgrades
|
// execute upgrades
|
||||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
try!(execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||||
|
|
||||||
// create dirs used by parity
|
// create dirs used by parity
|
||||||
try!(cmd.dirs.create_dirs(false, false));
|
try!(cmd.dirs.create_dirs(false, false));
|
||||||
@ -239,11 +238,8 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let informant = Informant::new(client.clone(), None, None, None, cmd.with_color);
|
let informant = Arc::new(Informant::new(client.clone(), None, None, None, cmd.with_color));
|
||||||
|
service.register_io_handler(informant).map_err(|_| "Unable to register informant handler".to_owned())?;
|
||||||
try!(service.register_io_handler(Arc::new(ImportIoHandler {
|
|
||||||
info: Arc::new(informant),
|
|
||||||
})).map_err(|_| "Unable to register informant handler".to_owned()));
|
|
||||||
|
|
||||||
let do_import = |bytes| {
|
let do_import = |bytes| {
|
||||||
while client.queue_info().is_full() { sleep(Duration::from_secs(1)); }
|
while client.queue_info().is_full() { sleep(Duration::from_secs(1)); }
|
||||||
@ -259,7 +255,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
match format {
|
match format {
|
||||||
DataFormat::Binary => {
|
DataFormat::Binary => {
|
||||||
loop {
|
loop {
|
||||||
@ -298,7 +293,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
|||||||
let report = client.report();
|
let report = client.report();
|
||||||
|
|
||||||
let ms = timer.elapsed().as_milliseconds();
|
let ms = timer.elapsed().as_milliseconds();
|
||||||
Ok(format!("Import completed in {} seconds, {} blocks, {} blk/s, {} transactions, {} tx/s, {} Mgas, {} Mgas/s",
|
info!("Import completed in {} seconds, {} blocks, {} blk/s, {} transactions, {} tx/s, {} Mgas, {} Mgas/s",
|
||||||
ms / 1000,
|
ms / 1000,
|
||||||
report.blocks_imported,
|
report.blocks_imported,
|
||||||
(report.blocks_imported * 1000) as u64 / ms,
|
(report.blocks_imported * 1000) as u64 / ms,
|
||||||
@ -306,7 +301,8 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
|||||||
(report.transactions_applied * 1000) as u64 / ms,
|
(report.transactions_applied * 1000) as u64 / ms,
|
||||||
report.gas_processed / From::from(1_000_000),
|
report.gas_processed / From::from(1_000_000),
|
||||||
(report.gas_processed / From::from(ms * 1000)).low_u64(),
|
(report.gas_processed / From::from(ms * 1000)).low_u64(),
|
||||||
).into())
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_client(
|
fn start_client(
|
||||||
@ -318,7 +314,8 @@ fn start_client(
|
|||||||
fat_db: Switch,
|
fat_db: Switch,
|
||||||
compaction: DatabaseCompactionProfile,
|
compaction: DatabaseCompactionProfile,
|
||||||
wal: bool,
|
wal: bool,
|
||||||
cache_config: CacheConfig) -> Result<ClientService, String> {
|
cache_config: CacheConfig
|
||||||
|
) -> Result<ClientService, String> {
|
||||||
|
|
||||||
// load spec file
|
// load spec file
|
||||||
let spec = try!(spec.spec());
|
let spec = try!(spec.spec());
|
||||||
@ -351,7 +348,7 @@ fn start_client(
|
|||||||
let snapshot_path = db_dirs.snapshot_path();
|
let snapshot_path = db_dirs.snapshot_path();
|
||||||
|
|
||||||
// execute upgrades
|
// execute upgrades
|
||||||
try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
try!(execute_upgrades(&dirs.base, &db_dirs, algorithm, compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||||
|
|
||||||
// create dirs used by parity
|
// create dirs used by parity
|
||||||
try!(dirs.create_dirs(false, false));
|
try!(dirs.create_dirs(false, false));
|
||||||
@ -372,7 +369,7 @@ fn start_client(
|
|||||||
Ok(service)
|
Ok(service)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
|
fn execute_export(cmd: ExportBlockchain) -> Result<(), String> {
|
||||||
// Setup panic handler
|
// Setup panic handler
|
||||||
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
|
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
@ -400,10 +397,11 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok("Export completed.".into())
|
info!("Export completed.");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_export_state(cmd: ExportState) -> Result<String, String> {
|
fn execute_export_state(cmd: ExportState) -> Result<(), String> {
|
||||||
// Setup panic handler
|
// Setup panic handler
|
||||||
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
|
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
@ -479,10 +477,11 @@ fn execute_export_state(cmd: ExportState) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.write_fmt(format_args!("\n]}}")).expect("Write error");
|
out.write_fmt(format_args!("\n]}}")).expect("Write error");
|
||||||
Ok("Export completed.".into())
|
info!("Export completed.");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill_db(cmd: KillBlockchain) -> Result<String, String> {
|
pub fn kill_db(cmd: KillBlockchain) -> Result<(), String> {
|
||||||
let spec = try!(cmd.spec.spec());
|
let spec = try!(cmd.spec.spec());
|
||||||
let genesis_hash = spec.genesis_header().hash();
|
let genesis_hash = spec.genesis_header().hash();
|
||||||
let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir);
|
let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir);
|
||||||
@ -491,7 +490,8 @@ pub fn kill_db(cmd: KillBlockchain) -> Result<String, String> {
|
|||||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||||
let dir = db_dirs.db_path(algorithm);
|
let dir = db_dirs.db_path(algorithm);
|
||||||
try!(fs::remove_dir_all(&dir).map_err(|e| format!("Error removing database: {:?}", e)));
|
try!(fs::remove_dir_all(&dir).map_err(|e| format!("Error removing database: {:?}", e)));
|
||||||
Ok("Database deleted.".to_owned())
|
info!("Database deleted.");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -2,8 +2,14 @@
|
|||||||
mode = "last"
|
mode = "last"
|
||||||
mode_timeout = 300
|
mode_timeout = 300
|
||||||
mode_alarm = 3600
|
mode_alarm = 3600
|
||||||
|
auto_update = "critical"
|
||||||
|
release_track = "current"
|
||||||
|
no_download = false
|
||||||
|
no_consensus = false
|
||||||
|
|
||||||
chain = "homestead"
|
chain = "homestead"
|
||||||
db_path = "$HOME/.parity"
|
base_path = "$HOME/.parity"
|
||||||
|
db_path = "$HOME/.parity/chains"
|
||||||
keys_path = "$HOME/.parity/keys"
|
keys_path = "$HOME/.parity/keys"
|
||||||
identity = ""
|
identity = ""
|
||||||
|
|
||||||
|
@ -85,9 +85,14 @@ usage! {
|
|||||||
flag_mode: String = "last", or |c: &Config| otry!(c.parity).mode.clone(),
|
flag_mode: String = "last", or |c: &Config| otry!(c.parity).mode.clone(),
|
||||||
flag_mode_timeout: u64 = 300u64, or |c: &Config| otry!(c.parity).mode_timeout.clone(),
|
flag_mode_timeout: u64 = 300u64, or |c: &Config| otry!(c.parity).mode_timeout.clone(),
|
||||||
flag_mode_alarm: u64 = 3600u64, or |c: &Config| otry!(c.parity).mode_alarm.clone(),
|
flag_mode_alarm: u64 = 3600u64, or |c: &Config| otry!(c.parity).mode_alarm.clone(),
|
||||||
|
flag_auto_update: String = "critical", or |c: &Config| otry!(c.parity).auto_update.clone(),
|
||||||
|
flag_release_track: String = "current", or |c: &Config| otry!(c.parity).release_track.clone(),
|
||||||
|
flag_no_download: bool = false, or |c: &Config| otry!(c.parity).no_download.clone(),
|
||||||
|
flag_no_consensus: bool = false, or |c: &Config| otry!(c.parity).no_consensus.clone(),
|
||||||
flag_chain: String = "homestead", or |c: &Config| otry!(c.parity).chain.clone(),
|
flag_chain: String = "homestead", or |c: &Config| otry!(c.parity).chain.clone(),
|
||||||
flag_db_path: String = default_data_path(), or |c: &Config| otry!(c.parity).db_path.clone(),
|
flag_base_path: String = default_data_path(), or |c: &Config| otry!(c.parity).base_path.clone(),
|
||||||
flag_keys_path: String = "$DATA/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
|
flag_db_path: String = "$BASE/chains", or |c: &Config| otry!(c.parity).db_path.clone(),
|
||||||
|
flag_keys_path: String = "$BASE/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
|
||||||
flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(),
|
flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(),
|
||||||
|
|
||||||
// -- Account Options
|
// -- Account Options
|
||||||
@ -106,7 +111,7 @@ usage! {
|
|||||||
or |c: &Config| otry!(c.ui).port.clone(),
|
or |c: &Config| otry!(c.ui).port.clone(),
|
||||||
flag_ui_interface: String = "local",
|
flag_ui_interface: String = "local",
|
||||||
or |c: &Config| otry!(c.ui).interface.clone(),
|
or |c: &Config| otry!(c.ui).interface.clone(),
|
||||||
flag_ui_path: String = "$DATA/signer",
|
flag_ui_path: String = "$BASE/signer",
|
||||||
or |c: &Config| otry!(c.ui).path.clone(),
|
or |c: &Config| otry!(c.ui).path.clone(),
|
||||||
// NOTE [todr] For security reasons don't put this to config files
|
// NOTE [todr] For security reasons don't put this to config files
|
||||||
flag_ui_no_validation: bool = false, or |_| None,
|
flag_ui_no_validation: bool = false, or |_| None,
|
||||||
@ -162,7 +167,7 @@ usage! {
|
|||||||
// IPC
|
// IPC
|
||||||
flag_no_ipc: bool = false,
|
flag_no_ipc: bool = false,
|
||||||
or |c: &Config| otry!(c.ipc).disable.clone(),
|
or |c: &Config| otry!(c.ipc).disable.clone(),
|
||||||
flag_ipc_path: String = "$DATA/jsonrpc.ipc",
|
flag_ipc_path: String = "$BASE/jsonrpc.ipc",
|
||||||
or |c: &Config| otry!(c.ipc).path.clone(),
|
or |c: &Config| otry!(c.ipc).path.clone(),
|
||||||
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
|
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
|
||||||
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
|
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
|
||||||
@ -176,7 +181,7 @@ usage! {
|
|||||||
or |c: &Config| otry!(c.dapps).interface.clone(),
|
or |c: &Config| otry!(c.dapps).interface.clone(),
|
||||||
flag_dapps_hosts: String = "none",
|
flag_dapps_hosts: String = "none",
|
||||||
or |c: &Config| otry!(c.dapps).hosts.clone().map(|vec| vec.join(",")),
|
or |c: &Config| otry!(c.dapps).hosts.clone().map(|vec| vec.join(",")),
|
||||||
flag_dapps_path: String = "$DATA/dapps",
|
flag_dapps_path: String = "$BASE/dapps",
|
||||||
or |c: &Config| otry!(c.dapps).path.clone(),
|
or |c: &Config| otry!(c.dapps).path.clone(),
|
||||||
flag_dapps_user: Option<String> = None,
|
flag_dapps_user: Option<String> = None,
|
||||||
or |c: &Config| otry!(c.dapps).user.clone().map(Some),
|
or |c: &Config| otry!(c.dapps).user.clone().map(Some),
|
||||||
@ -277,7 +282,7 @@ usage! {
|
|||||||
or |c: &Config| otry!(c.vm).jit.clone(),
|
or |c: &Config| otry!(c.vm).jit.clone(),
|
||||||
|
|
||||||
// -- Miscellaneous Options
|
// -- Miscellaneous Options
|
||||||
flag_config: String = "$DATA/config.toml", or |_| None,
|
flag_config: String = "$BASE/config.toml", or |_| None,
|
||||||
flag_logging: Option<String> = None,
|
flag_logging: Option<String> = None,
|
||||||
or |c: &Config| otry!(c.misc).logging.clone().map(Some),
|
or |c: &Config| otry!(c.misc).logging.clone().map(Some),
|
||||||
flag_log_file: Option<String> = None,
|
flag_log_file: Option<String> = None,
|
||||||
@ -309,7 +314,12 @@ struct Operating {
|
|||||||
mode: Option<String>,
|
mode: Option<String>,
|
||||||
mode_timeout: Option<u64>,
|
mode_timeout: Option<u64>,
|
||||||
mode_alarm: Option<u64>,
|
mode_alarm: Option<u64>,
|
||||||
|
auto_update: Option<String>,
|
||||||
|
release_track: Option<String>,
|
||||||
|
no_download: Option<bool>,
|
||||||
|
no_consensus: Option<bool>,
|
||||||
chain: Option<String>,
|
chain: Option<String>,
|
||||||
|
base_path: Option<String>,
|
||||||
db_path: Option<String>,
|
db_path: Option<String>,
|
||||||
keys_path: Option<String>,
|
keys_path: Option<String>,
|
||||||
identity: Option<String>,
|
identity: Option<String>,
|
||||||
@ -533,8 +543,13 @@ mod tests {
|
|||||||
flag_mode: "last".into(),
|
flag_mode: "last".into(),
|
||||||
flag_mode_timeout: 300u64,
|
flag_mode_timeout: 300u64,
|
||||||
flag_mode_alarm: 3600u64,
|
flag_mode_alarm: 3600u64,
|
||||||
|
flag_auto_update: "critical".into(),
|
||||||
|
flag_release_track: "current".into(),
|
||||||
|
flag_no_download: false,
|
||||||
|
flag_no_consensus: false,
|
||||||
flag_chain: "xyz".into(),
|
flag_chain: "xyz".into(),
|
||||||
flag_db_path: "$HOME/.parity".into(),
|
flag_base_path: "$HOME/.parity".into(),
|
||||||
|
flag_db_path: "$HOME/.parity/chains".into(),
|
||||||
flag_keys_path: "$HOME/.parity/keys".into(),
|
flag_keys_path: "$HOME/.parity/keys".into(),
|
||||||
flag_identity: "".into(),
|
flag_identity: "".into(),
|
||||||
|
|
||||||
@ -676,7 +691,7 @@ mod tests {
|
|||||||
|
|
||||||
// -- Miscellaneous Options
|
// -- Miscellaneous Options
|
||||||
flag_version: false,
|
flag_version: false,
|
||||||
flag_config: "$DATA/config.toml".into(),
|
flag_config: "$BASE/config.toml".into(),
|
||||||
flag_logging: Some("own_tx=trace".into()),
|
flag_logging: Some("own_tx=trace".into()),
|
||||||
flag_log_file: Some("/var/log/parity.log".into()),
|
flag_log_file: Some("/var/log/parity.log".into()),
|
||||||
flag_no_color: false,
|
flag_no_color: false,
|
||||||
@ -707,7 +722,12 @@ mod tests {
|
|||||||
mode: Some("dark".into()),
|
mode: Some("dark".into()),
|
||||||
mode_timeout: Some(15u64),
|
mode_timeout: Some(15u64),
|
||||||
mode_alarm: Some(10u64),
|
mode_alarm: Some(10u64),
|
||||||
|
auto_update: None,
|
||||||
|
release_track: None,
|
||||||
|
no_download: None,
|
||||||
|
no_consensus: None,
|
||||||
chain: Some("./chain.json".into()),
|
chain: Some("./chain.json".into()),
|
||||||
|
base_path: None,
|
||||||
db_path: None,
|
db_path: None,
|
||||||
keys_path: None,
|
keys_path: None,
|
||||||
identity: None,
|
identity: None,
|
||||||
|
@ -34,11 +34,34 @@ Operating Options:
|
|||||||
--mode-alarm SECS Specify the number of seconds before auto sleep
|
--mode-alarm SECS Specify the number of seconds before auto sleep
|
||||||
reawake timeout occurs when mode is passive
|
reawake timeout occurs when mode is passive
|
||||||
(default: {flag_mode_alarm}).
|
(default: {flag_mode_alarm}).
|
||||||
|
--auto-update SET Set a releases set to automatically update and
|
||||||
|
install.
|
||||||
|
all - All updates in the our release track.
|
||||||
|
critical - Only consensus/security updates.
|
||||||
|
none - No updates will be auto-installed.
|
||||||
|
(default: {flag_auto_update}).
|
||||||
|
--release-track TRACK Set which release track we should use for updates.
|
||||||
|
stable - Stable releases.
|
||||||
|
beta - Beta releases.
|
||||||
|
nightly - Nightly releases (unstable).
|
||||||
|
testing - Testing releases (do not use).
|
||||||
|
current - Whatever track this executable was
|
||||||
|
released on (default: {flag_release_track}).
|
||||||
|
--no-download Normally new releases will be downloaded ready for
|
||||||
|
updating. This disables it. Not recommended.
|
||||||
|
(default: {flag_no_download}).
|
||||||
|
--no-consensus Force the binary to run even if there are known
|
||||||
|
issues regarding consensus. Not recommended.
|
||||||
|
(default: {flag_no_consensus}).
|
||||||
|
--force-direct Run the originally installed version of Parity,
|
||||||
|
ignoring any updates that have since been installed.
|
||||||
--chain CHAIN Specify the blockchain type. CHAIN may be either a
|
--chain CHAIN Specify the blockchain type. CHAIN may be either a
|
||||||
JSON chain specification file or olympic, frontier,
|
JSON chain specification file or olympic, frontier,
|
||||||
homestead, mainnet, morden, ropsten, classic, expanse,
|
homestead, mainnet, morden, ropsten, classic, expanse,
|
||||||
testnet or dev (default: {flag_chain}).
|
testnet or dev (default: {flag_chain}).
|
||||||
-d --db-path PATH Specify the database & configuration directory path
|
-d --base-path PATH Specify the base data storage path.
|
||||||
|
(default: {flag_base_path}).
|
||||||
|
--db-path PATH Specify the database directory path
|
||||||
(default: {flag_db_path}).
|
(default: {flag_db_path}).
|
||||||
--keys-path PATH Specify the path for JSON key files to be found
|
--keys-path PATH Specify the path for JSON key files to be found
|
||||||
(default: {flag_keys_path}).
|
(default: {flag_keys_path}).
|
||||||
@ -339,6 +362,9 @@ Legacy Options:
|
|||||||
--extradata STRING Equivalent to --extra-data STRING.
|
--extradata STRING Equivalent to --extra-data STRING.
|
||||||
--cache MB Equivalent to --cache-size MB.
|
--cache MB Equivalent to --cache-size MB.
|
||||||
|
|
||||||
|
Internal Options:
|
||||||
|
--can-restart Executable will auto-restart if exiting with 69.
|
||||||
|
|
||||||
Miscellaneous Options:
|
Miscellaneous Options:
|
||||||
-c --config CONFIG Specify a filename containing a configuration file.
|
-c --config CONFIG Specify a filename containing a configuration file.
|
||||||
(default: {flag_config})
|
(default: {flag_config})
|
||||||
|
@ -23,7 +23,7 @@ use cli::{Args, ArgsError};
|
|||||||
use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address};
|
use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address};
|
||||||
use util::log::Colour;
|
use util::log::Colour;
|
||||||
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
|
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
|
||||||
use ethcore::client::VMType;
|
use ethcore::client::{VMType};
|
||||||
use ethcore::miner::{MinerOptions, Banning};
|
use ethcore::miner::{MinerOptions, Banning};
|
||||||
use ethcore::verification::queue::VerifierSettings;
|
use ethcore::verification::queue::VerifierSettings;
|
||||||
|
|
||||||
@ -34,9 +34,10 @@ use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_pri
|
|||||||
geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit, to_queue_strategy};
|
geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit, to_queue_strategy};
|
||||||
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras};
|
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras};
|
||||||
use ethcore_logger::Config as LogConfig;
|
use ethcore_logger::Config as LogConfig;
|
||||||
use dir::Directories;
|
use dir::{Directories, default_hypervisor_path};
|
||||||
use dapps::Configuration as DappsConfiguration;
|
use dapps::Configuration as DappsConfiguration;
|
||||||
use signer::{Configuration as SignerConfiguration};
|
use signer::{Configuration as SignerConfiguration};
|
||||||
|
use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack};
|
||||||
use run::RunCmd;
|
use run::RunCmd;
|
||||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat};
|
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat};
|
||||||
use presale::ImportWallet;
|
use presale::ImportWallet;
|
||||||
@ -99,6 +100,7 @@ impl Configuration {
|
|||||||
let pruning_history = self.args.flag_pruning_history;
|
let pruning_history = self.args.flag_pruning_history;
|
||||||
let vm_type = try!(self.vm_type());
|
let vm_type = try!(self.vm_type());
|
||||||
let mode = match self.args.flag_mode.as_ref() { "last" => None, mode => Some(try!(to_mode(&mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm))), };
|
let mode = match self.args.flag_mode.as_ref() { "last" => None, mode => Some(try!(to_mode(&mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm))), };
|
||||||
|
let update_policy = try!(self.update_policy());
|
||||||
let miner_options = try!(self.miner_options());
|
let miner_options = try!(self.miner_options());
|
||||||
let logger_config = self.logger_config();
|
let logger_config = self.logger_config();
|
||||||
let http_conf = try!(self.http_config());
|
let http_conf = try!(self.http_config());
|
||||||
@ -320,6 +322,7 @@ impl Configuration {
|
|||||||
acc_conf: try!(self.accounts_config()),
|
acc_conf: try!(self.accounts_config()),
|
||||||
gas_pricer: try!(self.gas_pricer_config()),
|
gas_pricer: try!(self.gas_pricer_config()),
|
||||||
miner_extras: try!(self.miner_extras()),
|
miner_extras: try!(self.miner_extras()),
|
||||||
|
update_policy: update_policy,
|
||||||
mode: mode,
|
mode: mode,
|
||||||
tracing: tracing,
|
tracing: tracing,
|
||||||
fat_db: fat_db,
|
fat_db: fat_db,
|
||||||
@ -589,7 +592,7 @@ impl Configuration {
|
|||||||
ret.snapshot_peers = self.snapshot_peers();
|
ret.snapshot_peers = self.snapshot_peers();
|
||||||
ret.allow_ips = try!(self.allow_ips());
|
ret.allow_ips = try!(self.allow_ips());
|
||||||
ret.max_pending_peers = self.max_pending_peers();
|
ret.max_pending_peers = self.max_pending_peers();
|
||||||
let mut net_path = PathBuf::from(self.directories().data);
|
let mut net_path = PathBuf::from(self.directories().base);
|
||||||
net_path.push("network");
|
net_path.push("network");
|
||||||
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
|
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
|
||||||
ret.reserved_nodes = try!(self.init_reserved_nodes());
|
ret.reserved_nodes = try!(self.init_reserved_nodes());
|
||||||
@ -680,11 +683,34 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_policy(&self) -> Result<UpdatePolicy, String> {
|
||||||
|
Ok(UpdatePolicy {
|
||||||
|
enable_downloading: !self.args.flag_no_download,
|
||||||
|
require_consensus: !self.args.flag_no_consensus,
|
||||||
|
filter: match self.args.flag_auto_update.as_ref() {
|
||||||
|
"none" => UpdateFilter::None,
|
||||||
|
"critical" => UpdateFilter::Critical,
|
||||||
|
"all" => UpdateFilter::All,
|
||||||
|
_ => return Err("Invalid value for `--auto-update`. See `--help` for more information.".into()),
|
||||||
|
},
|
||||||
|
track: match self.args.flag_release_track.as_ref() {
|
||||||
|
"stable" => ReleaseTrack::Stable,
|
||||||
|
"beta" => ReleaseTrack::Beta,
|
||||||
|
"nightly" => ReleaseTrack::Nightly,
|
||||||
|
"testing" => ReleaseTrack::Testing,
|
||||||
|
"current" => ReleaseTrack::Unknown,
|
||||||
|
_ => return Err("Invalid value for `--releases-track`. See `--help` for more information.".into()),
|
||||||
|
},
|
||||||
|
path: default_hypervisor_path(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn directories(&self) -> Directories {
|
fn directories(&self) -> Directories {
|
||||||
use util::path;
|
use util::path;
|
||||||
|
|
||||||
let data_path = replace_home("", self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path));
|
let data_path = replace_home("", self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_base_path));
|
||||||
|
|
||||||
|
let db_path = replace_home(&data_path, &self.args.flag_db_path);
|
||||||
let keys_path = replace_home(&data_path, &self.args.flag_keys_path);
|
let keys_path = replace_home(&data_path, &self.args.flag_keys_path);
|
||||||
let dapps_path = replace_home(&data_path, &self.args.flag_dapps_path);
|
let dapps_path = replace_home(&data_path, &self.args.flag_dapps_path);
|
||||||
let ui_path = replace_home(&data_path, &self.args.flag_ui_path);
|
let ui_path = replace_home(&data_path, &self.args.flag_ui_path);
|
||||||
@ -706,7 +732,8 @@ impl Configuration {
|
|||||||
|
|
||||||
Directories {
|
Directories {
|
||||||
keys: keys_path,
|
keys: keys_path,
|
||||||
data: data_path,
|
base: data_path,
|
||||||
|
db: db_path,
|
||||||
dapps: dapps_path,
|
dapps: dapps_path,
|
||||||
signer: ui_path,
|
signer: ui_path,
|
||||||
}
|
}
|
||||||
@ -716,7 +743,7 @@ impl Configuration {
|
|||||||
if self.args.flag_geth {
|
if self.args.flag_geth {
|
||||||
geth_ipc_path(self.args.flag_testnet)
|
geth_ipc_path(self.args.flag_testnet)
|
||||||
} else {
|
} else {
|
||||||
parity_ipc_path(&self.directories().data, &self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone()))
|
parity_ipc_path(&self.directories().base, &self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,13 +813,14 @@ mod tests {
|
|||||||
use ethcore::miner::{MinerOptions, PrioritizationStrategy};
|
use ethcore::miner::{MinerOptions, PrioritizationStrategy};
|
||||||
use helpers::{default_network_config};
|
use helpers::{default_network_config};
|
||||||
use run::RunCmd;
|
use run::RunCmd;
|
||||||
use dir::Directories;
|
use dir::{Directories, default_hypervisor_path};
|
||||||
use signer::{Configuration as SignerConfiguration};
|
use signer::{Configuration as SignerConfiguration};
|
||||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat, ExportState};
|
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat, ExportState};
|
||||||
use presale::ImportWallet;
|
use presale::ImportWallet;
|
||||||
use params::SpecType;
|
use params::SpecType;
|
||||||
use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts};
|
use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts};
|
||||||
use devtools::{RandomTempPath};
|
use devtools::{RandomTempPath};
|
||||||
|
use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::fs::{File, create_dir};
|
use std::fs::{File, create_dir};
|
||||||
|
|
||||||
@ -986,6 +1014,7 @@ mod tests {
|
|||||||
acc_conf: Default::default(),
|
acc_conf: Default::default(),
|
||||||
gas_pricer: Default::default(),
|
gas_pricer: Default::default(),
|
||||||
miner_extras: Default::default(),
|
miner_extras: Default::default(),
|
||||||
|
update_policy: UpdatePolicy { enable_downloading: true, require_consensus: true, filter: UpdateFilter::Critical, track: ReleaseTrack::Unknown, path: default_hypervisor_path() },
|
||||||
mode: Default::default(),
|
mode: Default::default(),
|
||||||
tracing: Default::default(),
|
tracing: Default::default(),
|
||||||
compaction: Default::default(),
|
compaction: Default::default(),
|
||||||
@ -1029,6 +1058,21 @@ mod tests {
|
|||||||
assert_eq!(conf3.miner_options().unwrap(), mining_options);
|
assert_eq!(conf3.miner_options().unwrap(), mining_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_updater_options() {
|
||||||
|
// when
|
||||||
|
let conf0 = parse(&["parity", "--release-track=testing"]);
|
||||||
|
let conf1 = parse(&["parity", "--auto-update", "all", "--no-consensus"]);
|
||||||
|
let conf2 = parse(&["parity", "--no-download", "--auto-update=all", "--release-track=beta"]);
|
||||||
|
let conf3 = parse(&["parity", "--auto-update=xxx"]);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(conf0.update_policy().unwrap(), UpdatePolicy{enable_downloading: true, require_consensus: true, filter: UpdateFilter::Critical, track: ReleaseTrack::Testing, path: default_hypervisor_path()});
|
||||||
|
assert_eq!(conf1.update_policy().unwrap(), UpdatePolicy{enable_downloading: true, require_consensus: false, filter: UpdateFilter::All, track: ReleaseTrack::Unknown, path: default_hypervisor_path()});
|
||||||
|
assert_eq!(conf2.update_policy().unwrap(), UpdatePolicy{enable_downloading: false, require_consensus: true, filter: UpdateFilter::All, track: ReleaseTrack::Beta, path: default_hypervisor_path()});
|
||||||
|
assert!(conf3.update_policy().is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_parse_network_settings() {
|
fn should_parse_network_settings() {
|
||||||
// given
|
// given
|
||||||
|
@ -43,7 +43,7 @@ impl Default for Configuration {
|
|||||||
hosts: Some(Vec::new()),
|
hosts: Some(Vec::new()),
|
||||||
user: None,
|
user: None,
|
||||||
pass: None,
|
pass: None,
|
||||||
dapps_path: replace_home(&data_dir, "$DATA/dapps"),
|
dapps_path: replace_home(&data_dir, "$BASE/dapps"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ const LEGACY_CLIENT_DB_VER_STR: &'static str = "5.3";
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Directories {
|
pub struct Directories {
|
||||||
pub data: String,
|
pub base: String,
|
||||||
|
pub db: String,
|
||||||
pub keys: String,
|
pub keys: String,
|
||||||
pub signer: String,
|
pub signer: String,
|
||||||
pub dapps: String,
|
pub dapps: String,
|
||||||
@ -37,17 +38,19 @@ impl Default for Directories {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let data_dir = default_data_path();
|
let data_dir = default_data_path();
|
||||||
Directories {
|
Directories {
|
||||||
data: replace_home(&data_dir, "$DATA"),
|
base: replace_home(&data_dir, "$BASE"),
|
||||||
keys: replace_home(&data_dir, "$DATA/keys"),
|
db: replace_home(&data_dir, "$BASE/chains"),
|
||||||
signer: replace_home(&data_dir, "$DATA/signer"),
|
keys: replace_home(&data_dir, "$BASE/keys"),
|
||||||
dapps: replace_home(&data_dir, "$DATA/dapps"),
|
signer: replace_home(&data_dir, "$BASE/signer"),
|
||||||
|
dapps: replace_home(&data_dir, "$BASE/dapps"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Directories {
|
impl Directories {
|
||||||
pub fn create_dirs(&self, dapps_enabled: bool, signer_enabled: bool) -> Result<(), String> {
|
pub fn create_dirs(&self, dapps_enabled: bool, signer_enabled: bool) -> Result<(), String> {
|
||||||
try!(fs::create_dir_all(&self.data).map_err(|e| e.to_string()));
|
try!(fs::create_dir_all(&self.base).map_err(|e| e.to_string()));
|
||||||
|
try!(fs::create_dir_all(&self.db).map_err(|e| e.to_string()));
|
||||||
try!(fs::create_dir_all(&self.keys).map_err(|e| e.to_string()));
|
try!(fs::create_dir_all(&self.keys).map_err(|e| e.to_string()));
|
||||||
if signer_enabled {
|
if signer_enabled {
|
||||||
try!(fs::create_dir_all(&self.signer).map_err(|e| e.to_string()));
|
try!(fs::create_dir_all(&self.signer).map_err(|e| e.to_string()));
|
||||||
@ -61,7 +64,8 @@ impl Directories {
|
|||||||
/// Database paths.
|
/// Database paths.
|
||||||
pub fn database(&self, genesis_hash: H256, fork_name: Option<String>, spec_name: String) -> DatabaseDirectories {
|
pub fn database(&self, genesis_hash: H256, fork_name: Option<String>, spec_name: String) -> DatabaseDirectories {
|
||||||
DatabaseDirectories {
|
DatabaseDirectories {
|
||||||
path: self.data.clone(),
|
path: self.db.clone(),
|
||||||
|
legacy_path: self.base.clone(),
|
||||||
genesis_hash: genesis_hash,
|
genesis_hash: genesis_hash,
|
||||||
fork_name: fork_name,
|
fork_name: fork_name,
|
||||||
spec_name: spec_name,
|
spec_name: spec_name,
|
||||||
@ -70,14 +74,14 @@ impl Directories {
|
|||||||
|
|
||||||
/// Get the ipc sockets path
|
/// Get the ipc sockets path
|
||||||
pub fn ipc_path(&self) -> PathBuf {
|
pub fn ipc_path(&self) -> PathBuf {
|
||||||
let mut dir = Path::new(&self.data).to_path_buf();
|
let mut dir = Path::new(&self.base).to_path_buf();
|
||||||
dir.push("ipc");
|
dir.push("ipc");
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove in 1.7
|
// TODO: remove in 1.7
|
||||||
pub fn legacy_keys_path(&self, testnet: bool) -> PathBuf {
|
pub fn legacy_keys_path(&self, testnet: bool) -> PathBuf {
|
||||||
let mut dir = Path::new(&self.data).to_path_buf();
|
let mut dir = Path::new(&self.base).to_path_buf();
|
||||||
if testnet {
|
if testnet {
|
||||||
dir.push("testnet_keys");
|
dir.push("testnet_keys");
|
||||||
} else {
|
} else {
|
||||||
@ -96,6 +100,7 @@ impl Directories {
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct DatabaseDirectories {
|
pub struct DatabaseDirectories {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
pub legacy_path: String,
|
||||||
pub genesis_hash: H256,
|
pub genesis_hash: H256,
|
||||||
pub fork_name: Option<String>,
|
pub fork_name: Option<String>,
|
||||||
pub spec_name: String,
|
pub spec_name: String,
|
||||||
@ -105,14 +110,13 @@ impl DatabaseDirectories {
|
|||||||
/// Base DB directory for the given fork.
|
/// Base DB directory for the given fork.
|
||||||
// TODO: remove in 1.7
|
// TODO: remove in 1.7
|
||||||
pub fn legacy_fork_path(&self) -> PathBuf {
|
pub fn legacy_fork_path(&self) -> PathBuf {
|
||||||
let mut dir = Path::new(&self.path).to_path_buf();
|
let mut dir = Path::new(&self.legacy_path).to_path_buf();
|
||||||
dir.push(format!("{:?}{}", H64::from(self.genesis_hash), self.fork_name.as_ref().map(|f| format!("-{}", f)).unwrap_or_default()));
|
dir.push(format!("{:?}{}", H64::from(self.genesis_hash), self.fork_name.as_ref().map(|f| format!("-{}", f)).unwrap_or_default()));
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spec_root_path(&self) -> PathBuf {
|
pub fn spec_root_path(&self) -> PathBuf {
|
||||||
let mut dir = Path::new(&self.path).to_path_buf();
|
let mut dir = Path::new(&self.path).to_path_buf();
|
||||||
dir.push("chains");
|
|
||||||
dir.push(&self.spec_name);
|
dir.push(&self.spec_name);
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
@ -195,6 +199,11 @@ pub fn default_data_path() -> String {
|
|||||||
get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity".to_owned())
|
get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_hypervisor_path() -> String {
|
||||||
|
let app_info = AppInfo { name: "parity-hypervisor", author: "parity" };
|
||||||
|
get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity-hypervisor".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Directories;
|
use super::Directories;
|
||||||
@ -204,10 +213,11 @@ mod tests {
|
|||||||
fn test_default_directories() {
|
fn test_default_directories() {
|
||||||
let data_dir = super::default_data_path();
|
let data_dir = super::default_data_path();
|
||||||
let expected = Directories {
|
let expected = Directories {
|
||||||
data: replace_home(&data_dir, "$DATA"),
|
base: replace_home(&data_dir, "$BASE"),
|
||||||
keys: replace_home(&data_dir, "$DATA/keys"),
|
db: replace_home(&data_dir, "$BASE/chains"),
|
||||||
signer: replace_home(&data_dir, "$DATA/signer"),
|
keys: replace_home(&data_dir, "$BASE/keys"),
|
||||||
dapps: replace_home(&data_dir, "$DATA/dapps"),
|
signer: replace_home(&data_dir, "$BASE/signer"),
|
||||||
|
dapps: replace_home(&data_dir, "$BASE/dapps"),
|
||||||
};
|
};
|
||||||
assert_eq!(expected, Directories::default());
|
assert_eq!(expected, Directories::default());
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ pub fn to_price(s: &str) -> Result<f32, String> {
|
|||||||
pub fn replace_home(base: &str, arg: &str) -> String {
|
pub fn replace_home(base: &str, arg: &str) -> String {
|
||||||
// the $HOME directory on mac os should be `~/Library` or `~/Library/Application Support`
|
// the $HOME directory on mac os should be `~/Library` or `~/Library/Application Support`
|
||||||
let r = arg.replace("$HOME", env::home_dir().unwrap().to_str().unwrap());
|
let r = arg.replace("$HOME", env::home_dir().unwrap().to_str().unwrap());
|
||||||
let r = r.replace("$DATA", base );
|
let r = r.replace("$BASE", base );
|
||||||
r.replace("/", &::std::path::MAIN_SEPARATOR.to_string() )
|
r.replace("/", &::std::path::MAIN_SEPARATOR.to_string() )
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ pub fn to_bootnodes(bootnodes: &Option<String>) -> Result<Vec<String>, String> {
|
|||||||
pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
||||||
use ethsync::{NetworkConfiguration, AllowIP};
|
use ethsync::{NetworkConfiguration, AllowIP};
|
||||||
NetworkConfiguration {
|
NetworkConfiguration {
|
||||||
config_path: Some(replace_home(&::dir::default_data_path(), "$DATA/network")),
|
config_path: Some(replace_home(&::dir::default_data_path(), "$BASE/network")),
|
||||||
net_config_path: None,
|
net_config_path: None,
|
||||||
listen_address: Some("0.0.0.0:30303".into()),
|
listen_address: Some("0.0.0.0:30303".into()),
|
||||||
public_address: None,
|
public_address: None,
|
||||||
@ -257,12 +257,13 @@ pub fn to_client_config(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_upgrades(
|
pub fn execute_upgrades(
|
||||||
|
base_path: &str,
|
||||||
dirs: &DatabaseDirectories,
|
dirs: &DatabaseDirectories,
|
||||||
pruning: Algorithm,
|
pruning: Algorithm,
|
||||||
compaction_profile: CompactionProfile
|
compaction_profile: CompactionProfile
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
|
|
||||||
upgrade_data_paths(dirs, pruning);
|
upgrade_data_paths(base_path, dirs, pruning);
|
||||||
|
|
||||||
match upgrade(Some(&dirs.path)) {
|
match upgrade(Some(&dirs.path)) {
|
||||||
Ok(upgrades_applied) if upgrades_applied > 0 => {
|
Ok(upgrades_applied) if upgrades_applied > 0 => {
|
||||||
|
@ -19,12 +19,14 @@ use self::ansi_term::Colour::{White, Yellow, Green, Cyan, Blue};
|
|||||||
use self::ansi_term::Style;
|
use self::ansi_term::Style;
|
||||||
|
|
||||||
use std::sync::{Arc};
|
use std::sync::{Arc};
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
|
use io::{TimerToken, IoContext, IoHandler};
|
||||||
use isatty::{stdout_isatty};
|
use isatty::{stdout_isatty};
|
||||||
use ethsync::{SyncProvider, ManageNetwork};
|
use ethsync::{SyncProvider, ManageNetwork};
|
||||||
use util::{Uint, RwLock, Mutex, H256, Colour, Bytes};
|
use util::{Uint, RwLock, Mutex, H256, Colour, Bytes};
|
||||||
use ethcore::client::*;
|
use ethcore::client::*;
|
||||||
|
use ethcore::service::ClientIoMessage;
|
||||||
use ethcore::views::BlockView;
|
use ethcore::views::BlockView;
|
||||||
use ethcore::snapshot::service::Service as SnapshotService;
|
use ethcore::snapshot::service::Service as SnapshotService;
|
||||||
use ethcore::snapshot::{RestorationStatus, SnapshotService as SS};
|
use ethcore::snapshot::{RestorationStatus, SnapshotService as SS};
|
||||||
@ -44,6 +46,7 @@ pub struct Informant {
|
|||||||
last_import: Mutex<Instant>,
|
last_import: Mutex<Instant>,
|
||||||
skipped: AtomicUsize,
|
skipped: AtomicUsize,
|
||||||
skipped_txs: AtomicUsize,
|
skipped_txs: AtomicUsize,
|
||||||
|
in_shutdown: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format byte counts to standard denominations.
|
/// Format byte counts to standard denominations.
|
||||||
@ -82,9 +85,14 @@ impl Informant {
|
|||||||
last_import: Mutex::new(Instant::now()),
|
last_import: Mutex::new(Instant::now()),
|
||||||
skipped: AtomicUsize::new(0),
|
skipped: AtomicUsize::new(0),
|
||||||
skipped_txs: AtomicUsize::new(0),
|
skipped_txs: AtomicUsize::new(0),
|
||||||
|
in_shutdown: AtomicBool::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Signal that we're shutting down; no more output necessary.
|
||||||
|
pub fn shutdown(&self) {
|
||||||
|
self.in_shutdown.store(true, ::std::sync::atomic::Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(match_bool))]
|
#[cfg_attr(feature="dev", allow(match_bool))]
|
||||||
pub fn tick(&self) {
|
pub fn tick(&self) {
|
||||||
@ -221,3 +229,16 @@ impl ChainNotify for Informant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const INFO_TIMER: TimerToken = 0;
|
||||||
|
|
||||||
|
impl IoHandler<ClientIoMessage> for Informant {
|
||||||
|
fn initialize(&self, io: &IoContext<ClientIoMessage>) {
|
||||||
|
io.register_timer(INFO_TIMER, 5000).expect("Error registering timer");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn timeout(&self, _io: &IoContext<ClientIoMessage>, timer: TimerToken) {
|
||||||
|
if timer == INFO_TIMER && !self.in_shutdown.load(AtomicOrdering::SeqCst) {
|
||||||
|
self.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use ethcore::client::Client;
|
|
||||||
use ethcore::service::ClientIoMessage;
|
|
||||||
use ethsync::{SyncProvider, ManageNetwork};
|
|
||||||
use ethcore::account_provider::AccountProvider;
|
|
||||||
use io::{TimerToken, IoHandler, IoContext};
|
|
||||||
|
|
||||||
use informant::Informant;
|
|
||||||
|
|
||||||
const INFO_TIMER: TimerToken = 0;
|
|
||||||
|
|
||||||
pub struct ClientIoHandler {
|
|
||||||
pub client: Arc<Client>,
|
|
||||||
pub sync: Arc<SyncProvider>,
|
|
||||||
pub net: Arc<ManageNetwork>,
|
|
||||||
pub accounts: Arc<AccountProvider>,
|
|
||||||
pub info: Arc<Informant>,
|
|
||||||
pub shutdown: Arc<AtomicBool>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IoHandler<ClientIoMessage> for ClientIoHandler {
|
|
||||||
fn initialize(&self, io: &IoContext<ClientIoMessage>) {
|
|
||||||
io.register_timer(INFO_TIMER, 5000).expect("Error registering timer");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn timeout(&self, _io: &IoContext<ClientIoMessage>, timer: TimerToken) {
|
|
||||||
if timer == INFO_TIMER && !self.shutdown.load(Ordering::SeqCst) {
|
|
||||||
self.info.tick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ImportIoHandler {
|
|
||||||
pub info: Arc<Informant>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IoHandler<ClientIoMessage> for ImportIoHandler {
|
|
||||||
fn initialize(&self, io: &IoContext<ClientIoMessage>) {
|
|
||||||
io.register_timer(INFO_TIMER, 5000).expect("Error registering timer");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn timeout(&self, _io: &IoContext<ClientIoMessage>, timer: TimerToken) {
|
|
||||||
if let INFO_TIMER = timer {
|
|
||||||
self.info.tick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
183
parity/main.rs
183
parity/main.rs
@ -42,13 +42,14 @@ extern crate ethcore_ipc_nano as nanoipc;
|
|||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate ethcore_hash_fetch as hash_fetch;
|
|
||||||
extern crate ethcore_light as light;
|
extern crate ethcore_light as light;
|
||||||
|
extern crate parity_hash_fetch as hash_fetch;
|
||||||
|
|
||||||
extern crate ethcore_ipc_hypervisor as hypervisor;
|
extern crate ethcore_ipc_hypervisor as hypervisor;
|
||||||
extern crate ethcore_rpc;
|
extern crate ethcore_rpc;
|
||||||
|
|
||||||
extern crate ethcore_signer;
|
extern crate ethcore_signer;
|
||||||
|
extern crate parity_updater as updater;
|
||||||
extern crate ansi_term;
|
extern crate ansi_term;
|
||||||
|
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
@ -90,7 +91,6 @@ mod upgrade;
|
|||||||
mod rpc;
|
mod rpc;
|
||||||
mod dapps;
|
mod dapps;
|
||||||
mod informant;
|
mod informant;
|
||||||
mod io_handler;
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod configuration;
|
mod configuration;
|
||||||
mod migration;
|
mod migration;
|
||||||
@ -117,13 +117,16 @@ mod user_defaults;
|
|||||||
mod stratum;
|
mod stratum;
|
||||||
|
|
||||||
use std::{process, env};
|
use std::{process, env};
|
||||||
use std::io::{self as stdio, BufReader, Write};
|
use std::collections::HashMap;
|
||||||
|
use std::io::{self as stdio, BufReader, Read, Write};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::path::PathBuf;
|
||||||
use util::sha3::sha3;
|
use util::sha3::sha3;
|
||||||
use cli::Args;
|
use cli::Args;
|
||||||
use configuration::{Cmd, Execute, Configuration};
|
use configuration::{Cmd, Execute, Configuration};
|
||||||
use deprecated::find_deprecated;
|
use deprecated::find_deprecated;
|
||||||
use ethcore_logger::setup_log;
|
use ethcore_logger::setup_log;
|
||||||
|
use dir::default_hypervisor_path;
|
||||||
|
|
||||||
fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
|
fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
|
||||||
if let Some(file) = maybe_file {
|
if let Some(file) = maybe_file {
|
||||||
@ -135,31 +138,34 @@ fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(command: Execute) -> Result<String, String> {
|
enum PostExecutionAction {
|
||||||
|
Print(String),
|
||||||
|
Restart,
|
||||||
|
Quit,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(command: Execute, can_restart: bool) -> Result<PostExecutionAction, String> {
|
||||||
let logger = setup_log(&command.logger).expect("Logger is initialized only once; qed");
|
let logger = setup_log(&command.logger).expect("Logger is initialized only once; qed");
|
||||||
|
|
||||||
match command.cmd {
|
match command.cmd {
|
||||||
Cmd::Run(run_cmd) => {
|
Cmd::Run(run_cmd) => {
|
||||||
try!(run::execute(run_cmd, logger));
|
let restart = run::execute(run_cmd, can_restart, logger)?;
|
||||||
Ok("".into())
|
Ok(if restart { PostExecutionAction::Restart } else { PostExecutionAction::Quit })
|
||||||
},
|
},
|
||||||
Cmd::Version => Ok(Args::print_version()),
|
Cmd::Version => Ok(PostExecutionAction::Print(Args::print_version())),
|
||||||
Cmd::Hash(maybe_file) => print_hash_of(maybe_file),
|
Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| PostExecutionAction::Print(s)),
|
||||||
Cmd::Account(account_cmd) => account::execute(account_cmd),
|
Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||||
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd),
|
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||||
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd),
|
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd).map(|_| PostExecutionAction::Quit),
|
||||||
Cmd::SignerToken(signer_cmd) => signer::execute(signer_cmd),
|
Cmd::SignerToken(signer_cmd) => signer::execute(signer_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||||
Cmd::SignerSign { id, pwfile, port, authfile } =>
|
Cmd::SignerSign { id, pwfile, port, authfile } => rpc_cli::signer_sign(id, pwfile, port, authfile).map(|s| PostExecutionAction::Print(s)),
|
||||||
rpc_cli::cmd_signer_sign(id, pwfile, port, authfile),
|
Cmd::SignerList { port, authfile } => rpc_cli::signer_list(port, authfile).map(|s| PostExecutionAction::Print(s)),
|
||||||
Cmd::SignerList { port, authfile } =>
|
Cmd::SignerReject { id, port, authfile } => rpc_cli::signer_reject(id, port, authfile).map(|s| PostExecutionAction::Print(s)),
|
||||||
rpc_cli::cmd_signer_list(port, authfile),
|
Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||||
Cmd::SignerReject { id, port, authfile } =>
|
|
||||||
rpc_cli::cmd_signer_reject(id, port, authfile),
|
|
||||||
Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start() -> Result<String, String> {
|
fn start(can_restart: bool) -> Result<PostExecutionAction, String> {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let conf = Configuration::parse(&args).unwrap_or_else(|e| e.exit());
|
let conf = Configuration::parse(&args).unwrap_or_else(|e| e.exit());
|
||||||
|
|
||||||
@ -169,61 +175,118 @@ fn start() -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cmd = try!(conf.into_command());
|
let cmd = try!(conf.into_command());
|
||||||
execute(cmd)
|
execute(cmd, can_restart)
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="stratum")]
|
|
||||||
mod stratum_optional {
|
|
||||||
pub fn probably_run() -> bool {
|
|
||||||
// just redirect to the stratum::main()
|
|
||||||
if ::std::env::args().nth(1).map_or(false, |arg| arg == "stratum") {
|
|
||||||
super::stratum::main();
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else { false }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature="stratum"))]
|
#[cfg(not(feature="stratum"))]
|
||||||
mod stratum_optional {
|
fn stratum_main(_: &mut HashMap<String, fn()>) {}
|
||||||
pub fn probably_run() -> bool {
|
|
||||||
false
|
#[cfg(feature="stratum")]
|
||||||
}
|
fn stratum_main(alt_mains: &mut HashMap<String, fn()>) {
|
||||||
|
alt_mains.insert("stratum".to_owned(), stratum::main);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature="ipc"))]
|
#[cfg(not(feature="ipc"))]
|
||||||
fn sync_main() -> bool {
|
fn sync_main(_: &mut HashMap<String, fn()>) {}
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="ipc")]
|
#[cfg(feature="ipc")]
|
||||||
fn sync_main() -> bool {
|
fn sync_main(alt_mains: &mut HashMap<String, fn()>) {
|
||||||
// just redirect to the sync::main()
|
alt_mains.insert("sync".to_owned(), sync::main);
|
||||||
if std::env::args().nth(1).map_or(false, |arg| arg == "sync") {
|
}
|
||||||
sync::main();
|
|
||||||
true
|
fn updates_path(name: &str) -> PathBuf {
|
||||||
|
let mut dest = PathBuf::from(default_hypervisor_path());
|
||||||
|
dest.push(name);
|
||||||
|
dest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn latest_exe_path() -> Option<PathBuf> {
|
||||||
|
File::open(updates_path("latest")).ok()
|
||||||
|
.and_then(|mut f| { let mut exe = String::new(); f.read_to_string(&mut exe).ok().map(|_| updates_path(&exe)) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts ~/.parity-updates/parity and returns the code it exits with.
|
||||||
|
fn run_parity() -> Option<i32> {
|
||||||
|
use ::std::ffi::OsString;
|
||||||
|
let prefix = vec![OsString::from("--can-restart"), OsString::from("--force-direct")];
|
||||||
|
latest_exe_path().and_then(|exe| process::Command::new(exe)
|
||||||
|
.args(&(env::args_os().chain(prefix.into_iter()).collect::<Vec<_>>()))
|
||||||
|
.status()
|
||||||
|
.map(|es| es.code().unwrap_or(128))
|
||||||
|
.ok()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PLEASE_RESTART_EXIT_CODE: i32 = 69;
|
||||||
|
|
||||||
|
// Run our version of parity.
|
||||||
|
// Returns the exit error code.
|
||||||
|
fn main_direct(can_restart: bool) -> i32 {
|
||||||
|
let mut alt_mains = HashMap::new();
|
||||||
|
sync_main(&mut alt_mains);
|
||||||
|
stratum_main(&mut alt_mains);
|
||||||
|
if let Some(f) = std::env::args().nth(1).and_then(|arg| alt_mains.get(&arg.to_string())) {
|
||||||
|
f();
|
||||||
|
0
|
||||||
} else {
|
} else {
|
||||||
false
|
match start(can_restart) {
|
||||||
|
Ok(result) => match result {
|
||||||
|
PostExecutionAction::Print(s) => { println!("{}", s); 0 },
|
||||||
|
PostExecutionAction::Restart => PLEASE_RESTART_EXIT_CODE,
|
||||||
|
PostExecutionAction::Quit => 0,
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed");
|
||||||
|
1
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn println_trace_main(s: String) {
|
||||||
|
if env::var("RUST_LOG").ok().and_then(|s| s.find("main=trace")).is_some() {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trace_main {
|
||||||
|
($arg:expr) => (println_trace_main($arg.into()));
|
||||||
|
($($arg:tt)*) => (println_trace_main(format!("{}", format_args!($($arg)*))));
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Always print backtrace on panic.
|
// Always print backtrace on panic.
|
||||||
::std::env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
|
|
||||||
if sync_main() {
|
// assuming the user is not running with `--force-direct`, then:
|
||||||
return;
|
// if argv[0] == "parity" and this executable != ~/.parity-updates/parity, run that instead.
|
||||||
}
|
let force_direct = std::env::args().any(|arg| arg == "--force-direct");
|
||||||
|
let exe = std::env::current_exe().ok();
|
||||||
if stratum_optional::probably_run() { return; }
|
let development = exe.as_ref().and_then(|p| p.parent().and_then(|p| p.parent()).and_then(|p| p.file_name()).map(|n| n == "target")).unwrap_or(false);
|
||||||
|
let same_name = exe.as_ref().map(|p| p.file_stem().map_or(false, |s| s == "parity") && p.extension().map_or(true, |x| x == "exe")).unwrap_or(false);
|
||||||
match start() {
|
let latest_exe = latest_exe_path();
|
||||||
Ok(result) => {
|
let have_update = latest_exe.as_ref().map_or(false, |p| p.exists());
|
||||||
info!("{}", result);
|
let is_non_updated_current = exe.map_or(false, |exe| latest_exe.as_ref().map_or(false, |lexe| exe.canonicalize().ok() != lexe.canonicalize().ok()));
|
||||||
},
|
trace_main!("Starting up {} (force-direct: {}, development: {}, same-name: {}, have-update: {}, non-updated-current: {})", std::env::current_exe().map(|x| format!("{}", x.display())).unwrap_or("<unknown>".to_owned()), force_direct, development, same_name, have_update, is_non_updated_current);
|
||||||
Err(err) => {
|
if !force_direct && !development && same_name && have_update && is_non_updated_current {
|
||||||
writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed");
|
// looks like we're not running ~/.parity-updates/parity when the user is expecting otherwise.
|
||||||
process::exit(1);
|
// Everything run inside a loop, so we'll be able to restart from the child into a new version seamlessly.
|
||||||
|
loop {
|
||||||
|
// If we fail to run the updated parity then fallback to local version.
|
||||||
|
trace_main!("Attempting to run latest update ({})...", latest_exe.as_ref().expect("guarded by have_update; latest_exe must exist for have_update; qed").display());
|
||||||
|
let exit_code = run_parity().unwrap_or_else(|| { trace_main!("Falling back to local..."); main_direct(true) });
|
||||||
|
trace_main!("Latest exited with {}", exit_code);
|
||||||
|
if exit_code != PLEASE_RESTART_EXIT_CODE {
|
||||||
|
trace_main!("Quitting...");
|
||||||
|
process::exit(exit_code);
|
||||||
|
}
|
||||||
|
trace_main!("Rerunning...");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
trace_main!("Running direct");
|
||||||
|
// Otherwise, we're presumably running the version we want. Just run and fall-through.
|
||||||
|
let can_restart = std::env::args().any(|arg| arg == "--can-restart");
|
||||||
|
process::exit(main_direct(can_restart));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ impl Default for IpcConfiguration {
|
|||||||
let data_dir = default_data_path();
|
let data_dir = default_data_path();
|
||||||
IpcConfiguration {
|
IpcConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
socket_addr: parity_ipc_path(&data_dir, "$DATA/jsonrpc.ipc"),
|
socket_addr: parity_ipc_path(&data_dir, "$BASE/jsonrpc.ipc"),
|
||||||
apis: ApiSet::IpcContext,
|
apis: ApiSet::IpcContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ use ethcore::snapshot::SnapshotService;
|
|||||||
use ethsync::{ManageNetwork, SyncProvider};
|
use ethsync::{ManageNetwork, SyncProvider};
|
||||||
use ethcore_rpc::{Extendable, NetworkSettings};
|
use ethcore_rpc::{Extendable, NetworkSettings};
|
||||||
pub use ethcore_rpc::SignerService;
|
pub use ethcore_rpc::SignerService;
|
||||||
|
use updater::Updater;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||||
pub enum Api {
|
pub enum Api {
|
||||||
@ -118,6 +118,7 @@ pub struct Dependencies {
|
|||||||
pub logger: Arc<RotatingLogger>,
|
pub logger: Arc<RotatingLogger>,
|
||||||
pub settings: Arc<NetworkSettings>,
|
pub settings: Arc<NetworkSettings>,
|
||||||
pub net_service: Arc<ManageNetwork>,
|
pub net_service: Arc<ManageNetwork>,
|
||||||
|
pub updater: Arc<Updater>,
|
||||||
pub geth_compatibility: bool,
|
pub geth_compatibility: bool,
|
||||||
pub dapps_interface: Option<String>,
|
pub dapps_interface: Option<String>,
|
||||||
pub dapps_port: Option<u16>,
|
pub dapps_port: Option<u16>,
|
||||||
@ -224,6 +225,7 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
|||||||
&deps.client,
|
&deps.client,
|
||||||
&deps.miner,
|
&deps.miner,
|
||||||
&deps.sync,
|
&deps.sync,
|
||||||
|
&deps.updater,
|
||||||
&deps.net_service,
|
&deps.net_service,
|
||||||
&deps.secret_store,
|
&deps.secret_store,
|
||||||
deps.logger.clone(),
|
deps.logger.clone(),
|
||||||
@ -240,7 +242,7 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
|||||||
server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
|
server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
|
||||||
},
|
},
|
||||||
Api::ParitySet => {
|
Api::ParitySet => {
|
||||||
server.add_delegate(ParitySetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate())
|
server.add_delegate(ParitySetClient::new(&deps.client, &deps.miner, &deps.updater, &deps.net_service).to_delegate())
|
||||||
},
|
},
|
||||||
Api::Traces => {
|
Api::Traces => {
|
||||||
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())
|
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())
|
||||||
|
@ -14,16 +14,16 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex, Condvar};
|
use std::sync::Arc;
|
||||||
use std::net::{TcpListener};
|
use std::net::{TcpListener};
|
||||||
use ctrlc::CtrlC;
|
use ctrlc::CtrlC;
|
||||||
use fdlimit::raise_fd_limit;
|
use fdlimit::raise_fd_limit;
|
||||||
use ethcore_rpc::{NetworkSettings, is_major_importing};
|
use ethcore_rpc::{NetworkSettings, is_major_importing};
|
||||||
use ethsync::NetworkConfiguration;
|
use ethsync::NetworkConfiguration;
|
||||||
use util::{Colour, version, RotatingLogger};
|
use util::{Colour, version, RotatingLogger, Mutex, Condvar};
|
||||||
use io::{MayPanic, ForwardPanic, PanicHandler};
|
use io::{MayPanic, ForwardPanic, PanicHandler};
|
||||||
use ethcore_logger::{Config as LogConfig};
|
use ethcore_logger::{Config as LogConfig};
|
||||||
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, ChainNotify, BlockChainClient};
|
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockChainClient};
|
||||||
use ethcore::service::ClientService;
|
use ethcore::service::ClientService;
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions};
|
use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions};
|
||||||
@ -31,11 +31,11 @@ use ethcore::snapshot;
|
|||||||
use ethcore::verification::queue::VerifierSettings;
|
use ethcore::verification::queue::VerifierSettings;
|
||||||
use ethsync::SyncConfig;
|
use ethsync::SyncConfig;
|
||||||
use informant::Informant;
|
use informant::Informant;
|
||||||
|
use updater::{UpdatePolicy, Updater};
|
||||||
|
|
||||||
use rpc::{HttpServer, IpcServer, HttpConfiguration, IpcConfiguration};
|
use rpc::{HttpServer, IpcServer, HttpConfiguration, IpcConfiguration};
|
||||||
use signer::SignerServer;
|
use signer::SignerServer;
|
||||||
use dapps::WebappServer;
|
use dapps::WebappServer;
|
||||||
use io_handler::ClientIoHandler;
|
|
||||||
use params::{
|
use params::{
|
||||||
SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch,
|
SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch,
|
||||||
tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool
|
tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool
|
||||||
@ -77,6 +77,7 @@ pub struct RunCmd {
|
|||||||
pub acc_conf: AccountsConfig,
|
pub acc_conf: AccountsConfig,
|
||||||
pub gas_pricer: GasPricerConfig,
|
pub gas_pricer: GasPricerConfig,
|
||||||
pub miner_extras: MinerExtras,
|
pub miner_extras: MinerExtras,
|
||||||
|
pub update_policy: UpdatePolicy,
|
||||||
pub mode: Option<Mode>,
|
pub mode: Option<Mode>,
|
||||||
pub tracing: Switch,
|
pub tracing: Switch,
|
||||||
pub fat_db: Switch,
|
pub fat_db: Switch,
|
||||||
@ -115,12 +116,12 @@ pub fn open_ui(dapps_conf: &dapps::Configuration, signer_conf: &signer::Configur
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> Result<bool, String> {
|
||||||
if cmd.ui && cmd.dapps_conf.enabled {
|
if cmd.ui && cmd.dapps_conf.enabled {
|
||||||
// Check if Parity is already running
|
// Check if Parity is already running
|
||||||
let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port);
|
let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port);
|
||||||
if !TcpListener::bind(&addr as &str).is_ok() {
|
if !TcpListener::bind(&addr as &str).is_ok() {
|
||||||
return open_ui(&cmd.dapps_conf, &cmd.signer_conf);
|
return open_ui(&cmd.dapps_conf, &cmd.signer_conf).map(|_| false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,12 +160,15 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
trace!(target: "mode", "mode is {:?}", mode);
|
trace!(target: "mode", "mode is {:?}", mode);
|
||||||
let network_enabled = match mode { Mode::Dark(_) | Mode::Off => false, _ => true, };
|
let network_enabled = match mode { Mode::Dark(_) | Mode::Off => false, _ => true, };
|
||||||
|
|
||||||
|
// get the update policy
|
||||||
|
let update_policy = cmd.update_policy;
|
||||||
|
|
||||||
// prepare client and snapshot paths.
|
// prepare client and snapshot paths.
|
||||||
let client_path = db_dirs.client_path(algorithm);
|
let client_path = db_dirs.client_path(algorithm);
|
||||||
let snapshot_path = db_dirs.snapshot_path();
|
let snapshot_path = db_dirs.snapshot_path();
|
||||||
|
|
||||||
// execute upgrades
|
// execute upgrades
|
||||||
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
try!(execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||||
|
|
||||||
// create dirs used by parity
|
// create dirs used by parity
|
||||||
try!(cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled));
|
try!(cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled));
|
||||||
@ -307,6 +311,10 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
chain_notify.start();
|
chain_notify.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the updater service
|
||||||
|
let updater = Updater::new(Arc::downgrade(&(service.client() as Arc<BlockChainClient>)), Arc::downgrade(&sync_provider), update_policy);
|
||||||
|
service.add_notify(updater.clone());
|
||||||
|
|
||||||
// set up dependencies for rpc servers
|
// set up dependencies for rpc servers
|
||||||
let signer_path = cmd.signer_conf.signer_path.clone();
|
let signer_path = cmd.signer_conf.signer_path.clone();
|
||||||
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
||||||
@ -323,6 +331,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
logger: logger.clone(),
|
logger: logger.clone(),
|
||||||
settings: Arc::new(cmd.net_settings.clone()),
|
settings: Arc::new(cmd.net_settings.clone()),
|
||||||
net_service: manage_network.clone(),
|
net_service: manage_network.clone(),
|
||||||
|
updater: updater.clone(),
|
||||||
geth_compatibility: cmd.geth_compatibility,
|
geth_compatibility: cmd.geth_compatibility,
|
||||||
dapps_interface: match cmd.dapps_conf.enabled {
|
dapps_interface: match cmd.dapps_conf.enabled {
|
||||||
true => Some(cmd.dapps_conf.interface.clone()),
|
true => Some(cmd.dapps_conf.interface.clone()),
|
||||||
@ -343,24 +352,23 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
let http_server = try!(rpc::new_http(cmd.http_conf, &dependencies));
|
let http_server = try!(rpc::new_http(cmd.http_conf, &dependencies));
|
||||||
let ipc_server = try!(rpc::new_ipc(cmd.ipc_conf, &dependencies));
|
let ipc_server = try!(rpc::new_ipc(cmd.ipc_conf, &dependencies));
|
||||||
|
|
||||||
|
// the dapps server
|
||||||
let dapps_deps = dapps::Dependencies {
|
let dapps_deps = dapps::Dependencies {
|
||||||
panic_handler: panic_handler.clone(),
|
panic_handler: panic_handler.clone(),
|
||||||
apis: deps_for_rpc_apis.clone(),
|
apis: deps_for_rpc_apis.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
sync: sync_provider.clone(),
|
sync: sync_provider.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// start dapps server
|
|
||||||
let dapps_server = try!(dapps::new(cmd.dapps_conf.clone(), dapps_deps));
|
let dapps_server = try!(dapps::new(cmd.dapps_conf.clone(), dapps_deps));
|
||||||
|
|
||||||
|
// the signer server
|
||||||
let signer_deps = signer::Dependencies {
|
let signer_deps = signer::Dependencies {
|
||||||
panic_handler: panic_handler.clone(),
|
panic_handler: panic_handler.clone(),
|
||||||
apis: deps_for_rpc_apis.clone(),
|
apis: deps_for_rpc_apis.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// start signer server
|
|
||||||
let signer_server = try!(signer::start(cmd.signer_conf.clone(), signer_deps));
|
let signer_server = try!(signer::start(cmd.signer_conf.clone(), signer_deps));
|
||||||
|
|
||||||
|
// the informant
|
||||||
let informant = Arc::new(Informant::new(
|
let informant = Arc::new(Informant::new(
|
||||||
service.client(),
|
service.client(),
|
||||||
Some(sync_provider.clone()),
|
Some(sync_provider.clone()),
|
||||||
@ -368,17 +376,8 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
Some(snapshot_service.clone()),
|
Some(snapshot_service.clone()),
|
||||||
cmd.logger_config.color
|
cmd.logger_config.color
|
||||||
));
|
));
|
||||||
let info_notify: Arc<ChainNotify> = informant.clone();
|
service.add_notify(informant.clone());
|
||||||
service.add_notify(info_notify);
|
service.register_io_handler(informant.clone()).map_err(|_| "Unable to register informant handler".to_owned())?;
|
||||||
let io_handler = Arc::new(ClientIoHandler {
|
|
||||||
client: service.client(),
|
|
||||||
info: informant,
|
|
||||||
sync: sync_provider.clone(),
|
|
||||||
net: manage_network.clone(),
|
|
||||||
accounts: account_provider.clone(),
|
|
||||||
shutdown: Default::default(),
|
|
||||||
});
|
|
||||||
service.register_io_handler(io_handler.clone()).expect("Error registering IO handler");
|
|
||||||
|
|
||||||
// save user defaults
|
// save user defaults
|
||||||
user_defaults.pruning = algorithm;
|
user_defaults.pruning = algorithm;
|
||||||
@ -387,13 +386,11 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
user_defaults.mode = mode;
|
user_defaults.mode = mode;
|
||||||
try!(user_defaults.save(&user_defaults_path));
|
try!(user_defaults.save(&user_defaults_path));
|
||||||
|
|
||||||
let on_mode_change = move |mode: &Mode| {
|
// tell client how to save the default mode if it gets changed.
|
||||||
|
client.on_mode_change(move |mode: &Mode| {
|
||||||
user_defaults.mode = mode.clone();
|
user_defaults.mode = mode.clone();
|
||||||
let _ = user_defaults.save(&user_defaults_path); // discard failures - there's nothing we can do
|
let _ = user_defaults.save(&user_defaults_path); // discard failures - there's nothing we can do
|
||||||
};
|
});
|
||||||
|
|
||||||
// tell client how to save the default mode if it gets changed.
|
|
||||||
client.on_mode_change(on_mode_change);
|
|
||||||
|
|
||||||
// the watcher must be kept alive.
|
// the watcher must be kept alive.
|
||||||
let _watcher = match cmd.no_periodic_snapshot {
|
let _watcher = match cmd.no_periodic_snapshot {
|
||||||
@ -419,18 +416,20 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle exit
|
// Handle exit
|
||||||
wait_for_exit(panic_handler, http_server, ipc_server, dapps_server, signer_server);
|
let restart = wait_for_exit(panic_handler, http_server, ipc_server, dapps_server, signer_server, updater, can_restart);
|
||||||
|
|
||||||
|
info!("Finishing work, please wait...");
|
||||||
|
|
||||||
// to make sure timer does not spawn requests while shutdown is in progress
|
// to make sure timer does not spawn requests while shutdown is in progress
|
||||||
io_handler.shutdown.store(true, ::std::sync::atomic::Ordering::SeqCst);
|
informant.shutdown();
|
||||||
// just Arc is dropping here, to allow other reference release in its default time
|
// just Arc is dropping here, to allow other reference release in its default time
|
||||||
drop(io_handler);
|
drop(informant);
|
||||||
|
|
||||||
// hypervisor should be shutdown first while everything still works and can be
|
// hypervisor should be shutdown first while everything still works and can be
|
||||||
// terminated gracefully
|
// terminated gracefully
|
||||||
drop(hypervisor);
|
drop(hypervisor);
|
||||||
|
|
||||||
Ok(())
|
Ok(restart)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
@ -438,11 +437,11 @@ fn daemonize(pid_file: String) -> Result<(), String> {
|
|||||||
extern crate daemonize;
|
extern crate daemonize;
|
||||||
|
|
||||||
daemonize::Daemonize::new()
|
daemonize::Daemonize::new()
|
||||||
.pid_file(pid_file)
|
.pid_file(pid_file)
|
||||||
.chown_pid_file(true)
|
.chown_pid_file(true)
|
||||||
.start()
|
.start()
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|e| format!("Couldn't daemonize; {}", e))
|
.map_err(|e| format!("Couldn't daemonize; {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -475,20 +474,30 @@ fn wait_for_exit(
|
|||||||
_http_server: Option<HttpServer>,
|
_http_server: Option<HttpServer>,
|
||||||
_ipc_server: Option<IpcServer>,
|
_ipc_server: Option<IpcServer>,
|
||||||
_dapps_server: Option<WebappServer>,
|
_dapps_server: Option<WebappServer>,
|
||||||
_signer_server: Option<SignerServer>
|
_signer_server: Option<SignerServer>,
|
||||||
) {
|
updater: Arc<Updater>,
|
||||||
let exit = Arc::new(Condvar::new());
|
can_restart: bool
|
||||||
|
) -> bool {
|
||||||
|
let exit = Arc::new((Mutex::new(false), Condvar::new()));
|
||||||
|
|
||||||
// Handle possible exits
|
// Handle possible exits
|
||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
CtrlC::set_handler(move || { e.notify_all(); });
|
CtrlC::set_handler(move || { e.1.notify_all(); });
|
||||||
|
|
||||||
// Handle panics
|
// Handle panics
|
||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
panic_handler.on_panic(move |_reason| { e.notify_all(); });
|
panic_handler.on_panic(move |_reason| { e.1.notify_all(); });
|
||||||
|
|
||||||
|
// Handle updater wanting to restart us
|
||||||
|
if can_restart {
|
||||||
|
let e = exit.clone();
|
||||||
|
updater.set_exit_handler(move || { *e.0.lock() = true; e.1.notify_all(); });
|
||||||
|
} else {
|
||||||
|
updater.set_exit_handler(|| info!("Update installed; ready for restart."));
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for signal
|
// Wait for signal
|
||||||
let mutex = Mutex::new(());
|
let mut l = exit.0.lock();
|
||||||
let _ = exit.wait(mutex.lock().unwrap());
|
let _ = exit.1.wait(&mut l);
|
||||||
info!("Finishing work, please wait...");
|
*l
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ impl Default for Configuration {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
port: 8180,
|
port: 8180,
|
||||||
interface: "127.0.0.1".into(),
|
interface: "127.0.0.1".into(),
|
||||||
signer_path: replace_home(&data_dir, "$DATA/signer"),
|
signer_path: replace_home(&data_dir, "$BASE/signer"),
|
||||||
skip_origin_validation: false,
|
skip_origin_validation: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ impl SnapshotCommand {
|
|||||||
let snapshot_path = db_dirs.snapshot_path();
|
let snapshot_path = db_dirs.snapshot_path();
|
||||||
|
|
||||||
// execute upgrades
|
// execute upgrades
|
||||||
try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
try!(execute_upgrades(&self.dirs.base, &db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.db_root_path().as_path())));
|
||||||
|
|
||||||
// prepare client config
|
// prepare client config
|
||||||
let client_config = to_client_config(&self.cache_config, Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true);
|
let client_config = to_client_config(&self.cache_config, Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true);
|
||||||
|
@ -200,11 +200,11 @@ fn upgrade_user_defaults(dirs: &DatabaseDirectories) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn upgrade_data_paths(dirs: &DatabaseDirectories, pruning: Algorithm) {
|
pub fn upgrade_data_paths(base_path: &str, dirs: &DatabaseDirectories, pruning: Algorithm) {
|
||||||
let legacy_root_path = replace_home("", "$HOME/.parity");
|
let legacy_root_path = replace_home("", "$HOME/.parity");
|
||||||
let default_path = default_data_path();
|
let default_path = default_data_path();
|
||||||
if legacy_root_path != dirs.path && dirs.path == default_path {
|
if legacy_root_path != base_path && base_path == default_path {
|
||||||
upgrade_dir_location(&PathBuf::from(legacy_root_path), &PathBuf::from(&dirs.path));
|
upgrade_dir_location(&PathBuf::from(legacy_root_path), &PathBuf::from(&base_path));
|
||||||
}
|
}
|
||||||
upgrade_dir_location(&dirs.legacy_version_path(pruning), &dirs.db_path(pruning));
|
upgrade_dir_location(&dirs.legacy_version_path(pruning), &dirs.db_path(pruning));
|
||||||
upgrade_dir_location(&dirs.legacy_snapshot_path(), &dirs.snapshot_path());
|
upgrade_dir_location(&dirs.legacy_snapshot_path(), &dirs.snapshot_path());
|
||||||
|
@ -26,6 +26,7 @@ ethash = { path = "../ethash" }
|
|||||||
ethsync = { path = "../sync" }
|
ethsync = { path = "../sync" }
|
||||||
ethjson = { path = "../json" }
|
ethjson = { path = "../json" }
|
||||||
ethcore-devtools = { path = "../devtools" }
|
ethcore-devtools = { path = "../devtools" }
|
||||||
|
parity-updater = { path = "../updater" }
|
||||||
rlp = { path = "../util/rlp" }
|
rlp = { path = "../util/rlp" }
|
||||||
fetch = { path = "../util/fetch" }
|
fetch = { path = "../util/fetch" }
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
@ -34,6 +35,7 @@ serde_macros = { version = "0.8.0", optional = true }
|
|||||||
clippy = { version = "0.0.103", optional = true}
|
clippy = { version = "0.0.103", optional = true}
|
||||||
ethcore-ipc = { path = "../ipc/rpc" }
|
ethcore-ipc = { path = "../ipc/rpc" }
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
|
semver = "0.5"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
serde_codegen = { version = "0.8.0", optional = true }
|
serde_codegen = { version = "0.8.0", optional = true }
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#![cfg_attr(feature="nightly", feature(custom_derive, custom_attribute, plugin))]
|
#![cfg_attr(feature="nightly", feature(custom_derive, custom_attribute, plugin))]
|
||||||
#![cfg_attr(feature="nightly", plugin(serde_macros, clippy))]
|
#![cfg_attr(feature="nightly", plugin(serde_macros, clippy))]
|
||||||
|
|
||||||
|
extern crate semver;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
@ -37,6 +38,7 @@ extern crate ethcore_ipc;
|
|||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate fetch;
|
extern crate fetch;
|
||||||
|
extern crate parity_updater as updater;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
@ -30,6 +30,7 @@ use ethcore::miner::MinerService;
|
|||||||
use ethcore::client::{MiningBlockChainClient};
|
use ethcore::client::{MiningBlockChainClient};
|
||||||
use ethcore::mode::Mode;
|
use ethcore::mode::Mode;
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
|
use updater::{Service as UpdateService};
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Trailing;
|
use jsonrpc_macros::Trailing;
|
||||||
@ -38,20 +39,23 @@ use v1::types::{
|
|||||||
Bytes, U256, H160, H256, H512,
|
Bytes, U256, H160, H256, H512,
|
||||||
Peers, Transaction, RpcSettings, Histogram,
|
Peers, Transaction, RpcSettings, Histogram,
|
||||||
TransactionStats, LocalTransactionStatus,
|
TransactionStats, LocalTransactionStatus,
|
||||||
BlockNumber,
|
BlockNumber, ConsensusCapability, VersionInfo,
|
||||||
|
OperationsInfo
|
||||||
};
|
};
|
||||||
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
||||||
use v1::helpers::dispatch::DEFAULT_MAC;
|
use v1::helpers::dispatch::DEFAULT_MAC;
|
||||||
|
|
||||||
/// Parity implementation.
|
/// Parity implementation.
|
||||||
pub struct ParityClient<C, M, S: ?Sized> where
|
pub struct ParityClient<C, M, S: ?Sized, U> where
|
||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
S: SyncProvider,
|
S: SyncProvider,
|
||||||
|
U: UpdateService,
|
||||||
{
|
{
|
||||||
client: Weak<C>,
|
client: Weak<C>,
|
||||||
miner: Weak<M>,
|
miner: Weak<M>,
|
||||||
sync: Weak<S>,
|
sync: Weak<S>,
|
||||||
|
updater: Weak<U>,
|
||||||
net: Weak<ManageNetwork>,
|
net: Weak<ManageNetwork>,
|
||||||
accounts: Weak<AccountProvider>,
|
accounts: Weak<AccountProvider>,
|
||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
@ -61,16 +65,18 @@ pub struct ParityClient<C, M, S: ?Sized> where
|
|||||||
dapps_port: Option<u16>,
|
dapps_port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S: ?Sized> ParityClient<C, M, S> where
|
impl<C, M, S: ?Sized, U> ParityClient<C, M, S, U> where
|
||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
S: SyncProvider,
|
S: SyncProvider,
|
||||||
|
U: UpdateService,
|
||||||
{
|
{
|
||||||
/// Creates new `ParityClient`.
|
/// Creates new `ParityClient`.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: &Arc<C>,
|
client: &Arc<C>,
|
||||||
miner: &Arc<M>,
|
miner: &Arc<M>,
|
||||||
sync: &Arc<S>,
|
sync: &Arc<S>,
|
||||||
|
updater: &Arc<U>,
|
||||||
net: &Arc<ManageNetwork>,
|
net: &Arc<ManageNetwork>,
|
||||||
store: &Arc<AccountProvider>,
|
store: &Arc<AccountProvider>,
|
||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
@ -83,6 +89,7 @@ impl<C, M, S: ?Sized> ParityClient<C, M, S> where
|
|||||||
client: Arc::downgrade(client),
|
client: Arc::downgrade(client),
|
||||||
miner: Arc::downgrade(miner),
|
miner: Arc::downgrade(miner),
|
||||||
sync: Arc::downgrade(sync),
|
sync: Arc::downgrade(sync),
|
||||||
|
updater: Arc::downgrade(updater),
|
||||||
net: Arc::downgrade(net),
|
net: Arc::downgrade(net),
|
||||||
accounts: Arc::downgrade(store),
|
accounts: Arc::downgrade(store),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
@ -100,10 +107,11 @@ impl<C, M, S: ?Sized> ParityClient<C, M, S> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
|
impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
|
||||||
M: MinerService + 'static,
|
M: MinerService + 'static,
|
||||||
C: MiningBlockChainClient + 'static,
|
C: MiningBlockChainClient + 'static,
|
||||||
S: SyncProvider + 'static {
|
S: SyncProvider + 'static,
|
||||||
|
U: UpdateService + 'static {
|
||||||
|
|
||||||
fn transactions_limit(&self) -> Result<usize, Error> {
|
fn transactions_limit(&self) -> Result<usize, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
@ -359,4 +367,22 @@ impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
|
|||||||
(format!("0x{}", a.hex()), m)
|
(format!("0x{}", a.hex()), m)
|
||||||
}).collect())
|
}).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn consensus_capability(&self) -> Result<ConsensusCapability, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
let updater = take_weak!(self.updater);
|
||||||
|
Ok(updater.capability().into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version_info(&self) -> Result<VersionInfo, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
let updater = take_weak!(self.updater);
|
||||||
|
Ok(updater.version_info().into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn releases_info(&self) -> Result<Option<OperationsInfo>, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
let updater = take_weak!(self.updater);
|
||||||
|
Ok(updater.info().map(Into::into))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,45 +24,51 @@ use ethcore::mode::Mode;
|
|||||||
use ethsync::ManageNetwork;
|
use ethsync::ManageNetwork;
|
||||||
use fetch::{Client as FetchClient, Fetch};
|
use fetch::{Client as FetchClient, Fetch};
|
||||||
use util::{Mutex, sha3};
|
use util::{Mutex, sha3};
|
||||||
|
use updater::{Service as UpdateService};
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Ready;
|
use jsonrpc_macros::Ready;
|
||||||
use v1::helpers::errors;
|
use v1::helpers::errors;
|
||||||
use v1::traits::ParitySet;
|
use v1::traits::ParitySet;
|
||||||
use v1::types::{Bytes, H160, H256, U256};
|
use v1::types::{Bytes, H160, H256, U256, ReleaseInfo};
|
||||||
|
|
||||||
/// Parity-specific rpc interface for operations altering the settings.
|
/// Parity-specific rpc interface for operations altering the settings.
|
||||||
pub struct ParitySetClient<C, M, F=FetchClient> where
|
pub struct ParitySetClient<C, M, U, F=FetchClient> where
|
||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
|
U: UpdateService,
|
||||||
F: Fetch,
|
F: Fetch,
|
||||||
{
|
{
|
||||||
client: Weak<C>,
|
client: Weak<C>,
|
||||||
miner: Weak<M>,
|
miner: Weak<M>,
|
||||||
|
updater: Weak<U>,
|
||||||
net: Weak<ManageNetwork>,
|
net: Weak<ManageNetwork>,
|
||||||
fetch: Mutex<F>,
|
fetch: Mutex<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M> ParitySetClient<C, M, FetchClient> where
|
impl<C, M, U> ParitySetClient<C, M, U, FetchClient> where
|
||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService
|
M: MinerService,
|
||||||
|
U: UpdateService,
|
||||||
{
|
{
|
||||||
/// Creates new `ParitySetClient` with default `FetchClient`.
|
/// Creates new `ParitySetClient` with default `FetchClient`.
|
||||||
pub fn new(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self {
|
pub fn new(client: &Arc<C>, miner: &Arc<M>, updater: &Arc<U>, net: &Arc<ManageNetwork>) -> Self {
|
||||||
Self::with_fetch(client, miner, net)
|
Self::with_fetch(client, miner, updater, net)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, F> ParitySetClient<C, M, F> where
|
impl<C, M, U, F> ParitySetClient<C, M, U, F> where
|
||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
|
U: UpdateService,
|
||||||
F: Fetch,
|
F: Fetch,
|
||||||
{
|
{
|
||||||
/// Creates new `ParitySetClient` with default `FetchClient`.
|
/// Creates new `ParitySetClient` with default `FetchClient`.
|
||||||
pub fn with_fetch(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self {
|
pub fn with_fetch(client: &Arc<C>, miner: &Arc<M>, updater: &Arc<U>, net: &Arc<ManageNetwork>) -> Self {
|
||||||
ParitySetClient {
|
ParitySetClient {
|
||||||
client: Arc::downgrade(client),
|
client: Arc::downgrade(client),
|
||||||
miner: Arc::downgrade(miner),
|
miner: Arc::downgrade(miner),
|
||||||
|
updater: Arc::downgrade(updater),
|
||||||
net: Arc::downgrade(net),
|
net: Arc::downgrade(net),
|
||||||
fetch: Mutex::new(F::default()),
|
fetch: Mutex::new(F::default()),
|
||||||
}
|
}
|
||||||
@ -75,9 +81,10 @@ impl<C, M, F> ParitySetClient<C, M, F> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, F> ParitySet for ParitySetClient<C, M, F> where
|
impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
|
||||||
C: MiningBlockChainClient + 'static,
|
C: MiningBlockChainClient + 'static,
|
||||||
M: MinerService + 'static,
|
M: MinerService + 'static,
|
||||||
|
U: UpdateService + 'static,
|
||||||
F: Fetch + 'static,
|
F: Fetch + 'static,
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -230,4 +237,16 @@ impl<C, M, F> ParitySet for ParitySetClient<C, M, F> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn upgrade_ready(&self) -> Result<Option<ReleaseInfo>, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
let updater = take_weak!(self.updater);
|
||||||
|
Ok(updater.upgrade_ready().map(Into::into))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute_upgrade(&self) -> Result<bool, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
let updater = take_weak!(self.updater);
|
||||||
|
Ok(updater.execute_upgrade())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,10 @@ mod sync_provider;
|
|||||||
mod miner_service;
|
mod miner_service;
|
||||||
mod fetch;
|
mod fetch;
|
||||||
mod snapshot_service;
|
mod snapshot_service;
|
||||||
|
mod update_service;
|
||||||
|
|
||||||
pub use self::sync_provider::{Config, TestSyncProvider};
|
pub use self::sync_provider::{Config, TestSyncProvider};
|
||||||
pub use self::miner_service::TestMinerService;
|
pub use self::miner_service::TestMinerService;
|
||||||
pub use self::fetch::TestFetch;
|
pub use self::fetch::TestFetch;
|
||||||
pub use self::snapshot_service::TestSnapshotService;
|
pub use self::snapshot_service::TestSnapshotService;
|
||||||
|
pub use self::update_service::TestUpdater;
|
97
rpc/src/v1/tests/helpers/update_service.rs
Normal file
97
rpc/src/v1/tests/helpers/update_service.rs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Test implementation of fetch client.
|
||||||
|
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
|
use semver::Version;
|
||||||
|
use updater::{Service as UpdateService, CapState, ReleaseInfo, VersionInfo, OperationsInfo, ReleaseTrack};
|
||||||
|
|
||||||
|
/// Test implementation of fetcher. Will always return the same file.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct TestUpdater {
|
||||||
|
updated: AtomicBool,
|
||||||
|
current_block: AtomicUsize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestUpdater {
|
||||||
|
/// Update the (faked) current block.
|
||||||
|
pub fn set_current_block(&self, n: usize) {
|
||||||
|
self.current_block.store(n, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the (faked) current block.
|
||||||
|
pub fn set_updated(&self, v: bool) {
|
||||||
|
self.updated.store(v, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UpdateService for TestUpdater {
|
||||||
|
fn capability(&self) -> CapState {
|
||||||
|
if self.updated.load(Ordering::Relaxed) {
|
||||||
|
CapState::Capable
|
||||||
|
} else {
|
||||||
|
if self.current_block.load(Ordering::Relaxed) < 15100 {
|
||||||
|
CapState::CapableUntil(15100)
|
||||||
|
} else {
|
||||||
|
CapState::IncapableSince(15100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn upgrade_ready(&self) -> Option<ReleaseInfo> {
|
||||||
|
if self.updated.load(Ordering::Relaxed) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.info().map(|i| i.track)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute_upgrade(&self) -> bool {
|
||||||
|
if self.updated.load(Ordering::Relaxed) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
self.updated.store(true, Ordering::Relaxed);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version_info(&self) -> VersionInfo {
|
||||||
|
VersionInfo {
|
||||||
|
track: ReleaseTrack::Beta,
|
||||||
|
version: Version{major: 1, minor: 5, patch: 0, build: vec![], pre: vec![]},
|
||||||
|
hash: 150.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn info(&self) -> Option<OperationsInfo> {
|
||||||
|
Some(OperationsInfo {
|
||||||
|
fork: 15100,
|
||||||
|
this_fork: Some(15000),
|
||||||
|
track: ReleaseInfo {
|
||||||
|
version: VersionInfo {
|
||||||
|
track: ReleaseTrack::Beta,
|
||||||
|
version: Version{major: 1, minor: 5, patch: 1, build: vec![], pre: vec![]},
|
||||||
|
hash: 151.into(),
|
||||||
|
},
|
||||||
|
is_critical: true,
|
||||||
|
fork: 15100,
|
||||||
|
binary: Some(1510.into()),
|
||||||
|
},
|
||||||
|
minor: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user