Merge branch 'master' into lightsync

This commit is contained in:
Robert Habermeier 2016-12-19 13:15:37 +01:00
commit a48435ca60
53 changed files with 576 additions and 338 deletions

View File

@ -20,8 +20,8 @@ linux-stable:
- stable - stable
- triggers - triggers
script: script:
- curl --data "secret=$RELEASES_SECRET" http://icarus.parity.io/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF - curl --data "secret=$RELEASES_SECRET" http://icarus.parity.io:1337/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF
- cargo build -j $(nproc) --release $CARGOFLAGS - cargo build -j $(nproc) --release --features final $CARGOFLAGS
- strip target/release/parity - strip target/release/parity
- export SHA3=$(target/release/parity tools hash target/release/parity) - export SHA3=$(target/release/parity tools hash target/release/parity)
- md5sum target/release/parity > parity.md5 - md5sum target/release/parity > parity.md5
@ -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://icarus.parity.io/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://icarus.parity.io:1337/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu
tags: tags:
- rust - rust
- rust-stable - rust-stable
@ -96,7 +96,7 @@ linux-centos:
- export CXX="g++" - export CXX="g++"
- export CC="gcc" - export CC="gcc"
- export PLATFORM=x86_64-unknown-centos-gnu - export PLATFORM=x86_64-unknown-centos-gnu
- cargo build -j $(nproc) --release $CARGOFLAGS - cargo build -j $(nproc) --release --features final $CARGOFLAGS
- strip target/release/parity - strip target/release/parity
- md5sum target/release/parity > parity.md5 - md5sum target/release/parity > parity.md5
- export SHA3=$(target/release/parity tools hash target/release/parity) - export SHA3=$(target/release/parity tools hash target/release/parity)
@ -106,7 +106,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://icarus.parity.io/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
tags: tags:
- rust - rust
- rust-centos - rust-centos
@ -127,7 +127,7 @@ linux-i686:
- export HOST_CXX=g++ - export HOST_CXX=g++
- export COMMIT=$(git rev-parse HEAD) - export COMMIT=$(git rev-parse HEAD)
- export PLATFORM=i686-unknown-linux-gnu - export PLATFORM=i686-unknown-linux-gnu
- cargo build -j $(nproc) --target i686-unknown-linux-gnu --release $CARGOFLAGS - cargo build -j $(nproc) --target i686-unknown-linux-gnu --features final --release $CARGOFLAGS
- strip target/$PLATFORM/release/parity - strip target/$PLATFORM/release/parity
- md5sum target/$PLATFORM/release/parity > parity.md5 - md5sum target/$PLATFORM/release/parity > parity.md5
- export SHA3=$(target/$PLATFORM/release/parity tools hash target/$PLATFORM/release/parity) - export SHA3=$(target/$PLATFORM/release/parity tools hash target/$PLATFORM/release/parity)
@ -144,7 +144,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://icarus.parity.io/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
tags: tags:
- rust - rust
- rust-i686 - rust-i686
@ -171,7 +171,7 @@ linux-armv7:
- echo "[target.armv7-unknown-linux-gnueabihf]" >> .cargo/config - echo "[target.armv7-unknown-linux-gnueabihf]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build -j $(nproc) --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS - cargo build -j $(nproc) --target armv7-unknown-linux-gnueabihf --features final --release $CARGOFLAGS
- arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/parity - arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/parity
- md5sum target/armv7-unknown-linux-gnueabihf/release/parity > parity.md5 - md5sum target/armv7-unknown-linux-gnueabihf/release/parity > parity.md5
- sh scripts/deb-build.sh armhf - sh scripts/deb-build.sh armhf
@ -213,7 +213,7 @@ linux-arm:
- echo "[target.arm-unknown-linux-gnueabihf]" >> .cargo/config - echo "[target.arm-unknown-linux-gnueabihf]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build -j $(nproc) --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS - cargo build -j $(nproc) --target arm-unknown-linux-gnueabihf --features final --release $CARGOFLAGS
- arm-linux-gnueabihf-strip target/arm-unknown-linux-gnueabihf/release/parity - arm-linux-gnueabihf-strip target/arm-unknown-linux-gnueabihf/release/parity
- md5sum target/arm-unknown-linux-gnueabihf/release/parity > parity.md5 - md5sum target/arm-unknown-linux-gnueabihf/release/parity > parity.md5
- sh scripts/deb-build.sh armhf - sh scripts/deb-build.sh armhf
@ -255,7 +255,7 @@ linux-armv6:
- echo "[target.arm-unknown-linux-gnueabi]" >> .cargo/config - echo "[target.arm-unknown-linux-gnueabi]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabi-gcc\"" >> .cargo/config - echo "linker= \"arm-linux-gnueabi-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build -j $(nproc) --target arm-unknown-linux-gnueabi --release $CARGOFLAGS - cargo build -j $(nproc) --target arm-unknown-linux-gnueabi --features final --release $CARGOFLAGS
- arm-linux-gnueabi-strip target/arm-unknown-linux-gnueabi/release/parity - arm-linux-gnueabi-strip target/arm-unknown-linux-gnueabi/release/parity
- md5sum target/arm-unknown-linux-gnueabi/release/parity > parity.md5 - md5sum target/arm-unknown-linux-gnueabi/release/parity > parity.md5
- aws configure set aws_access_key_id $s3_key - aws configure set aws_access_key_id $s3_key
@ -290,7 +290,7 @@ linux-aarch64:
- echo "[target.aarch64-unknown-linux-gnu]" >> .cargo/config - echo "[target.aarch64-unknown-linux-gnu]" >> .cargo/config
- echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config - echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config
- cat .cargo/config - cat .cargo/config
- cargo build -j $(nproc) --target aarch64-unknown-linux-gnu --release $CARGOFLAGS - cargo build -j $(nproc) --target aarch64-unknown-linux-gnu --features final --release $CARGOFLAGS
- aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/parity - aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/parity
- md5sum target/aarch64-unknown-linux-gnu/release/parity > parity.md5 - md5sum target/aarch64-unknown-linux-gnu/release/parity > parity.md5
- sh scripts/deb-build.sh arm64 - sh scripts/deb-build.sh arm64
@ -323,8 +323,8 @@ darwin:
script: script:
- export COMMIT=$(git rev-parse HEAD) - export COMMIT=$(git rev-parse HEAD)
- export PLATFORM=x86_64-apple-darwin - export PLATFORM=x86_64-apple-darwin
- cargo build -j 8 --release #$CARGOFLAGS - cargo build -j 8 --features final --release #$CARGOFLAGS
- cargo build -j 8 --release -p ethstore #$CARGOFLAGS - cargo build -j 8 --features final --release -p ethstore #$CARGOFLAGS
- rm -rf parity.md5 - rm -rf parity.md5
- md5sum target/release/parity > parity.md5 - md5sum target/release/parity > parity.md5
- export SHA3=$(target/release/parity tools hash target/release/parity) - export SHA3=$(target/release/parity tools hash target/release/parity)
@ -340,7 +340,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://icarus.parity.io/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
tags: tags:
- osx - osx
artifacts: artifacts:
@ -364,11 +364,12 @@ windows:
- set RUST_BACKTRACE=1 - set RUST_BACKTRACE=1
- set RUSTFLAGS=%RUSTFLAGS% - set RUSTFLAGS=%RUSTFLAGS%
- rustup default stable-x86_64-pc-windows-msvc - rustup default stable-x86_64-pc-windows-msvc
- cargo build --release #%CARGOFLAGS% - cargo build --features final --release #%CARGOFLAGS%
- FOR /F "tokens=* USEBACKQ" %%i IN ('target\release\parity.exe tools hash target\release\parity.exe') DO set SHA3=%%i - signtool sign /f %keyfile% /p %certpass% target\release\parity.exe
- target\release\parity.exe tools hash target\release\parity.exe > parity.sha3
- set /P SHA3=<parity.sha3
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll - curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe - curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe
- signtool sign /f %keyfile% /p %certpass% target\release\parity.exe
- msbuild windows\ptray\ptray.vcxproj /p:Platform=x64 /p:Configuration=Release - msbuild windows\ptray\ptray.vcxproj /p:Platform=x64 /p:Configuration=Release
- signtool sign /f %keyfile% /p %certpass% windows\ptray\x64\release\ptray.exe - signtool sign /f %keyfile% /p %certpass% windows\ptray\x64\release\ptray.exe
- cd nsis - cd nsis
@ -400,7 +401,7 @@ windows:
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5 - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip
- aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5 - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5
- curl --data "commit=$CI_BUILD_REF&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://icarus.parity.io/push-build/$CI_BUILD_REF_NAME/%PLATFORM% - curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://icarus.parity.io:1337/push-build/%CI_BUILD_REF_NAME%/%PLATFORM%
tags: tags:
- rust-windows - rust-windows
artifacts: artifacts:
@ -425,7 +426,7 @@ test-darwin:
test-windows: test-windows:
stage: test stage: test
only: only:
# - triggers - triggers
before_script: before_script:
- git submodule update --init --recursive - git submodule update --init --recursive
script: script:

28
Cargo.lock generated
View File

@ -885,18 +885,6 @@ name = "itoa"
version = "0.1.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jsonrpc-core"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "jsonrpc-core" name = "jsonrpc-core"
version = "4.0.0" version = "4.0.0"
@ -1349,7 +1337,7 @@ dependencies = [
"ethcore-signer 1.5.0", "ethcore-signer 1.5.0",
"ethcore-util 1.5.0", "ethcore-util 1.5.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 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 4.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)",
@ -1398,17 +1386,7 @@ dependencies = [
"ipc-common-types 1.5.0", "ipc-common-types 1.5.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.5.0", "parity-hash-fetch 1.5.0",
] "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "parking_lot"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2236,7 +2214,6 @@ 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 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5094610b07f28f3edaf3947b732dadb31dbba4941d4d0c1c7a8350208f4414"
"checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" "checksum jsonrpc-core 4.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 6.1.1 (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 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
@ -2284,7 +2261,6 @@ dependencies = [
"checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" "checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7"
"checksum parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98378dec0a185da2b7180308752f0bad73aaa949c3e0a3b0528d0e067945f7ab" "checksum parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98378dec0a185da2b7180308752f0bad73aaa949c3e0a3b0528d0e067945f7ab"
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "<none>" "checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "<none>"
"checksum parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "968f685642555d2f7e202c48b8b11de80569e9bfea817f7f12d7c61aac62d4e6"
"checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621" "checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621"
"checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" "checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068"
"checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026" "checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026"

View File

@ -61,7 +61,6 @@ daemonize = "0.2"
[features] [features]
default = ["ui-precompiled"] default = ["ui-precompiled"]
ui = [ ui = [
"dapps", "dapps",
"ethcore-dapps/ui", "ethcore-dapps/ui",
@ -72,7 +71,6 @@ ui-precompiled = [
"ethcore-signer/ui-precompiled", "ethcore-signer/ui-precompiled",
"ethcore-dapps/ui-precompiled", "ethcore-dapps/ui-precompiled",
] ]
dapps = ["ethcore-dapps"] dapps = ["ethcore-dapps"]
ipc = ["ethcore/ipc", "ethsync/ipc"] ipc = ["ethcore/ipc", "ethsync/ipc"]
jit = ["ethcore/jit"] jit = ["ethcore/jit"]
@ -85,6 +83,7 @@ ethstore-cli = ["ethcore/ethstore-cli"]
evm-debug = ["ethcore/evm-debug"] evm-debug = ["ethcore/evm-debug"]
evm-debug-tests = ["ethcore/evm-debug-tests"] evm-debug-tests = ["ethcore/evm-debug-tests"]
slow-blocks = ["ethcore/slow-blocks"] slow-blocks = ["ethcore/slow-blocks"]
final = ["ethcore-util/final"]
[[bin]] [[bin]]
path = "parity/main.rs" path = "parity/main.rs"

View File

@ -19,10 +19,10 @@ branches:
install: install:
- git submodule update --init --recursive - git submodule update --init --recursive
- ps: Install-Product node 6 - ps: Install-Product node 6
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.12.0-x86_64-pc-windows-msvc.exe" - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.13.0-x86_64-pc-windows-msvc.exe"
- ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll
- ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe
- rust-1.12.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - rust-1.13.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin
- rustc -V - rustc -V
- cargo -V - cargo -V

View File

@ -21,7 +21,7 @@ use ethcore::block_status::BlockStatus;
use ethcore::ids::BlockId; use ethcore::ids::BlockId;
use ethcore::header::Header; use ethcore::header::Header;
use ethcore::verification::queue::{self, HeaderQueue}; use ethcore::verification::queue::{self, HeaderQueue};
use ethcore::transaction::SignedTransaction; use ethcore::transaction::PendingTransaction;
use ethcore::blockchain_info::BlockChainInfo; use ethcore::blockchain_info::BlockChainInfo;
use ethcore::spec::Spec; use ethcore::spec::Spec;
use ethcore::service::ClientIoMessage; use ethcore::service::ClientIoMessage;
@ -75,7 +75,7 @@ pub trait LightChainClient: Send + Sync {
pub struct Client { pub struct Client {
queue: HeaderQueue, queue: HeaderQueue,
chain: HeaderChain, chain: HeaderChain,
tx_pool: Mutex<H256FastMap<SignedTransaction>>, tx_pool: Mutex<H256FastMap<PendingTransaction>>,
import_lock: Mutex<()>, import_lock: Mutex<()>,
} }
@ -96,13 +96,18 @@ impl Client {
} }
/// Import a local transaction. /// Import a local transaction.
pub fn import_own_transaction(&self, tx: SignedTransaction) { pub fn import_own_transaction(&self, tx: PendingTransaction) {
self.tx_pool.lock().insert(tx.hash(), tx); self.tx_pool.lock().insert(tx.transaction.hash(), tx);
} }
/// Fetch a vector of all pending transactions. /// Fetch a vector of all pending transactions.
pub fn pending_transactions(&self) -> Vec<SignedTransaction> { pub fn ready_transactions(&self) -> Vec<PendingTransaction> {
self.tx_pool.lock().values().cloned().collect() let best_num = self.chain.best_block().number;
self.tx_pool.lock()
.values()
.filter(|t| t.min_block.as_ref().map_or(true, |x| x <= &best_num))
.cloned()
.collect()
} }
/// Inquire about the status of a given header. /// Inquire about the status of a given header.
@ -234,7 +239,7 @@ impl Provider for Client {
Vec::new() Vec::new()
} }
fn pending_transactions(&self) -> Vec<SignedTransaction> { fn ready_transactions(&self) -> Vec<PendingTransaction> {
Client::pending_transactions(self) Client::ready_transactions(self)
} }
} }

