Merge branch 'master' into on-demand-les-request
This commit is contained in:
commit
7dde02b25d
@ -38,7 +38,7 @@ linux-stable:
|
|||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity.md5 --body parity.md5
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity.md5 --body parity.md5
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb" --body "parity_"$VER"_amd64.deb"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb" --body "parity_"$VER"_amd64.deb"
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb.md5" --body "parity_"$VER"_amd64.deb.md5"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb.md5" --body "parity_"$VER"_amd64.deb.md5"
|
||||||
# - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
@ -107,7 +107,7 @@ linux-centos:
|
|||||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu
|
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu
|
||||||
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity --body target/release/parity
|
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity --body target/release/parity
|
||||||
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity.md5 --body parity.md5
|
- aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity.md5 --body parity.md5
|
||||||
# - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
@ -146,7 +146,7 @@ linux-i686:
|
|||||||
- 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.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" --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"
|
- 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://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
@ -192,7 +192,7 @@ linux-armv7:
|
|||||||
- 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.md5 --body parity.md5
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb"
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5"
|
||||||
# - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
@ -238,7 +238,7 @@ linux-arm:
|
|||||||
- 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.md5 --body parity.md5
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb"
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5"
|
||||||
# - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
@ -277,7 +277,7 @@ linux-armv6:
|
|||||||
- aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM
|
- 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 --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.md5 --body parity.md5
|
||||||
# - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
@ -322,7 +322,7 @@ linux-aarch64:
|
|||||||
- 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.md5 --body parity.md5
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_arm64.deb" --body "parity_"$VER"_arm64.deb"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_arm64.deb" --body "parity_"$VER"_arm64.deb"
|
||||||
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_arm64.deb.md5" --body "parity_"$VER"_arm64.deb.md5"
|
- aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_arm64.deb.md5" --body "parity_"$VER"_arm64.deb.md5"
|
||||||
# - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- rust
|
- rust
|
||||||
@ -359,7 +359,7 @@ darwin:
|
|||||||
- 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.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" --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"
|
- 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://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
- curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM
|
||||||
tags:
|
tags:
|
||||||
- osx
|
- osx
|
||||||
@ -421,7 +421,7 @@ windows:
|
|||||||
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5
|
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5
|
||||||
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip
|
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip
|
||||||
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5
|
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5
|
||||||
# - curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://update.parity.io:1337/push-build/%CI_BUILD_REF_NAME%/%PLATFORM%
|
- curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://update.parity.io:1337/push-build/%CI_BUILD_REF_NAME%/%PLATFORM%
|
||||||
- curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://update.parity.io:1338/push-build/%CI_BUILD_REF_NAME%/%PLATFORM%
|
- curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://update.parity.io:1338/push-build/%CI_BUILD_REF_NAME%/%PLATFORM%
|
||||||
tags:
|
tags:
|
||||||
- rust-windows
|
- rust-windows
|
||||||
@ -535,7 +535,7 @@ push-release:
|
|||||||
- triggers
|
- triggers
|
||||||
image: ethcore/rust:stable
|
image: ethcore/rust:stable
|
||||||
script:
|
script:
|
||||||
# - curl --data "secret=$RELEASES_SECRET" http://update.parity.io:1337/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
|
- curl --data "secret=$RELEASES_SECRET" http://update.parity.io:1337/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
|
||||||
- curl --data "secret=$RELEASES_SECRET" http://update.parity.io:1338/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
|
- curl --data "secret=$RELEASES_SECRET" http://update.parity.io:1338/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
|
||||||
tags:
|
tags:
|
||||||
- curl
|
- curl
|
||||||
|
204
Cargo.lock
generated
204
Cargo.lock
generated
@ -28,6 +28,7 @@ dependencies = [
|
|||||||
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -44,7 +45,7 @@ dependencies = [
|
|||||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -100,14 +101,6 @@ dependencies = [
|
|||||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aster"
|
|
||||||
version = "0.25.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bigint"
|
name = "bigint"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -329,8 +322,8 @@ dependencies = [
|
|||||||
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -413,8 +406,8 @@ dependencies = [
|
|||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -426,8 +419,8 @@ dependencies = [
|
|||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -584,20 +577,19 @@ dependencies = [
|
|||||||
"ethsync 1.6.0",
|
"ethsync 1.6.0",
|
||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-ipc-server 1.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-macros 0.2.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-reactor 0.1.0",
|
"parity-reactor 0.1.0",
|
||||||
"parity-updater 1.6.0",
|
"parity-updater 1.6.0",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -612,7 +604,7 @@ dependencies = [
|
|||||||
"ethcore-io 1.6.0",
|
"ethcore-io 1.6.0",
|
||||||
"ethcore-rpc 1.6.0",
|
"ethcore-rpc 1.6.0",
|
||||||
"ethcore-util 1.6.0",
|
"ethcore-util 1.6.0",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-ui 1.6.0",
|
"parity-ui 1.6.0",
|
||||||
@ -631,8 +623,9 @@ dependencies = [
|
|||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-ipc-nano 1.6.0",
|
"ethcore-ipc-nano 1.6.0",
|
||||||
"ethcore-util 1.6.0",
|
"ethcore-util 1.6.0",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-macros 0.2.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
|
"jsonrpc-tcp-server 1.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
||||||
@ -693,8 +686,8 @@ dependencies = [
|
|||||||
"ethcore-util 1.6.0",
|
"ethcore-util 1.6.0",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -726,8 +719,8 @@ dependencies = [
|
|||||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -952,63 +945,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-core"
|
name = "jsonrpc-core"
|
||||||
version = "4.0.0"
|
version = "5.0.0"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-http-server"
|
name = "jsonrpc-http-server"
|
||||||
version = "6.1.1"
|
version = "7.0.0"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-ipc-server"
|
name = "jsonrpc-ipc-server"
|
||||||
version = "0.2.4"
|
version = "1.0.0"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-macros"
|
name = "jsonrpc-macros"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-tcp-server"
|
name = "jsonrpc-tcp-server"
|
||||||
version = "0.1.0"
|
version = "1.0.0"
|
||||||
source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a"
|
source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1472,13 +1471,13 @@ dependencies = [
|
|||||||
"ethcore-signer 1.6.0",
|
"ethcore-signer 1.6.0",
|
||||||
"ethcore-util 1.6.0",
|
"ethcore-util 1.6.0",
|
||||||
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ws 0.5.3 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)",
|
"ws 0.5.3 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)",
|
||||||
@ -1503,7 +1502,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-ui-precompiled"
|
name = "parity-ui-precompiled"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "git+https://github.com/ethcore/js-precompiled.git#e21ae69190fa390f5550e5cf17f5ea362ba4db41"
|
source = "git+https://github.com/ethcore/js-precompiled.git#73497e202735f4a6d2bf55de6509fc010419871b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -1639,15 +1638,6 @@ dependencies = [
|
|||||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quasi"
|
|
||||||
version = "0.18.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quasi_codegen"
|
name = "quasi_codegen"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@ -1658,17 +1648,6 @@ dependencies = [
|
|||||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quasi_codegen"
|
|
||||||
version = "0.18.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -1679,6 +1658,11 @@ name = "quine-mc_cluskey"
|
|||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "0.3.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
@ -1723,7 +1707,7 @@ dependencies = [
|
|||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -1912,29 +1896,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_codegen"
|
name = "serde_codegen"
|
||||||
version = "0.8.4"
|
version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quasi 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen_internals 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quasi_codegen 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_codegen_internals"
|
name = "serde_codegen_internals"
|
||||||
version = "0.7.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "0.8.1"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2032,6 +2014,15 @@ name = "strsim"
|
|||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syntex"
|
name = "syntex"
|
||||||
version = "0.33.0"
|
version = "0.33.0"
|
||||||
@ -2042,29 +2033,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syntex"
|
name = "syntex"
|
||||||
version = "0.42.2"
|
version = "0.50.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syntex_errors"
|
name = "syntex_errors"
|
||||||
version = "0.42.0"
|
version = "0.50.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syntex_pos"
|
name = "syntex_pos"
|
||||||
version = "0.42.0"
|
version = "0.50.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2085,15 +2076,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syntex_syntax"
|
name = "syntex_syntax"
|
||||||
version = "0.42.0"
|
version = "0.50.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -2368,7 +2359,6 @@ dependencies = [
|
|||||||
"checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4"
|
"checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4"
|
||||||
"checksum arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "16e3bdb2f54b3ace0285975d59a97cf8ed3855294b2b6bc651fcf22a9c352975"
|
"checksum arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "16e3bdb2f54b3ace0285975d59a97cf8ed3855294b2b6bc651fcf22a9c352975"
|
||||||
"checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a"
|
"checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a"
|
||||||
"checksum aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df293303e8a52e1df7984ac1415e195f5fcbf51e4bb7bda54557861a3954a08"
|
|
||||||
"checksum bigint 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2311bcd71b281e142a095311c22509f0d6bcd87b3000d7dbaa810929b9d6f6ae"
|
"checksum bigint 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2311bcd71b281e142a095311c22509f0d6bcd87b3000d7dbaa810929b9d6f6ae"
|
||||||
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
||||||
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
|
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
|
||||||
@ -2416,11 +2406,11 @@ dependencies = [
|
|||||||
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
|
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
|
||||||
"checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76"
|
"checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76"
|
||||||
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
|
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
|
||||||
"checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-ipc-server 1.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-macros 0.2.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
"checksum jsonrpc-tcp-server 1.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||||
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
|
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
|
||||||
@ -2482,11 +2472,10 @@ dependencies = [
|
|||||||
"checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5"
|
"checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5"
|
||||||
"checksum primal-sieve 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7aa73fd87e5984a00bdb4c1b14d3d5d6d0bad01b2caaaf924c16ab7260ac946c"
|
"checksum primal-sieve 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7aa73fd87e5984a00bdb4c1b14d3d5d6d0bad01b2caaaf924c16ab7260ac946c"
|
||||||
"checksum quasi 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b26543b563704e7d87f3ec7cfafb713010a905c5f1b155a8ab66863af43ca578"
|
"checksum quasi 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b26543b563704e7d87f3ec7cfafb713010a905c5f1b155a8ab66863af43ca578"
|
||||||
"checksum quasi 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb7eaef226a434a570fa336bc99502c4f5878208c1ebdd83b2d0bc37b1b1c34c"
|
|
||||||
"checksum quasi_codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0881d9a45d5f9ebe4a7e77742f8c604f3658c212baf8dd711a692dd000bc648c"
|
"checksum quasi_codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0881d9a45d5f9ebe4a7e77742f8c604f3658c212baf8dd711a692dd000bc648c"
|
||||||
"checksum quasi_codegen 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62e90381b315dfd00bfe6efbfeeec9f03a6d66159c3a5c8411b6c550d24b08fd"
|
|
||||||
"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
|
"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
|
||||||
"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a"
|
"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a"
|
||||||
|
"checksum quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6732e32663c9c271bfc7c1823486b471f18c47a2dbf87c066897b7b51afc83be"
|
||||||
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
|
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
|
||||||
"checksum rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "655df67c314c30fa3055a365eae276eb88aa4f3413a352a1ab32c1320eda41ea"
|
"checksum rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "655df67c314c30fa3055a365eae276eb88aa4f3413a352a1ab32c1320eda41ea"
|
||||||
"checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29"
|
"checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29"
|
||||||
@ -2510,9 +2499,9 @@ dependencies = [
|
|||||||
"checksum semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5"
|
"checksum semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5"
|
||||||
"checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9"
|
"checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9"
|
||||||
"checksum serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)" = "58a19c0871c298847e6b68318484685cd51fa5478c0c905095647540031356e5"
|
"checksum serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)" = "58a19c0871c298847e6b68318484685cd51fa5478c0c905095647540031356e5"
|
||||||
"checksum serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e422ae53d7933f59c6ff57e7b5870b5c9094b1f473f78ec33d89f8a692c3ec02"
|
"checksum serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ce29a6ae259579707650ec292199b5fed2c0b8e2a4bdc994452d24d1bcf2242a"
|
||||||
"checksum serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f877e2781ed0a323295d1c9f0e26556117b5a11489fc47b1848dfb98b3173d21"
|
"checksum serde_codegen_internals 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "59933a62554548c690d2673c5164f0c4a46be7c5731edfd94b0ecb1048940732"
|
||||||
"checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc"
|
"checksum serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7d3c184d35801fb8b32b46a7d58d57dbcc150b0eb2b46a1eb79645e8ecfd5b"
|
||||||
"checksum serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53d4ebaa8d1d4f90d1b63dfca81ccd98ac20e1e479dbae393cbaf60f6fecd8d8"
|
"checksum serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53d4ebaa8d1d4f90d1b63dfca81ccd98ac20e1e479dbae393cbaf60f6fecd8d8"
|
||||||
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
|
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
|
||||||
"checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d"
|
"checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d"
|
||||||
@ -2527,12 +2516,13 @@ dependencies = [
|
|||||||
"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf"
|
"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf"
|
||||||
"checksum stable-heap 0.1.0 (git+https://github.com/carllerche/stable-heap?rev=3c5cd1ca47)" = "<none>"
|
"checksum stable-heap 0.1.0 (git+https://github.com/carllerche/stable-heap?rev=3c5cd1ca47)" = "<none>"
|
||||||
"checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825"
|
"checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825"
|
||||||
|
"checksum syn 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94e7d81ecd16d39f16193af05b8d5a0111b9d8d2f3f78f31760f327a247da777"
|
||||||
"checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af"
|
"checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af"
|
||||||
"checksum syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a30b08a6b383a22e5f6edc127d169670d48f905bb00ca79a00ea3e442ebe317"
|
"checksum syntex 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd253b0d7d787723a33384d426f0ebec7f8edccfaeb2022d0177162bb134da0"
|
||||||
"checksum syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04c48f32867b6114449155b2a82114b86d4b09e1bddb21c47ff104ab9172b646"
|
"checksum syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84822a1178204a191239ad844599f8c85c128cf9f4173397def4eb46b55b0aa1"
|
||||||
"checksum syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd49988e52451813c61fecbe9abb5cfd4e1b7bb6cdbb980a6fbcbab859171a6"
|
"checksum syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a43abded5057c75bac8555e46ec913ce502efb418267b1ab8e9783897470c7db"
|
||||||
"checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e"
|
"checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e"
|
||||||
"checksum syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7628a0506e8f9666fdabb5f265d0059b059edac9a3f810bda077abb5d826bd8d"
|
"checksum syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef781e4b60f03431f1b5b59843546ce60ae029a787770cf8e0969ac1fd063a5"
|
||||||
"checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe"
|
"checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe"
|
||||||
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
||||||
"checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281"
|
"checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281"
|
||||||
|
15
Cargo.toml
15
Cargo.toml
@ -26,14 +26,13 @@ lazy_static = "0.2"
|
|||||||
regex = "0.1"
|
regex = "0.1"
|
||||||
isatty = "0.1"
|
isatty = "0.1"
|
||||||
toml = "0.2"
|
toml = "0.2"
|
||||||
serde = "0.8.0"
|
serde = "0.8"
|
||||||
serde_json = "0.8.0"
|
serde_json = "0.8"
|
||||||
app_dirs = "1.1.1"
|
app_dirs = "1.1.1"
|
||||||
|
fdlimit = "0.1"
|
||||||
hyper = { version = "0.9", default-features = false }
|
hyper = { version = "0.9", default-features = false }
|
||||||
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
|
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
|
||||||
fdlimit = "0.1"
|
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
clippy = { version = "0.0.103", optional = true}
|
|
||||||
rlp = { path = "util/rlp" }
|
|
||||||
ethsync = { path = "sync" }
|
ethsync = { path = "sync" }
|
||||||
ethcore = { path = "ethcore" }
|
ethcore = { path = "ethcore" }
|
||||||
ethcore-util = { path = "util" }
|
ethcore-util = { path = "util" }
|
||||||
@ -44,15 +43,17 @@ ethcore-signer = { path = "signer" }
|
|||||||
ethcore-ipc = { path = "ipc/rpc" }
|
ethcore-ipc = { path = "ipc/rpc" }
|
||||||
ethcore-ipc-nano = { path = "ipc/nano" }
|
ethcore-ipc-nano = { path = "ipc/nano" }
|
||||||
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
|
||||||
|
ethcore-light = { path = "ethcore/light" }
|
||||||
ethcore-logger = { path = "logger" }
|
ethcore-logger = { path = "logger" }
|
||||||
ethcore-stratum = { path = "stratum" }
|
ethcore-stratum = { path = "stratum" }
|
||||||
ethcore-dapps = { path = "dapps", optional = true }
|
rlp = { path = "util/rlp" }
|
||||||
rpc-cli = { path = "rpc_cli" }
|
rpc-cli = { path = "rpc_cli" }
|
||||||
parity-rpc-client = { path = "rpc_client" }
|
parity-rpc-client = { path = "rpc_client" }
|
||||||
ethcore-light = { path = "ethcore/light" }
|
|
||||||
parity-hash-fetch = { path = "hash-fetch" }
|
parity-hash-fetch = { path = "hash-fetch" }
|
||||||
parity-updater = { path = "updater" }
|
parity-updater = { path = "updater" }
|
||||||
parity-reactor = { path = "util/reactor" }
|
parity-reactor = { path = "util/reactor" }
|
||||||
|
ethcore-dapps = { path = "dapps", optional = true }
|
||||||
|
clippy = { version = "0.0.103", optional = true}
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = "0.2"
|
winapi = "0.2"
|
||||||
|
@ -15,30 +15,6 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Ethcore Webapplications for Parity
|
//! Ethcore Webapplications for Parity
|
||||||
//! ```
|
|
||||||
//! extern crate jsonrpc_core;
|
|
||||||
//! extern crate ethcore_dapps;
|
|
||||||
//!
|
|
||||||
//! use std::sync::Arc;
|
|
||||||
//! use jsonrpc_core::IoHandler;
|
|
||||||
//! use ethcore_dapps::*;
|
|
||||||
//!
|
|
||||||
//! struct SayHello;
|
|
||||||
//! impl MethodCommand for SayHello {
|
|
||||||
//! fn execute(&self, _params: Params) -> Result<Value, Error> {
|
|
||||||
//! Ok(Value::String("hello".to_string()))
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn main() {
|
|
||||||
//! let io = IoHandler::new();
|
|
||||||
//! io.add_method("say_hello", SayHello);
|
|
||||||
//! let _server = Server::start_unsecure_http(
|
|
||||||
//! &"127.0.0.1:3030".parse().unwrap(),
|
|
||||||
//! Arc::new(io)
|
|
||||||
//! );
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
//!
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![cfg_attr(feature="nightly", plugin(clippy))]
|
#![cfg_attr(feature="nightly", plugin(clippy))]
|
||||||
@ -93,11 +69,11 @@ use std::sync::{Arc, Mutex};
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use hash_fetch::urlhint::ContractClient;
|
use ethcore_rpc::Metadata;
|
||||||
use fetch::{Fetch, Client as FetchClient};
|
use fetch::{Fetch, Client as FetchClient};
|
||||||
use jsonrpc_core::{IoHandler, IoDelegate};
|
use hash_fetch::urlhint::ContractClient;
|
||||||
|
use jsonrpc_core::reactor::RpcHandler;
|
||||||
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
||||||
use ethcore_rpc::Extendable;
|
|
||||||
use parity_reactor::Remote;
|
use parity_reactor::Remote;
|
||||||
|
|
||||||
use self::apps::{HOME_PAGE, DAPPS_DOMAIN};
|
use self::apps::{HOME_PAGE, DAPPS_DOMAIN};
|
||||||
@ -126,32 +102,26 @@ impl<F> WebProxyTokens for F where F: Fn(String) -> bool + Send + Sync {
|
|||||||
pub struct ServerBuilder<T: Fetch = FetchClient> {
|
pub struct ServerBuilder<T: Fetch = FetchClient> {
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
handler: Arc<IoHandler>,
|
|
||||||
registrar: Arc<ContractClient>,
|
registrar: Arc<ContractClient>,
|
||||||
sync_status: Arc<SyncStatus>,
|
sync_status: Arc<SyncStatus>,
|
||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
signer_address: Option<(String, u16)>,
|
signer_address: Option<(String, u16)>,
|
||||||
|
allowed_hosts: Option<Vec<String>>,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
fetch: Option<T>,
|
fetch: Option<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Fetch> Extendable for ServerBuilder<T> {
|
|
||||||
fn add_delegate<D: Send + Sync + 'static>(&self, delegate: IoDelegate<D>) {
|
|
||||||
self.handler.add_delegate(delegate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ServerBuilder {
|
impl ServerBuilder {
|
||||||
/// Construct new dapps server
|
/// Construct new dapps server
|
||||||
pub fn new<P: AsRef<Path>>(dapps_path: P, registrar: Arc<ContractClient>, remote: Remote) -> Self {
|
pub fn new<P: AsRef<Path>>(dapps_path: P, registrar: Arc<ContractClient>, remote: Remote) -> Self {
|
||||||
ServerBuilder {
|
ServerBuilder {
|
||||||
dapps_path: dapps_path.as_ref().to_owned(),
|
dapps_path: dapps_path.as_ref().to_owned(),
|
||||||
extra_dapps: vec![],
|
extra_dapps: vec![],
|
||||||
handler: Arc::new(IoHandler::new()),
|
|
||||||
registrar: registrar,
|
registrar: registrar,
|
||||||
sync_status: Arc::new(|| false),
|
sync_status: Arc::new(|| false),
|
||||||
web_proxy_tokens: Arc::new(|_| false),
|
web_proxy_tokens: Arc::new(|_| false),
|
||||||
signer_address: None,
|
signer_address: None,
|
||||||
|
allowed_hosts: Some(vec![]),
|
||||||
remote: remote,
|
remote: remote,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
}
|
}
|
||||||
@ -164,11 +134,11 @@ impl<T: Fetch> ServerBuilder<T> {
|
|||||||
ServerBuilder {
|
ServerBuilder {
|
||||||
dapps_path: self.dapps_path,
|
dapps_path: self.dapps_path,
|
||||||
extra_dapps: vec![],
|
extra_dapps: vec![],
|
||||||
handler: self.handler,
|
|
||||||
registrar: self.registrar,
|
registrar: self.registrar,
|
||||||
sync_status: self.sync_status,
|
sync_status: self.sync_status,
|
||||||
web_proxy_tokens: self.web_proxy_tokens,
|
web_proxy_tokens: self.web_proxy_tokens,
|
||||||
signer_address: self.signer_address,
|
signer_address: self.signer_address,
|
||||||
|
allowed_hosts: self.allowed_hosts,
|
||||||
remote: self.remote,
|
remote: self.remote,
|
||||||
fetch: Some(fetch),
|
fetch: Some(fetch),
|
||||||
}
|
}
|
||||||
@ -192,6 +162,14 @@ impl<T: Fetch> ServerBuilder<T> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Change allowed hosts.
|
||||||
|
/// `None` - All hosts are allowed
|
||||||
|
/// `Some(whitelist)` - Allow only whitelisted hosts (+ listen address)
|
||||||
|
pub fn allowed_hosts(mut self, allowed_hosts: Option<Vec<String>>) -> Self {
|
||||||
|
self.allowed_hosts = allowed_hosts;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Change extra dapps paths (apart from `dapps_path`)
|
/// Change extra dapps paths (apart from `dapps_path`)
|
||||||
pub fn extra_dapps<P: AsRef<Path>>(mut self, extra_dapps: &[P]) -> Self {
|
pub fn extra_dapps<P: AsRef<Path>>(mut self, extra_dapps: &[P]) -> Self {
|
||||||
self.extra_dapps = extra_dapps.iter().map(|p| p.as_ref().to_owned()).collect();
|
self.extra_dapps = extra_dapps.iter().map(|p| p.as_ref().to_owned()).collect();
|
||||||
@ -200,39 +178,41 @@ impl<T: Fetch> ServerBuilder<T> {
|
|||||||
|
|
||||||
/// Asynchronously start server with no authentication,
|
/// Asynchronously start server with no authentication,
|
||||||
/// returns result with `Server` handle on success or an error.
|
/// returns result with `Server` handle on success or an error.
|
||||||
pub fn start_unsecured_http(self, addr: &SocketAddr, hosts: Option<Vec<String>>) -> Result<Server, ServerError> {
|
pub fn start_unsecured_http(self, addr: &SocketAddr, handler: RpcHandler<Metadata>) -> Result<Server, ServerError> {
|
||||||
|
let fetch = self.fetch_client()?;
|
||||||
Server::start_http(
|
Server::start_http(
|
||||||
addr,
|
addr,
|
||||||
hosts,
|
self.allowed_hosts,
|
||||||
NoAuth,
|
NoAuth,
|
||||||
self.handler.clone(),
|
handler,
|
||||||
self.dapps_path.clone(),
|
self.dapps_path,
|
||||||
self.extra_dapps.clone(),
|
self.extra_dapps,
|
||||||
self.signer_address.clone(),
|
self.signer_address,
|
||||||
self.registrar.clone(),
|
self.registrar,
|
||||||
self.sync_status.clone(),
|
self.sync_status,
|
||||||
self.web_proxy_tokens.clone(),
|
self.web_proxy_tokens,
|
||||||
self.remote.clone(),
|
self.remote,
|
||||||
self.fetch_client()?,
|
fetch,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously start server with `HTTP Basic Authentication`,
|
/// Asynchronously start server with `HTTP Basic Authentication`,
|
||||||
/// return result with `Server` handle on success or an error.
|
/// return result with `Server` handle on success or an error.
|
||||||
pub fn start_basic_auth_http(self, addr: &SocketAddr, hosts: Option<Vec<String>>, username: &str, password: &str) -> Result<Server, ServerError> {
|
pub fn start_basic_auth_http(self, addr: &SocketAddr, username: &str, password: &str, handler: RpcHandler<Metadata>) -> Result<Server, ServerError> {
|
||||||
|
let fetch = self.fetch_client()?;
|
||||||
Server::start_http(
|
Server::start_http(
|
||||||
addr,
|
addr,
|
||||||
hosts,
|
self.allowed_hosts,
|
||||||
HttpBasicAuth::single_user(username, password),
|
HttpBasicAuth::single_user(username, password),
|
||||||
self.handler.clone(),
|
handler,
|
||||||
self.dapps_path.clone(),
|
self.dapps_path,
|
||||||
self.extra_dapps.clone(),
|
self.extra_dapps,
|
||||||
self.signer_address.clone(),
|
self.signer_address,
|
||||||
self.registrar.clone(),
|
self.registrar,
|
||||||
self.sync_status.clone(),
|
self.sync_status,
|
||||||
self.web_proxy_tokens.clone(),
|
self.web_proxy_tokens,
|
||||||
self.remote.clone(),
|
self.remote,
|
||||||
self.fetch_client()?,
|
fetch,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +261,7 @@ impl Server {
|
|||||||
addr: &SocketAddr,
|
addr: &SocketAddr,
|
||||||
hosts: Option<Vec<String>>,
|
hosts: Option<Vec<String>>,
|
||||||
authorization: A,
|
authorization: A,
|
||||||
handler: Arc<IoHandler>,
|
handler: RpcHandler<Metadata>,
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
signer_address: Option<(String, u16)>,
|
signer_address: Option<(String, u16)>,
|
||||||
|
@ -17,13 +17,15 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use hyper;
|
use hyper;
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, ResponseHandler, Request, Response};
|
use ethcore_rpc::{Metadata, Origin};
|
||||||
use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin, RpcHandler};
|
use jsonrpc_core::reactor::RpcHandler;
|
||||||
|
use jsonrpc_http_server::{Rpc, ServerHandler, PanicHandler, AccessControlAllowOrigin, HttpMetaExtractor};
|
||||||
use endpoint::{Endpoint, EndpointPath, Handler};
|
use endpoint::{Endpoint, EndpointPath, Handler};
|
||||||
|
|
||||||
pub fn rpc(handler: Arc<IoHandler>, panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>) -> Box<Endpoint> {
|
pub fn rpc(handler: RpcHandler<Metadata>, panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>) -> Box<Endpoint> {
|
||||||
Box::new(RpcEndpoint {
|
Box::new(RpcEndpoint {
|
||||||
handler: Arc::new(RpcMiddleware::new(handler)),
|
handler: handler,
|
||||||
|
meta_extractor: Arc::new(MetadataExtractor),
|
||||||
panic_handler: panic_handler,
|
panic_handler: panic_handler,
|
||||||
cors_domain: None,
|
cors_domain: None,
|
||||||
// NOTE [ToDr] We don't need to do any hosts validation here. It's already done in router.
|
// NOTE [ToDr] We don't need to do any hosts validation here. It's already done in router.
|
||||||
@ -32,7 +34,8 @@ pub fn rpc(handler: Arc<IoHandler>, panic_handler: Arc<Mutex<Option<Box<Fn() ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct RpcEndpoint {
|
struct RpcEndpoint {
|
||||||
handler: Arc<RpcMiddleware>,
|
handler: RpcHandler<Metadata>,
|
||||||
|
meta_extractor: Arc<HttpMetaExtractor<Metadata>>,
|
||||||
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
|
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
|
||||||
cors_domain: Option<Vec<AccessControlAllowOrigin>>,
|
cors_domain: Option<Vec<AccessControlAllowOrigin>>,
|
||||||
allowed_hosts: Option<Vec<String>>,
|
allowed_hosts: Option<Vec<String>>,
|
||||||
@ -42,7 +45,7 @@ impl Endpoint for RpcEndpoint {
|
|||||||
fn to_async_handler(&self, _path: EndpointPath, control: hyper::Control) -> Box<Handler> {
|
fn to_async_handler(&self, _path: EndpointPath, control: hyper::Control) -> Box<Handler> {
|
||||||
let panic_handler = PanicHandler { handler: self.panic_handler.clone() };
|
let panic_handler = PanicHandler { handler: self.panic_handler.clone() };
|
||||||
Box::new(ServerHandler::new(
|
Box::new(ServerHandler::new(
|
||||||
self.handler.clone(),
|
Rpc::new(self.handler.clone(), self.meta_extractor.clone()),
|
||||||
self.cors_domain.clone(),
|
self.cors_domain.clone(),
|
||||||
self.allowed_hosts.clone(),
|
self.allowed_hosts.clone(),
|
||||||
panic_handler,
|
panic_handler,
|
||||||
@ -51,85 +54,19 @@ impl Endpoint for RpcEndpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RpcMiddleware {
|
struct MetadataExtractor;
|
||||||
handler: Arc<IoHandler>,
|
impl HttpMetaExtractor<Metadata> for MetadataExtractor {
|
||||||
methods: Vec<String>,
|
fn read_metadata(&self, request: &hyper::server::Request<hyper::net::HttpStream>) -> Metadata {
|
||||||
}
|
let dapp_id = request.headers().get::<hyper::header::Referer>()
|
||||||
|
|
||||||
impl RpcMiddleware {
|
|
||||||
fn new(handler: Arc<IoHandler>) -> Self {
|
|
||||||
RpcMiddleware {
|
|
||||||
handler: handler,
|
|
||||||
methods: vec!["eth_accounts".into(), "parity_accountsInfo".into()],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Appends additional parameter for specific calls.
|
|
||||||
fn augment_request(&self, request: &mut Request, meta: Option<Meta>) {
|
|
||||||
use jsonrpc_core::{Call, Params, to_value};
|
|
||||||
|
|
||||||
fn augment_call(call: &mut Call, meta: Option<&Meta>, methods: &Vec<String>) {
|
|
||||||
match (call, meta) {
|
|
||||||
(&mut Call::MethodCall(ref mut method_call), Some(meta)) if methods.contains(&method_call.method) => {
|
|
||||||
let session = to_value(&meta.app_id);
|
|
||||||
|
|
||||||
let params = match method_call.params {
|
|
||||||
Some(Params::Array(ref vec)) if vec.len() == 0 => Some(Params::Array(vec![session])),
|
|
||||||
// invalid params otherwise
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
method_call.params = params;
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match *request {
|
|
||||||
Request::Single(ref mut call) => augment_call(call, meta.as_ref(), &self.methods),
|
|
||||||
Request::Batch(ref mut vec) => {
|
|
||||||
for mut call in vec {
|
|
||||||
augment_call(call, meta.as_ref(), &self.methods)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Meta {
|
|
||||||
app_id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RpcHandler for RpcMiddleware {
|
|
||||||
type Metadata = Meta;
|
|
||||||
|
|
||||||
fn read_metadata(&self, request: &hyper::server::Request<hyper::net::HttpStream>) -> Option<Self::Metadata> {
|
|
||||||
request.headers().get::<hyper::header::Referer>()
|
|
||||||
.and_then(|referer| hyper::Url::parse(referer).ok())
|
.and_then(|referer| hyper::Url::parse(referer).ok())
|
||||||
.and_then(|url| {
|
.and_then(|url| {
|
||||||
url.path_segments()
|
url.path_segments()
|
||||||
.and_then(|mut split| split.next())
|
.and_then(|mut split| split.next())
|
||||||
.map(|app_id| Meta {
|
.map(|app_id| app_id.to_owned())
|
||||||
app_id: app_id.to_owned(),
|
});
|
||||||
})
|
Metadata {
|
||||||
})
|
dapp_id: dapp_id,
|
||||||
}
|
origin: Origin::Dapps,
|
||||||
|
|
||||||
fn handle_request<H>(&self, request_str: &str, response_handler: H, meta: Option<Self::Metadata>) where
|
|
||||||
H: ResponseHandler<Option<String>, Option<String>> + 'static
|
|
||||||
{
|
|
||||||
let handler = IoHandler::convert_handler(response_handler);
|
|
||||||
let request = IoHandler::read_request(request_str);
|
|
||||||
trace!(target: "rpc", "Request metadata: {:?}", meta);
|
|
||||||
|
|
||||||
match request {
|
|
||||||
Ok(mut request) => {
|
|
||||||
self.augment_request(&mut request, meta);
|
|
||||||
self.handler.request_handler().handle_request(request, handler, None)
|
|
||||||
},
|
|
||||||
Err(error) => handler.send(Some(Response::from(error))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use env_logger::LogBuilder;
|
use env_logger::LogBuilder;
|
||||||
|
use jsonrpc_core::MetaIoHandler;
|
||||||
|
use jsonrpc_core::reactor::RpcEventLoop;
|
||||||
|
|
||||||
use ServerBuilder;
|
use ServerBuilder;
|
||||||
use Server;
|
use Server;
|
||||||
@ -42,7 +45,20 @@ fn init_logger() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_server<F, B>(hosts: Option<Vec<String>>, process: F, remote: Remote) -> (Server, Arc<FakeRegistrar>) where
|
pub struct ServerLoop {
|
||||||
|
pub server: Server,
|
||||||
|
pub event_loop: RpcEventLoop,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ServerLoop {
|
||||||
|
type Target = Server;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.server
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_server<F, B>(process: F, remote: Remote) -> (ServerLoop, Arc<FakeRegistrar>) where
|
||||||
F: FnOnce(ServerBuilder) -> ServerBuilder<B>,
|
F: FnOnce(ServerBuilder) -> ServerBuilder<B>,
|
||||||
B: Fetch,
|
B: Fetch,
|
||||||
{
|
{
|
||||||
@ -50,60 +66,76 @@ pub fn init_server<F, B>(hosts: Option<Vec<String>>, process: F, remote: Remote)
|
|||||||
let registrar = Arc::new(FakeRegistrar::new());
|
let registrar = Arc::new(FakeRegistrar::new());
|
||||||
let mut dapps_path = env::temp_dir();
|
let mut dapps_path = env::temp_dir();
|
||||||
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
||||||
|
|
||||||
|
// TODO [ToDr] When https://github.com/ethcore/jsonrpc/issues/26 is resolved
|
||||||
|
// this additional EventLoop wouldn't be needed, we should be able to re-use remote.
|
||||||
|
let event_loop = RpcEventLoop::spawn();
|
||||||
|
let handler = event_loop.handler(Arc::new(MetaIoHandler::default()));
|
||||||
let server = process(ServerBuilder::new(
|
let server = process(ServerBuilder::new(
|
||||||
&dapps_path, registrar.clone(), remote,
|
&dapps_path, registrar.clone(), remote,
|
||||||
))
|
))
|
||||||
.signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)))
|
.signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)))
|
||||||
.start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), hosts).unwrap();
|
.start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), handler).unwrap();
|
||||||
(
|
(
|
||||||
server,
|
ServerLoop { server: server, event_loop: event_loop },
|
||||||
registrar,
|
registrar,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_with_auth(user: &str, pass: &str) -> Server {
|
pub fn serve_with_auth(user: &str, pass: &str) -> ServerLoop {
|
||||||
init_logger();
|
init_logger();
|
||||||
let registrar = Arc::new(FakeRegistrar::new());
|
let registrar = Arc::new(FakeRegistrar::new());
|
||||||
let mut dapps_path = env::temp_dir();
|
let mut dapps_path = env::temp_dir();
|
||||||
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
||||||
ServerBuilder::new(&dapps_path, registrar.clone(), Remote::new_sync())
|
|
||||||
|
let event_loop = RpcEventLoop::spawn();
|
||||||
|
let handler = event_loop.handler(Arc::new(MetaIoHandler::default()));
|
||||||
|
let server = ServerBuilder::new(&dapps_path, registrar, Remote::new(event_loop.remote()))
|
||||||
.signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)))
|
.signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)))
|
||||||
.start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), None, user, pass).unwrap()
|
.allowed_hosts(None)
|
||||||
|
.start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), user, pass, handler).unwrap();
|
||||||
|
ServerLoop {
|
||||||
|
server: server,
|
||||||
|
event_loop: event_loop,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_hosts(hosts: Option<Vec<String>>) -> Server {
|
pub fn serve_hosts(hosts: Option<Vec<String>>) -> ServerLoop {
|
||||||
init_server(hosts, |builder| builder, Remote::new_sync()).0
|
init_server(|builder| builder.allowed_hosts(hosts), Remote::new_sync()).0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_with_registrar() -> (Server, Arc<FakeRegistrar>) {
|
pub fn serve_with_registrar() -> (ServerLoop, Arc<FakeRegistrar>) {
|
||||||
init_server(None, |builder| builder, Remote::new_sync())
|
init_server(|builder| builder.allowed_hosts(None), Remote::new_sync())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_with_registrar_and_sync() -> (Server, Arc<FakeRegistrar>) {
|
pub fn serve_with_registrar_and_sync() -> (ServerLoop, Arc<FakeRegistrar>) {
|
||||||
init_server(None, |builder| {
|
init_server(|builder| {
|
||||||
builder.sync_status(Arc::new(|| true))
|
builder
|
||||||
|
.sync_status(Arc::new(|| true))
|
||||||
|
.allowed_hosts(None)
|
||||||
}, Remote::new_sync())
|
}, Remote::new_sync())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_with_registrar_and_fetch() -> (Server, FakeFetch, Arc<FakeRegistrar>) {
|
pub fn serve_with_registrar_and_fetch() -> (ServerLoop, FakeFetch, Arc<FakeRegistrar>) {
|
||||||
serve_with_registrar_and_fetch_and_threads(false)
|
serve_with_registrar_and_fetch_and_threads(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_with_registrar_and_fetch_and_threads(multi_threaded: bool) -> (Server, FakeFetch, Arc<FakeRegistrar>) {
|
pub fn serve_with_registrar_and_fetch_and_threads(multi_threaded: bool) -> (ServerLoop, FakeFetch, Arc<FakeRegistrar>) {
|
||||||
let fetch = FakeFetch::default();
|
let fetch = FakeFetch::default();
|
||||||
let f = fetch.clone();
|
let f = fetch.clone();
|
||||||
let (server, reg) = init_server(None, move |builder| {
|
let (server, reg) = init_server(move |builder| {
|
||||||
builder.fetch(f.clone())
|
builder.allowed_hosts(None).fetch(f.clone())
|
||||||
}, if multi_threaded { Remote::new_thread_per_future() } else { Remote::new_sync() });
|
}, if multi_threaded { Remote::new_thread_per_future() } else { Remote::new_sync() });
|
||||||
|
|
||||||
(server, fetch, reg)
|
(server, fetch, reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_with_fetch(web_token: &'static str) -> (Server, FakeFetch) {
|
pub fn serve_with_fetch(web_token: &'static str) -> (ServerLoop, FakeFetch) {
|
||||||
let fetch = FakeFetch::default();
|
let fetch = FakeFetch::default();
|
||||||
let f = fetch.clone();
|
let f = fetch.clone();
|
||||||
let (server, _) = init_server(None, move |builder| {
|
let (server, _) = init_server(move |builder| {
|
||||||
builder
|
builder
|
||||||
|
.allowed_hosts(None)
|
||||||
.fetch(f.clone())
|
.fetch(f.clone())
|
||||||
.web_proxy_tokens(Arc::new(move |token| &token == web_token))
|
.web_proxy_tokens(Arc::new(move |token| &token == web_token))
|
||||||
}, Remote::new_sync());
|
}, Remote::new_sync());
|
||||||
@ -111,11 +143,11 @@ pub fn serve_with_fetch(web_token: &'static str) -> (Server, FakeFetch) {
|
|||||||
(server, fetch)
|
(server, fetch)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve() -> Server {
|
pub fn serve() -> ServerLoop {
|
||||||
init_server(None, |builder| builder, Remote::new_sync()).0
|
init_server(|builder| builder.allowed_hosts(None), Remote::new_sync()).0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request(server: Server, request: &str) -> http_client::Response {
|
pub fn request(server: ServerLoop, request: &str) -> http_client::Response {
|
||||||
http_client::request(server.addr(), request)
|
http_client::request(server.addr(), request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,9 @@ pub trait LightChainClient: Send + Sync {
|
|||||||
/// Clear the queue.
|
/// Clear the queue.
|
||||||
fn clear_queue(&self);
|
fn clear_queue(&self);
|
||||||
|
|
||||||
|
/// Flush the queue.
|
||||||
|
fn flush_queue(&self);
|
||||||
|
|
||||||
/// Get queue info.
|
/// Get queue info.
|
||||||
fn queue_info(&self) -> queue::QueueInfo;
|
fn queue_info(&self) -> queue::QueueInfo;
|
||||||
|
|
||||||
@ -130,7 +133,7 @@ impl Client {
|
|||||||
|
|
||||||
BlockChainInfo {
|
BlockChainInfo {
|
||||||
total_difficulty: best_block.total_difficulty,
|
total_difficulty: best_block.total_difficulty,
|
||||||
pending_total_difficulty: best_block.total_difficulty,
|
pending_total_difficulty: best_block.total_difficulty + self.queue.total_difficulty(),
|
||||||
genesis_hash: genesis_hash,
|
genesis_hash: genesis_hash,
|
||||||
best_block_hash: best_block.hash,
|
best_block_hash: best_block.hash,
|
||||||
best_block_number: best_block.number,
|
best_block_number: best_block.number,
|
||||||
@ -151,6 +154,11 @@ impl Client {
|
|||||||
self.chain.get_header(id)
|
self.chain.get_header(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flush the header queue.
|
||||||
|
pub fn flush_queue(&self) {
|
||||||
|
self.queue.flush()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the `i`th CHT root.
|
/// Get the `i`th CHT root.
|
||||||
pub fn cht_root(&self, i: usize) -> Option<H256> {
|
pub fn cht_root(&self, i: usize) -> Option<H256> {
|
||||||
self.chain.cht_root(i)
|
self.chain.cht_root(i)
|
||||||
@ -211,6 +219,10 @@ impl LightChainClient for Client {
|
|||||||
self.queue.clear()
|
self.queue.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush_queue(&self) {
|
||||||
|
Client::flush_queue(self);
|
||||||
|
}
|
||||||
|
|
||||||
fn queue_info(&self) -> queue::QueueInfo {
|
fn queue_info(&self) -> queue::QueueInfo {
|
||||||
self.queue.queue_info()
|
self.queue.queue_info()
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
//! This module provides an interface for configuration of buffer
|
//! This module provides an interface for configuration of buffer
|
||||||
//! flow costs and recharge rates.
|
//! flow costs and recharge rates.
|
||||||
//!
|
//!
|
||||||
//! Current default costs are picked completely arbitrarily, not based
|
//! Current default costs are picked completely arbitrarily, not based
|
||||||
//! on any empirical timings or mathematical models.
|
//! on any empirical timings or mathematical models.
|
||||||
|
|
||||||
use request;
|
use request;
|
||||||
@ -184,6 +184,23 @@ impl FlowParams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create effectively infinite flow params.
|
||||||
|
pub fn free() -> Self {
|
||||||
|
let free_cost = Cost(0.into(), 0.into());
|
||||||
|
FlowParams {
|
||||||
|
limit: (!0u64).into(),
|
||||||
|
recharge: 1.into(),
|
||||||
|
costs: CostTable {
|
||||||
|
headers: free_cost.clone(),
|
||||||
|
bodies: free_cost.clone(),
|
||||||
|
receipts: free_cost.clone(),
|
||||||
|
state_proofs: free_cost.clone(),
|
||||||
|
contract_codes: free_cost.clone(),
|
||||||
|
header_proofs: free_cost.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a reference to the buffer limit.
|
/// Get a reference to the buffer limit.
|
||||||
pub fn limit(&self) -> &U256 { &self.limit }
|
pub fn limit(&self) -> &U256 { &self.limit }
|
||||||
|
|
||||||
@ -209,7 +226,7 @@ impl FlowParams {
|
|||||||
cost.0 + (amount * cost.1)
|
cost.0 + (amount * cost.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the maximum number of costs of a specific kind which can be made
|
/// Compute the maximum number of costs of a specific kind which can be made
|
||||||
/// with the given buffer.
|
/// with the given buffer.
|
||||||
/// Saturates at `usize::max()`. This is not a problem in practice because
|
/// Saturates at `usize::max()`. This is not a problem in practice because
|
||||||
/// this amount of requests is already prohibitively large.
|
/// this amount of requests is already prohibitively large.
|
||||||
@ -317,4 +334,4 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(buffer.estimate, 100.into());
|
assert_eq!(buffer.estimate, 100.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ use self::buffer_flow::{Buffer, FlowParams};
|
|||||||
use self::context::{Ctx, TickCtx};
|
use self::context::{Ctx, TickCtx};
|
||||||
use self::error::Punishment;
|
use self::error::Punishment;
|
||||||
|
|
||||||
mod buffer_flow;
|
|
||||||
mod context;
|
mod context;
|
||||||
mod error;
|
mod error;
|
||||||
mod status;
|
mod status;
|
||||||
@ -49,6 +48,8 @@ mod status;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
pub mod buffer_flow;
|
||||||
|
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
pub use self::context::{BasicContext, EventContext, IoContext};
|
pub use self::context::{BasicContext, EventContext, IoContext};
|
||||||
pub use self::status::{Status, Capabilities, Announcement};
|
pub use self::status::{Status, Capabilities, Announcement};
|
||||||
@ -244,7 +245,7 @@ pub struct LightProtocol {
|
|||||||
pending_requests: RwLock<HashMap<usize, Requested>>,
|
pending_requests: RwLock<HashMap<usize, Requested>>,
|
||||||
capabilities: RwLock<Capabilities>,
|
capabilities: RwLock<Capabilities>,
|
||||||
flow_params: FlowParams, // assumed static and same for every peer.
|
flow_params: FlowParams, // assumed static and same for every peer.
|
||||||
handlers: Vec<Box<Handler>>,
|
handlers: Vec<Arc<Handler>>,
|
||||||
req_id: AtomicUsize,
|
req_id: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,11 +384,11 @@ impl LightProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add an event handler.
|
/// Add an event handler.
|
||||||
/// Ownership will be transferred to the protocol structure,
|
///
|
||||||
/// and the handler will be kept alive as long as it is.
|
|
||||||
/// These are intended to be added when the protocol structure
|
/// These are intended to be added when the protocol structure
|
||||||
/// is initialized as a means of customizing its behavior.
|
/// is initialized as a means of customizing its behavior,
|
||||||
pub fn add_handler(&mut self, handler: Box<Handler>) {
|
/// and dispatching requests immediately upon events.
|
||||||
|
pub fn add_handler(&mut self, handler: Arc<Handler>) {
|
||||||
self.handlers.push(handler);
|
self.handlers.push(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,8 +448,10 @@ impl LightProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle a packet using the given io context.
|
/// Handle an LES packet using the given io context.
|
||||||
fn handle_packet(&self, io: &IoContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
/// Packet data is _untrusted_, which means that invalid data won't lead to
|
||||||
|
/// issues.
|
||||||
|
pub fn handle_packet(&self, io: &IoContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
||||||
let rlp = UntrustedRlp::new(data);
|
let rlp = UntrustedRlp::new(data);
|
||||||
|
|
||||||
trace!(target: "les", "Incoming packet {} from peer {}", packet_id, peer);
|
trace!(target: "les", "Incoming packet {} from peer {}", packet_id, peer);
|
||||||
@ -488,6 +491,71 @@ impl LightProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// called when a peer connects.
|
||||||
|
pub fn on_connect(&self, peer: &PeerId, io: &IoContext) {
|
||||||
|
let proto_version = match io.protocol_version(*peer).ok_or(Error::WrongNetwork) {
|
||||||
|
Ok(pv) => pv,
|
||||||
|
Err(e) => { punish(*peer, io, e); return }
|
||||||
|
};
|
||||||
|
|
||||||
|
if PROTOCOL_VERSIONS.iter().find(|x| **x == proto_version).is_none() {
|
||||||
|
punish(*peer, io, Error::UnsupportedProtocolVersion(proto_version));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let chain_info = self.provider.chain_info();
|
||||||
|
|
||||||
|
let status = Status {
|
||||||
|
head_td: chain_info.total_difficulty,
|
||||||
|
head_hash: chain_info.best_block_hash,
|
||||||
|
head_num: chain_info.best_block_number,
|
||||||
|
genesis_hash: chain_info.genesis_hash,
|
||||||
|
protocol_version: proto_version as u32, // match peer proto version
|
||||||
|
network_id: self.network_id,
|
||||||
|
last_head: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let capabilities = self.capabilities.read().clone();
|
||||||
|
let status_packet = status::write_handshake(&status, &capabilities, Some(&self.flow_params));
|
||||||
|
|
||||||
|
self.pending_peers.write().insert(*peer, PendingPeer {
|
||||||
|
sent_head: chain_info.best_block_hash,
|
||||||
|
last_update: SteadyTime::now(),
|
||||||
|
});
|
||||||
|
|
||||||
|
io.send(*peer, packet::STATUS, status_packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// called when a peer disconnects.
|
||||||
|
pub fn on_disconnect(&self, peer: PeerId, io: &IoContext) {
|
||||||
|
trace!(target: "les", "Peer {} disconnecting", peer);
|
||||||
|
|
||||||
|
|
||||||
|
self.pending_peers.write().remove(&peer);
|
||||||
|
if self.peers.write().remove(&peer).is_some() {
|
||||||
|
let unfulfilled: Vec<_> = self.pending_requests.read()
|
||||||
|
.iter()
|
||||||
|
.filter(|&(_, r)| r.peer_id == peer)
|
||||||
|
.map(|(&id, _)| ReqId(id))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut pending = self.pending_requests.write();
|
||||||
|
for &ReqId(ref inner) in &unfulfilled {
|
||||||
|
pending.remove(inner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for handler in &self.handlers {
|
||||||
|
handler.on_disconnect(&Ctx {
|
||||||
|
peer: peer,
|
||||||
|
io: io,
|
||||||
|
proto: self,
|
||||||
|
}, &unfulfilled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check timeouts and punish peers.
|
// check timeouts and punish peers.
|
||||||
fn timeout_check(&self, io: &IoContext) {
|
fn timeout_check(&self, io: &IoContext) {
|
||||||
let now = SteadyTime::now();
|
let now = SteadyTime::now();
|
||||||
@ -536,6 +604,16 @@ impl LightProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute the given closure with a basic context derived from the I/O context.
|
||||||
|
pub fn with_context<F, T>(&self, io: &IoContext, f: F) -> T
|
||||||
|
where F: FnOnce(&BasicContext) -> T
|
||||||
|
{
|
||||||
|
f(&TickCtx {
|
||||||
|
io: io,
|
||||||
|
proto: self,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn tick_handlers(&self, io: &IoContext) {
|
fn tick_handlers(&self, io: &IoContext) {
|
||||||
for handler in &self.handlers {
|
for handler in &self.handlers {
|
||||||
handler.tick(&TickCtx {
|
handler.tick(&TickCtx {
|
||||||
@ -547,71 +625,6 @@ impl LightProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LightProtocol {
|
impl LightProtocol {
|
||||||
// called when a peer connects.
|
|
||||||
fn on_connect(&self, peer: &PeerId, io: &IoContext) {
|
|
||||||
let proto_version = match io.protocol_version(*peer).ok_or(Error::WrongNetwork) {
|
|
||||||
Ok(pv) => pv,
|
|
||||||
Err(e) => { punish(*peer, io, e); return }
|
|
||||||
};
|
|
||||||
|
|
||||||
if PROTOCOL_VERSIONS.iter().find(|x| **x == proto_version).is_none() {
|
|
||||||
punish(*peer, io, Error::UnsupportedProtocolVersion(proto_version));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let chain_info = self.provider.chain_info();
|
|
||||||
|
|
||||||
let status = Status {
|
|
||||||
head_td: chain_info.total_difficulty,
|
|
||||||
head_hash: chain_info.best_block_hash,
|
|
||||||
head_num: chain_info.best_block_number,
|
|
||||||
genesis_hash: chain_info.genesis_hash,
|
|
||||||
protocol_version: proto_version as u32, // match peer proto version
|
|
||||||
network_id: self.network_id,
|
|
||||||
last_head: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let capabilities = self.capabilities.read().clone();
|
|
||||||
let status_packet = status::write_handshake(&status, &capabilities, Some(&self.flow_params));
|
|
||||||
|
|
||||||
self.pending_peers.write().insert(*peer, PendingPeer {
|
|
||||||
sent_head: chain_info.best_block_hash,
|
|
||||||
last_update: SteadyTime::now(),
|
|
||||||
});
|
|
||||||
|
|
||||||
io.send(*peer, packet::STATUS, status_packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when a peer disconnects.
|
|
||||||
fn on_disconnect(&self, peer: PeerId, io: &IoContext) {
|
|
||||||
trace!(target: "les", "Peer {} disconnecting", peer);
|
|
||||||
|
|
||||||
|
|
||||||
self.pending_peers.write().remove(&peer);
|
|
||||||
if self.peers.write().remove(&peer).is_some() {
|
|
||||||
let unfulfilled: Vec<_> = self.pending_requests.read()
|
|
||||||
.iter()
|
|
||||||
.filter(|&(_, r)| r.peer_id == peer)
|
|
||||||
.map(|(&id, _)| ReqId(id))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut pending = self.pending_requests.write();
|
|
||||||
for &ReqId(ref inner) in &unfulfilled {
|
|
||||||
pending.remove(inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for handler in &self.handlers {
|
|
||||||
handler.on_disconnect(&Ctx {
|
|
||||||
peer: peer,
|
|
||||||
io: io,
|
|
||||||
proto: self,
|
|
||||||
}, &unfulfilled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle status message from peer.
|
// Handle status message from peer.
|
||||||
fn status(&self, peer: &PeerId, io: &IoContext, data: UntrustedRlp) -> Result<(), Error> {
|
fn status(&self, peer: &PeerId, io: &IoContext, data: UntrustedRlp) -> Result<(), Error> {
|
||||||
let pending = match self.pending_peers.write().remove(peer) {
|
let pending = match self.pending_peers.write().remove(peer) {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
//! These don't test of the higher level logic on top of
|
//! These don't test of the higher level logic on top of
|
||||||
|
|
||||||
use ethcore::blockchain_info::BlockChainInfo;
|
use ethcore::blockchain_info::BlockChainInfo;
|
||||||
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient};
|
use ethcore::client::{EachBlockWith, TestBlockChainClient};
|
||||||
use ethcore::ids::BlockId;
|
use ethcore::ids::BlockId;
|
||||||
use ethcore::transaction::PendingTransaction;
|
use ethcore::transaction::PendingTransaction;
|
||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
@ -88,7 +88,7 @@ impl Provider for TestProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64> {
|
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64> {
|
||||||
self.0.client.tree_route(a, b).map(|route| route.index as u64)
|
self.0.client.reorg_depth(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn earliest_state(&self) -> Option<u64> {
|
fn earliest_state(&self) -> Option<u64> {
|
||||||
@ -305,7 +305,9 @@ fn get_block_bodies() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let request = request::Bodies {
|
let request = request::Bodies {
|
||||||
block_hashes: (0..10).map(|i| provider.client.block_hash(BlockId::Number(i)).unwrap()).collect(),
|
block_hashes: (0..10).map(|i|
|
||||||
|
provider.client.block_header(BlockId::Number(i)).unwrap().hash()
|
||||||
|
).collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
let req_id = 111;
|
let req_id = 111;
|
||||||
@ -353,8 +355,9 @@ fn get_block_receipts() {
|
|||||||
|
|
||||||
// find the first 10 block hashes starting with `f` because receipts are only provided
|
// find the first 10 block hashes starting with `f` because receipts are only provided
|
||||||
// by the test client in that case.
|
// by the test client in that case.
|
||||||
let block_hashes: Vec<_> = (0..1000).map(|i| provider.client.block_hash(BlockId::Number(i)).unwrap())
|
let block_hashes: Vec<_> = (0..1000).map(|i|
|
||||||
.filter(|hash| format!("{}", hash).starts_with("f")).take(10).collect();
|
provider.client.block_header(BlockId::Number(i)).unwrap().hash()
|
||||||
|
).filter(|hash| format!("{}", hash).starts_with("f")).take(10).collect();
|
||||||
|
|
||||||
let request = request::Receipts {
|
let request = request::Receipts {
|
||||||
block_hashes: block_hashes.clone(),
|
block_hashes: block_hashes.clone(),
|
||||||
|
@ -83,7 +83,7 @@ pub trait Provider: Send + Sync {
|
|||||||
|
|
||||||
(0u64..req.max as u64)
|
(0u64..req.max as u64)
|
||||||
.map(|x: u64| x.saturating_mul(req.skip + 1))
|
.map(|x: u64| x.saturating_mul(req.skip + 1))
|
||||||
.take_while(|x| if req.reverse { x < &start_num } else { best_num - start_num >= *x })
|
.take_while(|x| if req.reverse { x < &start_num } else { best_num.saturating_sub(start_num) >= *x })
|
||||||
.map(|x| if req.reverse { start_num - x } else { start_num + x })
|
.map(|x| if req.reverse { start_num - x } else { start_num + x })
|
||||||
.map(|x| self.block_header(BlockId::Number(x)))
|
.map(|x| self.block_header(BlockId::Number(x)))
|
||||||
.take_while(|x| x.is_some())
|
.take_while(|x| x.is_some())
|
||||||
|
@ -1329,6 +1329,7 @@ mod tests {
|
|||||||
use transaction::{Transaction, Action};
|
use transaction::{Transaction, Action};
|
||||||
use log_entry::{LogEntry, LocalizedLogEntry};
|
use log_entry::{LogEntry, LocalizedLogEntry};
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
|
use ethkey::Secret;
|
||||||
|
|
||||||
fn new_db(path: &str) -> Arc<Database> {
|
fn new_db(path: &str) -> Arc<Database> {
|
||||||
Arc::new(Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), path).unwrap())
|
Arc::new(Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), path).unwrap())
|
||||||
@ -1467,6 +1468,10 @@ mod tests {
|
|||||||
// TODO: insert block that already includes one of them as an uncle to check it's not allowed.
|
// TODO: insert block that already includes one of them as an uncle to check it's not allowed.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn secret() -> Secret {
|
||||||
|
Secret::from_slice(&"".sha3()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fork_transaction_addresses() {
|
fn test_fork_transaction_addresses() {
|
||||||
let mut canon_chain = ChainGenerator::default();
|
let mut canon_chain = ChainGenerator::default();
|
||||||
@ -1482,7 +1487,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
|
|
||||||
let b1a = canon_chain
|
let b1a = canon_chain
|
||||||
@ -1546,7 +1551,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
let t2 = Transaction {
|
let t2 = Transaction {
|
||||||
nonce: 1.into(),
|
nonce: 1.into(),
|
||||||
@ -1555,7 +1560,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
let t3 = Transaction {
|
let t3 = Transaction {
|
||||||
nonce: 2.into(),
|
nonce: 2.into(),
|
||||||
@ -1564,7 +1569,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
let b1a = canon_chain
|
let b1a = canon_chain
|
||||||
.with_transaction(t1.clone())
|
.with_transaction(t1.clone())
|
||||||
@ -1870,7 +1875,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 101.into(),
|
value: 101.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
let t2 = Transaction {
|
let t2 = Transaction {
|
||||||
nonce: 0.into(),
|
nonce: 0.into(),
|
||||||
gas_price: 0.into(),
|
gas_price: 0.into(),
|
||||||
@ -1878,7 +1883,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 102.into(),
|
value: 102.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
let t3 = Transaction {
|
let t3 = Transaction {
|
||||||
nonce: 0.into(),
|
nonce: 0.into(),
|
||||||
gas_price: 0.into(),
|
gas_price: 0.into(),
|
||||||
@ -1886,7 +1891,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 103.into(),
|
value: 103.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
let tx_hash1 = t1.hash();
|
let tx_hash1 = t1.hash();
|
||||||
let tx_hash2 = t2.hash();
|
let tx_hash2 = t2.hash();
|
||||||
let tx_hash3 = t3.hash();
|
let tx_hash3 = t3.hash();
|
||||||
|
@ -848,7 +848,7 @@ impl BlockChainClient for Client {
|
|||||||
difficulty: header.difficulty(),
|
difficulty: header.difficulty(),
|
||||||
last_hashes: last_hashes,
|
last_hashes: last_hashes,
|
||||||
gas_used: U256::zero(),
|
gas_used: U256::zero(),
|
||||||
gas_limit: header.gas_limit(),
|
gas_limit: U256::max_value(),
|
||||||
};
|
};
|
||||||
// that's just a copy of the state.
|
// that's just a copy of the state.
|
||||||
let mut state = self.state_at(block).ok_or(CallError::StatePruned)?;
|
let mut state = self.state_at(block).ok_or(CallError::StatePruned)?;
|
||||||
@ -874,6 +874,7 @@ impl BlockChainClient for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError> {
|
fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError> {
|
||||||
|
const UPPER_CEILING: u64 = 1_000_000_000_000u64;
|
||||||
let header = self.block_header(block).ok_or(CallError::StatePruned)?;
|
let header = self.block_header(block).ok_or(CallError::StatePruned)?;
|
||||||
let last_hashes = self.build_last_hashes(header.parent_hash());
|
let last_hashes = self.build_last_hashes(header.parent_hash());
|
||||||
let env_info = EnvInfo {
|
let env_info = EnvInfo {
|
||||||
@ -883,37 +884,38 @@ impl BlockChainClient for Client {
|
|||||||
difficulty: header.difficulty(),
|
difficulty: header.difficulty(),
|
||||||
last_hashes: last_hashes,
|
last_hashes: last_hashes,
|
||||||
gas_used: U256::zero(),
|
gas_used: U256::zero(),
|
||||||
gas_limit: header.gas_limit(),
|
gas_limit: UPPER_CEILING.into(),
|
||||||
};
|
};
|
||||||
// that's just a copy of the state.
|
// that's just a copy of the state.
|
||||||
let mut original_state = self.state_at(block).ok_or(CallError::StatePruned)?;
|
let original_state = self.state_at(block).ok_or(CallError::StatePruned)?;
|
||||||
let sender = t.sender().map_err(|e| {
|
let sender = t.sender().map_err(|e| {
|
||||||
let message = format!("Transaction malformed: {:?}", e);
|
let message = format!("Transaction malformed: {:?}", e);
|
||||||
ExecutionError::TransactionMalformed(message)
|
ExecutionError::TransactionMalformed(message)
|
||||||
})?;
|
})?;
|
||||||
let balance = original_state.balance(&sender);
|
let balance = original_state.balance(&sender);
|
||||||
let needed_balance = t.value + t.gas * t.gas_price;
|
|
||||||
if balance < needed_balance {
|
|
||||||
// give the sender a sufficient balance
|
|
||||||
original_state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty);
|
|
||||||
}
|
|
||||||
let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false };
|
let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false };
|
||||||
let mut tx = t.clone();
|
let mut tx = t.clone();
|
||||||
|
|
||||||
let mut cond = |gas| {
|
let mut cond = |gas| {
|
||||||
let mut state = original_state.clone();
|
|
||||||
tx.gas = gas;
|
tx.gas = gas;
|
||||||
|
|
||||||
|
let mut state = original_state.clone();
|
||||||
|
let needed_balance = tx.value + tx.gas * tx.gas_price;
|
||||||
|
if balance < needed_balance {
|
||||||
|
// give the sender a sufficient balance
|
||||||
|
state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm)
|
Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm)
|
||||||
.transact(&tx, options.clone())
|
.transact(&tx, options.clone())
|
||||||
.map(|r| r.trace[0].result.succeeded())
|
.map(|r| r.exception.is_some())
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut upper = env_info.gas_limit;
|
let mut upper = header.gas_limit();
|
||||||
if !cond(upper) {
|
if !cond(upper) {
|
||||||
// impossible at block gas limit - try `UPPER_CEILING` instead.
|
// impossible at block gas limit - try `UPPER_CEILING` instead.
|
||||||
// TODO: consider raising limit by powers of two.
|
// TODO: consider raising limit by powers of two.
|
||||||
const UPPER_CEILING: u64 = 1_000_000_000_000u64;
|
|
||||||
upper = UPPER_CEILING.into();
|
upper = UPPER_CEILING.into();
|
||||||
if !cond(upper) {
|
if !cond(upper) {
|
||||||
trace!(target: "estimate_gas", "estimate_gas failed with {}", upper);
|
trace!(target: "estimate_gas", "estimate_gas failed with {}", upper);
|
||||||
@ -1669,7 +1671,7 @@ mod tests {
|
|||||||
use util::Hashable;
|
use util::Hashable;
|
||||||
|
|
||||||
// given
|
// given
|
||||||
let key = KeyPair::from_secret("test".sha3()).unwrap();
|
let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap();
|
||||||
let secret = key.secret();
|
let secret = key.secret();
|
||||||
|
|
||||||
let block_number = 1;
|
let block_number = 1;
|
||||||
|
@ -26,6 +26,7 @@ use blockchain::TreeRoute;
|
|||||||
use client::{
|
use client::{
|
||||||
BlockChainClient, MiningBlockChainClient, EngineClient, BlockChainInfo, BlockStatus, BlockId,
|
BlockChainClient, MiningBlockChainClient, EngineClient, BlockChainInfo, BlockStatus, BlockId,
|
||||||
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError,
|
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError,
|
||||||
|
ProvingBlockChainClient,
|
||||||
};
|
};
|
||||||
use db::{NUM_COLUMNS, COL_STATE};
|
use db::{NUM_COLUMNS, COL_STATE};
|
||||||
use header::{Header as BlockHeader, BlockNumber};
|
use header::{Header as BlockHeader, BlockNumber};
|
||||||
@ -134,6 +135,9 @@ impl TestBlockChainClient {
|
|||||||
|
|
||||||
/// Create test client with custom spec and extra data.
|
/// Create test client with custom spec and extra data.
|
||||||
pub fn new_with_spec_and_extra(spec: Spec, extra_data: Bytes) -> Self {
|
pub fn new_with_spec_and_extra(spec: Spec, extra_data: Bytes) -> Self {
|
||||||
|
let genesis_block = spec.genesis_block();
|
||||||
|
let genesis_hash = spec.genesis_header().hash();
|
||||||
|
|
||||||
let mut client = TestBlockChainClient {
|
let mut client = TestBlockChainClient {
|
||||||
blocks: RwLock::new(HashMap::new()),
|
blocks: RwLock::new(HashMap::new()),
|
||||||
numbers: RwLock::new(HashMap::new()),
|
numbers: RwLock::new(HashMap::new()),
|
||||||
@ -158,8 +162,12 @@ impl TestBlockChainClient {
|
|||||||
traces: RwLock::new(None),
|
traces: RwLock::new(None),
|
||||||
history: RwLock::new(None),
|
history: RwLock::new(None),
|
||||||
};
|
};
|
||||||
client.add_blocks(1, EachBlockWith::Nothing); // add genesis block
|
|
||||||
client.genesis_hash = client.last_hash.read().clone();
|
// insert genesis hash.
|
||||||
|
client.blocks.get_mut().insert(genesis_hash, genesis_block);
|
||||||
|
client.numbers.get_mut().insert(0, genesis_hash);
|
||||||
|
*client.last_hash.get_mut() = genesis_hash;
|
||||||
|
client.genesis_hash = genesis_hash;
|
||||||
client
|
client
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,6 +728,20 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
fn registry_address(&self, _name: String) -> Option<Address> { None }
|
fn registry_address(&self, _name: String) -> Option<Address> { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ProvingBlockChainClient for TestBlockChainClient {
|
||||||
|
fn prove_storage(&self, _: H256, _: H256, _: u32, _: BlockId) -> Vec<Bytes> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prove_account(&self, _: H256, _: u32, _: BlockId) -> Vec<Bytes> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn code_by_hash(&self, _: H256, _: BlockId) -> Bytes {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl EngineClient for TestBlockChainClient {
|
impl EngineClient for TestBlockChainClient {
|
||||||
fn update_sealing(&self) {
|
fn update_sealing(&self) {
|
||||||
self.miner.update_sealing(self)
|
self.miner.update_sealing(self)
|
||||||
|
@ -354,6 +354,7 @@ mod tests {
|
|||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use error::{Error, BlockError};
|
use error::{Error, BlockError};
|
||||||
|
use ethkey::Secret;
|
||||||
use rlp::encode;
|
use rlp::encode;
|
||||||
use block::*;
|
use block::*;
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
@ -411,8 +412,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn generates_seal_and_does_not_double_propose() {
|
fn generates_seal_and_does_not_double_propose() {
|
||||||
let tap = AccountProvider::transient_provider();
|
let tap = AccountProvider::transient_provider();
|
||||||
let addr1 = tap.insert_account("1".sha3(), "1").unwrap();
|
let addr1 = tap.insert_account(Secret::from_slice(&"1".sha3()).unwrap(), "1").unwrap();
|
||||||
let addr2 = tap.insert_account("2".sha3(), "2").unwrap();
|
let addr2 = tap.insert_account(Secret::from_slice(&"2".sha3()).unwrap(), "2").unwrap();
|
||||||
|
|
||||||
let spec = Spec::new_test_round();
|
let spec = Spec::new_test_round();
|
||||||
let engine = &*spec.engine;
|
let engine = &*spec.engine;
|
||||||
@ -445,7 +446,7 @@ mod tests {
|
|||||||
fn proposer_switching() {
|
fn proposer_switching() {
|
||||||
let mut header: Header = Header::default();
|
let mut header: Header = Header::default();
|
||||||
let tap = AccountProvider::transient_provider();
|
let tap = AccountProvider::transient_provider();
|
||||||
let addr = tap.insert_account("0".sha3(), "0").unwrap();
|
let addr = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "0").unwrap();
|
||||||
|
|
||||||
header.set_author(addr);
|
header.set_author(addr);
|
||||||
|
|
||||||
@ -464,7 +465,7 @@ mod tests {
|
|||||||
fn rejects_future_block() {
|
fn rejects_future_block() {
|
||||||
let mut header: Header = Header::default();
|
let mut header: Header = Header::default();
|
||||||
let tap = AccountProvider::transient_provider();
|
let tap = AccountProvider::transient_provider();
|
||||||
let addr = tap.insert_account("0".sha3(), "0").unwrap();
|
let addr = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "0").unwrap();
|
||||||
|
|
||||||
header.set_author(addr);
|
header.set_author(addr);
|
||||||
|
|
||||||
|
@ -201,6 +201,7 @@ mod tests {
|
|||||||
use error::{BlockError, Error};
|
use error::{BlockError, Error};
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
|
use ethkey::Secret;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use engines::Seal;
|
use engines::Seal;
|
||||||
@ -261,7 +262,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn can_generate_seal() {
|
fn can_generate_seal() {
|
||||||
let tap = AccountProvider::transient_provider();
|
let tap = AccountProvider::transient_provider();
|
||||||
let addr = tap.insert_account("".sha3(), "").unwrap();
|
let addr = tap.insert_account(Secret::from_slice(&"".sha3()).unwrap(), "").unwrap();
|
||||||
|
|
||||||
let spec = new_test_authority();
|
let spec = new_test_authority();
|
||||||
let engine = &*spec.engine;
|
let engine = &*spec.engine;
|
||||||
@ -281,7 +282,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn seals_internally() {
|
fn seals_internally() {
|
||||||
let tap = AccountProvider::transient_provider();
|
let tap = AccountProvider::transient_provider();
|
||||||
let authority = tap.insert_account("".sha3(), "").unwrap();
|
let authority = tap.insert_account(Secret::from_slice(&"".sha3()).unwrap(), "").unwrap();
|
||||||
|
|
||||||
let engine = new_test_authority().engine;
|
let engine = new_test_authority().engine;
|
||||||
assert!(!engine.is_sealer(&Address::default()).unwrap());
|
assert!(!engine.is_sealer(&Address::default()).unwrap());
|
||||||
|
@ -23,15 +23,35 @@ use header::Header;
|
|||||||
use rlp::*;
|
use rlp::*;
|
||||||
use ethkey::{recover, public_to_address};
|
use ethkey::{recover, public_to_address};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
/// Message transmitted between consensus participants.
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
pub struct ConsensusMessage {
|
pub struct ConsensusMessage {
|
||||||
|
pub vote_step: VoteStep,
|
||||||
|
pub block_hash: Option<BlockHash>,
|
||||||
pub signature: H520,
|
pub signature: H520,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Complete step of the consensus process.
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
|
pub struct VoteStep {
|
||||||
pub height: Height,
|
pub height: Height,
|
||||||
pub round: Round,
|
pub round: Round,
|
||||||
pub step: Step,
|
pub step: Step,
|
||||||
pub block_hash: Option<BlockHash>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VoteStep {
|
||||||
|
pub fn new(height: Height, round: Round, step: Step) -> Self {
|
||||||
|
VoteStep { height: height, round: round, step: step }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_height(&self, height: Height) -> bool {
|
||||||
|
self.height == height
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_round(&self, height: Height, round: Round) -> bool {
|
||||||
|
self.height == height && self.round == round
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn consensus_round(header: &Header) -> Result<Round, ::rlp::DecoderError> {
|
fn consensus_round(header: &Header) -> Result<Round, ::rlp::DecoderError> {
|
||||||
let round_rlp = header.seal().get(0).expect("seal passed basic verification; seal has 3 fields; qed");
|
let round_rlp = header.seal().get(0).expect("seal passed basic verification; seal has 3 fields; qed");
|
||||||
@ -42,53 +62,29 @@ impl ConsensusMessage {
|
|||||||
pub fn new(signature: H520, height: Height, round: Round, step: Step, block_hash: Option<BlockHash>) -> Self {
|
pub fn new(signature: H520, height: Height, round: Round, step: Step, block_hash: Option<BlockHash>) -> Self {
|
||||||
ConsensusMessage {
|
ConsensusMessage {
|
||||||
signature: signature,
|
signature: signature,
|
||||||
height: height,
|
|
||||||
round: round,
|
|
||||||
step: step,
|
|
||||||
block_hash: block_hash,
|
block_hash: block_hash,
|
||||||
|
vote_step: VoteStep::new(height, round, step),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_proposal(header: &Header) -> Result<Self, ::rlp::DecoderError> {
|
pub fn new_proposal(header: &Header) -> Result<Self, ::rlp::DecoderError> {
|
||||||
Ok(ConsensusMessage {
|
Ok(ConsensusMessage {
|
||||||
|
vote_step: VoteStep::new(header.number() as Height, consensus_round(header)?, Step::Propose),
|
||||||
signature: UntrustedRlp::new(header.seal().get(1).expect("seal passed basic verification; seal has 3 fields; qed").as_slice()).as_val()?,
|
signature: UntrustedRlp::new(header.seal().get(1).expect("seal passed basic verification; seal has 3 fields; qed").as_slice()).as_val()?,
|
||||||
height: header.number() as Height,
|
|
||||||
round: consensus_round(header)?,
|
|
||||||
step: Step::Propose,
|
|
||||||
block_hash: Some(header.bare_hash()),
|
block_hash: Some(header.bare_hash()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_commit(proposal: &ConsensusMessage, signature: H520) -> Self {
|
pub fn new_commit(proposal: &ConsensusMessage, signature: H520) -> Self {
|
||||||
|
let mut vote_step = proposal.vote_step.clone();
|
||||||
|
vote_step.step = Step::Precommit;
|
||||||
ConsensusMessage {
|
ConsensusMessage {
|
||||||
signature: signature,
|
vote_step: vote_step,
|
||||||
height: proposal.height,
|
|
||||||
round: proposal.round,
|
|
||||||
step: Step::Precommit,
|
|
||||||
block_hash: proposal.block_hash,
|
block_hash: proposal.block_hash,
|
||||||
|
signature: signature,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_height(&self, height: Height) -> bool {
|
|
||||||
self.height == height
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_round(&self, height: Height, round: Round) -> bool {
|
|
||||||
self.height == height && self.round == round
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_step(&self, height: Height, round: Round, step: Step) -> bool {
|
|
||||||
self.height == height && self.round == round && self.step == step
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_block_hash(&self, h: Height, r: Round, s: Step, block_hash: Option<BlockHash>) -> bool {
|
|
||||||
self.height == h && self.round == r && self.step == s && self.block_hash == block_hash
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_aligned(&self, m: &ConsensusMessage) -> bool {
|
|
||||||
self.is_block_hash(m.height, m.round, m.step, m.block_hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify(&self) -> Result<Address, Error> {
|
pub fn verify(&self) -> Result<Address, Error> {
|
||||||
let full_rlp = ::rlp::encode(self);
|
let full_rlp = ::rlp::encode(self);
|
||||||
let block_info = Rlp::new(&full_rlp).at(1);
|
let block_info = Rlp::new(&full_rlp).at(1);
|
||||||
@ -97,16 +93,30 @@ impl ConsensusMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn precommit_hash(&self) -> H256 {
|
pub fn precommit_hash(&self) -> H256 {
|
||||||
message_info_rlp(self.height, self.round, Step::Precommit, self.block_hash).sha3()
|
let mut vote_step = self.vote_step.clone();
|
||||||
|
vote_step.step = Step::Precommit;
|
||||||
|
message_info_rlp(&vote_step, self.block_hash).sha3()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for ConsensusMessage {
|
impl PartialOrd for VoteStep {
|
||||||
fn partial_cmp(&self, m: &ConsensusMessage) -> Option<Ordering> {
|
fn partial_cmp(&self, m: &VoteStep) -> Option<Ordering> {
|
||||||
Some(self.cmp(m))
|
Some(self.cmp(m))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ord for VoteStep {
|
||||||
|
fn cmp(&self, m: &VoteStep) -> Ordering {
|
||||||
|
if self.height != m.height {
|
||||||
|
self.height.cmp(&m.height)
|
||||||
|
} else if self.round != m.round {
|
||||||
|
self.round.cmp(&m.round)
|
||||||
|
} else {
|
||||||
|
self.step.number().cmp(&m.step.number())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Step {
|
impl Step {
|
||||||
fn number(&self) -> u8 {
|
fn number(&self) -> u8 {
|
||||||
match *self {
|
match *self {
|
||||||
@ -118,20 +128,6 @@ impl Step {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for ConsensusMessage {
|
|
||||||
fn cmp(&self, m: &ConsensusMessage) -> Ordering {
|
|
||||||
if self.height != m.height {
|
|
||||||
self.height.cmp(&m.height)
|
|
||||||
} else if self.round != m.round {
|
|
||||||
self.round.cmp(&m.round)
|
|
||||||
} else if self.step != m.step {
|
|
||||||
self.step.number().cmp(&m.step.number())
|
|
||||||
} else {
|
|
||||||
self.signature.cmp(&m.signature)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decodable for Step {
|
impl Decodable for Step {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
match decoder.as_rlp().as_val()? {
|
match decoder.as_rlp().as_val()? {
|
||||||
@ -149,42 +145,39 @@ impl Encodable for Step {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// (signature, height, round, step, block_hash)
|
/// (signature, (height, round, step, block_hash))
|
||||||
impl Decodable for ConsensusMessage {
|
impl Decodable for ConsensusMessage {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
let rlp = decoder.as_rlp();
|
let rlp = decoder.as_rlp();
|
||||||
let m = rlp.at(1)?;
|
let m = rlp.at(1)?;
|
||||||
let block_message: H256 = m.val_at(3)?;
|
let block_message: H256 = m.val_at(3)?;
|
||||||
Ok(ConsensusMessage {
|
Ok(ConsensusMessage {
|
||||||
signature: rlp.val_at(0)?,
|
vote_step: VoteStep::new(m.val_at(0)?, m.val_at(1)?, m.val_at(2)?),
|
||||||
height: m.val_at(0)?,
|
|
||||||
round: m.val_at(1)?,
|
|
||||||
step: m.val_at(2)?,
|
|
||||||
block_hash: match block_message.is_zero() {
|
block_hash: match block_message.is_zero() {
|
||||||
true => None,
|
true => None,
|
||||||
false => Some(block_message),
|
false => Some(block_message),
|
||||||
}
|
},
|
||||||
|
signature: rlp.val_at(0)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for ConsensusMessage {
|
impl Encodable for ConsensusMessage {
|
||||||
fn rlp_append(&self, s: &mut RlpStream) {
|
fn rlp_append(&self, s: &mut RlpStream) {
|
||||||
let info = message_info_rlp(self.height, self.round, self.step, self.block_hash);
|
let info = message_info_rlp(&self.vote_step, self.block_hash);
|
||||||
s.begin_list(2)
|
s.begin_list(2)
|
||||||
.append(&self.signature)
|
.append(&self.signature)
|
||||||
.append_raw(&info, 1);
|
.append_raw(&info, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_info_rlp(height: Height, round: Round, step: Step, block_hash: Option<BlockHash>) -> Bytes {
|
pub fn message_info_rlp(vote_step: &VoteStep, block_hash: Option<BlockHash>) -> Bytes {
|
||||||
// TODO: figure out whats wrong with nested list encoding
|
// TODO: figure out whats wrong with nested list encoding
|
||||||
let mut s = RlpStream::new_list(5);
|
let mut s = RlpStream::new_list(5);
|
||||||
s.append(&height).append(&round).append(&step).append(&block_hash.unwrap_or_else(H256::zero));
|
s.append(&vote_step.height).append(&vote_step.round).append(&vote_step.step).append(&block_hash.unwrap_or_else(H256::zero));
|
||||||
s.out()
|
s.out()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn message_full_rlp(signature: &H520, vote_info: &Bytes) -> Bytes {
|
pub fn message_full_rlp(signature: &H520, vote_info: &Bytes) -> Bytes {
|
||||||
let mut s = RlpStream::new_list(2);
|
let mut s = RlpStream::new_list(2);
|
||||||
s.append(signature).append_raw(vote_info, 1);
|
s.append(signature).append_raw(vote_info, 1);
|
||||||
@ -199,14 +192,17 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
|
use ethkey::Secret;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encode_decode() {
|
fn encode_decode() {
|
||||||
let message = ConsensusMessage {
|
let message = ConsensusMessage {
|
||||||
signature: H520::default(),
|
signature: H520::default(),
|
||||||
height: 10,
|
vote_step: VoteStep {
|
||||||
round: 123,
|
height: 10,
|
||||||
step: Step::Precommit,
|
round: 123,
|
||||||
|
step: Step::Precommit,
|
||||||
|
},
|
||||||
block_hash: Some("1".sha3())
|
block_hash: Some("1".sha3())
|
||||||
};
|
};
|
||||||
let raw_rlp = ::rlp::encode(&message).to_vec();
|
let raw_rlp = ::rlp::encode(&message).to_vec();
|
||||||
@ -215,9 +211,11 @@ mod tests {
|
|||||||
|
|
||||||
let message = ConsensusMessage {
|
let message = ConsensusMessage {
|
||||||
signature: H520::default(),
|
signature: H520::default(),
|
||||||
height: 1314,
|
vote_step: VoteStep {
|
||||||
round: 0,
|
height: 1314,
|
||||||
step: Step::Prevote,
|
round: 0,
|
||||||
|
step: Step::Prevote,
|
||||||
|
},
|
||||||
block_hash: None
|
block_hash: None
|
||||||
};
|
};
|
||||||
let raw_rlp = ::rlp::encode(&message);
|
let raw_rlp = ::rlp::encode(&message);
|
||||||
@ -228,10 +226,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn generate_and_verify() {
|
fn generate_and_verify() {
|
||||||
let tap = Arc::new(AccountProvider::transient_provider());
|
let tap = Arc::new(AccountProvider::transient_provider());
|
||||||
let addr = tap.insert_account("0".sha3(), "0").unwrap();
|
let addr = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "0").unwrap();
|
||||||
tap.unlock_account_permanently(addr, "0".into()).unwrap();
|
tap.unlock_account_permanently(addr, "0".into()).unwrap();
|
||||||
|
|
||||||
let mi = message_info_rlp(123, 2, Step::Precommit, Some(H256::default()));
|
let mi = message_info_rlp(&VoteStep::new(123, 2, Step::Precommit), Some(H256::default()));
|
||||||
|
|
||||||
let raw_rlp = message_full_rlp(&tap.sign(addr, None, mi.sha3()).unwrap().into(), &mi);
|
let raw_rlp = message_full_rlp(&tap.sign(addr, None, mi.sha3()).unwrap().into(), &mi);
|
||||||
|
|
||||||
@ -254,9 +252,11 @@ mod tests {
|
|||||||
message,
|
message,
|
||||||
ConsensusMessage {
|
ConsensusMessage {
|
||||||
signature: Default::default(),
|
signature: Default::default(),
|
||||||
height: 0,
|
vote_step: VoteStep {
|
||||||
round: 0,
|
height: 0,
|
||||||
step: Step::Propose,
|
round: 0,
|
||||||
|
step: Step::Propose,
|
||||||
|
},
|
||||||
block_hash: Some(header.bare_hash())
|
block_hash: Some(header.bare_hash())
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -267,12 +267,10 @@ mod tests {
|
|||||||
let header = Header::default();
|
let header = Header::default();
|
||||||
let pro = ConsensusMessage {
|
let pro = ConsensusMessage {
|
||||||
signature: Default::default(),
|
signature: Default::default(),
|
||||||
height: 0,
|
vote_step: VoteStep::new(0, 0, Step::Propose),
|
||||||
round: 0,
|
|
||||||
step: Step::Propose,
|
|
||||||
block_hash: Some(header.bare_hash())
|
block_hash: Some(header.bare_hash())
|
||||||
};
|
};
|
||||||
let pre = message_info_rlp(0, 0, Step::Precommit, Some(header.bare_hash()));
|
let pre = message_info_rlp(&VoteStep::new(0, 0, Step::Precommit), Some(header.bare_hash()));
|
||||||
|
|
||||||
assert_eq!(pro.precommit_hash(), pre.sha3());
|
assert_eq!(pro.precommit_hash(), pre.sha3());
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ use self::transition::TransitionHandler;
|
|||||||
use self::params::TendermintParams;
|
use self::params::TendermintParams;
|
||||||
use self::vote_collector::VoteCollector;
|
use self::vote_collector::VoteCollector;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||||
pub enum Step {
|
pub enum Step {
|
||||||
Propose,
|
Propose,
|
||||||
Prevote,
|
Prevote,
|
||||||
@ -163,13 +163,13 @@ impl Tendermint {
|
|||||||
let h = self.height.load(AtomicOrdering::SeqCst);
|
let h = self.height.load(AtomicOrdering::SeqCst);
|
||||||
let r = self.round.load(AtomicOrdering::SeqCst);
|
let r = self.round.load(AtomicOrdering::SeqCst);
|
||||||
let s = self.step.read();
|
let s = self.step.read();
|
||||||
let vote_info = message_info_rlp(h, r, *s, block_hash);
|
let vote_info = message_info_rlp(&VoteStep::new(h, r, *s), block_hash);
|
||||||
let authority = self.authority.read();
|
let authority = self.authority.read();
|
||||||
match ap.sign(*authority, self.password.read().clone(), vote_info.sha3()).map(Into::into) {
|
match ap.sign(*authority, self.password.read().clone(), vote_info.sha3()).map(Into::into) {
|
||||||
Ok(signature) => {
|
Ok(signature) => {
|
||||||
let message_rlp = message_full_rlp(&signature, &vote_info);
|
let message_rlp = message_full_rlp(&signature, &vote_info);
|
||||||
let message = ConsensusMessage::new(signature, h, r, *s, block_hash);
|
let message = ConsensusMessage::new(signature, h, r, *s, block_hash);
|
||||||
self.votes.vote(message.clone(), *authority);
|
self.votes.vote(message.clone(), &*authority);
|
||||||
debug!(target: "poa", "Generated {:?} as {}.", message, *authority);
|
debug!(target: "poa", "Generated {:?} as {}.", message, *authority);
|
||||||
self.handle_valid_message(&message);
|
self.handle_valid_message(&message);
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ impl Tendermint {
|
|||||||
},
|
},
|
||||||
Step::Prevote => {
|
Step::Prevote => {
|
||||||
let block_hash = match *self.lock_change.read() {
|
let block_hash = match *self.lock_change.read() {
|
||||||
Some(ref m) if !self.should_unlock(m.round) => m.block_hash,
|
Some(ref m) if !self.should_unlock(m.vote_step.round) => m.block_hash,
|
||||||
_ => self.proposal.read().clone(),
|
_ => self.proposal.read().clone(),
|
||||||
};
|
};
|
||||||
self.generate_and_broadcast_message(block_hash);
|
self.generate_and_broadcast_message(block_hash);
|
||||||
@ -230,8 +230,8 @@ impl Tendermint {
|
|||||||
trace!(target: "poa", "to_step: Precommit.");
|
trace!(target: "poa", "to_step: Precommit.");
|
||||||
let block_hash = match *self.lock_change.read() {
|
let block_hash = match *self.lock_change.read() {
|
||||||
Some(ref m) if self.is_round(m) && m.block_hash.is_some() => {
|
Some(ref m) if self.is_round(m) && m.block_hash.is_some() => {
|
||||||
trace!(target: "poa", "Setting last lock: {}", m.round);
|
trace!(target: "poa", "Setting last lock: {}", m.vote_step.round);
|
||||||
self.last_lock.store(m.round, AtomicOrdering::SeqCst);
|
self.last_lock.store(m.vote_step.round, AtomicOrdering::SeqCst);
|
||||||
m.block_hash
|
m.block_hash
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -246,7 +246,7 @@ impl Tendermint {
|
|||||||
if let Some(block_hash) = *self.proposal.read() {
|
if let Some(block_hash) = *self.proposal.read() {
|
||||||
// Generate seal and remove old votes.
|
// Generate seal and remove old votes.
|
||||||
if self.is_proposer(&*self.authority.read()).is_ok() {
|
if self.is_proposer(&*self.authority.read()).is_ok() {
|
||||||
if let Some(seal) = self.votes.seal_signatures(height, round, block_hash) {
|
if let Some(seal) = self.votes.seal_signatures(height, round, &block_hash) {
|
||||||
trace!(target: "poa", "Collected seal: {:?}", seal);
|
trace!(target: "poa", "Collected seal: {:?}", seal);
|
||||||
let seal = vec![
|
let seal = vec![
|
||||||
::rlp::encode(&round).to_vec(),
|
::rlp::encode(&round).to_vec(),
|
||||||
@ -290,11 +290,11 @@ impl Tendermint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_height(&self, message: &ConsensusMessage) -> bool {
|
fn is_height(&self, message: &ConsensusMessage) -> bool {
|
||||||
message.is_height(self.height.load(AtomicOrdering::SeqCst))
|
message.vote_step.is_height(self.height.load(AtomicOrdering::SeqCst))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_round(&self, message: &ConsensusMessage) -> bool {
|
fn is_round(&self, message: &ConsensusMessage) -> bool {
|
||||||
message.is_round(self.height.load(AtomicOrdering::SeqCst), self.round.load(AtomicOrdering::SeqCst))
|
message.vote_step.is_round(self.height.load(AtomicOrdering::SeqCst), self.round.load(AtomicOrdering::SeqCst))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment_round(&self, n: Round) {
|
fn increment_round(&self, n: Round) {
|
||||||
@ -302,20 +302,20 @@ impl Tendermint {
|
|||||||
self.round.fetch_add(n, AtomicOrdering::SeqCst);
|
self.round.fetch_add(n, AtomicOrdering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_unlock(&self, lock_change_round: Round) -> bool {
|
fn should_unlock(&self, lock_change_round: Round) -> bool {
|
||||||
self.last_lock.load(AtomicOrdering::SeqCst) < lock_change_round
|
self.last_lock.load(AtomicOrdering::SeqCst) < lock_change_round
|
||||||
&& lock_change_round < self.round.load(AtomicOrdering::SeqCst)
|
&& lock_change_round < self.round.load(AtomicOrdering::SeqCst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn has_enough_any_votes(&self) -> bool {
|
fn has_enough_any_votes(&self) -> bool {
|
||||||
let step_votes = self.votes.count_step_votes(self.height.load(AtomicOrdering::SeqCst), self.round.load(AtomicOrdering::SeqCst), *self.step.read());
|
let step_votes = self.votes.count_step_votes(&VoteStep::new(self.height.load(AtomicOrdering::SeqCst), self.round.load(AtomicOrdering::SeqCst), *self.step.read()));
|
||||||
self.is_above_threshold(step_votes)
|
self.is_above_threshold(step_votes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_enough_future_step_votes(&self, message: &ConsensusMessage) -> bool {
|
fn has_enough_future_step_votes(&self, vote_step: &VoteStep) -> bool {
|
||||||
if message.round > self.round.load(AtomicOrdering::SeqCst) {
|
if vote_step.round > self.round.load(AtomicOrdering::SeqCst) {
|
||||||
let step_votes = self.votes.count_step_votes(message.height, message.round, message.step);
|
let step_votes = self.votes.count_step_votes(vote_step);
|
||||||
self.is_above_threshold(step_votes)
|
self.is_above_threshold(step_votes)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -328,12 +328,13 @@ impl Tendermint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_valid_message(&self, message: &ConsensusMessage) {
|
fn handle_valid_message(&self, message: &ConsensusMessage) {
|
||||||
|
let ref vote_step = message.vote_step;
|
||||||
let is_newer_than_lock = match *self.lock_change.read() {
|
let is_newer_than_lock = match *self.lock_change.read() {
|
||||||
Some(ref lock) => message > lock,
|
Some(ref lock) => vote_step > &lock.vote_step,
|
||||||
None => true,
|
None => true,
|
||||||
};
|
};
|
||||||
let lock_change = is_newer_than_lock
|
let lock_change = is_newer_than_lock
|
||||||
&& message.step == Step::Prevote
|
&& vote_step.step == Step::Prevote
|
||||||
&& message.block_hash.is_some()
|
&& message.block_hash.is_some()
|
||||||
&& self.has_enough_aligned_votes(message);
|
&& self.has_enough_aligned_votes(message);
|
||||||
if lock_change {
|
if lock_change {
|
||||||
@ -351,15 +352,15 @@ impl Tendermint {
|
|||||||
Some(Step::Commit)
|
Some(Step::Commit)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Step::Precommit if self.has_enough_future_step_votes(message) => {
|
Step::Precommit if self.has_enough_future_step_votes(&vote_step) => {
|
||||||
self.increment_round(message.round - self.round.load(AtomicOrdering::SeqCst));
|
self.increment_round(vote_step.round - self.round.load(AtomicOrdering::SeqCst));
|
||||||
Some(Step::Precommit)
|
Some(Step::Precommit)
|
||||||
},
|
},
|
||||||
// Avoid counting twice.
|
// Avoid counting twice.
|
||||||
Step::Prevote if lock_change => Some(Step::Precommit),
|
Step::Prevote if lock_change => Some(Step::Precommit),
|
||||||
Step::Prevote if self.has_enough_aligned_votes(message) => Some(Step::Precommit),
|
Step::Prevote if self.has_enough_aligned_votes(message) => Some(Step::Precommit),
|
||||||
Step::Prevote if self.has_enough_future_step_votes(message) => {
|
Step::Prevote if self.has_enough_future_step_votes(&vote_step) => {
|
||||||
self.increment_round(message.round - self.round.load(AtomicOrdering::SeqCst));
|
self.increment_round(vote_step.round - self.round.load(AtomicOrdering::SeqCst));
|
||||||
Some(Step::Prevote)
|
Some(Step::Prevote)
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -390,8 +391,8 @@ impl Engine for Tendermint {
|
|||||||
let message = ConsensusMessage::new_proposal(header).expect("Invalid header.");
|
let message = ConsensusMessage::new_proposal(header).expect("Invalid header.");
|
||||||
map![
|
map![
|
||||||
"signature".into() => message.signature.to_string(),
|
"signature".into() => message.signature.to_string(),
|
||||||
"height".into() => message.height.to_string(),
|
"height".into() => message.vote_step.height.to_string(),
|
||||||
"round".into() => message.round.to_string(),
|
"round".into() => message.vote_step.round.to_string(),
|
||||||
"block_hash".into() => message.block_hash.as_ref().map(ToString::to_string).unwrap_or("".into())
|
"block_hash".into() => message.block_hash.as_ref().map(ToString::to_string).unwrap_or("".into())
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -431,11 +432,11 @@ impl Engine for Tendermint {
|
|||||||
let height = header.number() as Height;
|
let height = header.number() as Height;
|
||||||
let round = self.round.load(AtomicOrdering::SeqCst);
|
let round = self.round.load(AtomicOrdering::SeqCst);
|
||||||
let bh = Some(header.bare_hash());
|
let bh = Some(header.bare_hash());
|
||||||
let vote_info = message_info_rlp(height, round, Step::Propose, bh.clone());
|
let vote_info = message_info_rlp(&VoteStep::new(height, round, Step::Propose), bh.clone());
|
||||||
if let Ok(signature) = ap.sign(*author, self.password.read().clone(), vote_info.sha3()).map(H520::from) {
|
if let Ok(signature) = ap.sign(*author, self.password.read().clone(), vote_info.sha3()).map(H520::from) {
|
||||||
// Insert Propose vote.
|
// Insert Propose vote.
|
||||||
debug!(target: "poa", "Submitting proposal {} at height {} round {}.", header.bare_hash(), height, round);
|
debug!(target: "poa", "Submitting proposal {} at height {} round {}.", header.bare_hash(), height, round);
|
||||||
self.votes.vote(ConsensusMessage::new(signature, height, round, Step::Propose, bh), *author);
|
self.votes.vote(ConsensusMessage::new(signature, height, round, Step::Propose, bh), author);
|
||||||
// Remember proposal for later seal submission.
|
// Remember proposal for later seal submission.
|
||||||
*self.proposal.write() = bh;
|
*self.proposal.write() = bh;
|
||||||
Seal::Proposal(vec![
|
Seal::Proposal(vec![
|
||||||
@ -461,9 +462,11 @@ impl Engine for Tendermint {
|
|||||||
if !self.is_authority(&sender) {
|
if !self.is_authority(&sender) {
|
||||||
Err(EngineError::NotAuthorized(sender))?;
|
Err(EngineError::NotAuthorized(sender))?;
|
||||||
}
|
}
|
||||||
self.broadcast_message(rlp.as_raw().to_vec());
|
if self.votes.vote(message.clone(), &sender).is_some() {
|
||||||
|
Err(EngineError::DoubleVote(sender))?
|
||||||
|
}
|
||||||
trace!(target: "poa", "Handling a valid {:?} from {}.", message, sender);
|
trace!(target: "poa", "Handling a valid {:?} from {}.", message, sender);
|
||||||
self.votes.vote(message.clone(), sender);
|
self.broadcast_message(rlp.as_raw().to_vec());
|
||||||
self.handle_valid_message(&message);
|
self.handle_valid_message(&message);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -502,7 +505,7 @@ impl Engine for Tendermint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||||
let proposal = ConsensusMessage::new_proposal(header)?;
|
let proposal = ConsensusMessage::new_proposal(header)?;
|
||||||
let proposer = proposal.verify()?;
|
let proposer = proposal.verify()?;
|
||||||
if !self.is_authority(&proposer) {
|
if !self.is_authority(&proposer) {
|
||||||
Err(EngineError::NotAuthorized(proposer))?
|
Err(EngineError::NotAuthorized(proposer))?
|
||||||
@ -541,7 +544,7 @@ impl Engine for Tendermint {
|
|||||||
found: signatures_len
|
found: signatures_len
|
||||||
}))?;
|
}))?;
|
||||||
}
|
}
|
||||||
self.is_round_proposer(proposal.height, proposal.round, &proposer)?;
|
self.is_round_proposer(proposal.vote_step.height, proposal.vote_step.round, &proposer)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -607,16 +610,16 @@ impl Engine for Tendermint {
|
|||||||
let proposal = ConsensusMessage::new_proposal(header).expect("block went through full verification; this Engine verifies new_proposal creation; qed");
|
let proposal = ConsensusMessage::new_proposal(header).expect("block went through full verification; this Engine verifies new_proposal creation; qed");
|
||||||
if signatures_len != 1 {
|
if signatures_len != 1 {
|
||||||
// New Commit received, skip to next height.
|
// New Commit received, skip to next height.
|
||||||
trace!(target: "poa", "Received a commit for height {}, round {}.", proposal.height, proposal.round);
|
trace!(target: "poa", "Received a commit: {:?}.", proposal.vote_step);
|
||||||
self.to_next_height(proposal.height);
|
self.to_next_height(proposal.vote_step.height);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let proposer = proposal.verify().expect("block went through full verification; this Engine tries verify; qed");
|
let proposer = proposal.verify().expect("block went through full verification; this Engine tries verify; qed");
|
||||||
debug!(target: "poa", "Received a new proposal for height {}, round {} from {}.", proposal.height, proposal.round, proposer);
|
debug!(target: "poa", "Received a new proposal {:?} from {}.", proposal.vote_step, proposer);
|
||||||
if self.is_round(&proposal) {
|
if self.is_round(&proposal) {
|
||||||
*self.proposal.write() = proposal.block_hash.clone();
|
*self.proposal.write() = proposal.block_hash.clone();
|
||||||
}
|
}
|
||||||
self.votes.vote(proposal, proposer);
|
self.votes.vote(proposal, &proposer);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,6 +674,7 @@ mod tests {
|
|||||||
use error::{Error, BlockError};
|
use error::{Error, BlockError};
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
|
use ethkey::Secret;
|
||||||
use client::chain_notify::ChainNotify;
|
use client::chain_notify::ChainNotify;
|
||||||
use miner::MinerService;
|
use miner::MinerService;
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
@ -703,7 +707,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn vote<F>(engine: &Engine, signer: F, height: usize, round: usize, step: Step, block_hash: Option<H256>) -> Bytes where F: FnOnce(H256) -> Result<H520, ::account_provider::Error> {
|
fn vote<F>(engine: &Engine, signer: F, height: usize, round: usize, step: Step, block_hash: Option<H256>) -> Bytes where F: FnOnce(H256) -> Result<H520, ::account_provider::Error> {
|
||||||
let mi = message_info_rlp(height, round, step, block_hash);
|
let mi = message_info_rlp(&VoteStep::new(height, round, step), block_hash);
|
||||||
let m = message_full_rlp(&signer(mi.sha3()).unwrap().into(), &mi);
|
let m = message_full_rlp(&signer(mi.sha3()).unwrap().into(), &mi);
|
||||||
engine.handle_message(&m).unwrap();
|
engine.handle_message(&m).unwrap();
|
||||||
m
|
m
|
||||||
@ -711,7 +715,7 @@ mod tests {
|
|||||||
|
|
||||||
fn proposal_seal(tap: &Arc<AccountProvider>, header: &Header, round: Round) -> Vec<Bytes> {
|
fn proposal_seal(tap: &Arc<AccountProvider>, header: &Header, round: Round) -> Vec<Bytes> {
|
||||||
let author = header.author();
|
let author = header.author();
|
||||||
let vote_info = message_info_rlp(header.number() as Height, round, Step::Propose, Some(header.bare_hash()));
|
let vote_info = message_info_rlp(&VoteStep::new(header.number() as Height, round, Step::Propose), Some(header.bare_hash()));
|
||||||
let signature = tap.sign(*author, None, vote_info.sha3()).unwrap();
|
let signature = tap.sign(*author, None, vote_info.sha3()).unwrap();
|
||||||
vec![
|
vec![
|
||||||
::rlp::encode(&round).to_vec(),
|
::rlp::encode(&round).to_vec(),
|
||||||
@ -721,7 +725,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn insert_and_unlock(tap: &Arc<AccountProvider>, acc: &str) -> Address {
|
fn insert_and_unlock(tap: &Arc<AccountProvider>, acc: &str) -> Address {
|
||||||
let addr = tap.insert_account(acc.sha3(), acc).unwrap();
|
let addr = tap.insert_account(Secret::from_slice(&acc.sha3()).unwrap(), acc).unwrap();
|
||||||
tap.unlock_account_permanently(addr, acc.into()).unwrap();
|
tap.unlock_account_permanently(addr, acc.into()).unwrap();
|
||||||
addr
|
addr
|
||||||
}
|
}
|
||||||
@ -825,7 +829,7 @@ mod tests {
|
|||||||
header.set_author(proposer);
|
header.set_author(proposer);
|
||||||
let mut seal = proposal_seal(&tap, &header, 0);
|
let mut seal = proposal_seal(&tap, &header, 0);
|
||||||
|
|
||||||
let vote_info = message_info_rlp(0, 0, Step::Precommit, Some(header.bare_hash()));
|
let vote_info = message_info_rlp(&VoteStep::new(0, 0, Step::Precommit), Some(header.bare_hash()));
|
||||||
let signature1 = tap.sign(proposer, None, vote_info.sha3()).unwrap();
|
let signature1 = tap.sign(proposer, None, vote_info.sha3()).unwrap();
|
||||||
|
|
||||||
seal[2] = ::rlp::encode(&vec![H520::from(signature1.clone())]).to_vec();
|
seal[2] = ::rlp::encode(&vec![H520::from(signature1.clone())]).to_vec();
|
||||||
@ -886,7 +890,7 @@ mod tests {
|
|||||||
fn relays_messages() {
|
fn relays_messages() {
|
||||||
let (spec, tap) = setup();
|
let (spec, tap) = setup();
|
||||||
let engine = spec.engine.clone();
|
let engine = spec.engine.clone();
|
||||||
|
|
||||||
let v0 = insert_and_register(&tap, engine.as_ref(), "0");
|
let v0 = insert_and_register(&tap, engine.as_ref(), "0");
|
||||||
let v1 = insert_and_register(&tap, engine.as_ref(), "1");
|
let v1 = insert_and_register(&tap, engine.as_ref(), "1");
|
||||||
|
|
||||||
|
@ -17,13 +17,50 @@
|
|||||||
//! Collects votes on hashes at each height and round.
|
//! Collects votes on hashes at each height and round.
|
||||||
|
|
||||||
use util::*;
|
use util::*;
|
||||||
use super::message::ConsensusMessage;
|
use super::message::*;
|
||||||
use super::{Height, Round, Step};
|
use super::{Height, Round, Step, BlockHash};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VoteCollector {
|
pub struct VoteCollector {
|
||||||
/// Storing all Proposals, Prevotes and Precommits.
|
/// Storing all Proposals, Prevotes and Precommits.
|
||||||
votes: RwLock<BTreeMap<ConsensusMessage, Address>>,
|
votes: RwLock<BTreeMap<VoteStep, StepCollector>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct StepCollector {
|
||||||
|
voted: HashSet<Address>,
|
||||||
|
pub block_votes: HashMap<Option<BlockHash>, HashMap<H520, Address>>,
|
||||||
|
messages: HashSet<ConsensusMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StepCollector {
|
||||||
|
/// Returns Some(&Address) when validator is double voting.
|
||||||
|
fn insert<'a>(&mut self, message: ConsensusMessage, address: &'a Address) -> Option<&'a Address> {
|
||||||
|
// Do nothing when message was seen.
|
||||||
|
if self.messages.insert(message.clone()) {
|
||||||
|
if self.voted.insert(address.clone()) {
|
||||||
|
self
|
||||||
|
.block_votes
|
||||||
|
.entry(message.block_hash)
|
||||||
|
.or_insert_with(HashMap::new)
|
||||||
|
.insert(message.signature, address.clone());
|
||||||
|
} else {
|
||||||
|
// Bad validator sent a different message.
|
||||||
|
return Some(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Count all votes for the given block hash at this step.
|
||||||
|
fn count_block(&self, block_hash: &Option<BlockHash>) -> usize {
|
||||||
|
self.block_votes.get(block_hash).map_or(0, HashMap::len)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Count all votes collected for the given step.
|
||||||
|
fn count(&self) -> usize {
|
||||||
|
self.block_votes.values().map(HashMap::len).sum()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -42,109 +79,105 @@ impl PartialEq for SealSignatures {
|
|||||||
impl Eq for SealSignatures {}
|
impl Eq for SealSignatures {}
|
||||||
|
|
||||||
impl VoteCollector {
|
impl VoteCollector {
|
||||||
pub fn new() -> VoteCollector {
|
pub fn new() -> Self {
|
||||||
let mut collector = BTreeMap::new();
|
let mut collector = BTreeMap::new();
|
||||||
// Insert dummy message to fulfill invariant: "only messages newer than the oldest are inserted".
|
// Insert dummy entry to fulfill invariant: "only messages newer than the oldest are inserted".
|
||||||
collector.insert(ConsensusMessage {
|
collector.insert(VoteStep::new(0, 0, Step::Propose), Default::default());
|
||||||
signature: H520::default(),
|
|
||||||
height: 0,
|
|
||||||
round: 0,
|
|
||||||
step: Step::Propose,
|
|
||||||
block_hash: None
|
|
||||||
},
|
|
||||||
Address::default());
|
|
||||||
VoteCollector { votes: RwLock::new(collector) }
|
VoteCollector { votes: RwLock::new(collector) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert vote if it is newer than the oldest one.
|
/// Insert vote if it is newer than the oldest one.
|
||||||
pub fn vote(&self, message: ConsensusMessage, voter: Address) -> Option<Address> {
|
pub fn vote<'a>(&self, message: ConsensusMessage, voter: &'a Address) -> Option<&'a Address> {
|
||||||
self.votes.write().insert(message, voter)
|
self
|
||||||
|
.votes
|
||||||
|
.write()
|
||||||
|
.entry(message.vote_step.clone())
|
||||||
|
.or_insert_with(Default::default)
|
||||||
|
.insert(message, voter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the message should be ignored.
|
||||||
pub fn is_old_or_known(&self, message: &ConsensusMessage) -> bool {
|
pub fn is_old_or_known(&self, message: &ConsensusMessage) -> bool {
|
||||||
self.votes.read().get(message).map_or(false, |a| {
|
self
|
||||||
trace!(target: "poa", "Known message from {}: {:?}.", a, message);
|
.votes
|
||||||
true
|
.read()
|
||||||
}) || {
|
.get(&message.vote_step)
|
||||||
|
.map_or(false, |c| {
|
||||||
|
let is_known = c.messages.contains(message);
|
||||||
|
if is_known { trace!(target: "poa", "Known message: {:?}.", message); }
|
||||||
|
is_known
|
||||||
|
})
|
||||||
|
|| {
|
||||||
let guard = self.votes.read();
|
let guard = self.votes.read();
|
||||||
let is_old = guard.keys().next().map_or(true, |oldest| message <= oldest);
|
let is_old = guard.keys().next().map_or(true, |oldest| message.vote_step <= *oldest);
|
||||||
if is_old { trace!(target: "poa", "Old message {:?}.", message); }
|
if is_old { trace!(target: "poa", "Old message {:?}.", message); }
|
||||||
is_old
|
is_old
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Throws out messages older than message, leaves message as marker for the oldest.
|
/// Throws out messages older than message, leaves message as marker for the oldest.
|
||||||
pub fn throw_out_old(&self, message: &ConsensusMessage) {
|
pub fn throw_out_old(&self, vote_step: &VoteStep) {
|
||||||
let mut guard = self.votes.write();
|
let mut guard = self.votes.write();
|
||||||
let new_collector = guard.split_off(message);
|
let new_collector = guard.split_off(vote_step);
|
||||||
*guard = new_collector;
|
*guard = new_collector;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seal_signatures(&self, height: Height, round: Round, block_hash: H256) -> Option<SealSignatures> {
|
/// Collects the signatures used to seal a block.
|
||||||
let bh = Some(block_hash);
|
pub fn seal_signatures(&self, height: Height, round: Round, block_hash: &H256) -> Option<SealSignatures> {
|
||||||
let (proposal, votes) = {
|
let ref bh = Some(*block_hash);
|
||||||
|
let precommit_step = VoteStep::new(height, round, Step::Precommit);
|
||||||
|
let maybe_seal = {
|
||||||
let guard = self.votes.read();
|
let guard = self.votes.read();
|
||||||
let mut current_signatures = guard.keys().skip_while(|m| !m.is_block_hash(height, round, Step::Propose, bh));
|
guard
|
||||||
let proposal = current_signatures.next().cloned();
|
.get(&VoteStep::new(height, round, Step::Propose))
|
||||||
let votes = current_signatures
|
.and_then(|c| c.block_votes.get(bh))
|
||||||
.skip_while(|m| !m.is_block_hash(height, round, Step::Precommit, bh))
|
.and_then(|proposals| proposals.keys().next())
|
||||||
.filter(|m| m.is_block_hash(height, round, Step::Precommit, bh))
|
.map(|proposal| SealSignatures {
|
||||||
.cloned()
|
proposal: proposal.clone(),
|
||||||
.collect::<Vec<_>>();
|
votes: guard
|
||||||
(proposal, votes)
|
.get(&precommit_step)
|
||||||
|
.and_then(|c| c.block_votes.get(bh))
|
||||||
|
.map(|precommits| precommits.keys().cloned().collect())
|
||||||
|
.unwrap_or_else(Vec::new),
|
||||||
|
})
|
||||||
|
.and_then(|seal| if seal.votes.is_empty() { None } else { Some(seal) })
|
||||||
};
|
};
|
||||||
if votes.is_empty() {
|
if maybe_seal.is_some() {
|
||||||
return None;
|
// Remove messages that are no longer relevant.
|
||||||
|
self.throw_out_old(&precommit_step);
|
||||||
}
|
}
|
||||||
// Remove messages that are no longer relevant.
|
maybe_seal
|
||||||
votes.last().map(|m| self.throw_out_old(m));
|
|
||||||
let mut votes_vec: Vec<_> = votes.into_iter().map(|m| m.signature).collect();
|
|
||||||
votes_vec.sort();
|
|
||||||
proposal.map(|p| SealSignatures {
|
|
||||||
proposal: p.signature,
|
|
||||||
votes: votes_vec,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Count votes which agree with the given message.
|
||||||
pub fn count_aligned_votes(&self, message: &ConsensusMessage) -> usize {
|
pub fn count_aligned_votes(&self, message: &ConsensusMessage) -> usize {
|
||||||
let guard = self.votes.read();
|
self
|
||||||
guard.keys()
|
.votes
|
||||||
.skip_while(|m| !m.is_aligned(message))
|
.read()
|
||||||
// sorted by signature so might not be continuous
|
.get(&message.vote_step)
|
||||||
.filter(|m| m.is_aligned(message))
|
.map_or(0, |m| m.count_block(&message.block_hash))
|
||||||
.count()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count_step_votes(&self, height: Height, round: Round, step: Step) -> usize {
|
/// Count all votes collected for a given step.
|
||||||
let guard = self.votes.read();
|
pub fn count_step_votes(&self, vote_step: &VoteStep) -> usize {
|
||||||
let current = guard.iter().skip_while(|&(m, _)| !m.is_step(height, round, step));
|
self.votes.read().get(vote_step).map_or(0, StepCollector::count)
|
||||||
let mut origins = HashSet::new();
|
|
||||||
let mut n = 0;
|
|
||||||
for (message, origin) in current {
|
|
||||||
if message.is_step(height, round, step) {
|
|
||||||
if origins.insert(origin) {
|
|
||||||
n += 1;
|
|
||||||
} else {
|
|
||||||
warn!("count_step_votes: Authority {} has cast multiple step votes, this indicates malicious behaviour.", origin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get all messages older than the height.
|
||||||
pub fn get_up_to(&self, height: Height) -> Vec<Bytes> {
|
pub fn get_up_to(&self, height: Height) -> Vec<Bytes> {
|
||||||
let guard = self.votes.read();
|
let guard = self.votes.read();
|
||||||
guard
|
guard
|
||||||
.keys()
|
.iter()
|
||||||
.filter(|m| m.step.is_pre())
|
.filter(|&(s, _)| s.step.is_pre())
|
||||||
.take_while(|m| m.height <= height)
|
.take_while(|&(s, _)| s.height <= height)
|
||||||
.map(|m| ::rlp::encode(m).to_vec())
|
.map(|(_, c)| c.messages.iter().map(|m| ::rlp::encode(m).to_vec()).collect::<Vec<_>>())
|
||||||
.collect()
|
.fold(Vec::new(), |mut acc, mut messages| { acc.append(&mut messages); acc })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve address from which the message was sent from cache.
|
||||||
pub fn get(&self, message: &ConsensusMessage) -> Option<Address> {
|
pub fn get(&self, message: &ConsensusMessage) -> Option<Address> {
|
||||||
let guard = self.votes.read();
|
let guard = self.votes.read();
|
||||||
guard.get(message).cloned()
|
guard.get(&message.vote_step).and_then(|c| c.block_votes.get(&message.block_hash)).and_then(|origins| origins.get(&message.signature).cloned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,15 +185,15 @@ impl VoteCollector {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use util::*;
|
use util::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::super::{Height, Round, BlockHash, Step};
|
use super::super::{BlockHash, Step};
|
||||||
use super::super::message::ConsensusMessage;
|
use super::super::message::*;
|
||||||
|
|
||||||
fn random_vote(collector: &VoteCollector, signature: H520, h: Height, r: Round, step: Step, block_hash: Option<BlockHash>) -> Option<H160> {
|
fn random_vote(collector: &VoteCollector, signature: H520, vote_step: VoteStep, block_hash: Option<BlockHash>) -> bool {
|
||||||
full_vote(collector, signature, h, r, step, block_hash, H160::random())
|
full_vote(collector, signature, vote_step, block_hash, &H160::random()).is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn full_vote(collector: &VoteCollector, signature: H520, h: Height, r: Round, step: Step, block_hash: Option<BlockHash>, address: Address) -> Option<H160> {
|
fn full_vote<'a>(collector: &VoteCollector, signature: H520, vote_step: VoteStep, block_hash: Option<BlockHash>, address: &'a Address) -> Option<&'a Address> {
|
||||||
collector.vote(ConsensusMessage { signature: signature, height: h, round: r, step: step, block_hash: block_hash }, address)
|
collector.vote(ConsensusMessage { signature: signature, vote_step: vote_step, block_hash: block_hash }, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -173,68 +206,71 @@ mod tests {
|
|||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
signatures.push(H520::random());
|
signatures.push(H520::random());
|
||||||
}
|
}
|
||||||
|
let propose_step = VoteStep::new(h, r, Step::Propose);
|
||||||
|
let prevote_step = VoteStep::new(h, r, Step::Prevote);
|
||||||
|
let precommit_step = VoteStep::new(h, r, Step::Precommit);
|
||||||
// Wrong height proposal.
|
// Wrong height proposal.
|
||||||
random_vote(&collector, signatures[4].clone(), h - 1, r, Step::Propose, bh.clone());
|
random_vote(&collector, signatures[4].clone(), VoteStep::new(h - 1, r, Step::Propose), bh.clone());
|
||||||
// Good proposal
|
// Good proposal
|
||||||
random_vote(&collector, signatures[0].clone(), h, r, Step::Propose, bh.clone());
|
random_vote(&collector, signatures[0].clone(), propose_step.clone(), bh.clone());
|
||||||
// Wrong block proposal.
|
// Wrong block proposal.
|
||||||
random_vote(&collector, signatures[0].clone(), h, r, Step::Propose, Some("0".sha3()));
|
random_vote(&collector, signatures[0].clone(), propose_step.clone(), Some("0".sha3()));
|
||||||
// Wrong block precommit.
|
// Wrong block precommit.
|
||||||
random_vote(&collector, signatures[3].clone(), h, r, Step::Precommit, Some("0".sha3()));
|
random_vote(&collector, signatures[3].clone(), precommit_step.clone(), Some("0".sha3()));
|
||||||
// Wrong round proposal.
|
// Wrong round proposal.
|
||||||
random_vote(&collector, signatures[0].clone(), h, r - 1, Step::Propose, bh.clone());
|
random_vote(&collector, signatures[0].clone(), VoteStep::new(h, r - 1, Step::Propose), bh.clone());
|
||||||
// Prevote.
|
// Prevote.
|
||||||
random_vote(&collector, signatures[0].clone(), h, r, Step::Prevote, bh.clone());
|
random_vote(&collector, signatures[0].clone(), prevote_step.clone(), bh.clone());
|
||||||
// Relevant precommit.
|
// Relevant precommit.
|
||||||
random_vote(&collector, signatures[2].clone(), h, r, Step::Precommit, bh.clone());
|
random_vote(&collector, signatures[2].clone(), precommit_step.clone(), bh.clone());
|
||||||
// Replcated vote.
|
// Replcated vote.
|
||||||
random_vote(&collector, signatures[2].clone(), h, r, Step::Precommit, bh.clone());
|
random_vote(&collector, signatures[2].clone(), precommit_step.clone(), bh.clone());
|
||||||
// Wrong round precommit.
|
// Wrong round precommit.
|
||||||
random_vote(&collector, signatures[4].clone(), h, r + 1, Step::Precommit, bh.clone());
|
random_vote(&collector, signatures[4].clone(), VoteStep::new(h, r + 1, Step::Precommit), bh.clone());
|
||||||
// Wrong height precommit.
|
// Wrong height precommit.
|
||||||
random_vote(&collector, signatures[3].clone(), h + 1, r, Step::Precommit, bh.clone());
|
random_vote(&collector, signatures[3].clone(), VoteStep::new(h + 1, r, Step::Precommit), bh.clone());
|
||||||
// Relevant precommit.
|
// Relevant precommit.
|
||||||
random_vote(&collector, signatures[1].clone(), h, r, Step::Precommit, bh.clone());
|
random_vote(&collector, signatures[1].clone(), precommit_step.clone(), bh.clone());
|
||||||
// Wrong round precommit, same signature.
|
// Wrong round precommit, same signature.
|
||||||
random_vote(&collector, signatures[1].clone(), h, r + 1, Step::Precommit, bh.clone());
|
random_vote(&collector, signatures[1].clone(), VoteStep::new(h, r + 1, Step::Precommit), bh.clone());
|
||||||
// Wrong round precommit.
|
// Wrong round precommit.
|
||||||
random_vote(&collector, signatures[4].clone(), h, r - 1, Step::Precommit, bh.clone());
|
random_vote(&collector, signatures[4].clone(), VoteStep::new(h, r - 1, Step::Precommit), bh.clone());
|
||||||
let seal = SealSignatures {
|
let seal = SealSignatures {
|
||||||
proposal: signatures[0],
|
proposal: signatures[0],
|
||||||
votes: signatures[1..3].to_vec()
|
votes: signatures[1..3].to_vec()
|
||||||
};
|
};
|
||||||
assert_eq!(seal, collector.seal_signatures(h, r, bh.unwrap()).unwrap());
|
assert_eq!(seal, collector.seal_signatures(h, r, &bh.unwrap()).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn count_votes() {
|
fn count_votes() {
|
||||||
let collector = VoteCollector::new();
|
let collector = VoteCollector::new();
|
||||||
|
let prevote_step = VoteStep::new(3, 2, Step::Prevote);
|
||||||
|
let precommit_step = VoteStep::new(3, 2, Step::Precommit);
|
||||||
// good prevote
|
// good prevote
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("0".sha3()));
|
random_vote(&collector, H520::random(), prevote_step.clone(), Some("0".sha3()));
|
||||||
random_vote(&collector, H520::random(), 3, 1, Step::Prevote, Some("0".sha3()));
|
random_vote(&collector, H520::random(), VoteStep::new(3, 1, Step::Prevote), Some("0".sha3()));
|
||||||
// good precommit
|
// good precommit
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Precommit, Some("0".sha3()));
|
random_vote(&collector, H520::random(), precommit_step.clone(), Some("0".sha3()));
|
||||||
random_vote(&collector, H520::random(), 3, 3, Step::Precommit, Some("0".sha3()));
|
random_vote(&collector, H520::random(), VoteStep::new(3, 3, Step::Precommit), Some("0".sha3()));
|
||||||
// good prevote
|
// good prevote
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("1".sha3()));
|
random_vote(&collector, H520::random(), prevote_step.clone(), Some("1".sha3()));
|
||||||
// good prevote
|
// good prevote
|
||||||
let same_sig = H520::random();
|
let same_sig = H520::random();
|
||||||
random_vote(&collector, same_sig.clone(), 3, 2, Step::Prevote, Some("1".sha3()));
|
random_vote(&collector, same_sig.clone(), prevote_step.clone(), Some("1".sha3()));
|
||||||
random_vote(&collector, same_sig, 3, 2, Step::Prevote, Some("1".sha3()));
|
random_vote(&collector, same_sig, prevote_step.clone(), Some("1".sha3()));
|
||||||
// good precommit
|
// good precommit
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Precommit, Some("1".sha3()));
|
random_vote(&collector, H520::random(), precommit_step.clone(), Some("1".sha3()));
|
||||||
// good prevote
|
// good prevote
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("0".sha3()));
|
random_vote(&collector, H520::random(), prevote_step.clone(), Some("0".sha3()));
|
||||||
random_vote(&collector, H520::random(), 2, 2, Step::Precommit, Some("2".sha3()));
|
random_vote(&collector, H520::random(), VoteStep::new(2, 2, Step::Precommit), Some("2".sha3()));
|
||||||
|
|
||||||
assert_eq!(collector.count_step_votes(3, 2, Step::Prevote), 4);
|
assert_eq!(collector.count_step_votes(&prevote_step), 4);
|
||||||
assert_eq!(collector.count_step_votes(3, 2, Step::Precommit), 2);
|
assert_eq!(collector.count_step_votes(&precommit_step), 2);
|
||||||
|
|
||||||
let message = ConsensusMessage {
|
let message = ConsensusMessage {
|
||||||
signature: H520::default(),
|
signature: H520::default(),
|
||||||
height: 3,
|
vote_step: prevote_step,
|
||||||
round: 2,
|
|
||||||
step: Step::Prevote,
|
|
||||||
block_hash: Some("1".sha3())
|
block_hash: Some("1".sha3())
|
||||||
};
|
};
|
||||||
assert_eq!(collector.count_aligned_votes(&message), 2);
|
assert_eq!(collector.count_aligned_votes(&message), 2);
|
||||||
@ -243,30 +279,29 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn remove_old() {
|
fn remove_old() {
|
||||||
let collector = VoteCollector::new();
|
let collector = VoteCollector::new();
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("0".sha3()));
|
let vote = |height, round, step, hash| {
|
||||||
random_vote(&collector, H520::random(), 3, 1, Step::Prevote, Some("0".sha3()));
|
random_vote(&collector, H520::random(), VoteStep::new(height, round, step), hash);
|
||||||
random_vote(&collector, H520::random(), 3, 3, Step::Precommit, Some("0".sha3()));
|
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("1".sha3()));
|
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("1".sha3()));
|
|
||||||
random_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("0".sha3()));
|
|
||||||
random_vote(&collector, H520::random(), 2, 2, Step::Precommit, Some("2".sha3()));
|
|
||||||
|
|
||||||
let message = ConsensusMessage {
|
|
||||||
signature: H520::default(),
|
|
||||||
height: 3,
|
|
||||||
round: 2,
|
|
||||||
step: Step::Precommit,
|
|
||||||
block_hash: Some("1".sha3())
|
|
||||||
};
|
};
|
||||||
collector.throw_out_old(&message);
|
vote(3, 2, Step::Prevote, Some("0".sha3()));
|
||||||
|
vote(3, 1, Step::Prevote, Some("0".sha3()));
|
||||||
|
vote(3, 3, Step::Precommit, Some("0".sha3()));
|
||||||
|
vote(3, 2, Step::Prevote, Some("1".sha3()));
|
||||||
|
vote(3, 2, Step::Prevote, Some("1".sha3()));
|
||||||
|
vote(3, 2, Step::Prevote, Some("0".sha3()));
|
||||||
|
vote(2, 2, Step::Precommit, Some("2".sha3()));
|
||||||
|
|
||||||
|
collector.throw_out_old(&VoteStep::new(3, 2, Step::Precommit));
|
||||||
assert_eq!(collector.votes.read().len(), 1);
|
assert_eq!(collector.votes.read().len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn malicious_authority() {
|
fn malicious_authority() {
|
||||||
let collector = VoteCollector::new();
|
let collector = VoteCollector::new();
|
||||||
full_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("0".sha3()), Address::default());
|
let vote_step = VoteStep::new(3, 2, Step::Prevote);
|
||||||
full_vote(&collector, H520::random(), 3, 2, Step::Prevote, Some("1".sha3()), Address::default());
|
// Vote is inserted fine.
|
||||||
assert_eq!(collector.count_step_votes(3, 2, Step::Prevote), 1);
|
assert!(full_vote(&collector, H520::random(), vote_step.clone(), Some("0".sha3()), &Address::default()).is_none());
|
||||||
|
// Returns the double voting address.
|
||||||
|
full_vote(&collector, H520::random(), vote_step.clone(), Some("1".sha3()), &Address::default()).unwrap();
|
||||||
|
assert_eq!(collector.count_step_votes(&vote_step), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,17 +118,17 @@ mod provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn as_string<T: fmt::Debug>(e: T) -> String { format!("{:?}", e) }
|
fn as_string<T: fmt::Debug>(e: T) -> String { format!("{:?}", e) }
|
||||||
|
|
||||||
/// Auto-generated from: `{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}`
|
/// Auto-generated from: `{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}`
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn get_validators(&self) -> Result<Vec<util::Address>, String> {
|
pub fn get_validators(&self) -> Result<Vec<util::Address>, String> {
|
||||||
let call = self.contract.function("getValidators".into()).map_err(Self::as_string)?;
|
let call = self.contract.function("getValidators".into()).map_err(Self::as_string)?;
|
||||||
let data = call.encode_call(
|
let data = call.encode_call(
|
||||||
vec![]
|
vec![]
|
||||||
).map_err(Self::as_string)?;
|
).map_err(Self::as_string)?;
|
||||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_array().and_then(|v| v.into_iter().map(|a| a.to_address()).collect::<Option<Vec<[u8; 20]>>>()).ok_or("Invalid type returned")?; r.into_iter().map(|a| util::Address::from(a)).collect::<Vec<_>>() }))
|
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_array().and_then(|v| v.into_iter().map(|a| a.to_address()).collect::<Option<Vec<[u8; 20]>>>()).ok_or("Invalid type returned")?; r.into_iter().map(|a| util::Address::from(a)).collect::<Vec<_>>() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,6 +140,7 @@ mod tests {
|
|||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
use transaction::{Transaction, Action};
|
use transaction::{Transaction, Action};
|
||||||
use client::{BlockChainClient, EngineClient};
|
use client::{BlockChainClient, EngineClient};
|
||||||
|
use ethkey::Secret;
|
||||||
use miner::MinerService;
|
use miner::MinerService;
|
||||||
use tests::helpers::generate_dummy_client_with_spec_and_data;
|
use tests::helpers::generate_dummy_client_with_spec_and_data;
|
||||||
use super::super::ValidatorSet;
|
use super::super::ValidatorSet;
|
||||||
@ -158,8 +159,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn changes_validators() {
|
fn changes_validators() {
|
||||||
let tap = Arc::new(AccountProvider::transient_provider());
|
let tap = Arc::new(AccountProvider::transient_provider());
|
||||||
let v0 = tap.insert_account("1".sha3(), "").unwrap();
|
let s0 = Secret::from_slice(&"1".sha3()).unwrap();
|
||||||
let v1 = tap.insert_account("0".sha3(), "").unwrap();
|
let v0 = tap.insert_account(s0.clone(), "").unwrap();
|
||||||
|
let v1 = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "").unwrap();
|
||||||
let spec_factory = || {
|
let spec_factory = || {
|
||||||
let spec = Spec::new_validator_contract();
|
let spec = Spec::new_validator_contract();
|
||||||
spec.engine.register_account_provider(tap.clone());
|
spec.engine.register_account_provider(tap.clone());
|
||||||
@ -178,7 +180,7 @@ mod tests {
|
|||||||
action: Action::Call(validator_contract),
|
action: Action::Call(validator_contract),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: "f94e18670000000000000000000000000000000000000000000000000000000000000001".from_hex().unwrap(),
|
data: "f94e18670000000000000000000000000000000000000000000000000000000000000001".from_hex().unwrap(),
|
||||||
}.sign(&"1".sha3(), None);
|
}.sign(&s0, None);
|
||||||
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
|
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
|
||||||
client.update_sealing();
|
client.update_sealing();
|
||||||
assert_eq!(client.chain_info().best_block_number, 1);
|
assert_eq!(client.chain_info().best_block_number, 1);
|
||||||
@ -190,7 +192,7 @@ mod tests {
|
|||||||
action: Action::Call(validator_contract),
|
action: Action::Call(validator_contract),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
|
data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
|
||||||
}.sign(&"1".sha3(), None);
|
}.sign(&s0, None);
|
||||||
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
|
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
|
||||||
client.update_sealing();
|
client.update_sealing();
|
||||||
// The transaction is not yet included so still unable to seal.
|
// The transaction is not yet included so still unable to seal.
|
||||||
@ -209,7 +211,7 @@ mod tests {
|
|||||||
action: Action::Call(Address::default()),
|
action: Action::Call(Address::default()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: Vec::new(),
|
data: Vec::new(),
|
||||||
}.sign(&"1".sha3(), None);
|
}.sign(&s0, None);
|
||||||
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
|
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
|
||||||
client.update_sealing();
|
client.update_sealing();
|
||||||
// Able to seal again.
|
// Able to seal again.
|
||||||
|
@ -22,7 +22,7 @@ use action_params::ActionParams;
|
|||||||
use evm::Ext;
|
use evm::Ext;
|
||||||
|
|
||||||
/// Evm errors.
|
/// Evm errors.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// `OutOfGas` is returned when transaction execution runs out of gas.
|
/// `OutOfGas` is returned when transaction execution runs out of gas.
|
||||||
/// The state should be reverted to the state from before the
|
/// The state should be reverted to the state from before the
|
||||||
|
@ -463,8 +463,9 @@ impl<'a> Executive<'a> {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(evm::Error::Internal) => Err(ExecutionError::Internal),
|
Err(evm::Error::Internal) => Err(ExecutionError::Internal),
|
||||||
Err(_) => {
|
Err(exception) => {
|
||||||
Ok(Executed {
|
Ok(Executed {
|
||||||
|
exception: Some(exception),
|
||||||
gas: t.gas,
|
gas: t.gas,
|
||||||
gas_used: t.gas,
|
gas_used: t.gas,
|
||||||
refunded: U256::zero(),
|
refunded: U256::zero(),
|
||||||
@ -479,6 +480,7 @@ impl<'a> Executive<'a> {
|
|||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Ok(Executed {
|
Ok(Executed {
|
||||||
|
exception: None,
|
||||||
gas: t.gas,
|
gas: t.gas,
|
||||||
gas_used: gas_used,
|
gas_used: gas_used,
|
||||||
refunded: refunded,
|
refunded: refunded,
|
||||||
|
@ -844,6 +844,7 @@ mod tests {
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use rustc_serialize::hex::FromHex;
|
use rustc_serialize::hex::FromHex;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use ethkey::Secret;
|
||||||
use util::{U256, H256, FixedHash, Address, Hashable};
|
use util::{U256, H256, FixedHash, Address, Hashable};
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use devtools::*;
|
use devtools::*;
|
||||||
@ -854,6 +855,10 @@ mod tests {
|
|||||||
use trace::{FlatTrace, TraceError, trace};
|
use trace::{FlatTrace, TraceError, trace};
|
||||||
use types::executed::CallType;
|
use types::executed::CallType;
|
||||||
|
|
||||||
|
fn secret() -> Secret {
|
||||||
|
Secret::from_slice(&"".sha3()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_apply_create_transaction() {
|
fn should_apply_create_transaction() {
|
||||||
init_log();
|
init_log();
|
||||||
@ -872,7 +877,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(),
|
data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
@ -932,7 +937,7 @@ mod tests {
|
|||||||
action: Action::Create,
|
action: Action::Create,
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: FromHex::from_hex("5b600056").unwrap(),
|
data: FromHex::from_hex("5b600056").unwrap(),
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
@ -969,7 +974,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
@ -1012,7 +1017,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
let result = state.apply(&info, &engine, &t, true).unwrap();
|
let result = state.apply(&info, &engine, &t, true).unwrap();
|
||||||
@ -1054,7 +1059,7 @@ mod tests {
|
|||||||
action: Action::Call(0x1.into()),
|
action: Action::Call(0x1.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
let result = state.apply(&info, engine, &t, true).unwrap();
|
let result = state.apply(&info, engine, &t, true).unwrap();
|
||||||
|
|
||||||
@ -1096,7 +1101,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap());
|
||||||
let result = state.apply(&info, engine, &t, true).unwrap();
|
let result = state.apply(&info, engine, &t, true).unwrap();
|
||||||
@ -1139,7 +1144,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
||||||
@ -1201,7 +1206,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 0.into(),
|
value: 0.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
||||||
@ -1260,7 +1265,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
@ -1300,7 +1305,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap());
|
||||||
@ -1360,7 +1365,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap());
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
@ -1415,7 +1420,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds.
|
state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds.
|
||||||
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty);
|
||||||
@ -1458,7 +1463,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],//600480600b6000396000f35b600056
|
data: vec![],//600480600b6000396000f35b600056
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap());
|
||||||
@ -1514,7 +1519,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap());
|
||||||
@ -1589,7 +1594,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],//600480600b6000396000f35b600056
|
data: vec![],//600480600b6000396000f35b600056
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap());
|
||||||
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap());
|
state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap());
|
||||||
@ -1662,7 +1667,7 @@ mod tests {
|
|||||||
action: Action::Call(0xa.into()),
|
action: Action::Call(0xa.into()),
|
||||||
value: 100.into(),
|
value: 100.into(),
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}.sign(&"".sha3(), None);
|
}.sign(&secret(), None);
|
||||||
|
|
||||||
state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap());
|
state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap());
|
||||||
state.add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty);
|
state.add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty);
|
||||||
|
@ -28,7 +28,7 @@ use rlp::View;
|
|||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use views::BlockView;
|
use views::BlockView;
|
||||||
use util::stats::Histogram;
|
use util::stats::Histogram;
|
||||||
use ethkey::KeyPair;
|
use ethkey::{KeyPair, Secret};
|
||||||
use transaction::{PendingTransaction, Transaction, Action};
|
use transaction::{PendingTransaction, Transaction, Action};
|
||||||
use miner::MinerService;
|
use miner::MinerService;
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ fn change_history_size() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn does_not_propagate_delayed_transactions() {
|
fn does_not_propagate_delayed_transactions() {
|
||||||
let key = KeyPair::from_secret("test".sha3()).unwrap();
|
let key = KeyPair::from_secret(Secret::from_slice(&"test".sha3()).unwrap()).unwrap();
|
||||||
let secret = key.secret();
|
let secret = key.secret();
|
||||||
let tx0 = PendingTransaction::new(Transaction {
|
let tx0 = PendingTransaction::new(Transaction {
|
||||||
nonce: 0.into(),
|
nonce: 0.into(),
|
||||||
|
@ -163,7 +163,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
|
|||||||
let mut last_hashes = vec![];
|
let mut last_hashes = vec![];
|
||||||
let mut last_header = genesis_header.clone();
|
let mut last_header = genesis_header.clone();
|
||||||
|
|
||||||
let kp = KeyPair::from_secret("".sha3()).unwrap();
|
let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap();
|
||||||
let author = kp.address();
|
let author = kp.address();
|
||||||
|
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
use util::{Bytes, U256, Address, U512};
|
use util::{Bytes, U256, Address, U512};
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
|
use evm;
|
||||||
use trace::{VMTrace, FlatTrace};
|
use trace::{VMTrace, FlatTrace};
|
||||||
use types::log_entry::LogEntry;
|
use types::log_entry::LogEntry;
|
||||||
use types::state_diff::StateDiff;
|
use types::state_diff::StateDiff;
|
||||||
@ -65,6 +66,9 @@ impl Decodable for CallType {
|
|||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
#[cfg_attr(feature = "ipc", binary)]
|
#[cfg_attr(feature = "ipc", binary)]
|
||||||
pub struct Executed {
|
pub struct Executed {
|
||||||
|
/// True if the outer call/create resulted in an exceptional exit.
|
||||||
|
pub exception: Option<evm::Error>,
|
||||||
|
|
||||||
/// Gas paid up front for execution of transaction.
|
/// Gas paid up front for execution of transaction.
|
||||||
pub gas: U256,
|
pub gas: U256,
|
||||||
|
|
||||||
@ -178,6 +182,8 @@ pub enum CallError {
|
|||||||
TransactionNotFound,
|
TransactionNotFound,
|
||||||
/// Couldn't find requested block's state in the chain.
|
/// Couldn't find requested block's state in the chain.
|
||||||
StatePruned,
|
StatePruned,
|
||||||
|
/// Couldn't find an amount of gas that didn't result in an exception.
|
||||||
|
Exceptional,
|
||||||
/// Error executing.
|
/// Error executing.
|
||||||
Execution(ExecutionError),
|
Execution(ExecutionError),
|
||||||
}
|
}
|
||||||
@ -195,6 +201,7 @@ impl fmt::Display for CallError {
|
|||||||
let msg = match *self {
|
let msg = match *self {
|
||||||
TransactionNotFound => "Transaction couldn't be found in the chain".into(),
|
TransactionNotFound => "Transaction couldn't be found in the chain".into(),
|
||||||
StatePruned => "Couldn't find the transaction block's state in the chain".into(),
|
StatePruned => "Couldn't find the transaction block's state in the chain".into(),
|
||||||
|
Exceptional => "An exception happened in the execution".into(),
|
||||||
Execution(ref e) => format!("{}", e),
|
Execution(ref e) => format!("{}", e),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@ impl HeapSizeOf for Transaction {
|
|||||||
impl From<ethjson::state::Transaction> for SignedTransaction {
|
impl From<ethjson::state::Transaction> for SignedTransaction {
|
||||||
fn from(t: ethjson::state::Transaction) -> Self {
|
fn from(t: ethjson::state::Transaction) -> Self {
|
||||||
let to: Option<ethjson::hash::Address> = t.to.into();
|
let to: Option<ethjson::hash::Address> = t.to.into();
|
||||||
|
let secret = Secret::from_slice(&t.secret.0).expect("Valid secret expected.");
|
||||||
Transaction {
|
Transaction {
|
||||||
nonce: t.nonce.into(),
|
nonce: t.nonce.into(),
|
||||||
gas_price: t.gas_price.into(),
|
gas_price: t.gas_price.into(),
|
||||||
@ -112,7 +113,7 @@ impl From<ethjson::state::Transaction> for SignedTransaction {
|
|||||||
},
|
},
|
||||||
value: t.value.into(),
|
value: t.value.into(),
|
||||||
data: t.data.into(),
|
data: t.data.into(),
|
||||||
}.sign(&t.secret.into(), None)
|
}.sign(&secret, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ pub mod aes {
|
|||||||
/// ECDH functions
|
/// ECDH functions
|
||||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||||
pub mod ecdh {
|
pub mod ecdh {
|
||||||
use secp256k1::{ecdh, key};
|
use secp256k1::{ecdh, key, Error as SecpError};
|
||||||
use ethkey::{Secret, Public, SECP256K1};
|
use ethkey::{Secret, Public, SECP256K1};
|
||||||
use Error;
|
use Error;
|
||||||
|
|
||||||
@ -180,13 +180,11 @@ pub mod ecdh {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let publ = key::PublicKey::from_slice(context, &pdata)?;
|
let publ = key::PublicKey::from_slice(context, &pdata)?;
|
||||||
// no way to create SecretKey from raw byte array.
|
let sec = key::SecretKey::from_slice(context, &secret)?;
|
||||||
let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) };
|
let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec);
|
||||||
let shared = ecdh::SharedSecret::new_raw(context, &publ, sec);
|
|
||||||
|
|
||||||
let mut s = Secret::default();
|
Secret::from_slice(&shared[0..32])
|
||||||
s.copy_from_slice(&shared[0..32]);
|
.map_err(|_| Error::Secp(SecpError::InvalidSecretKey))
|
||||||
Ok(s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use keccak::Keccak256;
|
use keccak::Keccak256;
|
||||||
use super::{KeyPair, Error, Generator};
|
use super::{KeyPair, Error, Generator, Secret};
|
||||||
|
|
||||||
/// Simple brainwallet.
|
/// Simple brainwallet.
|
||||||
pub struct Brain(String);
|
pub struct Brain(String);
|
||||||
@ -34,13 +34,15 @@ impl Generator for Brain {
|
|||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
secret = secret.keccak256();
|
secret = secret.keccak256();
|
||||||
|
|
||||||
match i > 16384 {
|
match i > 16384 {
|
||||||
false => i += 1,
|
false => i += 1,
|
||||||
true => {
|
true => {
|
||||||
let result = KeyPair::from_secret(secret.clone().into());
|
if let Ok(secret) = Secret::from_slice(&secret) {
|
||||||
if result.as_ref().ok().map_or(false, |r| r.address()[0] == 0) {
|
let result = KeyPair::from_secret(secret);
|
||||||
return result;
|
if result.as_ref().ok().map_or(false, |r| r.address()[0] == 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -60,11 +60,14 @@ impl KeyPair {
|
|||||||
Ok(keypair)
|
Ok(keypair)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_secret_slice(slice: &[u8]) -> Result<KeyPair, Error> {
|
||||||
|
Self::from_secret(Secret::from_slice(slice)?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_keypair(sec: key::SecretKey, publ: key::PublicKey) -> Self {
|
pub fn from_keypair(sec: key::SecretKey, publ: key::PublicKey) -> Self {
|
||||||
let context = &SECP256K1;
|
let context = &SECP256K1;
|
||||||
let serialized = publ.serialize_vec(context, false);
|
let serialized = publ.serialize_vec(context, false);
|
||||||
let mut secret = Secret::default();
|
let secret = Secret::from(sec);
|
||||||
secret.copy_from_slice(&sec[0..32]);
|
|
||||||
let mut public = Public::default();
|
let mut public = Public::default();
|
||||||
public.copy_from_slice(&serialized[1..65]);
|
public.copy_from_slice(&serialized[1..65]);
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ mod keccak;
|
|||||||
mod prefix;
|
mod prefix;
|
||||||
mod random;
|
mod random;
|
||||||
mod signature;
|
mod signature;
|
||||||
|
mod secret;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new();
|
pub static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new();
|
||||||
@ -46,10 +47,10 @@ pub use self::keypair::{KeyPair, public_to_address};
|
|||||||
pub use self::prefix::Prefix;
|
pub use self::prefix::Prefix;
|
||||||
pub use self::random::Random;
|
pub use self::random::Random;
|
||||||
pub use self::signature::{sign, verify_public, verify_address, recover, Signature};
|
pub use self::signature::{sign, verify_public, verify_address, recover, Signature};
|
||||||
|
pub use self::secret::Secret;
|
||||||
|
|
||||||
use bigint::hash::{H160, H256, H512};
|
use bigint::hash::{H160, H256, H512};
|
||||||
|
|
||||||
pub type Address = H160;
|
pub type Address = H160;
|
||||||
pub type Secret = H256;
|
|
||||||
pub type Message = H256;
|
pub type Message = H256;
|
||||||
pub type Public = H512;
|
pub type Public = H512;
|
||||||
|
69
ethkey/src/secret.rs
Normal file
69
ethkey/src/secret.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// 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::fmt;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use secp256k1::key;
|
||||||
|
use bigint::hash::H256;
|
||||||
|
use {Error};
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
|
pub struct Secret {
|
||||||
|
inner: H256,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Secret {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "Secret: 0x{:x}{:x}..{:x}{:x}", self.inner[0], self.inner[1], self.inner[30], self.inner[31])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Secret {
|
||||||
|
pub fn from_slice(key: &[u8]) -> Result<Self, Error> {
|
||||||
|
if key.len() != 32 {
|
||||||
|
return Err(Error::InvalidSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut h = H256::default();
|
||||||
|
h.copy_from_slice(&key[0..32]);
|
||||||
|
Ok(Secret { inner: h })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Secret {
|
||||||
|
type Err = Error;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let hash = H256::from_str(s).map_err(|e| Error::Custom(format!("{:?}", e)))?;
|
||||||
|
Self::from_slice(&hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<key::SecretKey> for Secret {
|
||||||
|
fn from(key: key::SecretKey) -> Self {
|
||||||
|
Self::from_slice(&key[0..32])
|
||||||
|
.expect("`key::SecretKey` is valid (no way to construct invalid one); qed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Secret {
|
||||||
|
type Target = H256;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
use std::{mem, fmt};
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use secp256k1::{Message as SecpMessage, RecoverableSignature, RecoveryId, Error as SecpError};
|
use secp256k1::{Message as SecpMessage, RecoverableSignature, RecoveryId, Error as SecpError};
|
||||||
@ -169,9 +169,8 @@ impl DerefMut for Signature {
|
|||||||
|
|
||||||
pub fn sign(secret: &Secret, message: &Message) -> Result<Signature, Error> {
|
pub fn sign(secret: &Secret, message: &Message) -> Result<Signature, Error> {
|
||||||
let context = &SECP256K1;
|
let context = &SECP256K1;
|
||||||
// no way to create from raw byte array.
|
let sec = SecretKey::from_slice(context, &secret)?;
|
||||||
let sec: &SecretKey = unsafe { mem::transmute(secret) };
|
let s = context.sign_recoverable(&SecpMessage::from_slice(&message[..])?, &sec)?;
|
||||||
let s = context.sign_recoverable(&SecpMessage::from_slice(&message[..])?, sec)?;
|
|
||||||
let (rec_id, data) = s.serialize_compact(context);
|
let (rec_id, data) = s.serialize_compact(context);
|
||||||
let mut data_arr = [0; 65];
|
let mut data_arr = [0; 65];
|
||||||
|
|
||||||
|
@ -122,16 +122,14 @@ impl Crypto {
|
|||||||
return Err(Error::InvalidPassword);
|
return Err(Error::InvalidPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut secret = Secret::default();
|
|
||||||
|
|
||||||
match self.cipher {
|
match self.cipher {
|
||||||
Cipher::Aes128Ctr(ref params) => {
|
Cipher::Aes128Ctr(ref params) => {
|
||||||
let from = 32 - self.ciphertext.len();
|
let from = 32 - self.ciphertext.len();
|
||||||
crypto::aes::decrypt(&derived_left_bits, ¶ms.iv, &self.ciphertext, &mut (&mut *secret)[from..])
|
let mut secret = [0; 32];
|
||||||
|
crypto::aes::decrypt(&derived_left_bits, ¶ms.iv, &self.ciphertext, &mut secret[from..]);
|
||||||
|
Ok(Secret::from_slice(&secret)?)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(secret)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ impl PresaleWallet {
|
|||||||
let len = crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key).map_err(|_| Error::InvalidPassword)?;
|
let len = crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key).map_err(|_| Error::InvalidPassword)?;
|
||||||
let unpadded = &key[..len];
|
let unpadded = &key[..len];
|
||||||
|
|
||||||
let secret = Secret::from(unpadded.keccak256());
|
let secret = Secret::from_slice(&unpadded.keccak256())?;
|
||||||
if let Ok(kp) = KeyPair::from_secret(secret) {
|
if let Ok(kp) = KeyPair::from_secret(secret) {
|
||||||
if kp.address() == self.address {
|
if kp.address() == self.address {
|
||||||
return Ok(kp)
|
return Ok(kp)
|
||||||
|
@ -133,9 +133,9 @@ fn secret_store_load_pat_files() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_decrypting_files_with_short_ciphertext() {
|
fn test_decrypting_files_with_short_ciphertext() {
|
||||||
// 31e9d1e6d844bd3a536800ef8d8be6a9975db509, 30
|
// 31e9d1e6d844bd3a536800ef8d8be6a9975db509, 30
|
||||||
let kp1 = KeyPair::from_secret("000081c29e8142bb6a81bef5a92bda7a8328a5c85bb2f9542e76f9b0f94fc018".into()).unwrap();
|
let kp1 = KeyPair::from_secret("000081c29e8142bb6a81bef5a92bda7a8328a5c85bb2f9542e76f9b0f94fc018".parse().unwrap()).unwrap();
|
||||||
// d1e64e5480bfaf733ba7d48712decb8227797a4e , 31
|
// d1e64e5480bfaf733ba7d48712decb8227797a4e , 31
|
||||||
let kp2 = KeyPair::from_secret("00fa7b3db73dc7dfdf8c5fbdb796d741e4488628c41fc4febd9160a866ba0f35".into()).unwrap();
|
let kp2 = KeyPair::from_secret("00fa7b3db73dc7dfdf8c5fbdb796d741e4488628c41fc4febd9160a866ba0f35".parse().unwrap()).unwrap();
|
||||||
let dir = DiskDirectory::at(ciphertext_path());
|
let dir = DiskDirectory::at(ciphertext_path());
|
||||||
let store = EthStore::open(Box::new(dir)).unwrap();
|
let store = EthStore::open(Box::new(dir)).unwrap();
|
||||||
let accounts = store.accounts().unwrap();
|
let accounts = store.accounts().unwrap();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "parity.js",
|
"name": "parity.js",
|
||||||
"version": "0.2.182",
|
"version": "0.2.184",
|
||||||
"main": "release/index.js",
|
"main": "release/index.js",
|
||||||
"jsnext:main": "src/index.js",
|
"jsnext:main": "src/index.js",
|
||||||
"author": "Parity Team <admin@parity.io>",
|
"author": "Parity Team <admin@parity.io>",
|
||||||
|
@ -23,12 +23,12 @@ import { eventSignature } from '../../util/signature';
|
|||||||
|
|
||||||
export default class Event {
|
export default class Event {
|
||||||
constructor (abi) {
|
constructor (abi) {
|
||||||
this._name = abi.name;
|
|
||||||
this._inputs = EventParam.toEventParams(abi.inputs || []);
|
this._inputs = EventParam.toEventParams(abi.inputs || []);
|
||||||
this._anonymous = !!abi.anonymous;
|
this._anonymous = !!abi.anonymous;
|
||||||
|
|
||||||
const { id, signature } = eventSignature(this._name, this.inputParamTypes());
|
const { id, name, signature } = eventSignature(abi.name, this.inputParamTypes());
|
||||||
this._id = id;
|
this._id = id;
|
||||||
|
this._name = name;
|
||||||
this._signature = signature;
|
this._signature = signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,14 +22,14 @@ import { methodSignature } from '../util/signature';
|
|||||||
export default class Func {
|
export default class Func {
|
||||||
constructor (abi) {
|
constructor (abi) {
|
||||||
this._abi = abi;
|
this._abi = abi;
|
||||||
this._name = abi.name;
|
|
||||||
this._constant = !!abi.constant;
|
this._constant = !!abi.constant;
|
||||||
this._payable = abi.payable;
|
this._payable = abi.payable;
|
||||||
this._inputs = Param.toParams(abi.inputs || []);
|
this._inputs = Param.toParams(abi.inputs || []);
|
||||||
this._outputs = Param.toParams(abi.outputs || []);
|
this._outputs = Param.toParams(abi.outputs || []);
|
||||||
|
|
||||||
const { id, signature } = methodSignature(this._name, this.inputParamTypes());
|
const { id, name, signature } = methodSignature(abi.name, this.inputParamTypes());
|
||||||
this._id = id;
|
this._id = id;
|
||||||
|
this._name = name;
|
||||||
this._signature = signature;
|
this._signature = signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,18 @@ describe('abi/spec/Function', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
|
it('returns signature correctly if name already contains it', () => {
|
||||||
|
const func = new Func({
|
||||||
|
name: 'test(bool,string)',
|
||||||
|
inputs: inputsArr,
|
||||||
|
outputs: outputsArr
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(func.name).to.equal('test');
|
||||||
|
expect(func.id).to.equal('test(bool,string)');
|
||||||
|
expect(func.signature).to.equal('02356205');
|
||||||
|
});
|
||||||
|
|
||||||
it('stores the parameters as received', () => {
|
it('stores the parameters as received', () => {
|
||||||
expect(func.name).to.equal('test');
|
expect(func.name).to.equal('test');
|
||||||
expect(func.constant).to.be.false;
|
expect(func.constant).to.be.false;
|
||||||
|
@ -17,15 +17,31 @@
|
|||||||
import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase
|
import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase
|
||||||
import { fromParamType } from '../spec/paramType/format';
|
import { fromParamType } from '../spec/paramType/format';
|
||||||
|
|
||||||
export function eventSignature (name, params) {
|
export function eventSignature (eventName, params) {
|
||||||
|
const { strName, name } = parseName(eventName);
|
||||||
const types = (params || []).map(fromParamType).join(',');
|
const types = (params || []).map(fromParamType).join(',');
|
||||||
const id = `${name || ''}(${types})`;
|
const id = `${strName}(${types})`;
|
||||||
|
|
||||||
return { id, signature: keccak_256(id) };
|
return { id, name, signature: keccak_256(id) };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function methodSignature (name, params) {
|
export function methodSignature (methodName, params) {
|
||||||
const { id, signature } = eventSignature(name, params);
|
const { id, name, signature } = eventSignature(methodName, params);
|
||||||
|
|
||||||
return { id, signature: signature.substr(0, 8) };
|
return { id, name, signature: signature.substr(0, 8) };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseName (name) {
|
||||||
|
const strName = `${name || ''}`;
|
||||||
|
const idx = strName.indexOf('(');
|
||||||
|
|
||||||
|
if (idx === -1) {
|
||||||
|
return { strName, name };
|
||||||
|
}
|
||||||
|
|
||||||
|
const trimmedName = strName.slice(0, idx);
|
||||||
|
return {
|
||||||
|
strName: trimmedName,
|
||||||
|
name: trimmedName
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -19,50 +19,93 @@ import { eventSignature, methodSignature } from './signature';
|
|||||||
describe('abi/util/signature', () => {
|
describe('abi/util/signature', () => {
|
||||||
describe('eventSignature', () => {
|
describe('eventSignature', () => {
|
||||||
it('encodes signature baz() correctly', () => {
|
it('encodes signature baz() correctly', () => {
|
||||||
expect(eventSignature('baz', []))
|
expect(eventSignature('baz', [])).to.deep.equal({
|
||||||
.to.deep.equal({ id: 'baz()', signature: 'a7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf' });
|
id: 'baz()',
|
||||||
|
name: 'baz',
|
||||||
|
signature: 'a7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes signature baz(uint32) correctly', () => {
|
it('encodes signature baz(uint32) correctly', () => {
|
||||||
expect(eventSignature('baz', [{ type: 'uint', length: 32 }]))
|
expect(eventSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({
|
||||||
.to.deep.equal({ id: 'baz(uint32)', signature: '7d68785e8fc871be024b75964bd86d093511d4bc2dc7cf7bea32c48a0efaecb1' });
|
id: 'baz(uint32)',
|
||||||
|
name: 'baz',
|
||||||
|
signature: '7d68785e8fc871be024b75964bd86d093511d4bc2dc7cf7bea32c48a0efaecb1'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes signature baz(uint32, bool) correctly', () => {
|
it('encodes signature baz(uint32, bool) correctly', () => {
|
||||||
expect(eventSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }]))
|
expect(eventSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({
|
||||||
.to.deep.equal({ id: 'baz(uint32,bool)', signature: 'cdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2' });
|
id: 'baz(uint32,bool)',
|
||||||
|
name: 'baz',
|
||||||
|
signature: 'cdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes no-name signature correctly as ()', () => {
|
it('encodes no-name signature correctly as ()', () => {
|
||||||
expect(eventSignature(undefined, []))
|
expect(eventSignature(undefined, [])).to.deep.equal({
|
||||||
.to.deep.equal({ id: '()', signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe' });
|
id: '()',
|
||||||
|
name: undefined,
|
||||||
|
signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes no-params signature correctly as ()', () => {
|
it('encodes no-params signature correctly as ()', () => {
|
||||||
expect(eventSignature(undefined, undefined))
|
expect(eventSignature(undefined, undefined)).to.deep.equal({
|
||||||
.to.deep.equal({ id: '()', signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe' });
|
id: '()',
|
||||||
|
name: undefined,
|
||||||
|
signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('methodSignature', () => {
|
describe('methodSignature', () => {
|
||||||
it('encodes signature baz() correctly', () => {
|
it('encodes signature baz() correctly', () => {
|
||||||
expect(methodSignature('baz', [])).to.deep.equal({ id: 'baz()', signature: 'a7916fac' });
|
expect(methodSignature('baz', [])).to.deep.equal({
|
||||||
|
id: 'baz()',
|
||||||
|
name: 'baz',
|
||||||
|
signature: 'a7916fac'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes signature baz(uint32) correctly', () => {
|
it('encodes signature baz(uint32) correctly', () => {
|
||||||
expect(methodSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({ id: 'baz(uint32)', signature: '7d68785e' });
|
expect(methodSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({
|
||||||
|
id: 'baz(uint32)',
|
||||||
|
name: 'baz',
|
||||||
|
signature: '7d68785e'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes signature baz(uint32, bool) correctly', () => {
|
it('encodes signature baz(uint32, bool) correctly', () => {
|
||||||
expect(methodSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ id: 'baz(uint32,bool)', signature: 'cdcd77c0' });
|
expect(methodSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({
|
||||||
|
id: 'baz(uint32,bool)',
|
||||||
|
name: 'baz',
|
||||||
|
signature: 'cdcd77c0'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('encodes signature in name correctly', () => {
|
||||||
|
expect(methodSignature('baz(uint32,bool)', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({
|
||||||
|
id: 'baz(uint32,bool)',
|
||||||
|
name: 'baz',
|
||||||
|
signature: 'cdcd77c0'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes no-name signature correctly as ()', () => {
|
it('encodes no-name signature correctly as ()', () => {
|
||||||
expect(methodSignature(undefined, [])).to.deep.equal({ id: '()', signature: '861731d5' });
|
expect(methodSignature(undefined, [])).to.deep.equal({
|
||||||
|
id: '()',
|
||||||
|
name: undefined,
|
||||||
|
signature: '861731d5'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encodes no-params signature correctly as ()', () => {
|
it('encodes no-params signature correctly as ()', () => {
|
||||||
expect(methodSignature(undefined, undefined)).to.deep.equal({ id: '()', signature: '861731d5' });
|
expect(methodSignature(undefined, undefined)).to.deep.equal({
|
||||||
|
id: '()',
|
||||||
|
name: undefined,
|
||||||
|
signature: '861731d5'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -248,18 +248,32 @@ export default class Contract {
|
|||||||
.call(callParams)
|
.call(callParams)
|
||||||
.then((encoded) => func.decodeOutput(encoded))
|
.then((encoded) => func.decodeOutput(encoded))
|
||||||
.then((tokens) => tokens.map((token) => token.value))
|
.then((tokens) => tokens.map((token) => token.value))
|
||||||
.then((returns) => returns.length === 1 ? returns[0] : returns);
|
.then((returns) => returns.length === 1 ? returns[0] : returns)
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn(`${func.name}.call`, values, error);
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!func.constant) {
|
if (!func.constant) {
|
||||||
func.postTransaction = (options, values = []) => {
|
func.postTransaction = (options, values = []) => {
|
||||||
const _options = this._encodeOptions(func, this._addOptionsTo(options), values);
|
const _options = this._encodeOptions(func, this._addOptionsTo(options), values);
|
||||||
return this._api.parity.postTransaction(_options);
|
return this._api.parity
|
||||||
|
.postTransaction(_options)
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn(`${func.name}.postTransaction`, values, error);
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
func.estimateGas = (options, values = []) => {
|
func.estimateGas = (options, values = []) => {
|
||||||
const _options = this._encodeOptions(func, this._addOptionsTo(options), values);
|
const _options = this._encodeOptions(func, this._addOptionsTo(options), values);
|
||||||
return this._api.eth.estimateGas(_options);
|
return this._api.eth
|
||||||
|
.estimateGas(_options)
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn(`${func.name}.estimateGas`, values, error);
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,6 +399,10 @@ export default class Contract {
|
|||||||
this._subscribeToChanges();
|
this._subscribeToChanges();
|
||||||
return subscriptionId;
|
return subscriptionId;
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('subscribe', event, _options, error);
|
||||||
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import { observer } from 'mobx-react';
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import { toWei } from '~/api/util/wei';
|
import { toWei } from '~/api/util/wei';
|
||||||
import { BusyStep, Button, CompletedStep, GasPriceEditor, IdentityIcon, Modal, TxHash, Warning } from '~/ui';
|
import { BusyStep, Button, CompletedStep, GasPriceEditor, IdentityIcon, Modal, TxHash, Warning } from '~/ui';
|
||||||
@ -470,11 +469,7 @@ function mapStateToProps (initState, initProps) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(ExecuteContract);
|
)(ExecuteContract);
|
||||||
|
@ -23,7 +23,7 @@ import { bytesToHex } from '~/api/util/format';
|
|||||||
import Contract from '~/api/contract';
|
import Contract from '~/api/contract';
|
||||||
import ERRORS from './errors';
|
import ERRORS from './errors';
|
||||||
import { ERROR_CODES } from '~/api/transport/error';
|
import { ERROR_CODES } from '~/api/transport/error';
|
||||||
import { DEFAULT_GAS, MAX_GAS_ESTIMATION } from '~/util/constants';
|
import { DEFAULT_GAS, DEFAULT_GASPRICE, MAX_GAS_ESTIMATION } from '~/util/constants';
|
||||||
import GasPriceStore from '~/ui/GasPriceEditor/store';
|
import GasPriceStore from '~/ui/GasPriceEditor/store';
|
||||||
import { getLogger, LOG_KEYS } from '~/config';
|
import { getLogger, LOG_KEYS } from '~/config';
|
||||||
|
|
||||||
@ -441,6 +441,8 @@ export default class TransferStore {
|
|||||||
const gasTotal = new BigNumber(_gasTotal || 0);
|
const gasTotal = new BigNumber(_gasTotal || 0);
|
||||||
const { valueAll, isEth, isWallet } = this;
|
const { valueAll, isEth, isWallet } = this;
|
||||||
|
|
||||||
|
log.debug('@getValues', 'gas', gasTotal.toFormat());
|
||||||
|
|
||||||
if (!valueAll) {
|
if (!valueAll) {
|
||||||
const value = this.getTokenValue();
|
const value = this.getTokenValue();
|
||||||
|
|
||||||
@ -568,6 +570,7 @@ export default class TransferStore {
|
|||||||
send () {
|
send () {
|
||||||
const { options, values } = this._getTransferParams();
|
const { options, values } = this._getTransferParams();
|
||||||
options.minBlock = new BigNumber(this.minBlock || 0).gt(0) ? this.minBlock : null;
|
options.minBlock = new BigNumber(this.minBlock || 0).gt(0) ? this.minBlock : null;
|
||||||
|
log.debug('@send', 'transfer value', options.value && options.value.toFormat());
|
||||||
|
|
||||||
return this._getTransferMethod().postTransaction(options, values);
|
return this._getTransferMethod().postTransaction(options, values);
|
||||||
}
|
}
|
||||||
@ -626,7 +629,8 @@ export default class TransferStore {
|
|||||||
options.gas = MAX_GAS_ESTIMATION;
|
options.gas = MAX_GAS_ESTIMATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { token } = this.getValues(options.gas);
|
const gasTotal = new BigNumber(options.gas || DEFAULT_GAS).mul(options.gasPrice || DEFAULT_GASPRICE);
|
||||||
|
const { token } = this.getValues(gasTotal);
|
||||||
|
|
||||||
if (isEth && !isWallet && !forceToken) {
|
if (isEth && !isWallet && !forceToken) {
|
||||||
options.value = token;
|
options.value = token;
|
||||||
|
@ -75,6 +75,9 @@ export function personalAccountsInfo (accountsInfo) {
|
|||||||
return wallet;
|
return wallet;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
.catch(() => {
|
||||||
|
return [];
|
||||||
|
})
|
||||||
.then((_wallets) => {
|
.then((_wallets) => {
|
||||||
_wallets.forEach((wallet) => {
|
_wallets.forEach((wallet) => {
|
||||||
const owners = wallet.owners.map((o) => o.address);
|
const owners = wallet.owners.map((o) => o.address);
|
||||||
@ -96,6 +99,10 @@ export function personalAccountsInfo (accountsInfo) {
|
|||||||
dispatch(_personalAccountsInfo(data));
|
dispatch(_personalAccountsInfo(data));
|
||||||
dispatch(attachWallets(wallets));
|
dispatch(attachWallets(wallets));
|
||||||
dispatch(fetchBalances());
|
dispatch(fetchBalances());
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('personalAccountsInfo', error);
|
||||||
|
throw error;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import unknownImage from '../../../assets/images/contracts/unknown-64x64.png';
|
import unknownImage from '../../../assets/images/contracts/unknown-64x64.png';
|
||||||
import styles from './balance.css';
|
import styles from './balance.css';
|
||||||
@ -107,11 +106,7 @@ function mapStateToProps (state) {
|
|||||||
return { images };
|
return { images };
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(Balance);
|
)(Balance);
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import styles from './blockStatus.css';
|
import styles from './blockStatus.css';
|
||||||
|
|
||||||
@ -113,11 +112,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(BlockStatus);
|
)(BlockStatus);
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import util from '~/api/util';
|
import util from '~/api/util';
|
||||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||||
@ -162,11 +161,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(InputAddress);
|
)(InputAddress);
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import AddressSelect from '../AddressSelect';
|
import AddressSelect from '../AddressSelect';
|
||||||
|
|
||||||
@ -68,11 +67,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(InputAddressSelect);
|
)(InputAddressSelect);
|
||||||
|
@ -377,11 +377,15 @@ class MethodDecoding extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const inputs = methodInputs.map((input, index) => {
|
const inputs = methodInputs.map((input, index) => {
|
||||||
|
const label = input.name
|
||||||
|
? `${input.name}: ${input.type}`
|
||||||
|
: input.type;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedInput
|
<TypedInput
|
||||||
allowCopy
|
allowCopy
|
||||||
className={ styles.input }
|
className={ styles.input }
|
||||||
label={ input.type }
|
label={ label }
|
||||||
key={ index }
|
key={ index }
|
||||||
param={ input.type }
|
param={ input.type }
|
||||||
readOnly
|
readOnly
|
||||||
|
@ -164,8 +164,8 @@ export default class MethodDecodingStore {
|
|||||||
methodInputs = this.api.util
|
methodInputs = this.api.util
|
||||||
.decodeMethodInput(abi, paramdata)
|
.decodeMethodInput(abi, paramdata)
|
||||||
.map((value, index) => {
|
.map((value, index) => {
|
||||||
const type = abi.inputs[index].type;
|
const { name, type } = abi.inputs[index];
|
||||||
return { type, value };
|
return { name, type, value };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
|
|
||||||
import { Dialog } from 'material-ui';
|
import { Dialog } from 'material-ui';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
@ -113,11 +112,7 @@ function mapStateToProps (state) {
|
|||||||
return { settings };
|
return { settings };
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(Modal);
|
)(Modal);
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase
|
import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase
|
||||||
import ActionFingerprint from 'material-ui/svg-icons/action/fingerprint';
|
import ActionFingerprint from 'material-ui/svg-icons/action/fingerprint';
|
||||||
|
|
||||||
@ -54,11 +53,7 @@ function mapStateToProps (state) {
|
|||||||
return { secureToken };
|
return { secureToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(SignerIcon);
|
)(SignerIcon);
|
||||||
|
@ -15,11 +15,10 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { LinearProgress } from 'material-ui';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { LinearProgress } from 'material-ui';
|
|
||||||
|
|
||||||
import { txLink } from '~/3rdparty/etherscan/links';
|
import { txLink } from '~/3rdparty/etherscan/links';
|
||||||
import ShortenedHash from '../ShortenedHash';
|
import ShortenedHash from '../ShortenedHash';
|
||||||
@ -169,11 +168,7 @@ function mapStateToProps (state) {
|
|||||||
return { isTest };
|
return { isTest };
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(TxHash);
|
)(TxHash);
|
||||||
|
@ -14,10 +14,9 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { observer } from 'mobx-react';
|
|
||||||
|
|
||||||
import Store from './store';
|
import Store from './store';
|
||||||
import TxRow from './TxRow';
|
import TxRow from './TxRow';
|
||||||
@ -92,11 +91,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(TxList);
|
)(TxList);
|
||||||
|
115
js/src/util/subscribe-to-events.spec.js
Normal file
115
js/src/util/subscribe-to-events.spec.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// 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 { spy, stub } from 'sinon';
|
||||||
|
|
||||||
|
import subscribeToEvents from './subscribe-to-events';
|
||||||
|
import {
|
||||||
|
pastLogs, liveLogs, createApi, createContract
|
||||||
|
} from './subscribe-to-events.test.js';
|
||||||
|
|
||||||
|
const delay = (t) => new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, t);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('util/subscribe-to-events', () => {
|
||||||
|
beforeEach(function () {
|
||||||
|
this.api = createApi();
|
||||||
|
this.contract = createContract(this.api);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('installs a filter', async function () {
|
||||||
|
const { api, contract } = this;
|
||||||
|
|
||||||
|
subscribeToEvents(contract, [ 'Foo', 'Bar' ]);
|
||||||
|
await delay(0);
|
||||||
|
|
||||||
|
expect(api.eth.newFilter.calledOnce).to.equal(true);
|
||||||
|
expect(api.eth.newFilter.firstCall.args).to.eql([ {
|
||||||
|
fromBlock: 0, toBlock: 'latest',
|
||||||
|
address: contract.address,
|
||||||
|
topics: [ [
|
||||||
|
contract.instance.Foo.signature,
|
||||||
|
contract.instance.Bar.signature
|
||||||
|
] ]
|
||||||
|
} ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('queries & parses logs in the beginning', async function () {
|
||||||
|
const { api, contract } = this;
|
||||||
|
|
||||||
|
subscribeToEvents(contract, [ 'Foo', 'Bar' ]);
|
||||||
|
|
||||||
|
await delay(0);
|
||||||
|
expect(api.eth.getFilterLogs.callCount).to.equal(1);
|
||||||
|
expect(api.eth.getFilterLogs.firstCall.args).to.eql([ 123 ]);
|
||||||
|
|
||||||
|
await delay(0);
|
||||||
|
expect(contract.parseEventLogs.callCount).to.equal(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('emits logs in the beginning', async function () {
|
||||||
|
const { contract } = this;
|
||||||
|
|
||||||
|
const onLog = spy();
|
||||||
|
const onFoo = spy();
|
||||||
|
const onBar = spy();
|
||||||
|
subscribeToEvents(contract, [ 'Foo', 'Bar' ])
|
||||||
|
.on('log', onLog)
|
||||||
|
.on('Foo', onFoo)
|
||||||
|
.on('Bar', onBar);
|
||||||
|
|
||||||
|
await delay(0);
|
||||||
|
|
||||||
|
expect(onLog.callCount).to.equal(2);
|
||||||
|
expect(onLog.firstCall.args).to.eql([ pastLogs[0] ]);
|
||||||
|
expect(onLog.secondCall.args).to.eql([ pastLogs[1] ]);
|
||||||
|
expect(onFoo.callCount).to.equal(1);
|
||||||
|
expect(onFoo.firstCall.args).to.eql([ pastLogs[0] ]);
|
||||||
|
expect(onBar.callCount).to.equal(1);
|
||||||
|
expect(onBar.firstCall.args).to.eql([ pastLogs[1] ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uninstalls the filter on sunsubscribe', async function () {
|
||||||
|
const { api, contract } = this;
|
||||||
|
|
||||||
|
const s = subscribeToEvents(contract, [ 'Foo', 'Bar' ]);
|
||||||
|
await delay(0);
|
||||||
|
s.unsubscribe();
|
||||||
|
await delay(0);
|
||||||
|
|
||||||
|
expect(api.eth.uninstallFilter.calledOnce).to.equal(true);
|
||||||
|
expect(api.eth.uninstallFilter.firstCall.args).to.eql([ 123 ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('checks for new events regularly', async function () {
|
||||||
|
const { api, contract } = this;
|
||||||
|
api.eth.getFilterLogs = stub().resolves([]);
|
||||||
|
|
||||||
|
const onLog = spy();
|
||||||
|
const onBar = spy();
|
||||||
|
const s = subscribeToEvents(contract, [ 'Bar' ], { interval: 5 })
|
||||||
|
.on('log', onLog)
|
||||||
|
.on('Bar', onBar);
|
||||||
|
await delay(9);
|
||||||
|
s.unsubscribe();
|
||||||
|
|
||||||
|
expect(onLog.callCount).to.equal(1);
|
||||||
|
expect(onLog.firstCall.args).to.eql([ liveLogs[0] ]);
|
||||||
|
expect(onBar.callCount).to.equal(1);
|
||||||
|
expect(onBar.firstCall.args).to.eql([ liveLogs[0] ]);
|
||||||
|
});
|
||||||
|
});
|
53
js/src/util/subscribe-to-events.test.js
Normal file
53
js/src/util/subscribe-to-events.test.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// 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 { stub } from 'sinon';
|
||||||
|
|
||||||
|
export const ADDRESS = '0x1111111111111111111111111111111111111111';
|
||||||
|
|
||||||
|
export const pastLogs = [
|
||||||
|
{ event: 'Foo', type: 'mined', address: ADDRESS, params: {} },
|
||||||
|
{ event: 'Bar', type: 'mined', address: ADDRESS, params: {} }
|
||||||
|
];
|
||||||
|
|
||||||
|
export const liveLogs = [
|
||||||
|
{ event: 'Bar', type: 'mined', address: ADDRESS, params: { foo: 'bar' } }
|
||||||
|
];
|
||||||
|
|
||||||
|
export const createApi = () => ({
|
||||||
|
eth: {
|
||||||
|
newFilter: stub().resolves(123),
|
||||||
|
uninstallFilter: stub()
|
||||||
|
.rejects(new Error('unknown filter id'))
|
||||||
|
.withArgs(123).resolves(null),
|
||||||
|
getFilterLogs: stub()
|
||||||
|
.rejects(new Error('unknown filter id'))
|
||||||
|
.withArgs(123).resolves(pastLogs),
|
||||||
|
getFilterChanges: stub()
|
||||||
|
.rejects(new Error('unknown filter id'))
|
||||||
|
.withArgs(123).resolves(liveLogs)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createContract = (api) => ({
|
||||||
|
api,
|
||||||
|
address: ADDRESS,
|
||||||
|
instance: {
|
||||||
|
Foo: { signature: 'Foo signature' },
|
||||||
|
Bar: { signature: 'Bar signature' }
|
||||||
|
},
|
||||||
|
parseEventLogs: stub().returnsArg(0)
|
||||||
|
});
|
@ -18,7 +18,6 @@ import { observer } from 'mobx-react';
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import { Container, TxList, Loading } from '~/ui';
|
import { Container, TxList, Loading } from '~/ui';
|
||||||
|
|
||||||
@ -118,11 +117,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(Transactions);
|
)(Transactions);
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
|
|
||||||
import { BlockStatus } from '~/ui';
|
import { BlockStatus } from '~/ui';
|
||||||
|
|
||||||
@ -133,11 +132,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(Status);
|
)(Status);
|
||||||
|
@ -14,10 +14,9 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { observer } from 'mobx-react';
|
|
||||||
|
|
||||||
import UpgradeStore from '~/modals/UpgradeParity/store';
|
import UpgradeStore from '~/modals/UpgradeParity/store';
|
||||||
|
|
||||||
@ -123,11 +122,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(Application);
|
)(Application);
|
||||||
|
@ -14,13 +14,12 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { omitBy } from 'lodash';
|
||||||
import { Checkbox } from 'material-ui';
|
import { Checkbox } from 'material-ui';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { omitBy } from 'lodash';
|
|
||||||
|
|
||||||
import { AddDapps, DappPermissions } from '~/modals';
|
import { AddDapps, DappPermissions } from '~/modals';
|
||||||
import PermissionStore from '~/modals/DappPermissions/store';
|
import PermissionStore from '~/modals/DappPermissions/store';
|
||||||
@ -169,11 +168,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(Dapps);
|
)(Dapps);
|
||||||
|
@ -256,7 +256,7 @@ export default class DappsStore {
|
|||||||
store.set(LS_KEY_DISPLAY, this.displayApps);
|
store.set(LS_KEY_DISPLAY, this.displayApps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action addApps = (_apps) => {
|
@action addApps = (_apps = []) => {
|
||||||
transaction(() => {
|
transaction(() => {
|
||||||
const apps = _apps.filter((app) => app);
|
const apps = _apps.filter((app) => app);
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import ActionFingerprint from 'material-ui/svg-icons/action/fingerprint';
|
import ActionFingerprint from 'material-ui/svg-icons/action/fingerprint';
|
||||||
import ContentClear from 'material-ui/svg-icons/content/clear';
|
import ContentClear from 'material-ui/svg-icons/content/clear';
|
||||||
|
|
||||||
@ -162,11 +161,7 @@ function mapStateToProps (state) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(ParityBar);
|
)(ParityBar);
|
||||||
|
@ -14,13 +14,12 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import keycode from 'keycode';
|
||||||
|
import RaisedButton from 'material-ui/RaisedButton';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import RaisedButton from 'material-ui/RaisedButton';
|
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
import keycode from 'keycode';
|
|
||||||
|
|
||||||
import { Form, Input, IdentityIcon } from '~/ui';
|
import { Form, Input, IdentityIcon } from '~/ui';
|
||||||
|
|
||||||
@ -258,11 +257,7 @@ function mapStateToProps (_, initProps) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
|
||||||
return bindActionCreators({}, dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
null
|
||||||
)(TransactionPendingFormConfirm);
|
)(TransactionPendingFormConfirm);
|
||||||
|
@ -20,9 +20,10 @@ use std::net::SocketAddr;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use cli::{Args, ArgsError};
|
use cli::{Args, ArgsError};
|
||||||
use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address};
|
use util::{Hashable, U256, Uint, Bytes, version_data, Address};
|
||||||
use util::log::Colour;
|
use util::log::Colour;
|
||||||
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
|
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
|
||||||
|
use ethcore::ethstore::ethkey::Secret;
|
||||||
use ethcore::client::{VMType};
|
use ethcore::client::{VMType};
|
||||||
use ethcore::miner::{MinerOptions, Banning};
|
use ethcore::miner::{MinerOptions, Banning};
|
||||||
use ethcore::verification::queue::VerifierSettings;
|
use ethcore::verification::queue::VerifierSettings;
|
||||||
@ -603,7 +604,13 @@ impl Configuration {
|
|||||||
let (listen, public) = self.net_addresses()?;
|
let (listen, public) = self.net_addresses()?;
|
||||||
ret.listen_address = listen.map(|l| format!("{}", l));
|
ret.listen_address = listen.map(|l| format!("{}", l));
|
||||||
ret.public_address = public.map(|p| format!("{}", p));
|
ret.public_address = public.map(|p| format!("{}", p));
|
||||||
ret.use_secret = self.args.flag_node_key.as_ref().map(|s| s.parse::<Secret>().unwrap_or_else(|_| s.sha3()));
|
ret.use_secret = match self.args.flag_node_key.as_ref()
|
||||||
|
.map(|s| s.parse::<Secret>().or_else(|_| Secret::from_slice(&s.sha3())).map_err(|e| format!("Invalid key: {:?}", e))
|
||||||
|
) {
|
||||||
|
None => None,
|
||||||
|
Some(Ok(key)) => Some(key),
|
||||||
|
Some(Err(err)) => return Err(err),
|
||||||
|
};
|
||||||
ret.discovery_enabled = !self.args.flag_no_discovery && !self.args.flag_nodiscover;
|
ret.discovery_enabled = !self.args.flag_no_discovery && !self.args.flag_nodiscover;
|
||||||
ret.max_peers = self.max_peers();
|
ret.max_peers = self.max_peers();
|
||||||
ret.min_peers = self.min_peers();
|
ret.min_peers = self.min_peers();
|
||||||
|
@ -22,9 +22,9 @@ use ethcore::client::Client;
|
|||||||
use ethsync::SyncProvider;
|
use ethsync::SyncProvider;
|
||||||
use helpers::replace_home;
|
use helpers::replace_home;
|
||||||
use dir::default_data_path;
|
use dir::default_data_path;
|
||||||
|
use jsonrpc_core::reactor::Remote;
|
||||||
use rpc_apis::SignerService;
|
use rpc_apis::SignerService;
|
||||||
use hash_fetch::fetch::Client as FetchClient;
|
use hash_fetch::fetch::Client as FetchClient;
|
||||||
use parity_reactor::Remote;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
@ -130,6 +130,8 @@ mod server {
|
|||||||
use rpc_apis;
|
use rpc_apis;
|
||||||
use ethcore_rpc::is_major_importing;
|
use ethcore_rpc::is_major_importing;
|
||||||
use hash_fetch::urlhint::ContractClient;
|
use hash_fetch::urlhint::ContractClient;
|
||||||
|
use jsonrpc_core::reactor::RpcHandler;
|
||||||
|
use parity_reactor;
|
||||||
|
|
||||||
pub use ethcore_dapps::Server as WebappServer;
|
pub use ethcore_dapps::Server as WebappServer;
|
||||||
|
|
||||||
@ -146,8 +148,9 @@ mod server {
|
|||||||
let server = dapps::ServerBuilder::new(
|
let server = dapps::ServerBuilder::new(
|
||||||
&dapps_path,
|
&dapps_path,
|
||||||
Arc::new(Registrar { client: deps.client.clone() }),
|
Arc::new(Registrar { client: deps.client.clone() }),
|
||||||
deps.remote.clone(),
|
parity_reactor::Remote::new(deps.remote.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let sync = deps.sync.clone();
|
let sync = deps.sync.clone();
|
||||||
let client = deps.client.clone();
|
let client = deps.client.clone();
|
||||||
let signer = deps.signer.clone();
|
let signer = deps.signer.clone();
|
||||||
@ -156,15 +159,17 @@ mod server {
|
|||||||
.sync_status(Arc::new(move || is_major_importing(Some(sync.status().state), client.queue_info())))
|
.sync_status(Arc::new(move || is_major_importing(Some(sync.status().state), client.queue_info())))
|
||||||
.web_proxy_tokens(Arc::new(move |token| signer.is_valid_web_proxy_access_token(&token)))
|
.web_proxy_tokens(Arc::new(move |token| signer.is_valid_web_proxy_access_token(&token)))
|
||||||
.extra_dapps(&extra_dapps)
|
.extra_dapps(&extra_dapps)
|
||||||
.signer_address(deps.signer.address());
|
.signer_address(deps.signer.address())
|
||||||
|
.allowed_hosts(allowed_hosts);
|
||||||
|
|
||||||
let server = rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext);
|
let apis = rpc_apis::setup_rpc(Default::default(), deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext);
|
||||||
|
let handler = RpcHandler::new(Arc::new(apis), deps.remote);
|
||||||
let start_result = match auth {
|
let start_result = match auth {
|
||||||
None => {
|
None => {
|
||||||
server.start_unsecured_http(url, allowed_hosts)
|
server.start_unsecured_http(url, handler)
|
||||||
},
|
},
|
||||||
Some((username, password)) => {
|
Some((username, password)) => {
|
||||||
server.start_basic_auth_http(url, allowed_hosts, &username, &password)
|
server.start_basic_auth_http(url, &username, &password, handler)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -175,8 +180,9 @@ mod server {
|
|||||||
},
|
},
|
||||||
Err(e) => Err(format!("WebApps error: {:?}", e)),
|
Err(e) => Err(format!("WebApps error: {:?}", e)),
|
||||||
Ok(server) => {
|
Ok(server) => {
|
||||||
|
let ph = deps.panic_handler;
|
||||||
server.set_panic_handler(move || {
|
server.set_panic_handler(move || {
|
||||||
deps.panic_handler.notify_all("Panic in WebApp thread.".to_owned());
|
ph.notify_all("Panic in WebApp thread.".to_owned());
|
||||||
});
|
});
|
||||||
Ok(server)
|
Ok(server)
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@ extern crate ethcore_ipc as ipc;
|
|||||||
extern crate ethcore_ipc_nano as nanoipc;
|
extern crate ethcore_ipc_nano as nanoipc;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
extern crate jsonrpc_core;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate ethcore_light as light;
|
extern crate ethcore_light as light;
|
||||||
extern crate parity_hash_fetch as hash_fetch;
|
extern crate parity_hash_fetch as hash_fetch;
|
||||||
|
@ -40,6 +40,6 @@ pub fn execute(cmd: ImportWallet) -> Result<String, String> {
|
|||||||
let acc_provider = AccountProvider::new(secret_store);
|
let acc_provider = AccountProvider::new(secret_store);
|
||||||
let wallet = PresaleWallet::open(cmd.wallet_path).map_err(|_| "Unable to open presale wallet.")?;
|
let wallet = PresaleWallet::open(cmd.wallet_path).map_err(|_| "Unable to open presale wallet.")?;
|
||||||
let kp = wallet.decrypt(&password).map_err(|_| "Invalid password.")?;
|
let kp = wallet.decrypt(&password).map_err(|_| "Invalid password.")?;
|
||||||
let address = acc_provider.insert_account(*kp.secret(), &password).unwrap();
|
let address = acc_provider.insert_account(kp.secret().clone(), &password).unwrap();
|
||||||
Ok(format!("{:?}", address))
|
Ok(format!("{:?}", address))
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,14 @@ use std::sync::Arc;
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::io;
|
use std::io;
|
||||||
use io::PanicHandler;
|
use io::PanicHandler;
|
||||||
use ethcore_rpc::{RpcServerError, RpcServer as Server, IpcServerError};
|
|
||||||
|
use dir::default_data_path;
|
||||||
|
use ethcore_rpc::{self as rpc, RpcServerError, IpcServerError, Metadata};
|
||||||
|
use helpers::parity_ipc_path;
|
||||||
|
use jsonrpc_core::MetaIoHandler;
|
||||||
|
use jsonrpc_core::reactor::{RpcHandler, Remote};
|
||||||
use rpc_apis;
|
use rpc_apis;
|
||||||
use rpc_apis::ApiSet;
|
use rpc_apis::ApiSet;
|
||||||
use helpers::parity_ipc_path;
|
|
||||||
use dir::default_data_path;
|
|
||||||
|
|
||||||
pub use ethcore_rpc::{IpcServer, Server as HttpServer};
|
pub use ethcore_rpc::{IpcServer, Server as HttpServer};
|
||||||
|
|
||||||
@ -81,6 +84,7 @@ impl fmt::Display for IpcConfiguration {
|
|||||||
pub struct Dependencies {
|
pub struct Dependencies {
|
||||||
pub panic_handler: Arc<PanicHandler>,
|
pub panic_handler: Arc<PanicHandler>,
|
||||||
pub apis: Arc<rpc_apis::Dependencies>,
|
pub apis: Arc<rpc_apis::Dependencies>,
|
||||||
|
pub remote: Remote,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Result<Option<HttpServer>, String> {
|
pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Result<Option<HttpServer>, String> {
|
||||||
@ -93,9 +97,8 @@ pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Result<Option<H
|
|||||||
Ok(Some(setup_http_rpc_server(deps, &addr, conf.cors, conf.hosts, conf.apis)?))
|
Ok(Some(setup_http_rpc_server(deps, &addr, conf.cors, conf.hosts, conf.apis)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_rpc_server(apis: ApiSet, deps: &Dependencies) -> Result<Server, String> {
|
fn setup_apis(apis: ApiSet, deps: &Dependencies) -> MetaIoHandler<Metadata> {
|
||||||
let server = Server::new();
|
rpc_apis::setup_rpc(MetaIoHandler::default(), deps.apis.clone(), apis)
|
||||||
Ok(rpc_apis::setup_rpc(server, deps.apis.clone(), apis))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_http_rpc_server(
|
pub fn setup_http_rpc_server(
|
||||||
@ -105,9 +108,10 @@ pub fn setup_http_rpc_server(
|
|||||||
allowed_hosts: Option<Vec<String>>,
|
allowed_hosts: Option<Vec<String>>,
|
||||||
apis: ApiSet
|
apis: ApiSet
|
||||||
) -> Result<HttpServer, String> {
|
) -> Result<HttpServer, String> {
|
||||||
let server = setup_rpc_server(apis, dependencies)?;
|
let apis = setup_apis(apis, dependencies);
|
||||||
|
let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone());
|
||||||
let ph = dependencies.panic_handler.clone();
|
let ph = dependencies.panic_handler.clone();
|
||||||
let start_result = server.start_http(url, cors_domains, allowed_hosts, ph);
|
let start_result = rpc::start_http(url, cors_domains, allowed_hosts, ph, handler);
|
||||||
match start_result {
|
match start_result {
|
||||||
Err(RpcServerError::IoError(err)) => match err.kind() {
|
Err(RpcServerError::IoError(err)) => match err.kind() {
|
||||||
io::ErrorKind::AddrInUse => Err(format!("RPC address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --jsonrpc-port and --jsonrpc-interface options.", url)),
|
io::ErrorKind::AddrInUse => Err(format!("RPC address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --jsonrpc-port and --jsonrpc-interface options.", url)),
|
||||||
@ -118,14 +122,15 @@ pub fn setup_http_rpc_server(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result<Option<IpcServer>, String> {
|
pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result<Option<IpcServer<Metadata>>, String> {
|
||||||
if !conf.enabled { return Ok(None); }
|
if !conf.enabled { return Ok(None); }
|
||||||
Ok(Some(setup_ipc_rpc_server(deps, &conf.socket_addr, conf.apis)?))
|
Ok(Some(setup_ipc_rpc_server(deps, &conf.socket_addr, conf.apis)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result<IpcServer, String> {
|
pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result<IpcServer<Metadata>, String> {
|
||||||
let server = setup_rpc_server(apis, dependencies)?;
|
let apis = setup_apis(apis, dependencies);
|
||||||
match server.start_ipc(addr) {
|
let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone());
|
||||||
|
match rpc::start_ipc(addr, handler) {
|
||||||
Err(IpcServerError::Io(io_error)) => Err(format!("RPC io error: {}", io_error)),
|
Err(IpcServerError::Io(io_error)) => Err(format!("RPC io error: {}", io_error)),
|
||||||
Err(any_error) => Err(format!("Rpc error: {:?}", any_error)),
|
Err(any_error) => Err(format!("Rpc error: {:?}", any_error)),
|
||||||
Ok(server) => Ok(server)
|
Ok(server) => Ok(server)
|
||||||
|
@ -20,16 +20,16 @@ use std::cmp::PartialEq;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use util::RotatingLogger;
|
use util::RotatingLogger;
|
||||||
|
use jsonrpc_core::{MetaIoHandler};
|
||||||
use ethcore::miner::{Miner, ExternalMiner};
|
use ethcore::miner::{Miner, ExternalMiner};
|
||||||
use ethcore::client::Client;
|
use ethcore::client::Client;
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::snapshot::SnapshotService;
|
use ethcore::snapshot::SnapshotService;
|
||||||
use ethsync::{ManageNetwork, SyncProvider};
|
use ethsync::{ManageNetwork, SyncProvider};
|
||||||
use ethcore_rpc::{Extendable, NetworkSettings};
|
use ethcore_rpc::{Metadata, NetworkSettings};
|
||||||
pub use ethcore_rpc::SignerService;
|
pub use ethcore_rpc::SignerService;
|
||||||
use updater::Updater;
|
use updater::Updater;
|
||||||
use hash_fetch::fetch::Client as FetchClient;
|
use hash_fetch::fetch::Client as FetchClient;
|
||||||
use parity_reactor::Remote;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||||
pub enum Api {
|
pub enum Api {
|
||||||
@ -125,7 +125,6 @@ pub struct Dependencies {
|
|||||||
pub dapps_interface: Option<String>,
|
pub dapps_interface: Option<String>,
|
||||||
pub dapps_port: Option<u16>,
|
pub dapps_port: Option<u16>,
|
||||||
pub fetch: FetchClient,
|
pub fetch: FetchClient,
|
||||||
pub remote: Remote,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
|
fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
|
||||||
@ -170,18 +169,20 @@ impl ApiSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! add_signing_methods {
|
macro_rules! add_signing_methods {
|
||||||
($namespace:ident, $server:expr, $deps:expr) => {
|
($namespace:ident, $handler:expr, $deps:expr) => {
|
||||||
let server = &$server;
|
{
|
||||||
let deps = &$deps;
|
let handler = &mut $handler;
|
||||||
if deps.signer_service.is_enabled() {
|
let deps = &$deps;
|
||||||
server.add_delegate($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store)))
|
if deps.signer_service.is_enabled() {
|
||||||
} else {
|
handler.extend_with($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store)))
|
||||||
server.add_delegate($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner)))
|
} else {
|
||||||
|
handler.extend_with($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet) -> T {
|
pub fn setup_rpc(mut handler: MetaIoHandler<Metadata>, deps: Arc<Dependencies>, apis: ApiSet) -> MetaIoHandler<Metadata> {
|
||||||
use ethcore_rpc::v1::*;
|
use ethcore_rpc::v1::*;
|
||||||
|
|
||||||
// it's turned into vector, cause ont of the cases requires &[]
|
// it's turned into vector, cause ont of the cases requires &[]
|
||||||
@ -189,10 +190,10 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
|||||||
for api in &apis {
|
for api in &apis {
|
||||||
match *api {
|
match *api {
|
||||||
Api::Web3 => {
|
Api::Web3 => {
|
||||||
server.add_delegate(Web3Client::new().to_delegate());
|
handler.extend_with(Web3Client::new().to_delegate());
|
||||||
},
|
},
|
||||||
Api::Net => {
|
Api::Net => {
|
||||||
server.add_delegate(NetClient::new(&deps.sync).to_delegate());
|
handler.extend_with(NetClient::new(&deps.sync).to_delegate());
|
||||||
},
|
},
|
||||||
Api::Eth => {
|
Api::Eth => {
|
||||||
let client = EthClient::new(
|
let client = EthClient::new(
|
||||||
@ -207,25 +208,25 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
|||||||
send_block_number_in_get_work: !deps.geth_compatibility,
|
send_block_number_in_get_work: !deps.geth_compatibility,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
server.add_delegate(client.to_delegate());
|
handler.extend_with(client.to_delegate());
|
||||||
|
|
||||||
let filter_client = EthFilterClient::new(&deps.client, &deps.miner);
|
let filter_client = EthFilterClient::new(&deps.client, &deps.miner);
|
||||||
server.add_delegate(filter_client.to_delegate());
|
handler.extend_with(filter_client.to_delegate());
|
||||||
|
|
||||||
add_signing_methods!(EthSigning, server, deps);
|
add_signing_methods!(EthSigning, handler, deps);
|
||||||
},
|
},
|
||||||
Api::Personal => {
|
Api::Personal => {
|
||||||
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
|
handler.extend_with(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
|
||||||
},
|
},
|
||||||
Api::Signer => {
|
Api::Signer => {
|
||||||
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
|
handler.extend_with(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
|
||||||
},
|
},
|
||||||
Api::Parity => {
|
Api::Parity => {
|
||||||
let signer = match deps.signer_service.is_enabled() {
|
let signer = match deps.signer_service.is_enabled() {
|
||||||
true => Some(deps.signer_service.clone()),
|
true => Some(deps.signer_service.clone()),
|
||||||
false => None,
|
false => None,
|
||||||
};
|
};
|
||||||
server.add_delegate(ParityClient::new(
|
handler.extend_with(ParityClient::new(
|
||||||
&deps.client,
|
&deps.client,
|
||||||
&deps.miner,
|
&deps.miner,
|
||||||
&deps.sync,
|
&deps.sync,
|
||||||
@ -239,32 +240,31 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
|||||||
deps.dapps_port,
|
deps.dapps_port,
|
||||||
).to_delegate());
|
).to_delegate());
|
||||||
|
|
||||||
add_signing_methods!(EthSigning, server, deps);
|
add_signing_methods!(EthSigning, handler, deps);
|
||||||
add_signing_methods!(ParitySigning, server, deps);
|
add_signing_methods!(ParitySigning, handler, deps);
|
||||||
},
|
},
|
||||||
Api::ParityAccounts => {
|
Api::ParityAccounts => {
|
||||||
server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
|
handler.extend_with(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
|
||||||
},
|
},
|
||||||
Api::ParitySet => {
|
Api::ParitySet => {
|
||||||
server.add_delegate(ParitySetClient::new(
|
handler.extend_with(ParitySetClient::new(
|
||||||
&deps.client,
|
&deps.client,
|
||||||
&deps.miner,
|
&deps.miner,
|
||||||
&deps.updater,
|
&deps.updater,
|
||||||
&deps.net_service,
|
&deps.net_service,
|
||||||
deps.fetch.clone(),
|
deps.fetch.clone(),
|
||||||
deps.remote.clone(),
|
|
||||||
).to_delegate())
|
).to_delegate())
|
||||||
},
|
},
|
||||||
Api::Traces => {
|
Api::Traces => {
|
||||||
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())
|
handler.extend_with(TracesClient::new(&deps.client, &deps.miner).to_delegate())
|
||||||
},
|
},
|
||||||
Api::Rpc => {
|
Api::Rpc => {
|
||||||
let modules = to_modules(&apis);
|
let modules = to_modules(&apis);
|
||||||
server.add_delegate(RpcClient::new(modules).to_delegate());
|
handler.extend_with(RpcClient::new(modules).to_delegate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server
|
handler
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -347,7 +347,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
);
|
);
|
||||||
service.add_notify(updater.clone());
|
service.add_notify(updater.clone());
|
||||||
|
|
||||||
|
|
||||||
// set up dependencies for rpc servers
|
// set up dependencies for rpc servers
|
||||||
let signer_path = cmd.signer_conf.signer_path.clone();
|
let signer_path = cmd.signer_conf.signer_path.clone();
|
||||||
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
||||||
@ -375,12 +374,12 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
false => None,
|
false => None,
|
||||||
},
|
},
|
||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
remote: event_loop.remote(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let dependencies = rpc::Dependencies {
|
let dependencies = rpc::Dependencies {
|
||||||
panic_handler: panic_handler.clone(),
|
panic_handler: panic_handler.clone(),
|
||||||
apis: deps_for_rpc_apis.clone(),
|
apis: deps_for_rpc_apis.clone(),
|
||||||
|
remote: event_loop.raw_remote(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// start rpc servers
|
// start rpc servers
|
||||||
@ -393,7 +392,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
apis: deps_for_rpc_apis.clone(),
|
apis: deps_for_rpc_apis.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
sync: sync_provider.clone(),
|
sync: sync_provider.clone(),
|
||||||
remote: event_loop.remote(),
|
remote: event_loop.raw_remote(),
|
||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
signer: deps_for_rpc_apis.signer_service.clone(),
|
signer: deps_for_rpc_apis.signer_service.clone(),
|
||||||
};
|
};
|
||||||
@ -403,6 +402,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
let signer_deps = signer::Dependencies {
|
let signer_deps = signer::Dependencies {
|
||||||
panic_handler: panic_handler.clone(),
|
panic_handler: panic_handler.clone(),
|
||||||
apis: deps_for_rpc_apis.clone(),
|
apis: deps_for_rpc_apis.clone(),
|
||||||
|
remote: event_loop.raw_remote(),
|
||||||
};
|
};
|
||||||
let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?;
|
let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?;
|
||||||
|
|
||||||
|
@ -22,8 +22,9 @@ use io::{ForwardPanic, PanicHandler};
|
|||||||
use util::path::restrict_permissions_owner;
|
use util::path::restrict_permissions_owner;
|
||||||
use rpc_apis;
|
use rpc_apis;
|
||||||
use ethcore_signer as signer;
|
use ethcore_signer as signer;
|
||||||
use helpers::replace_home;
|
|
||||||
use dir::default_data_path;
|
use dir::default_data_path;
|
||||||
|
use helpers::replace_home;
|
||||||
|
use jsonrpc_core::reactor::{RpcHandler, Remote};
|
||||||
pub use ethcore_signer::Server as SignerServer;
|
pub use ethcore_signer::Server as SignerServer;
|
||||||
|
|
||||||
const CODES_FILENAME: &'static str = "authcodes";
|
const CODES_FILENAME: &'static str = "authcodes";
|
||||||
@ -53,6 +54,7 @@ impl Default for Configuration {
|
|||||||
pub struct Dependencies {
|
pub struct Dependencies {
|
||||||
pub panic_handler: Arc<PanicHandler>,
|
pub panic_handler: Arc<PanicHandler>,
|
||||||
pub apis: Arc<rpc_apis::Dependencies>,
|
pub apis: Arc<rpc_apis::Dependencies>,
|
||||||
|
pub remote: Remote,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NewToken {
|
pub struct NewToken {
|
||||||
@ -124,8 +126,9 @@ fn do_start(conf: Configuration, deps: Dependencies) -> Result<SignerServer, Str
|
|||||||
info!("If you do not intend this, exit now.");
|
info!("If you do not intend this, exit now.");
|
||||||
}
|
}
|
||||||
let server = server.skip_origin_validation(conf.skip_origin_validation);
|
let server = server.skip_origin_validation(conf.skip_origin_validation);
|
||||||
let server = rpc_apis::setup_rpc(server, deps.apis, rpc_apis::ApiSet::SafeContext);
|
let apis = rpc_apis::setup_rpc(Default::default(), deps.apis, rpc_apis::ApiSet::SafeContext);
|
||||||
server.start(addr)
|
let handler = RpcHandler::new(Arc::new(apis), deps.remote);
|
||||||
|
server.start(addr, handler)
|
||||||
};
|
};
|
||||||
|
|
||||||
match start_result {
|
match start_result {
|
||||||
|
@ -11,18 +11,18 @@ build = "build.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
rustc-serialize = "0.3"
|
semver = "0.5"
|
||||||
serde = "0.8"
|
serde = "0.8"
|
||||||
serde_json = "0.8"
|
serde_json = "0.8"
|
||||||
|
rustc-serialize = "0.3"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
rand = "0.3"
|
|
||||||
semver = "0.5"
|
|
||||||
transient-hashmap = "0.1"
|
transient-hashmap = "0.1"
|
||||||
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
|
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" }
|
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" }
|
jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
jsonrpc-macros = { git = "https://github.com/ethcore/jsonrpc.git" }
|
jsonrpc-macros = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||||
ethcore-io = { path = "../util/io" }
|
ethcore-io = { path = "../util/io" }
|
||||||
|
ethcore-ipc = { path = "../ipc/rpc" }
|
||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
ethcore = { path = "../ethcore" }
|
ethcore = { path = "../ethcore" }
|
||||||
ethcrypto = { path = "../ethcrypto" }
|
ethcrypto = { path = "../ethcrypto" }
|
||||||
@ -36,12 +36,11 @@ parity-updater = { path = "../updater" }
|
|||||||
rlp = { path = "../util/rlp" }
|
rlp = { path = "../util/rlp" }
|
||||||
fetch = { path = "../util/fetch" }
|
fetch = { path = "../util/fetch" }
|
||||||
parity-reactor = { path = "../util/reactor" }
|
parity-reactor = { path = "../util/reactor" }
|
||||||
serde_macros = { version = "0.8.0", optional = true }
|
serde_macros = { version = "0.8", optional = true }
|
||||||
clippy = { version = "0.0.103", optional = true}
|
clippy = { version = "0.0.103", optional = true}
|
||||||
ethcore-ipc = { path = "../ipc/rpc" }
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
serde_codegen = { version = "0.8.0", optional = true }
|
serde_codegen = { version = "0.8", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["serde_codegen"]
|
default = ["serde_codegen"]
|
||||||
|
@ -14,4 +14,4 @@ ethcore-devtools = { path = "../../devtools" }
|
|||||||
ethcore-rpc = { path = ".." }
|
ethcore-rpc = { path = ".." }
|
||||||
ethcore-util = { path = "../../util" }
|
ethcore-util = { path = "../../util" }
|
||||||
ethjson = { path = "../../json" }
|
ethjson = { path = "../../json" }
|
||||||
serde_json = "0.7.0"
|
serde_json = "0.8"
|
||||||
|
@ -32,6 +32,7 @@ extern crate ethkey;
|
|||||||
extern crate ethcrypto as crypto;
|
extern crate ethcrypto as crypto;
|
||||||
extern crate ethstore;
|
extern crate ethstore;
|
||||||
extern crate ethsync;
|
extern crate ethsync;
|
||||||
|
extern crate ethash;
|
||||||
extern crate transient_hashmap;
|
extern crate transient_hashmap;
|
||||||
extern crate jsonrpc_ipc_server as ipc;
|
extern crate jsonrpc_ipc_server as ipc;
|
||||||
extern crate ethcore_ipc;
|
extern crate ethcore_ipc;
|
||||||
@ -39,7 +40,6 @@ extern crate time;
|
|||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate fetch;
|
extern crate fetch;
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate rand;
|
|
||||||
extern crate parity_updater as updater;
|
extern crate parity_updater as updater;
|
||||||
extern crate parity_reactor;
|
extern crate parity_reactor;
|
||||||
|
|
||||||
@ -58,72 +58,45 @@ extern crate ethcore_devtools as devtools;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use io::PanicHandler;
|
use io::PanicHandler;
|
||||||
use jsonrpc_core::{IoHandler, IoDelegate};
|
use jsonrpc_core::reactor::RpcHandler;
|
||||||
|
|
||||||
pub use ipc::{Server as IpcServer, Error as IpcServerError};
|
pub use ipc::{Server as IpcServer, Error as IpcServerError};
|
||||||
pub use jsonrpc_http_server::{ServerBuilder, Server, RpcServerError};
|
pub use jsonrpc_http_server::{ServerBuilder, Server, RpcServerError};
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings};
|
pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, Metadata, Origin};
|
||||||
pub use v1::block_import::is_major_importing;
|
pub use v1::block_import::is_major_importing;
|
||||||
|
|
||||||
/// An object that can be extended with `IoDelegates`
|
/// Start http server asynchronously and returns result with `Server` handle on success or an error.
|
||||||
pub trait Extendable {
|
pub fn start_http<M: jsonrpc_core::Metadata>(
|
||||||
/// Add `Delegate` to this object.
|
addr: &SocketAddr,
|
||||||
fn add_delegate<D: Send + Sync + 'static>(&self, delegate: IoDelegate<D>);
|
cors_domains: Option<Vec<String>>,
|
||||||
}
|
allowed_hosts: Option<Vec<String>>,
|
||||||
|
panic_handler: Arc<PanicHandler>,
|
||||||
|
handler: RpcHandler<M>,
|
||||||
|
) -> Result<Server, RpcServerError> {
|
||||||
|
|
||||||
/// Http server.
|
let cors_domains = cors_domains.map(|domains| {
|
||||||
pub struct RpcServer {
|
domains.into_iter()
|
||||||
handler: Arc<IoHandler>,
|
.map(|v| match v.as_str() {
|
||||||
}
|
"*" => jsonrpc_http_server::AccessControlAllowOrigin::Any,
|
||||||
|
"null" => jsonrpc_http_server::AccessControlAllowOrigin::Null,
|
||||||
impl Extendable for RpcServer {
|
v => jsonrpc_http_server::AccessControlAllowOrigin::Value(v.into()),
|
||||||
/// Add io delegate.
|
|
||||||
fn add_delegate<D: Send + Sync + 'static>(&self, delegate: IoDelegate<D>) {
|
|
||||||
self.handler.add_delegate(delegate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RpcServer {
|
|
||||||
/// Construct new http server object.
|
|
||||||
pub fn new() -> RpcServer {
|
|
||||||
RpcServer {
|
|
||||||
handler: Arc::new(IoHandler::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Start http server asynchronously and returns result with `Server` handle on success or an error.
|
|
||||||
pub fn start_http(
|
|
||||||
&self,
|
|
||||||
addr: &SocketAddr,
|
|
||||||
cors_domains: Option<Vec<String>>,
|
|
||||||
allowed_hosts: Option<Vec<String>>,
|
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
) -> Result<Server, RpcServerError> {
|
|
||||||
|
|
||||||
let cors_domains = cors_domains.map(|domains| {
|
|
||||||
domains.into_iter()
|
|
||||||
.map(|v| match v.as_str() {
|
|
||||||
"*" => jsonrpc_http_server::AccessControlAllowOrigin::Any,
|
|
||||||
"null" => jsonrpc_http_server::AccessControlAllowOrigin::Null,
|
|
||||||
v => jsonrpc_http_server::AccessControlAllowOrigin::Value(v.into()),
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
|
|
||||||
ServerBuilder::new(self.handler.clone())
|
|
||||||
.cors(cors_domains.into())
|
|
||||||
.allowed_hosts(allowed_hosts.into())
|
|
||||||
.panic_handler(move || {
|
|
||||||
panic_handler.notify_all("Panic in RPC thread.".to_owned());
|
|
||||||
})
|
})
|
||||||
.start_http(addr)
|
.collect()
|
||||||
}
|
});
|
||||||
|
|
||||||
/// Start ipc server asynchronously and returns result with `Server` handle on success or an error.
|
ServerBuilder::with_rpc_handler(handler)
|
||||||
pub fn start_ipc(&self, addr: &str) -> Result<ipc::Server, ipc::Error> {
|
.cors(cors_domains.into())
|
||||||
let server = ipc::Server::new(addr, &self.handler)?;
|
.allowed_hosts(allowed_hosts.into())
|
||||||
server.run_async()?;
|
.panic_handler(move || {
|
||||||
Ok(server)
|
panic_handler.notify_all("Panic in RPC thread.".to_owned());
|
||||||
}
|
})
|
||||||
|
.start_http(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start ipc server asynchronously and returns result with `Server` handle on success or an error.
|
||||||
|
pub fn start_ipc<M: jsonrpc_core::Metadata>(addr: &str, handler: RpcHandler<M>) -> Result<ipc::Server<M>, ipc::Error> {
|
||||||
|
let server = ipc::Server::with_rpc_handler(addr, handler)?;
|
||||||
|
server.run_async()?;
|
||||||
|
Ok(server)
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ mod codes {
|
|||||||
pub const UNKNOWN_ERROR: i64 = -32009;
|
pub const UNKNOWN_ERROR: i64 = -32009;
|
||||||
pub const TRANSACTION_ERROR: i64 = -32010;
|
pub const TRANSACTION_ERROR: i64 = -32010;
|
||||||
pub const EXECUTION_ERROR: i64 = -32015;
|
pub const EXECUTION_ERROR: i64 = -32015;
|
||||||
|
pub const EXCEPTION_ERROR: i64 = -32016;
|
||||||
pub const ACCOUNT_LOCKED: i64 = -32020;
|
pub const ACCOUNT_LOCKED: i64 = -32020;
|
||||||
pub const PASSWORD_INVALID: i64 = -32021;
|
pub const PASSWORD_INVALID: i64 = -32021;
|
||||||
pub const ACCOUNT_ERROR: i64 = -32023;
|
pub const ACCOUNT_ERROR: i64 = -32023;
|
||||||
@ -130,6 +131,14 @@ pub fn state_pruned() -> Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exceptional() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::EXCEPTION_ERROR),
|
||||||
|
message: "The execution failed due to an exception.".into(),
|
||||||
|
data: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn no_work() -> Error {
|
pub fn no_work() -> Error {
|
||||||
Error {
|
Error {
|
||||||
code: ErrorCode::ServerError(codes::NO_WORK),
|
code: ErrorCode::ServerError(codes::NO_WORK),
|
||||||
@ -286,6 +295,7 @@ pub fn from_rlp_error(error: DecoderError) -> Error {
|
|||||||
pub fn from_call_error(error: CallError) -> Error {
|
pub fn from_call_error(error: CallError) -> Error {
|
||||||
match error {
|
match error {
|
||||||
CallError::StatePruned => state_pruned(),
|
CallError::StatePruned => state_pruned(),
|
||||||
|
CallError::Exceptional => exceptional(),
|
||||||
CallError::Execution(e) => execution(e),
|
CallError::Execution(e) => execution(e),
|
||||||
CallError::TransactionNotFound => internal("{}, this should not be the case with eth_call, most likely a bug.", CallError::TransactionNotFound),
|
CallError::TransactionNotFound => internal("{}, this should not be the case with eth_call, most likely a bug.", CallError::TransactionNotFound),
|
||||||
}
|
}
|
||||||
|
@ -16,41 +16,45 @@
|
|||||||
|
|
||||||
//! Eth rpc implementation.
|
//! Eth rpc implementation.
|
||||||
|
|
||||||
extern crate ethash;
|
|
||||||
|
|
||||||
use std::io::{Write};
|
use std::io::{Write};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use time::get_time;
|
|
||||||
use ethsync::{SyncProvider};
|
use futures::{self, BoxFuture, Future};
|
||||||
use ethcore::miner::{MinerService, ExternalMinerService};
|
|
||||||
use jsonrpc_core::*;
|
|
||||||
use jsonrpc_macros::Trailing;
|
|
||||||
use util::{H256, Address, FixedHash, U256, H64, Uint};
|
|
||||||
use util::sha3::*;
|
|
||||||
use util::{FromHex, Mutex};
|
|
||||||
use rlp::{self, UntrustedRlp, View};
|
use rlp::{self, UntrustedRlp, View};
|
||||||
|
use time::get_time;
|
||||||
|
use util::{H256, Address, FixedHash, U256, H64, Uint};
|
||||||
|
use util::sha3::Hashable;
|
||||||
|
use util::{FromHex, Mutex};
|
||||||
|
|
||||||
|
use ethash::SeedHashCompute;
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::client::{MiningBlockChainClient, BlockId, TransactionId, UncleId};
|
|
||||||
use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber};
|
|
||||||
use ethcore::block::IsBlock;
|
use ethcore::block::IsBlock;
|
||||||
|
use ethcore::client::{MiningBlockChainClient, BlockId, TransactionId, UncleId};
|
||||||
use ethcore::ethereum::Ethash;
|
use ethcore::ethereum::Ethash;
|
||||||
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, PendingTransaction, Action};
|
|
||||||
use ethcore::log_entry::LogEntry;
|
|
||||||
use ethcore::filter::Filter as EthcoreFilter;
|
use ethcore::filter::Filter as EthcoreFilter;
|
||||||
|
use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber};
|
||||||
|
use ethcore::log_entry::LogEntry;
|
||||||
|
use ethcore::miner::{MinerService, ExternalMinerService};
|
||||||
|
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, PendingTransaction, Action};
|
||||||
use ethcore::snapshot::SnapshotService;
|
use ethcore::snapshot::SnapshotService;
|
||||||
use self::ethash::SeedHashCompute;
|
use ethsync::{SyncProvider};
|
||||||
|
|
||||||
|
use jsonrpc_core::Error;
|
||||||
|
use jsonrpc_macros::Trailing;
|
||||||
|
|
||||||
use v1::traits::Eth;
|
use v1::traits::Eth;
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
|
RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
|
||||||
Transaction, CallRequest, Index, Filter, Log, Receipt, Work, DappId,
|
Transaction, CallRequest, Index, Filter, Log, Receipt, Work,
|
||||||
H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
|
H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
|
||||||
};
|
};
|
||||||
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
||||||
use v1::helpers::dispatch::{dispatch_transaction, default_gas_price};
|
use v1::helpers::dispatch::{dispatch_transaction, default_gas_price};
|
||||||
use v1::helpers::block_import::is_major_importing;
|
use v1::helpers::block_import::is_major_importing;
|
||||||
|
use v1::metadata::Metadata;
|
||||||
|
|
||||||
const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";
|
const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";
|
||||||
|
|
||||||
@ -271,7 +275,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
|||||||
SN: SnapshotService + 'static,
|
SN: SnapshotService + 'static,
|
||||||
S: SyncProvider + 'static,
|
S: SyncProvider + 'static,
|
||||||
M: MinerService + 'static,
|
M: MinerService + 'static,
|
||||||
EM: ExternalMinerService + 'static {
|
EM: ExternalMinerService + 'static,
|
||||||
|
{
|
||||||
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn protocol_version(&self) -> Result<String, Error> {
|
fn protocol_version(&self) -> Result<String, Error> {
|
||||||
self.active()?;
|
self.active()?;
|
||||||
@ -338,18 +344,21 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
|||||||
Ok(RpcU256::from(default_gas_price(&*client, &*miner)))
|
Ok(RpcU256::from(default_gas_price(&*client, &*miner)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accounts(&self, id: Trailing<DappId>) -> Result<Vec<RpcH160>, Error> {
|
fn accounts(&self, meta: Metadata) -> BoxFuture<Vec<RpcH160>, Error> {
|
||||||
self.active()?;
|
let dapp = meta.dapp_id.unwrap_or_default();
|
||||||
|
|
||||||
let dapp = id.0;
|
let accounts = move || {
|
||||||
|
self.active()?;
|
||||||
|
|
||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
let accounts = store
|
let accounts = store
|
||||||
.note_dapp_used(dapp.clone().into())
|
.note_dapp_used(dapp.clone().into())
|
||||||
.and_then(|_| store.dapps_addresses(dapp.into()))
|
.and_then(|_| store.dapps_addresses(dapp.into()))
|
||||||
.map_err(|e| errors::internal("Could not fetch accounts.", e))?;
|
.map_err(|e| errors::internal("Could not fetch accounts.", e))?;
|
||||||
|
Ok(accounts.into_iter().map(Into::into).collect())
|
||||||
|
};
|
||||||
|
|
||||||
Ok(accounts.into_iter().map(Into::into).collect())
|
futures::done(accounts()).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_number(&self) -> Result<RpcU256, Error> {
|
fn block_number(&self) -> Result<RpcU256, Error> {
|
||||||
@ -660,7 +669,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
|||||||
num => take_weak!(self.client).call(&signed, num.into(), Default::default()),
|
num => take_weak!(self.client).call(&signed, num.into(), Default::default()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
result
|
result
|
||||||
.map(|b| b.output.into())
|
.map(|b| b.output.into())
|
||||||
.map_err(errors::from_call_error)
|
.map_err(errors::from_call_error)
|
||||||
|
@ -19,7 +19,7 @@ use std::sync::{Arc, Weak};
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use util::{Address};
|
use util::{Address};
|
||||||
|
|
||||||
use ethkey::{Brain, Generator};
|
use ethkey::{Brain, Generator, Secret};
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
|
|
||||||
@ -73,7 +73,8 @@ impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlock
|
|||||||
self.active()?;
|
self.active()?;
|
||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
|
|
||||||
store.insert_account(*Brain::new(phrase).generate().unwrap().secret(), &pass)
|
let brain = Brain::new(phrase).generate().unwrap();
|
||||||
|
store.insert_account(brain.secret().clone(), &pass)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.map_err(|e| errors::account("Could not create account.", e))
|
.map_err(|e| errors::account("Could not create account.", e))
|
||||||
}
|
}
|
||||||
@ -92,7 +93,9 @@ impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlock
|
|||||||
self.active()?;
|
self.active()?;
|
||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
|
|
||||||
store.insert_account(secret.into(), &pass)
|
let secret = Secret::from_slice(&secret.0)
|
||||||
|
.map_err(|e| errors::account("Could not create account.", e))?;
|
||||||
|
store.insert_account(secret, &pass)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.map_err(|e| errors::account("Could not create account.", e))
|
.map_err(|e| errors::account("Could not create account.", e))
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,11 @@ use ethcore::client::MiningBlockChainClient;
|
|||||||
use ethcore::mode::Mode;
|
use ethcore::mode::Mode;
|
||||||
use ethsync::ManageNetwork;
|
use ethsync::ManageNetwork;
|
||||||
use fetch::{self, Fetch};
|
use fetch::{self, Fetch};
|
||||||
use futures::Future;
|
use futures::{self, BoxFuture, Future};
|
||||||
use util::sha3;
|
use util::sha3;
|
||||||
use updater::{Service as UpdateService};
|
use updater::{Service as UpdateService};
|
||||||
use parity_reactor::Remote;
|
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Ready;
|
|
||||||
use v1::helpers::errors;
|
use v1::helpers::errors;
|
||||||
use v1::traits::ParitySet;
|
use v1::traits::ParitySet;
|
||||||
use v1::types::{Bytes, H160, H256, U256, ReleaseInfo};
|
use v1::types::{Bytes, H160, H256, U256, ReleaseInfo};
|
||||||
@ -46,7 +44,6 @@ pub struct ParitySetClient<C, M, U, F=fetch::Client> where
|
|||||||
updater: Weak<U>,
|
updater: Weak<U>,
|
||||||
net: Weak<ManageNetwork>,
|
net: Weak<ManageNetwork>,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
remote: Remote,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, U, F> ParitySetClient<C, M, U, F> where
|
impl<C, M, U, F> ParitySetClient<C, M, U, F> where
|
||||||
@ -56,14 +53,13 @@ impl<C, M, U, F> ParitySetClient<C, M, U, F> where
|
|||||||
F: Fetch,
|
F: Fetch,
|
||||||
{
|
{
|
||||||
/// Creates new `ParitySetClient` with given `Fetch`.
|
/// Creates new `ParitySetClient` with given `Fetch`.
|
||||||
pub fn new(client: &Arc<C>, miner: &Arc<M>, updater: &Arc<U>, net: &Arc<ManageNetwork>, fetch: F, remote: Remote) -> Self {
|
pub fn new(client: &Arc<C>, miner: &Arc<M>, updater: &Arc<U>, net: &Arc<ManageNetwork>, fetch: F) -> Self {
|
||||||
ParitySetClient {
|
ParitySetClient {
|
||||||
client: Arc::downgrade(client),
|
client: Arc::downgrade(client),
|
||||||
miner: Arc::downgrade(miner),
|
miner: Arc::downgrade(miner),
|
||||||
updater: Arc::downgrade(updater),
|
updater: Arc::downgrade(updater),
|
||||||
net: Arc::downgrade(net),
|
net: Arc::downgrade(net),
|
||||||
fetch: fetch,
|
fetch: fetch,
|
||||||
remote: remote,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,28 +185,19 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_content(&self, ready: Ready<H256>, url: String) {
|
fn hash_content(&self, url: String) -> BoxFuture<H256, Error> {
|
||||||
let res = self.active();
|
if let Err(e) = self.active() {
|
||||||
|
return futures::failed(e).boxed();
|
||||||
match res {
|
|
||||||
Err(e) => ready.ready(Err(e)),
|
|
||||||
Ok(()) => {
|
|
||||||
let task = self.fetch.fetch(&url).then(move |result| {
|
|
||||||
let result = result
|
|
||||||
.map_err(errors::from_fetch_error)
|
|
||||||
.and_then(|response| {
|
|
||||||
sha3(&mut io::BufReader::new(response)).map_err(errors::from_fetch_error)
|
|
||||||
})
|
|
||||||
.map(Into::into);
|
|
||||||
|
|
||||||
// Receive ready and invoke with result.
|
|
||||||
ready.ready(result);
|
|
||||||
Ok(()) as Result<(), ()>
|
|
||||||
});
|
|
||||||
|
|
||||||
self.remote.spawn(task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.fetch.process(self.fetch.fetch(&url).then(move |result| {
|
||||||
|
result
|
||||||
|
.map_err(errors::from_fetch_error)
|
||||||
|
.and_then(|response| {
|
||||||
|
sha3(&mut io::BufReader::new(response)).map_err(errors::from_fetch_error)
|
||||||
|
})
|
||||||
|
.map(Into::into)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upgrade_ready(&self) -> Result<Option<ReleaseInfo>, Error> {
|
fn upgrade_ready(&self) -> Result<Option<ReleaseInfo>, Error> {
|
||||||
|
@ -24,8 +24,8 @@ use ethcore::account_provider::AccountProvider;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
|
|
||||||
|
use futures::{self, BoxFuture, Future};
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Ready;
|
|
||||||
use v1::helpers::{
|
use v1::helpers::{
|
||||||
errors, dispatch,
|
errors, dispatch,
|
||||||
SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
|
SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService
|
||||||
@ -164,17 +164,21 @@ impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt_message(&self, ready: Ready<RpcBytes>, address: RpcH160, data: RpcBytes) {
|
fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcBytes, Error> {
|
||||||
let res = self.active()
|
let res = self.active()
|
||||||
.and_then(|_| self.dispatch(RpcConfirmationPayload::Decrypt((address, data).into())));
|
.and_then(|_| self.dispatch(RpcConfirmationPayload::Decrypt((address, data).into())));
|
||||||
|
|
||||||
|
let (ready, p) = futures::oneshot();
|
||||||
// TODO [todr] typed handle_dispatch
|
// TODO [todr] typed handle_dispatch
|
||||||
self.handle_dispatch(res, |response| {
|
self.handle_dispatch(res, |response| {
|
||||||
match response {
|
match response {
|
||||||
Ok(RpcConfirmationResponse::Decrypt(data)) => ready.ready(Ok(data)),
|
Ok(RpcConfirmationResponse::Decrypt(data)) => ready.complete(Ok(data)),
|
||||||
Err(e) => ready.ready(Err(e)),
|
Err(e) => ready.complete(Err(e)),
|
||||||
e => ready.ready(Err(errors::internal("Unexpected result.", e))),
|
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,37 +186,49 @@ impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
|
|||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
fn sign(&self, ready: Ready<RpcH520>, address: RpcH160, data: RpcBytes) {
|
fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
||||||
let hash = data.0.sha3().into();
|
let hash = data.0.sha3().into();
|
||||||
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::Signature((address, hash).into())));
|
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::Signature((address, hash).into())));
|
||||||
|
|
||||||
|
let (ready, p) = futures::oneshot();
|
||||||
self.handle_dispatch(res, |response| {
|
self.handle_dispatch(res, |response| {
|
||||||
match response {
|
match response {
|
||||||
Ok(RpcConfirmationResponse::Signature(signature)) => ready.ready(Ok(signature)),
|
Ok(RpcConfirmationResponse::Signature(signature)) => ready.complete(Ok(signature)),
|
||||||
Err(e) => ready.ready(Err(e)),
|
Err(e) => ready.complete(Err(e)),
|
||||||
e => ready.ready(Err(errors::internal("Unexpected result.", e))),
|
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_transaction(&self, ready: Ready<RpcH256>, request: RpcTransactionRequest) {
|
fn send_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
|
||||||
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SendTransaction(request)));
|
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SendTransaction(request)));
|
||||||
|
|
||||||
|
let (ready, p) = futures::oneshot();
|
||||||
self.handle_dispatch(res, |response| {
|
self.handle_dispatch(res, |response| {
|
||||||
match response {
|
match response {
|
||||||
Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.ready(Ok(hash)),
|
Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.complete(Ok(hash)),
|
||||||
Err(e) => ready.ready(Err(e)),
|
Err(e) => ready.complete(Err(e)),
|
||||||
e => ready.ready(Err(errors::internal("Unexpected result.", e))),
|
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_transaction(&self, ready: Ready<RpcRichRawTransaction>, request: RpcTransactionRequest) {
|
fn sign_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
|
||||||
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SignTransaction(request)));
|
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SignTransaction(request)));
|
||||||
|
|
||||||
|
let (ready, p) = futures::oneshot();
|
||||||
self.handle_dispatch(res, |response| {
|
self.handle_dispatch(res, |response| {
|
||||||
match response {
|
match response {
|
||||||
Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.ready(Ok(tx)),
|
Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.complete(Ok(tx)),
|
||||||
Err(e) => ready.ready(Err(e)),
|
Err(e) => ready.complete(Err(e)),
|
||||||
e => ready.ready(Err(errors::internal("Unexpected result.", e))),
|
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@ use ethcore::account_provider::AccountProvider;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
|
|
||||||
|
use futures::{self, BoxFuture, Future};
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Ready;
|
|
||||||
use v1::helpers::errors;
|
use v1::helpers::errors;
|
||||||
use v1::helpers::dispatch;
|
use v1::helpers::dispatch;
|
||||||
use v1::traits::{EthSigning, ParitySigning};
|
use v1::traits::{EthSigning, ParitySigning};
|
||||||
@ -85,32 +85,35 @@ impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
|
|||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
fn sign(&self, ready: Ready<RpcH520>, address: RpcH160, data: RpcBytes) {
|
fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
||||||
let hash = data.0.sha3().into();
|
let hash = data.0.sha3().into();
|
||||||
let result = match self.handle(RpcConfirmationPayload::Signature((address, hash).into())) {
|
let result = match self.handle(RpcConfirmationPayload::Signature((address, hash).into())) {
|
||||||
Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature),
|
Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
};
|
};
|
||||||
ready.ready(result);
|
|
||||||
|
futures::done(result).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_transaction(&self, ready: Ready<RpcH256>, request: RpcTransactionRequest) {
|
fn send_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcH256, Error> {
|
||||||
let result = match self.handle(RpcConfirmationPayload::SendTransaction(request)) {
|
let result = match self.handle(RpcConfirmationPayload::SendTransaction(request)) {
|
||||||
Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
|
Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
};
|
};
|
||||||
ready.ready(result);
|
|
||||||
|
futures::done(result).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_transaction(&self, ready: Ready<RpcRichRawTransaction>, request: RpcTransactionRequest) {
|
fn sign_transaction(&self, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction, Error> {
|
||||||
let result = match self.handle(RpcConfirmationPayload::SignTransaction(request)) {
|
let result = match self.handle(RpcConfirmationPayload::SignTransaction(request)) {
|
||||||
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
|
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
};
|
};
|
||||||
ready.ready(result);
|
|
||||||
|
futures::done(result).boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,13 +121,14 @@ impl<C: 'static, M: 'static> ParitySigning for SigningUnsafeClient<C, M> where
|
|||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
fn decrypt_message(&self, ready: Ready<RpcBytes>, address: RpcH160, data: RpcBytes) {
|
fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcBytes, Error> {
|
||||||
let result = match self.handle(RpcConfirmationPayload::Decrypt((address, data).into())) {
|
let result = match self.handle(RpcConfirmationPayload::Decrypt((address, data).into())) {
|
||||||
Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data),
|
Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
e => Err(errors::internal("Unexpected result", e)),
|
e => Err(errors::internal("Unexpected result", e)),
|
||||||
};
|
};
|
||||||
ready.ready(result);
|
|
||||||
|
futures::done(result).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_sign(&self, _: RpcH160, _: RpcH256) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
fn post_sign(&self, _: RpcH160, _: RpcH256) -> Result<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
|
||||||
|
@ -77,7 +77,6 @@ impl<C, M> TracesClient<C, M> where C: BlockChainClient, M: MinerService {
|
|||||||
impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M: MinerService + 'static {
|
impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M: MinerService + 'static {
|
||||||
fn filter(&self, filter: TraceFilter) -> Result<Vec<LocalizedTrace>, Error> {
|
fn filter(&self, filter: TraceFilter) -> Result<Vec<LocalizedTrace>, Error> {
|
||||||
self.active()?;
|
self.active()?;
|
||||||
|
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
let traces = client.filter_traces(filter.into());
|
let traces = client.filter_traces(filter.into());
|
||||||
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
|
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
|
||||||
@ -94,7 +93,6 @@ impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M:
|
|||||||
|
|
||||||
fn transaction_traces(&self, transaction_hash: H256) -> Result<Vec<LocalizedTrace>, Error> {
|
fn transaction_traces(&self, transaction_hash: H256) -> Result<Vec<LocalizedTrace>, Error> {
|
||||||
self.active()?;
|
self.active()?;
|
||||||
|
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
let traces = client.transaction_traces(TransactionId::Hash(transaction_hash.into()));
|
let traces = client.transaction_traces(TransactionId::Hash(transaction_hash.into()));
|
||||||
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
|
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
|
||||||
|
50
rpc/src/v1/metadata.rs
Normal file
50
rpc/src/v1/metadata.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// 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 jsonrpc_core;
|
||||||
|
|
||||||
|
/// RPC methods metadata.
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq)]
|
||||||
|
pub struct Metadata {
|
||||||
|
/// Current dapplication identifier
|
||||||
|
pub dapp_id: Option<String>,
|
||||||
|
/// Request origin
|
||||||
|
pub origin: Origin,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RPC request origin
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum Origin {
|
||||||
|
/// RPC server
|
||||||
|
Rpc,
|
||||||
|
/// Dapps server
|
||||||
|
Dapps,
|
||||||
|
/// IPC server
|
||||||
|
Ipc,
|
||||||
|
/// Signer
|
||||||
|
Signer,
|
||||||
|
/// Unknown
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Origin {
|
||||||
|
fn default() -> Self {
|
||||||
|
Origin::Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl jsonrpc_core::Metadata for Metadata {}
|
||||||
|
|
@ -21,6 +21,7 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod helpers;
|
mod helpers;
|
||||||
mod impls;
|
mod impls;
|
||||||
|
mod metadata;
|
||||||
|
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
@ -29,3 +30,4 @@ pub mod types;
|
|||||||
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Signer, Personal, Traces, Rpc};
|
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Signer, Personal, Traces, Rpc};
|
||||||
pub use self::impls::*;
|
pub use self::impls::*;
|
||||||
pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import};
|
pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import};
|
||||||
|
pub use self::metadata::{Metadata, Origin};
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use devtools::RandomTempPath;
|
||||||
use ethcore::client::{BlockChainClient, Client, ClientConfig};
|
use ethcore::client::{BlockChainClient, Client, ClientConfig};
|
||||||
use ethcore::ids::BlockId;
|
use ethcore::ids::BlockId;
|
||||||
use ethcore::spec::{Genesis, Spec};
|
use ethcore::spec::{Genesis, Spec};
|
||||||
@ -26,18 +27,17 @@ use ethcore::views::BlockView;
|
|||||||
use ethcore::ethereum;
|
use ethcore::ethereum;
|
||||||
use ethcore::miner::{MinerOptions, Banning, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, PrioritizationStrategy, GasLimit};
|
use ethcore::miner::{MinerOptions, Banning, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, PrioritizationStrategy, GasLimit};
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use devtools::RandomTempPath;
|
|
||||||
use util::Hashable;
|
|
||||||
use io::IoChannel;
|
|
||||||
use util::{U256, H256, Uint, Address};
|
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
|
||||||
use ethjson::blockchain::BlockChain;
|
use ethjson::blockchain::BlockChain;
|
||||||
|
use io::IoChannel;
|
||||||
|
use util::{U256, H256, Uint, Address, Hashable};
|
||||||
|
|
||||||
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::impls::{EthClient, SigningUnsafeClient};
|
use v1::impls::{EthClient, SigningUnsafeClient};
|
||||||
use v1::types::U256 as NU256;
|
use v1::metadata::Metadata;
|
||||||
|
use v1::tests::helpers::{TestSnapshotService, TestSyncProvider, Config};
|
||||||
use v1::traits::eth::Eth;
|
use v1::traits::eth::Eth;
|
||||||
use v1::traits::eth_signing::EthSigning;
|
use v1::traits::eth_signing::EthSigning;
|
||||||
use v1::tests::helpers::{TestSnapshotService, TestSyncProvider, Config};
|
use v1::types::U256 as NU256;
|
||||||
|
|
||||||
fn account_provider() -> Arc<AccountProvider> {
|
fn account_provider() -> Arc<AccountProvider> {
|
||||||
Arc::new(AccountProvider::transient_provider())
|
Arc::new(AccountProvider::transient_provider())
|
||||||
@ -92,7 +92,7 @@ struct EthTester {
|
|||||||
_miner: Arc<MinerService>,
|
_miner: Arc<MinerService>,
|
||||||
_snapshot: Arc<TestSnapshotService>,
|
_snapshot: Arc<TestSnapshotService>,
|
||||||
accounts: Arc<AccountProvider>,
|
accounts: Arc<AccountProvider>,
|
||||||
handler: IoHandler,
|
handler: IoHandler<Metadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthTester {
|
impl EthTester {
|
||||||
@ -147,9 +147,9 @@ impl EthTester {
|
|||||||
&miner_service
|
&miner_service
|
||||||
);
|
);
|
||||||
|
|
||||||
let handler = IoHandler::new();
|
let mut handler = IoHandler::default();
|
||||||
handler.add_delegate(eth_client.to_delegate());
|
handler.extend_with(eth_client.to_delegate());
|
||||||
handler.add_delegate(eth_sign.to_delegate());
|
handler.extend_with(eth_sign.to_delegate());
|
||||||
|
|
||||||
EthTester {
|
EthTester {
|
||||||
_miner: miner_service,
|
_miner: miner_service,
|
||||||
@ -307,7 +307,7 @@ const POSITIVE_NONCE_SPEC: &'static [u8] = br#"{
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn eth_transaction_count() {
|
fn eth_transaction_count() {
|
||||||
let secret = "8a283037bb19c4fed7b1c569e40c7dcff366165eb869110a1b11532963eb9cb2".into();
|
let secret = "8a283037bb19c4fed7b1c569e40c7dcff366165eb869110a1b11532963eb9cb2".parse().unwrap();
|
||||||
let tester = EthTester::from_spec(Spec::load(TRANSACTION_COUNT_SPEC).expect("invalid chain spec"));
|
let tester = EthTester::from_spec(Spec::load(TRANSACTION_COUNT_SPEC).expect("invalid chain spec"));
|
||||||
let address = tester.accounts.insert_account(secret, "").unwrap();
|
let address = tester.accounts.insert_account(secret, "").unwrap();
|
||||||
tester.accounts.unlock_account_permanently(address, "".into()).unwrap();
|
tester.accounts.unlock_account_permanently(address, "".into()).unwrap();
|
||||||
|
@ -31,9 +31,10 @@ use ethcore::transaction::{Transaction, Action};
|
|||||||
use ethcore::miner::{ExternalMiner, MinerService};
|
use ethcore::miner::{ExternalMiner, MinerService};
|
||||||
use ethsync::SyncState;
|
use ethsync::SyncState;
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient};
|
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient};
|
||||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
|
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
|
||||||
|
use v1::metadata::Metadata;
|
||||||
|
|
||||||
fn blockchain_client() -> Arc<TestBlockChainClient> {
|
fn blockchain_client() -> Arc<TestBlockChainClient> {
|
||||||
let client = TestBlockChainClient::new();
|
let client = TestBlockChainClient::new();
|
||||||
@ -66,7 +67,7 @@ struct EthTester {
|
|||||||
pub miner: Arc<TestMinerService>,
|
pub miner: Arc<TestMinerService>,
|
||||||
pub snapshot: Arc<TestSnapshotService>,
|
pub snapshot: Arc<TestSnapshotService>,
|
||||||
hashrates: Arc<Mutex<HashMap<H256, (Instant, U256)>>>,
|
hashrates: Arc<Mutex<HashMap<H256, (Instant, U256)>>>,
|
||||||
pub io: IoHandler,
|
pub io: IoHandler<Metadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EthTester {
|
impl Default for EthTester {
|
||||||
@ -87,10 +88,10 @@ impl EthTester {
|
|||||||
let eth = EthClient::new(&client, &snapshot, &sync, &ap, &miner, &external_miner, options).to_delegate();
|
let eth = EthClient::new(&client, &snapshot, &sync, &ap, &miner, &external_miner, options).to_delegate();
|
||||||
let filter = EthFilterClient::new(&client, &miner).to_delegate();
|
let filter = EthFilterClient::new(&client, &miner).to_delegate();
|
||||||
let sign = SigningUnsafeClient::new(&client, &ap, &miner).to_delegate();
|
let sign = SigningUnsafeClient::new(&client, &ap, &miner).to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io: IoHandler<Metadata> = IoHandler::default();
|
||||||
io.add_delegate(eth);
|
io.extend_with(eth);
|
||||||
io.add_delegate(sign);
|
io.extend_with(sign);
|
||||||
io.add_delegate(filter);
|
io.extend_with(filter);
|
||||||
|
|
||||||
EthTester {
|
EthTester {
|
||||||
client: client,
|
client: client,
|
||||||
@ -373,9 +374,11 @@ fn rpc_eth_accounts() {
|
|||||||
|
|
||||||
// when we add visible address it should return that.
|
// when we add visible address it should return that.
|
||||||
tester.accounts_provider.set_dapps_addresses("app1".into(), vec![10.into()]).unwrap();
|
tester.accounts_provider.set_dapps_addresses("app1".into(), vec![10.into()]).unwrap();
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": ["app1"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
let mut meta = Metadata::default();
|
||||||
|
meta.dapp_id = Some("app1".into());
|
||||||
|
assert_eq!((*tester.io).handle_request_sync(request, meta), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -561,6 +564,7 @@ fn rpc_eth_code() {
|
|||||||
fn rpc_eth_call_latest() {
|
fn rpc_eth_call_latest() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
tester.client.set_execution_result(Ok(Executed {
|
tester.client.set_execution_result(Ok(Executed {
|
||||||
|
exception: None,
|
||||||
gas: U256::zero(),
|
gas: U256::zero(),
|
||||||
gas_used: U256::from(0xff30),
|
gas_used: U256::from(0xff30),
|
||||||
refunded: U256::from(0x5),
|
refunded: U256::from(0x5),
|
||||||
@ -596,6 +600,7 @@ fn rpc_eth_call_latest() {
|
|||||||
fn rpc_eth_call() {
|
fn rpc_eth_call() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
tester.client.set_execution_result(Ok(Executed {
|
tester.client.set_execution_result(Ok(Executed {
|
||||||
|
exception: None,
|
||||||
gas: U256::zero(),
|
gas: U256::zero(),
|
||||||
gas_used: U256::from(0xff30),
|
gas_used: U256::from(0xff30),
|
||||||
refunded: U256::from(0x5),
|
refunded: U256::from(0x5),
|
||||||
@ -631,6 +636,7 @@ fn rpc_eth_call() {
|
|||||||
fn rpc_eth_call_default_block() {
|
fn rpc_eth_call_default_block() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
tester.client.set_execution_result(Ok(Executed {
|
tester.client.set_execution_result(Ok(Executed {
|
||||||
|
exception: None,
|
||||||
gas: U256::zero(),
|
gas: U256::zero(),
|
||||||
gas_used: U256::from(0xff30),
|
gas_used: U256::from(0xff30),
|
||||||
refunded: U256::from(0x5),
|
refunded: U256::from(0x5),
|
||||||
@ -665,6 +671,7 @@ fn rpc_eth_call_default_block() {
|
|||||||
fn rpc_eth_estimate_gas() {
|
fn rpc_eth_estimate_gas() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
tester.client.set_execution_result(Ok(Executed {
|
tester.client.set_execution_result(Ok(Executed {
|
||||||
|
exception: None,
|
||||||
gas: U256::zero(),
|
gas: U256::zero(),
|
||||||
gas_used: U256::from(0xff30),
|
gas_used: U256::from(0xff30),
|
||||||
refunded: U256::from(0x5),
|
refunded: U256::from(0x5),
|
||||||
@ -700,6 +707,7 @@ fn rpc_eth_estimate_gas() {
|
|||||||
fn rpc_eth_estimate_gas_default_block() {
|
fn rpc_eth_estimate_gas_default_block() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
tester.client.set_execution_result(Ok(Executed {
|
tester.client.set_execution_result(Ok(Executed {
|
||||||
|
exception: None,
|
||||||
gas: U256::zero(),
|
gas: U256::zero(),
|
||||||
gas_used: U256::from(0xff30),
|
gas_used: U256::from(0xff30),
|
||||||
refunded: U256::from(0x5),
|
refunded: U256::from(0x5),
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{Net, NetClient};
|
use v1::{Net, NetClient};
|
||||||
use v1::tests::helpers::{Config, TestSyncProvider};
|
use v1::tests::helpers::{Config, TestSyncProvider};
|
||||||
|
|
||||||
@ -30,8 +30,8 @@ fn sync_provider() -> Arc<TestSyncProvider> {
|
|||||||
fn rpc_net_version() {
|
fn rpc_net_version() {
|
||||||
let sync = sync_provider();
|
let sync = sync_provider();
|
||||||
let net = NetClient::new(&sync).to_delegate();
|
let net = NetClient::new(&sync).to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(net);
|
io.extend_with(net);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "net_version", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "net_version", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"3","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"3","id":1}"#;
|
||||||
@ -43,8 +43,8 @@ fn rpc_net_version() {
|
|||||||
fn rpc_net_peer_count() {
|
fn rpc_net_peer_count() {
|
||||||
let sync = sync_provider();
|
let sync = sync_provider();
|
||||||
let net = NetClient::new(&sync).to_delegate();
|
let net = NetClient::new(&sync).to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(net);
|
io.extend_with(net);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "net_peerCount", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "net_peerCount", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0x78","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0x78","id":1}"#;
|
||||||
@ -56,8 +56,8 @@ fn rpc_net_peer_count() {
|
|||||||
fn rpc_net_listening() {
|
fn rpc_net_listening() {
|
||||||
let sync = sync_provider();
|
let sync = sync_provider();
|
||||||
let net = NetClient::new(&sync).to_delegate();
|
let net = NetClient::new(&sync).to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(net);
|
io.extend_with(net);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "net_listening", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "net_listening", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
|
@ -23,7 +23,7 @@ use ethcore::client::{TestBlockChainClient};
|
|||||||
use ethcore::miner::LocalTransactionStatus;
|
use ethcore::miner::LocalTransactionStatus;
|
||||||
use ethstore::ethkey::{Generator, Random};
|
use ethstore::ethkey::{Generator, Random};
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{Parity, ParityClient};
|
use v1::{Parity, ParityClient};
|
||||||
use v1::helpers::{SignerService, NetworkSettings};
|
use v1::helpers::{SignerService, NetworkSettings};
|
||||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater};
|
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater};
|
||||||
@ -87,14 +87,14 @@ impl Dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn default_client(&self) -> IoHandler {
|
fn default_client(&self) -> IoHandler {
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::default();
|
||||||
io.add_delegate(self.client(None).to_delegate());
|
io.extend_with(self.client(None).to_delegate());
|
||||||
io
|
io
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_signer(&self, signer: SignerService) -> IoHandler {
|
fn with_signer(&self, signer: SignerService) -> IoHandler {
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::default();
|
||||||
io.add_delegate(self.client(Some(Arc::new(signer))).to_delegate());
|
io.extend_with(self.client(Some(Arc::new(signer))).to_delegate());
|
||||||
io
|
io
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ use std::sync::Arc;
|
|||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::client::TestBlockChainClient;
|
use ethcore::client::TestBlockChainClient;
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{ParityAccounts, ParityAccountsClient};
|
use v1::{ParityAccounts, ParityAccountsClient};
|
||||||
|
|
||||||
struct ParityAccountsTester {
|
struct ParityAccountsTester {
|
||||||
@ -44,8 +44,8 @@ fn setup() -> ParityAccountsTester {
|
|||||||
let client = blockchain_client();
|
let client = blockchain_client();
|
||||||
let parity_accounts = ParityAccountsClient::new(&accounts, &client);
|
let parity_accounts = ParityAccountsClient::new(&accounts, &client);
|
||||||
|
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::default();
|
||||||
io.add_delegate(parity_accounts.to_delegate());
|
io.extend_with(parity_accounts.to_delegate());
|
||||||
|
|
||||||
let tester = ParityAccountsTester {
|
let tester = ParityAccountsTester {
|
||||||
accounts: accounts,
|
accounts: accounts,
|
||||||
|
@ -22,9 +22,8 @@ use util::{U256, Address};
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::client::TestBlockChainClient;
|
use ethcore::client::TestBlockChainClient;
|
||||||
use ethsync::ManageNetwork;
|
use ethsync::ManageNetwork;
|
||||||
use parity_reactor::Remote;
|
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{ParitySet, ParitySetClient};
|
use v1::{ParitySet, ParitySetClient};
|
||||||
use v1::tests::helpers::{TestMinerService, TestFetch, TestUpdater};
|
use v1::tests::helpers::{TestMinerService, TestFetch, TestUpdater};
|
||||||
use super::manage_network::TestManageNetwork;
|
use super::manage_network::TestManageNetwork;
|
||||||
@ -48,7 +47,7 @@ fn updater_service() -> Arc<TestUpdater> {
|
|||||||
pub type TestParitySetClient = ParitySetClient<TestBlockChainClient, TestMinerService, TestUpdater, TestFetch>;
|
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 {
|
fn parity_set_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>, updater: &Arc<TestUpdater>, net: &Arc<TestManageNetwork>) -> TestParitySetClient {
|
||||||
ParitySetClient::new(client, miner, updater, &(net.clone() as Arc<ManageNetwork>), TestFetch::default(), Remote::new_sync())
|
ParitySetClient::new(client, miner, updater, &(net.clone() as Arc<ManageNetwork>), TestFetch::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -57,8 +56,8 @@ fn rpc_parity_execute_upgrade() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_executeUpgrade", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_executeUpgrade", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
@ -75,8 +74,8 @@ fn rpc_parity_upgrade_ready() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_upgradeReady", "params": [], "id": 1}"#;
|
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}"#;
|
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}"#;
|
||||||
@ -95,8 +94,9 @@ fn rpc_parity_set_min_gas_price() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
let mut io = IoHandler::new();
|
||||||
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
@ -111,8 +111,9 @@ fn rpc_parity_set_gas_floor_target() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
let mut io = IoHandler::new();
|
||||||
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
@ -127,8 +128,9 @@ fn rpc_parity_set_extra_data() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
let mut io = IoHandler::new();
|
||||||
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
@ -143,8 +145,8 @@ fn rpc_parity_set_author() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
@ -159,8 +161,8 @@ fn rpc_parity_set_engine_signer() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
@ -177,8 +179,8 @@ fn rpc_parity_set_transactions_limit() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
@ -193,8 +195,8 @@ fn rpc_parity_set_hash_content() {
|
|||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let updater = updater_service();
|
let updater = updater_service();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate());
|
io.extend_with(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 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}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use util::{U256, Uint, Address};
|
use util::{U256, Uint, Address};
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use v1::{PersonalClient, Personal};
|
use v1::{PersonalClient, Personal};
|
||||||
@ -52,8 +52,8 @@ fn setup() -> PersonalTester {
|
|||||||
let miner = miner_service();
|
let miner = miner_service();
|
||||||
let personal = PersonalClient::new(&accounts, &client, &miner, false);
|
let personal = PersonalClient::new(&accounts, &client, &miner, false);
|
||||||
|
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::default();
|
||||||
io.add_delegate(personal.to_delegate());
|
io.extend_with(personal.to_delegate());
|
||||||
|
|
||||||
let tester = PersonalTester {
|
let tester = PersonalTester {
|
||||||
accounts: accounts,
|
accounts: accounts,
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{Rpc, RpcClient};
|
use v1::{Rpc, RpcClient};
|
||||||
|
|
||||||
|
|
||||||
@ -30,8 +30,8 @@ fn rpc_client() -> RpcClient {
|
|||||||
#[test]
|
#[test]
|
||||||
fn modules() {
|
fn modules() {
|
||||||
let rpc = rpc_client().to_delegate();
|
let rpc = rpc_client().to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(rpc);
|
io.extend_with(rpc);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "modules", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "modules", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"rpc":"1.0","web3":"1.0"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":{"rpc":"1.0","web3":"1.0"},"id":1}"#;
|
||||||
@ -42,8 +42,8 @@ fn modules() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn rpc_modules() {
|
fn rpc_modules() {
|
||||||
let rpc = rpc_client().to_delegate();
|
let rpc = rpc_client().to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(rpc);
|
io.extend_with(rpc);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "rpc_modules", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "rpc_modules", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"ethcore":"1.0","rpc":"1.0","web3":"1.0"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":{"ethcore":"1.0","rpc":"1.0","web3":"1.0"},"id":1}"#;
|
||||||
|
@ -24,7 +24,7 @@ use ethcore::transaction::{Transaction, Action};
|
|||||||
use rlp::encode;
|
use rlp::encode;
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{SignerClient, Signer};
|
use v1::{SignerClient, Signer};
|
||||||
use v1::tests::helpers::TestMinerService;
|
use v1::tests::helpers::TestMinerService;
|
||||||
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
||||||
@ -58,8 +58,8 @@ fn signer_tester() -> SignerTester {
|
|||||||
let client = blockchain_client();
|
let client = blockchain_client();
|
||||||
let miner = miner_service();
|
let miner = miner_service();
|
||||||
|
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::default();
|
||||||
io.add_delegate(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate());
|
io.extend_with(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate());
|
||||||
|
|
||||||
SignerTester {
|
SignerTester {
|
||||||
signer: signer,
|
signer: signer,
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{mpsc, Arc};
|
use std::sync::Arc;
|
||||||
use rlp;
|
use rlp;
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, Success, GenericIoHandler};
|
use jsonrpc_core::{IoHandler, Success};
|
||||||
use v1::impls::SigningQueueClient;
|
use v1::impls::SigningQueueClient;
|
||||||
use v1::traits::{EthSigning, ParitySigning, Parity};
|
use v1::traits::{EthSigning, ParitySigning, Parity};
|
||||||
use v1::helpers::{SignerService, SigningQueue};
|
use v1::helpers::{SignerService, SigningQueue};
|
||||||
@ -31,6 +31,7 @@ use ethcore::account_provider::AccountProvider;
|
|||||||
use ethcore::client::TestBlockChainClient;
|
use ethcore::client::TestBlockChainClient;
|
||||||
use ethcore::transaction::{Transaction, Action};
|
use ethcore::transaction::{Transaction, Action};
|
||||||
use ethstore::ethkey::{Generator, Random};
|
use ethstore::ethkey::{Generator, Random};
|
||||||
|
use futures::Future;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
struct SigningTester {
|
struct SigningTester {
|
||||||
@ -47,11 +48,11 @@ impl Default for SigningTester {
|
|||||||
let client = Arc::new(TestBlockChainClient::default());
|
let client = Arc::new(TestBlockChainClient::default());
|
||||||
let miner = Arc::new(TestMinerService::default());
|
let miner = Arc::new(TestMinerService::default());
|
||||||
let accounts = Arc::new(AccountProvider::transient_provider());
|
let accounts = Arc::new(AccountProvider::transient_provider());
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::default();
|
||||||
let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
|
let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
|
||||||
io.add_delegate(EthSigning::to_delegate(rpc));
|
io.extend_with(EthSigning::to_delegate(rpc));
|
||||||
let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
|
let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
|
||||||
io.add_delegate(ParitySigning::to_delegate(rpc));
|
io.extend_with(ParitySigning::to_delegate(rpc));
|
||||||
|
|
||||||
SigningTester {
|
SigningTester {
|
||||||
signer: signer,
|
signer: signer,
|
||||||
@ -87,15 +88,12 @@ fn should_add_sign_to_queue() {
|
|||||||
let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let (tx, rx) = mpsc::channel();
|
let promise = tester.io.handle_request(&request);
|
||||||
tester.io.handle_request(&request, move |response| {
|
|
||||||
tx.send(response).unwrap();
|
|
||||||
});
|
|
||||||
assert_eq!(tester.signer.requests().len(), 1);
|
assert_eq!(tester.signer.requests().len(), 1);
|
||||||
// respond
|
// respond
|
||||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Signature(0.into())));
|
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Signature(0.into())));
|
||||||
|
|
||||||
let res = rx.try_recv().unwrap();
|
let res = promise.wait().unwrap();
|
||||||
assert_eq!(res, Some(response.to_owned()));
|
assert_eq!(res, Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,15 +228,12 @@ fn should_add_transaction_to_queue() {
|
|||||||
let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let (tx, rx) = mpsc::channel();
|
let promise = tester.io.handle_request(&request);
|
||||||
tester.io.handle_request(&request, move |response| {
|
|
||||||
tx.send(response).unwrap();
|
|
||||||
});
|
|
||||||
assert_eq!(tester.signer.requests().len(), 1);
|
assert_eq!(tester.signer.requests().len(), 1);
|
||||||
// respond
|
// respond
|
||||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SendTransaction(0.into())));
|
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SendTransaction(0.into())));
|
||||||
|
|
||||||
let res = rx.try_recv().unwrap();
|
let res = promise.wait().unwrap();
|
||||||
assert_eq!(res, Some(response.to_owned()));
|
assert_eq!(res, Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,16 +294,13 @@ fn should_add_sign_transaction_to_the_queue() {
|
|||||||
r#"}},"id":1}"#;
|
r#"}},"id":1}"#;
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let (tx, rx) = mpsc::channel();
|
|
||||||
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
|
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
|
||||||
tester.io.handle_request(&request, move |response| {
|
let promise = tester.io.handle_request(&request);
|
||||||
tx.send(response).unwrap();
|
|
||||||
});
|
|
||||||
assert_eq!(tester.signer.requests().len(), 1);
|
assert_eq!(tester.signer.requests().len(), 1);
|
||||||
// respond
|
// respond
|
||||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into())));
|
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into())));
|
||||||
|
|
||||||
let res = rx.try_recv().unwrap();
|
let res = promise.wait().unwrap();
|
||||||
assert_eq!(res, Some(response.to_owned()));
|
assert_eq!(res, Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,9 +344,9 @@ fn should_dispatch_transaction_if_account_is_unlock() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_decrypt_message_if_account_is_unlocked() {
|
fn should_decrypt_message_if_account_is_unlocked() {
|
||||||
// given
|
// given
|
||||||
let tester = eth_signing();
|
let mut tester = eth_signing();
|
||||||
let parity = parity::Dependencies::new();
|
let parity = parity::Dependencies::new();
|
||||||
tester.io.add_delegate(parity.client(None).to_delegate());
|
tester.io.extend_with(parity.client(None).to_delegate());
|
||||||
let (address, public) = tester.accounts.new_account_and_public("test").unwrap();
|
let (address, public) = tester.accounts.new_account_and_public("test").unwrap();
|
||||||
tester.accounts.unlock_account_permanently(address, "test".into()).unwrap();
|
tester.accounts.unlock_account_permanently(address, "test".into()).unwrap();
|
||||||
|
|
||||||
@ -400,14 +392,11 @@ fn should_add_decryption_to_the_queue() {
|
|||||||
let response = r#"{"jsonrpc":"2.0","result":"0x0102","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0x0102","id":1}"#;
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let (tx, rx) = mpsc::channel();
|
let promise = tester.io.handle_request(&request);
|
||||||
tester.io.handle_request(&request, move |response| {
|
|
||||||
tx.send(response).unwrap();
|
|
||||||
});
|
|
||||||
assert_eq!(tester.signer.requests().len(), 1);
|
assert_eq!(tester.signer.requests().len(), 1);
|
||||||
// respond
|
// respond
|
||||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Decrypt(vec![0x1, 0x2].into())));
|
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Decrypt(vec![0x1, 0x2].into())));
|
||||||
|
|
||||||
let res = rx.try_recv().unwrap();
|
let res = promise.wait().unwrap();
|
||||||
assert_eq!(res, Some(response.to_owned()));
|
assert_eq!(res, Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ use ethcore::trace::trace::{Action, Res, Call};
|
|||||||
use ethcore::trace::LocalizedTrace;
|
use ethcore::trace::LocalizedTrace;
|
||||||
use ethcore::client::{TestBlockChainClient};
|
use ethcore::client::{TestBlockChainClient};
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::tests::helpers::{TestMinerService};
|
use v1::tests::helpers::{TestMinerService};
|
||||||
use v1::{Traces, TracesClient};
|
use v1::{Traces, TracesClient};
|
||||||
|
|
||||||
@ -51,6 +51,7 @@ fn io() -> Tester {
|
|||||||
block_hash: 10.into(),
|
block_hash: 10.into(),
|
||||||
}]);
|
}]);
|
||||||
*client.execution_result.write() = Some(Ok(Executed {
|
*client.execution_result.write() = Some(Ok(Executed {
|
||||||
|
exception: None,
|
||||||
gas: 20_000.into(),
|
gas: 20_000.into(),
|
||||||
gas_used: 10_000.into(),
|
gas_used: 10_000.into(),
|
||||||
refunded: 0.into(),
|
refunded: 0.into(),
|
||||||
@ -64,8 +65,8 @@ fn io() -> Tester {
|
|||||||
}));
|
}));
|
||||||
let miner = Arc::new(TestMinerService::default());
|
let miner = Arc::new(TestMinerService::default());
|
||||||
let traces = TracesClient::new(&client, &miner);
|
let traces = TracesClient::new(&client, &miner);
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(traces.to_delegate());
|
io.extend_with(traces.to_delegate());
|
||||||
|
|
||||||
Tester {
|
Tester {
|
||||||
_client: client,
|
_client: client,
|
||||||
|
@ -14,15 +14,15 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
use jsonrpc_core::IoHandler;
|
||||||
use util::version;
|
use util::version;
|
||||||
use v1::{Web3, Web3Client};
|
use v1::{Web3, Web3Client};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_web3_version() {
|
fn rpc_web3_version() {
|
||||||
let web3 = Web3Client::new().to_delegate();
|
let web3 = Web3Client::new().to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(web3);
|
io.extend_with(web3);
|
||||||
|
|
||||||
let v = version().to_owned().replace("Parity/", "Parity//");
|
let v = version().to_owned().replace("Parity/", "Parity//");
|
||||||
|
|
||||||
@ -35,8 +35,8 @@ fn rpc_web3_version() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn rpc_web3_sha3() {
|
fn rpc_web3_sha3() {
|
||||||
let web3 = Web3Client::new().to_delegate();
|
let web3 = Web3Client::new().to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(web3);
|
io.extend_with(web3);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x00"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x00"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a","id":1}"#;
|
||||||
@ -47,8 +47,8 @@ fn rpc_web3_sha3() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn rpc_web3_sha3_wiki() {
|
fn rpc_web3_sha3_wiki() {
|
||||||
let web3 = Web3Client::new().to_delegate();
|
let web3 = Web3Client::new().to_delegate();
|
||||||
let io = IoHandler::new();
|
let mut io = IoHandler::new();
|
||||||
io.add_delegate(web3);
|
io.extend_with(web3);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x68656c6c6f20776f726c64"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x68656c6c6f20776f726c64"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad","id":1}"#;
|
||||||
|
@ -16,16 +16,19 @@
|
|||||||
|
|
||||||
//! Eth rpc interface.
|
//! Eth rpc interface.
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
use jsonrpc_macros::Trailing;
|
||||||
|
|
||||||
use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index, DappId};
|
use futures::BoxFuture;
|
||||||
|
|
||||||
|
use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index};
|
||||||
use v1::types::{Log, Receipt, SyncStatus, Transaction, Work};
|
use v1::types::{Log, Receipt, SyncStatus, Transaction, Work};
|
||||||
use v1::types::{H64, H160, H256, U256};
|
use v1::types::{H64, H160, H256, U256};
|
||||||
|
|
||||||
use jsonrpc_macros::Trailing;
|
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Eth rpc interface.
|
/// Eth rpc interface.
|
||||||
pub trait Eth {
|
pub trait Eth {
|
||||||
|
type Metadata;
|
||||||
|
|
||||||
/// Returns protocol version encoded as a string (quotes are necessary).
|
/// Returns protocol version encoded as a string (quotes are necessary).
|
||||||
#[rpc(name = "eth_protocolVersion")]
|
#[rpc(name = "eth_protocolVersion")]
|
||||||
fn protocol_version(&self) -> Result<String, Error>;
|
fn protocol_version(&self) -> Result<String, Error>;
|
||||||
@ -51,8 +54,8 @@ build_rpc_trait! {
|
|||||||
fn gas_price(&self) -> Result<U256, Error>;
|
fn gas_price(&self) -> Result<U256, Error>;
|
||||||
|
|
||||||
/// Returns accounts list.
|
/// Returns accounts list.
|
||||||
#[rpc(name = "eth_accounts")]
|
#[rpc(meta, name = "eth_accounts")]
|
||||||
fn accounts(&self, Trailing<DappId>) -> Result<Vec<H160>, Error>;
|
fn accounts(&self, Self::Metadata) -> BoxFuture<Vec<H160>, Error>;
|
||||||
|
|
||||||
/// Returns highest block number.
|
/// Returns highest block number.
|
||||||
#[rpc(name = "eth_blockNumber")]
|
#[rpc(name = "eth_blockNumber")]
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
//! Eth rpc interface.
|
//! Eth rpc interface.
|
||||||
|
|
||||||
use jsonrpc_macros::Ready;
|
use jsonrpc_core::Error;
|
||||||
|
use futures::BoxFuture;
|
||||||
|
|
||||||
use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction};
|
use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction};
|
||||||
|
|
||||||
@ -25,18 +26,18 @@ build_rpc_trait! {
|
|||||||
pub trait EthSigning {
|
pub trait EthSigning {
|
||||||
/// Signs the hash of data with given address signature.
|
/// Signs the hash of data with given address signature.
|
||||||
#[rpc(async, name = "eth_sign")]
|
#[rpc(async, name = "eth_sign")]
|
||||||
fn sign(&self, Ready<H520>, H160, Bytes);
|
fn sign(&self, H160, Bytes) -> BoxFuture<H520, Error>;
|
||||||
|
|
||||||
/// Sends transaction; will block waiting for signer to return the
|
/// Sends transaction; will block waiting for signer to return the
|
||||||
/// transaction hash.
|
/// transaction hash.
|
||||||
/// If Signer is disable it will require the account to be unlocked.
|
/// If Signer is disable it will require the account to be unlocked.
|
||||||
#[rpc(async, name = "eth_sendTransaction")]
|
#[rpc(async, name = "eth_sendTransaction")]
|
||||||
fn send_transaction(&self, Ready<H256>, TransactionRequest);
|
fn send_transaction(&self, TransactionRequest) -> BoxFuture<H256, Error>;
|
||||||
|
|
||||||
/// Signs transactions without dispatching it to the network.
|
/// Signs transactions without dispatching it to the network.
|
||||||
/// Returns signed transaction RLP representation and the transaction itself.
|
/// Returns signed transaction RLP representation and the transaction itself.
|
||||||
/// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`.
|
/// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`.
|
||||||
#[rpc(async, name = "eth_signTransaction")]
|
#[rpc(async, name = "eth_signTransaction")]
|
||||||
fn sign_transaction(&self, Ready<RichRawTransaction>, TransactionRequest);
|
fn sign_transaction(&self, TransactionRequest) -> BoxFuture<RichRawTransaction, Error>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Parity-specific rpc interface for operations altering the settings.
|
//! Parity-specific rpc interface for operations altering the settings.
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Ready;
|
use futures::BoxFuture;
|
||||||
|
|
||||||
use v1::types::{Bytes, H160, H256, U256, ReleaseInfo};
|
use v1::types::{Bytes, H160, H256, U256, ReleaseInfo};
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ build_rpc_trait! {
|
|||||||
|
|
||||||
/// Hash a file content under given URL.
|
/// Hash a file content under given URL.
|
||||||
#[rpc(async, name = "parity_hashContent")]
|
#[rpc(async, name = "parity_hashContent")]
|
||||||
fn hash_content(&self, Ready<H256>, String);
|
fn hash_content(&self, String) -> BoxFuture<H256, Error>;
|
||||||
|
|
||||||
/// Is there a release ready for install?
|
/// Is there a release ready for install?
|
||||||
#[rpc(name = "parity_upgradeReady")]
|
#[rpc(name = "parity_upgradeReady")]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user