Compare commits

...

10 Commits

Author SHA1 Message Date
Afri Schoedon
7b1d3e180c Backports for Stable 2.2.10 (#10332)
* version: bump stable to 2.2.10

* import rpc transactions sequentially (#10051)

* import rpc transactions sequentially

* use impl trait in argument position, renamed ProspectiveDispatcher to WithPostSign

* grouped imports

* integrates PostSign with ProspectiveSigner

* fix spaces, removed unnecessary type cast and duplicate polling

* clean up code style

* Apply suggestions from code review

* Additional tests for uint deserialization. (#10279)

* Don't run the CPP example on CI (#10285)

* Don't run the CPP example on CI

* Add comment

* CI optimizations (#10297)

* CI optimizations

* fix stripping

* new dockerfile

* no need n submodule upd

* review

* moved dockerfile

* it becomes large

* onchain update depends on s3

* fix dependency

* fix cache status

* fix cache status

* new cache status

* fix publish job (#10317)

* fix publish job

* dashes and colonels

* Add Statetest support for Constantinople Fix (#10323)

* Update Ethereum tests repo to v6.0.0-beta.3 tag

* Add spec for St.Peter's / ConstantinopleFix statetests

* fix(add helper for timestamp overflows) (#10330)

* fix(add helper timestamp overflows)

* fix(simplify code)

* fix(make helper private)

* fix(docker): fix not receives SIGINT (#10059)

* fix(docker): fix not receives SIGINT

* fix: update with reviews

* update with review

* update

* update

* snap: official image / test (#10168)

* official image / test

* fix / test

* bit more necromancy

* fix paths

* add source bin/df /test

* add source bin/df /test2

* something w paths /test

* something w paths /test

* add source-type /test

* show paths /test

* copy plugin /test

* plugin -> nil

* install rhash

* no questions while installing rhash

* publish snap only for release

* Don't add discovery initiators to the node table (#10305)

* Don't add discovery initiators to the node table

* Use enums for tracking state of the nodes in discovery

* Dont try to ping ourselves

* Fix minor nits

* Update timeouts when observing an outdated node

* Extracted update_bucket_record from update_node

* Fixed typo

* Fix two final nits from @todr

* change docker image based on debian instead of ubuntu due to the chan… (#10336)

* change docker image based on debian instead of ubuntu due to the changes of the build container

* role back docker build image and docker deploy image to ubuntu:xenial based (#10338)

* perform stripping during build (#10208)

* perform stripping during build (#10208)

* perform stripping during build

* var RUSTFLAGS

* fix(docker-aarch64) : cross-compile config (#9798)

* fix(docker-aarch64) : cross-compile config (#9798)

* ci: remove trailing double newline from dockerfile
2019-02-13 11:00:15 +01:00
Kirill Pimenov
cc91e95f03 Additional error for invalid gas (#10327) (#10329)
* Tag sensible place (ECHECH)

* Additional overflows checks.
2019-02-12 10:53:01 +01:00
Afri Schoedon
5d5b372f44 version: bump stable to 2.2.9 (#10282) 2019-02-03 12:44:08 +01:00
Kirill Pimenov
abb41f60f4 Additional tests for uint deserialization. (#10281) 2019-02-03 12:43:13 +01:00
Afri Schoedon
ec81d67009 Stable: Macos heapsize force jemalloc (#10234) (#10258)
* Macos heapsize force jemalloc (#10234)

* Switch to non prefixed malloc_size_of on macos

* Fix

* Testing darwin build

* Fix import

* conflict

* switch heapsize deps commit

* switch heapsize commit

* Rename branch

* Restore gitlab ci to origin

* test for mac

* mac tests?

* Switch of macos CI tests.

* Update Cargo.lock

Co-Authored-By: 5chdn <5chdn@users.noreply.github.com>
2019-01-30 12:01:55 +01:00
Afri Schoedon
2a7dc644b7 Stable Backports 2.2.8 (#10224)
* version: bump stable to 2.2.8

* Update for Android cross-compilation. (#10180)

* build-unix update

* .gitlab-ci update

* Update build-unix.sh

add android postprocessing

* path to android lib

libparity.so

* fix path to libparity

* add android lib to artifacts

* Cancel Constantinople HF on POA Core (#10198)

* Add EIP-1283 disable transition (#10214)

* Enable St-Peters-Fork ("Constantinople Fix") (#10223)

* ethcore: disable eip-1283 on kovan block 10255201

* ethcore: disable eip-1283 on ropsten block 4939394

* ethcore: enable st-peters-fork on mainnet block 7280000

* ethcore: fix kovan chain spec

* version: update fork blocks

* ethcore: disable eip-1283 on sokol block 7026400
2019-01-22 12:32:56 +01:00
Afri Schoedon
b00a21f39a backports for stable 2.2.7 (#10163)
* version: bump stable to 2.2.7

* version: mark 2.2 track stable

* version: mark update critical on all networks

* version: commit cargo lock

* Ping nodes from discovery (#10167)

* snap: fix path in script (#10157)

* snap: fix path in script

* debug, revert me

* fix

* necromancer awk magic

* awk necromancy and path fixing

* working track selection

* Fix _cannot recursively call into `Core`_ issue (#10144)

* Change igd to github:maufl/rust-igd

* Run `igd::search_gateway_from_timeout` from own thread

* Handle the case for contract creation on an empty but exist account with storage items (#10065)

* Add is_base_storage_root_unchanged

* Fix compile, use a shortcut for check, and remove ignored tests

* Add a warn!

* Update ethereum/tests to v6.0.0-beta.2

* grumble: use {:#x} instead of 0x{:x}

Co-Authored-By: sorpaas <accounts@that.world>

* version: bump fork blocks for kovan and foundation (#10186)

* pull constantinople on ethereum network (#10189)

* ethcore: pull constantinople on ethereum network

* version: mark update as critical

* ethcore: remove constantinople alltogether from chain spec

* version: revert fork block for ethereum
2019-01-15 22:25:31 +01:00
Afri Schoedon
e9396e158b beta backports v2.2.6 (#10113)
* version: bump beta to v2.2.6

* Update pwasm-utils to 0.6.1 (#10134)

* version: mark upgrade critical on kovan

* Identity fix (#10128)

* fix #10125

fix service transaction version detection if --identity is enabled, change test to match how --identity actually works

* fix wrong var

* get the index of  v, not /

* idx, not idx.len()

* Update ethcore/sync/src/chain/propagator.rs

Co-Authored-By: joshua-mir <43032097+joshua-mir@users.noreply.github.com>

* Update ethcore/sync/src/chain/propagator.rs

Co-Authored-By: joshua-mir <43032097+joshua-mir@users.noreply.github.com>

* change version prefix to a const

* space

Co-Authored-By: joshua-mir <43032097+joshua-mir@users.noreply.github.com>

* [Hit return to continue]

* ethcore: update hardcoded headers for foundation

* ethcore: update hardcoded headers for ropsten

* ethcore: update hardcoded headers for kovan

* ethcore: use consistant formatting

* ethcore: restore spaces after colon in chain spec

* ethcore: fix bootnodes in chain specs

* ethcore: fix bootnodes in chain specs

* ethcore: enforce newline at the end of chainspecs

* Follow-up to #10105 (#10107)

* HF in POA Sokol (2019-01-04) (#10077)

* HF in POA Sokol (2019-01-04)

https://github.com/poanetwork/poa-chain-spec/pull/91

* Update POA Core bootnodes

* Autogen docs for the "Configuring Parity Ethereum" wiki page. (#10067)

* publish docs changes for autogen config docs

* Update publish-docs.sh

adding an environment variable so js knows not to download git master and just grab the local repo

* Update publish-docs.sh

made some changes making this unnecessary

* fix env variable

env variable passes to node properly now

* use yarn

* test pipeline, revert me

* fix test pipeline, revert me

* change runner tag

* change runner tag 2

* change runner tag

* global git config

* supress upload_files output

* Update .gitlab-ci.yml

reverting testing changes

* Replace tag if exists

Very unlikely to be important/useful

* Autogen docs for the "Configuring Parity Ethereum" wiki page. (#10067)

* publish docs changes for autogen config docs

* Update publish-docs.sh

adding an environment variable so js knows not to download git master and just grab the local repo

* Update publish-docs.sh

made some changes making this unnecessary

* fix env variable

env variable passes to node properly now

* use yarn

* test pipeline, revert me

* fix test pipeline, revert me

* change runner tag

* change runner tag 2

* change runner tag

* global git config

* supress upload_files output

* Update .gitlab-ci.yml

reverting testing changes

* Replace tag if exists

Very unlikely to be important/useful

* finality: dont require chain head to be in the chain (#10054)

* Fill transaction hash on ethGetLog of light client. (#9938)

* Fill transaction hash on ethGetLog of light client. This is enifficient
but we keep align with spec.

* Using better variables names.

* Expose old fast light get log as `parity_getLogsLight`.

* Update rpc/src/v1/helpers/light_fetch.rs

Fix indent.

Co-Authored-By: cheme <emericchevalier.pro@gmail.com>

* Factor common code between light_logs and logs.

* Remove useless check

* Rename parity light logs to 'parity_getLogsNoTransactionHash'.
Fix indent and extra white lines.

* Use vec instead of tree map to avoid inner function.

* better loop

* fix pubsub new_blocks notifications to include all blocks (#9987)

Fix: new blocks notifications sometimes missing in pubsub RPC

Implement new struct to pass to `new_blocks()` with extra parameter - `has_more_blocks_to_import`, which was previously used to determine whether the notification should be sent. Now it's up to each implementation to decide what to do.

Updated all implementations to behave as before, except `eth_pubsub`, which will send notification even when the queue is not empty.

Update tests.

* Revert part of 70a6db7

* HF in POA Core (2019-01-18) - Constantinople (#10155)

https://github.com/poanetwork/poa-chain-spec/pull/100

* ci: re-enable snap publishing (#10142)

* ci: enable snap publishing~

* ci: add publish snap script

* ci: add snapcraft skeleton

* ci: group export statements

* ci: enable snaps on pr branch

* ci: enable snaps on pr branch

* ci: set default BUILD_ARCH

* ci: enable snaps on pr branch

* ci: enable snaps on pr branch

* ci: add libdb to snap

* ci: reinitiate gitlabci

* ci: reinitiate publish-snap script

* ci: fix yaml syntax

* cargo/gitlab env vars

* debug, revert me

* version?

* debug vars

* vars

* vars fix

* vars fix

* revert

* Update scripts/gitlab/publish-snap.sh

Co-Authored-By: 5chdn <5chdn@users.noreply.github.com>

* ci: read track from cargo toml

* Make sure parent block is not in importing queue when importing ancient blocks (#10138)

* Make sure parent block is not in importing queue when importing ancient blocks

* Clear queue when an ancient import fails

* Lock only once in clear

* Add comments why queued check is needed

* Should push the value back to the queue

* Directly check in chain.read()

* Remove extra empty line

* Revert unused verification change
2019-01-09 15:15:57 +01:00
Thibaut Sardan
7fbcdfeed4 Backports for beta 2.2.5 (#10047)
* bump beta to 2.2.5

* Fix empty steps (#9939)

* Don't send empty step twice or empty step then block.

* Perform basic validation of locally sealed blocks.

* Don't include empty step twice.

* Strict empty steps validation (#10041)

* Add two failings tests for strict empty steps.

* Implement strict validation of empty steps.

* ethcore: enable constantinople on ethereum (#10031)

* ethcore: change blockreward to 2e18 for foundation after constantinople

* ethcore: delay diff bomb by 2e6 blocks for foundation after constantinople

* ethcore: enable eip-{145,1014,1052,1283} for foundation after constantinople

* Change test miner max memory to malloc reports. (#10024)

* Fix: test corpus_inaccessible panic (#10019)

If system uptime is less than the duration in the test, thread
will panic due to: 'overflow when subtracting duration from instant'.

Changed duration to 20 seconds to make it unlikely the test will
fail due to this condition.

Since no operations that carry a similar risk of panic occur outside
of the tests, it doesn't seem warranted to depend on an external crate
to fix this.

* Bump crossbeam. (#10048)
2018-12-13 17:52:49 +01:00
Afri Schoedon
f44d885b6d patch beta release pipeline (#10020)
* version: bump beta to 2.2.4

* ci: move future releases to ethereum subdir on s3 (#10017)

* ci: move future releases to ethereum subdir on s3

* ci: redesign s3 bucket logic

* ci: use the releases bucket

* Handle failing case for update account cache in require (#9989)

* state: remove accidently merged test

* state: remove merge leftovers
2018-12-05 16:07:11 +01:00
78 changed files with 21022 additions and 18975 deletions

View File

@@ -2,11 +2,14 @@ stages:
- test
- build
- publish
- publish-onchain
- optional
image: parity/rust:gitlab-ci
variables:
GIT_STRATEGY: fetch
GIT_SUBMODULE_STRATEGY: recursive
CI_SERVER_NAME: "GitLab CI"
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
CARGO_TARGET: x86_64-unknown-linux-gnu
@@ -40,27 +43,29 @@ test-linux:
variables:
RUN_TESTS: all
script:
- scripts/gitlab/test-all.sh stable
- scripts/gitlab/test-all.sh
- sccache -s
tags:
- rust-stable
- linux-docker
test-audit:
stage: test
script:
- scripts/gitlab/cargo-audit.sh
- set -e
- set -u
- cargo audit
tags:
- rust-stable
- linux-docker
build-linux:
stage: build
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-unknown-linux-gnu
script:
- scripts/gitlab/build-unix.sh
- sccache -s
<<: *collect_artifacts
tags:
- rust-stable
- linux-docker
build-darwin:
stage: build
@@ -97,19 +102,83 @@ publish-docker:
script:
- scripts/gitlab/publish-docker.sh parity
publish-awss3:
stage: publish
publish-snap:
stage: optional #publish
only: *releaseable_branches
image: snapcore/snapcraft
variables:
BUILD_ARCH: amd64
cache: {}
before_script: *determine_version
dependencies:
- build-linux
tags:
- rust-stable
script:
- scripts/gitlab/publish-snap.sh
allow_failure: true
<<: *collect_artifacts
publish-onnet-update:
stage: publish-onchain
only: *releaseable_branches
cache: {}
dependencies:
- build-linux
- build-darwin
- build-windows
- publish-awss3-release
before_script: *determine_version
script:
- scripts/gitlab/publish-awss3.sh
- scripts/gitlab/publish-onnet-update.sh
tags:
- shell
- linux-docker
# configures aws for fast uploads/syncs
.s3-before-script: &s3-before-script
before_script:
- mkdir -p ${HOME}/.aws
- |
cat > ${HOME}/.aws/config <<EOC
[default]
s3 =
max_concurrent_requests = 20
max_queue_size = 10000
multipart_threshold = 64MB
multipart_chunksize = 16MB
max_bandwidth = 50MB/s
use_accelerate_endpoint = false
addressing_style = path
EOC
publish-awss3-release:
image: parity/awscli:latest
stage: publish
only: *releaseable_branches
cache: {}
dependencies:
- build-linux
- build-darwin
- build-windows
variables:
GIT_STRATEGY: none
<<: *s3-before-script
script:
- echo "__________Push binaries to AWS S3____________"
- case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in
(beta|stable|nightly)
export BUCKET=releases.parity.io/ethereum;
;;
(*)
export BUCKET=builds-parity;
;;
esac
- aws s3 sync ./artifacts s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/
after_script:
- aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/
--recursive --human-readable --summarize
tags:
- linux-docker
publish-docs:
stage: publish
@@ -121,7 +190,7 @@ publish-docs:
script:
- scripts/gitlab/publish-docs.sh
tags:
- shell
- linux-docker
build-android:
stage: optional
@@ -131,25 +200,7 @@ build-android:
script:
- scripts/gitlab/build-unix.sh
tags:
- rust-arm
- linux-docker
allow_failure: true
<<: *collect_artifacts
test-beta:
stage: optional
variables:
RUN_TESTS: cargo
script:
- scripts/gitlab/test-all.sh beta
tags:
- rust-beta
allow_failure: true
test-nightly:
stage: optional
variables:
RUN_TESTS: all
script:
- scripts/gitlab/test-all.sh nightly
tags:
- rust-nightly
allow_failure: true

137
Cargo.lock generated
View File

@@ -276,7 +276,7 @@ version = "0.1.0"
dependencies = [
"ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethjson 0.1.0",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -286,8 +286,26 @@ dependencies = [
[[package]]
name = "crossbeam"
version = "0.3.2"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-channel"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-deque"
@@ -298,6 +316,15 @@ dependencies = [
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-deque"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-deque"
version = "0.6.1"
@@ -334,6 +361,19 @@ dependencies = [
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.2.2"
@@ -347,6 +387,14 @@ name = "crossbeam-utils"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crossbeam-utils"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crunchy"
version = "0.1.6"
@@ -456,7 +504,7 @@ name = "elastic-array"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
]
[[package]]
@@ -566,7 +614,7 @@ dependencies = [
"bn 0.4.4 (git+https://github.com/paritytech/bn)",
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -587,7 +635,7 @@ dependencies = [
"fake-hardware-wallet 0.0.1",
"hardware-wallet 1.12.0",
"hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"journaldb 0.2.0",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -668,7 +716,7 @@ dependencies = [
"fastmap 0.1.0",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hasher 0.1.1",
@@ -721,7 +769,7 @@ dependencies = [
"ethkey 0.3.0",
"fetch 0.1.0",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"hyper 0.12.11 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -770,6 +818,7 @@ dependencies = [
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -806,7 +855,7 @@ dependencies = [
"ethkey 0.3.0",
"fetch 0.1.0",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -915,7 +964,7 @@ dependencies = [
"ethkey 0.3.0",
"fastmap 0.1.0",
"hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hasher 0.1.1",
"kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -939,7 +988,7 @@ dependencies = [
"ethjson 0.1.0",
"ethkey 0.3.0",
"evm 0.1.0",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1061,7 +1110,7 @@ version = "0.1.0"
dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1171,7 +1220,7 @@ name = "fixed-hash"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1198,6 +1247,11 @@ dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fs_extra"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
@@ -1313,8 +1367,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "heapsize"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/cheme/heapsize.git?branch=ec-macfix#421df390a930cb523a09e5528e6fe57b534b3b26"
dependencies = [
"jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1521,6 +1576,25 @@ name = "itoa"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jemalloc-sys"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jemallocator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jni"
version = "0.10.2"
@@ -1547,7 +1621,7 @@ dependencies = [
"ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fastmap 0.1.0",
"hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hasher 0.1.1",
"kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1874,7 +1948,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "memory-cache"
version = "0.1.0"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1889,7 +1963,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"plain_hasher 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2162,7 +2236,7 @@ version = "1.12.0"
dependencies = [
"jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_hook 0.1.0",
"parity-ethereum 2.2.3",
"parity-ethereum 2.2.10",
]
[[package]]
@@ -2178,7 +2252,7 @@ dependencies = [
[[package]]
name = "parity-ethereum"
version = "2.2.3"
version = "2.2.10"
dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2227,7 +2301,7 @@ dependencies = [
"parity-rpc-client 1.4.0",
"parity-runtime 0.1.0",
"parity-updater 1.12.0",
"parity-version 2.2.3",
"parity-version 2.2.10",
"parity-whisper 0.1.0",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2382,7 +2456,7 @@ dependencies = [
"parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-runtime 0.1.0",
"parity-updater 1.12.0",
"parity-version 2.2.3",
"parity-version 2.2.10",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2479,7 +2553,7 @@ dependencies = [
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.12.0",
"parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-version 2.2.3",
"parity-version 2.2.10",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2489,7 +2563,7 @@ dependencies = [
[[package]]
name = "parity-version"
version = "2.2.3"
version = "2.2.10"
dependencies = [
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2755,7 +2829,7 @@ dependencies = [
[[package]]
name = "pwasm-utils"
version = "0.2.2"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3697,7 +3771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)",
"rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3889,7 +3963,7 @@ dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
"pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pwasm-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
"wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -4067,13 +4141,17 @@ dependencies = [
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a"
"checksum combine 3.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc1d011beeed29187b8db2ac3925c8dd4d3e87db463dc9d2d2833985388fc5bc"
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
"checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650"
"checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
"checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a"
"checksum crossbeam-deque 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3486aefc4c0487b9cb52372c97df0a48b8c249514af1ee99703bf70d2f2ceda1"
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9"
"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2"
"checksum ct-logs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95a4bf5107667e12bf6ce31a3a5066d67acc88942b6742117a41198734aaccaa"
@@ -4103,6 +4181,7 @@ dependencies = [
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "921d332c89b3b61a826de38c61ee5b6e02c56806cade1b0e5d81bd71f57a71bb"
"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
@@ -4115,7 +4194,7 @@ dependencies = [
"checksum h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a27e7ed946e8335bdf9a191bc1b9b14a03ba822d013d2f58437f4fabcbd7fc2c"
"checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1"
"checksum hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d91261ee336dd046ac7df28306cb297b7a7228bd1ae25e9a57f4ed5e0ab628c7"
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
"checksum heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)" = "<none>"
"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
"checksum hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)" = "<none>"
@@ -4137,6 +4216,8 @@ dependencies = [
"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc"
"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae"
"checksum jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0cd42ac65f758063fea55126b0148b1ce0a6354ff78e07a4d6806bc65c4ab3"
"checksum jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1ecfa3b81afc64d9a6539c4eece96ac9a93c551c713a313800dade8e33d7b5c1"
"checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
"checksum jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "<none>"
@@ -4227,7 +4308,7 @@ dependencies = [
"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee"
"checksum protobuf 1.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "52fbc45bf6709565e44ef31847eb7407b3c3c80af811ee884a04da071dcca12b"
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
"checksum pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "90d2b3c5bf24275fc77db6b14ec00a7a085d8ff9d1c4215fb6f6263e8d7b01bc"
"checksum pwasm-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e9135bed7b452e20dbb395a2d519abaf0c46d60e7ecc02daeeab447d29bada1"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"

View File

@@ -2,7 +2,7 @@
description = "Parity Ethereum client"
name = "parity-ethereum"
# NOTE Make sure to update util/version/Cargo.toml as well
version = "2.2.3"
version = "2.2.10"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
@@ -137,3 +137,6 @@ members = [
"util/patricia-trie-ethereum",
"util/fastmap",
]
[patch.crates-io]
heapsize = { git = "https://github.com/cheme/heapsize.git", branch = "ec-macfix" }

View File

@@ -12,7 +12,7 @@ blooms-db = { path = "../util/blooms-db" }
bn = { git = "https://github.com/paritytech/bn", default-features = false }
byteorder = "1.0"
common-types = { path = "types" }
crossbeam = "0.3"
crossbeam = "0.4"
ethash = { path = "../ethash" }
ethcore-bloom-journal = { path = "../util/bloom" }
parity-bytes = "0.1"

View File

@@ -571,10 +571,10 @@ impl<Cost: CostType> Interpreter<Cost> {
let out_size = self.stack.pop_back();
// Add stipend (only CALL|CALLCODE when value > 0)
let call_gas = call_gas + value.map_or_else(|| Cost::from(0), |val| match val.is_zero() {
let call_gas = call_gas.overflow_add(value.map_or_else(|| Cost::from(0), |val| match val.is_zero() {
false => Cost::from(ext.schedule().call_stipend),
true => Cost::from(0),
});
})).0;
// Get sender & receive addresses, check if we have balance
let (sender_address, receive_address, has_balance, call_type) = match instruction {

View File

@@ -179,14 +179,15 @@ mod tests {
#[test]
fn corpus_inaccessible() {
let mut cache = Cache::new(Default::default(), Duration::from_secs(5 * 3600));
let duration = Duration::from_secs(20);
let mut cache = Cache::new(Default::default(), duration.clone());
cache.set_gas_price_corpus(vec![].into());
assert_eq!(cache.gas_price_corpus(), Some(vec![].into()));
{
let corpus_time = &mut cache.corpus.as_mut().unwrap().1;
*corpus_time = *corpus_time - Duration::from_secs(6 * 3600);
*corpus_time = *corpus_time - duration;
}
assert!(cache.gas_price_corpus().is_none());
}

View File

@@ -95,7 +95,7 @@ impl AccountTransactions {
}
fn next_nonce(&self) -> U256 {
self.current.last().map(|last| last.nonce + 1)
self.current.last().map(|last| last.nonce.saturating_add(1.into()))
.unwrap_or_else(|| *self.cur_nonce.value())
}
@@ -107,7 +107,7 @@ impl AccountTransactions {
while let Some(tx) = self.future.remove(&next_nonce) {
promoted.push(tx.hash);
self.current.push(tx);
next_nonce = next_nonce + 1;
next_nonce = next_nonce.saturating_add(1.into());
}
promoted

View File

@@ -69,7 +69,6 @@ pub use error::{Error, ErrorKind};
use std::sync::{Arc, Weak};
use std::collections::{HashMap, HashSet};
use std::time::Duration;
use ethereum_types::{H128, H256, U256, Address};
use hash::keccak;
use rlp::*;
@@ -82,7 +81,7 @@ use ethcore::executed::{Executed};
use transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction};
use ethcore::{contract_address as ethcore_contract_address};
use ethcore::client::{
Client, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage, BlockId, CallContract
Client, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage, BlockId, CallContract
};
use ethcore::account_provider::AccountProvider;
use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
@@ -102,6 +101,12 @@ const INIT_VEC_LEN: usize = 16;
/// Size of nonce cache
const NONCE_CACHE_SIZE: usize = 128;
/// Version for the initial private contract wrapper
const INITIAL_PRIVATE_CONTRACT_VER: usize = 1;
/// Version for the private contract notification about private state changes added
const PRIVATE_CONTRACT_WITH_NOTIFICATION_VER: usize = 2;
/// Configurtion for private transaction provider
#[derive(Default, PartialEq, Debug, Clone)]
pub struct ProviderConfig {
@@ -203,29 +208,29 @@ impl Provider where {
bail!(ErrorKind::BadTransactonType);
}
Action::Call(contract) => {
let data = signed_transaction.rlp_bytes();
let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?;
let private = PrivateTransaction::new(encrypted_transaction, contract);
let data = signed_transaction.rlp_bytes();
let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?;
let private = PrivateTransaction::new(encrypted_transaction, contract);
// TODO [ToDr] Using BlockId::Latest is bad here,
// the block may change in the middle of execution
// causing really weird stuff to happen.
// We should retrieve hash and stick to that. IMHO
// best would be to change the API and only allow H256 instead of BlockID
// in private-tx to avoid such mistakes.
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?;
let private_state = self.execute_private_transaction(BlockId::Latest, &signed_transaction)?;
trace!(target: "privatetx", "Private transaction created, encrypted transaction: {:?}, private state: {:?}", private, private_state);
let contract_validators = self.get_validators(BlockId::Latest, &contract)?;
trace!(target: "privatetx", "Required validators: {:?}", contract_validators);
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash);
self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?;
self.broadcast_private_transaction(private.hash(), private.rlp_bytes());
Ok(Receipt {
hash: tx_hash,
contract_address: Some(contract),
status_code: 0,
})
// the block may change in the middle of execution
// causing really weird stuff to happen.
// We should retrieve hash and stick to that. IMHO
// best would be to change the API and only allow H256 instead of BlockID
// in private-tx to avoid such mistakes.
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?;
let private_state = self.execute_private_transaction(BlockId::Latest, &signed_transaction)?;
trace!(target: "privatetx", "Private transaction created, encrypted transaction: {:?}, private state: {:?}", private, private_state);
let contract_validators = self.get_validators(BlockId::Latest, &contract)?;
trace!(target: "privatetx", "Required validators: {:?}", contract_validators);
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash);
self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?;
self.broadcast_private_transaction(private.hash(), private.rlp_bytes());
Ok(Receipt {
hash: tx_hash,
contract_address: Some(contract),
status_code: 0,
})
}
}
}
@@ -271,27 +276,27 @@ impl Provider where {
let tx_action = transaction.transaction.action.clone();
if let Action::Call(contract) = tx_action {
// TODO [ToDr] Usage of BlockId::Latest
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest);
if let Err(e) = contract_nonce {
bail!("Cannot retrieve contract nonce: {:?}", e);
}
let contract_nonce = contract_nonce.expect("Error was checked before");
let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction);
if let Err(e) = private_state {
bail!("Cannot retrieve private state: {:?}", e);
}
let private_state = private_state.expect("Error was checked before");
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash);
let password = find_account_password(&self.passwords, &*self.accounts, &validator_account);
let signed_state = self.accounts.sign(validator_account, password, private_state_hash);
if let Err(e) = signed_state {
bail!("Cannot sign the state: {:?}", e);
}
let signed_state = signed_state.expect("Error was checked before");
let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None);
trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction);
self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes());
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest);
if let Err(e) = contract_nonce {
bail!("Cannot retrieve contract nonce: {:?}", e);
}
let contract_nonce = contract_nonce.expect("Error was checked before");
let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction);
if let Err(e) = private_state {
bail!("Cannot retrieve private state: {:?}", e);
}
let private_state = private_state.expect("Error was checked before");
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash);
let password = find_account_password(&self.passwords, &*self.accounts, &validator_account);
let signed_state = self.accounts.sign(validator_account, password, private_state_hash);
if let Err(e) = signed_state {
bail!("Cannot sign the state: {:?}", e);
}
let signed_state = signed_state.expect("Error was checked before");
let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None);
trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction);
self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes());
} else {
bail!("Incorrect type of action for the transaction");
}
@@ -327,7 +332,7 @@ impl Provider where {
let mut signatures = desc.received_signatures.clone();
signatures.push(signed_tx.signature());
let rsv: Vec<Signature> = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect();
//Create public transaction
// Create public transaction
let public_tx = self.public_transaction(
desc.state.clone(),
&desc.original_transaction,
@@ -336,7 +341,7 @@ impl Provider where {
desc.original_transaction.gas_price
)?;
trace!(target: "privatetx", "Last required signature received, public transaction created: {:?}", public_tx);
//Sign and add it to the queue
// Sign and add it to the queue
let chain_id = desc.original_transaction.chain_id();
let hash = public_tx.hash(chain_id);
let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?;
@@ -350,13 +355,13 @@ impl Provider where {
bail!(err);
}
}
//Remove from store for signing
// Remove from store for signing
if let Err(err) = self.transactions_for_signing.write().remove(&private_hash) {
warn!(target: "privatetx", "Failed to remove transaction from signing store, error: {:?}", err);
bail!(err);
}
} else {
//Add signature to the store
// Add signature to the store
match self.transactions_for_signing.write().add_signature(&private_hash, signed_tx.signature()) {
Ok(_) => trace!(target: "privatetx", "Signature stored for private transaction"),
Err(err) => {
@@ -684,12 +689,11 @@ fn find_account_password(passwords: &Vec<Password>, account_provider: &AccountPr
}
impl ChainNotify for Provider {
fn new_blocks(&self, imported: Vec<H256>, _invalid: Vec<H256>, _route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: Duration) {
if !imported.is_empty() {
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.imported.is_empty() || new_blocks.has_more_blocks_to_import { return }
trace!(target: "privatetx", "New blocks imported, try to prune the queue");
if let Err(err) = self.process_verification_queue() {
warn!(target: "privatetx", "Cannot prune private transactions queue. error: {:?}", err);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
{
"name": "Kovan",
"name": "Kovan Testnet",
"dataDir": "kovan",
"engine": {
"authorityRound": {
"params": {
"stepDuration": "4",
"stepDuration": "0x4",
"blockReward": "0x4563918244F40000",
"validators" : {
"list": [
@@ -19,10 +19,10 @@
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
},
"validateScoreTransition": 4301764,
"validateStepTransition": 1500000,
"maximumUncleCountTransition": 5067000,
"maximumUncleCount": 0
"validateScoreTransition": "0x41a3c4",
"validateStepTransition": "0x16e360",
"maximumUncleCountTransition": "0x4d50f8",
"maximumUncleCount": "0x0"
}
}
},
@@ -32,24 +32,26 @@
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2A",
"forkBlock": 4297256,
"forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f",
"eip155Transition": 1000000,
"maxCodeSize": 24576,
"maxCodeSizeTransition": 6600000,
"validateChainIdTransition": 1000000,
"validateReceiptsTransition" : 1000000,
"eip140Transition": 5067000,
"eip211Transition": 5067000,
"eip214Transition": 5067000,
"eip658Transition": 5067000,
"wasmActivationTransition": 6600000,
"eip145Transition": 9200000,
"eip1014Transition": 9200000,
"eip1052Transition": 9200000,
"eip1283Transition": 9200000,
"kip4Transition": 9200000,
"kip6Transition": 9200000
"forkBlock": "0x9766dc",
"forkCanonHash": "0xf2fa4bcc417ad374100c2035aa865ff60fb568a83db1b6f6cb8fb52cfebc28b5",
"eip155Transition": "0xf4240",
"maxCodeSize": "0x6000",
"maxCodeSizeTransition": "0x64b540",
"validateChainIdTransition": "0xf4240",
"validateReceiptsTransition": "0xf4240",
"eip98Transition": "0x0",
"eip140Transition": "0x4d50f8",
"eip211Transition": "0x4d50f8",
"eip214Transition": "0x4d50f8",
"eip658Transition": "0x4d50f8",
"wasmActivationTransition": "0x64b540",
"eip145Transition": "0x8c6180",
"eip1014Transition": "0x8c6180",
"eip1052Transition": "0x8c6180",
"eip1283Transition": "0x8c6180",
"eip1283DisableTransition": "0x9c7b61",
"kip4Transition": "0x8c6180",
"kip6Transition": "0x8c6180"
},
"genesis": {
"seal": {
@@ -62,8 +64,8 @@
"gasLimit": "0x5B8D80"
},
"hardcodedSync": {
"header": "f90247a0434ba1ebe3bc9d9d12886f616afee0eb785dd00d78aa64502045b249c8a3cc33a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940010f94b296a852aaac52ea6c5ac72e03afd032da0d1c1137be913218840c44bdb8f5709a59d8608b05be0dc2401402e11ff1bf2ada0eb50a864e57e19bd4c8499725a6a3841f706ff5d743e64f1d06db903aca62eaba0d4d77727f7253c109e6f048fa5b1583b6c2911ad77f7d59d8947d38a96a67729b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe838ee001837a120083013502845bea4f689fde830200088f5061726974792d457468657265756d86312e32392e30826c698416fa93dab841c80b3e34bacdc91e01f6a76c64a920a65edfea86b84e0fd59c6d8dbd7758f2dc4e3cb446de8dc07f3d8cb71375a6315f401cd1ce54c56694e4e01f7e774555e701",
"totalDifficulty": "3135776192732436705400032023148164213445066062",
"header": "f90247a0017c9292a6abf6bb9aa48c30f8854dc0e9649bceaf19079b1aac50ebea4fa316a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794007733a1fe69cf3f2cf989f81c7b4cac1693387aa06b81f6633226562f466201f0d097877c903a650f7427aefa7433fb971f601287a0098141509099d91ed2c2e503d43db5b5412d51880994e8e03a86e1d7a9ca8e8ca0495f318f8bfdd4beb517d115ad5d5330aebafe70eb2b1cfb0ab029221a0f48c1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe83975801837a120083035108845c2c49e49fde830202058f5061726974792d457468657265756d86312e33312e30826c6984170b1279b8413ee0655a59d1f7f8db39c22055c614346450e99965fef62efa43b21b20f0966e3e41eb65fcaf6f9ce3a34359dc064827e06f3a29d2c717f287234785d369e56f00",
"totalDifficulty": "3324635628632492920129912637269655024947201711",
"CHTs": [
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
@@ -4636,19 +4638,379 @@
"0x8b4f8964062d0f00e40a41d21852a2e22abba1f4cf75f594797e368e4df21f7d",
"0x916993123d91b181d145e2668efed6eae3845fd76d4765df3a04d8adde8c7142",
"0x21b91051b5c5fbd22164a655de8485cfc2a9eff58ed09d6fbbb454560898daed",
"0xb52ca76065bcf43f06335977ab87d6c809dcf4e6cdfc452ac2018b77c64089a5"
"0xb52ca76065bcf43f06335977ab87d6c809dcf4e6cdfc452ac2018b77c64089a5",
"0x9437d47e7f7fb4c95aacd5e1322a9c7b457888dbfb1e485142cb16ba805b5ded",
"0xb7cb3f7394fef7de5884e165c8441d441c98c1080865b604dd21766759f7fffa",
"0xfaff33c1aae8882f3a9d84678b55b8945b037b1f05785f2874079da71caf4aa5",
"0xe032d77db9e882bfb3d5adc89d9a9812fb9775f98c03765ffdf0c40d0dbf11f8",
"0xc9c4ded5821040df911b23d92d8270fc83164531c9d631c4d8e228a71e189ba1",
"0xa27f4dd47059fdd4afe78ce8c9029c9a7c0916d10cc7dba1ce011c886d2275bb",
"0x6dd0d3b0e07535d8350cb888c75ca355c4abb07bfc6ceba3eae02095324679a0",
"0xee4a3c6125a5e69848457d35f9614705b651c68857b03968bc5420a809d1d9b8",
"0xc14947239d0a7061d796313aca233659059b13740e63f967f8bd4806feb895ff",
"0x36d9ad9d6ad2e1a1aca489524303aaa8534b137c5e9ef708d589b7a75cbf6500",
"0x497c4cf7509b12ebd34d5c0520a24ae1b6e1c5c050bb3412d7d1a702c48d07d3",
"0xac81f9bcce95283b7f188f16eb68d22adb22dc1cff0853739c46f27523a653b7",
"0x2f0818ee594d2d1fbfe9a6a03cf4ae08dee69fbb9c289c2789d792f14a3e4e7d",
"0x9beb888d86489512a9d1d8d6461490e23599c1595aa5b4d4b113d18c0eb99697",
"0x7708aa2a88f9b41cde9f338da6d2f9dde2b57f1538f7aeefb66a0e9dce488ff3",
"0x548a59ae0782fc5202431a472a8dc5e21ac83b68dc88afb2b0afd56cd3e880dc",
"0x271397f861034f73fe228e3921d835a313041c260a6c2ca3d0c28d407d17ba89",
"0x732b95d3ebdf035182863a540bc002cef70f98b91f90ee8dcef2285a970ade6b",
"0x605d419ecbcdaa05d6f09c9734469847f52164df26417d7807f959986b843869",
"0xdc56e2800a637475662632ac37e9eec90d9f3962a454d6f32ee7f56426ab9f42",
"0xdcd35988aa6982f14b3a2834f841c755ad42dcc61eb0dc6122f2aa9db65fcf92",
"0x659b06e2aa0359e3743f59d2b128cf85bfabc20ac9d8c42a89d9cdda2bef7697",
"0x45377222c3910f95b3f5d0adef823dc4184189cab9eed54b9997d2b30fdbae43",
"0x15d66d0b9347f12bf9c408910edf41623f460244f309076d55cf969dc158b36e",
"0xe5de2158113351c0ea314eb12b28f9502c307decf883ed480c53c1310c9f7c11",
"0xc7342c08dd73fbe5801cc6c8764c53f924d6a77cd5a5b8bdbb22d2b6d3e0336e",
"0xf10486dc44a10f7eec6739dd56e0f7519507777e78e3974d974ee0bd931f03d0",
"0x5985752f0b3849e9cc6a5d38b65617be10b52b8fd0c2642c328b864d59a23f9f",
"0xce899213bc8a178cbf2a8eb86f045f59895530b0af5e209b60553869000070f4",
"0x724dd7b5e5d0e93017a62faffd534e423610c494ef0b5689304bc80a68df0e46",
"0x318073daf925850c412d6a1f2db2d2093268896a88c49e822ccae4070b406408",
"0x74fd03921ea801d4618fa7c2375c4369a15c7774564dfb0373b5913bdc9a6df8",
"0xb10896436461c2660cfe36a60c433b32ef8a1e772f3f9c16ae243840a1aa3aa8",
"0xecfc10478a368b186e4299447ec9d3ce27ca8386274c545f3edac3608ad6cd0d",
"0x288c697b29a0d2c5d45b9507aaf62bc4bfecca1b34e1a5ce13a17711af0df3cd",
"0x429fc79b89ad00887096417282a571de77fe73dbfd1564c13bec5830b38890cd",
"0x4d859982815d597e31d0e5374d7077b59a4b9beec01040608bad05c6a9d0be2a",
"0x1addc6e300b6120cd196bcb7340ca163879ac55f7c9069be77947aa01e778cf9",
"0x2e648a4eefda9d35e26b148028a0b336ef7d75809454e36795edb9d3fdeff550",
"0x814e65df8c720e8c9c7d64c76b6b9554328d6c780b5f3dff96aa3e29506e7e49",
"0x4841c38f2a920bb1a072b9a7853dd7d2e44dcbc35e2737aa2f3cf6652dabfdd2",
"0xdc63afe7974211db82b2602c26d6ace8d93f34736c0fa68eac3bd5d2c1af7484",
"0x2052d12d3534c5d7693d420c8e080bcee99ce10ccebc7451272b7ef08f8a3dc2",
"0x4985769df508ccc2add583d187095a8af4ca73a5be2506a506146e23dbc67d55",
"0x4a6744d48fc2d85cc99e419483ec1111ccb6fc7ab13e4eba28a29269acb30952",
"0x527b0514dd83336c0524add1f01799512517378b2045c4ed43ccc0e977553bac",
"0xfc33e6a20033fff41a9b885dc5bbaa848a0f244fe89b4a1af261d382c544fbaa",
"0xadce691a1b4224bd56682784ec106dc93af89185721db8b427eab6b0ff22776c",
"0x0fdef2a9525541c1e96172c8a33ccc08ed759dc024d437b82126ff03b65e1684",
"0x7aa9e8c1e9da3c68080f099281b367de26838ec7bcd474590ae101fcd68a7116",
"0x7eb70f0a4c42726f5b3a67ab12bdf5b4e6bf5e4c347b6c32f6fd3a04c4a003e5",
"0x546f5f3c2e44b7a61d6d0dafd802fcc114db7acb7f887f0dd0b1878979fd3eac",
"0x5c5294fd77081b1a23037c34170b568358011be2fdc0e3ffa2230b1a017ec5b9",
"0x6c854d3de1f2a28dd8f6320a534b915b032078377e3b880eaa8e9a3775768e2c",
"0xc2be1a4c7a5351063084c5907f19e63f25e048f3e27648a6d9056d3d4b635c19",
"0x5d0673ecaecd00cc8847827bbda1dd7bb21f537e5e10f10d8b5944496b55e9e6",
"0x8a1bfbf9dd51b727c17e8920019caae599f53d37563935c584c84cbdebf942e2",
"0x75649056bcd2a520811d8f9d5c0c629f492e93fcdcd298c0657a8c857fdf2cc6",
"0x71421a3eb42eeba485fb90918511b0a430311856c27a968e52096c6cdaf0cce1",
"0xdf19c2d595ec81bacaabd39217e100e6731f8bd7c3d6c5bfd987b27f89be146d",
"0x573839677ae138670609c499107217fcae5de5fa9905c78a21b07f7a906a0a53",
"0x1e8db73865049c1cde4004c2a60945edd9ce9847c360a2feb36205e1f1cbd5da",
"0x52a602e7c2f462a39288465c733d2133b7f77a7a77d7e60e214d4d4eff917258",
"0xdc30b1767c78f2ac953c5046e6440b7de488933cdece18fa3566f00d8a96c92f",
"0xfc0baf76004e7d87b36ea52de7d886c9b3be44bb8063549bba31b63b87ac3f92",
"0x3426c56db720ccd184f2e49385e96e5a37fd378cd486de8fadcc7d5e727aebb8",
"0x39fc1cbf20cab093c75b42931fc6371e9851cc4357badb6961359e07b9d97fca",
"0x6b3725ada81d881bbe245d4b55c7be12926b42d0e58dfc8fa38d54f68ff79ee4",
"0x69bbab0d123bbf03499984698c162f9dfb81375f6bf9f2e643badcc8e0281ef8",
"0x101cf365b31d4b37910433ffa265e1a978d4f80c478936809e1bcca7baff59b1",
"0x65d26a27a34ca4ca98c2b5f609e4596344514698f2137547e815dfcf91f5bb36",
"0x3b8598589a6ef43efe0b7a64832360ab02e150c4b4ec02f2a028d2522f4c0ba7",
"0xd8776563bb522b42a25cb2714f9ea294fffa4c4fb5ad040a9458e10637861f34",
"0xb1b85b8c9bea99a2bde16ab99b2d7e42571ba15dfeaf28a2897322bb444171b1",
"0x803cc4e5c23bd3842736b36a425364416dc69a3efb95f3c7fdbf7782d6de7edc",
"0xf5803ed2a130a19600ca887ad06813482b678ac0eee049cbb2e56e39a90d9867",
"0xd3f6125b061023531cbd3d625c9382631e2fecc75945dd6f78f883353ec98962",
"0x7b1d59f8c9869a9c73a09385c82762b86fcc995e75db00bda388e1423be19df4",
"0x2b7a8289bf9f93c589866af1a224c34943433b6a5a571df7dc4524bcf2adde42",
"0x9199d73dd306fc9038b36212c3ed7706d8b0f30cfcf3359408a8e6fd8ebab0a7",
"0x0cc8446d21ccc31bee04addd48b50f394390ef3340745555f9d7ccc3c13eefbe",
"0x80052b2097d7f836090ba9f94ad7c33066453d8ee62a2e215a82003ed92568f1",
"0x231c2d4e6a6039342ac03f766fac9f0a587ef6828d071e63a1e3f660fff13263",
"0xcfa0cae426e4b6b9422d72a687d50139654fc3351993b5d38ea4fc6f8944e662",
"0x9dc837a60a2c18493fd3b40083996f18a44f37a7a762ca649bc5d8c8b272aaca",
"0x30b4651c3496efed5997116b7a12f9cdc24040a4e110478f1a2330fbba48fbec",
"0x99567d98d73fe92c81c69aa465bd62b02492839519f0380686349da64caaf758",
"0x9618fd333f89357a22bb3101cc386003c2745f8a24b5affd2be9cc3c26a93e34",
"0xe539d1a4de2a57dd65cea42302fac83aed570f2fd7a318c6d226dea58d5f94c1",
"0xe69e3ef5d9d8cf08d3a354da7179d5bab9c68b4b6ea6a7e5a58cae9d901b5f35",
"0x97cd995441161fe4f50a339c6323020db6f56b9221b549194a93b9895a043e59",
"0x803e04ee8a22299e779491a6749b7d57973a59fe714d080f03749bccde30d5c6",
"0xace95a4dc00b3fef757aa76445b1edc582246eeebb7c2bdc71fa648e06428485",
"0x1c8bd27b857dd8dd5a671fb4aa6cec3c41ca1c747c9f86edca8f389ac637e09f",
"0x554b4d1bbe92718dd1aba2a9d10f48f803287d2c26108bf3cab2574a91375511",
"0xd5856bc0794ddc23049639fc438c360d66e4b3eb1f96516ba0c02c46cda8fb49",
"0x25a4c78e490c1d5fc6c1252b2ba13ca9ad5113a5c64e02220969146c5bbe9730",
"0xa8dd024efc7f03b61ff9926421107b54c42f5f9c936d956e9b6c6eb36f9b242b",
"0x26d488bff06eff3fe1912ce985ced65325e09e1c01a95bc16d0df22481690640",
"0x01b89e65f1a82ea7e456e96e2ddf29be42dced7c7ea9b12e841bd973506dcc25",
"0xf0f5d3392e3fb73697e44755d38c84bd99394ec2ef9dec841049baf8166e6d55",
"0x91c4f65d698130b132d0a33e44c27ea55f477cfb134224139ba0264b5737ed42",
"0x1d2295b21e1bb810d35471fe17adc80e59c6c57b5037de90c88e99021ac78b24",
"0x667cc89337d382967727f0740819a2f6298dd5f2b7b5e82dc45e3f1c15c5e998",
"0x908ac480019af2d3c3017c413077a73905e27ec01721aa499c24fa7e13bf8ad9",
"0xbeb7ebf8ffae71221e5ff149e3333fdefe6b11780d439b45a874129b2c25d71d",
"0x235c2ed0e3fd286df5cabca5f0f61bfe356ad0d7c8bb9c642814d01f2fd26699",
"0x22fc5189fb1945ae98d89e50b258514baaf525e8137e9581c99339e1097e33c1",
"0x148256253b74711fc61f8af7d4efcf8694752426715a0a4c788556feb68c1a2d",
"0x26ad59543cfd91bbe37cd8fd1995b81d0f095ac4e02cda0b4f5f40c9db6d320f",
"0xee340b0f25450c23a5c9b16cd5aa59657a9992c1c341172bcc8c9038eb6789fe",
"0x5da22a0b434f041d76be1d53ef63ae24031861dce1ff4baa3511d67664060bbd",
"0x6009815cd4da0162884d0be4cfe6936f1b251f50e9c89d9fdc2f0af430012e11",
"0x9342474f10ce871dfeb70fde89b181075b18e973d4806364d52f83f6be4d69f1",
"0x3c4c598faaf3c9fa8b9c1bf856872e65e3d53435177992b29a7674198e7df000",
"0xdf0d952cca28797dbb503cb8c7192e811a7dfc0797379391f839341e210078ee",
"0xdd48052c8e9a9ec62a58a580abe1c420b89393bfffe53fbe6b7f9079b5ec4d3c",
"0x028846c41592546d1d11375d00c1d10a18c06ee5f968b2ce8e8c42bee7aa263d",
"0x4aa08dc77484d15f8423a1fb2df0fb0c67729de1d48e61831884e49d7697674d",
"0x084c72f0f0fb1cdd4ff80ebc9379c9d29c8d1e35cc45901a67b231ac201ff9b4",
"0xe904eec627d475fcb3e61b2db0366a24ebcc286ccda2b1614049fa17ae9a9d85",
"0xc3fb5ed46f30f566b1d5547d5e00c4c999960dcbd1b60f0b337bff8da30c054d",
"0x1503b399ce9dd9f1cd8005036006e4bae2b3f05fbb1393b8f5d868332605c98b",
"0x70de442d35565513b92d8cdb95c6537f72d7e099e217af7c260fdf92499ecfae",
"0xc6b86174c627fdb002d187feada8c72b9bc6b1fa5d11785988c72b06480ef1c8",
"0x06212692407b9b701ed1b115a8ae1cf07668cd7498cbd7c5c58e9b52a0a0093e",
"0xfdc722f761f07d5c52d36c147ab8e80a666af5aa77fdefa37e86c7b2518aca12",
"0x7396bd40c5677c5f4388d956ec437071cd4352cac44b7b97eecebb6c5c99b507",
"0xf634b80145415b2086d4a20746bef5c7d34034ac6601487792889be39bac54c8",
"0xfb8cbee41b441d5424cbd12b064b04f5618f0b360b1c2ae5ffb90a0194e61106",
"0xf77c56810755fe69822c1250295092fb8e7c88d789706d6769d0cbdeb386137b",
"0x9e0f084e1184804e850784a4e376b8acbf58f4235a3829d49217c888e4e5d535",
"0x6b39d6de64090febb49dc6f6a31eb606d8e278b7ff4fa9e1a9774d3d9dc71f81",
"0xb5d9e67fd6cdd93c74536e5a74dac8eb8ea6914c2315c22e079d61eaecb18c29",
"0xac3dbb4fa1da752bff5884154e02ab975e993201e69ef9ca532c8b1e00b1628b",
"0x747b42a7005c41ae222f8c2ecd4bf7000c274366237e68b2e95a64cef3799ef2",
"0x8f06b121d921274a0d8da269d19ffd6a417cec988f0018647966960ac822fd60",
"0x13451d3ecba978d3c0d88c2dd4068cf060e949889ea514306c23a7a1ec574ca2",
"0x737f8bd85cce3a392da15c8e68c3ea9748a6523ab92dba8d1c6c8081311c3ef7",
"0x83cca9d97f8c4b2776b96d887c5ab1e8e6172970d6d237da98dd5c6ce07db7f3",
"0xb5bb3dd88ecfe2e4ac4e4be2b605cc7c5e79024782628a95df33c4967dc8251a",
"0x640c6050e63c965742cdfc6d3217eca459a24b3acf3a5ec64eed9bd7bbcefaad",
"0xe74478890f186d41b5157dbcef1f2754a35a5af332095dd25d34caf01580062c",
"0xfaabbc9703e049e49d1d22da051cfe6cae0697e7e728e954bd5abc40d0e2014c",
"0x8aa4a19c4ec50a68a6541ecc11d4473cf02773a0ba7bb4012ccd76ae11ce8bf9",
"0x01abdedb1886ec8220a4f6ce6a43863ab77215f03e8116b03f3efe44bee658b7",
"0x18e44060426a05d3d9500b7d6ae6d99133109bac39942ab825ae81c551c0ef39",
"0x19a60001bc92289e73d3a8320f7601eae1bcf70f65c3a43ff6af1b2c2c17355f",
"0x2dbc82c8ba30fe69aa00c7abf129cd1a65e8fb9398b2ebca0843e526e001ce1b",
"0xec773bb4cf7d35feb70ea19cb53cd64af2cd34c1e4f1e282bd3cd0b39720bd2e",
"0xc966e10e5568661e0930bbff1561e2de413f9f89d984b46224ced75d57213401",
"0x29658e4a7e4dec3e9a449902af34ab93fe760c6a1695c1a97e0a093e3d187782",
"0x98b0b147d3f6a8a21dd9e3fe01082dc9031c193dec4def76e53ad1c13269c3d7",
"0x288b646ad44d5f4ea299917a9b69c9c07b5ddc50e93d03fc1c1ed653599d7a7d",
"0x87c26362fb801ef77354375eadedc1489a4fc39401521cb06b604fd9288e4d82",
"0xa5cf4098a62d2dcc87e589c8269dc712e2ac2be5adf07ca33c520556d4da0cc1",
"0x4f253c49f87e135e4a0941409fe70ec6b29f6b0d9aed3f654f5eee7f4eb0a486",
"0x5370ae8dfa2a982dab86dfb45950a50ffd29039781b2b065ef5057f7b43b84d2",
"0x044f950f82d97f0fa164ec4174c238203d15f4cf32dd739931c3e291e0902ed4",
"0x792c3af8c8808b95f38d6e21979450e3ebeae129f0a9a9d0cf2951252801dd7d",
"0x141e09e2ca0a96d50e7c12aae794ed0f22c0441fcc51d1c4e179f891cb06ee1e",
"0xc475b7c5293efed9c9f0a5e1d8800e4dd10810bc7dd33c406da131b15524ee48",
"0x0018d2c2e814bff6fa8f5e162de402db71dd9eea45d320f60e280a00aadafc2a",
"0xc68336fc8904777bf8ec4d5a61f79f2e847c028889bce39ae0f307d11efad818",
"0xd6439bee30ae288496a022e04f5c21b9b047edbb370ea3e33ed236a217c6ca0c",
"0x03e096d6ce43823e4543ddbfd8f55528d49c38b5c701c520e95a51547b5b193b",
"0xfb80f18124198c12b6359ea7805f110f9f25a6686e7a917c110ad511554e634b",
"0xcf9a0aa896f5c54982a827e07314a81b58beb3de97fdf112ee1539ee47158f59",
"0x948cb5dcc88a5502d82a292e7337d5d010055ae4964c09b2c6d55b0401e1781b",
"0xb91614b49ef967aef3b113983cea703a60097e0cd4c0d9cf1ad6f36d594750a9",
"0xe29abd32597fbfcffb8d185931986a8519fcabca73abfc5be6e42bc8b6439374",
"0x9ebbe1b1037327c4f2f3c9b6191b6f28aaf9b04dc58f3314ec2c16ac1eaba9b7",
"0x098529aee4331ef9ee00ee624912ed1a7cd8d63ebf27a96059f56e60ab9a95b2",
"0xcab9578772277f3e1f7a6920b96df6ce3e6d7f60c42925b7bb1ac1d71d733718",
"0x43cb7ebd27e7207228ecee10cfb11aefe077bf03053877b53c42a41e4f39f607",
"0x12ef0a09e0f5dc9d89b01cfd66b34182e80821f0f9d86c80327086a9960ab9f8",
"0x30bafa474c54d2912897a13911cd1df20988be102333bcb9fc54905789f87718",
"0x383205a3e0b07e359127b28c3ad1b451564091893edc87d3d92e081111dd20e7",
"0x74382d6b160ac8b1e7b86abf22cb943b43afc4480be4b09c87c8b796f22eafe9",
"0xe84cbe2ed5a30d7b25ec540b1934577387626fb894e4248c719d417ff1b0f171",
"0x068dd7e31af946d3427dd6822c22577886c32a7f1e3a3bc61ee061be7c456751",
"0xff5309cf09f24f3666205ae09e542634bb848c47031ebc10079d96819095b60a",
"0x82991fe8d442572aafde5e2f6d2c0ba0823ae72110c2f4b65a0d39244db460a0",
"0xb86d9c8e378420595feae0f728e00736f5b72ffe37e289088c03235b3ae8f556",
"0xd678cbfb25960efc5a64d48f2ada784a5b43123da5db8636804c2ab7d1a6cc36",
"0x1ceacf6ae9acb6e7438e6971b133aa7a8ba7b648c130962c3f60b7449266f3ff",
"0xe81d2bbf5efd047428040f86caa351a8785a0ee864e74760569318c997b25116",
"0xde530285d36c4a50d0f91d48a42e9b85de919e51246b6aa54a55eb2041b17289",
"0xd5b86ba5c24729d199007133a8000314476135cc5b84dbc49de41a7d9f3060c7",
"0x95b2fc8a95f67d4d67cba712a98bb3b35fc4b92581f5eab9e737f2555592bf3d",
"0x9808b933e2c732a2b4d6229467430cd73715ac93d1000c470dbe403d0f14b6ce",
"0x8a708bd8ec41b6aeb1f822ed4892c4d685ae3fd1a752a0b79a10a6cf288c8a26",
"0x689c7f32af0a20de771b9c03efeb6304b08a421cbc2f178b63cd284f3d74407f",
"0x0375180a004265f4a38946353455c221785c3f6da1dcbde2c09c373fa42c434c",
"0x764f8f063124e8226a65af4823b260354924781b339a93f6eeb0622e10333741",
"0xd0a28ce8c50017ad2e0bf1c1f8193792228b879688f01354552e656272bd7936",
"0x20b12fa78b655cce826e87bd18cf938917d37c306cb620afef671b0548b1e1d0",
"0xc94540910d93236aff53413af46597dcb51c02508f14bf81817966ef32799c00",
"0xeeda2d6df1baa5dd3cf904c4402e4e99aaaaa16b6f3a0832bffad5492fd9e725",
"0x74de84a1158dfb1af0c1478cf0b048ae8b0ae00139588e91d37a6874b524522b",
"0xe9c92a1b7b298d7222890fffbd5ae4d2f8a8e0c5519cd06c3e34fd94b1f12767",
"0x18261f839aab59220f72e4e4bfa7a8dde2d3c5cd8c0179d2ff32a151f7af92c2",
"0x35fd53473534a3bdbf0ada29529991bfe6ac1865cc6786306b92dc26a6aa8116",
"0x6f40f093a08a00eefae4cb848462ba663b62f089005acb49a8f5ee3f1a767375",
"0xb0d49e32ac2ddef6bf0729ce9212c4bcc053aaa7cf8dd6649247749bab68cfac",
"0xb616c68f680b5cc9be3fc5bca40621514109dbc1316b848f1f3ce18b05e76d33",
"0x3ac8fe2f016f98eaa25451e36ce4fcfcbd160c0306c57f2edea049cdf541538a",
"0xb45e54eca70d4943eecaebfef3dc2219e79bdc71bddaec6adf53a1d058a65a30",
"0x74284120c5fa1ddcb7c294533eedd0b1ca2703626b7361543cb8e2a922177aae",
"0x8b15208a8b5d6ddfbe8b09148d497a5e3fc267b8f1d24272814d72f4826f8e88",
"0x3f9d4dcd96d5c902d4ef5655c10620c3e5a25edfa6fa093b0546d05c7c724d8c",
"0xf91ef06068659865a7c94e955f9c01ba4794214ebab33c9ec7030b2dfa47604a",
"0xadd5bb3d2f06ada2edb35754833e1bf1e317edff3e33535e135e67b4e4c5fdca",
"0x5aeb51beab2c98d3f77f2f04a39c2dfaed3ff759de9f5c16d4d88692a95eca60",
"0xeab1ab2c49609df8e29041ffefea082f92941aefae697fd915b9aeee8665c57b",
"0xbcf847e97f7f6fa5a16075ea54a67254e21fadeaa38d7aa42d16f223fd179faa",
"0x07f25413e56e9dfbd9bedf4b0676755f0cdbbf10b8f13ac7ef360bef7ac905d1",
"0x373e2f4dca323c9c4b4cd0cf4a1eb04ce7fd4d7548078200d9ffde2e3fa4cee7",
"0x5b9fd47a0d9cb386ccdcb2755934bfb8b27be896e52afaf18a0d130bcdff5432",
"0x1050a77797e0fc3a98c1d172496b8a3bbb2b045ebaa6b8b4af4e1542180f464c",
"0xea29629a5b08050c92412a25506d4d6dd8ea0f6bd8c962422d8f4913090a6d2c",
"0x1cc76b2b9f505bc358df15e285ac7cdde0009a2a19de9fcb5a44156ff76c5585",
"0x03cbbc18173700023643a8d6d7ff57cb0503336794c5fbe0b705a95034b7af80",
"0x9e2a5b70615a5c057d2956ac21838616ffd5cfb26fdf7398c4ad988a8cbc27ed",
"0xb2ef5e7c15e169ad2ec00e254415f4fa6c1f0635f728a98724dca4335e1c7801",
"0x50f9e432ed8c0c999685735ad95a4c2b3e0c0002d1159056392ed541ddca9b11",
"0x40ecd3140c4c8b02ce66489b39842d92ca64d05c30a9eddbfe675dded3fb6f3f",
"0xa1417d5ef7d185323ae3452fd99d54d5336f69ff866cfba06838da5efe273ebc",
"0x93b51cb9e7c9ca4e5f67fae55992ef6b0869c8c2effc8d244791cd2275f5f136",
"0xd9889fbd8c71e14316b5dfd46a6d049ec05127e5d3db6f0a31a935cb86b42d0f",
"0x384e1275612d71431d80d155015010e22b8b14a0648328bf1b32f92b1673308b",
"0x5eeac9b703836463fc0019c1b6f4be32282f4ade6778f897f6cf9d4c33e16085",
"0x2bdd040915ac28a0a604b727f062cf49fd413c44bcfaa2cc5eaaa9224248ef51",
"0xd7c85280a461c43df6c82f6ef60a973f2581c428394996191eeaa0d06a4b6473",
"0xe57d7c71a989601a066f8447a5be928ad0ce47d5413eceb709761654a30667e4",
"0xe1514ee44d1db8307cc08177a343887b5bd843cc510c5153b7f251aa10704f87",
"0x2898a69c885bb4cfcffa45a8aa63a8e81a40d4e3a7e1ff218ca3b4c70b836e08",
"0x27b66b51bb80e11582319b2fe176490daff05f0ce72a9dbfe79691676a455e0c",
"0x321d7bade5b8a1adee64bb0362620d99a5528831cdc0f1bd0258c9d66e4515f1",
"0x0a5443109753ff0845752dc998e82148d1de44d8347e51accd03cdbdcf405acd",
"0x1ef3a558361ee68b83346d40624b13d3170519e10dd18f60b6c5d7804f3c2d1b",
"0xf81fadde2aa798e6c151b35f764009d754f01aa0d8dacdd1a8f3109bd5d711d7",
"0x1af5b4d637429fab034b33b5fb3add567b5896608bcdc9e8d86a7d7ce762b4c2",
"0x8dcae50013fcabdc708c7b99c46fb4a68c75971775c135b7f7727bdf8db645a2",
"0x74dd3719b6229c2f675e41bae47aa0de9587608e8ad76e9dd911d695cbe3727a",
"0xca02fb569c275518e1cb95018a3b67dde118e82ade5cc9a43e118afa8da5e3d4",
"0xd5a890bef2beb2920a7ac22be90d0ed203dcf6b37ed0b3d2cea1fcc8f68c6d98",
"0x917c9cc04ac1f8afae96f0dc9b49161c352ed4e1da970e17d52fca31b8c1978a",
"0x009f16eb012717beb87fcc2b4417c8096a621fddc2421d02d84d0bfe92cd3587",
"0xe5ff9e2a1ffbcf1f53cf716b7caaa1317151ed8b81bd641bcf41eeadcdb0790f",
"0x2dfd67dc149772d4aa52588315df62edbc8a9340f2b3afb367f7f1564c1b8503",
"0x830df571a176933f6a72ac634933d61e602f744d1e3a046b7b639c9d2110580c",
"0xb2a030fd70ad2290c69e9b41220c14800d9adc33d7f8af049120fc6526a654d4",
"0x8a013c2432c60aa6315b1adc7155dd022df24129106cccbdf463273051ee0efc",
"0x55040dc6b554877d752f2f0bf0d97f71b34583b3d939587106affdacaf5d7c0a",
"0x251817e5c81aba6d675d47d688f19d5cb6957cea13ef3e15c66a6573b84af432",
"0x708cc1d141308870ea3ac36e5781cbfa3b5af327c565231123496354b5a9e74b",
"0x4efb2006e58b45c648d27654d45f1f797d4798217b2d0b54958fc576f115d81c",
"0x7d1bc87fd32a1b2ce74fe3784be5c0fe2e625ceac523ad55da7ebcd3cd1cb94f",
"0x575cc8bf8070ea53a54d027cb7d42eec9dffb85489013634350a96a434cb498b",
"0xc69812969e85bcd2e7e048b4323a726691c78d1902c1f1dbdd3893c11b9df8f6",
"0x6193928c0a4e47c9409c1af5d945a8c92c9e28a76570dfaaecfdda8071d6558d",
"0xb8982114b6b5da8849c27ee7d23280e15aa780248ebd36e5d364f2a05ae1fe45",
"0x49577950e5a3d4a06629686f9353adecdad6670fc9f4e6d3eaf6735296cc6775",
"0x6444155176ebe3b62f028ad79f058271d5b317360c0b97b7fe8c2a642da88229",
"0x9a3f0adf9c7b9380f60baf1d524590bec23b4d3790b3909ec8da3e79303252c7",
"0x591f122777ae7a313b6c4ba8c052d483f2aa3a687b5d85ed39e19d7e0c0e6de2",
"0xe3d68466d0747ab6245e5d8620eaae080a0f3c2aa34a56defe8adaef56d5474a",
"0x8d0f53bb5f7610133f04a763263815e092e43b0016369866e959d22eca466d85",
"0x8c8f0fff76977593112a64826f15ec0e909d9a1f1589e121a37f73d881e6b696",
"0x9ab1411e7ef5b295ab1a9dfe4ee1cd1a740af5b7e4b0a0e9c4a5f37e803c7c94"
]
},
"accounts": {
"0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 5067000, "pricing": { "modexp": { "divisor": 20 } } } },
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 5067000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 5067000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 5067000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
"0x0000000000000000000000000000000000000001": {
"balance": "0x1",
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000002": {
"balance": "0x1",
"builtin": {
"name": "sha256",
"pricing": {
"linear": {
"base": 60,
"word": 12
}
}
}
},
"0x0000000000000000000000000000000000000003": {
"balance": "0x1",
"builtin": {
"name": "ripemd160",
"pricing": {
"linear": {
"base": 600,
"word": 120
}
}
}
},
"0x0000000000000000000000000000000000000004": {
"balance": "0x1",
"builtin": {
"name": "identity",
"pricing": {
"linear": {
"base": 15,
"word": 3
}
}
}
},
"0x0000000000000000000000000000000000000005": {
"builtin": {
"name": "modexp",
"activate_at": "0x4d50f8",
"pricing": {
"modexp": {
"divisor": 20
}
}
}
},
"0x0000000000000000000000000000000000000006": {
"builtin": {
"name": "alt_bn128_add",
"activate_at": "0x4d50f8",
"pricing": {
"linear": {
"base": 500,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000007": {
"builtin": {
"name": "alt_bn128_mul",
"activate_at": "0x4d50f8",
"pricing": {
"linear": {
"base": 40000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000008": {
"builtin": {
"name": "alt_bn128_pairing",
"activate_at": "0x4d50f8",
"pricing": {
"alt_bn128_pairing": {
"base": 100000,
"pair": 80000
}
}
}
},
"0x00521965e7bd230323c423d96c657db5b79d099f": {
"balance": "1606938044258990275541962092341162602522202993782792835301376"
}
},
"nodes": [
"enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303",

View File

@@ -50,12 +50,10 @@
"enode://6e3d1b39cbd2a9c4f053a27e68fd90d0bac83691dfdc4a13c59f2555078a71e63c5daaee5a82aa6db500512760a5456f86076bf8bbe8011c27c82ed7d6f5fb26@45.77.140.210:30303",
"enode://f4698ad485a027497e1cc992bb5f7cecee2b32a44c47202738d8d0eecfab719541988d0cbcbc5ea94c6c959e5cddeb85fc6ae75fb63dc3bf87cdbe9e6f615e9d@206.156.242.64:30303",
"enode://31dffed97f8fed1f34fe66453280a89cbeeda60cf28f6fbb212ebbefd7c7566a02c1c7d5c00bbbb49b9fa8a49f157e0f786f379ca9bcbf2fea24de70d70a22b6@206.156.242.61:30303",
"enode://efe1a701595b7bfc20cc71a70dcdf1d731a5ca618cbc1bd0059edc6658d5958a2b243cc88112c7ded48f3d331a26a6a76b4d3f4a51260b5fb5d13f798e5786f0@206.156.242.62:30303",
"enode://6bdc7553ab2e4914cb47774c1e6d8c8f47ac7c3981891f85f65d06f208ea1bc4d3bf982b330950e0a0cd127efd7145c4df7113159a1d4a06ed722e6c16d0ac6c@45.32.215.190:30303",
"enode://872d82a24144bc007658fb6fac0dcdfb9b63aeb05ef563a06d0186f2d1e5ffbfc5c4f1244891a8a86ef70682b9d24382e654b305224883698862e2df647a4d23@45.76.236.247:30303",
"enode://b11fbc6cde81c80be69508aca8ffea8460680a25a9c151b683293f8617282062b8e8e139bf91e88cedf60068a3cf927b0d48832fda5169b58a8f7ce442de6fb4@206.189.76.132:30303",
"enode://96678da10ac83769ab3f63114a41b57b700476c5ac02719b878fa89909a936551bb7609aa09b068bf89903206fa03f23e1b5b9117ca278de304c2570b87dcb27@18.208.191.114:30303",
"enode://47ee6bc6312210caa0087a5754221f7666e37ab2d5c10cfe386ecdf9e5f935fc55726b37d10f0eaf493f762a270445d3e6d569891c328759b8baeb39f6f6ed2d@34.224.215.151:30303"
"enode://96678da10ac83769ab3f63114a41b57b700476c5ac02719b878fa89909a936551bb7609aa09b068bf89903206fa03f23e1b5b9117ca278de304c2570b87dcb27@35.175.15.164:30303"
],
"accounts": {
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } },

View File

@@ -37,7 +37,12 @@
"eip140Transition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip658Transition": "0x0"
"eip658Transition": "0x0",
"eip145Transition": 6464300,
"eip1014Transition": 6464300,
"eip1052Transition": 6464300,
"eip1283Transition": 6464300,
"eip1283DisableTransition": 7026400
},
"genesis": {
"seal": {
@@ -51,19 +56,12 @@
},
"nodes": [
"enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303",
"enode://0171db265a569636372566e86cb7a69306fe5c15a8e2ed5bed4010012fa1d146ae4918a688cf1bd3fd98e8c2d5c3705d68ff941c88ab974ff52c7fc8606ce2f8@35.168.201.160:30303",
"enode://9a4a3788471af17a8346da7fc41057f037da692d4fad0ac5023fc0c88cf64666d74ee9f6396012eec98cd6bc772418b42dddd823a38e359bbfdc4fc93ba38de8@34.229.128.189:30303",
"enode://881e56dc71472376b65ddaad5e42ee73084c96eb368c1e219b4fbcd73ffa339703cca168b6620cb1eabb7b8dcfe72e563117670c7ce94298c20d04b709c65697@165.227.111.36:30303",
"enode://8e3733fe1606b17dd743e7d4fdb7ec1e0b909aab3c5289beabcb36e9d3175ca05bb36a52589090d4899c85a9219622ea4cbb9541057b722be65241db557b51a8@52.201.214.63:30303",
"enode://f1a5100a81cb73163ae450c584d06b1f644aa4fad4486c6aeb4c384b343c54bb66c744aa5f133af66ea1b25f0f4a454f04878f3e96ee4cd2390c047396d6357b@209.97.158.4:30303",
"enode://0d1e0372f63a3f0b82d66635ea101ecc0f6797788a078805cc933dd93e6a22f7c9fa51ab4e2d21da02d04480ef19f3bbb9a2b41dd1c262085d295a354bb8b0f9@18.217.47.209:30303",
"enode://ab083db73da15b3995ac9c68035cdb32901835a823cb848fccb672e43dd21f14428706118d6fe5b921d8e741f122f35aad0255bc86807b1d17bcfa1e86e40a14@165.227.37.104:30303",
"enode://a2a8545ccceaa1152721a213e6aca912c6d89a37bc6eea73999fdb08a95c6f07a79057f7f41c75c128f58ed77a13985e5c33c8c50d6a3d60b50c43f5f69c1fcd@52.170.16.34:30303",
"enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303",
"enode://182ee200ca134dc4d6390f3d5aadbcd80df0f7f24335830335d142573eacce4eeb919d30e82c5df588034e167e6ba6dd11187502ac9264a71005127f6b146a99@159.203.95.241:30303",
"enode://b022ff70b5fcaf9596ae5efed99a8198b4ae0578ee9d17b733609d803a75cef95d3a2a18e50dca9a7c3b26139f158c59eaf8b5fb8d1d331c9a46934a78acabe8@206.189.76.128:30303",
"enode://4a16c9a597dad00c000523fc2f4302bb8bb7f05949ec0ea4a516f0c6de9e191662f650ab55ea2a05f5af0f0eeee879800074f7263328f09181c7156059b7b6b7@18.221.62.190:30303",
"enode://6527003feb6b534a7fac297b92d2f368bdf679d8f489639006c78640bf3ead3cdbf88a88a7bec29e6e29510122f279adf094d1b1b6e9e5005c4584aeb482c4a0@35.172.215.190:30303",
"enode://99f335f9dffe978f7a925590f011909f2db1a2b28b05a0dc10da47e285e3d20b2d827caee258607c707c5261d9ba5f7f5b899dd025315c0afbfd5536a91ccf73@18.209.18.86:30303"
"enode://b022ff70b5fcaf9596ae5efed99a8198b4ae0578ee9d17b733609d803a75cef95d3a2a18e50dca9a7c3b26139f158c59eaf8b5fb8d1d331c9a46934a78acabe8@206.189.76.128:30303"
],
"accounts": {
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } },

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
{
"name": "St. Peter's (test)",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x1BC16D674EC80000",
"homesteadTransition": "0x0",
"eip100bTransition": "0x0",
"difficultyBombDelays": {
"0": 5000000
}
}
}
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x1",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x0",
"eip150Transition": "0x0",
"eip160Transition": "0x0",
"eip161abcTransition": "0x0",
"eip161dTransition": "0x0",
"eip140Transition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip155Transition": "0x0",
"eip658Transition": "0x0",
"eip145Transition": "0x0",
"eip1014Transition": "0x0",
"eip1052Transition": "0x0",
"eip1283DisableTransition": "0x0"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x0000000000000042",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x400000000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x1388"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
}
}

View File

@@ -1,42 +1,4 @@
{ "block":
[
{
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "GeneralStateTest_stCreate2",
"subtests": ["RevertInCreateInInitCreate2_d0g0v0_Constantinople"]
},
{
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "GeneralStateTest_stRevertTest",
"subtests": ["RevertInCreateInInit_d0g0v0_Constantinople"]
}
],
"state":
[
{
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "stCreate2Test",
"subtests": {
"RevertInCreateInInitCreate2": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "stRevertTest",
"subtests": {
"RevertInCreateInInit": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
}
}
}
]
{
"block": [],
"state": []
}

View File

@@ -114,19 +114,51 @@ impl ChainRoute {
}
}
/// Used by `ChainNotify` `new_blocks()`
pub struct NewBlocks {
/// Imported blocks
pub imported: Vec<H256>,
/// Invalid blocks
pub invalid: Vec<H256>,
/// Route
pub route: ChainRoute,
/// Sealed
pub sealed: Vec<H256>,
/// Block bytes.
pub proposed: Vec<Bytes>,
/// Duration
pub duration: Duration,
/// Has more blocks to import
pub has_more_blocks_to_import: bool,
}
impl NewBlocks {
/// Constructor
pub fn new (
imported: Vec<H256>,
invalid: Vec<H256>,
route: ChainRoute,
sealed: Vec<H256>,
proposed: Vec<Bytes>,
duration: Duration,
has_more_blocks_to_import: bool,
) -> NewBlocks {
NewBlocks {
imported,
invalid,
route,
sealed,
proposed,
duration,
has_more_blocks_to_import,
}
}
}
/// Represents what has to be handled by actor listening to chain events
pub trait ChainNotify : Send + Sync {
/// fires when chain has new blocks.
fn new_blocks(
&self,
_imported: Vec<H256>,
_invalid: Vec<H256>,
_route: ChainRoute,
_sealed: Vec<H256>,
// Block bytes.
_proposed: Vec<Bytes>,
_duration: Duration,
) {
fn new_blocks( &self, _new_blocks: NewBlocks) {
// does nothing by default
}

View File

@@ -44,7 +44,7 @@ use client::{
use client::{
BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient,
TraceFilter, CallAnalytics, Mode,
ChainNotify, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType,
ChainNotify, NewBlocks, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType,
IoClient, BadBlocks,
};
use client::bad_blocks;
@@ -268,7 +268,7 @@ impl Importer {
}
let max_blocks_to_import = client.config.max_round_blocks_to_import;
let (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, is_empty) = {
let (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, has_more_blocks_to_import) = {
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
let mut invalid_blocks = HashSet::new();
let mut proposed_blocks = Vec::with_capacity(max_blocks_to_import);
@@ -322,26 +322,29 @@ impl Importer {
if !invalid_blocks.is_empty() {
self.block_queue.mark_as_bad(&invalid_blocks);
}
let is_empty = self.block_queue.mark_as_good(&imported_blocks);
(imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, start.elapsed(), is_empty)
let has_more_blocks_to_import = !self.block_queue.mark_as_good(&imported_blocks);
(imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, start.elapsed(), has_more_blocks_to_import)
};
{
if !imported_blocks.is_empty() && is_empty {
if !imported_blocks.is_empty() {
let route = ChainRoute::from(import_results.as_ref());
if is_empty {
if !has_more_blocks_to_import {
self.miner.chain_new_blocks(client, &imported_blocks, &invalid_blocks, route.enacted(), route.retracted(), false);
}
client.notify(|notify| {
notify.new_blocks(
NewBlocks::new(
imported_blocks.clone(),
invalid_blocks.clone(),
route.clone(),
Vec::new(),
proposed_blocks.clone(),
duration,
has_more_blocks_to_import,
)
);
});
}
@@ -2164,11 +2167,8 @@ impl IoClient for Client {
// NOTE To prevent race condition with import, make sure to check queued blocks first
// (and attempt to acquire lock)
let is_parent_pending = self.queued_ancient_blocks.read().0.contains(&parent_hash);
if !is_parent_pending {
let status = self.block_status(BlockId::Hash(parent_hash));
if status == BlockStatus::Unknown {
bail!(EthcoreErrorKind::Block(BlockError::UnknownParent(parent_hash)));
}
if !is_parent_pending && !self.chain.read().is_known(&parent_hash) {
bail!(EthcoreErrorKind::Block(BlockError::UnknownParent(parent_hash)));
}
}
@@ -2198,6 +2198,10 @@ impl IoClient for Client {
);
if let Err(e) = result {
error!(target: "client", "Error importing ancient block: {}", e);
let mut queued = queued.write();
queued.0.clear();
queued.1.clear();
}
// remove from pending
queued.write().0.remove(&hash);
@@ -2342,12 +2346,15 @@ impl ImportSealedBlock for Client {
);
self.notify(|notify| {
notify.new_blocks(
vec![hash],
vec![],
route.clone(),
vec![hash],
vec![],
start.elapsed(),
NewBlocks::new(
vec![hash],
vec![],
route.clone(),
vec![hash],
vec![],
start.elapsed(),
false
)
);
});
self.db.read().key_value().flush().expect("DB flush failed.");
@@ -2360,12 +2367,15 @@ impl BroadcastProposalBlock for Client {
const DURATION_ZERO: Duration = Duration::from_millis(0);
self.notify(|notify| {
notify.new_blocks(
vec![],
vec![],
ChainRoute::default(),
vec![],
vec![block.rlp_bytes()],
DURATION_ZERO,
NewBlocks::new(
vec![],
vec![],
ChainRoute::default(),
vec![],
vec![block.rlp_bytes()],
DURATION_ZERO,
false
)
);
});
}

View File

@@ -87,6 +87,7 @@ impl<'a> EvmTestClient<'a> {
ForkSpec::EIP158 => Some(ethereum::new_eip161_test()),
ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()),
ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()),
ForkSpec::ConstantinopleFix => Some(ethereum::new_constantinople_fix_test()),
ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()),
ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None,
}

View File

@@ -34,7 +34,7 @@ pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult};
pub use self::io_message::ClientIoMessage;
#[cfg(any(test, feature = "test-helpers"))]
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
pub use self::chain_notify::{ChainNotify, ChainRoute, ChainRouteType, ChainMessageType};
pub use self::chain_notify::{ChainNotify, NewBlocks, ChainRoute, ChainRouteType, ChainMessageType};
pub use self::traits::{
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock,
StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, BadBlocks,

View File

@@ -81,6 +81,8 @@ pub struct AuthorityRoundParams {
pub empty_steps_transition: u64,
/// Number of accepted empty steps.
pub maximum_empty_steps: usize,
/// Transition block to strict empty steps validation.
pub strict_empty_steps_transition: u64,
}
const U16_MAX: usize = ::std::u16::MAX as usize;
@@ -110,6 +112,7 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into),
empty_steps_transition: p.empty_steps_transition.map_or(u64::max_value(), |n| ::std::cmp::max(n.into(), 1)),
maximum_empty_steps: p.maximum_empty_steps.map_or(0, Into::into),
strict_empty_steps_transition: p.strict_empty_steps_transition.map_or(0, Into::into),
}
}
}
@@ -421,6 +424,7 @@ pub struct AuthorityRound {
maximum_uncle_count_transition: u64,
maximum_uncle_count: usize,
empty_steps_transition: u64,
strict_empty_steps_transition: u64,
maximum_empty_steps: usize,
machine: EthereumMachine,
}
@@ -674,6 +678,7 @@ impl AuthorityRound {
maximum_uncle_count: our_params.maximum_uncle_count,
empty_steps_transition: our_params.empty_steps_transition,
maximum_empty_steps: our_params.maximum_empty_steps,
strict_empty_steps_transition: our_params.strict_empty_steps_transition,
machine: machine,
});
@@ -1250,8 +1255,11 @@ impl Engine<EthereumMachine> for AuthorityRound {
// reported as there's no way to tell whether the empty step message was never sent or simply not included.
let empty_steps_len = if header.number() >= self.empty_steps_transition {
let validate_empty_steps = || -> Result<usize, Error> {
let strict_empty_steps = header.number() >= self.strict_empty_steps_transition;
let empty_steps = header_empty_steps(header)?;
let empty_steps_len = empty_steps.len();
let mut prev_empty_step = 0;
for empty_step in empty_steps {
if empty_step.step <= parent_step || empty_step.step >= step {
Err(EngineError::InsufficientProof(
@@ -1267,7 +1275,20 @@ impl Engine<EthereumMachine> for AuthorityRound {
Err(EngineError::InsufficientProof(
format!("invalid empty step proof: {:?}", empty_step)))?;
}
if strict_empty_steps {
if empty_step.step <= prev_empty_step {
Err(EngineError::InsufficientProof(format!(
"{} empty step: {:?}",
if empty_step.step == prev_empty_step { "duplicate" } else { "unordered" },
empty_step
)))?;
}
prev_empty_step = empty_step.step;
}
}
Ok(empty_steps_len)
};
@@ -1400,16 +1421,21 @@ impl Engine<EthereumMachine> for AuthorityRound {
let mut finality_proof: Vec<_> = itertools::repeat_call(move || {
chain(hash).and_then(|header| {
hash = *header.parent_hash();
if header.number() == 0 { return None }
else { return Some(header) }
if header.number() == 0 { None }
else { Some(header) }
})
})
.while_some()
.take_while(|h| h.hash() != *finalized_hash)
.collect();
let finalized_header = chain(*finalized_hash)
.expect("header is finalized; finalized headers must exist in the chain; qed");
let finalized_header = if *finalized_hash == chain_head.hash() {
// chain closure only stores ancestry, but the chain head is also unfinalized.
chain_head.clone()
} else {
chain(*finalized_hash)
.expect("header is finalized; finalized headers must exist in the chain; qed")
};
let signal_number = finalized_header.number();
info!(target: "engine", "Applying validator set change signalled at block {}", signal_number);
@@ -1518,10 +1544,40 @@ mod tests {
use spec::Spec;
use transaction::{Action, Transaction};
use engines::{Seal, Engine, EngineError, EthEngine};
use engines::validator_set::TestSet;
use engines::validator_set::{TestSet, SimpleList};
use error::{Error, ErrorKind};
use super::{AuthorityRoundParams, AuthorityRound, EmptyStep, SealedEmptyStep, calculate_score};
fn aura<F>(f: F) -> Arc<AuthorityRound> where
F: FnOnce(&mut AuthorityRoundParams),
{
let mut params = AuthorityRoundParams {
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::default()),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
strict_empty_steps_transition: 0,
};
// mutate aura params
f(&mut params);
// create engine
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap()
}
#[test]
fn has_valid_metadata() {
let engine = Spec::new_test_round().engine;
@@ -1695,28 +1751,9 @@ mod tests {
#[test]
fn reports_skipped() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let aura = {
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap()
};
let aura = aura(|p| {
p.validators = Box::new(TestSet::new(Default::default(), last_benign.clone()));
});
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&1usize)]);
@@ -1745,29 +1782,9 @@ mod tests {
#[test]
fn test_uncles_transition() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 1,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let aura = {
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap()
};
let aura = aura(|params| {
params.maximum_uncle_count_transition = 1;
});
assert_eq!(aura.maximum_uncle_count(0), 2);
assert_eq!(aura.maximum_uncle_count(1), 0);
@@ -1801,27 +1818,9 @@ mod tests {
#[test]
#[should_panic(expected="authority_round: step duration can't be zero")]
fn test_step_duration_zero() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 0,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap();
aura(|params| {
params.step_duration = 0;
});
}
fn setup_empty_steps() -> (Spec, Arc<AccountProvider>, Vec<Address>) {
@@ -1849,6 +1848,23 @@ mod tests {
SealedEmptyStep { signature, step }
}
fn set_empty_steps_seal(header: &mut Header, step: u64, block_signature: &ethkey::Signature, empty_steps: &[SealedEmptyStep]) {
header.set_seal(vec![
encode(&(step as usize)),
encode(&(&**block_signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
}
fn assert_insufficient_proof<T: ::std::fmt::Debug>(result: Result<T, Error>, contains: &str) {
match result {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _)) =>{
assert!(s.contains(contains), "Expected {:?} to contain {:?}", s, contains);
},
e => assert!(false, "Unexpected result: {:?}", e),
}
}
#[test]
fn broadcast_empty_step_message() {
let (spec, tap, accounts) = setup_empty_steps();
@@ -2050,46 +2066,31 @@ mod tests {
// empty step with invalid step
let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 2 }];
header.set_seal(vec![
encode(&2usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
assert!(match engine.verify_block_family(&header, &parent_header) {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _))
if s.contains("invalid step") => true,
_ => false,
});
assert_insufficient_proof(
engine.verify_block_family(&header, &parent_header),
"invalid step"
);
// empty step with invalid signature
let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 1 }];
header.set_seal(vec![
encode(&2usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
assert!(match engine.verify_block_family(&header, &parent_header) {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _))
if s.contains("invalid empty step proof") => true,
_ => false,
});
assert_insufficient_proof(
engine.verify_block_family(&header, &parent_header),
"invalid empty step proof"
);
// empty step with valid signature from incorrect proposer for step
engine.set_signer(tap.clone(), addr1, "1".into());
let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())];
header.set_seal(vec![
encode(&2usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
assert!(match engine.verify_block_family(&header, &parent_header) {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _))
if s.contains("invalid empty step proof") => true,
_ => false,
});
assert_insufficient_proof(
engine.verify_block_family(&header, &parent_header),
"invalid empty step proof"
);
// valid empty steps
engine.set_signer(tap.clone(), addr1, "1".into());
@@ -2100,11 +2101,7 @@ mod tests {
let empty_steps = vec![empty_step2, empty_step3];
header.set_difficulty(calculate_score(0, 4, 2));
let signature = tap.sign(addr1, Some("1".into()), header.bare_hash()).unwrap();
header.set_seal(vec![
encode(&4usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
set_empty_steps_seal(&mut header, 4, &signature, &empty_steps);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
}
@@ -2216,28 +2213,11 @@ mod tests {
#[test]
fn test_empty_steps() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 4,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: 0,
maximum_empty_steps: 10,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
let engine = AuthorityRound::new(params, machine).unwrap();
let engine = aura(|p| {
p.step_duration = 4;
p.empty_steps_transition = 0;
p.maximum_empty_steps = 0;
});
let parent_hash: H256 = 1.into();
let signature = H520::default();
@@ -2261,4 +2241,85 @@ mod tests {
assert_eq!(engine.empty_steps(0, 3, parent_hash), vec![]);
assert_eq!(engine.empty_steps(0, 4, parent_hash), vec![step(3)]);
}
#[test]
fn should_reject_duplicate_empty_steps() {
// given
let (_spec, tap, accounts) = setup_empty_steps();
let engine = aura(|p| {
p.validators = Box::new(SimpleList::new(accounts.clone()));
p.step_duration = 4;
p.empty_steps_transition = 0;
p.maximum_empty_steps = 0;
});
let mut parent = Header::default();
parent.set_seal(vec![encode(&0usize)]);
let mut header = Header::default();
header.set_number(parent.number() + 1);
header.set_parent_hash(parent.hash());
header.set_author(accounts[0]);
// when
engine.set_signer(tap.clone(), accounts[1], "0".into());
let empty_steps = vec![
sealed_empty_step(&*engine, 1, &parent.hash()),
sealed_empty_step(&*engine, 1, &parent.hash()),
];
let step = 2;
let signature = tap.sign(accounts[0], Some("1".into()), header.bare_hash()).unwrap();
set_empty_steps_seal(&mut header, step, &signature, &empty_steps);
header.set_difficulty(calculate_score(0, step, empty_steps.len()));
// then
assert_insufficient_proof(
engine.verify_block_family(&header, &parent),
"duplicate empty step"
);
}
#[test]
fn should_reject_empty_steps_out_of_order() {
// given
let (_spec, tap, accounts) = setup_empty_steps();
let engine = aura(|p| {
p.validators = Box::new(SimpleList::new(accounts.clone()));
p.step_duration = 4;
p.empty_steps_transition = 0;
p.maximum_empty_steps = 0;
});
let mut parent = Header::default();
parent.set_seal(vec![encode(&0usize)]);
let mut header = Header::default();
header.set_number(parent.number() + 1);
header.set_parent_hash(parent.hash());
header.set_author(accounts[0]);
// when
engine.set_signer(tap.clone(), accounts[1], "0".into());
let es1 = sealed_empty_step(&*engine, 1, &parent.hash());
engine.set_signer(tap.clone(), accounts[0], "1".into());
let es2 = sealed_empty_step(&*engine, 2, &parent.hash());
let mut empty_steps = vec![es2, es1];
let step = 3;
let signature = tap.sign(accounts[1], Some("0".into()), header.bare_hash()).unwrap();
set_empty_steps_seal(&mut header, step, &signature, &empty_steps);
header.set_difficulty(calculate_score(0, step, empty_steps.len()));
// then make sure it's rejected because of the order
assert_insufficient_proof(
engine.verify_block_family(&header, &parent),
"unordered empty step"
);
// now try to fix the order
empty_steps.reverse();
set_empty_steps_seal(&mut header, step, &signature, &empty_steps);
assert_eq!(engine.verify_block_family(&header, &parent).unwrap(), ());
}
}

View File

@@ -34,12 +34,18 @@ pub struct TestSet {
last_benign: Arc<AtomicUsize>,
}
impl Default for TestSet {
fn default() -> Self {
TestSet::new(Default::default(), Default::default())
}
}
impl TestSet {
pub fn new(last_malicious: Arc<AtomicUsize>, last_benign: Arc<AtomicUsize>) -> Self {
TestSet {
validator: SimpleList::new(vec![Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()]),
last_malicious: last_malicious,
last_benign: last_benign,
last_malicious,
last_benign,
}
}
}

View File

@@ -89,6 +89,8 @@ pub enum BlockError {
InvalidNumber(Mismatch<BlockNumber>),
/// Block number isn't sensible.
RidiculousNumber(OutOfBounds<BlockNumber>),
/// Timestamp header overflowed
TimestampOverflow,
/// Too many transactions from a particular address.
TooManyTransactions(Address),
/// Parent given is unknown.
@@ -138,6 +140,7 @@ impl fmt::Display for BlockError {
UnknownParent(ref hash) => format!("Unknown parent: {}", hash),
UnknownUncleParent(ref hash) => format!("Unknown uncle parent: {}", hash),
UnknownEpochTransition(ref num) => format!("Unknown transition to epoch number: {}", num),
TimestampOverflow => format!("Timestamp overflow"),
TooManyTransactions(ref address) => format!("Too many transactions from: {}", address),
};

View File

@@ -143,6 +143,9 @@ pub fn new_byzantium_test() -> Spec { load(None, include_bytes!("../../res/ether
/// Create a new Foundation Constantinople era spec.
pub fn new_constantinople_test() -> Spec { load(None, include_bytes!("../../res/ethereum/constantinople_test.json")) }
/// Create a new Foundation St. Peter's (Contantinople Fix) era spec.
pub fn new_constantinople_fix_test() -> Spec { load(None, include_bytes!("../../res/ethereum/st_peters_test.json")) }
/// Create a new Musicoin-MCIP3-era spec.
pub fn new_mcip3_test() -> Spec { load(None, include_bytes!("../../res/ethereum/mcip3_test.json")) }
@@ -163,6 +166,9 @@ pub fn new_byzantium_test_machine() -> EthereumMachine { load_machine(include_by
/// Create a new Foundation Constantinople era spec.
pub fn new_constantinople_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/constantinople_test.json")) }
/// Create a new Foundation St. Peter's (Contantinople Fix) era spec.
pub fn new_constantinople_fix_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/st_peters_test.json")) }
/// Create a new Musicoin-MCIP3-era spec.
pub fn new_mcip3_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) }

View File

@@ -311,7 +311,7 @@ impl<'a> CallCreateExecutive<'a> {
let prev_bal = state.balance(&params.address)?;
if let ActionValue::Transfer(val) = params.value {
state.sub_balance(&params.sender, &val, &mut substate.to_cleanup_mode(&schedule))?;
state.new_contract(&params.address, val + prev_bal, nonce_offset)?;
state.new_contract(&params.address, val.saturating_add(prev_bal), nonce_offset)?;
} else {
state.new_contract(&params.address, prev_bal, nonce_offset)?;
}
@@ -979,7 +979,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
scope.builder().stack_size(::std::cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer)
}).expect("Sub-thread creation cannot fail; the host might run out of resources; qed")
}).join()
}).join().expect("Sub-thread never panics; qed")
}
}
@@ -1063,7 +1063,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
scope.builder().stack_size(::std::cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
self.create_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer)
}).expect("Sub-thread creation cannot fail; the host might run out of resources; qed")
}).join()
}).join().expect("Sub-thread never panics; qed")
}
}
@@ -1102,9 +1102,13 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) >> 1);
let gas_left = gas_left_prerefund + refunded;
let gas_used = t.gas - gas_left;
let refund_value = gas_left * t.gas_price;
let fees_value = gas_used * t.gas_price;
let gas_used = t.gas.saturating_sub(gas_left);
let (refund_value, overflow_1) = gas_left.overflowing_mul(t.gas_price);
let (fees_value, overflow_2) = gas_used.overflowing_mul(t.gas_price);
if overflow_1 || overflow_2 {
return Err(ExecutionError::TransactionMalformed("U256 Overflow".to_string()));
}
trace!("exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={}\n",
t.gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value);
@@ -1122,7 +1126,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
}
// perform garbage-collection
let min_balance = if schedule.kill_dust != CleanDustMode::Off { Some(U256::from(schedule.tx_gas) * t.gas_price) } else { None };
let min_balance = if schedule.kill_dust != CleanDustMode::Off { Some(U256::from(schedule.tx_gas).overflowing_mul(t.gas_price).0) } else { None };
self.state.kill_garbage(&substate.touched, schedule.kill_empty, &min_balance, schedule.kill_dust == CleanDustMode::WithCodeAndStorage)?;
match result {

View File

@@ -116,7 +116,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
where T: Tracer, V: VMTracer, B: StateBackend
{
fn initial_storage_at(&self, key: &H256) -> vm::Result<H256> {
self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into)
if self.state.is_base_storage_root_unchanged(&self.origin_info.address)? {
self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into)
} else {
warn!(target: "externalities", "Detected existing account {:#x} where a forced contract creation happened.", self.origin_info.address);
Ok(H256::zero())
}
}
fn storage_at(&self, key: &H256) -> vm::Result<H256> {

View File

@@ -165,6 +165,7 @@ mod state_tests {
declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"}
declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"}
declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"}
declare_test!{GeneralStateTest_stSStoreTest, "GeneralStateTests/stSStoreTest/"}
declare_test!{GeneralStateTest_stShift, "GeneralStateTests/stShift/"}
declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"}
declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"}
@@ -177,7 +178,6 @@ mod state_tests {
declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"}
declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"}
declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"}
declare_test!{GeneralStateTest_stSStoreTest, "GeneralStateTests/stSStoreTest/"}
// Attempts to send a transaction that requires more than current balance:
// Tx:

View File

@@ -192,11 +192,11 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(
state_guards.push(state_guard);
}
let block_hashes = block_guard.join()?;
let block_hashes = block_guard.join().expect("Sub-thread never panics; qed")?;
let mut state_hashes = Vec::new();
for guard in state_guards {
let part_state_hashes = guard.join()?;
let part_state_hashes = guard.join().expect("Sub-thread never panics; qed")?;
state_hashes.extend(part_state_hashes);
}

View File

@@ -17,14 +17,13 @@
//! Watcher for snapshot-related chain events.
use parking_lot::Mutex;
use client::{BlockInfo, Client, ChainNotify, ChainRoute, ClientIoMessage};
use client::{BlockInfo, Client, ChainNotify, NewBlocks, ClientIoMessage};
use ids::BlockId;
use io::IoChannel;
use ethereum_types::H256;
use bytes::Bytes;
use std::{sync::Arc, time::Duration};
use std::sync::Arc;
// helper trait for transforming hashes to numbers and checking if syncing.
trait Oracle: Send + Sync {
@@ -99,20 +98,12 @@ impl Watcher {
}
impl ChainNotify for Watcher {
fn new_blocks(
&self,
imported: Vec<H256>,
_: Vec<H256>,
_: ChainRoute,
_: Vec<H256>,
_: Vec<Bytes>,
_duration: Duration)
{
if self.oracle.is_major_importing() { return }
fn new_blocks(&self, new_blocks: NewBlocks) {
if self.oracle.is_major_importing() || new_blocks.has_more_blocks_to_import { return }
trace!(target: "snapshot_watcher", "{} imported", imported.len());
trace!(target: "snapshot_watcher", "{} imported", new_blocks.imported.len());
let highest = imported.into_iter()
let highest = new_blocks.imported.into_iter()
.filter_map(|h| self.oracle.to_number(h))
.filter(|&num| num >= self.period + self.history)
.map(|num| num - self.history)
@@ -130,7 +121,7 @@ impl ChainNotify for Watcher {
mod tests {
use super::{Broadcast, Oracle, Watcher};
use client::{ChainNotify, ChainRoute};
use client::{ChainNotify, NewBlocks, ChainRoute};
use ethereum_types::{H256, U256};
@@ -170,14 +161,15 @@ mod tests {
history: history,
};
watcher.new_blocks(
watcher.new_blocks(NewBlocks::new(
hashes,
vec![],
ChainRoute::default(),
vec![],
vec![],
DURATION_ZERO,
);
false
));
}
// helper

View File

@@ -120,6 +120,8 @@ pub struct CommonParams {
pub eip1052_transition: BlockNumber,
/// Number of first block where EIP-1283 rules begin.
pub eip1283_transition: BlockNumber,
/// Number of first block where EIP-1283 rules end.
pub eip1283_disable_transition: BlockNumber,
/// Number of first block where EIP-1014 rules begin.
pub eip1014_transition: BlockNumber,
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
@@ -188,7 +190,7 @@ impl CommonParams {
schedule.have_return_data = block_number >= self.eip211_transition;
schedule.have_bitwise_shifting = block_number >= self.eip145_transition;
schedule.have_extcodehash = block_number >= self.eip1052_transition;
schedule.eip1283 = block_number >= self.eip1283_transition;
schedule.eip1283 = block_number >= self.eip1283_transition && !(block_number >= self.eip1283_disable_transition);
if block_number >= self.eip210_transition {
schedule.blockhash_gas = 800;
}
@@ -296,6 +298,10 @@ impl From<ethjson::spec::Params> for CommonParams {
BlockNumber::max_value,
Into::into,
),
eip1283_disable_transition: p.eip1283_disable_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1014_transition: p.eip1014_transition.map_or_else(
BlockNumber::max_value,
Into::into,

View File

@@ -447,6 +447,11 @@ impl Account {
}
}
/// Whether the base storage root of this account is unchanged.
pub fn is_base_storage_root_unchanged(&self) -> bool {
self.original_storage_cache.is_none()
}
/// Storage root where the account changes are based upon.
pub fn base_storage_root(&self) -> H256 {
self.storage_root
@@ -457,12 +462,12 @@ impl Account {
/// Increment the nonce of the account by one.
pub fn inc_nonce(&mut self) {
self.nonce = self.nonce + U256::from(1u8);
self.nonce = self.nonce.saturating_add(U256::from(1u8));
}
/// Increase account balance.
pub fn add_balance(&mut self, x: &U256) {
self.balance = self.balance + *x;
self.balance = self.balance.saturating_add(*x);
}
/// Decrease account balance.

View File

@@ -500,7 +500,12 @@ impl<B: Backend> State<B> {
/// it will have its code reset, ready for `init_code()`.
pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) -> TrieResult<()> {
let original_storage_root = self.original_storage_root(contract)?;
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset, original_storage_root))));
let (nonce, overflow) = self.account_start_nonce.overflowing_add(nonce_offset);
if overflow {
return Err(Box::new(TrieError::DecoderError(H256::from(contract),
rlp::DecoderError::Custom("Nonce overflow".into()))));
}
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, nonce, original_storage_root))));
Ok(())
}
@@ -539,6 +544,13 @@ impl<B: Backend> State<B> {
|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce()))
}
/// Whether the base storage root of an account remains unchanged.
pub fn is_base_storage_root_unchanged(&self, a: &Address) -> TrieResult<bool> {
Ok(self.ensure_cached(a, RequireCache::None, true,
|a| a.as_ref().map(|account| account.is_base_storage_root_unchanged()))?
.unwrap_or(true))
}
/// Get the storage root of account `a`.
pub fn storage_root(&self, a: &Address) -> TrieResult<Option<H256>> {
self.ensure_cached(a, RequireCache::None, true,
@@ -1136,7 +1148,7 @@ impl<B: Backend> State<B> {
self.note_cache(a);
// at this point the entry is guaranteed to be in the cache.
Ok(RefMut::map(self.cache.borrow_mut(), |c| {
let mut account = RefMut::map(self.cache.borrow_mut(), |c| {
let entry = c.get_mut(a).expect("entry known to exist in the cache; qed");
match &mut entry.account {
@@ -1146,18 +1158,19 @@ impl<B: Backend> State<B> {
// set the dirty flag after changing account data.
entry.state = AccountState::Dirty;
match entry.account {
Some(ref mut account) => {
if require_code {
let addr_hash = account.address_hash(a);
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), addr_hash);
Self::update_account_cache(RequireCache::Code, account, &self.db, accountdb.as_hashdb());
}
account
},
_ => panic!("Required account must always exist; qed"),
entry.account.as_mut().expect("Required account must always exist; qed")
});
if require_code {
let addr_hash = account.address_hash(a);
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), addr_hash);
if !Self::update_account_cache(RequireCache::Code, &mut account, &self.db, accountdb.as_hashdb()) {
return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a))))
}
}))
}
Ok(account)
}
/// Replace account code and storage. Creates account if it does not exist.
@@ -2591,12 +2604,12 @@ mod tests {
assert_eq!(diff_map.len(), 1);
assert!(diff_map.get(&a).is_some());
assert_eq!(diff_map.get(&a),
pod_account::diff_pod(Some(&PodAccount {
balance: U256::from(100),
nonce: U256::zero(),
code: Some(Default::default()),
storage: Default::default()
}), None).as_ref());
pod_account::diff_pod(Some(&PodAccount {
balance: U256::from(100),
nonce: U256::zero(),
code: Some(Default::default()),
storage: Default::default()
}), None).as_ref());
}
#[test]
@@ -2622,18 +2635,18 @@ mod tests {
assert_eq!(diff_map.len(), 1);
assert!(diff_map.get(&a).is_some());
assert_eq!(diff_map.get(&a),
pod_account::diff_pod(Some(&PodAccount {
balance: U256::zero(),
nonce: U256::zero(),
code: Some(Default::default()),
storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(20u64)))]
.into_iter().collect(),
}), Some(&PodAccount {
balance: U256::zero(),
nonce: U256::zero(),
code: Some(Default::default()),
storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(100u64)))]
.into_iter().collect(),
})).as_ref());
pod_account::diff_pod(Some(&PodAccount {
balance: U256::zero(),
nonce: U256::zero(),
code: Some(Default::default()),
storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(20u64)))]
.into_iter().collect(),
}), Some(&PodAccount {
balance: U256::zero(),
nonce: U256::zero(),
code: Some(Default::default()),
storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(100u64)))]
.into_iter().collect(),
})).as_ref());
}
}

View File

@@ -39,6 +39,25 @@ use header::{BlockNumber, Header};
use transaction::SignedTransaction;
use verification::queue::kind::blocks::Unverified;
/// Returns `Ok<SystemTime>` when the result less or equal to `i32::max_value` to prevent `SystemTime` to panic because
/// it is platform specific, may be i32 or i64.
///
/// `Err<BlockError::TimestampOver` otherwise.
///
// FIXME: @niklasad1 - remove this when and use `SystemTime::checked_add`
// when https://github.com/rust-lang/rust/issues/55940 is stabilized.
fn timestamp_checked_add(sys: SystemTime, d2: Duration) -> Result<SystemTime, BlockError> {
let d1 = sys.duration_since(UNIX_EPOCH).map_err(|_| BlockError::TimestampOverflow)?;
let total_time = d1.checked_add(d2).ok_or(BlockError::TimestampOverflow)?;
if total_time.as_secs() <= i32::max_value() as u64 {
Ok(sys + d2)
} else {
Err(BlockError::TimestampOverflow)
}
}
/// Preprocessed block data gathered in `verify_block_unordered` call
pub struct PreverifiedBlock {
/// Populated block header
@@ -305,7 +324,7 @@ pub fn verify_header_params(header: &Header, engine: &EthEngine, is_full: bool,
const ACCEPTABLE_DRIFT: Duration = Duration::from_secs(15);
let max_time = SystemTime::now() + ACCEPTABLE_DRIFT;
let invalid_threshold = max_time + ACCEPTABLE_DRIFT * 9;
let timestamp = UNIX_EPOCH + Duration::from_secs(header.timestamp());
let timestamp = timestamp_checked_add(UNIX_EPOCH, Duration::from_secs(header.timestamp()))?;
if timestamp > invalid_threshold {
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: timestamp })))
@@ -327,8 +346,8 @@ fn verify_parent(header: &Header, parent: &Header, engine: &EthEngine) -> Result
let gas_limit_divisor = engine.params().gas_limit_bound_divisor;
if !engine.is_timestamp_valid(header.timestamp(), parent.timestamp()) {
let min = SystemTime::now() + Duration::from_secs(parent.timestamp() + 1);
let found = SystemTime::now() + Duration::from_secs(header.timestamp());
let min = timestamp_checked_add(SystemTime::now(), Duration::from_secs(parent.timestamp().saturating_add(1)))?;
let found = timestamp_checked_add(SystemTime::now(), Duration::from_secs(header.timestamp()))?;
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(min), found })))
}
if header.number() != parent.number() + 1 {
@@ -734,7 +753,8 @@ mod tests {
check_fail_timestamp(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc), false);
header = good.clone();
header.set_timestamp(2450000000);
// will return `BlockError::TimestampOverflow` when timestamp > `i32::max_value()`
header.set_timestamp(i32::max_value() as u64);
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine), false);
header = good.clone();
@@ -806,4 +826,11 @@ mod tests {
check_fail(unordered_test(&create_test_block_with_data(&header, &bad_transactions, &[]), &engine), TooManyTransactions(keypair.address()));
unordered_test(&create_test_block_with_data(&header, &good_transactions, &[]), &engine).unwrap();
}
#[test]
fn checked_add_systime_dur() {
assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 + 1, 0)).is_err());
assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64, 0)).is_ok());
assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 - 1, 1_000_000_000)).is_ok());
}
}

View File

@@ -29,7 +29,7 @@ use types::pruning_info::PruningInfo;
use ethereum_types::{H256, H512, U256};
use io::{TimerToken};
use ethcore::ethstore::ethkey::Secret;
use ethcore::client::{BlockChainClient, ChainNotify, ChainRoute, ChainMessageType};
use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks, ChainMessageType};
use ethcore::snapshot::SnapshotService;
use ethcore::header::BlockNumber;
use sync_io::NetSyncIo;
@@ -498,14 +498,9 @@ impl ChainNotify for EthSync {
}
}
fn new_blocks(&self,
imported: Vec<H256>,
invalid: Vec<H256>,
route: ChainRoute,
sealed: Vec<H256>,
proposed: Vec<Bytes>,
_duration: Duration)
fn new_blocks(&self, new_blocks: NewBlocks)
{
if new_blocks.has_more_blocks_to_import { return }
use light::net::Announcement;
self.network.with_context(self.subprotocol_name, |context| {
@@ -513,12 +508,12 @@ impl ChainNotify for EthSync {
&self.eth_handler.overlay);
self.eth_handler.sync.write().chain_new_blocks(
&mut sync_io,
&imported,
&invalid,
route.enacted(),
route.retracted(),
&sealed,
&proposed);
&new_blocks.imported,
&new_blocks.invalid,
new_blocks.route.enacted(),
new_blocks.route.retracted(),
&new_blocks.sealed,
&new_blocks.proposed);
});
self.network.with_context(self.light_subprotocol_name, |context| {

View File

@@ -45,13 +45,13 @@ fn accepts_service_transaction(client_id: &str) -> bool {
// Parity versions starting from this will accept service-transactions
const SERVICE_TRANSACTIONS_VERSION: (u32, u32) = (1u32, 6u32);
// Parity client string prefix
const LEGACY_CLIENT_ID_PREFIX: &'static str = "Parity/v";
const PARITY_CLIENT_ID_PREFIX: &'static str = "Parity-Ethereum/v";
let splitted = if client_id.starts_with(LEGACY_CLIENT_ID_PREFIX) {
client_id[LEGACY_CLIENT_ID_PREFIX.len()..].split('.')
} else if client_id.starts_with(PARITY_CLIENT_ID_PREFIX) {
client_id[PARITY_CLIENT_ID_PREFIX.len()..].split('.')
const LEGACY_CLIENT_ID_PREFIX: &'static str = "Parity/";
const PARITY_CLIENT_ID_PREFIX: &'static str = "Parity-Ethereum/";
const VERSION_PREFIX: &'static str = "/v";
let idx = client_id.rfind(VERSION_PREFIX).map(|idx| idx + VERSION_PREFIX.len()).unwrap_or(client_id.len());
let splitted = if client_id.starts_with(LEGACY_CLIENT_ID_PREFIX) || client_id.starts_with(PARITY_CLIENT_ID_PREFIX) {
client_id[idx..].split('.')
} else {
return false;
};
@@ -599,7 +599,7 @@ mod tests {
io.peers_info.insert(3, "Parity/v1.5".to_owned());
// and peer#4 is Parity, accepting service transactions
insert_dummy_peer(&mut sync, 4, block_hash);
io.peers_info.insert(4, "Parity-Ethereum/v2.7.3-ABCDEFGH".to_owned());
io.peers_info.insert(4, "Parity-Ethereum/ABCDEFGH/v2.7.3".to_owned());
// and new service transaction is propagated to peers
SyncPropagator::propagate_new_transactions(&mut sync, &mut io, || true);

View File

@@ -16,14 +16,13 @@
use std::collections::{VecDeque, HashSet, HashMap};
use std::sync::Arc;
use std::time::Duration;
use ethereum_types::H256;
use parking_lot::{RwLock, Mutex};
use bytes::Bytes;
use network::{self, PeerId, ProtocolId, PacketId, SessionInfo};
use tests::snapshot::*;
use ethcore::client::{TestBlockChainClient, BlockChainClient, Client as EthcoreClient,
ClientConfig, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage};
ClientConfig, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage};
use ethcore::header::BlockNumber;
use ethcore::snapshot::SnapshotService;
use ethcore::spec::Spec;
@@ -535,23 +534,18 @@ impl IoHandler<ClientIoMessage> for TestIoHandler {
}
impl ChainNotify for EthPeer<EthcoreClient> {
fn new_blocks(&self,
imported: Vec<H256>,
invalid: Vec<H256>,
route: ChainRoute,
sealed: Vec<H256>,
proposed: Vec<Bytes>,
_duration: Duration)
fn new_blocks(&self, new_blocks: NewBlocks)
{
let (enacted, retracted) = route.into_enacted_retracted();
if new_blocks.has_more_blocks_to_import { return }
let (enacted, retracted) = new_blocks.route.into_enacted_retracted();
self.new_blocks_queue.write().push_back(NewBlockMessage {
imported,
invalid,
imported: new_blocks.imported,
invalid: new_blocks.invalid,
enacted,
retracted,
sealed,
proposed,
sealed: new_blocks.sealed,
proposed: new_blocks.proposed,
});
}

View File

@@ -9,7 +9,7 @@ ethereum-types = "0.4"
log = "0.4"
parity-wasm = "0.31"
libc = "0.2"
pwasm-utils = "0.2.2"
pwasm-utils = "0.6.1"
vm = { path = "../vm" }
ethcore-logger = { path = "../../logger" }
wasmi = "0.3.0"

View File

@@ -68,6 +68,8 @@ pub struct AuthorityRoundParams {
/// Maximum number of accepted empty steps.
#[serde(rename="maximumEmptySteps")]
pub maximum_empty_steps: Option<Uint>,
/// Strict validation of empty steps transition block.
pub strict_empty_steps_transition: Option<Uint>,
}
/// Authority engine deserialization.

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity is free software: you can redistribute it and/or modify
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec params deserialization.
@@ -112,6 +112,10 @@ pub struct Params {
/// See `CommonParams` docs.
#[serde(rename="eip1283Transition")]
pub eip1283_transition: Option<Uint>,
/// See `CommonParams` docs.
#[serde(rename="eip1283DisableTransition")]
pub eip1283_disable_transition: Option<Uint>,
/// See `CommonParams` docs.
#[serde(rename="eip1014Transition")]
pub eip1014_transition: Option<Uint>,
/// See `CommonParams` docs.
@@ -210,3 +214,4 @@ mod tests {
let _deserialized: Params = serde_json::from_str(s).unwrap();
}
}

View File

@@ -30,6 +30,7 @@ pub enum ForkSpec {
Homestead,
Byzantium,
Constantinople,
ConstantinopleFix,
EIP158ToByzantiumAt5,
FrontierToHomesteadAt5,
HomesteadToDaoAt5,

View File

@@ -474,7 +474,7 @@ impl TransactionQueue {
self.pool.read().pending_from_sender(state_readiness, address)
.last()
.map(|tx| tx.signed().nonce + 1)
.map(|tx| tx.signed().nonce.saturating_add(U256::from(1)))
}
/// Retrieve a transaction from the pool.

View File

@@ -95,7 +95,7 @@ impl<C: NonceClient> txpool::Ready<VerifiedTransaction> for State<C> {
},
cmp::Ordering::Less => txpool::Readiness::Stale,
cmp::Ordering::Equal => {
*nonce = *nonce + 1;
*nonce = nonce.saturating_add(U256::from(1));
txpool::Readiness::Ready
},
}
@@ -159,7 +159,7 @@ impl<C: Fn(&Address) -> Option<U256>> txpool::Ready<VerifiedTransaction> for Opt
cmp::Ordering::Greater => txpool::Readiness::Future,
cmp::Ordering::Less => txpool::Readiness::Stale,
cmp::Ordering::Equal => {
*nonce = *nonce + 1;
*nonce = nonce.saturating_add(U256::from(1));
txpool::Readiness::Ready
},
}

View File

@@ -26,12 +26,18 @@ pub mod client;
use self::tx::{Tx, TxExt, PairExt};
use self::client::TestClient;
// max mem for 3 transaction, this is relative
// to the global use allocator, the value is currently
// set to reflect malloc usage.
// 50 was enough when using jmalloc.
const TEST_QUEUE_MAX_MEM: usize = 80;
fn new_queue() -> TransactionQueue {
TransactionQueue::new(
txpool::Options {
max_count: 3,
max_per_sender: 3,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -49,7 +55,7 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() {
txpool::Options {
max_count: 3,
max_per_sender: 1,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -103,7 +109,7 @@ fn should_never_drop_local_transactions_from_different_senders() {
txpool::Options {
max_count: 3,
max_per_sender: 1,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -477,7 +483,7 @@ fn should_prefer_current_transactions_when_hitting_the_limit() {
txpool::Options {
max_count: 1,
max_per_sender: 2,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -707,7 +713,7 @@ fn should_accept_local_transactions_below_min_gas_price() {
txpool::Options {
max_count: 3,
max_per_sender: 3,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 10.into(),
@@ -890,7 +896,7 @@ fn should_include_local_transaction_to_a_full_pool() {
txpool::Options {
max_count: 1,
max_per_sender: 2,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -922,7 +928,7 @@ fn should_avoid_verifying_transaction_already_in_pool() {
txpool::Options {
max_count: 1,
max_per_sender: 2,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -957,7 +963,7 @@ fn should_avoid_reverifying_recently_rejected_transactions() {
txpool::Options {
max_count: 1,
max_per_sender: 2,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -999,7 +1005,7 @@ fn should_reject_early_in_case_gas_price_is_less_than_min_effective() {
txpool::Options {
max_count: 1,
max_per_sender: 2,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),
@@ -1039,7 +1045,7 @@ fn should_not_reject_early_in_case_gas_price_is_less_than_min_effective() {
txpool::Options {
max_count: 1,
max_per_sender: 2,
max_mem_usage: 50
max_mem_usage: TEST_QUEUE_MAX_MEM
},
verifier::Options {
minimal_gas_price: 1.into(),

View File

@@ -283,7 +283,19 @@ impl<C: Client> txpool::Verifier<Transaction> for Verifier<C, ::pool::scoring::N
}
}
let cost = transaction.value + transaction.gas_price * transaction.gas;
let (full_gas_price, overflow_1) = transaction.gas_price.overflowing_mul(transaction.gas);
let (cost, overflow_2) = transaction.value.overflowing_add(full_gas_price);
if overflow_1 || overflow_2 {
trace!(
target: "txqueue",
"[{:?}] Rejected tx, price overflow",
hash
);
bail!(transaction::Error::InsufficientBalance {
cost: U256::max_value(),
balance: account_details.balance,
});
}
if account_details.balance < cost {
debug!(
target: "txqueue",

View File

@@ -25,7 +25,7 @@ use std::time::{Instant, Duration};
use atty;
use ethcore::client::{
BlockId, BlockChainClient, ChainInfo, BlockInfo, BlockChainInfo,
BlockQueueInfo, ChainNotify, ChainRoute, ClientReport, Client, ClientIoMessage
BlockQueueInfo, ChainNotify, NewBlocks, ClientReport, Client, ClientIoMessage
};
use ethcore::header::BlockNumber;
use ethcore::snapshot::{RestorationStatus, SnapshotService as SS};
@@ -38,7 +38,6 @@ use number_prefix::{binary_prefix, Standalone, Prefixed};
use parity_rpc::is_major_importing_or_waiting;
use parity_rpc::informant::RpcStats;
use ethereum_types::H256;
use bytes::Bytes;
use parking_lot::{RwLock, Mutex};
/// Format byte counts to standard denominations.
@@ -365,29 +364,30 @@ impl<T: InformantData> Informant<T> {
}
impl ChainNotify for Informant<FullNodeInformantData> {
fn new_blocks(&self, imported: Vec<H256>, _invalid: Vec<H256>, _route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, duration: Duration) {
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.has_more_blocks_to_import { return }
let mut last_import = self.last_import.lock();
let client = &self.target.client;
let importing = self.target.is_major_importing();
let ripe = Instant::now() > *last_import + Duration::from_secs(1) && !importing;
let txs_imported = imported.iter()
.take(imported.len().saturating_sub(if ripe { 1 } else { 0 }))
let txs_imported = new_blocks.imported.iter()
.take(new_blocks.imported.len().saturating_sub(if ripe { 1 } else { 0 }))
.filter_map(|h| client.block(BlockId::Hash(*h)))
.map(|b| b.transactions_count())
.sum();
if ripe {
if let Some(block) = imported.last().and_then(|h| client.block(BlockId::Hash(*h))) {
if let Some(block) = new_blocks.imported.last().and_then(|h| client.block(BlockId::Hash(*h))) {
let header_view = block.header_view();
let size = block.rlp().as_raw().len();
let (skipped, skipped_txs) = (self.skipped.load(AtomicOrdering::Relaxed) + imported.len() - 1, self.skipped_txs.load(AtomicOrdering::Relaxed) + txs_imported);
let (skipped, skipped_txs) = (self.skipped.load(AtomicOrdering::Relaxed) + new_blocks.imported.len() - 1, self.skipped_txs.load(AtomicOrdering::Relaxed) + txs_imported);
info!(target: "import", "Imported {} {} ({} txs, {} Mgas, {} ms, {} KiB){}",
Colour::White.bold().paint(format!("#{}", header_view.number())),
Colour::White.bold().paint(format!("{}", header_view.hash())),
Colour::Yellow.bold().paint(format!("{}", block.transactions_count())),
Colour::Yellow.bold().paint(format!("{:.2}", header_view.gas_used().low_u64() as f32 / 1000000f32)),
Colour::Purple.bold().paint(format!("{}", duration.as_milliseconds())),
Colour::Purple.bold().paint(format!("{}", new_blocks.duration.as_milliseconds())),
Colour::Blue.bold().paint(format!("{:.2}", size as f32 / 1024f32)),
if skipped > 0 {
format!(" + another {} block(s) containing {} tx(s)",
@@ -403,7 +403,7 @@ impl ChainNotify for Informant<FullNodeInformantData> {
*last_import = Instant::now();
}
} else {
self.skipped.fetch_add(imported.len(), AtomicOrdering::Relaxed);
self.skipped.fetch_add(new_blocks.imported.len(), AtomicOrdering::Relaxed);
self.skipped_txs.fetch_add(txs_imported, AtomicOrdering::Relaxed);
}
}

View File

@@ -41,11 +41,11 @@ use sync::LightSync;
use transaction::{Action, SignedTransaction, PendingTransaction, Transaction, Error as TransactionError};
use jsonrpc_core::{BoxFuture, Result, Error};
use jsonrpc_core::futures::{future, Future, Poll, Async};
use jsonrpc_core::futures::{future, Future, Poll, Async, IntoFuture};
use jsonrpc_core::futures::future::Either;
use v1::helpers::{errors, nonce, TransactionRequest, FilledTransactionRequest, ConfirmationPayload};
use v1::types::{
H256 as RpcH256, H520 as RpcH520, Bytes as RpcBytes,
H520 as RpcH520, Bytes as RpcBytes,
RichRawTransaction as RpcRichRawTransaction,
ConfirmationPayload as RpcConfirmationPayload,
ConfirmationResponse,
@@ -69,12 +69,20 @@ pub trait Dispatcher: Send + Sync + Clone {
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool)
-> BoxFuture<FilledTransactionRequest>;
/// Sign the given transaction request without dispatching, fetching appropriate nonce.
fn sign(&self, accounts: Arc<AccountProvider>, filled: FilledTransactionRequest, password: SignWith)
-> BoxFuture<WithToken<SignedTransaction>>;
/// Sign the given transaction request, fetching appropriate nonce and executing the PostSign action
fn sign<P>(
&self,
accounts: Arc<AccountProvider>,
filled: FilledTransactionRequest,
password: SignWith,
post_sign: P
) -> BoxFuture<P::Item>
where
P: PostSign + 'static,
<P::Out as futures::future::IntoFuture>::Future: Send;
/// Converts a `SignedTransaction` into `RichRawTransaction`
fn enrich(&self, SignedTransaction) -> RpcRichRawTransaction;
fn enrich(&self, signed: SignedTransaction) -> RpcRichRawTransaction;
/// "Dispatch" a local transaction.
fn dispatch_transaction(&self, signed_transaction: PendingTransaction)
@@ -164,19 +172,30 @@ impl<C: miner::BlockChainClient + BlockChainClient, M: MinerService> Dispatcher
}))
}
fn sign(&self, accounts: Arc<AccountProvider>, filled: FilledTransactionRequest, password: SignWith)
-> BoxFuture<WithToken<SignedTransaction>>
fn sign<P>(
&self,
accounts: Arc<AccountProvider>,
filled: FilledTransactionRequest,
password: SignWith,
post_sign: P
) -> BoxFuture<P::Item>
where
P: PostSign + 'static,
<P::Out as futures::future::IntoFuture>::Future: Send
{
let chain_id = self.client.signing_chain_id();
if let Some(nonce) = filled.nonce {
return Box::new(future::done(sign_transaction(&*accounts, filled, chain_id, nonce, password)));
let future = sign_transaction(&*accounts, filled, chain_id, nonce, password)
.into_future()
.and_then(move |signed| post_sign.execute(signed));
Box::new(future)
} else {
let state = self.state_nonce(&filled.from);
let reserved = self.nonces.lock().reserve(filled.from, state);
Box::new(ProspectiveSigner::new(accounts, filled, chain_id, reserved, password, post_sign))
}
let state = self.state_nonce(&filled.from);
let reserved = self.nonces.lock().reserve(filled.from, state);
Box::new(ProspectiveSigner::new(accounts, filled, chain_id, reserved, password))
}
fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction {
@@ -396,12 +415,24 @@ impl Dispatcher for LightDispatcher {
}))
}
fn sign(&self, accounts: Arc<AccountProvider>, filled: FilledTransactionRequest, password: SignWith)
-> BoxFuture<WithToken<SignedTransaction>>
fn sign<P>(
&self,
accounts: Arc<AccountProvider>,
filled: FilledTransactionRequest,
password: SignWith,
post_sign: P
) -> BoxFuture<P::Item>
where
P: PostSign + 'static,
<P::Out as futures::future::IntoFuture>::Future: Send
{
let chain_id = self.client.signing_chain_id();
let nonce = filled.nonce.expect("nonce is always provided; qed");
Box::new(future::done(sign_transaction(&*accounts, filled, chain_id, nonce, password)))
let future = sign_transaction(&*accounts, filled, chain_id, nonce, password)
.into_future()
.and_then(move |signed| post_sign.execute(signed));
Box::new(future)
}
fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction {
@@ -449,28 +480,60 @@ fn sign_transaction(
#[derive(Debug, Clone, Copy)]
enum ProspectiveSignerState {
TryProspectiveSign,
WaitForPostSign,
WaitForNonce,
Finish,
}
struct ProspectiveSigner {
struct ProspectiveSigner<P: PostSign> {
accounts: Arc<AccountProvider>,
filled: FilledTransactionRequest,
chain_id: Option<u64>,
reserved: nonce::Reserved,
password: SignWith,
state: ProspectiveSignerState,
prospective: Option<Result<WithToken<SignedTransaction>>>,
prospective: Option<WithToken<SignedTransaction>>,
ready: Option<nonce::Ready>,
post_sign: Option<P>,
post_sign_future: Option<<P::Out as IntoFuture>::Future>
}
impl ProspectiveSigner {
/// action to execute after signing
/// e.g importing a transaction into the chain
pub trait PostSign: Send {
/// item that this PostSign returns
type Item: Send;
/// incase you need to perform async PostSign actions
type Out: IntoFuture<Item = Self::Item, Error = Error> + Send;
/// perform an action with the signed transaction
fn execute(self, signer: WithToken<SignedTransaction>) -> Self::Out;
}
impl PostSign for () {
type Item = WithToken<SignedTransaction>;
type Out = Result<Self::Item>;
fn execute(self, signed: WithToken<SignedTransaction>) -> Self::Out {
Ok(signed)
}
}
impl<F: Send, T: Send> PostSign for F
where F: FnOnce(WithToken<SignedTransaction>) -> Result<T>
{
type Item = T;
type Out = Result<Self::Item>;
fn execute(self, signed: WithToken<SignedTransaction>) -> Self::Out {
(self)(signed)
}
}
impl<P: PostSign> ProspectiveSigner<P> {
pub fn new(
accounts: Arc<AccountProvider>,
filled: FilledTransactionRequest,
chain_id: Option<u64>,
reserved: nonce::Reserved,
password: SignWith,
post_sign: P
) -> Self {
// If the account is permanently unlocked we can try to sign
// using prospective nonce. This should speed up sending
@@ -491,6 +554,8 @@ impl ProspectiveSigner {
},
prospective: None,
ready: None,
post_sign: Some(post_sign),
post_sign_future: None
}
}
@@ -509,8 +574,8 @@ impl ProspectiveSigner {
}
}
impl Future for ProspectiveSigner {
type Item = WithToken<SignedTransaction>;
impl<P: PostSign> Future for ProspectiveSigner<P> {
type Item = P::Item;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
@@ -523,32 +588,45 @@ impl Future for ProspectiveSigner {
match self.poll_reserved()? {
Async::NotReady => {
self.state = WaitForNonce;
self.prospective = Some(self.sign(self.reserved.prospective_value()));
self.prospective = Some(self.sign(self.reserved.prospective_value())?);
},
Async::Ready(nonce) => {
self.state = Finish;
self.prospective = Some(self.sign(nonce.value()));
self.state = WaitForPostSign;
self.post_sign_future = Some(self.post_sign.take()
.expect("post_sign is set on creation; qed")
.execute(self.sign(nonce.value())?)
.into_future());
self.ready = Some(nonce);
},
}
},
WaitForNonce => {
let nonce = try_ready!(self.poll_reserved());
let result = match (self.prospective.take(), nonce.matches_prospective()) {
let prospective = match (self.prospective.take(), nonce.matches_prospective()) {
(Some(prospective), true) => prospective,
_ => self.sign(nonce.value()),
_ => self.sign(nonce.value())?,
};
self.state = Finish;
self.prospective = Some(result);
self.ready = Some(nonce);
self.state = WaitForPostSign;
self.post_sign_future = Some(self.post_sign.take()
.expect("post_sign is set on creation; qed")
.execute(prospective)
.into_future());
},
Finish => {
if let (Some(result), Some(nonce)) = (self.prospective.take(), self.ready.take()) {
// Mark nonce as used on successful signing
return result.map(move |tx| {
nonce.mark_used();
Async::Ready(tx)
})
WaitForPostSign => {
if let Some(mut fut) = self.post_sign_future.as_mut() {
match fut.poll()? {
Async::Ready(item) => {
let nonce = self.ready
.take()
.expect("nonce is set before state transitions to WaitForPostSign; qed");
nonce.mark_used();
return Ok(Async::Ready(item))
},
Async::NotReady => {
return Ok(Async::NotReady)
}
}
} else {
panic!("Poll after ready.");
}
@@ -655,19 +733,21 @@ pub fn execute<D: Dispatcher + 'static>(
match payload {
ConfirmationPayload::SendTransaction(request) => {
let condition = request.condition.clone().map(Into::into);
Box::new(dispatcher.sign(accounts, request, pass)
.map(move |v| v.map(move |tx| PendingTransaction::new(tx, condition)))
.map(WithToken::into_tuple)
.map(|(tx, token)| (tx, token, dispatcher))
.and_then(|(tx, tok, dispatcher)| {
dispatcher.dispatch_transaction(tx)
.map(RpcH256::from)
.map(ConfirmationResponse::SendTransaction)
.map(move |h| WithToken::from((h, tok)))
}))
let cloned_dispatcher = dispatcher.clone();
let post_sign = move |with_token_signed: WithToken<SignedTransaction>| {
let (signed, token) = with_token_signed.into_tuple();
let signed_transaction = PendingTransaction::new(signed, condition);
cloned_dispatcher.dispatch_transaction(signed_transaction)
.map(|hash| (hash, token))
};
let future = dispatcher.sign(accounts, request, pass, post_sign)
.map(|(hash, token)| {
WithToken::from((ConfirmationResponse::SendTransaction(hash.into()), token))
});
Box::new(future)
},
ConfirmationPayload::SignTransaction(request) => {
Box::new(dispatcher.sign(accounts, request, pass)
Box::new(dispatcher.sign(accounts, request, pass, ())
.map(move |result| result
.map(move |tx| dispatcher.enrich(tx))
.map(ConfirmationResponse::SignTransaction)

View File

@@ -46,6 +46,7 @@ use ethereum_types::{U256, Address};
use hash::H256;
use parking_lot::Mutex;
use fastmap::H256FastMap;
use std::collections::BTreeMap;
use transaction::{Action, Transaction as EthTransaction, PendingTransaction, SignedTransaction, LocalizedTransaction};
use v1::helpers::{CallRequest as CallRequestHelper, errors, dispatch};
@@ -310,9 +311,7 @@ impl LightFetch {
}))
}
/// Get transaction logs
pub fn logs(&self, filter: EthcoreFilter) -> impl Future<Item = Vec<Log>, Error = Error> + Send {
use std::collections::BTreeMap;
pub fn logs_no_tx_hash(&self, filter: EthcoreFilter) -> impl Future<Item = Vec<Log>, Error = Error> + Send {
use jsonrpc_core::futures::stream::{self, Stream};
const MAX_BLOCK_RANGE: u64 = 1000;
@@ -343,7 +342,7 @@ impl LightFetch {
// insert them into a BTreeMap to maintain order by number and block index.
stream::futures_unordered(receipts_futures)
.fold(BTreeMap::new(), move |mut matches, (num, hash, receipts)| {
let mut block_index = 0;
let mut block_index: usize = 0;
for (transaction_index, receipt) in receipts.into_iter().enumerate() {
for (transaction_log_index, log) in receipt.logs.into_iter().enumerate() {
if filter.matches(&log) {
@@ -366,9 +365,9 @@ impl LightFetch {
}
}
future::ok::<_,OnDemandError>(matches)
}) // and then collect them into a vector.
.map(|matches| matches.into_iter().map(|(_, v)| v).collect())
})
.map_err(errors::on_demand_error)
.map(|matches| matches.into_iter().map(|(_, v)| v).collect())
});
match maybe_future {
@@ -378,6 +377,39 @@ impl LightFetch {
})
}
/// Get transaction logs
pub fn logs(&self, filter: EthcoreFilter) -> impl Future<Item = Vec<Log>, Error = Error> + Send {
use jsonrpc_core::futures::stream::{self, Stream};
let fetcher_block = self.clone();
self.logs_no_tx_hash(filter)
// retrieve transaction hash.
.and_then(move |mut result| {
let mut blocks = BTreeMap::new();
for log in result.iter() {
let block_hash = log.block_hash.as_ref().expect("Previously initialized with value; qed");
blocks.entry(block_hash.clone()).or_insert_with(|| {
fetcher_block.block(BlockId::Hash(block_hash.clone().into()))
});
}
// future get blocks (unordered it)
stream::futures_unordered(blocks.into_iter().map(|(_, v)| v)).collect().map(move |blocks| {
let transactions_per_block: BTreeMap<_, _> = blocks.iter()
.map(|block| (block.hash(), block.transactions())).collect();
for log in result.iter_mut() {
let log_index: U256 = log.transaction_index.expect("Previously initialized with value; qed").into();
let block_hash = log.block_hash.clone().expect("Previously initialized with value; qed").into();
let tx_hash = transactions_per_block.get(&block_hash)
// transaction index is from an enumerate call in log common so not need to check value
.and_then(|txs| txs.get(log_index.as_usize()))
.map(|tr| tr.hash().into());
log.transaction_hash = tx_hash;
}
result
})
})
}
// Get a transaction by hash. also returns the index in the block.
// Only returns transactions in the canonical chain.
pub fn transaction_by_hash(&self, tx_hash: H256)

View File

@@ -141,6 +141,33 @@ enum PendingTransactionId {
Location(PendingOrBlock, usize)
}
pub fn base_logs<C, M, T: StateInfo + 'static> (client: &C, miner: &M, filter: Filter) -> BoxFuture<Vec<Log>> where
C: miner::BlockChainClient + BlockChainClient + StateClient<State=T> + Call<State=T>,
M: MinerService<State=T> {
let include_pending = filter.to_block == Some(BlockNumber::Pending);
let filter: EthcoreFilter = match filter.try_into() {
Ok(value) => value,
Err(err) => return Box::new(future::err(err)),
};
let mut logs = match client.logs(filter.clone()) {
Ok(logs) => logs
.into_iter()
.map(From::from)
.collect::<Vec<Log>>(),
Err(id) => return Box::new(future::err(errors::filter_block_not_found(id))),
};
if include_pending {
let best_block = client.chain_info().best_block_number;
let pending = pending_logs(&*miner, best_block, &filter);
logs.extend(pending);
}
let logs = limit_logs(logs, filter.limit);
Box::new(future::ok(logs))
}
impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S, M, EM> where
C: miner::BlockChainClient + BlockChainClient + StateClient<State=T> + Call<State=T> + EngineInfo,
SN: SnapshotService,
@@ -714,28 +741,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
}
fn logs(&self, filter: Filter) -> BoxFuture<Vec<Log>> {
let include_pending = filter.to_block == Some(BlockNumber::Pending);
let filter: EthcoreFilter = match filter.try_into() {
Ok(value) => value,
Err(err) => return Box::new(future::err(err)),
};
let mut logs = match self.client.logs(filter.clone()) {
Ok(logs) => logs
.into_iter()
.map(From::from)
.collect::<Vec<Log>>(),
Err(id) => return Box::new(future::err(errors::filter_block_not_found(id))),
};
if include_pending {
let best_block = self.client.chain_info().best_block_number;
let pending = pending_logs(&*self.miner, best_block, &filter);
logs.extend(pending);
}
let logs = limit_logs(logs, filter.limit);
Box::new(future::ok(logs))
base_logs(&*self.client, &*self.miner, filter.into())
}
fn work(&self, no_new_work_timeout: Trailing<u64>) -> Result<Work> {

View File

@@ -18,7 +18,6 @@
use std::sync::{Arc, Weak};
use std::collections::BTreeMap;
use std::time::Duration;
use jsonrpc_core::{BoxFuture, Result, Error};
use jsonrpc_core::futures::{self, Future, IntoFuture};
@@ -34,14 +33,13 @@ use v1::types::{pubsub, RichHeader, Log};
use ethcore::encoded;
use ethcore::filter::Filter as EthFilter;
use ethcore::client::{BlockChainClient, ChainNotify, ChainRoute, ChainRouteType, BlockId};
use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks, ChainRouteType, BlockId};
use sync::LightSync;
use light::cache::Cache;
use light::on_demand::OnDemand;
use light::client::{LightChainClient, LightChainNotify};
use parity_runtime::Executor;
use ethereum_types::H256;
use bytes::Bytes;
use parking_lot::{RwLock, Mutex};
type Client = Sink<pubsub::Result>;
@@ -220,18 +218,10 @@ impl<C: LightClient> LightChainNotify for ChainNotificationHandler<C> {
}
impl<C: BlockChainClient> ChainNotify for ChainNotificationHandler<C> {
fn new_blocks(
&self,
_imported: Vec<H256>,
_invalid: Vec<H256>,
route: ChainRoute,
_sealed: Vec<H256>,
// Block bytes.
_proposed: Vec<Bytes>,
_duration: Duration,
) {
fn new_blocks(&self, new_blocks: NewBlocks) {
if self.heads_subscribers.read().is_empty() && self.logs_subscribers.read().is_empty() { return }
const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";
let headers = route.route()
let headers = new_blocks.route.route()
.iter()
.filter_map(|&(hash, ref typ)| {
match typ {
@@ -249,7 +239,7 @@ impl<C: BlockChainClient> ChainNotify for ChainNotificationHandler<C> {
self.notify_heads(&headers);
// We notify logs enacting and retracting as the order in route.
self.notify_logs(route.route(), |filter, ex| {
self.notify_logs(new_blocks.route.route(), |filter, ex| {
match ex {
&ChainRouteType::Enacted =>
Ok(self.client.logs(filter).unwrap_or_default().into_iter().map(Into::into).collect()),

View File

@@ -28,7 +28,7 @@ use ethcore::account_provider::AccountProvider;
use ethcore_logger::RotatingLogger;
use jsonrpc_core::{Result, BoxFuture};
use jsonrpc_core::futures::Future;
use jsonrpc_core::futures::{future, Future};
use jsonrpc_macros::Trailing;
use v1::helpers::{self, errors, ipfs, SigningQueue, SignerService, NetworkSettings};
use v1::helpers::dispatch::LightDispatcher;
@@ -42,6 +42,7 @@ use v1::types::{
BlockNumber, LightBlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, ChainStatus,
AccountInfo, HwAccountInfo, Header, RichHeader, Receipt,
Log, Filter,
};
use Host;
@@ -414,4 +415,13 @@ impl Parity for ParityClient {
fn submit_work_detail(&self, _nonce: H64, _pow_hash: H256, _mix_hash: H256) -> Result<H256> {
Err(errors::light_unimplemented(None))
}
fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture<Vec<Log>> {
let filter = match filter.try_into() {
Ok(value) => value,
Err(err) => return Box::new(future::err(err)),
};
Box::new(self.fetcher().logs_no_tx_hash(filter)) as BoxFuture<_>
}
}

View File

@@ -44,7 +44,7 @@ use v1::types::{
Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus,
BlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, ChainStatus,
OperationsInfo, ChainStatus, Log, Filter,
AccountInfo, HwAccountInfo, RichHeader, Receipt,
block_number_to_id
};
@@ -481,4 +481,10 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
fn submit_work_detail(&self, nonce: H64, pow_hash: H256, mix_hash: H256) -> Result<H256> {
helpers::submit_work_detail(&self.client, &self.miner, nonce, pow_hash, mix_hash)
}
fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture<Vec<Log>> {
use v1::impls::eth::base_logs;
// only specific impl for lightclient
base_logs(&*self.client, &*self.miner, filter.into())
}
}

View File

@@ -18,7 +18,7 @@
use std::sync::Arc;
use std::time::Duration;
use bytes::{Bytes, ToPretty};
use bytes::Bytes;
use ethcore::account_provider::AccountProvider;
use transaction::PendingTransaction;
use ethereum_types::{H520, U128, Address};
@@ -27,7 +27,7 @@ use ethkey::{public_to_address, recover, Signature};
use jsonrpc_core::{BoxFuture, Result};
use jsonrpc_core::futures::{future, Future};
use v1::helpers::{errors, eip191};
use v1::helpers::dispatch::{self, eth_data_hash, Dispatcher, SignWith};
use v1::helpers::dispatch::{self, eth_data_hash, Dispatcher, SignWith, PostSign, WithToken};
use v1::traits::Personal;
use v1::types::{
H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U128 as RpcU128,
@@ -41,6 +41,7 @@ use v1::types::{
use v1::metadata::Metadata;
use eip712::{EIP712, hash_structured_data};
use jsonrpc_core::types::Value;
use transaction::SignedTransaction;
/// Account management (personal) rpc implementation.
pub struct PersonalClient<D: Dispatcher> {
@@ -68,7 +69,16 @@ impl<D: Dispatcher> PersonalClient<D> {
}
impl<D: Dispatcher + 'static> PersonalClient<D> {
fn do_sign_transaction(&self, _meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<(PendingTransaction, D)> {
fn do_sign_transaction<P>(
&self,
_meta: Metadata,
request: TransactionRequest,
password: String,
post_sign: P
) -> BoxFuture<P::Item>
where P: PostSign + 'static,
<P::Out as futures::future::IntoFuture>::Future: Send
{
let dispatcher = self.dispatcher.clone();
let accounts = self.accounts.clone();
@@ -86,11 +96,7 @@ impl<D: Dispatcher + 'static> PersonalClient<D> {
Box::new(dispatcher.fill_optional_fields(request.into(), default, false)
.and_then(move |filled| {
let condition = filled.condition.clone().map(Into::into);
dispatcher.sign(accounts, filled, SignWith::Password(password.into()))
.map(|tx| tx.into_value())
.map(move |tx| PendingTransaction::new(tx, condition))
.map(move |tx| (tx, dispatcher))
dispatcher.sign(accounts, filled, SignWith::Password(password.into()), post_sign)
})
)
}
@@ -223,18 +229,26 @@ impl<D: Dispatcher + 'static> Personal for PersonalClient<D> {
}
fn sign_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<RpcRichRawTransaction> {
Box::new(self.do_sign_transaction(meta, request, password)
.map(|(pending_tx, dispatcher)| dispatcher.enrich(pending_tx.transaction)))
let condition = request.condition.clone().map(Into::into);
let dispatcher = self.dispatcher.clone();
Box::new(self.do_sign_transaction(meta, request, password, ())
.map(move |tx| PendingTransaction::new(tx.into_value(), condition))
.map(move |pending_tx| dispatcher.enrich(pending_tx.transaction)))
}
fn send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<RpcH256> {
Box::new(self.do_sign_transaction(meta, request, password)
.and_then(|(pending_tx, dispatcher)| {
let chain_id = pending_tx.chain_id();
trace!(target: "miner", "send_transaction: dispatching tx: {} for chain ID {:?}",
::rlp::encode(&*pending_tx).pretty(), chain_id);
dispatcher.dispatch_transaction(pending_tx).map(Into::into)
let condition = request.condition.clone().map(Into::into);
let dispatcher = self.dispatcher.clone();
Box::new(self.do_sign_transaction(meta, request, password, move |signed: WithToken<SignedTransaction>| {
dispatcher.dispatch_transaction(
PendingTransaction::new(
signed.into_value(),
condition
)
)
})
.and_then(|hash| {
Ok(RpcH256::from(hash))
})
)
}

View File

@@ -24,7 +24,7 @@ use std::time::Duration;
use v1::{EthPubSub, EthPubSubClient, Metadata};
use ethcore::client::{TestBlockChainClient, EachBlockWith, ChainNotify, ChainRoute, ChainRouteType};
use ethcore::client::{TestBlockChainClient, EachBlockWith, ChainNotify, NewBlocks, ChainRoute, ChainRouteType};
use parity_runtime::Runtime;
const DURATION_ZERO: Duration = Duration::from_millis(0);
@@ -57,13 +57,13 @@ fn should_subscribe_to_new_heads() {
assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()));
// Check notifications
handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO);
handler.new_blocks(NewBlocks::new(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO, true));
let (res, receiver) = receiver.into_future().wait().unwrap();
let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x1","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x1","parentHash":"0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x416d77337e24399d"}}"#;
assert_eq!(res, Some(response.into()));
// Notify about two blocks
handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h2, ChainRouteType::Enacted), (h3, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO);
handler.new_blocks(NewBlocks::new(vec![], vec![], ChainRoute::new(vec![(h2, ChainRouteType::Enacted), (h3, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO, true));
// Receive both
let (res, receiver) = receiver.into_future().wait().unwrap();
@@ -129,7 +129,7 @@ fn should_subscribe_to_logs() {
assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()));
// Check notifications (enacted)
handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO);
handler.new_blocks(NewBlocks::new(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO, false));
let (res, receiver) = receiver.into_future().wait().unwrap();
let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","removed":false,"topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned()
+ &format!("0x{:x}", tx_hash)
@@ -137,7 +137,7 @@ fn should_subscribe_to_logs() {
assert_eq!(res, Some(response.into()));
// Check notifications (retracted)
handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Retracted)]), vec![], vec![], DURATION_ZERO);
handler.new_blocks(NewBlocks::new(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Retracted)]), vec![], vec![], DURATION_ZERO, false));
let (res, receiver) = receiver.into_future().wait().unwrap();
let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","removed":true,"topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned()
+ &format!("0x{:x}", tx_hash)

View File

@@ -20,13 +20,12 @@ use std::collections::BTreeMap;
use jsonrpc_core::{BoxFuture, Result};
use jsonrpc_macros::Trailing;
use v1::types::{
H64, H160, H256, H512, U256, Bytes, CallRequest,
Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus,
BlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, ChainStatus,
OperationsInfo, ChainStatus, Log, Filter,
AccountInfo, HwAccountInfo, RichHeader, Receipt,
};
@@ -227,5 +226,11 @@ build_rpc_trait! {
/// but returns block hash on success, and returns an explicit error message on failure).
#[rpc(name = "parity_submitWorkDetail")]
fn submit_work_detail(&self, H64, H256, H256) -> Result<H256>;
/// Returns logs matching given filter object.
/// Is allowed to skip filling transaction hash for faster query.
#[rpc(name = "parity_getLogsNoTransactionHash")]
fn logs_no_tx_hash(&self, Filter) -> BoxFuture<Vec<Log>>;
}
}

View File

@@ -74,7 +74,7 @@ impl<'a> Visitor<'a> for BytesVisitor {
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: Error {
if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 {
if value.len() >= 2 && value.starts_with("0x") && value.len() & 1 == 0 {
Ok(Bytes::new(FromHex::from_hex(&value[2..]).map_err(|e| Error::custom(format!("Invalid hex: {}", e)))?))
} else {
Err(Error::custom("Invalid bytes format. Expected a 0x-prefixed hex string with even length"))
@@ -101,6 +101,7 @@ mod tests {
#[test]
fn test_bytes_deserialize() {
let bytes0: Result<Bytes, serde_json::Error> = serde_json::from_str(r#""∀∂""#);
let bytes1: Result<Bytes, serde_json::Error> = serde_json::from_str(r#""""#);
let bytes2: Result<Bytes, serde_json::Error> = serde_json::from_str(r#""0x123""#);
let bytes3: Result<Bytes, serde_json::Error> = serde_json::from_str(r#""0xgg""#);
@@ -109,6 +110,7 @@ mod tests {
let bytes5: Bytes = serde_json::from_str(r#""0x12""#).unwrap();
let bytes6: Bytes = serde_json::from_str(r#""0x0123""#).unwrap();
assert!(bytes0.is_err());
assert!(bytes1.is_err());
assert!(bytes2.is_err());
assert!(bytes3.is_err());

View File

@@ -129,7 +129,7 @@ macro_rules! impl_hash {
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error {
if value.len() < 2 || &value[0..2] != "0x" {
if value.len() < 2 || !value.starts_with("0x") {
return Err(E::custom("expected a hex-encoded hash with 0x prefix"));
}
if value.len() != 2 + $size * 2 {

View File

@@ -72,7 +72,7 @@ macro_rules! impl_uint {
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error {
if value.len() < 2 || &value[0..2] != "0x" {
if value.len() < 2 || !value.starts_with("0x") {
return Err(E::custom("expected a hex-encoded numbers with 0x prefix"))
}
@@ -140,12 +140,14 @@ mod tests {
#[test]
fn should_fail_to_deserialize_decimals() {
let deserialized0: Res = serde_json::from_str(r#""∀∂""#);
let deserialized1: Res = serde_json::from_str(r#""""#);
let deserialized2: Res = serde_json::from_str(r#""0""#);
let deserialized3: Res = serde_json::from_str(r#""10""#);
let deserialized4: Res = serde_json::from_str(r#""1000000""#);
let deserialized5: Res = serde_json::from_str(r#""1000000000000000000""#);
assert!(deserialized0.is_err());
assert!(deserialized1.is_err());
assert!(deserialized2.is_err());
assert!(deserialized3.is_err());

View File

@@ -1,8 +1,5 @@
FROM ubuntu:xenial
MAINTAINER Parity Technologies <devops@parity.io>
#set ENVIROMENT
ARG TARGET
ENV TARGET ${TARGET}
LABEL MAINTAINER="Parity Technologies <devops-team@parity.io>"
# install tools and dependencies
RUN apt update && apt install -y --no-install-recommends openssl libudev-dev file curl jq
@@ -10,31 +7,25 @@ RUN apt update && apt install -y --no-install-recommends openssl libudev-dev fil
# show backtraces
ENV RUST_BACKTRACE 1
#cleanup Docker image
RUN apt autoremove -y
RUN apt clean -y
RUN rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/*
# cleanup Docker image
RUN apt autoremove -y \
&& apt clean -y \
&& rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/*
RUN groupadd -g 1000 parity \
&& useradd -m -u 1000 -g parity -s /bin/sh parity
WORKDIR /home/parity
ENV PATH "~/bin:${PATH}"
#add TARGET to docker image
COPY artifacts/x86_64-unknown-linux-gnu/$TARGET ./bin/$TARGET
# Build a shell script because the ENTRYPOINT command doesn't like using ENV
RUN echo "#!/bin/bash \n ${TARGET} \$@" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
# add parity-ethereum to docker image
COPY artifacts/x86_64-unknown-linux-gnu/parity /bin/parity
COPY scripts/docker/hub/check_sync.sh /check_sync.sh
# switch to user parity here
USER parity
# setup ENTRYPOINT
VOLUME [ "/home/parity/.local/share/io.parity.ethereum" ]
EXPOSE 5001 8080 8082 8083 8545 8546 8180 30303/tcp 30303/udp
ENTRYPOINT ["./entrypoint.sh"]
ENTRYPOINT ["/bin/parity"]

View File

@@ -1,14 +1,30 @@
FROM ubuntu:14.04
FROM ubuntu:xenial
WORKDIR /build
# install aarch64(armv8) dependencies and tools
RUN dpkg --add-architecture arm64
RUN echo '# source urls for arm64 \n\
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ xenial main \n\
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ xenial main \n\
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main \n\
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main \n\
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ xenial-security main \n\
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ xenial-security main \n # end arm64 section' >> /etc/apt/sources.list &&\
sed -r 's/deb h/deb \[arch=amd64\] h/g' /etc/apt/sources.list > /tmp/sources-tmp.list && \
cp /tmp/sources-tmp.list /etc/apt/sources.list&& \
sed -r 's/deb-src h/deb-src \[arch=amd64\] h/g' /etc/apt/sources.list > /tmp/sources-tmp.list&&cat /etc/apt/sources.list &&\
cp /tmp/sources-tmp.list /etc/apt/sources.list&& echo "next"&&cat /etc/apt/sources.list
# install tools and dependencies
RUN apt-get -y update && \
apt-get install -y --force-yes --no-install-recommends \
curl git make g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
libc6-arm64-cross libc6-dev-arm64-cross wget file ca-certificates \
binutils-aarch64-linux-gnu cmake3 libudev-dev \
&& \
apt-get clean
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
curl make cmake file ca-certificates \
g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
libc6-dev-arm64-cross binutils-aarch64-linux-gnu \
libudev-dev libudev-dev:arm64 \
&& \
apt-get clean
# install rustup
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
@@ -30,14 +46,14 @@ RUN rustc -vV && cargo -V
# build parity
ADD . /build/parity
RUN cd parity && \
mkdir -p .cargo && \
echo '[target.aarch64-unknown-linux-gnu]\n\
linker = "aarch64-linux-gnu-gcc"\n'\
>>.cargo/config && \
cat .cargo/config && \
cargo build --target aarch64-unknown-linux-gnu --release --verbose && \
ls /build/parity/target/aarch64-unknown-linux-gnu/release/parity && \
/usr/bin/aarch64-linux-gnu-strip /build/parity/target/aarch64-unknown-linux-gnu/release/parity
mkdir -p .cargo && \
echo '[target.aarch64-unknown-linux-gnu]\n\
linker = "aarch64-linux-gnu-gcc"\n'\
>>.cargo/config && \
cat .cargo/config && \
cargo build --target aarch64-unknown-linux-gnu --release --verbose && \
ls /build/parity/target/aarch64-unknown-linux-gnu/release/parity && \
/usr/bin/aarch64-linux-gnu-strip /build/parity/target/aarch64-unknown-linux-gnu/release/parity
RUN file /build/parity/target/aarch64-unknown-linux-gnu/release/parity

View File

@@ -9,48 +9,34 @@ echo "CARGO_HOME: " $CARGO_HOME
echo "CARGO_TARGET: " $CARGO_TARGET
echo "CC: " $CC
echo "CXX: " $CXX
echo "__________CARGO CONFIG__________"
if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ]
then
# use build container's cargo config
cat /.cargo/config
else
mkdir -p .cargo
rm -f .cargo/config
echo "[target.$CARGO_TARGET]" >> .cargo/config
echo "linker= \"$CC\"" >> .cargo/config
cat .cargo/config
fi
#strip ON
export RUSTFLAGS=" -C link-arg=-s"
echo "_____ Building target: "$CARGO_TARGET" _____"
time cargo build --target $CARGO_TARGET --release --features final
time cargo build --target $CARGO_TARGET --release -p evmbin
time cargo build --target $CARGO_TARGET --release -p ethstore-cli
time cargo build --target $CARGO_TARGET --release -p ethkey-cli
time cargo build --target $CARGO_TARGET --release -p whisper-cli
echo "_____ Post-processing binaries _____"
rm -rf artifacts
mkdir -p artifacts
cd artifacts
mkdir -p $CARGO_TARGET
cd $CARGO_TARGET
cp -v ../../target/$CARGO_TARGET/release/parity ./parity
cp -v ../../target/$CARGO_TARGET/release/parity-evm ./parity-evm
cp -v ../../target/$CARGO_TARGET/release/ethstore ./ethstore
cp -v ../../target/$CARGO_TARGET/release/ethkey ./ethkey
cp -v ../../target/$CARGO_TARGET/release/whisper ./whisper
# stripping can also be done on release build time
# export RUSTFLAGS="${RUSTFLAGS} -C link-arg=-s"
if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ]
then
arm-linux-androideabi-strip -v ./*
time cargo build --target $CARGO_TARGET --release -p parity-clib --features final
else
strip -v ./*
time cargo build --target $CARGO_TARGET --release --features final
time cargo build --target $CARGO_TARGET --release -p evmbin
time cargo build --target $CARGO_TARGET --release -p ethstore-cli
time cargo build --target $CARGO_TARGET --release -p ethkey-cli
time cargo build --target $CARGO_TARGET --release -p whisper-cli
fi
echo "_____ Post-processing binaries _____"
mkdir -p artifacts/$CARGO_TARGET
cd artifacts/$CARGO_TARGET
if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ]
then
cp -v ../../target/$CARGO_TARGET/release/libparity.so ./libparity.so
else
cp -v ../../target/$CARGO_TARGET/release/parity ./parity
cp -v ../../target/$CARGO_TARGET/release/parity-evm ./parity-evm
cp -v ../../target/$CARGO_TARGET/release/ethstore ./ethstore
cp -v ../../target/$CARGO_TARGET/release/ethkey ./ethkey
cp -v ../../target/$CARGO_TARGET/release/whisper ./whisper
fi
echo "_____ Calculating checksums _____"
@@ -64,4 +50,3 @@ do
./parity tools hash $binary > $binary.sha3
fi
done

View File

@@ -1,7 +0,0 @@
#!/bin/bash
set -e # fail on any error
set -u # treat unset variables as error
cargo install cargo-audit
cargo audit

View File

@@ -7,6 +7,7 @@ clone_repos() {
echo "__________Clone repos__________"
git clone https://github.com/parity-js/jsonrpc.git jsonrpc
git clone https://github.com/paritytech/wiki.git wiki
git clone https://github.com/paritytech/parity-config-generator
}
build_docs() {
@@ -15,18 +16,25 @@ build_docs() {
npm run build:markdown
}
build_config() {
echo "_______Build config docs______"
yarn install
AUTOGENSCRIPT=1 yarn generate-docs
}
update_wiki_docs() {
echo "__________Update WIKI docs__________"
for file in $(ls jsonrpc/docs); do
module_name=${file:0:-3}
mv jsonrpc/docs/$file wiki/JSONRPC-$module_name-module.md
done
mv parity-config-generator/docs/config.md wiki/Configuring-Parity-Ethereum.md
}
setup_git() {
echo "__________Set github__________"
git config user.email "devops@parity.com"
git config user.name "Devops Parity"
git config --global user.email "devops@parity.com"
git config --global user.name "Devops Parity"
}
set_remote_wiki() {
@@ -38,13 +46,13 @@ commit_files() {
git checkout -b rpcdoc-update-${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}
git add .
git commit -m "Update docs to ${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
git tag -a "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" -m "Update RPC docs to ${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
git tag -a -f "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" -m "Update RPC and config docs to ${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
}
upload_files() {
echo "__________Upload files__________"
git push origin HEAD
git push --tags
git push -q origin HEAD
git push -q -f --tags
}
RPC_TRAITS_DIR="rpc/src/v1/traits"
@@ -56,6 +64,9 @@ cp $RPC_TRAITS_DIR/*.rs "jsonrpc/.parity/$RPC_TRAITS_DIR"
cd jsonrpc
build_docs
cd ..
cd parity-config-generator
build_config
cd ..
update_wiki_docs
cd wiki
set_remote_wiki

View File

@@ -36,19 +36,3 @@ do
esac
cd ..
done
echo "__________Push binaries to AWS S3____________"
aws configure set aws_access_key_id $s3_key
aws configure set aws_secret_access_key $s3_secret
case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in
(beta|stable|nightly)
export S3_BUCKET=builds-parity-published;
;;
(*)
export S3_BUCKET=builds-parity;
;;
esac
aws s3 sync ./ s3://$S3_BUCKET/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/

52
scripts/gitlab/publish-snap.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
set -e # fail on any error
set -u # treat unset variables as error
# some necromancy:
# gsub(/"/, "", $2) deletes "qoutes"
# gsub(/ /, "", $2) deletes whitespaces
TRACK=`awk -F '=' '/^track/ {gsub(/"/, "", $2); gsub(/ /, "", $2); print $2}' ./util/version/Cargo.toml`
echo Track is: $TRACK
case ${TRACK} in
nightly) export GRADE="devel" CHANNEL="edge";;
beta) export GRADE="stable" CHANNEL="beta";;
stable) export GRADE="stable" CHANNEL="stable";;
*) echo "No release" && exit 0;;
esac
SNAP_PACKAGE="parity_"$VERSION"_"$BUILD_ARCH".snap"
echo "__________Create snap package__________"
echo "Release channel :" $GRADE " Branch/tag: " $CI_COMMIT_REF_NAME
echo $VERSION:$GRADE:$BUILD_ARCH
# cat scripts/snap/snapcraft.template.yaml | envsubst '$VERSION:$GRADE:$BUILD_ARCH:$CARGO_TARGET' > snapcraft.yaml
# a bit more necromancy (substitutions):
pwd
cd /builds/$CI_PROJECT_PATH/scripts/snap/
sed -e 's/$VERSION/'"$VERSION"'/g' \
-e 's/$GRADE/'"$GRADE"'/g' \
-e 's/$BUILD_ARCH/'"$BUILD_ARCH"'/g' \
-e 's/$CARGO_TARGET/'"$CARGO_TARGET"'/g' \
snapcraft.template.yaml > /builds/$CI_PROJECT_PATH/snapcraft.yaml
cd /builds/$CI_PROJECT_PATH
pwd
apt update
apt install -y --no-install-recommends rhash
cat snapcraft.yaml
snapcraft --target-arch=$BUILD_ARCH
ls *.snap
echo "__________Calculating checksums__________"
rhash --sha256 $SNAP_PACKAGE -o $SNAP_PACKAGE".sha256"
cat $SNAP_PACKAGE".sha256"
echo "__________Releasing snap package__________"
echo "Release channel :" $CHANNEL " Branch/tag: " $CI_COMMIT_REF_NAME
echo $SNAPCRAFT_LOGIN_PARITY_BASE64 | base64 --decode > snapcraft.login
snapcraft login --with snapcraft.login
snapcraft push --release $CHANNEL $SNAP_PACKAGE
snapcraft status parity
snapcraft logout

View File

@@ -1,6 +1,4 @@
#!/bin/bash
# ARGUMENT $1 Rust flavor to test with (stable/beta/nightly)
set -e # fail on any error
set -u # treat unset variables as error
@@ -27,9 +25,6 @@ then
exit 0
fi
rustup default $1
git submodule update --init --recursive
rustup show
exec ./test.sh

BIN
scripts/snap/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=Parity Ethereum
Comment=The fastest and most advanced Ethereum client.
Exec=parity
Icon=/usr/share/pixmaps/icon.png
Terminal=true

View File

@@ -0,0 +1,53 @@
name: parity
version: $VERSION
architectures: [$BUILD_ARCH]
grade: $GRADE
confinement: strict
summary: Fast, light, robust Ethereum implementation
description: |
Parity's goal is to be the fastest, lightest, and most secure Ethereum
client. We are developing Parity using the sophisticated and cutting-edge
Rust programming language. Parity is licensed under the GPLv3, and can be
used for all your Ethereum needs.
apps:
parity:
command: parity
plugs: [home, network, network-bind, mount-observe, x11, unity7, desktop, desktop-legacy, wayland]
desktop: ./usr/share/applications/parity.desktop
parity-evm:
command: parity-evm
plugs: [home, network, network-bind]
ethkey:
command: ethkey
plugs: [home]
ethstore:
command: ethstore
plugs: [home]
whisper:
command: whisper
plugs: [home, network-bind]
icon: ./scripts/snap/icon.png
parts:
desktop-icon:
source: ./scripts/snap
plugin: nil
override-build: |
mkdir -p $SNAPCRAFT_PART_INSTALL/usr/share/applications
mkdir -p $SNAPCRAFT_PART_INSTALL/usr/share/pixmaps
cp -v ./parity.desktop $SNAPCRAFT_PART_INSTALL/usr/share/applications/
cp -v ./icon.png $SNAPCRAFT_PART_INSTALL/usr/share/pixmaps/
parity:
source: ./artifacts/$CARGO_TARGET
plugin: nil
override-build: |
mkdir -p $SNAPCRAFT_PART_INSTALL/usr/bin
cp -v parity $SNAPCRAFT_PART_INSTALL/usr/bin/parity
cp -v parity-evm $SNAPCRAFT_PART_INSTALL/usr/bin/parity-evm
cp -v ethkey $SNAPCRAFT_PART_INSTALL/usr/bin/ethkey
cp -v ethstore $SNAPCRAFT_PART_INSTALL/usr/bin/ethstore
cp -v whisper $SNAPCRAFT_PART_INSTALL/usr/bin/whisper
stage-packages: [libc6, libudev1, libstdc++6, cmake, libdb5.3]

View File

@@ -16,12 +16,10 @@
use std::sync::Arc;
use std::collections::{HashMap, HashSet};
use std::time::Duration;
use parking_lot::{Mutex, RwLock};
use ethcore::client::{BlockId, ChainNotify, ChainRoute, CallContract};
use ethereum_types::{H256, Address};
use ethcore::client::{BlockId, ChainNotify, NewBlocks, CallContract};
use ethereum_types::Address;
use ethabi::FunctionOutputDecoder;
use bytes::Bytes;
use trusted_client::TrustedClient;
use types::{Error, ServerKeyId, ContractAddress};
@@ -77,8 +75,9 @@ impl AclStorage for OnChainAclStorage {
}
impl ChainNotify for OnChainAclStorage {
fn new_blocks(&self, _imported: Vec<H256>, _invalid: Vec<H256>, route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: Duration) {
if !route.enacted().is_empty() || !route.retracted().is_empty() {
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.has_more_blocks_to_import { return }
if !new_blocks.route.enacted().is_empty() || !new_blocks.route.retracted().is_empty() {
self.contract.lock().update_contract_address()
}
}

View File

@@ -17,10 +17,9 @@
use std::sync::Arc;
use std::net::SocketAddr;
use std::collections::{BTreeMap, HashSet};
use std::time::Duration;
use parking_lot::Mutex;
use ethabi::FunctionOutputDecoder;
use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, ChainRoute, CallContract};
use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, NewBlocks, CallContract};
use ethereum_types::{H256, Address};
use ethkey::public_to_address;
use bytes::Bytes;
@@ -151,8 +150,9 @@ impl KeyServerSet for OnChainKeyServerSet {
}
impl ChainNotify for OnChainKeyServerSet {
fn new_blocks(&self, _imported: Vec<H256>, _invalid: Vec<H256>, route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: Duration) {
let (enacted, retracted) = route.into_enacted_retracted();
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.has_more_blocks_to_import { return }
let (enacted, retracted) = new_blocks.route.into_enacted_retracted();
if !enacted.is_empty() || !retracted.is_empty() {
self.contract.lock().update(enacted, retracted)

View File

@@ -17,10 +17,9 @@
use std::collections::HashSet;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
use std::thread;
use parking_lot::Mutex;
use ethcore::client::{ChainNotify, ChainRoute};
use ethcore::client::{ChainNotify, NewBlocks};
use ethkey::{Public, public_to_address};
use bytes::Bytes;
use ethereum_types::{H256, U256, Address};
@@ -435,9 +434,10 @@ impl Drop for ServiceContractListener {
}
impl ChainNotify for ServiceContractListener {
fn new_blocks(&self, _imported: Vec<H256>, _invalid: Vec<H256>, route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: Duration) {
let enacted_len = route.enacted().len();
if enacted_len == 0 && route.retracted().is_empty() {
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.has_more_blocks_to_import { return }
let enacted_len = new_blocks.route.enacted().len();
if enacted_len == 0 && new_blocks.route.retracted().is_empty() {
return;
}

33
test.sh
View File

@@ -1,33 +1,12 @@
#!/bin/sh
# Running Parity Full Test Suite
echo "________Running test.sh________"
FEATURES="json-tests,ci-skip-issue"
OPTIONS="--release"
VALIDATE=1
THREADS=8
case $1 in
--no-json)
FEATURES="ipc"
shift # past argument=value
;;
--no-release)
OPTIONS=""
shift
;;
--no-validate)
VALIDATE=0
shift
;;
--no-run)
OPTIONS="--no-run"
shift
;;
*)
# unknown option
;;
esac
set -e
@@ -35,9 +14,9 @@ validate () {
if [ "$VALIDATE" -eq "1" ]
then
echo "________Validate build________"
time cargo check $@ --no-default-features
time cargo check $@ --manifest-path util/io/Cargo.toml --no-default-features
time cargo check $@ --manifest-path util/io/Cargo.toml --features "mio"
time cargo check $@ --locked --no-default-features
time cargo check $@ --locked --manifest-path util/io/Cargo.toml --no-default-features
time cargo check $@ --locked --manifest-path util/io/Cargo.toml --features "mio"
# Validate chainspecs
echo "________Validate chainspecs________"
@@ -57,7 +36,6 @@ cpp_test () {
cd build && \
cmake .. && \
make -j $THREADS && \
./parity-example && \
cd .. && \
rm -rf build && \
cd ../..
@@ -71,7 +49,7 @@ cpp_test () {
cargo_test () {
echo "________Running Parity Full Test Suite________"
git submodule update --init --recursive
time cargo test $OPTIONS --features "$FEATURES" --all $@ -- --test-threads $THREADS
time cargo test $OPTIONS --features "$FEATURES" --locked --all $@ -- --test-threads $THREADS
}
@@ -98,4 +76,3 @@ then
else
cargo_test $@
fi

View File

@@ -25,9 +25,8 @@ use parking_lot::{Mutex, MutexGuard};
use rand::{self, Rng};
use target_info::Target;
use bytes::Bytes;
use ethcore::BlockNumber;
use ethcore::client::{BlockId, BlockChainClient, ChainNotify, ChainRoute};
use ethcore::client::{BlockId, BlockChainClient, ChainNotify, NewBlocks};
use ethcore::filter::Filter;
use ethereum_types::H256;
use hash_fetch::{self as fetch, HashFetch};
@@ -669,7 +668,8 @@ impl<O: OperationsClient, F: HashFetch, T: TimeProvider, R: GenRange> Updater<O,
}
impl ChainNotify for Updater {
fn new_blocks(&self, _imported: Vec<H256>, _invalid: Vec<H256>, _route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: Duration) {
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.has_more_blocks_to_import { return }
match (self.client.upgrade(), self.sync.as_ref().and_then(Weak::upgrade)) {
(Some(ref c), Some(ref s)) if !s.status().is_syncing(c.queue_info()) => self.poll(),
_ => {},

View File

@@ -35,6 +35,7 @@ serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
error-chain = { version = "0.12", default-features = false }
lru-cache = "0.1"
[dev-dependencies]
tempdir = "0.3"

View File

@@ -20,6 +20,7 @@ use std::collections::{HashSet, HashMap, VecDeque};
use std::collections::hash_map::Entry;
use std::default::Default;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use lru_cache::LruCache;
use hash::keccak;
use ethereum_types::{H256, H520};
use rlp::{Rlp, RlpStream};
@@ -53,12 +54,17 @@ const REQUEST_BACKOFF: [Duration; 4] = [
Duration::from_secs(64)
];
const NODE_LAST_SEEN_TIMEOUT: Duration = Duration::from_secs(24*60*60);
const OBSERVED_NODES_MAX_SIZE: usize = 10_000;
#[derive(Clone, Debug)]
pub struct NodeEntry {
pub id: NodeId,
pub endpoint: NodeEndpoint,
}
#[derive(Debug)]
pub struct BucketEntry {
pub address: NodeEntry,
pub id_hash: H256,
@@ -89,6 +95,32 @@ struct FindNodeRequest {
answered: bool,
}
#[derive(Clone, Copy)]
enum PingReason {
Default,
FromDiscoveryRequest(NodeId, NodeValidity),
}
#[derive(Clone, Copy, PartialEq)]
enum NodeCategory {
Bucket,
Observed
}
#[derive(Clone, Copy, PartialEq)]
enum NodeValidity {
Ourselves,
ValidNode(NodeCategory),
ExpiredNode(NodeCategory),
UnknownNode
}
#[derive(Debug)]
enum BucketError {
Ourselves,
NotInTheBucket{node_entry: NodeEntry, bucket_distance: usize},
}
struct PingRequest {
// Time when the request was sent
sent_at: Instant,
@@ -99,8 +131,10 @@ struct PingRequest {
// The hash Parity used to respond with (until rev 01f825b0e1f1c4c420197b51fc801cbe89284b29)
#[deprecated()]
deprecated_echo_hash: H256,
reason: PingReason
}
#[derive(Debug)]
pub struct NodeBucket {
nodes: VecDeque<BucketEntry>, //sorted by last active
}
@@ -134,6 +168,12 @@ pub struct Discovery<'a> {
discovery_id: NodeId,
discovery_nodes: HashSet<NodeId>,
node_buckets: Vec<NodeBucket>,
// Sometimes we don't want to add nodes to the NodeTable, but still want to
// keep track of them to avoid excessive pinging (happens when an unknown node sends
// a discovery request to us -- the node might be on a different net).
other_observed_nodes: LruCache<NodeId, (NodeEndpoint, Instant)>,
in_flight_pings: HashMap<NodeId, PingRequest>,
in_flight_find_nodes: HashMap<NodeId, FindNodeRequest>,
send_queue: VecDeque<Datagram>,
@@ -160,6 +200,7 @@ impl<'a> Discovery<'a> {
discovery_id: NodeId::new(),
discovery_nodes: HashSet::new(),
node_buckets: (0..ADDRESS_BITS).map(|_| NodeBucket::new()).collect(),
other_observed_nodes: LruCache::new(OBSERVED_NODES_MAX_SIZE),
in_flight_pings: HashMap::new(),
in_flight_find_nodes: HashMap::new(),
send_queue: VecDeque::new(),
@@ -178,7 +219,7 @@ impl<'a> Discovery<'a> {
if self.node_buckets[dist].nodes.iter().any(|n| n.id_hash == id_hash) {
return;
}
self.try_ping(e);
self.try_ping(e, PingReason::Default);
}
}
@@ -189,41 +230,53 @@ impl<'a> Discovery<'a> {
}
}
fn update_node(&mut self, e: NodeEntry) -> Option<TableUpdates> {
trace!(target: "discovery", "Inserting {:?}", &e);
fn update_bucket_record(&mut self, e: NodeEntry) -> Result<(), BucketError> {
let id_hash = keccak(e.id);
let dist = match Discovery::distance(&self.id_hash, &id_hash) {
Some(dist) => dist,
None => {
debug!(target: "discovery", "Attempted to update own entry: {:?}", e);
return None;
return Err(BucketError::Ourselves);
}
};
let bucket = &mut self.node_buckets[dist];
bucket.nodes.iter_mut().find(|n| n.address.id == e.id)
.map_or(Err(BucketError::NotInTheBucket{node_entry: e.clone(), bucket_distance: dist}.into()), |entry| {
entry.address = e;
entry.last_seen = Instant::now();
entry.backoff_until = Instant::now();
entry.fail_count = 0;
Ok(())
})
}
let mut added_map = HashMap::new();
let ping = {
let bucket = &mut self.node_buckets[dist];
let updated = if let Some(node) = bucket.nodes.iter_mut().find(|n| n.address.id == e.id) {
node.address = e.clone();
node.last_seen = Instant::now();
node.backoff_until = Instant::now();
node.fail_count = 0;
true
} else { false };
fn update_node(&mut self, e: NodeEntry) -> Option<TableUpdates> {
trace!(target: "discovery", "Inserting {:?}", &e);
if !updated {
added_map.insert(e.id, e.clone());
bucket.nodes.push_front(BucketEntry::new(e));
match self.update_bucket_record(e) {
Ok(()) => None,
Err(BucketError::Ourselves) => None,
Err(BucketError::NotInTheBucket{node_entry, bucket_distance}) => Some((node_entry, bucket_distance))
}.map(|(node_entry, bucket_distance)| {
trace!(target: "discovery", "Adding a new node {:?} into our bucket {}", &node_entry, bucket_distance);
let mut added = HashMap::with_capacity(1);
added.insert(node_entry.id, node_entry.clone());
let node_to_ping = {
let bucket = &mut self.node_buckets[bucket_distance];
bucket.nodes.push_front(BucketEntry::new(node_entry));
if bucket.nodes.len() > BUCKET_SIZE {
select_bucket_ping(bucket.nodes.iter())
} else { None }
} else { None }
};
if let Some(node) = ping {
self.try_ping(node);
}
Some(TableUpdates { added: added_map, removed: HashSet::new() })
} else {
None
}
};
if let Some(node) = node_to_ping {
self.try_ping(node, PingReason::Default);
};
TableUpdates{added, removed: HashSet::new()}
})
}
/// Starts the discovery process at round 0
@@ -244,7 +297,7 @@ impl<'a> Discovery<'a> {
fn update_new_nodes(&mut self) {
while self.in_flight_pings.len() < MAX_NODES_PING {
match self.adding_nodes.pop() {
Some(next) => self.try_ping(next),
Some(next) => self.try_ping(next, PingReason::Default),
None => break,
}
}
@@ -298,7 +351,7 @@ impl<'a> Discovery<'a> {
None // a and b are equal, so log distance is -inf
}
fn try_ping(&mut self, node: NodeEntry) {
fn try_ping(&mut self, node: NodeEntry, reason: PingReason) {
if !self.is_allowed(&node) {
trace!(target: "discovery", "Node {:?} not allowed", node);
return;
@@ -313,7 +366,7 @@ impl<'a> Discovery<'a> {
}
if self.in_flight_pings.len() < MAX_NODES_PING {
self.ping(&node)
self.ping(&node, reason)
.unwrap_or_else(|e| {
warn!(target: "discovery", "Error sending Ping packet: {:?}", e);
});
@@ -322,7 +375,7 @@ impl<'a> Discovery<'a> {
}
}
fn ping(&mut self, node: &NodeEntry) -> Result<(), Error> {
fn ping(&mut self, node: &NodeEntry, reason: PingReason) -> Result<(), Error> {
let mut rlp = RlpStream::new_list(4);
rlp.append(&PROTOCOL_VERSION);
self.public_endpoint.to_rlp_list(&mut rlp);
@@ -336,6 +389,7 @@ impl<'a> Discovery<'a> {
node: node.clone(),
echo_hash: hash,
deprecated_echo_hash: old_parity_hash,
reason: reason
});
trace!(target: "discovery", "Sent Ping to {:?} ; node_id={:#x}", &node.endpoint, node.id);
@@ -515,7 +569,7 @@ impl<'a> Discovery<'a> {
if request.deprecated_echo_hash == echo_hash {
trace!(target: "discovery", "Got Pong from an old parity-ethereum version.");
}
Some(request.node.clone())
Some((request.node.clone(), request.reason.clone()))
}
};
@@ -529,29 +583,98 @@ impl<'a> Discovery<'a> {
},
};
if let Some(node) = expected_node {
Ok(self.update_node(node))
if let Some((node, ping_reason)) = expected_node {
if let PingReason::FromDiscoveryRequest(target, validity) = ping_reason {
self.respond_with_discovery(target, &node)?;
// kirushik: I would prefer to probe the network id of the remote node here, and add it to the nodes list if it's on "our" net --
// but `on_packet` happens synchronously, so doing the full TCP handshake ceremony here is a bad idea.
// So instead we just LRU-caching most recently seen nodes to avoid unnecessary pinging
match validity {
NodeValidity::ValidNode(NodeCategory::Bucket) | NodeValidity::ExpiredNode(NodeCategory::Bucket) => {
trace!(target: "discovery", "Updating node {:?} in our Kad buckets", &node);
self.update_bucket_record(node).unwrap_or_else(|error| {
debug!(target: "discovery", "Error occured when processing ping from a bucket node: {:?}", &error);
});
},
NodeValidity::UnknownNode | NodeValidity::ExpiredNode(NodeCategory::Observed) | NodeValidity::ValidNode(NodeCategory::Observed)=> {
trace!(target: "discovery", "Updating node {:?} in the list of other_observed_nodes", &node);
self.other_observed_nodes.insert(node.id, (node.endpoint, Instant::now()));
},
NodeValidity::Ourselves => (),
}
Ok(None)
} else {
Ok(self.update_node(node))
}
} else {
debug!(target: "discovery", "Got unexpected Pong from {:?} ; request not found", &from);
Ok(None)
}
}
fn on_find_node(&mut self, rlp: &Rlp, _node: &NodeId, from: &SocketAddr) -> Result<Option<TableUpdates>, Error> {
fn on_find_node(&mut self, rlp: &Rlp, node_id: &NodeId, from: &SocketAddr) -> Result<Option<TableUpdates>, Error> {
trace!(target: "discovery", "Got FindNode from {:?}", &from);
let target: NodeId = rlp.val_at(0)?;
let timestamp: u64 = rlp.val_at(1)?;
self.check_timestamp(timestamp)?;
let node = NodeEntry {
id: node_id.clone(),
endpoint: NodeEndpoint {
address: *from,
udp_port: from.port()
}
};
match self.check_validity(&node) {
NodeValidity::Ourselves => (), // It makes no sense to respond to the discovery request from ourselves
NodeValidity::ValidNode(_) => self.respond_with_discovery(target, &node)?,
// Make sure the request source is actually there and responds to pings before actually responding
invalidity_reason => self.try_ping(node, PingReason::FromDiscoveryRequest(target, invalidity_reason))
}
Ok(None)
}
fn check_validity(&mut self, node: &NodeEntry) -> NodeValidity {
let id_hash = keccak(node.id);
let dist = match Discovery::distance(&self.id_hash, &id_hash) {
Some(dist) => dist,
None => {
debug!(target: "discovery", "Got an incoming discovery request from self: {:?}", node);
return NodeValidity::Ourselves;
}
};
let bucket = &self.node_buckets[dist];
if let Some(known_node) = bucket.nodes.iter().find(|n| n.address.id == node.id) {
debug!(target: "discovery", "Found a known node in a bucket when processing discovery: {:?}/{:?}", known_node, node);
match ((known_node.address.endpoint == node.endpoint), (known_node.last_seen.elapsed() < NODE_LAST_SEEN_TIMEOUT)) {
(true, true) => NodeValidity::ValidNode(NodeCategory::Bucket),
(true, false) => NodeValidity::ExpiredNode(NodeCategory::Bucket),
_ => NodeValidity::UnknownNode
}
} else {
self.other_observed_nodes.get_mut(&node.id).map_or(NodeValidity::UnknownNode, |(endpoint, observed_at)| {
match ((node.endpoint==*endpoint), (observed_at.elapsed() < NODE_LAST_SEEN_TIMEOUT)) {
(true, true) => NodeValidity::ValidNode(NodeCategory::Observed),
(true, false) => NodeValidity::ExpiredNode(NodeCategory::Observed),
_ => NodeValidity::UnknownNode
}
})
}
}
fn respond_with_discovery(&mut self, target: NodeId, node: &NodeEntry) -> Result<(), Error> {
let nearest = self.nearest_node_entries(&target);
if nearest.is_empty() {
return Ok(None);
return Ok(());
}
let mut packets = Discovery::prepare_neighbours_packets(&nearest);
for p in packets.drain(..) {
self.send_packet(PACKET_NEIGHBOURS, from, &p)?;
self.send_packet(PACKET_NEIGHBOURS, &node.endpoint.address, &p)?;
}
trace!(target: "discovery", "Sent {} Neighbours to {:?}", nearest.len(), &from);
Ok(None)
trace!(target: "discovery", "Sent {} Neighbours to {:?}", nearest.len(), &node.endpoint);
Ok(())
}
fn prepare_neighbours_packets(nearest: &[NodeEntry]) -> Vec<Bytes> {
@@ -827,7 +950,7 @@ mod tests {
}
// After 4 discovery rounds, the first one should have learned about the rest.
for _round in 0 .. 4 {
for _round in 0 .. 5 {
discovery_handlers[0].round();
let mut continue_loop = true;
@@ -835,9 +958,9 @@ mod tests {
continue_loop = false;
// Process all queued messages.
for i in 0 .. 5 {
let src = discovery_handlers[i].public_endpoint.address.clone();
while let Some(datagram) = discovery_handlers[i].dequeue_send() {
for i in 0 .. 20 {
let src = discovery_handlers[i%5].public_endpoint.address.clone();
while let Some(datagram) = discovery_handlers[i%5].dequeue_send() {
let dest = discovery_handlers.iter_mut()
.find(|disc| datagram.address == disc.public_endpoint.address)
.unwrap();
@@ -929,14 +1052,14 @@ mod tests {
let mut discovery = Discovery { request_backoff: &request_backoff, ..discovery };
for _ in 0..2 {
discovery.ping(&node_entries[101]).unwrap();
discovery.ping(&node_entries[101], PingReason::Default).unwrap();
let num_nodes = total_bucket_nodes(&discovery.node_buckets);
discovery.check_expired(Instant::now() + PING_TIMEOUT);
let removed = num_nodes - total_bucket_nodes(&discovery.node_buckets);
assert_eq!(removed, 0);
}
discovery.ping(&node_entries[101]).unwrap();
discovery.ping(&node_entries[101], PingReason::Default).unwrap();
let num_nodes = total_bucket_nodes(&discovery.node_buckets);
discovery.check_expired(Instant::now() + PING_TIMEOUT);
let removed = num_nodes - total_bucket_nodes(&discovery.node_buckets);
@@ -1123,7 +1246,7 @@ mod tests {
let mut discovery1 = Discovery::new(&key1, ep1.clone(), IpFilter::default());
let mut discovery2 = Discovery::new(&key2, ep2.clone(), IpFilter::default());
discovery1.ping(&NodeEntry { id: discovery2.id, endpoint: ep2.clone() }).unwrap();
discovery1.ping(&NodeEntry { id: discovery2.id, endpoint: ep2.clone() }, PingReason::Default).unwrap();
let ping_data = discovery1.dequeue_send().unwrap();
assert!(!discovery1.any_sends_queued());
let data = &ping_data.payload[(32 + 65)..];

View File

@@ -40,7 +40,7 @@ pub trait SocketAddrExt {
fn is_documentation_s(&self) -> bool { false }
fn is_global_multicast(&self) -> bool { false }
fn is_other_multicast(&self) -> bool { false }
fn is_reserved(&self) -> bool;
fn is_usable_public(&self) -> bool;
fn is_usable_private(&self) -> bool;
@@ -50,38 +50,38 @@ pub trait SocketAddrExt {
impl SocketAddrExt for Ipv4Addr {
fn is_global_s(&self) -> bool {
!self.is_private() &&
!self.is_loopback() &&
!self.is_private() &&
!self.is_loopback() &&
!self.is_link_local() &&
!self.is_broadcast() &&
!self.is_broadcast() &&
!self.is_documentation()
}
// Used for communications between a service provider and its subscribers when using a carrier-grade NAT
// Used for communications between a service provider and its subscribers when using a carrier-grade NAT
// see: https://en.wikipedia.org/wiki/Reserved_IP_addresses
fn is_shared_space(&self) -> bool {
*self >= Ipv4Addr::new(100, 64, 0, 0) &&
*self >= Ipv4Addr::new(100, 64, 0, 0) &&
*self <= Ipv4Addr::new(100, 127, 255, 255)
}
// Used for the IANA IPv4 Special Purpose Address Registry
// see: https://en.wikipedia.org/wiki/Reserved_IP_addresses
fn is_special_purpose(&self) -> bool {
*self >= Ipv4Addr::new(192, 0, 0, 0) &&
*self >= Ipv4Addr::new(192, 0, 0, 0) &&
*self <= Ipv4Addr::new(192, 0, 0, 255)
}
// Used for testing of inter-network communications between two separate subnets
// see: https://en.wikipedia.org/wiki/Reserved_IP_addresses
fn is_benchmarking(&self) -> bool {
*self >= Ipv4Addr::new(198, 18, 0, 0) &&
*self >= Ipv4Addr::new(198, 18, 0, 0) &&
*self <= Ipv4Addr::new(198, 19, 255, 255)
}
// Reserved for future use
// see: https://en.wikipedia.org/wiki/Reserved_IP_addresses
fn is_future_use(&self) -> bool {
*self >= Ipv4Addr::new(240, 0, 0, 0) &&
*self >= Ipv4Addr::new(240, 0, 0, 0) &&
*self <= Ipv4Addr::new(255, 255, 255, 254)
}
@@ -102,7 +102,7 @@ impl SocketAddrExt for Ipv4Addr {
!self.is_reserved() &&
!self.is_private()
}
fn is_usable_private(&self) -> bool {
self.is_private()
}
@@ -118,7 +118,7 @@ impl SocketAddrExt for Ipv4Addr {
impl SocketAddrExt for Ipv6Addr {
fn is_global_s(&self) -> bool {
self.is_global_multicast() ||
(!self.is_loopback() &&
(!self.is_loopback() &&
!self.is_unique_local_s() &&
!self.is_unicast_link_local_s() &&
!self.is_documentation_s() &&
@@ -134,7 +134,7 @@ impl SocketAddrExt for Ipv6Addr {
fn is_unicast_link_local_s(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfe80
}
// reserved for documentation (2001:db8::/32).
fn is_documentation_s(&self) -> bool {
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
@@ -160,7 +160,7 @@ impl SocketAddrExt for Ipv6Addr {
!self.is_reserved() &&
!self.is_unique_local_s()
}
fn is_usable_private(&self) -> bool {
self.is_unique_local_s()
}
@@ -194,7 +194,7 @@ impl SocketAddrExt for IpAddr {
IpAddr::V6(ref ip) => ip.is_usable_public(),
}
}
fn is_usable_private(&self) -> bool {
match *self {
IpAddr::V4(ref ip) => ip.is_usable_private(),
@@ -308,7 +308,15 @@ pub fn select_public_address(port: u16) -> SocketAddr {
pub fn map_external_address(local: &NodeEndpoint) -> Option<NodeEndpoint> {
if let SocketAddr::V4(ref local_addr) = local.address {
match search_gateway_from_timeout(*local_addr.ip(), Duration::new(5, 0)) {
let local_ip = *local_addr.ip();
let search_gateway_child = ::std::thread::spawn(move || {
search_gateway_from_timeout(local_ip, Duration::new(5, 0))
});
let gateway_result = match search_gateway_child.join() {
Err(_) => return None,
Ok(gateway_result) => gateway_result,
};
match gateway_result {
Err(ref err) => debug!("Gateway search error: {}", err),
Ok(gateway) => {
match gateway.get_external_ip() {
@@ -425,32 +433,32 @@ fn ipv4_future_use() {
fn ipv4_usable_public() {
assert!(!Ipv4Addr::new(0,0,0,0).is_usable_public()); // unspecified
assert!(Ipv4Addr::new(0,0,0,1).is_usable_public());
assert!(Ipv4Addr::new(9,255,255,255).is_usable_public());
assert!(!Ipv4Addr::new(10,0,0,0).is_usable_public()); // private intra-network
assert!(!Ipv4Addr::new(10,255,255,255).is_usable_public()); // private intra-network
assert!(Ipv4Addr::new(11,0,0,0).is_usable_public());
assert!(Ipv4Addr::new(100, 63, 255, 255).is_usable_public());
assert!(!Ipv4Addr::new(100, 64, 0, 0).is_usable_public()); // shared space
assert!(!Ipv4Addr::new(100, 64, 0, 0).is_usable_public()); // shared space
assert!(!Ipv4Addr::new(100, 127, 255, 255).is_usable_public()); // shared space
assert!(Ipv4Addr::new(100, 128, 0, 0).is_usable_public());
assert!(Ipv4Addr::new(126,255,255,255).is_usable_public());
assert!(!Ipv4Addr::new(127,0,0,0).is_usable_public()); // loopback
assert!(!Ipv4Addr::new(127,255,255,255).is_usable_public()); // loopback
assert!(Ipv4Addr::new(128,0,0,0).is_usable_public());
assert!(Ipv4Addr::new(169,253,255,255).is_usable_public());
assert!(!Ipv4Addr::new(169,254,0,0).is_usable_public()); // link-local
assert!(!Ipv4Addr::new(169,254,255,255).is_usable_public()); // link-local
assert!(Ipv4Addr::new(169,255,0,0).is_usable_public());
assert!(Ipv4Addr::new(172,15,255,255).is_usable_public());
assert!(!Ipv4Addr::new(172,16,0,0).is_usable_public()); // private intra-network
assert!(!Ipv4Addr::new(172,31,255,255).is_usable_public()); // private intra-network
assert!(Ipv4Addr::new(172,32,255,255).is_usable_public());
assert!(Ipv4Addr::new(191,255,255,255).is_usable_public());
assert!(!Ipv4Addr::new(192,0,0,0).is_usable_public()); // special purpose
assert!(!Ipv4Addr::new(192,0,0,255).is_usable_public()); // special purpose
@@ -458,19 +466,19 @@ fn ipv4_usable_public() {
assert!(Ipv4Addr::new(192,0,1,255).is_usable_public());
assert!(!Ipv4Addr::new(192,0,2,0).is_usable_public()); // documentation
assert!(!Ipv4Addr::new(192,0,2,255).is_usable_public()); // documentation
assert!(!Ipv4Addr::new(192,0,2,255).is_usable_public()); // documentation
assert!(Ipv4Addr::new(192,0,3,0).is_usable_public());
assert!(Ipv4Addr::new(192,167,255,255).is_usable_public());
assert!(!Ipv4Addr::new(192,168,0,0).is_usable_public()); // private intra-network
assert!(!Ipv4Addr::new(192,168,255,255).is_usable_public()); // private intra-network
assert!(Ipv4Addr::new(192,169,0,0).is_usable_public());
assert!(Ipv4Addr::new(198,17,255,255).is_usable_public());
assert!(!Ipv4Addr::new(198,18,0,0).is_usable_public()); // benchmarking
assert!(!Ipv4Addr::new(198,19,255,255).is_usable_public()); // benchmarking
assert!(Ipv4Addr::new(198,20,0,0).is_usable_public());
assert!(Ipv4Addr::new(198,51,99,255).is_usable_public());
assert!(!Ipv4Addr::new(198,51,100,0).is_usable_public()); // documentation
assert!(!Ipv4Addr::new(198,51,100,255).is_usable_public()); // documentation
@@ -485,7 +493,7 @@ fn ipv4_usable_public() {
assert!(!Ipv4Addr::new(224,0,0,0).is_usable_public()); // multicast
assert!(!Ipv4Addr::new(239, 255, 255, 255).is_usable_public()); // multicast
assert!(!Ipv4Addr::new(240, 0, 0, 0).is_usable_public()); // future use
assert!(!Ipv4Addr::new(255, 255, 255, 254).is_usable_public()); // future use
assert!(!Ipv4Addr::new(255, 255, 255, 254).is_usable_public()); // future use
assert!(!Ipv4Addr::new(255, 255, 255, 255).is_usable_public()); // limited broadcast
}
@@ -495,12 +503,12 @@ fn ipv4_usable_private() {
assert!(Ipv4Addr::new(10,0,0,0).is_usable_private()); // private intra-network
assert!(Ipv4Addr::new(10,255,255,255).is_usable_private()); // private intra-network
assert!(!Ipv4Addr::new(11,0,0,0).is_usable_private());
assert!(!Ipv4Addr::new(172,15,255,255).is_usable_private());
assert!(Ipv4Addr::new(172,16,0,0).is_usable_private()); // private intra-network
assert!(Ipv4Addr::new(172,31,255,255).is_usable_private()); // private intra-network
assert!(!Ipv4Addr::new(172,32,255,255).is_usable_private());
assert!(!Ipv4Addr::new(192,167,255,255).is_usable_private());
assert!(Ipv4Addr::new(192,168,0,0).is_usable_private()); // private intra-network
assert!(Ipv4Addr::new(192,168,255,255).is_usable_private()); // private intra-network

View File

@@ -85,6 +85,7 @@ extern crate keccak_hash as hash;
extern crate serde;
extern crate serde_json;
extern crate parity_snappy as snappy;
extern crate lru_cache;
#[macro_use]
extern crate error_chain;

View File

@@ -3,22 +3,22 @@
[package]
name = "parity-version"
# NOTE: this value is used for Parity Ethereum version string (via env CARGO_PKG_VERSION)
version = "2.2.3"
version = "2.2.10"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
[package.metadata]
# This versions track. Should be changed to `stable` or `beta` when on respective branches.
# Used by auto-updater and for Parity version string.
track = "beta"
track = "stable"
# Network specific settings, used ONLY by auto-updater.
# Latest supported fork blocks.
# Indicates a critical release in this track (i.e. consensus issue).
[package.metadata.networks]
foundation = { forkBlock = 4370000, critical = false }
ropsten = { forkBlock = 4230000, critical = false }
kovan = { forkBlock = 6600000, critical = false }
foundation = { forkBlock = 7280000, critical = false }
ropsten = { forkBlock = 4939394, critical = false }
kovan = { forkBlock = 10255201, critical = false }
[dependencies]
parity-bytes = "0.1"