View File

@ -20,7 +20,7 @@
use ethcore::blockchain_info::BlockChainInfo; use ethcore::blockchain_info::BlockChainInfo;
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient};
use ethcore::ids::BlockId; use ethcore::ids::BlockId;
use ethcore::transaction::SignedTransaction; use ethcore::transaction::PendingTransaction;
use network::{PeerId, NodeId}; use network::{PeerId, NodeId};
use net::buffer_flow::FlowParams; use net::buffer_flow::FlowParams;
@ -169,8 +169,8 @@ impl Provider for TestProvider {
req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect()
} }
fn pending_transactions(&self) -> Vec<SignedTransaction> { fn ready_transactions(&self) -> Vec<PendingTransaction> {
self.0.client.pending_transactions() self.0.client.ready_transactions()
} }
} }

View File

@ -19,7 +19,7 @@
use ethcore::blockchain_info::BlockChainInfo; use ethcore::blockchain_info::BlockChainInfo;
use ethcore::client::{BlockChainClient, ProvingBlockChainClient}; use ethcore::client::{BlockChainClient, ProvingBlockChainClient};
use ethcore::transaction::SignedTransaction; use ethcore::transaction::PendingTransaction;
use ethcore::ids::BlockId; use ethcore::ids::BlockId;
use util::{Bytes, H256}; use util::{Bytes, H256};
@ -79,7 +79,7 @@ pub trait Provider: Send + Sync {
fn header_proofs(&self, req: request::HeaderProofs) -> Vec<Bytes>; fn header_proofs(&self, req: request::HeaderProofs) -> Vec<Bytes>;
/// Provide pending transactions. /// Provide pending transactions.
fn pending_transactions(&self) -> Vec<SignedTransaction>; fn ready_transactions(&self) -> Vec<PendingTransaction>;
} }
// Implementation of a light client data provider for a client. // Implementation of a light client data provider for a client.
@ -178,7 +178,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect()
} }
fn pending_transactions(&self) -> Vec<SignedTransaction> { fn ready_transactions(&self) -> Vec<PendingTransaction> {
BlockChainClient::pending_transactions(self) BlockChainClient::ready_transactions(self)
} }
} }

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

View File

