Merge branch 'master' into lightsync
This commit is contained in:
commit
f85313fbff
2
.gitignore
vendored
2
.gitignore
vendored
@ -32,3 +32,5 @@
|
||||
out/
|
||||
|
||||
.vscode
|
||||
|
||||
/parity.*
|
||||
|
@ -20,8 +20,10 @@ linux-stable:
|
||||
- stable
|
||||
- triggers
|
||||
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
|
||||
- strip target/release/parity
|
||||
- export SHA3=$(target/release/parity tools hash target/release/parity)
|
||||
- md5sum target/release/parity > parity.md5
|
||||
- sh scripts/deb-build.sh amd64
|
||||
- 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_"$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"
|
||||
- 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:
|
||||
- rust
|
||||
- rust-stable
|
||||
@ -92,15 +95,18 @@ linux-centos:
|
||||
script:
|
||||
- export CXX="g++"
|
||||
- export CC="gcc"
|
||||
- export PLATFORM=x86_64-unknown-centos-gnu
|
||||
- cargo build -j $(nproc) --release $CARGOFLAGS
|
||||
- strip target/release/parity
|
||||
- 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_secret_access_key $s3_secret
|
||||
- if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
|
||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu
|
||||
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity --body target/release/parity
|
||||
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity.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:
|
||||
- rust
|
||||
- rust-centos
|
||||
@ -119,22 +125,26 @@ linux-i686:
|
||||
script:
|
||||
- export HOST_CC=gcc
|
||||
- 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
|
||||
- strip target/i686-unknown-linux-gnu/release/parity
|
||||
- md5sum target/i686-unknown-linux-gnu/release/parity > parity.md5
|
||||
- strip target/$PLATFORM/release/parity
|
||||
- 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
|
||||
- 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")
|
||||
- dpkg-deb -b deb "parity_"$VER"_i386.deb"
|
||||
- md5sum "parity_"$VER"_i386.deb" > "parity_"$VER"_i386.deb.md5"
|
||||
- aws configure set aws_access_key_id $s3_key
|
||||
- aws configure set aws_secret_access_key $s3_secret
|
||||
- if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
|
||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/i686-unknown-linux-gnu
|
||||
- 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/i686-unknown-linux-gnu/parity.md5 --body parity.md5
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/"parity_"$VER"_i386.deb" --body "parity_"$VER"_i386.deb"
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/i686-unknown-linux-gnu/"parity_"$VER"_i386.deb.md5" --body "parity_"$VER"_i386.deb.md5"
|
||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM
|
||||
- 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/$PLATFORM/parity.md5 --body parity.md5
|
||||
- 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/$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:
|
||||
- rust
|
||||
- rust-i686
|
||||
@ -292,7 +302,6 @@ linux-aarch64:
|
||||
- aws configure set aws_secret_access_key $s3_secret
|
||||
- if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
|
||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity --body target/aarch64-unknown-linux-gnu/release/parity
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity.md5 --body parity.md5
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/"parity_"$VER"_arm64.deb" --body "parity_"$VER"_arm64.deb"
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/"parity_"$VER"_arm64.deb.md5" --body "parity_"$VER"_arm64.deb.md5"
|
||||
@ -312,10 +321,13 @@ darwin:
|
||||
- stable
|
||||
- triggers
|
||||
script:
|
||||
- export COMMIT=$(git rev-parse HEAD)
|
||||
- export PLATFORM=x86_64-apple-darwin
|
||||
- cargo build -j 8 --release #$CARGOFLAGS
|
||||
- cargo build -j 8 --release -p ethstore #$CARGOFLAGS
|
||||
- rm -rf parity.md5
|
||||
- md5sum target/release/parity > parity.md5
|
||||
- export SHA3=$(target/release/parity tools hash target/release/parity)
|
||||
- packagesbuild -v mac/Parity.pkgproj
|
||||
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
|
||||
- mv target/release/Parity\ Ethereum.pkg "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg"
|
||||
@ -323,11 +335,12 @@ darwin:
|
||||
- aws configure set aws_access_key_id $s3_key
|
||||
- aws configure set aws_secret_access_key $s3_secret
|
||||
- if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
|
||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-apple-darwin
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/parity --body target/release/parity
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/parity.md5 --body parity.md5
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/"parity-"$VER"-osx-installer-EXPERIMENTAL.pkg" --body "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg"
|
||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-apple-darwin/"parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5" --body "parity-"$VER"-osx-installer-EXPERIMENTAL.pkg.md5"
|
||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM
|
||||
- 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/$PLATFORM/parity.md5 --body parity.md5
|
||||
- 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/$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:
|
||||
- osx
|
||||
artifacts:
|
||||
@ -345,12 +358,14 @@ windows:
|
||||
- stable
|
||||
- triggers
|
||||
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 LIB=C:\vs2015\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64
|
||||
- set RUST_BACKTRACE=1
|
||||
- set RUSTFLAGS=%RUSTFLAGS%
|
||||
- rustup default stable-x86_64-pc-windows-msvc
|
||||
- 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/vc_redist.x64.exe" -o nsis\vc_redist.x64.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/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
|
||||
- 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:
|
||||
- rust-windows
|
||||
artifacts:
|
||||
@ -399,9 +415,10 @@ test-darwin:
|
||||
- triggers
|
||||
before_script:
|
||||
- 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:
|
||||
- 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:
|
||||
- osx
|
||||
allow_failure: true
|
||||
@ -413,7 +430,7 @@ test-windows:
|
||||
- git submodule update --init --recursive
|
||||
script:
|
||||
- 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:
|
||||
- rust-windows
|
||||
allow_failure: true
|
||||
@ -448,10 +465,10 @@ test-rust-beta:
|
||||
image: ethcore/rust:beta
|
||||
before_script:
|
||||
- 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:
|
||||
- export RUST_BACKTRACE=1
|
||||
- echo $JS_FILES_MODIFIED
|
||||
- ./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:
|
||||
- rust
|
||||
- rust-beta
|
||||
@ -463,9 +480,10 @@ test-rust-nightly:
|
||||
image: ethcore/rust:nightly
|
||||
before_script:
|
||||
- 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:
|
||||
- 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:
|
||||
- rust
|
||||
- rust-nightly
|
||||
|
94
Cargo.lock
generated
94
Cargo.lock
generated
@ -12,7 +12,6 @@ dependencies = [
|
||||
"ethcore 1.5.0",
|
||||
"ethcore-dapps 1.5.0",
|
||||
"ethcore-devtools 1.5.0",
|
||||
"ethcore-hash-fetch 1.5.0",
|
||||
"ethcore-io 1.5.0",
|
||||
"ethcore-ipc 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)",
|
||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-hash-fetch 1.5.0",
|
||||
"parity-rpc-client 1.4.0",
|
||||
"parity-updater 1.5.0",
|
||||
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.1.0",
|
||||
"rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rpc-cli 1.4.0",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.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_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)",
|
||||
@ -306,6 +307,7 @@ dependencies = [
|
||||
"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)",
|
||||
"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",
|
||||
"ethcore-bloom-journal 0.1.0",
|
||||
"ethcore-devtools 1.5.0",
|
||||
@ -330,7 +332,7 @@ dependencies = [
|
||||
"rlp 0.1.0",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-devtools 1.5.0",
|
||||
"ethcore-hash-fetch 1.5.0",
|
||||
"ethcore-rpc 1.5.0",
|
||||
"ethcore-util 1.5.0",
|
||||
"fetch 0.1.0",
|
||||
@ -371,6 +372,7 @@ dependencies = [
|
||||
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-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",
|
||||
"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)",
|
||||
@ -390,18 +392,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "ethcore-io"
|
||||
version = "1.5.0"
|
||||
@ -420,7 +410,7 @@ dependencies = [
|
||||
"ethcore-devtools 1.5.0",
|
||||
"ethcore-util 1.5.0",
|
||||
"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]]
|
||||
@ -443,7 +433,7 @@ dependencies = [
|
||||
"ethcore-ipc-nano 1.5.0",
|
||||
"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)",
|
||||
"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)",
|
||||
]
|
||||
|
||||
@ -468,7 +458,7 @@ dependencies = [
|
||||
"ethcore-util 1.5.0",
|
||||
"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)",
|
||||
"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]]
|
||||
@ -547,8 +537,10 @@ dependencies = [
|
||||
"jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||
"jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-updater 1.5.0",
|
||||
"rlp 0.1.0",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_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)",
|
||||
@ -590,7 +582,7 @@ dependencies = [
|
||||
"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)",
|
||||
"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]]
|
||||
@ -706,7 +698,7 @@ dependencies = [
|
||||
"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)",
|
||||
"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)",
|
||||
]
|
||||
|
||||
@ -795,6 +787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "https-fetch"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
||||
"rustls 0.1.2 (git+https://github.com/ctz/rustls)",
|
||||
@ -861,6 +854,17 @@ dependencies = [
|
||||
"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]]
|
||||
name = "isatty"
|
||||
version = "0.1.1"
|
||||
@ -1325,6 +1329,18 @@ dependencies = [
|
||||
"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]]
|
||||
name = "parity-rpc-client"
|
||||
version = "1.4.0"
|
||||
@ -1364,11 +1380,26 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "parity-ui-precompiled"
|
||||
version = "1.4.0"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git#2cdda91549dfeebd94775b348a443f8ee5446e9f"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git#3d390b35737ce212d358f26b5ec8d9644b252a88"
|
||||
dependencies = [
|
||||
"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]]
|
||||
name = "parking_lot"
|
||||
version = "0.2.8"
|
||||
@ -1698,6 +1729,23 @@ dependencies = [
|
||||
"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]]
|
||||
name = "serde"
|
||||
version = "0.8.4"
|
||||
@ -2271,6 +2319,8 @@ dependencies = [
|
||||
"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.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_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"
|
||||
|
15
Cargo.toml
15
Cargo.toml
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
description = "Ethcore client."
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity"
|
||||
version = "1.5.0"
|
||||
license = "GPL-3.0"
|
||||
@ -20,7 +20,7 @@ time = "0.1"
|
||||
num_cpus = "0.2"
|
||||
number_prefix = "0.2"
|
||||
rpassword = "0.2.1"
|
||||
semver = "0.2"
|
||||
semver = "0.5"
|
||||
ansi_term = "0.7"
|
||||
lazy_static = "0.2"
|
||||
regex = "0.1"
|
||||
@ -32,25 +32,26 @@ app_dirs = "1.1.1"
|
||||
hyper = { version = "0.9", default-features = false }
|
||||
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
|
||||
fdlimit = "0.1"
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
rlp = { path = "util/rlp" }
|
||||
ethsync = { path = "sync" }
|
||||
ethcore = { path = "ethcore" }
|
||||
ethcore-util = { path = "util" }
|
||||
ethsync = { path = "sync" }
|
||||
ethcore-io = { path = "util/io" }
|
||||
ethcore-devtools = { path = "devtools" }
|
||||
ethcore-rpc = { path = "rpc" }
|
||||
ethcore-signer = { path = "signer" }
|
||||
ethcore-ipc-nano = { path = "ipc/nano" }
|
||||
ethcore-ipc = { path = "ipc/rpc" }
|
||||
ethcore-ipc-nano = { path = "ipc/nano" }
|
||||
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
||||
ethcore-logger = { path = "logger" }
|
||||
ethcore-hash-fetch = { path = "ethcore/hash-fetch" }
|
||||
rlp = { path = "util/rlp" }
|
||||
ethcore-stratum = { path = "stratum" }
|
||||
ethcore-dapps = { path = "dapps", optional = true }
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
rpc-cli = { path = "rpc_cli" }
|
||||
parity-rpc-client = { path = "rpc_client" }
|
||||
ethcore-light = { path = "ethcore/light" }
|
||||
parity-hash-fetch = { path = "hash-fetch" }
|
||||
parity-updater = { path = "updater" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = "0.2"
|
||||
|
@ -30,9 +30,9 @@ zip = { version = "0.1", default-features = false }
|
||||
ethcore-devtools = { path = "../devtools" }
|
||||
ethcore-rpc = { path = "../rpc" }
|
||||
ethcore-util = { path = "../util" }
|
||||
ethcore-hash-fetch = { path = "../ethcore/hash-fetch" }
|
||||
fetch = { path = "../util/fetch" }
|
||||
parity-ui = { path = "./ui" }
|
||||
parity-hash-fetch = { path = "../hash-fetch" }
|
||||
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
|
||||
|
@ -57,7 +57,7 @@ extern crate mime_guess;
|
||||
extern crate rustc_serialize;
|
||||
extern crate ethcore_rpc;
|
||||
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 fetch;
|
||||
extern crate parity_dapps_glue as parity_dapps;
|
||||
|
@ -65,7 +65,7 @@ fn init_logger() {
|
||||
if let Ok(log) = env::var("RUST_LOG") {
|
||||
let mut builder = LogBuilder::new();
|
||||
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-ipc = { path = "../ipc/rpc" }
|
||||
rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" }
|
||||
semver = "0.2"
|
||||
semver = "0.5"
|
||||
ethcore-ipc-nano = { path = "../ipc/nano" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
crossbeam = "0.2"
|
||||
|
@ -270,8 +270,7 @@ impl DatabaseService for Database {
|
||||
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 iterator = match iterators.get_mut(&handle) {
|
||||
Some(some_iterator) => some_iterator,
|
||||
|
@ -21,7 +21,7 @@ crossbeam = "0.2.9"
|
||||
lazy_static = "0.2"
|
||||
bloomchain = "0.1"
|
||||
rayon = "0.4.2"
|
||||
semver = "0.2"
|
||||
semver = "0.5"
|
||||
bit-set = "0.4"
|
||||
time = "0.1"
|
||||
rand = "0.3"
|
||||
@ -42,6 +42,7 @@ ethcore-ipc-nano = { path = "../ipc/nano" }
|
||||
rlp = { path = "../util/rlp" }
|
||||
lru-cache = "0.1.0"
|
||||
ethcore-bloom-journal = { path = "../util/bloom" }
|
||||
ethabi = "0.2.2"
|
||||
|
||||
[dependencies.hyper]
|
||||
git = "https://github.com/ethcore/hyper"
|
||||
|
@ -15,7 +15,8 @@
|
||||
"eip155Transition": 10,
|
||||
"eip160Transition": 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
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::path::{Path};
|
||||
use std::fmt;
|
||||
@ -22,7 +24,7 @@ use std::time::{Instant};
|
||||
use time::precise_time_ns;
|
||||
|
||||
// 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::{U256, H256, Address, H2048, Uint, FixedHash};
|
||||
use util::trie::TrieSpec;
|
||||
@ -42,7 +44,7 @@ use env_info::LastHashes;
|
||||
use verification;
|
||||
use verification::{PreverifiedBlock, Verifier};
|
||||
use block::*;
|
||||
use transaction::{LocalizedTransaction, SignedTransaction, Action};
|
||||
use transaction::{LocalizedTransaction, SignedTransaction, Transaction, Action};
|
||||
use blockchain::extras::TransactionAddress;
|
||||
use types::filter::Filter;
|
||||
use types::mode::Mode as IpcMode;
|
||||
@ -68,6 +70,7 @@ use factory::Factories;
|
||||
use rlp::{decode, View, UntrustedRlp};
|
||||
use state_db::StateDB;
|
||||
use rand::OsRng;
|
||||
use client::registry::Registry;
|
||||
|
||||
// re-export
|
||||
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.
|
||||
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
|
||||
pub struct Client {
|
||||
enabled: AtomicBool,
|
||||
mode: Mutex<Mode>,
|
||||
chain: RwLock<Arc<BlockChain>>,
|
||||
tracedb: RwLock<TraceDB<BlockChain>>,
|
||||
@ -148,6 +152,7 @@ pub struct Client {
|
||||
history: u64,
|
||||
rng: Mutex<OsRng>,
|
||||
on_mode_change: Mutex<Option<Box<FnMut(&Mode) + 'static + Send>>>,
|
||||
registrar: Mutex<Option<Registry>>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
@ -160,6 +165,7 @@ impl Client {
|
||||
message_channel: IoChannel<ClientIoMessage>,
|
||||
db_config: &DatabaseConfig,
|
||||
) -> Result<Arc<Client>, ClientError> {
|
||||
|
||||
let path = path.to_path_buf();
|
||||
let gb = spec.genesis_block();
|
||||
|
||||
@ -221,7 +227,8 @@ impl Client {
|
||||
accountdb: Default::default(),
|
||||
};
|
||||
|
||||
let client = Client {
|
||||
let client = Arc::new(Client {
|
||||
enabled: AtomicBool::new(true),
|
||||
sleep_state: Mutex::new(SleepState::new(awake)),
|
||||
liveness: AtomicBool::new(awake),
|
||||
mode: Mutex::new(config.mode.clone()),
|
||||
@ -246,8 +253,15 @@ impl Client {
|
||||
history: history,
|
||||
rng: Mutex::new(try!(OsRng::new().map_err(::util::UtilError::StdIo))),
|
||||
on_mode_change: Mutex::new(None),
|
||||
};
|
||||
Ok(Arc::new(client))
|
||||
registrar: Mutex::new(None),
|
||||
});
|
||||
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
|
||||
@ -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.
|
||||
pub fn on_mode_change<F>(&self, f: F) where F: 'static + FnMut(&Mode) + Send {
|
||||
*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
|
||||
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 (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, is_empty) = {
|
||||
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
|
||||
@ -663,10 +688,17 @@ impl Client {
|
||||
/// Tick the client.
|
||||
// TODO: manage by real events.
|
||||
pub fn tick(&self) {
|
||||
self.check_garbage();
|
||||
self.check_snooze();
|
||||
}
|
||||
|
||||
fn check_garbage(&self) {
|
||||
self.chain.read().collect_garbage();
|
||||
self.block_queue.collect_garbage();
|
||||
self.tracedb.read().collect_garbage();
|
||||
}
|
||||
|
||||
fn check_snooze(&self) {
|
||||
let mode = self.mode.lock().clone();
|
||||
match mode {
|
||||
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.
|
||||
/// 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> {
|
||||
@ -908,8 +930,17 @@ impl BlockChainClient for Client {
|
||||
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) {
|
||||
trace!(target: "mode", "Client::set_mode({:?})", new_mode);
|
||||
if !self.enabled.load(AtomicOrdering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
let mut mode = self.mode.lock();
|
||||
*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))
|
||||
}
|
||||
|
||||
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> {
|
||||
let chain = self.chain.read();
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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 util::UtilError;
|
||||
use std::fmt::{Display, Formatter, Error as FmtError};
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
//! Blockchain database client.
|
||||
|
||||
mod registry;
|
||||
mod config;
|
||||
mod error;
|
||||
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()))
|
||||
}
|
||||
|
||||
fn block_number(&self, _id: BlockId) -> Option<BlockNumber> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn block_body(&self, id: BlockId) -> Option<Bytes> {
|
||||
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
@ -694,10 +698,18 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
|
||||
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
||||
|
||||
fn disable(&self) { unimplemented!(); }
|
||||
|
||||
fn pruning_info(&self) -> PruningInfo {
|
||||
PruningInfo {
|
||||
earliest_chain: 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.
|
||||
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.
|
||||
/// Block body is an RLP list of two items: uncles and transactions.
|
||||
fn block_body(&self, id: BlockId) -> Option<Bytes>;
|
||||
@ -255,6 +258,10 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// Set the 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`.
|
||||
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.
|
||||
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 { }
|
||||
|
@ -100,6 +100,7 @@ impl AsMillis for Duration {
|
||||
impl AuthorityRound {
|
||||
/// Create a new instance of AuthorityRound engine.
|
||||
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 engine = Arc::new(
|
||||
AuthorityRound {
|
||||
@ -113,18 +114,17 @@ impl AuthorityRound {
|
||||
account_provider: Mutex::new(None),
|
||||
password: RwLock::new(None),
|
||||
});
|
||||
// Do not initialize timeouts for tests.
|
||||
if should_timeout {
|
||||
let handler = TransitionHandler { engine: Arc::downgrade(&engine) };
|
||||
try!(engine.transition_service.register_handler(Arc::new(handler)));
|
||||
Ok(engine)
|
||||
}
|
||||
|
||||
fn step(&self) -> usize {
|
||||
self.step.load(AtomicOrdering::SeqCst)
|
||||
Ok(engine)
|
||||
}
|
||||
|
||||
fn remaining_step_duration(&self) -> Duration {
|
||||
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 {
|
||||
step_end - now
|
||||
} else {
|
||||
@ -228,7 +228,7 @@ impl Engine for AuthorityRound {
|
||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||
if self.proposed.load(AtomicOrdering::SeqCst) { return Seal::None; }
|
||||
let header = block.header();
|
||||
let step = self.step();
|
||||
let step = self.step.load(AtomicOrdering::SeqCst);
|
||||
if self.is_step_proposer(step, header.author()) {
|
||||
if let Some(ref ap) = *self.account_provider.lock() {
|
||||
// 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> {
|
||||
let header_step = try!(header_step(header));
|
||||
// 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 ok_sig = try!(verify_address(self.step_proposer(header_step), &proposer_signature, &header.bare_hash()));
|
||||
if ok_sig {
|
||||
|
@ -29,6 +29,12 @@ pub use self::denominations::*;
|
||||
|
||||
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 {
|
||||
Spec::load(b).expect("chain spec is invalid")
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ extern crate lru_cache;
|
||||
|
||||
#[cfg(feature = "jit" )]
|
||||
extern crate evmjit;
|
||||
extern crate ethabi;
|
||||
|
||||
pub extern crate ethstore;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
use util::{U256, H256};
|
||||
use header::BlockNumber;
|
||||
use types::security_level::SecurityLevel;
|
||||
|
||||
/// Information about the blockchain gathered together.
|
||||
#[derive(Clone, Debug, Binary)]
|
||||
@ -41,3 +42,15 @@ pub struct BlockChainInfo {
|
||||
/// Number of the first block on the best sequence.
|
||||
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"))
|
||||
}
|
||||
}
|
||||
}
|
@ -35,3 +35,4 @@ pub mod restoration_status;
|
||||
pub mod snapshot_manifest;
|
||||
pub mod mode;
|
||||
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."
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-hash-fetch"
|
||||
name = "parity-hash-fetch"
|
||||
version = "1.5.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
@ -11,5 +11,5 @@ log = "0.3"
|
||||
rustc-serialize = "0.3"
|
||||
ethabi = "0.2.2"
|
||||
mime_guess = "1.6.1"
|
||||
fetch = { path = "../../util/fetch" }
|
||||
ethcore-util = { path = "../../util" }
|
||||
fetch = { path = "../util/fetch" }
|
||||
ethcore-util = { path = "../util" }
|
@ -26,7 +26,7 @@ use fetch::{Fetch, FetchError, Client as FetchClient};
|
||||
use urlhint::{ContractClient, URLHintContract, URLHint, URLHintResult};
|
||||
|
||||
/// API for fetching by hash.
|
||||
pub trait HashFetch {
|
||||
pub trait HashFetch: Send + Sync + 'static {
|
||||
/// Fetch hash-addressed content.
|
||||
/// Parameters:
|
||||
/// 1. `hash` - content hash
|
||||
@ -42,7 +42,12 @@ pub enum Error {
|
||||
/// Hash could not be resolved to a valid content address.
|
||||
NoResolution,
|
||||
/// 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(io::Error),
|
||||
/// Error during fetch.
|
||||
@ -79,7 +84,7 @@ impl Client {
|
||||
|
||||
impl HashFetch for Client {
|
||||
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!(
|
||||
self.contract.resolve(hash.to_vec()).map(|content| match content {
|
||||
@ -92,7 +97,7 @@ impl HashFetch for Client {
|
||||
}).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| {
|
||||
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))
|
||||
})).map_err(Into::into)
|
||||
}
|
@ -30,4 +30,4 @@ mod client;
|
||||
|
||||
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 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() {
|
||||
"u8" => {
|
||||
@ -286,7 +286,6 @@ fn binary_expr_struct(
|
||||
post_write_stmts.push(quote_stmt!(cx,
|
||||
if $range_ident.end - $range_ident.start > 0 {
|
||||
if let Err(e) = $member_expr .to_bytes(&mut buffer[$range_ident], length_stack) {
|
||||
warn!(target: "ipc", $error_message_literal);
|
||||
return Err(e)
|
||||
};
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ build = "build.rs"
|
||||
ethcore-ipc = { path = "../rpc" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
ethcore-ipc-nano = { path = "../nano" }
|
||||
semver = "0.2"
|
||||
semver = "0.5"
|
||||
log = "0.3"
|
||||
time = "0.1"
|
||||
|
||||
|
@ -10,4 +10,4 @@ license = "GPL-3.0"
|
||||
ethcore-devtools = { path = "../../devtools" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
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!(Address);
|
||||
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]
|
||||
fn vec_serialize() {
|
||||
|
@ -24,4 +24,4 @@ extern crate ethcore_util as util;
|
||||
pub mod interface;
|
||||
pub mod binary;
|
||||
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]
|
||||
ethcore-ipc = { path = "../rpc" }
|
||||
ethcore-devtools = { path = "../../devtools" }
|
||||
semver = "0.2"
|
||||
semver = "0.5"
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
ethcore-ipc-nano = { path = "../nano" }
|
||||
ethcore-util = { path = "../../util" }
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "parity.js",
|
||||
"version": "0.2.127",
|
||||
"version": "0.2.128",
|
||||
"main": "release/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
"author": "Parity Team <admin@parity.io>",
|
||||
@ -36,7 +36,7 @@
|
||||
"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: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",
|
||||
"lint": "npm run lint:css && npm run lint:js",
|
||||
"lint:cached": "npm run lint:css && npm run lint:js:cached",
|
||||
|
@ -110,7 +110,8 @@ export function outPeers (peers) {
|
||||
return {
|
||||
active: outNumber(peers.active),
|
||||
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', () => {
|
||||
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),
|
||||
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));
|
||||
}
|
||||
|
||||
consensusCapability () {
|
||||
return this._transport
|
||||
.execute('parity_consensusCapability');
|
||||
}
|
||||
|
||||
dappsPort () {
|
||||
return this._transport
|
||||
.execute('parity_dappsPort')
|
||||
@ -90,6 +95,11 @@ export default class Parity {
|
||||
.execute('parity_enode');
|
||||
}
|
||||
|
||||
executeUpgrade () {
|
||||
return this._transport
|
||||
.execute('parity_executeUpgrade');
|
||||
}
|
||||
|
||||
extraData () {
|
||||
return this._transport
|
||||
.execute('parity_extraData');
|
||||
@ -243,6 +253,11 @@ export default class Parity {
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
releasesInfo () {
|
||||
return this._transport
|
||||
.execute('parity_releasesInfo');
|
||||
}
|
||||
|
||||
removeReservedPeer (encode) {
|
||||
return this._transport
|
||||
.execute('parity_removeReservedPeer', encode);
|
||||
@ -315,4 +330,14 @@ export default class Parity {
|
||||
.execute('parity_unsignedTransactionsCount')
|
||||
.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', () => {
|
||||
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) => {
|
||||
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: {
|
||||
desc: 'Returns the port the dapps are running on, error if not enabled',
|
||||
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: {
|
||||
desc: 'Returns currently set extra data',
|
||||
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: {
|
||||
desc: '?',
|
||||
params: [
|
||||
@ -651,5 +678,23 @@ export default {
|
||||
type: Quantity,
|
||||
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,12 +23,13 @@ import DeployContract from './DeployContract';
|
||||
import EditMeta from './EditMeta';
|
||||
import ExecuteContract from './ExecuteContract';
|
||||
import FirstRun from './FirstRun';
|
||||
import LoadContract from './LoadContract';
|
||||
import SaveContract from './SaveContract';
|
||||
import Shapeshift from './Shapeshift';
|
||||
import Verification from './Verification';
|
||||
import Transfer from './Transfer';
|
||||
import PasswordManager from './PasswordManager';
|
||||
import SaveContract from './SaveContract';
|
||||
import LoadContract from './LoadContract';
|
||||
import UpgradeParity from './UpgradeParity';
|
||||
import WalletSettings from './WalletSettings';
|
||||
|
||||
export {
|
||||
@ -41,11 +42,12 @@ export {
|
||||
EditMeta,
|
||||
ExecuteContract,
|
||||
FirstRun,
|
||||
LoadContract,
|
||||
SaveContract,
|
||||
Shapeshift,
|
||||
Verification,
|
||||
Transfer,
|
||||
PasswordManager,
|
||||
LoadContract,
|
||||
SaveContract,
|
||||
UpgradeParity,
|
||||
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 { nodeOrStringProptype } from '~/util/proptypes';
|
||||
|
||||
import styles from './busy.css';
|
||||
|
||||
export default class Busy extends Component {
|
||||
static propTypes = {
|
||||
title: PropTypes.string,
|
||||
state: PropTypes.string,
|
||||
children: PropTypes.node
|
||||
children: PropTypes.node,
|
||||
state: nodeOrStringProptype(),
|
||||
title: nodeOrStringProptype()
|
||||
}
|
||||
|
||||
render () {
|
||||
const { children, title, state } = this.props;
|
||||
const { children, state, title } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ styles.center }>
|
||||
|
@ -36,7 +36,13 @@ export default class Title extends Component {
|
||||
|
||||
return (
|
||||
<div className={ styles.title }>
|
||||
<h3>{ steps ? steps[current] : title }</h3>
|
||||
<h3>
|
||||
{
|
||||
steps
|
||||
? steps[current]
|
||||
: title
|
||||
}
|
||||
</h3>
|
||||
{ this.renderSteps() }
|
||||
{ this.renderWaiting() }
|
||||
</div>
|
||||
@ -63,10 +69,10 @@ export default class Title extends Component {
|
||||
renderTimeline () {
|
||||
const { steps } = this.props;
|
||||
|
||||
return steps.map((label) => {
|
||||
return steps.map((label, index) => {
|
||||
return (
|
||||
<Step
|
||||
key={ label }>
|
||||
key={ label.key || index }>
|
||||
<StepLabel>
|
||||
{ label }
|
||||
</StepLabel>
|
||||
|
@ -14,16 +14,17 @@
|
||||
/* You should have received a copy of the GNU General Public License
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.actions {
|
||||
background: rgba(0, 0, 0, 0.25) !important;
|
||||
}
|
||||
|
||||
.actions button:not([disabled]) {
|
||||
button:not([disabled]) {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.actions button:not([disabled]) svg {
|
||||
svg {
|
||||
fill: white !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
@ -36,26 +37,26 @@
|
||||
.content {
|
||||
transform: translate(0px, 0px) !important;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.content>div {
|
||||
&>div {
|
||||
background: rgba(0, 0, 0, 0.5) !important;
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
background: rgba(0, 0, 0, 0.25) !important;
|
||||
padding: 1em;
|
||||
margin-bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.25) !important;
|
||||
}
|
||||
|
||||
.title h3 {
|
||||
h3 {
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
.title .steps {
|
||||
.steps {
|
||||
margin-bottom: -1em;
|
||||
}
|
||||
}
|
||||
|
||||
.waiting {
|
||||
|
@ -14,10 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Dialog } from 'material-ui';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { Dialog } from 'material-ui';
|
||||
|
||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||
|
||||
@ -51,7 +51,7 @@ class Modal extends Component {
|
||||
|
||||
render () {
|
||||
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 header = (
|
||||
<Title
|
||||
|
@ -33,6 +33,7 @@ import Errors from './Errors';
|
||||
import Form, { AddressSelect, FormWrap, TypedInput, Input, InputAddress, InputAddressSelect, InputChip, InputInline, Select, RadioButtons } from './Form';
|
||||
import GasPriceEditor from './GasPriceEditor';
|
||||
import GasPriceSelector from './GasPriceSelector';
|
||||
import Icons from './Icons';
|
||||
import IdentityIcon from './IdentityIcon';
|
||||
import IdentityName from './IdentityName';
|
||||
import LanguageSelector from './LanguageSelector';
|
||||
@ -72,6 +73,7 @@ export {
|
||||
FormWrap,
|
||||
GasPriceEditor,
|
||||
GasPriceSelector,
|
||||
Icons,
|
||||
Input,
|
||||
InputAddress,
|
||||
InputAddressSelect,
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import { FirstRun } from '~/modals';
|
||||
import { FirstRun, UpgradeParity } from '~/modals';
|
||||
import { Errors, ParityBackground, Tooltips } from '~/ui';
|
||||
|
||||
import styles from '../application.css';
|
||||
@ -28,20 +28,24 @@ export default class Container extends Component {
|
||||
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
onCloseFirstRun: PropTypes.func,
|
||||
showFirstRun: PropTypes.bool,
|
||||
onCloseFirstRun: PropTypes.func
|
||||
upgradeStore: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
render () {
|
||||
const { children, showFirstRun, onCloseFirstRun } = this.props;
|
||||
const { muiTheme } = this.context;
|
||||
const { children, onCloseFirstRun, showFirstRun, upgradeStore } = this.props;
|
||||
|
||||
return (
|
||||
<ParityBackground className={ styles.container } muiTheme={ muiTheme }>
|
||||
<ParityBackground
|
||||
className={ styles.container }
|
||||
muiTheme={ muiTheme }>
|
||||
<FirstRun
|
||||
visible={ showFirstRun }
|
||||
onClose={ onCloseFirstRun } />
|
||||
onClose={ onCloseFirstRun }
|
||||
visible={ showFirstRun } />
|
||||
<Tooltips />
|
||||
<UpgradeParity store={ upgradeStore } />
|
||||
<Errors />
|
||||
{ children }
|
||||
</ParityBackground>
|
||||
|
@ -14,55 +14,52 @@
|
||||
/* You should have received a copy of the GNU General Public License
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.status {
|
||||
position: fixed;
|
||||
align-items: center;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
bottom: 0;
|
||||
color: #ccc;
|
||||
display: flex;
|
||||
font-size: 0.75em;
|
||||
left: 0;
|
||||
padding: .4em .5em;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
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 {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
color: #ddd;
|
||||
}
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
text-align: right;
|
||||
|
||||
.netinfo > * {
|
||||
div {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.network {
|
||||
padding: 0.25em 0.5em;
|
||||
border-radius: .4em;
|
||||
border-radius: 0.4em;
|
||||
line-height: 1.2;
|
||||
padding: 0.25em 0.5em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.networklive {
|
||||
&.live {
|
||||
background: rgb(0, 136, 0);
|
||||
}
|
||||
|
||||
&.test {
|
||||
background: rgb(136, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.networktest {
|
||||
background: rgb(136, 0, 0);
|
||||
.upgrade {
|
||||
div {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
@ -15,78 +15,118 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
import { BlockStatus } from '~/ui';
|
||||
import CopyToClipboard from '~/ui/CopyToClipboard';
|
||||
|
||||
import styles from './status.css';
|
||||
|
||||
class Status extends Component {
|
||||
static propTypes = {
|
||||
blockNumber: PropTypes.object.isRequired,
|
||||
clientVersion: PropTypes.string,
|
||||
enode: PropTypes.string,
|
||||
netPeers: PropTypes.object,
|
||||
isTest: PropTypes.bool,
|
||||
netChain: PropTypes.string,
|
||||
isTest: PropTypes.bool
|
||||
netPeers: PropTypes.object,
|
||||
upgradeStore: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
render () {
|
||||
const { blockNumber, clientVersion, netChain, netPeers, isTest } = this.props;
|
||||
const netStyle = `${styles.network} ${styles[isTest ? 'networktest' : 'networklive']}`;
|
||||
|
||||
if (!blockNumber) {
|
||||
return null;
|
||||
}
|
||||
const { clientVersion, isTest, netChain, netPeers } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ styles.status }>
|
||||
<div className={ styles.version }>
|
||||
{ clientVersion }
|
||||
</div>
|
||||
<div className={ styles.upgrade }>
|
||||
{ this.renderConsensus() }
|
||||
{ this.renderUpgradeButton() }
|
||||
</div>
|
||||
<div className={ styles.netinfo }>
|
||||
<BlockStatus />
|
||||
<div className={ netStyle }>
|
||||
{ isTest ? 'test' : netChain }
|
||||
<div className={ `${styles.network} ${styles[isTest ? 'test' : 'live']}` }>
|
||||
{ netChain }
|
||||
</div>
|
||||
<div className={ styles.peers }>
|
||||
{ netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
|
||||
</div>
|
||||
</div>
|
||||
{ this.renderEnode() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderEnode () {
|
||||
const { enode } = this.props;
|
||||
renderConsensus () {
|
||||
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;
|
||||
}
|
||||
|
||||
const [protocol, rest] = enode.split('://');
|
||||
const [id, host] = rest.split('@');
|
||||
const abbreviated = `${protocol}://${id.slice(0, 3)}…${id.slice(-3)}@${host}`;
|
||||
|
||||
return (
|
||||
<div className={ styles.enode }>
|
||||
<CopyToClipboard data={ enode } size={ 12 } />
|
||||
<div>{ abbreviated }</div>
|
||||
<div>
|
||||
<a
|
||||
href='javascript:void(0)'
|
||||
onClick={ upgradeStore.openModal }>
|
||||
<FormattedMessage
|
||||
id='application.status.upgrade'
|
||||
defaultMessage='Upgrade' />
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const { blockNumber, clientVersion, enode, netPeers, netChain, isTest } = state.nodeStatus;
|
||||
const { clientVersion, netPeers, netChain, isTest } = state.nodeStatus;
|
||||
|
||||
return {
|
||||
blockNumber,
|
||||
clientVersion,
|
||||
enode,
|
||||
netPeers,
|
||||
netChain,
|
||||
isTest
|
||||
|
@ -22,5 +22,5 @@
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-bottom: 1em;
|
||||
padding-bottom: 1.25em;
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import UpgradeStore from '~/modals/UpgradeParity/store';
|
||||
|
||||
import Connection from '../Connection';
|
||||
import ParityBar from '../ParityBar';
|
||||
|
||||
@ -42,14 +44,15 @@ class Application extends Component {
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
blockNumber: PropTypes.object,
|
||||
children: PropTypes.node,
|
||||
netChain: PropTypes.string,
|
||||
isTest: PropTypes.bool,
|
||||
pending: PropTypes.array,
|
||||
blockNumber: PropTypes.object
|
||||
netChain: PropTypes.string,
|
||||
pending: PropTypes.array
|
||||
}
|
||||
|
||||
store = new Store(this.context.api);
|
||||
upgradeStore = new UpgradeStore(this.context.api);
|
||||
|
||||
render () {
|
||||
const [root] = (window.location.hash || '').replace('#/', '').split('/');
|
||||
@ -71,12 +74,13 @@ class Application extends Component {
|
||||
}
|
||||
|
||||
renderApp () {
|
||||
const { children, pending, netChain, isTest, blockNumber } = this.props;
|
||||
const { blockNumber, children, pending, netChain, isTest } = this.props;
|
||||
|
||||
return (
|
||||
<Container
|
||||
showFirstRun={ this.store.firstrunVisible }
|
||||
onCloseFirstRun={ this.store.closeFirstrun }>
|
||||
upgradeStore={ this.upgradeStore }
|
||||
onCloseFirstRun={ this.store.closeFirstrun }
|
||||
showFirstRun={ this.store.firstrunVisible }>
|
||||
<TabBar
|
||||
netChain={ netChain }
|
||||
isTest={ isTest }
|
||||
@ -84,7 +88,11 @@ class Application extends Component {
|
||||
<div className={ styles.content }>
|
||||
{ children }
|
||||
</div>
|
||||
{ blockNumber ? (<Status />) : null }
|
||||
{
|
||||
blockNumber
|
||||
? <Status upgradeStore={ this.upgradeStore } />
|
||||
: null
|
||||
}
|
||||
<Snackbar />
|
||||
</Container>
|
||||
);
|
||||
@ -102,16 +110,16 @@ class Application extends Component {
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const { netChain, isTest, blockNumber } = state.nodeStatus;
|
||||
const { blockNumber, netChain, isTest } = state.nodeStatus;
|
||||
const { hasAccounts } = state.personal;
|
||||
const { pending } = state.signer;
|
||||
|
||||
return {
|
||||
blockNumber,
|
||||
hasAccounts,
|
||||
netChain,
|
||||
isTest,
|
||||
pending,
|
||||
blockNumber
|
||||
netChain,
|
||||
pending
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,12 @@
|
||||
|
||||
.row {
|
||||
margin: 0 -1em;
|
||||
}
|
||||
|
||||
.row::after {
|
||||
&::after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.blockInfo {
|
||||
@ -44,7 +44,7 @@
|
||||
}
|
||||
|
||||
.col,
|
||||
.col1, .col2, .col3, .col4, .col5, .col6, .col7, .col8, .col9, .col10, .col11, .col12 {
|
||||
.col3, .col4_5, .col6, .col12 {
|
||||
float: left;
|
||||
padding: 0 1em;
|
||||
box-sizing: border-box;
|
||||
@ -57,18 +57,11 @@
|
||||
width: calc(100% / 12 * 3);
|
||||
}
|
||||
|
||||
.col4 {
|
||||
width: 33.33333%;
|
||||
width: -webkit-calc(100% / 12 * 4);
|
||||
width: -moz-calc(100% / 12 * 4);
|
||||
width: calc(100% / 12 * 4);
|
||||
}
|
||||
|
||||
.col5 {
|
||||
width: 41.66665%;
|
||||
width: -webkit-calc(100% / 12 * 5);
|
||||
width: -moz-calc(100% / 12 * 5);
|
||||
width: calc(100% / 12 * 5);
|
||||
.col4_5 {
|
||||
width: 37.5%;
|
||||
width: -webkit-calc(100% / 12 * 4.5);
|
||||
width: -moz-calc(100% / 12 * 4.5);
|
||||
width: calc(100% / 12 * 4.5);
|
||||
}
|
||||
|
||||
.col6 {
|
||||
|
@ -68,13 +68,13 @@ export default class Status extends Component {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={ styles.col5 }>
|
||||
<div className={ styles.col4_5 }>
|
||||
<MiningSettings
|
||||
{ ...this._test('mining') }
|
||||
nodeStatus={ nodeStatus }
|
||||
actions={ this.props.actions } />
|
||||
</div>
|
||||
<div className={ styles.col4 }>
|
||||
<div className={ styles.col4_5 }>
|
||||
{ this.renderSettings() }
|
||||
</div>
|
||||
</div>
|
||||
@ -102,6 +102,7 @@ export default class Status extends Component {
|
||||
<div { ...this._test('settings') }>
|
||||
<ContainerTitle title='network settings' />
|
||||
<Input
|
||||
allowCopy
|
||||
readOnly
|
||||
label='chain'
|
||||
value={ nodeStatus.netChain }
|
||||
@ -109,6 +110,7 @@ export default class Status extends Component {
|
||||
<div className={ styles.row }>
|
||||
<div className={ styles.col6 }>
|
||||
<Input
|
||||
allowCopy
|
||||
readOnly
|
||||
label='peers'
|
||||
value={ peers }
|
||||
@ -116,6 +118,7 @@ export default class Status extends Component {
|
||||
</div>
|
||||
<div className={ styles.col6 }>
|
||||
<Input
|
||||
allowCopy
|
||||
readOnly
|
||||
label='network port'
|
||||
value={ nodeStatus.netPort.toString() }
|
||||
@ -124,6 +127,7 @@ export default class Status extends Component {
|
||||
</div>
|
||||
|
||||
<Input
|
||||
allowCopy
|
||||
readOnly
|
||||
label='rpc enabled'
|
||||
value={ rpcSettings.enabled ? 'yes' : 'no' }
|
||||
@ -131,6 +135,7 @@ export default class Status extends Component {
|
||||
<div className={ styles.row }>
|
||||
<div className={ styles.col6 }>
|
||||
<Input
|
||||
allowCopy
|
||||
readOnly
|
||||
label='rpc interface'
|
||||
value={ rpcSettings.interface }
|
||||
@ -138,12 +143,24 @@ export default class Status extends Component {
|
||||
</div>
|
||||
<div className={ styles.col6 }>
|
||||
<Input
|
||||
allowCopy
|
||||
readOnly
|
||||
label='rpc port'
|
||||
value={ rpcSettings.port.toString() }
|
||||
{ ...this._test('rpc-port') } />
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
@ -27,12 +27,12 @@ extern crate time;
|
||||
extern crate lazy_static;
|
||||
|
||||
use std::{env, thread, fs};
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Weak, Arc};
|
||||
use std::io::Write;
|
||||
use isatty::{stderr_isatty, stdout_isatty};
|
||||
use env_logger::LogBuilder;
|
||||
use regex::Regex;
|
||||
use util::RotatingLogger;
|
||||
use util::{Mutex, RotatingLogger} ;
|
||||
use util::log::Colour;
|
||||
|
||||
#[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
|
||||
pub fn setup_log(config: &Config) -> Result<Arc<RotatingLogger>, String> {
|
||||
use rlog::*;
|
||||
@ -121,9 +125,17 @@ pub fn setup_log(config: &Config) -> Result<Arc<RotatingLogger>, String> {
|
||||
};
|
||||
|
||||
builder.format(format);
|
||||
builder.init().expect("Logger initialized only once.");
|
||||
|
||||
builder.init()
|
||||
.and_then(|_| {
|
||||
*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 {
|
||||
|
@ -32,7 +32,6 @@ use ethcore::verification::queue::VerifierSettings;
|
||||
use cache::CacheConfig;
|
||||
use informant::{Informant, MillisecondDuration};
|
||||
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 dir::Directories;
|
||||
use user_defaults::UserDefaults;
|
||||
@ -134,7 +133,7 @@ pub struct ExportState {
|
||||
pub max_balance: Option<U256>,
|
||||
}
|
||||
|
||||
pub fn execute(cmd: BlockchainCmd) -> Result<String, String> {
|
||||
pub fn execute(cmd: BlockchainCmd) -> Result<(), String> {
|
||||
match cmd {
|
||||
BlockchainCmd::Kill(kill_cmd) => kill_db(kill_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();
|
||||
|
||||
// Setup panic handler
|
||||
@ -180,7 +179,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
try!(service.register_io_handler(Arc::new(ImportIoHandler {
|
||||
info: Arc::new(informant),
|
||||
})).map_err(|_| "Unable to register informant handler".to_owned()));
|
||||
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())?;
|
||||
|
||||
let do_import = |bytes| {
|
||||
while client.queue_info().is_full() { sleep(Duration::from_secs(1)); }
|
||||
@ -259,7 +255,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
|
||||
match format {
|
||||
DataFormat::Binary => {
|
||||
loop {
|
||||
@ -298,7 +293,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
let report = client.report();
|
||||
|
||||
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,
|
||||
report.blocks_imported,
|
||||
(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.gas_processed / From::from(1_000_000),
|
||||
(report.gas_processed / From::from(ms * 1000)).low_u64(),
|
||||
).into())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start_client(
|
||||
@ -318,7 +314,8 @@ fn start_client(
|
||||
fat_db: Switch,
|
||||
compaction: DatabaseCompactionProfile,
|
||||
wal: bool,
|
||||
cache_config: CacheConfig) -> Result<ClientService, String> {
|
||||
cache_config: CacheConfig
|
||||
) -> Result<ClientService, String> {
|
||||
|
||||
// load spec file
|
||||
let spec = try!(spec.spec());
|
||||
@ -351,7 +348,7 @@ fn start_client(
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// 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
|
||||
try!(dirs.create_dirs(false, false));
|
||||
@ -372,7 +369,7 @@ fn start_client(
|
||||
Ok(service)
|
||||
}
|
||||
|
||||
fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
|
||||
fn execute_export(cmd: ExportBlockchain) -> Result<(), String> {
|
||||
// Setup panic handler
|
||||
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
@ -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
|
||||
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();
|
||||
@ -479,10 +477,11 @@ fn execute_export_state(cmd: ExportState) -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
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 genesis_hash = spec.genesis_header().hash();
|
||||
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 dir = db_dirs.db_path(algorithm);
|
||||
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)]
|
||||
|
@ -2,8 +2,14 @@
|
||||
mode = "last"
|
||||
mode_timeout = 300
|
||||
mode_alarm = 3600
|
||||
auto_update = "critical"
|
||||
release_track = "current"
|
||||
no_download = false
|
||||
no_consensus = false
|
||||
|
||||
chain = "homestead"
|
||||
db_path = "$HOME/.parity"
|
||||
base_path = "$HOME/.parity"
|
||||
db_path = "$HOME/.parity/chains"
|
||||
keys_path = "$HOME/.parity/keys"
|
||||
identity = ""
|
||||
|
||||
|
@ -85,9 +85,14 @@ usage! {
|
||||
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_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_db_path: String = default_data_path(), or |c: &Config| otry!(c.parity).db_path.clone(),
|
||||
flag_keys_path: String = "$DATA/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
|
||||
flag_base_path: String = default_data_path(), or |c: &Config| otry!(c.parity).base_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(),
|
||||
|
||||
// -- Account Options
|
||||
@ -106,7 +111,7 @@ usage! {
|
||||
or |c: &Config| otry!(c.ui).port.clone(),
|
||||
flag_ui_interface: String = "local",
|
||||
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(),
|
||||
// NOTE [todr] For security reasons don't put this to config files
|
||||
flag_ui_no_validation: bool = false, or |_| None,
|
||||
@ -162,7 +167,7 @@ usage! {
|
||||
// IPC
|
||||
flag_no_ipc: bool = false,
|
||||
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(),
|
||||
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
|
||||
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(),
|
||||
flag_dapps_hosts: String = "none",
|
||||
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(),
|
||||
flag_dapps_user: Option<String> = None,
|
||||
or |c: &Config| otry!(c.dapps).user.clone().map(Some),
|
||||
@ -277,7 +282,7 @@ usage! {
|
||||
or |c: &Config| otry!(c.vm).jit.clone(),
|
||||
|
||||
// -- Miscellaneous Options
|
||||
flag_config: String = "$DATA/config.toml", or |_| None,
|
||||
flag_config: String = "$BASE/config.toml", or |_| None,
|
||||
flag_logging: Option<String> = None,
|
||||
or |c: &Config| otry!(c.misc).logging.clone().map(Some),
|
||||
flag_log_file: Option<String> = None,
|
||||
@ -309,7 +314,12 @@ struct Operating {
|
||||
mode: Option<String>,
|
||||
mode_timeout: 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>,
|
||||
base_path: Option<String>,
|
||||
db_path: Option<String>,
|
||||
keys_path: Option<String>,
|
||||
identity: Option<String>,
|
||||
@ -533,8 +543,13 @@ mod tests {
|
||||
flag_mode: "last".into(),
|
||||
flag_mode_timeout: 300u64,
|
||||
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_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_identity: "".into(),
|
||||
|
||||
@ -676,7 +691,7 @@ mod tests {
|
||||
|
||||
// -- Miscellaneous Options
|
||||
flag_version: false,
|
||||
flag_config: "$DATA/config.toml".into(),
|
||||
flag_config: "$BASE/config.toml".into(),
|
||||
flag_logging: Some("own_tx=trace".into()),
|
||||
flag_log_file: Some("/var/log/parity.log".into()),
|
||||
flag_no_color: false,
|
||||
@ -707,7 +722,12 @@ mod tests {
|
||||
mode: Some("dark".into()),
|
||||
mode_timeout: Some(15u64),
|
||||
mode_alarm: Some(10u64),
|
||||
auto_update: None,
|
||||
release_track: None,
|
||||
no_download: None,
|
||||
no_consensus: None,
|
||||
chain: Some("./chain.json".into()),
|
||||
base_path: None,
|
||||
db_path: None,
|
||||
keys_path: None,
|
||||
identity: None,
|
||||
|
@ -34,11 +34,34 @@ Operating Options:
|
||||
--mode-alarm SECS Specify the number of seconds before auto sleep
|
||||
reawake timeout occurs when mode is passive
|
||||
(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
|
||||
JSON chain specification file or olympic, frontier,
|
||||
homestead, mainnet, morden, ropsten, classic, expanse,
|
||||
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}).
|
||||
--keys-path PATH Specify the path for JSON key files to be found
|
||||
(default: {flag_keys_path}).
|
||||
@ -339,6 +362,9 @@ Legacy Options:
|
||||
--extradata STRING Equivalent to --extra-data STRING.
|
||||
--cache MB Equivalent to --cache-size MB.
|
||||
|
||||
Internal Options:
|
||||
--can-restart Executable will auto-restart if exiting with 69.
|
||||
|
||||
Miscellaneous Options:
|
||||
-c --config CONFIG Specify a filename containing a configuration file.
|
||||
(default: {flag_config})
|
||||
|
@ -23,7 +23,7 @@ use cli::{Args, ArgsError};
|
||||
use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address};
|
||||
use util::log::Colour;
|
||||
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
|
||||
use ethcore::client::VMType;
|
||||
use ethcore::client::{VMType};
|
||||
use ethcore::miner::{MinerOptions, Banning};
|
||||
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};
|
||||
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras};
|
||||
use ethcore_logger::Config as LogConfig;
|
||||
use dir::Directories;
|
||||
use dir::{Directories, default_hypervisor_path};
|
||||
use dapps::Configuration as DappsConfiguration;
|
||||
use signer::{Configuration as SignerConfiguration};
|
||||
use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack};
|
||||
use run::RunCmd;
|
||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat};
|
||||
use presale::ImportWallet;
|
||||
@ -99,6 +100,7 @@ impl Configuration {
|
||||
let pruning_history = self.args.flag_pruning_history;
|
||||
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 update_policy = try!(self.update_policy());
|
||||
let miner_options = try!(self.miner_options());
|
||||
let logger_config = self.logger_config();
|
||||
let http_conf = try!(self.http_config());
|
||||
@ -320,6 +322,7 @@ impl Configuration {
|
||||
acc_conf: try!(self.accounts_config()),
|
||||
gas_pricer: try!(self.gas_pricer_config()),
|
||||
miner_extras: try!(self.miner_extras()),
|
||||
update_policy: update_policy,
|
||||
mode: mode,
|
||||
tracing: tracing,
|
||||
fat_db: fat_db,
|
||||
@ -589,7 +592,7 @@ impl Configuration {
|
||||
ret.snapshot_peers = self.snapshot_peers();
|
||||
ret.allow_ips = try!(self.allow_ips());
|
||||
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");
|
||||
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
|
||||
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 {
|
||||
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 dapps_path = replace_home(&data_path, &self.args.flag_dapps_path);
|
||||
let ui_path = replace_home(&data_path, &self.args.flag_ui_path);
|
||||
@ -706,7 +732,8 @@ impl Configuration {
|
||||
|
||||
Directories {
|
||||
keys: keys_path,
|
||||
data: data_path,
|
||||
base: data_path,
|
||||
db: db_path,
|
||||
dapps: dapps_path,
|
||||
signer: ui_path,
|
||||
}
|
||||
@ -716,7 +743,7 @@ impl Configuration {
|
||||
if self.args.flag_geth {
|
||||
geth_ipc_path(self.args.flag_testnet)
|
||||
} 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 helpers::{default_network_config};
|
||||
use run::RunCmd;
|
||||
use dir::Directories;
|
||||
use dir::{Directories, default_hypervisor_path};
|
||||
use signer::{Configuration as SignerConfiguration};
|
||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat, ExportState};
|
||||
use presale::ImportWallet;
|
||||
use params::SpecType;
|
||||
use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts};
|
||||
use devtools::{RandomTempPath};
|
||||
use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack};
|
||||
use std::io::Write;
|
||||
use std::fs::{File, create_dir};
|
||||
|
||||
@ -986,6 +1014,7 @@ mod tests {
|
||||
acc_conf: Default::default(),
|
||||
gas_pricer: 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(),
|
||||
tracing: Default::default(),
|
||||
compaction: Default::default(),
|
||||
@ -1029,6 +1058,21 @@ mod tests {
|
||||
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]
|
||||
fn should_parse_network_settings() {
|
||||
// given
|
||||
|
@ -43,7 +43,7 @@ impl Default for Configuration {
|
||||
hosts: Some(Vec::new()),
|
||||
user: 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)]
|
||||
pub struct Directories {
|
||||
pub data: String,
|
||||
pub base: String,
|
||||
pub db: String,
|
||||
pub keys: String,
|
||||
pub signer: String,
|
||||
pub dapps: String,
|
||||
@ -37,17 +38,19 @@ impl Default for Directories {
|
||||
fn default() -> Self {
|
||||
let data_dir = default_data_path();
|
||||
Directories {
|
||||
data: replace_home(&data_dir, "$DATA"),
|
||||
keys: replace_home(&data_dir, "$DATA/keys"),
|
||||
signer: replace_home(&data_dir, "$DATA/signer"),
|
||||
dapps: replace_home(&data_dir, "$DATA/dapps"),
|
||||
base: replace_home(&data_dir, "$BASE"),
|
||||
db: replace_home(&data_dir, "$BASE/chains"),
|
||||
keys: replace_home(&data_dir, "$BASE/keys"),
|
||||
signer: replace_home(&data_dir, "$BASE/signer"),
|
||||
dapps: replace_home(&data_dir, "$BASE/dapps"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Directories {
|
||||
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()));
|
||||
if signer_enabled {
|
||||
try!(fs::create_dir_all(&self.signer).map_err(|e| e.to_string()));
|
||||
@ -61,7 +64,8 @@ impl Directories {
|
||||
/// Database paths.
|
||||
pub fn database(&self, genesis_hash: H256, fork_name: Option<String>, spec_name: String) -> DatabaseDirectories {
|
||||
DatabaseDirectories {
|
||||
path: self.data.clone(),
|
||||
path: self.db.clone(),
|
||||
legacy_path: self.base.clone(),
|
||||
genesis_hash: genesis_hash,
|
||||
fork_name: fork_name,
|
||||
spec_name: spec_name,
|
||||
@ -70,14 +74,14 @@ impl Directories {
|
||||
|
||||
/// Get the ipc sockets path
|
||||
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
|
||||
}
|
||||
|
||||
// TODO: remove in 1.7
|
||||
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 {
|
||||
dir.push("testnet_keys");
|
||||
} else {
|
||||
@ -96,6 +100,7 @@ impl Directories {
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct DatabaseDirectories {
|
||||
pub path: String,
|
||||
pub legacy_path: String,
|
||||
pub genesis_hash: H256,
|
||||
pub fork_name: Option<String>,
|
||||
pub spec_name: String,
|
||||
@ -105,14 +110,13 @@ impl DatabaseDirectories {
|
||||
/// Base DB directory for the given fork.
|
||||
// TODO: remove in 1.7
|
||||
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
|
||||
}
|
||||
|
||||
pub fn spec_root_path(&self) -> PathBuf {
|
||||
let mut dir = Path::new(&self.path).to_path_buf();
|
||||
dir.push("chains");
|
||||
dir.push(&self.spec_name);
|
||||
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())
|
||||
}
|
||||
|
||||
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)]
|
||||
mod tests {
|
||||
use super::Directories;
|
||||
@ -204,10 +213,11 @@ mod tests {
|
||||
fn test_default_directories() {
|
||||
let data_dir = super::default_data_path();
|
||||
let expected = Directories {
|
||||
data: replace_home(&data_dir, "$DATA"),
|
||||
keys: replace_home(&data_dir, "$DATA/keys"),
|
||||
signer: replace_home(&data_dir, "$DATA/signer"),
|
||||
dapps: replace_home(&data_dir, "$DATA/dapps"),
|
||||
base: replace_home(&data_dir, "$BASE"),
|
||||
db: replace_home(&data_dir, "$BASE/chains"),
|
||||
keys: replace_home(&data_dir, "$BASE/keys"),
|
||||
signer: replace_home(&data_dir, "$BASE/signer"),
|
||||
dapps: replace_home(&data_dir, "$BASE/dapps"),
|
||||
};
|
||||
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 {
|
||||
// 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 = r.replace("$DATA", base );
|
||||
let r = r.replace("$BASE", base );
|
||||
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 {
|
||||
use ethsync::{NetworkConfiguration, AllowIP};
|
||||
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,
|
||||
listen_address: Some("0.0.0.0:30303".into()),
|
||||
public_address: None,
|
||||
@ -257,12 +257,13 @@ pub fn to_client_config(
|
||||
}
|
||||
|
||||
pub fn execute_upgrades(
|
||||
base_path: &str,
|
||||
dirs: &DatabaseDirectories,
|
||||
pruning: Algorithm,
|
||||
compaction_profile: CompactionProfile
|
||||
) -> Result<(), String> {
|
||||
|
||||
upgrade_data_paths(dirs, pruning);
|
||||
upgrade_data_paths(base_path, dirs, pruning);
|
||||
|
||||
match upgrade(Some(&dirs.path)) {
|
||||
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 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 io::{TimerToken, IoContext, IoHandler};
|
||||
use isatty::{stdout_isatty};
|
||||
use ethsync::{SyncProvider, ManageNetwork};
|
||||
use util::{Uint, RwLock, Mutex, H256, Colour, Bytes};
|
||||
use ethcore::client::*;
|
||||
use ethcore::service::ClientIoMessage;
|
||||
use ethcore::views::BlockView;
|
||||
use ethcore::snapshot::service::Service as SnapshotService;
|
||||
use ethcore::snapshot::{RestorationStatus, SnapshotService as SS};
|
||||
@ -44,6 +46,7 @@ pub struct Informant {
|
||||
last_import: Mutex<Instant>,
|
||||
skipped: AtomicUsize,
|
||||
skipped_txs: AtomicUsize,
|
||||
in_shutdown: AtomicBool,
|
||||
}
|
||||
|
||||
/// Format byte counts to standard denominations.
|
||||
@ -82,9 +85,14 @@ impl Informant {
|
||||
last_import: Mutex::new(Instant::now()),
|
||||
skipped: 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))]
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
181
parity/main.rs
181
parity/main.rs
@ -42,13 +42,14 @@ extern crate ethcore_ipc_nano as nanoipc;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate rlp;
|
||||
extern crate ethcore_hash_fetch as hash_fetch;
|
||||
extern crate ethcore_light as light;
|
||||
extern crate parity_hash_fetch as hash_fetch;
|
||||
|
||||
extern crate ethcore_ipc_hypervisor as hypervisor;
|
||||
extern crate ethcore_rpc;
|
||||
|
||||
extern crate ethcore_signer;
|
||||
extern crate parity_updater as updater;
|
||||
extern crate ansi_term;
|
||||
|
||||
extern crate regex;
|
||||
@ -90,7 +91,6 @@ mod upgrade;
|
||||
mod rpc;
|
||||
mod dapps;
|
||||
mod informant;
|
||||
mod io_handler;
|
||||
mod cli;
|
||||
mod configuration;
|
||||
mod migration;
|
||||
@ -117,13 +117,16 @@ mod user_defaults;
|
||||
mod stratum;
|
||||
|
||||
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::path::PathBuf;
|
||||
use util::sha3::sha3;
|
||||
use cli::Args;
|
||||
use configuration::{Cmd, Execute, Configuration};
|
||||
use deprecated::find_deprecated;
|
||||
use ethcore_logger::setup_log;
|
||||
use dir::default_hypervisor_path;
|
||||
|
||||
fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
|
||||
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");
|
||||
|
||||
match command.cmd {
|
||||
Cmd::Run(run_cmd) => {
|
||||
try!(run::execute(run_cmd, logger));
|
||||
Ok("".into())
|
||||
let restart = run::execute(run_cmd, can_restart, logger)?;
|
||||
Ok(if restart { PostExecutionAction::Restart } else { PostExecutionAction::Quit })
|
||||
},
|
||||
Cmd::Version => Ok(Args::print_version()),
|
||||
Cmd::Hash(maybe_file) => print_hash_of(maybe_file),
|
||||
Cmd::Account(account_cmd) => account::execute(account_cmd),
|
||||
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd),
|
||||
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd),
|
||||
Cmd::SignerToken(signer_cmd) => signer::execute(signer_cmd),
|
||||
Cmd::SignerSign { id, pwfile, port, authfile } =>
|
||||
rpc_cli::cmd_signer_sign(id, pwfile, port, authfile),
|
||||
Cmd::SignerList { port, authfile } =>
|
||||
rpc_cli::cmd_signer_list(port, authfile),
|
||||
Cmd::SignerReject { id, port, authfile } =>
|
||||
rpc_cli::cmd_signer_reject(id, port, authfile),
|
||||
Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd),
|
||||
Cmd::Version => Ok(PostExecutionAction::Print(Args::print_version())),
|
||||
Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| PostExecutionAction::Print(s)),
|
||||
Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd).map(|_| PostExecutionAction::Quit),
|
||||
Cmd::SignerToken(signer_cmd) => signer::execute(signer_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||
Cmd::SignerSign { id, pwfile, port, authfile } => rpc_cli::signer_sign(id, pwfile, port, authfile).map(|s| PostExecutionAction::Print(s)),
|
||||
Cmd::SignerList { port, authfile } => rpc_cli::signer_list(port, authfile).map(|s| PostExecutionAction::Print(s)),
|
||||
Cmd::SignerReject { id, port, authfile } => rpc_cli::signer_reject(id, port, authfile).map(|s| PostExecutionAction::Print(s)),
|
||||
Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd).map(|s| PostExecutionAction::Print(s)),
|
||||
}
|
||||
}
|
||||
|
||||
fn start() -> Result<String, String> {
|
||||
fn start(can_restart: bool) -> Result<PostExecutionAction, String> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
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());
|
||||
execute(cmd)
|
||||
}
|
||||
|
||||
#[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 }
|
||||
}
|
||||
execute(cmd, can_restart)
|
||||
}
|
||||
|
||||
#[cfg(not(feature="stratum"))]
|
||||
mod stratum_optional {
|
||||
pub fn probably_run() -> bool {
|
||||
false
|
||||
}
|
||||
fn stratum_main(_: &mut HashMap<String, fn()>) {}
|
||||
|
||||
#[cfg(feature="stratum")]
|
||||
fn stratum_main(alt_mains: &mut HashMap<String, fn()>) {
|
||||
alt_mains.insert("stratum".to_owned(), stratum::main);
|
||||
}
|
||||
|
||||
#[cfg(not(feature="ipc"))]
|
||||
fn sync_main() -> bool {
|
||||
false
|
||||
}
|
||||
fn sync_main(_: &mut HashMap<String, fn()>) {}
|
||||
|
||||
#[cfg(feature="ipc")]
|
||||
fn sync_main() -> bool {
|
||||
// just redirect to the sync::main()
|
||||
if std::env::args().nth(1).map_or(false, |arg| arg == "sync") {
|
||||
sync::main();
|
||||
true
|
||||
fn sync_main(alt_mains: &mut HashMap<String, fn()>) {
|
||||
alt_mains.insert("sync".to_owned(), sync::main);
|
||||
}
|
||||
|
||||
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 {
|
||||
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() {
|
||||
// Always print backtrace on panic.
|
||||
::std::env::set_var("RUST_BACKTRACE", "1");
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
|
||||
if sync_main() {
|
||||
return;
|
||||
// assuming the user is not running with `--force-direct`, then:
|
||||
// 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();
|
||||
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);
|
||||
let latest_exe = latest_exe_path();
|
||||
let have_update = latest_exe.as_ref().map_or(false, |p| p.exists());
|
||||
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);
|
||||
if !force_direct && !development && same_name && have_update && is_non_updated_current {
|
||||
// looks like we're not running ~/.parity-updates/parity when the user is expecting otherwise.
|
||||
// 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);
|
||||
}
|
||||
|
||||
if stratum_optional::probably_run() { return; }
|
||||
|
||||
match start() {
|
||||
Ok(result) => {
|
||||
info!("{}", result);
|
||||
},
|
||||
Err(err) => {
|
||||
writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed");
|
||||
process::exit(1);
|
||||
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();
|
||||
IpcConfiguration {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ use ethcore::snapshot::SnapshotService;
|
||||
use ethsync::{ManageNetwork, SyncProvider};
|
||||
use ethcore_rpc::{Extendable, NetworkSettings};
|
||||
pub use ethcore_rpc::SignerService;
|
||||
|
||||
use updater::Updater;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||
pub enum Api {
|
||||
@ -118,6 +118,7 @@ pub struct Dependencies {
|
||||
pub logger: Arc<RotatingLogger>,
|
||||
pub settings: Arc<NetworkSettings>,
|
||||
pub net_service: Arc<ManageNetwork>,
|
||||
pub updater: Arc<Updater>,
|
||||
pub geth_compatibility: bool,
|
||||
pub dapps_interface: Option<String>,
|
||||
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.miner,
|
||||
&deps.sync,
|
||||
&deps.updater,
|
||||
&deps.net_service,
|
||||
&deps.secret_store,
|
||||
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());
|
||||
},
|
||||
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 => {
|
||||
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
|
||||
// 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 ctrlc::CtrlC;
|
||||
use fdlimit::raise_fd_limit;
|
||||
use ethcore_rpc::{NetworkSettings, is_major_importing};
|
||||
use ethsync::NetworkConfiguration;
|
||||
use util::{Colour, version, RotatingLogger};
|
||||
use util::{Colour, version, RotatingLogger, Mutex, Condvar};
|
||||
use io::{MayPanic, ForwardPanic, PanicHandler};
|
||||
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::account_provider::AccountProvider;
|
||||
use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions};
|
||||
@ -31,11 +31,11 @@ use ethcore::snapshot;
|
||||
use ethcore::verification::queue::VerifierSettings;
|
||||
use ethsync::SyncConfig;
|
||||
use informant::Informant;
|
||||
use updater::{UpdatePolicy, Updater};
|
||||
|
||||
use rpc::{HttpServer, IpcServer, HttpConfiguration, IpcConfiguration};
|
||||
use signer::SignerServer;
|
||||
use dapps::WebappServer;
|
||||
use io_handler::ClientIoHandler;
|
||||
use params::{
|
||||
SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch,
|
||||
tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool
|
||||
@ -77,6 +77,7 @@ pub struct RunCmd {
|
||||
pub acc_conf: AccountsConfig,
|
||||
pub gas_pricer: GasPricerConfig,
|
||||
pub miner_extras: MinerExtras,
|
||||
pub update_policy: UpdatePolicy,
|
||||
pub mode: Option<Mode>,
|
||||
pub tracing: Switch,
|
||||
pub fat_db: Switch,
|
||||
@ -115,12 +116,12 @@ pub fn open_ui(dapps_conf: &dapps::Configuration, signer_conf: &signer::Configur
|
||||
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 {
|
||||
// Check if Parity is already running
|
||||
let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port);
|
||||
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);
|
||||
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.
|
||||
let client_path = db_dirs.client_path(algorithm);
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// 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
|
||||
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();
|
||||
}
|
||||
|
||||
// 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
|
||||
let signer_path = cmd.signer_conf.signer_path.clone();
|
||||
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(),
|
||||
settings: Arc::new(cmd.net_settings.clone()),
|
||||
net_service: manage_network.clone(),
|
||||
updater: updater.clone(),
|
||||
geth_compatibility: cmd.geth_compatibility,
|
||||
dapps_interface: match cmd.dapps_conf.enabled {
|
||||
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 ipc_server = try!(rpc::new_ipc(cmd.ipc_conf, &dependencies));
|
||||
|
||||
// the dapps server
|
||||
let dapps_deps = dapps::Dependencies {
|
||||
panic_handler: panic_handler.clone(),
|
||||
apis: deps_for_rpc_apis.clone(),
|
||||
client: client.clone(),
|
||||
sync: sync_provider.clone(),
|
||||
};
|
||||
|
||||
// start dapps server
|
||||
let dapps_server = try!(dapps::new(cmd.dapps_conf.clone(), dapps_deps));
|
||||
|
||||
// the signer server
|
||||
let signer_deps = signer::Dependencies {
|
||||
panic_handler: panic_handler.clone(),
|
||||
apis: deps_for_rpc_apis.clone(),
|
||||
};
|
||||
|
||||
// start signer server
|
||||
let signer_server = try!(signer::start(cmd.signer_conf.clone(), signer_deps));
|
||||
|
||||
// the informant
|
||||
let informant = Arc::new(Informant::new(
|
||||
service.client(),
|
||||
Some(sync_provider.clone()),
|
||||
@ -368,17 +376,8 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
Some(snapshot_service.clone()),
|
||||
cmd.logger_config.color
|
||||
));
|
||||
let info_notify: Arc<ChainNotify> = informant.clone();
|
||||
service.add_notify(info_notify);
|
||||
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");
|
||||
service.add_notify(informant.clone());
|
||||
service.register_io_handler(informant.clone()).map_err(|_| "Unable to register informant handler".to_owned())?;
|
||||
|
||||
// save user defaults
|
||||
user_defaults.pruning = algorithm;
|
||||
@ -387,13 +386,11 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
user_defaults.mode = mode;
|
||||
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();
|
||||
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.
|
||||
let _watcher = match cmd.no_periodic_snapshot {
|
||||
@ -419,18 +416,20 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
drop(io_handler);
|
||||
drop(informant);
|
||||
|
||||
// hypervisor should be shutdown first while everything still works and can be
|
||||
// terminated gracefully
|
||||
drop(hypervisor);
|
||||
|
||||
Ok(())
|
||||
Ok(restart)
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
@ -475,20 +474,30 @@ fn wait_for_exit(
|
||||
_http_server: Option<HttpServer>,
|
||||
_ipc_server: Option<IpcServer>,
|
||||
_dapps_server: Option<WebappServer>,
|
||||
_signer_server: Option<SignerServer>
|
||||
) {
|
||||
let exit = Arc::new(Condvar::new());
|
||||
_signer_server: Option<SignerServer>,
|
||||
updater: Arc<Updater>,
|
||||
can_restart: bool
|
||||
) -> bool {
|
||||
let exit = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
|
||||
// Handle possible exits
|
||||
let e = exit.clone();
|
||||
CtrlC::set_handler(move || { e.notify_all(); });
|
||||
CtrlC::set_handler(move || { e.1.notify_all(); });
|
||||
|
||||
// Handle panics
|
||||
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
|
||||
let mutex = Mutex::new(());
|
||||
let _ = exit.wait(mutex.lock().unwrap());
|
||||
info!("Finishing work, please wait...");
|
||||
let mut l = exit.0.lock();
|
||||
let _ = exit.1.wait(&mut l);
|
||||
*l
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ impl Default for Configuration {
|
||||
enabled: true,
|
||||
port: 8180,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ impl SnapshotCommand {
|
||||
let snapshot_path = db_dirs.snapshot_path();
|
||||
|
||||
// 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
|
||||
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 default_path = default_data_path();
|
||||
if legacy_root_path != dirs.path && dirs.path == default_path {
|
||||
upgrade_dir_location(&PathBuf::from(legacy_root_path), &PathBuf::from(&dirs.path));
|
||||
if legacy_root_path != base_path && base_path == default_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_snapshot_path(), &dirs.snapshot_path());
|
||||
|
@ -26,6 +26,7 @@ ethash = { path = "../ethash" }
|
||||
ethsync = { path = "../sync" }
|
||||
ethjson = { path = "../json" }
|
||||
ethcore-devtools = { path = "../devtools" }
|
||||
parity-updater = { path = "../updater" }
|
||||
rlp = { path = "../util/rlp" }
|
||||
fetch = { path = "../util/fetch" }
|
||||
rustc-serialize = "0.3"
|
||||
@ -34,6 +35,7 @@ serde_macros = { version = "0.8.0", optional = true }
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
ethcore-ipc = { path = "../ipc/rpc" }
|
||||
time = "0.1"
|
||||
semver = "0.5"
|
||||
|
||||
[build-dependencies]
|
||||
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", plugin(serde_macros, clippy))]
|
||||
|
||||
extern crate semver;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
@ -37,6 +38,7 @@ extern crate ethcore_ipc;
|
||||
extern crate time;
|
||||
extern crate rlp;
|
||||
extern crate fetch;
|
||||
extern crate parity_updater as updater;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
@ -30,6 +30,7 @@ use ethcore::miner::MinerService;
|
||||
use ethcore::client::{MiningBlockChainClient};
|
||||
use ethcore::mode::Mode;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use updater::{Service as UpdateService};
|
||||
|
||||
use jsonrpc_core::Error;
|
||||
use jsonrpc_macros::Trailing;
|
||||
@ -38,20 +39,23 @@ use v1::types::{
|
||||
Bytes, U256, H160, H256, H512,
|
||||
Peers, Transaction, RpcSettings, Histogram,
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber,
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
OperationsInfo
|
||||
};
|
||||
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
||||
use v1::helpers::dispatch::DEFAULT_MAC;
|
||||
|
||||
/// Parity implementation.
|
||||
pub struct ParityClient<C, M, S: ?Sized> where
|
||||
pub struct ParityClient<C, M, S: ?Sized, U> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
S: SyncProvider,
|
||||
U: UpdateService,
|
||||
{
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
sync: Weak<S>,
|
||||
updater: Weak<U>,
|
||||
net: Weak<ManageNetwork>,
|
||||
accounts: Weak<AccountProvider>,
|
||||
logger: Arc<RotatingLogger>,
|
||||
@ -61,16 +65,18 @@ pub struct ParityClient<C, M, S: ?Sized> where
|
||||
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,
|
||||
M: MinerService,
|
||||
S: SyncProvider,
|
||||
U: UpdateService,
|
||||
{
|
||||
/// Creates new `ParityClient`.
|
||||
pub fn new(
|
||||
client: &Arc<C>,
|
||||
miner: &Arc<M>,
|
||||
sync: &Arc<S>,
|
||||
updater: &Arc<U>,
|
||||
net: &Arc<ManageNetwork>,
|
||||
store: &Arc<AccountProvider>,
|
||||
logger: Arc<RotatingLogger>,
|
||||
@ -83,6 +89,7 @@ impl<C, M, S: ?Sized> ParityClient<C, M, S> where
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
sync: Arc::downgrade(sync),
|
||||
updater: Arc::downgrade(updater),
|
||||
net: Arc::downgrade(net),
|
||||
accounts: Arc::downgrade(store),
|
||||
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,
|
||||
C: MiningBlockChainClient + 'static,
|
||||
S: SyncProvider + 'static {
|
||||
S: SyncProvider + 'static,
|
||||
U: UpdateService + 'static {
|
||||
|
||||
fn transactions_limit(&self) -> Result<usize, Error> {
|
||||
try!(self.active());
|
||||
@ -353,4 +361,22 @@ impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
|
||||
(format!("0x{}", a.hex()), m)
|
||||
}).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 fetch::{Client as FetchClient, Fetch};
|
||||
use util::{Mutex, sha3};
|
||||
use updater::{Service as UpdateService};
|
||||
|
||||
use jsonrpc_core::Error;
|
||||
use jsonrpc_macros::Ready;
|
||||
use v1::helpers::errors;
|
||||
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.
|
||||
pub struct ParitySetClient<C, M, F=FetchClient> where
|
||||
pub struct ParitySetClient<C, M, U, F=FetchClient> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
U: UpdateService,
|
||||
F: Fetch,
|
||||
{
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
updater: Weak<U>,
|
||||
net: Weak<ManageNetwork>,
|
||||
fetch: Mutex<F>,
|
||||
}
|
||||
|
||||
impl<C, M> ParitySetClient<C, M, FetchClient> where
|
||||
impl<C, M, U> ParitySetClient<C, M, U, FetchClient> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService
|
||||
M: MinerService,
|
||||
U: UpdateService,
|
||||
{
|
||||
/// Creates new `ParitySetClient` with default `FetchClient`.
|
||||
pub fn new(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self {
|
||||
Self::with_fetch(client, miner, net)
|
||||
pub fn new(client: &Arc<C>, miner: &Arc<M>, updater: &Arc<U>, net: &Arc<ManageNetwork>) -> Self {
|
||||
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,
|
||||
M: MinerService,
|
||||
U: UpdateService,
|
||||
F: Fetch,
|
||||
{
|
||||
/// 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 {
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
updater: Arc::downgrade(updater),
|
||||
net: Arc::downgrade(net),
|
||||
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,
|
||||
M: MinerService + 'static,
|
||||
U: UpdateService + '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 fetch;
|
||||
mod snapshot_service;
|
||||
mod update_service;
|
||||
|
||||
pub use self::sync_provider::{Config, TestSyncProvider};
|
||||
pub use self::miner_service::TestMinerService;
|
||||
pub use self::fetch::TestFetch;
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
@ -26,15 +26,16 @@ use ethstore::ethkey::{Generator, Random};
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{Parity, ParityClient};
|
||||
use v1::helpers::{SignerService, NetworkSettings};
|
||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
|
||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater};
|
||||
use super::manage_network::TestManageNetwork;
|
||||
|
||||
pub type TestParityClient = ParityClient<TestBlockChainClient, TestMinerService, TestSyncProvider>;
|
||||
pub type TestParityClient = ParityClient<TestBlockChainClient, TestMinerService, TestSyncProvider, TestUpdater>;
|
||||
|
||||
pub struct Dependencies {
|
||||
pub miner: Arc<TestMinerService>,
|
||||
pub client: Arc<TestBlockChainClient>,
|
||||
pub sync: Arc<TestSyncProvider>,
|
||||
pub updater: Arc<TestUpdater>,
|
||||
pub logger: Arc<RotatingLogger>,
|
||||
pub settings: Arc<NetworkSettings>,
|
||||
pub network: Arc<ManageNetwork>,
|
||||
@ -52,6 +53,7 @@ impl Dependencies {
|
||||
network_id: 3,
|
||||
num_peers: 120,
|
||||
})),
|
||||
updater: Arc::new(TestUpdater::default()),
|
||||
logger: Arc::new(RotatingLogger::new("rpc=trace".to_owned())),
|
||||
settings: Arc::new(NetworkSettings {
|
||||
name: "mynode".to_owned(),
|
||||
@ -73,6 +75,7 @@ impl Dependencies {
|
||||
&self.client,
|
||||
&self.miner,
|
||||
&self.sync,
|
||||
&self.updater,
|
||||
&self.network,
|
||||
&self.accounts,
|
||||
self.logger.clone(),
|
||||
@ -96,6 +99,48 @@ impl Dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_consensus_capability() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_consensusCapability", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"capableUntil":15100},"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
deps.updater.set_current_block(15101);
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_consensusCapability", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"incapableSince":15100},"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
deps.updater.set_updated(true);
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_consensusCapability", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"capable","id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_version_info() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_versionInfo", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"hash":"0x0000000000000000000000000000000000000096","track":"beta","version":{"major":1,"minor":5,"patch":0}},"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_releases_info() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_releasesInfo", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"fork":15100,"minor":null,"this_fork":15000,"track":{"binary":"0x00000000000000000000000000000000000000000000000000000000000005e6","fork":15100,"is_critical":true,"version":{"hash":"0x0000000000000000000000000000000000000097","track":"beta","version":{"major":1,"minor":5,"patch":1}}}},"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_extra_data() {
|
||||
let deps = Dependencies::new();
|
||||
@ -196,12 +241,7 @@ fn rpc_parity_net_peers() {
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_netPeers", "params":[], "id": 1}"#;
|
||||
let response = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":120,\"max\":50,\"peers\":[{\"caps\":[\"eth/62\",\"eth/63\"],\
|
||||
\"id\":\"node1\",\"name\":\"Parity/1\",\"network\":{\"localAddress\":\"127.0.0.1:8888\",\"remoteAddress\":\"127.0.0.1:7777\"}\
|
||||
,\"protocols\":{\"eth\":{\"difficulty\":\"0x28\",\"head\":\"0000000000000000000000000000000000000000000000000000000000000032\"\
|
||||
,\"version\":62}}},{\"caps\":[\"eth/63\",\"eth/64\"],\"id\":null,\"name\":\"Parity/2\",\"network\":{\"localAddress\":\
|
||||
\"127.0.0.1:3333\",\"remoteAddress\":\"Handshake\"},\"protocols\":{\"eth\":{\"difficulty\":null,\"head\":\
|
||||
\"000000000000000000000000000000000000000000000000000000000000003c\",\"version\":64}}}]},\"id\":1}";
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"active":0,"connected":120,"max":50,"peers":[{"caps":["eth/62","eth/63"],"id":"node1","name":"Parity/1","network":{"localAddress":"127.0.0.1:8888","remoteAddress":"127.0.0.1:7777"},"protocols":{"eth":{"difficulty":"0x28","head":"0000000000000000000000000000000000000000000000000000000000000032","version":62}}},{"caps":["eth/63","eth/64"],"id":null,"name":"Parity/2","network":{"localAddress":"127.0.0.1:3333","remoteAddress":"Handshake"},"protocols":{"eth":{"difficulty":null,"head":"000000000000000000000000000000000000000000000000000000000000003c","version":64}}}]},"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use ethsync::ManageNetwork;
|
||||
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{ParitySet, ParitySetClient};
|
||||
use v1::tests::helpers::{TestMinerService, TestFetch};
|
||||
use v1::tests::helpers::{TestMinerService, TestFetch, TestUpdater};
|
||||
use super::manage_network::TestManageNetwork;
|
||||
|
||||
fn miner_service() -> Arc<TestMinerService> {
|
||||
@ -40,10 +40,52 @@ fn network_service() -> Arc<TestManageNetwork> {
|
||||
Arc::new(TestManageNetwork)
|
||||
}
|
||||
|
||||
pub type TestParitySetClient = ParitySetClient<TestBlockChainClient, TestMinerService, TestFetch>;
|
||||
fn updater_service() -> Arc<TestUpdater> {
|
||||
Arc::new(TestUpdater::default())
|
||||
}
|
||||
|
||||
fn parity_set_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>, net: &Arc<TestManageNetwork>) -> TestParitySetClient {
|
||||
ParitySetClient::with_fetch(client, miner, &(net.clone() as Arc<ManageNetwork>))
|
||||
pub type TestParitySetClient = ParitySetClient<TestBlockChainClient, TestMinerService, TestUpdater, TestFetch>;
|
||||
|
||||
fn parity_set_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>, updater: &Arc<TestUpdater>, net: &Arc<TestManageNetwork>) -> TestParitySetClient {
|
||||
ParitySetClient::with_fetch(client, miner, updater, &(net.clone() as Arc<ManageNetwork>))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_execute_upgrade() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_executeUpgrade", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_executeUpgrade", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_upgrade_ready() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_upgradeReady", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"binary":"0x00000000000000000000000000000000000000000000000000000000000005e6","fork":15100,"is_critical":true,"version":{"hash":"0x0000000000000000000000000000000000000097","track":"beta","version":{"major":1,"minor":5,"patch":1}}},"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
updater.set_updated(true);
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_upgradeReady", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -51,8 +93,9 @@ fn rpc_parity_set_min_gas_price() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
@ -66,8 +109,9 @@ fn rpc_parity_set_gas_floor_target() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
@ -81,8 +125,9 @@ fn rpc_parity_set_extra_data() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
@ -96,8 +141,9 @@ fn rpc_parity_set_author() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
@ -111,8 +157,9 @@ fn rpc_parity_set_engine_signer() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
@ -128,8 +175,9 @@ fn rpc_parity_set_transactions_limit() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
@ -143,8 +191,9 @@ fn rpc_parity_set_hash_content() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let updater = updater_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_hashContent", "params":["https://ethcore.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#;
|
||||
|
@ -25,7 +25,8 @@ use v1::types::{
|
||||
H160, H256, H512, U256, Bytes,
|
||||
Peers, Transaction, RpcSettings, Histogram,
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
OperationsInfo
|
||||
};
|
||||
|
||||
build_rpc_trait! {
|
||||
@ -157,5 +158,17 @@ build_rpc_trait! {
|
||||
/// Returns accounts information.
|
||||
#[rpc(name = "parity_accounts")]
|
||||
fn accounts(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error>;
|
||||
|
||||
/// Returns information on current consensus capability.
|
||||
#[rpc(name = "parity_consensusCapability")]
|
||||
fn consensus_capability(&self) -> Result<ConsensusCapability, Error>;
|
||||
|
||||
/// Get our version information in a nice object.
|
||||
#[rpc(name = "parity_versionInfo")]
|
||||
fn version_info(&self) -> Result<VersionInfo, Error>;
|
||||
|
||||
/// Get information concerning the latest releases if available.
|
||||
#[rpc(name = "parity_releasesInfo")]
|
||||
fn releases_info(&self) -> Result<Option<OperationsInfo>, Error>;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
use jsonrpc_core::Error;
|
||||
use jsonrpc_macros::Ready;
|
||||
|
||||
use v1::types::{Bytes, H160, H256, U256};
|
||||
use v1::types::{Bytes, H160, H256, U256, ReleaseInfo};
|
||||
|
||||
build_rpc_trait! {
|
||||
/// Parity-specific rpc interface for operations altering the settings.
|
||||
@ -91,5 +91,13 @@ build_rpc_trait! {
|
||||
/// Hash a file content under given URL.
|
||||
#[rpc(async, name = "parity_hashContent")]
|
||||
fn hash_content(&self, Ready<H256>, String);
|
||||
|
||||
/// Is there a release ready for install?
|
||||
#[rpc(name = "parity_upgradeReady")]
|
||||
fn upgrade_ready(&self) -> Result<Option<ReleaseInfo>, Error>;
|
||||
|
||||
/// Execute a release which is ready according to upgrade_ready().
|
||||
#[rpc(name = "parity_executeUpgrade")]
|
||||
fn execute_upgrade(&self) -> Result<bool, Error>;
|
||||
}
|
||||
}
|
||||
|
169
rpc/src/v1/types/consensus_status.rs
Normal file
169
rpc/src/v1/types/consensus_status.rs
Normal file
@ -0,0 +1,169 @@
|
||||
// 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 semver;
|
||||
use v1::types::{H160, H256};
|
||||
use updater::{self, CapState};
|
||||
|
||||
/// Capability info
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
pub enum ConsensusCapability {
|
||||
/// Unknown.
|
||||
#[serde(rename="unknown")]
|
||||
Unknown,
|
||||
/// Capable of consensus indefinitely.
|
||||
#[serde(rename="capable")]
|
||||
Capable,
|
||||
/// Capable of consensus up until a definite block.
|
||||
#[serde(rename="capableUntil")]
|
||||
CapableUntil(u64),
|
||||
/// Incapable of consensus since a particular block.
|
||||
#[serde(rename="incapableSince")]
|
||||
IncapableSince(u64),
|
||||
}
|
||||
|
||||
impl Into<ConsensusCapability> for CapState {
|
||||
fn into(self) -> ConsensusCapability {
|
||||
match self {
|
||||
CapState::Unknown => ConsensusCapability::Unknown,
|
||||
CapState::Capable => ConsensusCapability::Capable,
|
||||
CapState::CapableUntil(n) => ConsensusCapability::CapableUntil(n),
|
||||
CapState::IncapableSince(n) => ConsensusCapability::IncapableSince(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A release's track.
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
pub enum ReleaseTrack {
|
||||
/// Stable track.
|
||||
#[serde(rename="stable")]
|
||||
Stable,
|
||||
/// Beta track.
|
||||
#[serde(rename="beta")]
|
||||
Beta,
|
||||
/// Nightly track.
|
||||
#[serde(rename="nightly")]
|
||||
Nightly,
|
||||
/// Testing track.
|
||||
#[serde(rename="testing")]
|
||||
Testing,
|
||||
/// No known track.
|
||||
#[serde(rename="null")]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Into<ReleaseTrack> for updater::ReleaseTrack {
|
||||
fn into(self) -> ReleaseTrack {
|
||||
match self {
|
||||
updater::ReleaseTrack::Stable => ReleaseTrack::Stable,
|
||||
updater::ReleaseTrack::Beta => ReleaseTrack::Beta,
|
||||
updater::ReleaseTrack::Nightly => ReleaseTrack::Nightly,
|
||||
updater::ReleaseTrack::Testing => ReleaseTrack::Testing,
|
||||
updater::ReleaseTrack::Unknown => ReleaseTrack::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Semantic version.
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
pub struct Version {
|
||||
/// Major part.
|
||||
major: u64,
|
||||
/// Minor part.
|
||||
minor: u64,
|
||||
/// Patch part.
|
||||
patch: u64,
|
||||
}
|
||||
|
||||
impl Into<Version> for semver::Version {
|
||||
fn into(self) -> Version {
|
||||
Version {
|
||||
major: self.major,
|
||||
minor: self.minor,
|
||||
patch: self.patch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Version information of a particular release.
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
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 Into<VersionInfo> for updater::VersionInfo {
|
||||
fn into(self) -> VersionInfo {
|
||||
VersionInfo {
|
||||
track: self.track.into(),
|
||||
version: self.version.into(),
|
||||
hash: self.hash.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information regarding a particular release of Parity
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
pub struct ReleaseInfo {
|
||||
/// Information on the version.
|
||||
pub version: VersionInfo,
|
||||
/// Does this release contain critical security updates?
|
||||
pub is_critical: bool,
|
||||
/// The latest fork that this release can handle.
|
||||
pub fork: u64,
|
||||
/// Our platform's binary, if known.
|
||||
pub binary: Option<H256>,
|
||||
}
|
||||
|
||||
impl Into<ReleaseInfo> for updater::ReleaseInfo {
|
||||
fn into(self) -> ReleaseInfo {
|
||||
ReleaseInfo {
|
||||
version: self.version.into(),
|
||||
is_critical: self.is_critical,
|
||||
fork: self.fork,
|
||||
binary: self.binary.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information on our operations environment.
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
pub struct OperationsInfo {
|
||||
/// Our blockchain's latest fork.
|
||||
pub fork: u64,
|
||||
/// Last fork our client supports, if known.
|
||||
pub this_fork: Option<u64>,
|
||||
/// Information on our track's latest release.
|
||||
pub track: ReleaseInfo,
|
||||
/// Information on our minor version's latest release.
|
||||
pub minor: Option<ReleaseInfo>,
|
||||
}
|
||||
|
||||
impl Into<OperationsInfo> for updater::OperationsInfo {
|
||||
fn into(self) -> OperationsInfo {
|
||||
OperationsInfo {
|
||||
fork: self.fork,
|
||||
this_fork: self.this_fork,
|
||||
track: self.track.into(),
|
||||
minor: self.minor.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ mod trace_filter;
|
||||
mod uint;
|
||||
mod work;
|
||||
mod histogram;
|
||||
mod consensus_status;
|
||||
|
||||
pub use self::bytes::Bytes;
|
||||
pub use self::block::{RichBlock, Block, BlockTransactions};
|
||||
@ -58,3 +59,4 @@ pub use self::trace_filter::TraceFilter;
|
||||
pub use self::uint::{U128, U256};
|
||||
pub use self::work::Work;
|
||||
pub use self::histogram::Histogram;
|
||||
pub use self::consensus_status::*;
|
@ -117,7 +117,7 @@ fn reject_transaction(
|
||||
|
||||
// cmds
|
||||
|
||||
pub fn cmd_signer_list(
|
||||
pub fn signer_list(
|
||||
signerport: u16, authfile: PathBuf
|
||||
) -> Result<String, String> {
|
||||
let addr = &format!("ws://127.0.0.1:{}", signerport);
|
||||
@ -127,7 +127,7 @@ pub fn cmd_signer_list(
|
||||
list_transactions(&mut signer)
|
||||
}
|
||||
|
||||
pub fn cmd_signer_reject(
|
||||
pub fn signer_reject(
|
||||
id: Option<usize>, signerport: u16, authfile: PathBuf
|
||||
) -> Result<String, String> {
|
||||
let id = try!(id.ok_or(format!("id required for signer reject")));
|
||||
@ -138,7 +138,7 @@ pub fn cmd_signer_reject(
|
||||
reject_transaction(&mut signer, U256::from(id))
|
||||
}
|
||||
|
||||
pub fn cmd_signer_sign(
|
||||
pub fn signer_sign(
|
||||
id: Option<usize>,
|
||||
pwfile: Option<PathBuf>,
|
||||
signerport: u16,
|
||||
|
222
scripts/contractABI.js
Normal file
222
scripts/contractABI.js
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user