@ -44,7 +44,7 @@ use env_info::LastHashes;
use verification; use verification;
use verification::{PreverifiedBlock, Verifier}; use verification::{PreverifiedBlock, Verifier};
use block::*; use block::*;
use transaction::{LocalizedTransaction, SignedTransaction, Transaction, Action}; use transaction::{LocalizedTransaction, SignedTransaction, Transaction, PendingTransaction, Action};
use blockchain::extras::TransactionAddress; use blockchain::extras::TransactionAddress;
use types::filter::Filter; use types::filter::Filter;
use types::mode::Mode as IpcMode; use types::mode::Mode as IpcMode;
@ -1334,8 +1334,8 @@ impl BlockChainClient for Client {
} }
} }
fn pending_transactions(&self) -> Vec<SignedTransaction> { fn ready_transactions(&self) -> Vec<PendingTransaction> {
self.miner.pending_transactions(self.chain.read().best_block_number()) self.miner.ready_transactions(self.chain.read().best_block_number())
} }
fn queue_consensus_message(&self, message: Bytes) { fn queue_consensus_message(&self, message: Bytes) {

View File

@ -21,7 +21,7 @@ use util::*;
use rlp::*; use rlp::*;
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use devtools::*; use devtools::*;
use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; use transaction::{Transaction, LocalizedTransaction, SignedTransaction, PendingTransaction, Action};
use blockchain::TreeRoute; use blockchain::TreeRoute;
use client::{ use client::{
BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId, BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId,
@ -688,8 +688,8 @@ impl BlockChainClient for TestBlockChainClient {
fn broadcast_consensus_message(&self, _message: Bytes) {} fn broadcast_consensus_message(&self, _message: Bytes) {}
fn pending_transactions(&self) -> Vec<SignedTransaction> { fn ready_transactions(&self) -> Vec<PendingTransaction> {
self.miner.pending_transactions(self.chain_info().best_block_number) self.miner.ready_transactions(self.chain_info().best_block_number)
} }
fn signing_network_id(&self) -> Option<u64> { None } fn signing_network_id(&self) -> Option<u64> { None }

View File

@ -21,7 +21,7 @@ use blockchain::TreeRoute;
use verification::queue::QueueInfo as BlockQueueInfo; use verification::queue::QueueInfo as BlockQueueInfo;
use block::{OpenBlock, SealedBlock}; use block::{OpenBlock, SealedBlock};
use header::{BlockNumber}; use header::{BlockNumber};
use transaction::{LocalizedTransaction, SignedTransaction}; use transaction::{LocalizedTransaction, SignedTransaction, PendingTransaction};
use log_entry::LocalizedLogEntry; use log_entry::LocalizedLogEntry;
use filter::Filter; use filter::Filter;
use views::{BlockView}; use views::{BlockView};
@ -211,8 +211,8 @@ pub trait BlockChainClient : Sync + Send {
/// Used by PoA to communicate with peers. /// Used by PoA to communicate with peers.
fn broadcast_consensus_message(&self, message: Bytes); fn broadcast_consensus_message(&self, message: Bytes);
/// list all transactions /// List all transactions that are allowed into the next block.
fn pending_transactions(&self) -> Vec<SignedTransaction>; fn ready_transactions(&self) -> Vec<PendingTransaction>;
/// Sorted list of transaction gas prices from at least last sample_size blocks. /// Sorted list of transaction gas prices from at least last sample_size blocks.
fn gas_price_corpus(&self, sample_size: usize) -> Vec<U256> { fn gas_price_corpus(&self, sample_size: usize) -> Vec<U256> {

View File

@ -178,15 +178,15 @@ impl Engine for Ethash {
let gas_limit = { let gas_limit = {
let gas_limit = parent.gas_limit().clone(); let gas_limit = parent.gas_limit().clone();
let bound_divisor = self.ethash_params.gas_limit_bound_divisor; let bound_divisor = self.ethash_params.gas_limit_bound_divisor;
let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into();
let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into();
if gas_limit < gas_floor_target { if gas_limit < gas_floor_target {
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) min(gas_floor_target, upper_limit)
} else if gas_limit > gas_ceil_target { } else if gas_limit > gas_ceil_target {
max(gas_ceil_target, gas_limit - gas_limit / bound_divisor + 1.into()) max(gas_ceil_target, lower_limit)
} else { } else {
min(gas_ceil_target, max(gas_floor_target, min(min(gas_ceil_target, upper_limit),
max(gas_floor_target, lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor))
gas_limit - gas_limit / bound_divisor + 1.into() +
(header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor))
} }
}; };
header.set_difficulty(difficulty); header.set_difficulty(difficulty);

View File

@ -115,7 +115,7 @@ impl BanningTransactionQueue {
} }
} }
} }
self.queue.add(transaction, TransactionOrigin::External, account_details, gas_estimator) self.queue.add(transaction, TransactionOrigin::External, None, account_details, gas_estimator)
} }
/// Ban transaction with given hash. /// Ban transaction with given hash.
@ -263,7 +263,7 @@ mod tests {
let mut txq = queue(); let mut txq = queue();
// when // when
txq.queue().add(tx, TransactionOrigin::External, &default_account_details, &gas_required).unwrap(); txq.queue().add(tx, TransactionOrigin::External, None, &default_account_details, &gas_required).unwrap();
// then // then
// should also deref to queue // should also deref to queue

View File

@ -28,7 +28,7 @@ use client::TransactionImportResult;
use executive::contract_address; use executive::contract_address;
use block::{ClosedBlock, IsBlock, Block}; use block::{ClosedBlock, IsBlock, Block};
use error::*; use error::*;
use transaction::{Action, SignedTransaction}; use transaction::{Action, SignedTransaction, PendingTransaction};
use receipt::{Receipt, RichReceipt}; use receipt::{Receipt, RichReceipt};
use spec::Spec; use spec::Spec;
use engines::{Engine, Seal}; use engines::{Engine, Seal};
@ -320,11 +320,12 @@ impl Miner {
} }
let _timer = PerfTimer::new("prepare_block"); let _timer = PerfTimer::new("prepare_block");
let chain_info = chain.chain_info();
let (transactions, mut open_block, original_work_hash) = { let (transactions, mut open_block, original_work_hash) = {
let transactions = {self.transaction_queue.lock().top_transactions()}; let transactions = {self.transaction_queue.lock().top_transactions_at(chain_info.best_block_number)};
let mut sealing_work = self.sealing_work.lock(); let mut sealing_work = self.sealing_work.lock();
let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash()); let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash());
let best_hash = chain.best_block_header().sha3(); let best_hash = chain_info.best_block_hash;
/* /*
// check to see if last ClosedBlock in would_seals is actually same parent block. // check to see if last ClosedBlock in would_seals is actually same parent block.
// if so // if so
@ -577,8 +578,14 @@ impl Miner {
prepare_new prepare_new
} }
fn add_transactions_to_queue(&self, chain: &MiningBlockChainClient, transactions: Vec<SignedTransaction>, default_origin: TransactionOrigin, transaction_queue: &mut BanningTransactionQueue) -> fn add_transactions_to_queue(
Vec<Result<TransactionImportResult, Error>> { &self,
chain: &MiningBlockChainClient,
transactions: Vec<SignedTransaction>,
default_origin: TransactionOrigin,
min_block: Option<BlockNumber>,
transaction_queue: &mut BanningTransactionQueue)
-> Vec<Result<TransactionImportResult, Error>> {
let fetch_account = |a: &Address| AccountDetails { let fetch_account = |a: &Address| AccountDetails {
nonce: chain.latest_nonce(a), nonce: chain.latest_nonce(a),
@ -613,7 +620,7 @@ impl Miner {
match origin { match origin {
TransactionOrigin::Local | TransactionOrigin::RetractedBlock => { TransactionOrigin::Local | TransactionOrigin::RetractedBlock => {
transaction_queue.add(tx, origin, &fetch_account, &gas_required) transaction_queue.add(tx, origin, min_block, &fetch_account, &gas_required)
}, },
TransactionOrigin::External => { TransactionOrigin::External => {
transaction_queue.add_with_banlist(tx, &fetch_account, &gas_required) transaction_queue.add_with_banlist(tx, &fetch_account, &gas_required)
@ -839,7 +846,7 @@ impl MinerService for Miner {
let results = { let results = {
let mut transaction_queue = self.transaction_queue.lock(); let mut transaction_queue = self.transaction_queue.lock();
self.add_transactions_to_queue( self.add_transactions_to_queue(
chain, transactions, TransactionOrigin::External, &mut transaction_queue chain, transactions, TransactionOrigin::External, None, &mut transaction_queue
) )
}; };
@ -857,17 +864,17 @@ impl MinerService for Miner {
fn import_own_transaction( fn import_own_transaction(
&self, &self,
chain: &MiningBlockChainClient, chain: &MiningBlockChainClient,
transaction: SignedTransaction, pending: PendingTransaction,
) -> Result<TransactionImportResult, Error> { ) -> Result<TransactionImportResult, Error> {
let hash = transaction.hash(); let hash = pending.transaction.hash();
trace!(target: "own_tx", "Importing transaction: {:?}", transaction); trace!(target: "own_tx", "Importing transaction: {:?}", pending);
let imported = { let imported = {
// Be sure to release the lock before we call prepare_work_sealing // Be sure to release the lock before we call prepare_work_sealing
let mut transaction_queue = self.transaction_queue.lock(); let mut transaction_queue = self.transaction_queue.lock();
let import = self.add_transactions_to_queue( let import = self.add_transactions_to_queue(
chain, vec![transaction], TransactionOrigin::Local, &mut transaction_queue chain, vec![pending.transaction], TransactionOrigin::Local, pending.min_block, &mut transaction_queue
).pop().expect("one result returned per added transaction; one added => one result; qed"); ).pop().expect("one result returned per added transaction; one added => one result; qed");
match import { match import {
@ -902,9 +909,9 @@ impl MinerService for Miner {
imported imported
} }
fn all_transactions(&self) -> Vec<SignedTransaction> { fn pending_transactions(&self) -> Vec<PendingTransaction> {
let queue = self.transaction_queue.lock(); let queue = self.transaction_queue.lock();
queue.top_transactions() queue.pending_transactions(BlockNumber::max_value())
} }
fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus> { fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus> {
@ -915,22 +922,26 @@ impl MinerService for Miner {
.collect() .collect()
} }
fn pending_transactions(&self, best_block: BlockNumber) -> Vec<SignedTransaction> { fn future_transactions(&self) -> Vec<PendingTransaction> {
self.transaction_queue.lock().future_transactions()
}
fn ready_transactions(&self, best_block: BlockNumber) -> Vec<PendingTransaction> {
let queue = self.transaction_queue.lock(); let queue = self.transaction_queue.lock();
match self.options.pending_set { match self.options.pending_set {
PendingSet::AlwaysQueue => queue.top_transactions(), PendingSet::AlwaysQueue => queue.pending_transactions(best_block),
PendingSet::SealingOrElseQueue => { PendingSet::SealingOrElseQueue => {
self.from_pending_block( self.from_pending_block(
best_block, best_block,
|| queue.top_transactions(), || queue.pending_transactions(best_block),
|sealing| sealing.transactions().to_owned() |sealing| sealing.transactions().iter().map(|t| t.clone().into()).collect()
) )
}, },
PendingSet::AlwaysSealing => { PendingSet::AlwaysSealing => {
self.from_pending_block( self.from_pending_block(
best_block, best_block,
|| vec![], || vec![],
|sealing| sealing.transactions().to_owned() |sealing| sealing.transactions().iter().map(|t| t.clone().into()).collect()
) )
}, },
} }
@ -1126,7 +1137,7 @@ impl MinerService for Miner {
}).for_each(|txs| { }).for_each(|txs| {
let mut transaction_queue = self.transaction_queue.lock(); let mut transaction_queue = self.transaction_queue.lock();
let _ = self.add_transactions_to_queue( let _ = self.add_transactions_to_queue(
chain, txs, TransactionOrigin::RetractedBlock, &mut transaction_queue chain, txs, TransactionOrigin::RetractedBlock, None, &mut transaction_queue
); );
}); });
} }
@ -1159,7 +1170,7 @@ mod tests {
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult}; use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult};
use header::BlockNumber; use header::BlockNumber;
use types::transaction::{Transaction, SignedTransaction, Action}; use types::transaction::{Transaction, SignedTransaction, PendingTransaction, Action};
use spec::Spec; use spec::Spec;
use tests::helpers::{generate_dummy_client}; use tests::helpers::{generate_dummy_client};
@ -1238,12 +1249,12 @@ mod tests {
let transaction = transaction(); let transaction = transaction();
let best_block = 0; let best_block = 0;
// when // when
let res = miner.import_own_transaction(&client, transaction); let res = miner.import_own_transaction(&client, PendingTransaction::new(transaction, None));
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
assert_eq!(miner.all_transactions().len(), 1); assert_eq!(miner.pending_transactions().len(), 1);
assert_eq!(miner.pending_transactions(best_block).len(), 1); assert_eq!(miner.ready_transactions(best_block).len(), 1);
assert_eq!(miner.pending_transactions_hashes(best_block).len(), 1); assert_eq!(miner.pending_transactions_hashes(best_block).len(), 1);
assert_eq!(miner.pending_receipts(best_block).len(), 1); assert_eq!(miner.pending_receipts(best_block).len(), 1);
// This method will let us know if pending block was created (before calling that method) // This method will let us know if pending block was created (before calling that method)
@ -1258,12 +1269,12 @@ mod tests {
let transaction = transaction(); let transaction = transaction();
let best_block = 10; let best_block = 10;
// when // when
let res = miner.import_own_transaction(&client, transaction); let res = miner.import_own_transaction(&client, PendingTransaction::new(transaction, None));
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
assert_eq!(miner.all_transactions().len(), 1); assert_eq!(miner.pending_transactions().len(), 1);
assert_eq!(miner.pending_transactions(best_block).len(), 0); assert_eq!(miner.ready_transactions(best_block).len(), 0);
assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0); assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0);
assert_eq!(miner.pending_receipts(best_block).len(), 0); assert_eq!(miner.pending_receipts(best_block).len(), 0);
} }
@ -1280,9 +1291,9 @@ mod tests {
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
assert_eq!(miner.all_transactions().len(), 1); assert_eq!(miner.pending_transactions().len(), 1);
assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0); assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0);
assert_eq!(miner.pending_transactions(best_block).len(), 0); assert_eq!(miner.ready_transactions(best_block).len(), 0);
assert_eq!(miner.pending_receipts(best_block).len(), 0); assert_eq!(miner.pending_receipts(best_block).len(), 0);
// This method will let us know if pending block was created (before calling that method) // This method will let us know if pending block was created (before calling that method)
assert!(miner.prepare_work_sealing(&client)); assert!(miner.prepare_work_sealing(&client));
@ -1315,7 +1326,7 @@ mod tests {
assert!(miner.pending_block().is_none()); assert!(miner.pending_block().is_none());
assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber); assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber);
assert_eq!(miner.import_own_transaction(client, transaction()).unwrap(), TransactionImportResult::Current); assert_eq!(miner.import_own_transaction(client, PendingTransaction::new(transaction(), None)).unwrap(), TransactionImportResult::Current);
miner.update_sealing(client); miner.update_sealing(client);
client.flush_queue(); client.flush_queue();

View File

@ -62,7 +62,7 @@ use block::ClosedBlock;
use header::BlockNumber; use header::BlockNumber;
use receipt::{RichReceipt, Receipt}; use receipt::{RichReceipt, Receipt};
use error::{Error, CallError}; use error::{Error, CallError};
use transaction::SignedTransaction; use transaction::{SignedTransaction, PendingTransaction};
/// Miner client API /// Miner client API
pub trait MinerService : Send + Sync { pub trait MinerService : Send + Sync {
@ -118,7 +118,7 @@ pub trait MinerService : Send + Sync {
Vec<Result<TransactionImportResult, Error>>; Vec<Result<TransactionImportResult, Error>>;
/// Imports own (node owner) transaction to queue. /// Imports own (node owner) transaction to queue.
fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction) -> fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: PendingTransaction) ->
Result<TransactionImportResult, Error>; Result<TransactionImportResult, Error>;
/// Returns hashes of transactions currently in pending /// Returns hashes of transactions currently in pending
@ -144,11 +144,14 @@ pub trait MinerService : Send + Sync {
/// Query pending transactions for hash. /// Query pending transactions for hash.
fn transaction(&self, best_block: BlockNumber, hash: &H256) -> Option<SignedTransaction>; fn transaction(&self, best_block: BlockNumber, hash: &H256) -> Option<SignedTransaction>;
/// Get a list of all transactions. /// Get a list of all pending transactions in the queue.
fn all_transactions(&self) -> Vec<SignedTransaction>; fn pending_transactions(&self) -> Vec<PendingTransaction>;
/// Get a list of all pending transactions. /// Get a list of all transactions that can go into the given block.
fn pending_transactions(&self, best_block: BlockNumber) -> Vec<SignedTransaction>; fn ready_transactions(&self, best_block: BlockNumber) -> Vec<PendingTransaction>;
/// Get a list of all future transactions.
fn future_transactions(&self) -> Vec<PendingTransaction>;
/// Get a list of local transactions with statuses. /// Get a list of local transactions with statuses.
fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus>; fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus>;

View File

@ -51,8 +51,8 @@
//! let gas_estimator = |_tx: &SignedTransaction| 2.into(); //! let gas_estimator = |_tx: &SignedTransaction| 2.into();
//! //!
//! let mut txq = TransactionQueue::default(); //! let mut txq = TransactionQueue::default();
//! txq.add(st2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); //! txq.add(st2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
//! txq.add(st1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); //! txq.add(st1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
//! //!
//! // Check status //! // Check status
//! assert_eq!(txq.status().pending, 2); //! assert_eq!(txq.status().pending, 2);
@ -94,6 +94,7 @@ use util::table::Table;
use transaction::*; use transaction::*;
use error::{Error, TransactionError}; use error::{Error, TransactionError};
use client::TransactionImportResult; use client::TransactionImportResult;
use header::BlockNumber;
use miner::local_transactions::{LocalTransactionsList, Status as LocalTransactionStatus}; use miner::local_transactions::{LocalTransactionsList, Status as LocalTransactionStatus};
/// Transaction origin /// Transaction origin
@ -253,18 +254,21 @@ impl Ord for TransactionOrder {
/// Verified transaction (with sender) /// Verified transaction (with sender)
#[derive(Debug)] #[derive(Debug)]
struct VerifiedTransaction { struct VerifiedTransaction {
/// Transaction /// Transaction.
transaction: SignedTransaction, transaction: SignedTransaction,
/// transaction origin /// Transaction origin.
origin: TransactionOrigin, origin: TransactionOrigin,
/// Delay until specifid block.
min_block: Option<BlockNumber>,
} }
impl VerifiedTransaction { impl VerifiedTransaction {
fn new(transaction: SignedTransaction, origin: TransactionOrigin) -> Result<Self, Error> { fn new(transaction: SignedTransaction, origin: TransactionOrigin, min_block: Option<BlockNumber>) -> Result<Self, Error> {
try!(transaction.sender()); try!(transaction.sender());
Ok(VerifiedTransaction { Ok(VerifiedTransaction {
transaction: transaction, transaction: transaction,
origin: origin, origin: origin,
min_block: min_block,
}) })
} }
@ -620,6 +624,7 @@ impl TransactionQueue {
&mut self, &mut self,
tx: SignedTransaction, tx: SignedTransaction,
origin: TransactionOrigin, origin: TransactionOrigin,
min_block: Option<BlockNumber>,
fetch_account: &F, fetch_account: &F,
gas_estimator: &G, gas_estimator: &G,
) -> Result<TransactionImportResult, Error> where ) -> Result<TransactionImportResult, Error> where
@ -630,7 +635,7 @@ impl TransactionQueue {
let hash = tx.hash(); let hash = tx.hash();
let cloned_tx = tx.clone(); let cloned_tx = tx.clone();
let result = self.add_internal(tx, origin, fetch_account, gas_estimator); let result = self.add_internal(tx, origin, min_block, fetch_account, gas_estimator);
match result { match result {
Ok(TransactionImportResult::Current) => { Ok(TransactionImportResult::Current) => {
self.local_transactions.mark_pending(hash); self.local_transactions.mark_pending(hash);
@ -651,7 +656,7 @@ impl TransactionQueue {
} }
result result
} else { } else {
self.add_internal(tx, origin, fetch_account, gas_estimator) self.add_internal(tx, origin, min_block, fetch_account, gas_estimator)
} }
} }
@ -660,6 +665,7 @@ impl TransactionQueue {
&mut self, &mut self,
tx: SignedTransaction, tx: SignedTransaction,
origin: TransactionOrigin, origin: TransactionOrigin,
min_block: Option<BlockNumber>,
fetch_account: &F, fetch_account: &F,
gas_estimator: &G, gas_estimator: &G,
) -> Result<TransactionImportResult, Error> where ) -> Result<TransactionImportResult, Error> where
@ -728,7 +734,7 @@ impl TransactionQueue {
// Verify signature // Verify signature
try!(tx.check_low_s()); try!(tx.check_low_s());
let vtx = try!(VerifiedTransaction::new(tx, origin)); let vtx = try!(VerifiedTransaction::new(tx, origin, min_block));
let client_account = fetch_account(&vtx.sender()); let client_account = fetch_account(&vtx.sender());
let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas; let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas;
@ -968,10 +974,48 @@ impl TransactionQueue {
/// Returns top transactions from the queue ordered by priority. /// Returns top transactions from the queue ordered by priority.
pub fn top_transactions(&self) -> Vec<SignedTransaction> { pub fn top_transactions(&self) -> Vec<SignedTransaction> {
self.current.by_priority self.top_transactions_at(BlockNumber::max_value())
}
fn filter_pending_transaction<F>(&self, best_block: BlockNumber, mut f: F)
where F: FnMut(&VerifiedTransaction) {
let mut delayed = HashSet::new();
for t in self.current.by_priority.iter() {
let tx = self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`");
let sender = tx.sender();
if delayed.contains(&sender) {
continue;
}
if tx.min_block.unwrap_or(0) > best_block {
delayed.insert(sender);
continue;
}
f(&tx);
}
}
/// Returns top transactions from the queue ordered by priority.
pub fn top_transactions_at(&self, best_block: BlockNumber) -> Vec<SignedTransaction> {
let mut r = Vec::new();
self.filter_pending_transaction(best_block, |tx| r.push(tx.transaction.clone()));
r
}
/// Return all ready transactions.
pub fn pending_transactions(&self, best_block: BlockNumber) -> Vec<PendingTransaction> {
let mut r = Vec::new();
self.filter_pending_transaction(best_block, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.min_block)));
r
}
/// Return all ready transactions.
pub fn future_transactions(&self) -> Vec<PendingTransaction> {
self.future.by_priority
.iter() .iter()
.map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) .map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`"))
.map(|t| t.transaction.clone()) .map(|t| PendingTransaction { transaction: t.transaction.clone(), min_block: t.min_block })
.collect() .collect()
} }
@ -980,15 +1024,6 @@ impl TransactionQueue {
self.local_transactions.all_transactions() self.local_transactions.all_transactions()
} }
#[cfg(test)]
fn future_transactions(&self) -> Vec<SignedTransaction> {
self.future.by_priority
.iter()
.map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`"))
.map(|t| t.transaction.clone())
.collect()
}
/// Returns hashes of all transactions from current, ordered by priority. /// Returns hashes of all transactions from current, ordered by priority.
pub fn pending_hashes(&self) -> Vec<H256> { pub fn pending_hashes(&self) -> Vec<H256> {
self.current.by_priority self.current.by_priority
@ -1353,14 +1388,14 @@ mod test {
let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into()); let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into());
let sender = tx1.sender().unwrap(); let sender = tx1.sender().unwrap();
let nonce = tx1.nonce; let nonce = tx1.nonce;
txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into())); assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into()));
// when // when
let tx = new_tx(123.into(), 1.into()); let tx = new_tx(123.into(), 1.into());
let res = txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
// No longer the case as we don't even consider a transaction that isn't above a full // No longer the case as we don't even consider a transaction that isn't above a full
@ -1392,12 +1427,12 @@ mod test {
gas_limit: !U256::zero(), gas_limit: !U256::zero(),
}; };
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap(); let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap(); let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap();
let mut by_hash = { let mut by_hash = {
let mut x = HashMap::new(); let mut x = HashMap::new();
let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap(); let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap(); let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap();
x.insert(tx1.hash(), tx1); x.insert(tx1.hash(), tx1);
x.insert(tx2.hash(), tx2); x.insert(tx2.hash(), tx2);
x x
@ -1435,12 +1470,12 @@ mod test {
// Create two transactions with same nonce // Create two transactions with same nonce
// (same hash) // (same hash)
let (tx1, tx2) = new_tx_pair_default(0.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(0.into(), 0.into());
let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap(); let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap(); let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap();
let by_hash = { let by_hash = {
let mut x = HashMap::new(); let mut x = HashMap::new();
let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap(); let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap();
let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap(); let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap();
x.insert(tx1.hash(), tx1); x.insert(tx1.hash(), tx1);
x.insert(tx2.hash(), tx2); x.insert(tx2.hash(), tx2);
x x
@ -1482,10 +1517,10 @@ mod test {
gas_limit: !U256::zero(), gas_limit: !U256::zero(),
}; };
let tx = new_tx_default(); let tx = new_tx_default();
let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap(); let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap();
let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx1.sender(), tx1.nonce(), order1).is_none()); assert!(set.insert(tx1.sender(), tx1.nonce(), order1).is_none());
let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External).unwrap(); let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External, None).unwrap();
let order2 = TransactionOrder::for_transaction(&tx2, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); let order2 = TransactionOrder::for_transaction(&tx2, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx2.sender(), tx2.nonce(), order2).is_some()); assert!(set.insert(tx2.sender(), tx2.nonce(), order2).is_some());
} }
@ -1502,7 +1537,7 @@ mod test {
assert_eq!(set.gas_price_entry_limit(), 0.into()); assert_eq!(set.gas_price_entry_limit(), 0.into());
let tx = new_tx_default(); let tx = new_tx_default();
let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap(); let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap();
let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none()); assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none());
assert_eq!(set.gas_price_entry_limit(), 2.into()); assert_eq!(set.gas_price_entry_limit(), 2.into());
@ -1517,12 +1552,12 @@ mod test {
!U256::zero() }; !U256::zero() };
// First insert one transaction to future // First insert one transaction to future
let res = txq.add(tx, TransactionOrigin::External, &prev_nonce, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, None, &prev_nonce, &gas_estimator);
assert_eq!(res.unwrap(), TransactionImportResult::Future); assert_eq!(res.unwrap(), TransactionImportResult::Future);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// now import second transaction to current // now import second transaction to current
let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// and then there should be only one transaction in current (the one with higher gas_price) // and then there should be only one transaction in current (the one with higher gas_price)
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1542,12 +1577,12 @@ mod test {
!U256::zero() }; !U256::zero() };
// First insert one transaction to future // First insert one transaction to future
let res = txq.add(tx.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator); let res = txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator);
assert_eq!(res.unwrap(), TransactionImportResult::Future); assert_eq!(res.unwrap(), TransactionImportResult::Future);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// now import second transaction to current // now import second transaction to current
let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1566,7 +1601,7 @@ mod test {
let tx = new_tx_default(); let tx = new_tx_default();
// when // when
let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1585,10 +1620,10 @@ mod test {
txq.set_minimal_gas_price(15.into()); txq.set_minimal_gas_price(15.into());
// when // when
let res1 = txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator); let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
let res2 = txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator); let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
let res3 = txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator); let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
let res4 = txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator); let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res1.unwrap(), TransactionImportResult::Current); assert_eq!(res1.unwrap(), TransactionImportResult::Current);
@ -1619,10 +1654,10 @@ mod test {
txq.set_minimal_gas_price(15.into()); txq.set_minimal_gas_price(15.into());
// when // when
let res1 = txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator); let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
let res2 = txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator); let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
let res3 = txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator); let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
let res4 = txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator); let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res1.unwrap(), TransactionImportResult::Current); assert_eq!(res1.unwrap(), TransactionImportResult::Current);
@ -1665,7 +1700,7 @@ mod test {
txq.set_gas_limit(limit); txq.set_gas_limit(limit);
// when // when
let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded {
@ -1689,7 +1724,7 @@ mod test {
}; };
// when // when
let res = txq.add(tx, TransactionOrigin::External, &account, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, None, &account, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance { assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance {
@ -1709,7 +1744,7 @@ mod test {
txq.set_minimal_gas_price(tx.gas_price + U256::one()); txq.set_minimal_gas_price(tx.gas_price + U256::one());
// when // when
let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice {
@ -1729,7 +1764,7 @@ mod test {
txq.set_minimal_gas_price(tx.gas_price + U256::one()); txq.set_minimal_gas_price(tx.gas_price + U256::one());
// when // when
let res = txq.add(tx, TransactionOrigin::Local, &default_account_details, &gas_estimator); let res = txq.add(tx, TransactionOrigin::Local, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(res.unwrap(), TransactionImportResult::Current);
@ -1759,7 +1794,7 @@ mod test {
rlp::decode(s.as_raw()) rlp::decode(s.as_raw())
}; };
// when // when
let res = txq.add(stx, TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(stx, TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
assert!(res.is_err()); assert!(res.is_err());
@ -1773,8 +1808,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when // when
txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1793,9 +1828,9 @@ mod test {
// when // when
// first insert the one with higher gas price // first insert the one with higher gas price
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then the one with lower gas price, but local // then the one with lower gas price, but local
txq.add(tx.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1812,15 +1847,15 @@ mod test {
// the second one has same nonce but higher `gas_price` // the second one has same nonce but higher `gas_price`
let (_, tx0) = new_similar_tx_pair(); let (_, tx0) = new_similar_tx_pair();
txq.add(tx0.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx0.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// the one with higher gas price is first // the one with higher gas price is first
assert_eq!(txq.top_transactions()[0], tx0); assert_eq!(txq.top_transactions()[0], tx0);
assert_eq!(txq.top_transactions()[1], tx1); assert_eq!(txq.top_transactions()[1], tx1);
// when // when
// insert second as local // insert second as local
txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
// then // then
// the order should be updated // the order should be updated
@ -1839,9 +1874,9 @@ mod test {
// when // when
// first insert local one with higher gas price // first insert local one with higher gas price
txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
// then the one with lower gas price, but from retracted block // then the one with lower gas price, but from retracted block
txq.add(tx.clone(), TransactionOrigin::RetractedBlock, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::RetractedBlock, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1857,8 +1892,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when // when
txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.top_transactions(); let top = txq.top_transactions();
@ -1877,10 +1912,10 @@ mod test {
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
// insert everything // insert everything
txq.add(txa.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); txq.add(txa.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(txb.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); txq.add(txb.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 4); assert_eq!(txq.status().future, 4);
@ -1889,10 +1924,10 @@ mod test {
// then // then
let top = txq.future_transactions(); let top = txq.future_transactions();
assert_eq!(top[0], txa); assert_eq!(top[0].transaction, txa);
assert_eq!(top[1], txb); assert_eq!(top[1].transaction, txb);
assert_eq!(top[2], tx1); assert_eq!(top[2].transaction, tx1);
assert_eq!(top[3], tx2); assert_eq!(top[3].transaction, tx2);
assert_eq!(top.len(), 4); assert_eq!(top.len(), 4);
} }
@ -1905,10 +1940,10 @@ mod test {
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
// insert everything // insert everything
txq.add(txa.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(txa.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
txq.add(txb.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(txb.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
let top = txq.top_transactions(); let top = txq.top_transactions();
assert_eq!(top[0], tx1); assert_eq!(top[0], tx1);
@ -1938,10 +1973,10 @@ mod test {
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
// insert everything // insert everything
txq.add(txa.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(txa.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(txb.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(txb.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
let top = txq.top_transactions(); let top = txq.top_transactions();
assert_eq!(top[0], tx1); assert_eq!(top[0], tx1);
@ -1970,8 +2005,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when // when
txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let top = txq.pending_hashes(); let top = txq.pending_hashes();
@ -1988,8 +2023,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(2.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(2.into(), 0.into());
// when // when
let res1 = txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); let res1 = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
let res2 = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
assert_eq!(res1, TransactionImportResult::Current); assert_eq!(res1, TransactionImportResult::Current);
@ -2002,6 +2037,26 @@ mod test {
assert_eq!(top[0], tx); assert_eq!(top[0], tx);
} }
#[test]
fn should_handle_min_block() {
// given
let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when
let res1 = txq.add(tx.clone(), TransactionOrigin::External, Some(1), &default_account_details, &gas_estimator).unwrap();
let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then
assert_eq!(res1, TransactionImportResult::Current);
assert_eq!(res2, TransactionImportResult::Current);
let top = txq.top_transactions_at(0);
assert_eq!(top.len(), 0);
let top = txq.top_transactions_at(1);
assert_eq!(top.len(), 2);
}
#[test] #[test]
fn should_correctly_update_futures_when_removing() { fn should_correctly_update_futures_when_removing() {
// given // given
@ -2012,8 +2067,8 @@ mod test {
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 2); assert_eq!(txq.status().future, 2);
// when // when
@ -2035,13 +2090,13 @@ mod test {
let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret, None); let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret, None);
let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret, None); let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret, None);
txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().pending, 1);
txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
// when // when
txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2057,8 +2112,8 @@ mod test {
// given // given
let mut txq2 = TransactionQueue::default(); let mut txq2 = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(3.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(3.into(), 0.into());
txq2.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq2.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq2.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq2.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq2.status().pending, 1); assert_eq!(txq2.status().pending, 1);
assert_eq!(txq2.status().future, 1); assert_eq!(txq2.status().future, 1);
@ -2079,10 +2134,10 @@ mod test {
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx3 = new_tx_default(); let tx3 = new_tx_default();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 3); assert_eq!(txq.status().pending, 3);
// when // when
@ -2101,8 +2156,8 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// add // add
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
let stats = txq.status(); let stats = txq.status();
assert_eq!(stats.pending, 2); assert_eq!(stats.pending, 2);
@ -2121,11 +2176,11 @@ mod test {
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let sender = tx.sender().unwrap(); let sender = tx.sender().unwrap();
let nonce = tx.nonce; let nonce = tx.nonce;
txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().pending, 1);
// when // when
let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator);
// then // then
let t = txq.top_transactions(); let t = txq.top_transactions();
@ -2142,14 +2197,14 @@ mod test {
txq.current.set_limit(10); txq.current.set_limit(10);
let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into()); let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into());
let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into()); let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into());
txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
// when // when
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx4.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
@ -2160,11 +2215,11 @@ mod test {
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero()); let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero());
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// limited by gas // limited by gas
txq.add(tx4.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap_err(); txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
} }
@ -2174,12 +2229,12 @@ mod test {
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2));
txq.add(tx1.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
// Not accepted because of limit // Not accepted because of limit
txq.add(tx5.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap_err(); txq.add(tx5.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err();
txq.add(tx3.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx4.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx4.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 4); assert_eq!(txq.status().pending, 4);
} }
@ -2191,7 +2246,7 @@ mod test {
let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() }; let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() };
// when // when
let res = txq.add(tx, TransactionOrigin::External, &fetch_last_nonce, &gas_estimator); let res = txq.add(tx, TransactionOrigin::External, None, &fetch_last_nonce, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::Old); assert_eq!(unwrap_tx_err(res), TransactionError::Old);
@ -2207,12 +2262,12 @@ mod test {
balance: !U256::zero() }; balance: !U256::zero() };
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (_tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (_tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().pending, 0);
// when // when
let res = txq.add(tx2.clone(), TransactionOrigin::External, &nonce, &gas_estimator); let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &nonce, &gas_estimator);
// then // then
assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported); assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported);
@ -2226,15 +2281,15 @@ mod test {
// given // given
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().pending, 2);
// when // when
txq.remove_invalid(&tx1.hash(), &default_account_details); txq.remove_invalid(&tx1.hash(), &default_account_details);
assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().pending, 0);
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2248,10 +2303,10 @@ mod test {
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx3 = new_tx_default(); let tx3 = new_tx_default();
txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().pending, 3); assert_eq!(txq.status().pending, 3);
// when // when
@ -2278,8 +2333,8 @@ mod test {
}; };
// when // when
txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2306,10 +2361,10 @@ mod test {
}; };
// when // when
txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 1); assert_eq!(txq.status().future, 1);
txq.add(tx0, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx0, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
// then // then
let stats = txq.status(); let stats = txq.status();
@ -2327,8 +2382,8 @@ mod test {
!U256::zero() }; !U256::zero() };
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx1.clone(), TransactionOrigin::External, &previous_nonce, &gas_estimator).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, &previous_nonce, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap();
assert_eq!(txq.status().future, 2); assert_eq!(txq.status().future, 2);
// when // when
@ -2359,7 +2414,7 @@ mod test {
let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() }; let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() };
// when // when
txq.add(tx, TransactionOrigin::External, &details, &gas_estimator).unwrap(); txq.add(tx, TransactionOrigin::External, None, &details, &gas_estimator).unwrap();
// then // then
assert_eq!(txq.last_nonce(&from), Some(nonce)); assert_eq!(txq.last_nonce(&from), Some(nonce));
@ -2374,7 +2429,7 @@ mod test {
let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() }; let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() };
// Insert first transaction // Insert first transaction
txq.add(tx1, TransactionOrigin::External, &details1, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap();
// when // when
txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one()); txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one());
@ -2394,9 +2449,9 @@ mod test {
// when // when
// Insert first transaction // Insert first transaction
assert_eq!(txq.add(tx1, TransactionOrigin::External, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current);
// Second should go to future // Second should go to future
assert_eq!(txq.add(tx2, TransactionOrigin::External, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future); assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future);
// Now block is imported // Now block is imported
txq.remove_all(sender, nonce2 - U256::from(1)); txq.remove_all(sender, nonce2 - U256::from(1));
// tx2 should be not be promoted to current // tx2 should be not be promoted to current
@ -2415,9 +2470,9 @@ mod test {
assert_eq!(txq.has_local_pending_transactions(), false); assert_eq!(txq.has_local_pending_transactions(), false);
// when // when
assert_eq!(txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current);
assert_eq!(txq.has_local_pending_transactions(), false); assert_eq!(txq.has_local_pending_transactions(), false);
assert_eq!(txq.add(tx2, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); assert_eq!(txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current);
// then // then
assert_eq!(txq.has_local_pending_transactions(), true); assert_eq!(txq.has_local_pending_transactions(), true);
@ -2432,8 +2487,8 @@ mod test {
default_account_details(a).balance }; default_account_details(a).balance };
// when // when
assert_eq!(txq.add(tx2, TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future);
assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future);
// then // then
assert_eq!(txq.future.by_priority.len(), 1); assert_eq!(txq.future.by_priority.len(), 1);
@ -2458,14 +2513,14 @@ mod test {
(tx.sign(secret, None), tx2.sign(secret, None), tx2_2.sign(secret, None), tx3.sign(secret, None)) (tx.sign(secret, None), tx2.sign(secret, None), tx2_2.sign(secret, None), tx3.sign(secret, None))
}; };
let sender = tx1.sender().unwrap(); let sender = tx1.sender().unwrap();
txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.future.by_priority.len(), 0); assert_eq!(txq.future.by_priority.len(), 0);
assert_eq!(txq.current.by_priority.len(), 3); assert_eq!(txq.current.by_priority.len(), 3);
// when // when
let res = txq.add(tx2_2, TransactionOrigin::Local, &default_account_details, &gas_estimator); let res = txq.add(tx2_2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator);
// then // then
assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into()); assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into());
@ -2481,8 +2536,8 @@ mod test {
let high_gas = |_: &SignedTransaction| 100_001.into(); let high_gas = |_: &SignedTransaction| 100_001.into();
// when // when
let res1 = txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator); let res1 = txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator);
let res2 = txq.add(tx2, TransactionOrigin::Local, &default_account_details, &high_gas); let res2 = txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &high_gas);
// then // then
assert_eq!(res1.unwrap(), TransactionImportResult::Current); assert_eq!(res1.unwrap(), TransactionImportResult::Current);
@ -2502,10 +2557,10 @@ mod test {
let nonce1 = tx1.nonce; let nonce1 = tx1.nonce;
// Insert all transactions // Insert all transactions
txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap();
assert_eq!(txq.top_transactions().len(), 4); assert_eq!(txq.top_transactions().len(), 4);
// when // when

View File

@ -28,6 +28,9 @@ use rlp::{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 transaction::{PendingTransaction, Transaction, Action};
use miner::MinerService;
#[test] #[test]
fn imports_from_empty() { fn imports_from_empty() {
@ -284,3 +287,37 @@ fn change_history_size() {
let client = Client::new(config, &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap(); let client = Client::new(config, &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap();
assert_eq!(client.state().balance(&address), 100.into()); assert_eq!(client.state().balance(&address), 100.into());
} }
#[test]
fn does_not_propagate_delayed_transactions() {
let key = KeyPair::from_secret("test".sha3()).unwrap();
let secret = key.secret();
let tx0 = PendingTransaction::new(Transaction {
nonce: 0.into(),
gas_price: 0.into(),
gas: 21000.into(),
action: Action::Call(Address::default()),
value: 0.into(),
data: Vec::new(),
}.sign(secret, None), Some(2));
let tx1 = PendingTransaction::new(Transaction {
nonce: 1.into(),
gas_price: 0.into(),
gas: 21000.into(),
action: Action::Call(Address::default()),
value: 0.into(),
data: Vec::new(),
}.sign(secret, None), None);
let client_result = generate_dummy_client(1);
let client = client_result.reference();
client.miner().import_own_transaction(&**client, tx0).unwrap();
client.miner().import_own_transaction(&**client, tx1).unwrap();
assert_eq!(0, client.ready_transactions().len());
assert_eq!(2, client.miner().pending_transactions().len());
push_blocks_to_client(client, 53, 2, 2);
client.flush_queue();
assert_eq!(2, client.ready_transactions().len());
assert_eq!(2, client.miner().pending_transactions().len());
}

View File

@ -390,6 +390,34 @@ impl Deref for LocalizedTransaction {
} }
} }
/// Queued transaction with additional information.
#[derive(Debug, Clone, PartialEq, Eq, Binary)]
pub struct PendingTransaction {
/// Signed transaction data.
pub transaction: SignedTransaction,
/// To be activated at this block. `None` for immediately.
pub min_block: Option<BlockNumber>,
}
impl PendingTransaction {
/// Create a new pending transaction from signed transaction.
pub fn new(signed: SignedTransaction, min_block: Option<BlockNumber>) -> Self {
PendingTransaction {
transaction: signed,
min_block: min_block,
}
}
}
impl From<SignedTransaction> for PendingTransaction {
fn from(t: SignedTransaction) -> Self {
PendingTransaction {
transaction: t,
min_block: None,
}
}
}
#[test] #[test]
fn sender_test() { fn sender_test() {
let t: SignedTransaction = decode(&::rustc_serialize::hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); let t: SignedTransaction = decode(&::rustc_serialize::hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap());

View File

@ -38,7 +38,7 @@ export default class SecureApi extends Api {
setToken = () => { setToken = () => {
window.localStorage.setItem('sysuiToken', this._transport.token); window.localStorage.setItem('sysuiToken', this._transport.token);
console.log('SecureApi:setToken', this._transport.token); // DEBUG: console.log('SecureApi:setToken', this._transport.token);
} }
_checkNodeUp () { _checkNodeUp () {
@ -149,14 +149,14 @@ export default class SecureApi extends Api {
this._signerPort = signerPort.toNumber(); this._signerPort = signerPort.toNumber();
}); });
console.log('SecureApi:connectSuccess', this._transport.token); // DEBUG: console.log('SecureApi:connectSuccess', this._transport.token);
} }
updateToken (token, connectState = 0) { updateToken (token, connectState = 0) {
this._connectState = connectState; this._connectState = connectState;
this._transport.updateToken(token.replace(/[^a-zA-Z0-9]/g, '')); this._transport.updateToken(token.replace(/[^a-zA-Z0-9]/g, ''));
this._followConnection(); this._followConnection();
console.log('SecureApi:updateToken', this._transport.token, connectState); // DEBUG: console.log('SecureApi:updateToken', this._transport.token, connectState);
} }
get dappsPort () { get dappsPort () {

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundlePackageType</key><string>APPL</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string> <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundleIconFiles</key><string>Parity.png</string><key>CFBundlePackageType</key><string>APPL</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
<key>CFBundleName</key> <string>Parity Ethereum</string> <key>CFBundleName</key> <string>Parity Ethereum</string>
<key>CFBundleExecutable</key> <string>go.sh</string> <key>CFBundleExecutable</key> <string>go.sh</string>

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

View File

@ -145,7 +145,7 @@ macro_rules! usage {
} }
let config_file = raw_args.flag_config.clone().unwrap_or_else(|| raw_args.clone().into_args(Config::default()).flag_config); let config_file = raw_args.flag_config.clone().unwrap_or_else(|| raw_args.clone().into_args(Config::default()).flag_config);
let config_file = replace_home("", &config_file); let config_file = replace_home(&::dir::default_data_path(), &config_file);
let config = match (fs::File::open(&config_file), raw_args.flag_config.is_some()) { let config = match (fs::File::open(&config_file), raw_args.flag_config.is_some()) {
// Load config file // Load config file
(Ok(mut file), _) => { (Ok(mut file), _) => {

View File

@ -21,6 +21,16 @@ use util::journaldb::Algorithm;
use helpers::replace_home; use helpers::replace_home;
use app_dirs::{AppInfo, get_app_root, AppDataType}; use app_dirs::{AppInfo, get_app_root, AppDataType};
#[cfg(target_os = "macos")] const AUTHOR: &'static str = "Parity";
#[cfg(target_os = "macos")] const PRODUCT: &'static str = "io.parity.ethereum";
#[cfg(target_os = "macos")] const PRODUCT_HYPERVISOR: &'static str = "io.parity.ethereum-updates";
#[cfg(target_os = "windows")] const AUTHOR: &'static str = "Parity";
#[cfg(target_os = "windows")] const PRODUCT: &'static str = "Ethereum";
#[cfg(target_os = "windows")] const PRODUCT_HYPERVISOR: &'static str = "EthereumUpdates";
#[cfg(not(any(target_os = "windows", target_os = "macos")))] const AUTHOR: &'static str = "parity";
#[cfg(not(any(target_os = "windows", target_os = "macos")))] const PRODUCT: &'static str = "io.parity.ethereum";
#[cfg(not(any(target_os = "windows", target_os = "macos")))] const PRODUCT_HYPERVISOR: &'static str = "io.parity.ethereum-updates";
// this const is irrelevent cause we do have migrations now, // this const is irrelevent cause we do have migrations now,
// but we still use it for backwards compatibility // but we still use it for backwards compatibility
const LEGACY_CLIENT_DB_VER_STR: &'static str = "5.3"; const LEGACY_CLIENT_DB_VER_STR: &'static str = "5.3";
@ -195,12 +205,12 @@ impl DatabaseDirectories {
} }
pub fn default_data_path() -> String { pub fn default_data_path() -> String {
let app_info = AppInfo { name: "parity", author: "parity" }; let app_info = AppInfo { name: PRODUCT, author: AUTHOR };
get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity".to_owned()) get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity".to_owned())
} }
pub fn default_hypervisor_path() -> String { pub fn default_hypervisor_path() -> String {
let app_info = AppInfo { name: "parity-hypervisor", author: "parity" }; let app_info = AppInfo { name: PRODUCT_HYPERVISOR, author: AUTHOR };
get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity-hypervisor".to_owned()) get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity-hypervisor".to_owned())
} }

View File

@ -72,7 +72,7 @@ pub fn start(conf: Configuration, deps: Dependencies) -> Result<Option<SignerSer
fn codes_path(path: String) -> PathBuf { fn codes_path(path: String) -> PathBuf {
let mut p = PathBuf::from(path); let mut p = PathBuf::from(path);
p.push(CODES_FILENAME); p.push(CODES_FILENAME);
let _ = restrict_permissions_owner(&p); let _ = restrict_permissions_owner(&p, true, false);
p p
} }

View File

@ -23,7 +23,7 @@ use util::bytes::ToPretty;
use ethkey::Signature; use ethkey::Signature;
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use ethcore::transaction::{Action, SignedTransaction, Transaction}; use ethcore::transaction::{Action, SignedTransaction, PendingTransaction, Transaction};
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use jsonrpc_core::Error; use jsonrpc_core::Error;
@ -147,9 +147,9 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: S
}) })
} }
pub fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result<H256, Error> pub fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: PendingTransaction) -> Result<H256, Error>
where C: MiningBlockChainClient, M: MinerService { where C: MiningBlockChainClient, M: MinerService {
let hash = signed_transaction.hash(); let hash = signed_transaction.transaction.hash();
miner.import_own_transaction(client, signed_transaction) miner.import_own_transaction(client, signed_transaction)
.map_err(errors::from_transaction_error) .map_err(errors::from_transaction_error)
@ -190,6 +190,7 @@ pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider
{ {
let network_id = client.signing_network_id(); let network_id = client.signing_network_id();
let min_block = filled.min_block.clone();
let signed_transaction = try!(sign_no_dispatch(client, miner, accounts, filled, password)); let signed_transaction = try!(sign_no_dispatch(client, miner, accounts, filled, password));
let (signed_transaction, token) = match signed_transaction { let (signed_transaction, token) = match signed_transaction {
@ -198,7 +199,8 @@ pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, accounts: &AccountProvider
}; };
trace!(target: "miner", "send_transaction: dispatching tx: {} for network ID {:?}", rlp::encode(&signed_transaction).to_vec().pretty(), network_id); trace!(target: "miner", "send_transaction: dispatching tx: {} for network ID {:?}", rlp::encode(&signed_transaction).to_vec().pretty(), network_id);
dispatch_transaction(&*client, &*miner, signed_transaction).map(|hash| { let pending_transaction = PendingTransaction::new(signed_transaction, min_block);
dispatch_transaction(&*client, &*miner, pending_transaction).map(|hash| {
match token { match token {
Some(ref token) => WithToken::Yes(hash, token.clone()), Some(ref token) => WithToken::Yes(hash, token.clone()),
None => WithToken::No(hash), None => WithToken::No(hash),
@ -217,6 +219,7 @@ pub fn fill_optional_fields<C, M>(request: TransactionRequest, client: &C, miner
gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
value: request.value.unwrap_or_else(|| 0.into()), value: request.value.unwrap_or_else(|| 0.into()),
data: request.data.unwrap_or_else(Vec::new), data: request.data.unwrap_or_else(Vec::new),
min_block: request.min_block,
} }
} }

View File

@ -33,6 +33,8 @@ pub struct TransactionRequest {
pub data: Option<Bytes>, pub data: Option<Bytes>,
/// Transaction's nonce /// Transaction's nonce
pub nonce: Option<U256>, pub nonce: Option<U256>,
/// Delay until this block if specified.
pub min_block: Option<u64>,
} }
/// Transaction request coming from RPC with default values filled in. /// Transaction request coming from RPC with default values filled in.
@ -52,6 +54,8 @@ pub struct FilledTransactionRequest {
pub data: Bytes, pub data: Bytes,
/// Transaction's nonce /// Transaction's nonce
pub nonce: Option<U256>, pub nonce: Option<U256>,
/// Delay until this block if specified.
pub min_block: Option<u64>,
} }
impl From<FilledTransactionRequest> for TransactionRequest { impl From<FilledTransactionRequest> for TransactionRequest {
@ -64,6 +68,7 @@ impl From<FilledTransactionRequest> for TransactionRequest {
value: Some(r.value), value: Some(r.value),
data: Some(r.data), data: Some(r.data),
nonce: r.nonce, nonce: r.nonce,
min_block: r.min_block,
} }
} }
} }

View File

@ -328,6 +328,7 @@ mod test {
value: 10_000_000.into(), value: 10_000_000.into(),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
}) })
} }

View File

@ -38,7 +38,7 @@ use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber};
use ethcore::block::IsBlock; use ethcore::block::IsBlock;
use ethcore::views::*; use ethcore::views::*;
use ethcore::ethereum::Ethash; use ethcore::ethereum::Ethash;
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, PendingTransaction, Action};
use ethcore::log_entry::LogEntry; use ethcore::log_entry::LogEntry;
use ethcore::filter::Filter as EthcoreFilter; use ethcore::filter::Filter as EthcoreFilter;
use ethcore::snapshot::SnapshotService; use ethcore::snapshot::SnapshotService;
@ -617,7 +617,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let raw_transaction = raw.to_vec(); let raw_transaction = raw.to_vec();
match UntrustedRlp::new(&raw_transaction).as_val() { match UntrustedRlp::new(&raw_transaction).as_val() {
Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction).map(Into::into), Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), PendingTransaction::new(signed_transaction, None)).map(Into::into),
Err(e) => Err(errors::from_rlp_error(e)), Err(e) => Err(errors::from_rlp_error(e)),
} }
} }

View File

@ -270,7 +270,13 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
fn pending_transactions(&self) -> Result<Vec<Transaction>, Error> { fn pending_transactions(&self) -> Result<Vec<Transaction>, Error> {
try!(self.active()); try!(self.active());
Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::<Vec<_>>()) Ok(take_weak!(self.miner).pending_transactions().into_iter().map(Into::into).collect::<Vec<_>>())
}
fn future_transactions(&self) -> Result<Vec<Transaction>, Error> {
try!(self.active());
Ok(take_weak!(self.miner).future_transactions().into_iter().map(Into::into).collect::<Vec<_>>())
} }
fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error> { fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error> {

View File

@ -21,7 +21,7 @@ use std::sync::{Arc, Weak};
use rlp::{UntrustedRlp, View}; use rlp::{UntrustedRlp, View};
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use ethcore::transaction::SignedTransaction; use ethcore::transaction::{SignedTransaction, PendingTransaction};
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use jsonrpc_core::Error; use jsonrpc_core::Error;
@ -82,6 +82,9 @@ impl<C: 'static, M: 'static> SignerClient<C, M> where C: MiningBlockChainClient,
if let Some(gas) = modification.gas { if let Some(gas) = modification.gas {
request.gas = gas.into(); request.gas = gas.into();
} }
if let Some(ref min_block) = modification.min_block {
request.min_block = min_block.as_ref().and_then(|b| b.to_min_block_num());
}
} }
let result = f(&*client, &*miner, &*accounts, payload); let result = f(&*client, &*miner, &*accounts, payload);
// Execute // Execute
@ -155,7 +158,8 @@ impl<C: 'static, M: 'static> Signer for SignerClient<C, M> where C: MiningBlockC
// Dispatch if everything is ok // Dispatch if everything is ok
if sender_matches && data_matches && value_matches && nonce_matches { if sender_matches && data_matches && value_matches && nonce_matches {
dispatch_transaction(&*client, &*miner, signed_transaction) let pending_transaction = PendingTransaction::new(signed_transaction, request.min_block);
dispatch_transaction(&*client, &*miner, pending_transaction)
.map(Into::into) .map(Into::into)
.map(ConfirmationResponse::SendTransaction) .map(ConfirmationResponse::SendTransaction)
} else { } else {

View File

@ -22,7 +22,7 @@ use ethcore::error::{Error, CallError};
use ethcore::client::{MiningBlockChainClient, Executed, CallAnalytics}; use ethcore::client::{MiningBlockChainClient, Executed, CallAnalytics};
use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::block::{ClosedBlock, IsBlock};
use ethcore::header::BlockNumber; use ethcore::header::BlockNumber;
use ethcore::transaction::SignedTransaction; use ethcore::transaction::{SignedTransaction, PendingTransaction};
use ethcore::receipt::{Receipt, RichReceipt}; use ethcore::receipt::{Receipt, RichReceipt};
use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus}; use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus};
use ethcore::account_provider::Error as AccountError; use ethcore::account_provider::Error as AccountError;
@ -160,17 +160,17 @@ impl MinerService for TestMinerService {
} }
/// Imports transactions to transaction queue. /// Imports transactions to transaction queue.
fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction) -> fn import_own_transaction(&self, chain: &MiningBlockChainClient, pending: PendingTransaction) ->
Result<TransactionImportResult, Error> { Result<TransactionImportResult, Error> {
// keep the pending nonces up to date // keep the pending nonces up to date
if let Ok(ref sender) = transaction.sender() { if let Ok(ref sender) = pending.transaction.sender() {
let nonce = self.last_nonce(sender).unwrap_or(chain.latest_nonce(sender)); let nonce = self.last_nonce(sender).unwrap_or(chain.latest_nonce(sender));
self.last_nonces.write().insert(sender.clone(), nonce + U256::from(1)); self.last_nonces.write().insert(sender.clone(), nonce + U256::from(1));
} }
// lets assume that all txs are valid // lets assume that all txs are valid
self.imported_transactions.lock().push(transaction); self.imported_transactions.lock().push(pending.transaction);
Ok(TransactionImportResult::Current) Ok(TransactionImportResult::Current)
} }
@ -204,16 +204,20 @@ impl MinerService for TestMinerService {
self.pending_transactions.lock().get(hash).cloned() self.pending_transactions.lock().get(hash).cloned()
} }
fn all_transactions(&self) -> Vec<SignedTransaction> { fn pending_transactions(&self) -> Vec<PendingTransaction> {
self.pending_transactions.lock().values().cloned().collect() self.pending_transactions.lock().values().cloned().map(Into::into).collect()
} }
fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus> { fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus> {
self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect() self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect()
} }
fn pending_transactions(&self, _best_block: BlockNumber) -> Vec<SignedTransaction> { fn ready_transactions(&self, _best_block: BlockNumber) -> Vec<PendingTransaction> {
self.pending_transactions.lock().values().cloned().collect() self.pending_transactions.lock().values().cloned().map(Into::into).collect()
}
fn future_transactions(&self) -> Vec<PendingTransaction> {
vec![]
} }
fn pending_receipt(&self, _best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> { fn pending_receipt(&self, _best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {

View File

@ -501,7 +501,7 @@ fn rpc_eth_pending_transaction_by_hash() {
tester.miner.pending_transactions.lock().insert(H256::zero(), tx); tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
} }
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","networkId":null,"nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","minBlock":null,"networkId":null,"nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#;
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_getTransactionByHash", "method": "eth_getTransactionByHash",
@ -817,6 +817,7 @@ fn rpc_eth_sign_transaction() {
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
&format!("\"hash\":\"0x{:?}\",", t.hash()) + &format!("\"hash\":\"0x{:?}\",", t.hash()) +
r#""input":"0x","# + r#""input":"0x","# +
r#""minBlock":null,"# +
&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) + &format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) +
r#""nonce":"0x1","# + r#""nonce":"0x1","# +
&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) + &format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) +

View File

@ -82,6 +82,7 @@ fn should_return_list_of_items_to_confirm() {
value: U256::from(1), value: U256::from(1),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
})).unwrap(); })).unwrap();
tester.signer.add_request(ConfirmationPayload::Signature(1.into(), 5.into())).unwrap(); tester.signer.add_request(ConfirmationPayload::Signature(1.into(), 5.into())).unwrap();
@ -89,7 +90,7 @@ fn should_return_list_of_items_to_confirm() {
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
let response = concat!( let response = concat!(
r#"{"jsonrpc":"2.0","result":["#, r#"{"jsonrpc":"2.0","result":["#,
r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","minBlock":null,"nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#, r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#,
r#"],"id":1}"# r#"],"id":1}"#
); );
@ -111,6 +112,7 @@ fn should_reject_transaction_from_queue_without_dispatching() {
value: U256::from(1), value: U256::from(1),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
})).unwrap(); })).unwrap();
assert_eq!(tester.signer.requests().len(), 1); assert_eq!(tester.signer.requests().len(), 1);
@ -136,6 +138,7 @@ fn should_not_remove_transaction_if_password_is_invalid() {
value: U256::from(1), value: U256::from(1),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
})).unwrap(); })).unwrap();
assert_eq!(tester.signer.requests().len(), 1); assert_eq!(tester.signer.requests().len(), 1);
@ -178,6 +181,7 @@ fn should_confirm_transaction_and_dispatch() {
value: U256::from(1), value: U256::from(1),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
})).unwrap(); })).unwrap();
let t = Transaction { let t = Transaction {
@ -223,6 +227,7 @@ fn should_confirm_transaction_with_token() {
value: U256::from(1), value: U256::from(1),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
})).unwrap(); })).unwrap();
let t = Transaction { let t = Transaction {
@ -270,6 +275,7 @@ fn should_confirm_transaction_with_rlp() {
value: U256::from(1), value: U256::from(1),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
})).unwrap(); })).unwrap();
let t = Transaction { let t = Transaction {
@ -317,6 +323,7 @@ fn should_return_error_when_sender_does_not_match() {
value: U256::from(1), value: U256::from(1),
data: vec![], data: vec![],
nonce: None, nonce: None,
min_block: None,
})).unwrap(); })).unwrap();
let t = Transaction { let t = Transaction {

View File

@ -285,6 +285,7 @@ fn should_add_sign_transaction_to_the_queue() {
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
&format!("\"hash\":\"0x{:?}\",", t.hash()) + &format!("\"hash\":\"0x{:?}\",", t.hash()) +
r#""input":"0x","# + r#""input":"0x","# +
r#""minBlock":null,"# +
&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) + &format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) +
r#""nonce":"0x1","# + r#""nonce":"0x1","# +
&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) + &format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) +

View File

@ -123,6 +123,10 @@ build_rpc_trait! {
#[rpc(name = "parity_pendingTransactions")] #[rpc(name = "parity_pendingTransactions")]
fn pending_transactions(&self) -> Result<Vec<Transaction>, Error>; fn pending_transactions(&self) -> Result<Vec<Transaction>, Error>;
/// Returns all future transactions from transaction queue.
#[rpc(name = "parity_futureTransactions")]
fn future_transactions(&self) -> Result<Vec<Transaction>, Error>;
/// Returns propagation statistics on transactions pending in the queue. /// Returns propagation statistics on transactions pending in the queue.
#[rpc(name = "parity_pendingTransactionsStats")] #[rpc(name = "parity_pendingTransactionsStats")]
fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error>; fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error>;

View File

@ -139,7 +139,7 @@ mod tests {
fn test_serialize_block_transactions() { fn test_serialize_block_transactions() {
let t = BlockTransactions::Full(vec![Transaction::default()]); let t = BlockTransactions::Full(vec![Transaction::default()]);
let serialized = serde_json::to_string(&t).unwrap(); let serialized = serde_json::to_string(&t).unwrap();
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}]"#); assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","minBlock":null}]"#);
let t = BlockTransactions::Hashes(vec![H256::default().into()]); let t = BlockTransactions::Hashes(vec![H256::default().into()]);
let serialized = serde_json::to_string(&t).unwrap(); let serialized = serde_json::to_string(&t).unwrap();

View File

@ -14,12 +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/>.
use serde::{Deserialize, Deserializer, Error}; use serde::{Deserialize, Deserializer, Error, Serialize, Serializer};
use serde::de::Visitor; use serde::de::Visitor;
use ethcore::client::BlockId; use ethcore::client::BlockId;
/// Represents rpc api block number param. /// Represents rpc api block number param.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone, Hash, Eq)]
pub enum BlockNumber { pub enum BlockNumber {
/// Number /// Number
Num(u64), Num(u64),
@ -44,6 +44,27 @@ impl Deserialize for BlockNumber {
} }
} }
impl BlockNumber {
/// Convert block number to min block target.
pub fn to_min_block_num(&self) -> Option<u64> {
match *self {
BlockNumber::Num(ref x) => Some(*x),
_ => None,
}
}
}
impl Serialize for BlockNumber {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
match *self {
BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{:x}", x)),
BlockNumber::Latest => serializer.serialize_str("latest"),
BlockNumber::Earliest => serializer.serialize_str("earliest"),
BlockNumber::Pending => serializer.serialize_str("pending"),
}
}
}
struct BlockNumberVisitor; struct BlockNumberVisitor;
impl Visitor for BlockNumberVisitor { impl Visitor for BlockNumberVisitor {

View File

@ -20,7 +20,7 @@ use std::fmt;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use util::log::Colour; use util::log::Colour;
use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes}; use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes, BlockNumber};
use v1::helpers; use v1::helpers;
/// Confirmation waiting in a queue /// Confirmation waiting in a queue
@ -193,6 +193,9 @@ pub struct TransactionModification {
pub gas_price: Option<U256>, pub gas_price: Option<U256>,
/// Modified gas /// Modified gas
pub gas: Option<U256>, pub gas: Option<U256>,
/// Modified min block
#[serde(rename="minBlock")]
pub min_block: Option<Option<BlockNumber>>,
} }
/// Represents two possible return values. /// Represents two possible return values.
@ -234,7 +237,7 @@ impl<A, B> Serialize for Either<A, B> where
mod tests { mod tests {
use std::str::FromStr; use std::str::FromStr;
use serde_json; use serde_json;
use v1::types::{U256, H256}; use v1::types::{U256, H256, BlockNumber};
use v1::helpers; use v1::helpers;
use super::*; use super::*;
@ -267,12 +270,13 @@ mod tests {
value: 100_000.into(), value: 100_000.into(),
data: vec![1, 2, 3], data: vec![1, 2, 3],
nonce: Some(1.into()), nonce: Some(1.into()),
min_block: None,
}), }),
}; };
// when // when
let res = serde_json::to_string(&ConfirmationRequest::from(request)); let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","minBlock":null}}}"#;
// then // then
assert_eq!(res.unwrap(), expected.to_owned()); assert_eq!(res.unwrap(), expected.to_owned());
@ -291,12 +295,13 @@ mod tests {
value: 100_000.into(), value: 100_000.into(),
data: vec![1, 2, 3], data: vec![1, 2, 3],
nonce: Some(1.into()), nonce: Some(1.into()),
min_block: None,
}), }),
}; };
// when // when
let res = serde_json::to_string(&ConfirmationRequest::from(request)); let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","minBlock":null}}}"#;
// then // then
assert_eq!(res.unwrap(), expected.to_owned()); assert_eq!(res.unwrap(), expected.to_owned());
@ -324,7 +329,8 @@ mod tests {
fn should_deserialize_modification() { fn should_deserialize_modification() {
// given // given
let s1 = r#"{ let s1 = r#"{
"gasPrice":"0xba43b7400" "gasPrice":"0xba43b7400",
"minBlock":"0x42"
}"#; }"#;
let s2 = r#"{"gas": "0x1233"}"#; let s2 = r#"{"gas": "0x1233"}"#;
let s3 = r#"{}"#; let s3 = r#"{}"#;
@ -338,14 +344,17 @@ mod tests {
assert_eq!(res1, TransactionModification { assert_eq!(res1, TransactionModification {
gas_price: Some(U256::from_str("0ba43b7400").unwrap()), gas_price: Some(U256::from_str("0ba43b7400").unwrap()),
gas: None, gas: None,
min_block: Some(Some(BlockNumber::Num(0x42))),
}); });
assert_eq!(res2, TransactionModification { assert_eq!(res2, TransactionModification {
gas_price: None, gas_price: None,
gas: Some(U256::from_str("1233").unwrap()), gas: Some(U256::from_str("1233").unwrap()),
min_block: None,
}); });
assert_eq!(res3, TransactionModification { assert_eq!(res3, TransactionModification {
gas_price: None, gas_price: None,
gas: None, gas: None,
min_block: None,
}); });
} }

View File

@ -17,9 +17,9 @@
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use ethcore::miner; use ethcore::miner;
use ethcore::contract_address; use ethcore::contract_address;
use ethcore::transaction::{LocalizedTransaction, Action, SignedTransaction}; use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction};
use v1::helpers::errors; use v1::helpers::errors;
use v1::types::{Bytes, H160, H256, U256, H512}; use v1::types::{Bytes, H160, H256, U256, H512, BlockNumber};
/// Transaction /// Transaction
#[derive(Debug, Default, Clone, PartialEq, Serialize)] #[derive(Debug, Default, Clone, PartialEq, Serialize)]
@ -69,6 +69,9 @@ pub struct Transaction {
pub r: U256, pub r: U256,
/// The S field of the signature. /// The S field of the signature.
pub s: U256, pub s: U256,
/// Transaction activates at specified block.
#[serde(rename="minBlock")]
pub min_block: Option<BlockNumber>,
} }
/// Local Transaction Status /// Local Transaction Status
@ -187,6 +190,7 @@ impl From<LocalizedTransaction> for Transaction {
v: t.original_v().into(), v: t.original_v().into(),
r: signature.r().into(), r: signature.r().into(),
s: signature.s().into(), s: signature.s().into(),
min_block: None,
} }
} }
} }
@ -220,10 +224,19 @@ impl From<SignedTransaction> for Transaction {
v: t.original_v().into(), v: t.original_v().into(),
r: signature.r().into(), r: signature.r().into(),
s: signature.s().into(), s: signature.s().into(),
min_block: None,
} }
} }
} }
impl From<PendingTransaction> for Transaction {
fn from(t: PendingTransaction) -> Transaction {
let mut r = Transaction::from(t.transaction);
r.min_block = t.min_block.map(|b| BlockNumber::Num(b));
r
}
}
impl From<miner::LocalTransactionStatus> for LocalTransactionStatus { impl From<miner::LocalTransactionStatus> for LocalTransactionStatus {
fn from(s: miner::LocalTransactionStatus) -> Self { fn from(s: miner::LocalTransactionStatus) -> Self {
use ethcore::miner::LocalTransactionStatus::*; use ethcore::miner::LocalTransactionStatus::*;
@ -248,7 +261,7 @@ mod tests {
fn test_transaction_serialize() { fn test_transaction_serialize() {
let t = Transaction::default(); let t = Transaction::default();
let serialized = serde_json::to_string(&t).unwrap(); let serialized = serde_json::to_string(&t).unwrap();
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}"#); assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","minBlock":null}"#);
} }
#[test] #[test]

View File

@ -16,7 +16,7 @@
//! `TransactionRequest` type //! `TransactionRequest` type
use v1::types::{Bytes, H160, U256}; use v1::types::{Bytes, H160, U256, BlockNumber};
use v1::helpers; use v1::helpers;
use util::log::Colour; use util::log::Colour;
@ -41,6 +41,9 @@ pub struct TransactionRequest {
pub data: Option<Bytes>, pub data: Option<Bytes>,
/// Transaction's nonce /// Transaction's nonce
pub nonce: Option<U256>, pub nonce: Option<U256>,
/// Delay until this block if specified.
#[serde(rename="minBlock")]
pub min_block: Option<BlockNumber>,
} }
pub fn format_ether(i: U256) -> String { pub fn format_ether(i: U256) -> String {
@ -90,6 +93,7 @@ impl From<helpers::TransactionRequest> for TransactionRequest {
value: r.value.map(Into::into), value: r.value.map(Into::into),
data: r.data.map(Into::into), data: r.data.map(Into::into),
nonce: r.nonce.map(Into::into), nonce: r.nonce.map(Into::into),
min_block: r.min_block.map(|b| BlockNumber::Num(b)),
} }
} }
} }
@ -104,6 +108,7 @@ impl From<helpers::FilledTransactionRequest> for TransactionRequest {
value: Some(r.value.into()), value: Some(r.value.into()),
data: Some(r.data.into()), data: Some(r.data.into()),
nonce: r.nonce.map(Into::into), nonce: r.nonce.map(Into::into),
min_block: r.min_block.map(|b| BlockNumber::Num(b)),
} }
} }
} }
@ -118,6 +123,7 @@ impl Into<helpers::TransactionRequest> for TransactionRequest {
value: self.value.map(Into::into), value: self.value.map(Into::into),
data: self.data.map(Into::into), data: self.data.map(Into::into),
nonce: self.nonce.map(Into::into), nonce: self.nonce.map(Into::into),
min_block: self.min_block.and_then(|b| b.to_min_block_num()),
} }
} }
} }
@ -128,7 +134,7 @@ mod tests {
use std::str::FromStr; use std::str::FromStr;
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use serde_json; use serde_json;
use v1::types::{U256, H160}; use v1::types::{U256, H160, BlockNumber};
use super::*; use super::*;
#[test] #[test]
@ -140,7 +146,8 @@ mod tests {
"gas":"0x2", "gas":"0x2",
"value":"0x3", "value":"0x3",
"data":"0x123456", "data":"0x123456",
"nonce":"0x4" "nonce":"0x4",
"minBlock":"0x13"
}"#; }"#;
let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); let deserialized: TransactionRequest = serde_json::from_str(s).unwrap();
@ -152,6 +159,7 @@ mod tests {
value: Some(U256::from(3)), value: Some(U256::from(3)),
data: Some(vec![0x12, 0x34, 0x56].into()), data: Some(vec![0x12, 0x34, 0x56].into()),
nonce: Some(U256::from(4)), nonce: Some(U256::from(4)),
min_block: Some(BlockNumber::Num(0x13)),
}); });
} }
@ -174,7 +182,8 @@ mod tests {
gas: Some(U256::from_str("76c0").unwrap()), gas: Some(U256::from_str("76c0").unwrap()),
value: Some(U256::from_str("9184e72a").unwrap()), value: Some(U256::from_str("9184e72a").unwrap()),
data: Some("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675".from_hex().unwrap().into()), data: Some("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675".from_hex().unwrap().into()),
nonce: None nonce: None,
min_block: None,
}); });
} }
@ -191,6 +200,7 @@ mod tests {
value: None, value: None,
data: None, data: None,
nonce: None, nonce: None,
min_block: None,
}); });
} }
@ -214,6 +224,7 @@ mod tests {
value: None, value: None,
data: Some(vec![0x85, 0x95, 0xba, 0xb1].into()), data: Some(vec![0x85, 0x95, 0xba, 0xb1].into()),
nonce: None, nonce: None,
min_block: None,
}); });
} }

View File

@ -91,7 +91,7 @@ fn list_transactions(signer: &mut SignerRpc) -> Result<String, String> {
fn sign_transaction( fn sign_transaction(
signer: &mut SignerRpc, id: U256, password: &str signer: &mut SignerRpc, id: U256, password: &str
) -> Result<String, String> { ) -> Result<String, String> {
try!(signer.confirm_request(id, None, None, password).map(|res| { try!(signer.confirm_request(id, None, None, None, password).map(|res| {
match res { match res {
Ok(u) => Ok(format!("Signed transaction id: {:#x}", u)), Ok(u) => Ok(format!("Signed transaction id: {:#x}", u)),
Err(e) => Err(format!("{:?}", e)), Err(e) => Err(format!("{:?}", e)),

View File

@ -8,7 +8,6 @@ version = "1.4.0"
[dependencies] [dependencies]
futures = "0.1" futures = "0.1"
jsonrpc-core = "3.0.2"
lazy_static = "0.2.1" lazy_static = "0.2.1"
log = "0.3.6" log = "0.3.6"
matches = "0.1.2" matches = "0.1.2"
@ -17,6 +16,7 @@ serde = "0.8"
serde_json = "0.8" serde_json = "0.8"
tempdir = "0.3.5" tempdir = "0.3.5"
url = "1.2.0" url = "1.2.0"
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "mio-upstream-stable" } ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "mio-upstream-stable" }
ethcore-rpc = { path = "../rpc" } ethcore-rpc = { path = "../rpc" }
ethcore-signer = { path = "../signer" } ethcore-signer = { path = "../signer" }

View File

@ -36,7 +36,7 @@ use futures::{BoxFuture, Canceled, Complete, Future, oneshot, done};
use jsonrpc_core::{Id, Version, Params, Error as JsonRpcError}; use jsonrpc_core::{Id, Version, Params, Error as JsonRpcError};
use jsonrpc_core::request::MethodCall; use jsonrpc_core::request::MethodCall;
use jsonrpc_core::response::{SyncOutput, Success, Failure}; use jsonrpc_core::response::{Output, Success, Failure};
/// The actual websocket connection handler, passed into the /// The actual websocket connection handler, passed into the
/// event loop of ws-rs /// event loop of ws-rs
@ -107,13 +107,13 @@ impl Handler for RpcHandler {
let ret: Result<JsonValue, JsonRpcError>; let ret: Result<JsonValue, JsonRpcError>;
let response_id; let response_id;
let string = &msg.to_string(); let string = &msg.to_string();
match json::from_str::<SyncOutput>(&string) { match json::from_str::<Output>(&string) {
Ok(SyncOutput::Success(Success { result, id: Id::Num(id), .. })) => Ok(Output::Success(Success { result, id: Id::Num(id), .. })) =>
{ {
ret = Ok(result); ret = Ok(result);
response_id = id as usize; response_id = id as usize;
} }
Ok(SyncOutput::Failure(Failure { error, id: Id::Num(id), .. })) => { Ok(Output::Failure(Failure { error, id: Id::Num(id), .. })) => {
ret = Err(error); ret = Err(error);
response_id = id as usize; response_id = id as usize;
} }

View File

@ -1,7 +1,5 @@
use client::{Rpc, RpcError}; use client::{Rpc, RpcError};
use rpc::v1::types::{ConfirmationRequest, use rpc::v1::types::{ConfirmationRequest, TransactionModification, U256, BlockNumber};
TransactionModification,
U256};
use serde_json::{Value as JsonValue, to_value}; use serde_json::{Value as JsonValue, to_value};
use std::path::PathBuf; use std::path::PathBuf;
use futures::{BoxFuture, Canceled}; use futures::{BoxFuture, Canceled};
@ -24,12 +22,13 @@ impl SignerRpc {
id: U256, id: U256,
new_gas: Option<U256>, new_gas: Option<U256>,
new_gas_price: Option<U256>, new_gas_price: Option<U256>,
new_min_block: Option<Option<BlockNumber>>,
pwd: &str pwd: &str
) -> BoxFuture<Result<U256, RpcError>, Canceled> ) -> BoxFuture<Result<U256, RpcError>, Canceled>
{ {
self.rpc.request("signer_confirmRequest", vec![ self.rpc.request("signer_confirmRequest", vec![
to_value(&format!("{:#x}", id)), to_value(&format!("{:#x}", id)),
to_value(&TransactionModification { gas_price: new_gas_price, gas: new_gas }), to_value(&TransactionModification { gas_price: new_gas_price, gas: new_gas, min_block: new_min_block }),
to_value(&pwd), to_value(&pwd),
]) ])
} }

View File

@ -1919,15 +1919,15 @@ impl ChainSync {
return 0; return 0;
} }
let transactions = io.chain().pending_transactions(); let transactions = io.chain().ready_transactions();
if transactions.is_empty() { if transactions.is_empty() {
return 0; return 0;
} }
let all_transactions_hashes = transactions.iter().map(|tx| tx.hash()).collect::<HashSet<H256>>(); let all_transactions_hashes = transactions.iter().map(|tx| tx.transaction.hash()).collect::<HashSet<H256>>();
let all_transactions_rlp = { let all_transactions_rlp = {
let mut packet = RlpStream::new_list(transactions.len()); let mut packet = RlpStream::new_list(transactions.len());
for tx in &transactions { packet.append(tx); } for tx in &transactions { packet.append(&tx.transaction); }
packet.out() packet.out()
}; };
@ -1965,11 +1965,11 @@ impl ChainSync {
// Construct RLP // Construct RLP
let mut packet = RlpStream::new_list(to_send.len()); let mut packet = RlpStream::new_list(to_send.len());
for tx in &transactions { for tx in &transactions {
if to_send.contains(&tx.hash()) { if to_send.contains(&tx.transaction.hash()) {
packet.append(tx); packet.append(&tx.transaction);
// update stats // update stats
let id = io.peer_session_info(*peer_id).and_then(|info| info.id); let id = io.peer_session_info(*peer_id).and_then(|info| info.id);
stats.propagated(tx.hash(), id, block_number); stats.propagated(tx.transaction.hash(), id, block_number);
} }
} }

View File

@ -44,15 +44,16 @@ impl IoHandler<ClientIoMessage> for TestIoHandler {
} }
} }
fn new_tx(secret: &H256, nonce: U256) -> SignedTransaction { fn new_tx(secret: &H256, nonce: U256) -> PendingTransaction {
Transaction { let signed = Transaction {
nonce: nonce.into(), nonce: nonce.into(),
gas_price: 0.into(), gas_price: 0.into(),
gas: 21000.into(), gas: 21000.into(),
action: Action::Call(Address::default()), action: Action::Call(Address::default()),
value: 0.into(), value: 0.into(),
data: Vec::new(), data: Vec::new(),
}.sign(secret, None) }.sign(secret, None);
PendingTransaction::new(signed, None)
} }
#[test] #[test]

View File

@ -18,6 +18,7 @@ ethcore-util = { path = "../util" }
parity-hash-fetch = { path = "../hash-fetch" } parity-hash-fetch = { path = "../hash-fetch" }
ipc-common-types = { path = "../ipc-common-types" } ipc-common-types = { path = "../ipc-common-types" }
ethcore-ipc = { path = "../ipc/rpc" } ethcore-ipc = { path = "../ipc/rpc" }
target_info = "0.1"
[profile.release] [profile.release]
debug = true debug = true

View File

@ -24,6 +24,7 @@ extern crate ethcore;
extern crate ethabi; extern crate ethabi;
extern crate ethsync; extern crate ethsync;
extern crate ethcore_ipc as ipc; extern crate ethcore_ipc as ipc;
extern crate target_info;
mod updater; mod updater;
mod operations; mod operations;

View File

@ -18,8 +18,10 @@ use std::sync::{Arc, Weak};
use std::fs; use std::fs;
use std::io::Write; use std::io::Write;
use std::path::{PathBuf}; use std::path::{PathBuf};
use util::misc::platform; use target_info::Target;
use util::misc;
use ipc_common_types::{VersionInfo, ReleaseTrack}; use ipc_common_types::{VersionInfo, ReleaseTrack};
use util::path::restrict_permissions_owner;
use util::{Address, H160, H256, FixedHash, Mutex, Bytes}; use util::{Address, H160, H256, FixedHash, Mutex, Bytes};
use ethsync::{SyncProvider}; use ethsync::{SyncProvider};
use ethcore::client::{BlockId, BlockChainClient, ChainNotify}; use ethcore::client::{BlockId, BlockChainClient, ChainNotify};
@ -97,6 +99,18 @@ pub struct Updater {
const CLIENT_ID: &'static str = "parity"; const CLIENT_ID: &'static str = "parity";
fn platform() -> String {
if cfg!(target_os = "macos") {
"x86_64-apple-darwin".into()
} else if cfg!(windows) {
"x86_64-pc-windows-msvc".into()
} else if cfg!(target_os = "linux") {
format!("{}-unknown-linux-gnu", Target::arch())
} else {
misc::platform()
}
}
impl Updater { impl Updater {
pub fn new(client: Weak<BlockChainClient>, sync: Weak<SyncProvider>, update_policy: UpdatePolicy) -> Arc<Self> { pub fn new(client: Weak<BlockChainClient>, sync: Weak<SyncProvider>, update_policy: UpdatePolicy) -> Arc<Self> {
let r = Arc::new(Updater { let r = Arc::new(Updater {
@ -197,7 +211,8 @@ impl Updater {
let dest = self.updates_path(&Self::update_file_name(&fetched.version)); let dest = self.updates_path(&Self::update_file_name(&fetched.version));
fs::create_dir_all(dest.parent().expect("at least one thing pushed; qed")).map_err(|e| format!("Unable to create updates path: {:?}", e))?; fs::create_dir_all(dest.parent().expect("at least one thing pushed; qed")).map_err(|e| format!("Unable to create updates path: {:?}", e))?;
fs::copy(&b, &dest).map_err(|e| format!("Unable to copy update: {:?}", e))?; fs::copy(&b, &dest).map_err(|e| format!("Unable to copy update: {:?}", e))?;
info!(target: "updater", "Copied file to {}", dest.display()); restrict_permissions_owner(&dest, false, true).map_err(|e| format!("Unable to update permissions: {}", e))?;
info!(target: "updater", "Installed updated binary to {}", dest.display());
let auto = match self.update_policy.filter { let auto = match self.update_policy.filter {
UpdateFilter::All => true, UpdateFilter::All => true,
UpdateFilter::Critical if fetched.is_critical /* TODO: or is on a bad fork */ => true, UpdateFilter::Critical if fetched.is_critical /* TODO: or is on a bad fork */ => true,
@ -241,7 +256,7 @@ impl Updater {
trace!(target: "updater", "Latest release in our track is v{} it is {}critical ({} binary is {})", trace!(target: "updater", "Latest release in our track is v{} it is {}critical ({} binary is {})",
latest.track.version, latest.track.version,
if latest.track.is_critical {""} else {"non-"}, if latest.track.is_critical {""} else {"non-"},
platform(), &platform(),
if let Some(ref b) = latest.track.binary { if let Some(ref b) = latest.track.binary {
format!("{}", b) format!("{}", b)
} else { } else {

View File

@ -41,6 +41,7 @@ lru-cache = "0.1.0"
[features] [features]
default = [] default = []
dev = ["clippy"] dev = ["clippy"]
final = []
[build-dependencies] [build-dependencies]
vergen = "*" vergen = "*"

View File

@ -1168,8 +1168,8 @@ fn save_key(path: &Path, key: &Secret) {
return; return;
} }
}; };
if let Err(e) = restrict_permissions_owner(path) { if let Err(e) = restrict_permissions_owner(path, true, false) {
warn!(target: "network", "Failed to modify permissions of the file (chmod: {})", e); warn!(target: "network", "Failed to modify permissions of the file ({})", e);
} }
if let Err(e) = file.write(&key.hex().into_bytes()) { if let Err(e) = file.write(&key.hex().into_bytes()) {
warn!("Error writing key file: {:?}", e); warn!("Error writing key file: {:?}", e);

View File

@ -23,6 +23,14 @@ use target_info::Target;
include!(concat!(env!("OUT_DIR"), "/version.rs")); include!(concat!(env!("OUT_DIR"), "/version.rs"));
include!(concat!(env!("OUT_DIR"), "/rustc_version.rs")); include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
#[cfg(feature = "final")]
const THIS_TRACK: &'static str = "nightly";
// ^^^ should be reset to "stable" or "beta" according to the release branch.
#[cfg(not(feature = "final"))]
const THIS_TRACK: &'static str = "unstable";
// ^^^ This gets used when we're not building a final release; should stay as "unstable".
/// Boolean type for clean/dirty status. /// Boolean type for clean/dirty status.
#[derive(PartialEq, Eq, Clone, Copy, Debug)] #[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Filth { pub enum Filth {
@ -45,7 +53,7 @@ pub fn version() -> String {
let sha3_dash = if sha3.is_empty() { "" } else { "-" }; let sha3_dash = if sha3.is_empty() { "" } else { "-" };
let commit_date = commit_date().replace("-", ""); let commit_date = commit_date().replace("-", "");
let date_dash = if commit_date.is_empty() { "" } else { "-" }; let date_dash = if commit_date.is_empty() { "" } else { "-" };
format!("Parity/v{}-unstable{}{}{}{}/{}/rustc{}", env!("CARGO_PKG_VERSION"), sha3_dash, sha3, date_dash, commit_date, platform(), rustc_version()) format!("Parity/v{}-{}{}{}{}{}/{}/rustc{}", env!("CARGO_PKG_VERSION"), THIS_TRACK, sha3_dash, sha3, date_dash, commit_date, platform(), rustc_version())
} }
/// Get the standard version data for this software. /// Get the standard version data for this software.
@ -64,5 +72,5 @@ pub fn version_data() -> Bytes {
/// Provide raw information on the package. /// Provide raw information on the package.
pub fn raw_package_info() -> (&'static str, &'static str, &'static str) { pub fn raw_package_info() -> (&'static str, &'static str, &'static str) {
(env!["CARGO_PKG_VERSION_PRE"], env!["CARGO_PKG_VERSION"], sha()) (THIS_TRACK, env!["CARGO_PKG_VERSION"], sha())
} }

View File

@ -86,18 +86,15 @@ pub mod ethereum {
} }
/// Restricts the permissions of given path only to the owner. /// Restricts the permissions of given path only to the owner.
#[cfg(not(windows))] #[cfg(unix)]
pub fn restrict_permissions_owner(file_path: &Path) -> Result<(), i32> { pub fn restrict_permissions_owner(file_path: &Path, write: bool, executable: bool) -> Result<(), String> {
let cstr = ::std::ffi::CString::new(file_path.to_str().unwrap()).unwrap(); let perms = ::std::os::unix::fs::PermissionsExt::from_mode(0o400 + write as u32 * 0o200 + executable as u32 * 0o100);
match unsafe { ::libc::chmod(cstr.as_ptr(), ::libc::S_IWUSR | ::libc::S_IRUSR) } { ::std::fs::set_permissions(file_path, perms).map_err(|e| format!("{:?}", e))
0 => Ok(()),
x => Err(x),
}
} }
/// Restricts the permissions of given path only to the owner. /// Restricts the permissions of given path only to the owner.
#[cfg(windows)] #[cfg(not(unix))]
pub fn restrict_permissions_owner(_file_path: &Path) -> Result<(), i32> { pub fn restrict_permissions_owner(_file_path: &Path, _write: bool, _executable: bool) -> Result<(), String> {
//TODO: implement me //TODO: implement me
Ok(()) Ok(())
} }