Compare commits

..

6 Commits

Author SHA1 Message Date
Pierre Krieger
678138f097 Backport #10285 to beta (#10286)
* Don't run the CPP example on CI

* Add comment
2019-02-03 14:02:40 +01:00
Kirill Pimenov
b4e4038fb5 Additional tests for uint deserialization. (#10280) 2019-02-03 12:50:38 +01:00
Afri Schoedon
7a8e5976bc version: bump beta to 2.3.2 (#10283) 2019-02-03 12:44:26 +01:00
Afri Schoedon
938c8d8bcd Macos heapsize force jemalloc (#10234) (#10259)
* 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.
2019-01-30 12:02:02 +01:00
Afri Schoedon
3aefa2b960 Beta Backports 2.3.1 (#10225)
* version: bump beta to 2.3.1

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

* Change igd to github:maufl/rust-igd

* Run `igd::search_gateway_from_timeout` from own thread

* 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

* Run all `igd` methods in its own thread (#10195)

* 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:33:45 +01:00
Afri Schoedon
10657d96c4 backports for 2.3.0 beta (#10164)
* version: mark 2.3 track beta

* version: mark update critical on all networks

* Ping nodes from discovery (#10167)

* 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 23:05:56 +01:00
339 changed files with 10986 additions and 17652 deletions

View File

@@ -4,17 +4,12 @@ stages:
- publish
- optional
image: parity/rust-parity-ethereum-build:xenial
variables:
GIT_STRATEGY: fetch
GIT_SUBMODULE_STRATEGY: recursive
CI_SERVER_NAME: "GitLab CI"
CARGO_TARGET: x86_64-unknown-linux-gnu
image: parity/rust:gitlab-ci
.no_git: &no_git # disable git strategy
variables:
GIT_STRATEGY: none
GIT_SUBMODULE_STRATEGY: none
variables:
CI_SERVER_NAME: "GitLab CI"
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
CARGO_TARGET: x86_64-unknown-linux-gnu
.releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries")
only: &releaseable_branches
@@ -23,126 +18,57 @@ variables:
- tags
- schedules
.collect_artifacts: &collect_artifacts
artifacts:
name: "${CI_JOB_NAME}_${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
when: on_success
expire_in: 1 mos
paths:
- artifacts/
- artifacts/
.docker-cache-status: &docker-cache-status
variables:
CARGO_HOME: "/cargo/${CI_JOB_NAME}"
before_script:
- SCCACHE_ERROR_LOG=/builds/parity/parity-ethereum/sccache_error.log RUST_LOG=sccache::server=debug sccache --start-server
- sccache -s
after_script:
- echo "All crate-types:"
- grep 'parse_arguments.*--crate-type' sccache_error.log | sed -re 's/.*"--crate-type", "([^"]+)".*/\1/' | sort | uniq -c
- echo "Non-cacheable reasons:"
- grep CannotCache sccache_error.log | sed -re 's/.*CannotCache\((.+)\).*/\1/' | sort | uniq -c
tags:
- linux-docker
cargo-check 0 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --no-default-features
- sccache -s
cargo-check 1 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --no-default-features
- sccache -s
cargo-check 2 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --features "mio"
- sccache -s
cargo-audit:
stage: test
<<: *docker-cache-status
script:
- cargo audit
- sccache -s
validate-chainspecs:
stage: test
<<: *docker-cache-status
script:
- ./scripts/gitlab/validate-chainspecs.sh
- sccache -s
test-cpp:
stage: build
<<: *docker-cache-status
script:
- ./scripts/gitlab/test-cpp.sh
- sccache -s
.determine_version: &determine_version
- VERSION="$(sed -r -n '1,/^version/s/^version = "([^"]+)".*$/\1/p' Cargo.toml)"
- DATE_STR="$(date +%Y%m%d)"
- ID_SHORT="$(echo ${CI_COMMIT_SHA} | cut -c 1-7)"
- test "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" = "nightly" && VERSION="${VERSION}-${ID_SHORT}-${DATE_STR}"
- export VERSION
- echo "Version = ${VERSION}"
test-linux:
stage: build
<<: *docker-cache-status
script:
- ./scripts/gitlab/test-linux.sh
- sccache -s
build-android:
stage: build
image: parity/rust-android:gitlab-ci
stage: test
variables:
CARGO_TARGET: armv7-linux-androideabi
RUN_TESTS: all
script:
- scripts/gitlab/build-linux.sh
- scripts/gitlab/test-all.sh stable
tags:
- linux-docker
<<: *collect_artifacts
- rust-stable
build-linux: &build-linux
test-audit:
stage: test
script:
- scripts/gitlab/cargo-audit.sh
tags:
- rust-stable
build-linux:
stage: build
only: *releaseable_branches
<<: *docker-cache-status
script:
- scripts/gitlab/build-linux.sh
- sccache -s
- scripts/gitlab/build-unix.sh
<<: *collect_artifacts
build-linux-i386:
<<: *build-linux
image: parity/rust-parity-ethereum-build:i386
variables:
CARGO_TARGET: i686-unknown-linux-gnu
build-linux-arm64:
<<: *build-linux
image: parity/rust-parity-ethereum-build:arm64
variables:
CARGO_TARGET: aarch64-unknown-linux-gnu
build-linux-armhf:
<<: *build-linux
image: parity/rust-parity-ethereum-build:armhf
variables:
CARGO_TARGET: armv7-unknown-linux-gnueabihf
tags:
- rust-stable
build-darwin:
stage: build
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-apple-darwin
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
CC: gcc
CXX: g++
script:
- scripts/gitlab/build-linux.sh
- scripts/gitlab/build-unix.sh
tags:
- rust-osx
<<: *collect_artifacts
@@ -152,17 +78,16 @@ build-windows:
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-pc-windows-msvc
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
script:
- sh scripts/gitlab/build-windows.sh
tags:
- rust-windows
- rust-windows
<<: *collect_artifacts
publish-docker:
stage: publish
only: *releaseable_branches
cache: {}
cache: {}
dependencies:
- build-linux
tags:
@@ -170,91 +95,77 @@ publish-docker:
script:
- scripts/gitlab/publish-docker.sh parity
publish-snap: &publish-snap
publish-snap:
stage: publish
only: *releaseable_branches
image: snapcore/snapcraft
image: parity/snapcraft:gitlab-ci
variables:
BUILD_ARCH: amd64
cache: {}
BUILD_ARCH: amd64
cache: {}
before_script: *determine_version
dependencies:
- build-linux
tags:
- linux-docker
- rust-stable
script:
- scripts/gitlab/publish-snap.sh
allow_failure: true
<<: *collect_artifacts
publish-snap-i386:
<<: *publish-snap
variables:
BUILD_ARCH: i386
dependencies:
- build-linux-i386
publish-snap-arm64:
<<: *publish-snap
variables:
BUILD_ARCH: arm64
dependencies:
- build-linux-arm64
publish-snap-armhf:
<<: *publish-snap
variables:
BUILD_ARCH: armhf
dependencies:
- build-linux-armhf
publish-onchain:
publish-awss3:
stage: publish
only: *releaseable_branches
cache: {}
cache: {}
dependencies:
- build-linux
- build-darwin
- build-windows
before_script: *determine_version
script:
- scripts/gitlab/publish-onchain.sh
- scripts/gitlab/publish-awss3.sh
tags:
- linux-docker
publish-awss3-release:
image: parity/awscli:latest
stage: publish
only: *releaseable_branches
<<: *no_git
cache: {}
dependencies:
- build-linux
- build-darwin
- build-windows
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}}/
- echo "__________Read from S3____________"
- aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}} --recursive --human-readable --summarize
tags:
- linux-docker
- shell
publish-docs:
stage: publish
# <<: *no_git
only:
- tags
except:
- nightly
cache: {}
cache: {}
script:
- scripts/gitlab/publish-docs.sh
tags:
- linux-docker
build-android:
stage: optional
image: parity/rust-android:gitlab-ci
variables:
CARGO_TARGET: armv7-linux-androideabi
script:
- scripts/gitlab/build-unix.sh
tags:
- 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

View File

@@ -1,163 +1,276 @@
## Parity-Ethereum [v2.3.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.0) (2019-01-16)
## Parity-Ethereum [v2.2.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.5) (2018-12-14)
Parity-Ethereum 2.2.5-beta is an important release that introduces Constantinople fork at block 7080000 on Mainnet.
This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you.
If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release`strict_empty_steps_transition` **is enabled by default at block 0** for any chain with `empty_steps`.
If your network uses `empty_steps` you **must**:
- plan a hard fork and change `strict_empty_steps_transition` to the desire fork block
- update the clients of the whole network to 2.2.5-beta / 2.1.10-stable.
If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it.
Parity-Ethereum 2.3.0-beta is a consensus-relevant security release that reverts Constantinople on the Ethereum network. Upgrading is mandatory for Ethereum, and strongly recommended for other networks.
The full list of included changes:
- Backports for beta 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047))
- Bump beta to 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047))
- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939))
- Prevent sending empty step message twice
- Prevent sending empty step and then block in the same step
- Don't accept double empty steps
- Do basic validation of self-sealed blocks
- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041))
- Enables strict verification of empty steps - there can be no duplicates and empty steps should be ordered inside the seal.
- Note that authorities won't produce invalid seals after [#9939](https://github.com/paritytech/parity-ethereum/pull/9939), this PR just adds verification to the seal to prevent forging incorrect blocks and potentially causing consensus issues.
- This features is enabled by default so any AuRa + EmptySteps chain should set strict_empty_steps_transition fork block number in their spec and upgrade to v2.2.5-beta or v2.1.10-stable.
- ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/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](https://github.com/paritytech/parity-ethereum/pull/10024))
- Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019))
- **Consensus** - Ethereum Network: Pull Constantinople protocol upgrade on Ethereum (#10189)
- Read more: [Security Alert: Ethereum Constantinople Postponement](https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/)
- **Networking** - All networks: Ping nodes from discovery (#10167)
- **Wasm** - Kovan Network: Update pwasm-utils to 0.6.1 (#10134)
## Parity-Ethereum [v2.2.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.2) (2018-11-29)
Other notable changes:
Parity-Ethereum 2.2.2-beta is an exciting release. Among others, it improves sync performance, peering stability, block propagation, and transaction propagation times. Also, a warp-sync no longer removes existing blocks from the database, but rather reuses locally available information to decrease sync times and reduces required bandwidth.
- Existing blocks in the database are now kept when restoring a Snapshot. (#8643)
- Block and transaction propagation is improved significantly. (#9954)
- The ERC-191 Signed Data Standard is now supported by `personal_sign191`. (#9701)
- Add support for ERC-191/712 `eth_signTypedData` as a standard for machine-verifiable and human-readable typed data signing with Ethereum keys. (#9631)
- Add support for ERC-1186 `eth_getProof` (#9001)
- Add experimental RPCs flag to enable ERC-191, ERC-712, and ERC-1186 APIs via `--jsonrpc-experimental` (#9928)
- Make `CALLCODE` to trace value to be the code address. (#9881)
Before upgrading to 2.2.2, please also verify the validity of your chain specs. Parity Ethereum now denies unknown fields in the specification. To do this, use the chainspec tool:
Configuration changes:
```
cargo build --release -p chainspec
./target/release/chainspec /path/to/spec.json
```
- The EIP-98 transition is now disabled by default. If you previously had no `eip98transition` specified in your chain specification, you would enable this now manually on block `0x0`. (#9955)
- Also, unknown fields in chain specs are now rejected. (#9972)
- The Tendermint engine was removed from Parity Ethereum and is no longer available and maintained. (#9980)
- Ropsten testnet data and keys moved from `test/` to `ropsten/` subdir. To reuse your old keys and data either copy or symlink them to the new location. (#10123)
- Strict empty steps validation (#10041)
- If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release `strict_empty_steps_transition` is enabled by default at block `0x0` for any chain with `empty_steps`.
- If your network uses `empty_steps` you **must** (A) plan a hard fork and change `strict_empty_steps_transition` to the desired fork block and (B) update the clients of the whole network to 2.2.7-stable / 2.3.0-beta. If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it.
_Note:_ This release marks Parity 2.3 as _beta_. All versions of Parity 2.2 are now considered _stable_.
Last but not least, JSONRPC APIs which are not yet accepted as an EIP in the `eth`, `personal`, or `web3` namespace, are now considere experimental as their final specification might change in future. These APIs have to be manually enabled by explicitly running `--jsonrpc-experimental`.
The full list of included changes:
- Backports for 2.3.0 beta ([#10164](https://github.com/paritytech/parity-ethereum/pull/10164))
- Snap: fix path in script ([#10157](https://github.com/paritytech/parity-ethereum/pull/10157))
- Make sure parent block is not in importing queue when importing ancient blocks ([#10138](https://github.com/paritytech/parity-ethereum/pull/10138))
- Ci: re-enable snap publishing ([#10142](https://github.com/paritytech/parity-ethereum/pull/10142))
- Hf in POA Core (2019-01-18) - Constantinople ([#10155](https://github.com/paritytech/parity-ethereum/pull/10155))
- Update EWF's tobalaba chainspec ([#10152](https://github.com/paritytech/parity-ethereum/pull/10152))
- Replace ethcore-logger with env-logger. ([#10102](https://github.com/paritytech/parity-ethereum/pull/10102))
- Finality: dont require chain head to be in the chain ([#10054](https://github.com/paritytech/parity-ethereum/pull/10054))
- Remove caching for node connections ([#10143](https://github.com/paritytech/parity-ethereum/pull/10143))
- Blooms file iterator empty on out of range position. ([#10145](https://github.com/paritytech/parity-ethereum/pull/10145))
- Autogen docs for the "Configuring Parity Ethereum" wiki page. ([#10067](https://github.com/paritytech/parity-ethereum/pull/10067))
- Misc: bump license header to 2019 ([#10135](https://github.com/paritytech/parity-ethereum/pull/10135))
- Hide most of the logs from cpp example. ([#10139](https://github.com/paritytech/parity-ethereum/pull/10139))
- Don't try to send oversized packets ([#10042](https://github.com/paritytech/parity-ethereum/pull/10042))
- Private tx enabled flag added into STATUS packet ([#9999](https://github.com/paritytech/parity-ethereum/pull/9999))
- Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134))
- Extract blockchain from ethcore ([#10114](https://github.com/paritytech/parity-ethereum/pull/10114))
- Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123))
- Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128))
- Use LenCachingMutex to optimize verification. ([#10117](https://github.com/paritytech/parity-ethereum/pull/10117))
- Pyethereum keystore support ([#9710](https://github.com/paritytech/parity-ethereum/pull/9710))
- Bump rocksdb-sys to 0.5.5 ([#10124](https://github.com/paritytech/parity-ethereum/pull/10124))
- Parity-clib: `async C bindings to RPC requests` + `subscribe/unsubscribe to websocket events` ([#9920](https://github.com/paritytech/parity-ethereum/pull/9920))
- Refactor (hardware wallet) : reduce the number of threads ([#9644](https://github.com/paritytech/parity-ethereum/pull/9644))
- Hf in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077))
- Fix broken links ([#10119](https://github.com/paritytech/parity-ethereum/pull/10119))
- Follow-up to [#10105](https://github.com/paritytech/parity-ethereum/issues/10105) ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107))
- Move EIP-712 crate back to parity-ethereum ([#10106](https://github.com/paritytech/parity-ethereum/pull/10106))
- Move a bunch of stuff around ([#10101](https://github.com/paritytech/parity-ethereum/pull/10101))
- Revert "Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081))" ([#10105](https://github.com/paritytech/parity-ethereum/pull/10105))
- Fix left over small grumbles on whitespaces ([#10084](https://github.com/paritytech/parity-ethereum/pull/10084))
- Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081))
- Fix pubsub new_blocks notifications to include all blocks ([#9987](https://github.com/paritytech/parity-ethereum/pull/9987))
- Update some dependencies for compilation with pc-windows-gnu ([#10082](https://github.com/paritytech/parity-ethereum/pull/10082))
- Fill transaction hash on ethGetLog of light client. ([#9938](https://github.com/paritytech/parity-ethereum/pull/9938))
- Update changelog update for 2.2.5-beta and 2.1.10-stable ([#10064](https://github.com/paritytech/parity-ethereum/pull/10064))
- Implement len caching for parking_lot RwLock ([#10032](https://github.com/paritytech/parity-ethereum/pull/10032))
- Update parking_lot to 0.7 ([#10050](https://github.com/paritytech/parity-ethereum/pull/10050))
- Bump crossbeam. ([#10048](https://github.com/paritytech/parity-ethereum/pull/10048))
- Ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/10031))
- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041))
- Center the Subtitle, use some CAPS ([#10034](https://github.com/paritytech/parity-ethereum/pull/10034))
- Change test miner max memory to malloc reports. ([#10024](https://github.com/paritytech/parity-ethereum/pull/10024))
- Sort the storage for private state ([#10018](https://github.com/paritytech/parity-ethereum/pull/10018))
- Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019))
- Ci: move future releases to ethereum subdir on s3 ([#10017](https://github.com/paritytech/parity-ethereum/pull/10017))
- Light(on_demand): decrease default time window to 10 secs ([#10016](https://github.com/paritytech/parity-ethereum/pull/10016))
- Light client : failsafe crate (circuit breaker) ([#9790](https://github.com/paritytech/parity-ethereum/pull/9790))
- Lencachingmutex ([#9988](https://github.com/paritytech/parity-ethereum/pull/9988))
- Version and notification for private contract wrapper added ([#9761](https://github.com/paritytech/parity-ethereum/pull/9761))
- Handle failing case for update account cache in require ([#9989](https://github.com/paritytech/parity-ethereum/pull/9989))
- Add tokio runtime to ethcore io worker ([#9979](https://github.com/paritytech/parity-ethereum/pull/9979))
- Move daemonize before creating account provider ([#10003](https://github.com/paritytech/parity-ethereum/pull/10003))
- Docs: update changelogs ([#9990](https://github.com/paritytech/parity-ethereum/pull/9990))
- Fix daemonize ([#10000](https://github.com/paritytech/parity-ethereum/pull/10000))
- Fix Bloom migration ([#9992](https://github.com/paritytech/parity-ethereum/pull/9992))
- Remove tendermint engine support ([#9980](https://github.com/paritytech/parity-ethereum/pull/9980))
- Calculate gas for deployment transaction ([#9840](https://github.com/paritytech/parity-ethereum/pull/9840))
- Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967))
- Adds parity_verifySignature RPC method ([#9507](https://github.com/paritytech/parity-ethereum/pull/9507))
- Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954))
- Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972))
- Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971))
- Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970))
- Add changelogs for 2.0.9, 2.1.4, 2.1.6, and 2.2.1 ([#9963](https://github.com/paritytech/parity-ethereum/pull/9963))
- Add Error message when sync is still in progress. ([#9475](https://github.com/paritytech/parity-ethereum/pull/9475))
- Make CALLCODE to trace value to be the code address ([#9881](https://github.com/paritytech/parity-ethereum/pull/9881))
- Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932))
- Add a optional json dump state to evm-bin ([#9706](https://github.com/paritytech/parity-ethereum/pull/9706))
- Disable EIP-98 transition by default ([#9955](https://github.com/paritytech/parity-ethereum/pull/9955))
- Remove secret_store runtimes. ([#9888](https://github.com/paritytech/parity-ethereum/pull/9888))
- Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952))
- Chore(eip712): remove unused `failure-derive` ([#9958](https://github.com/paritytech/parity-ethereum/pull/9958))
- Do not use the home directory as the working dir in docker ([#9834](https://github.com/paritytech/parity-ethereum/pull/9834))
- Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946))
- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939))
- Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925))
- Eip-1186: add `eth_getProof` RPC-Method ([#9001](https://github.com/paritytech/parity-ethereum/pull/9001))
- Missing blocks in filter_changes RPC ([#9947](https://github.com/paritytech/parity-ethereum/pull/9947))
- Allow rust-nightly builds fail in nightly builds ([#9944](https://github.com/paritytech/parity-ethereum/pull/9944))
- Update eth-secp256k1 to include fix for BSDs ([#9935](https://github.com/paritytech/parity-ethereum/pull/9935))
- Unbreak build on rust -stable ([#9934](https://github.com/paritytech/parity-ethereum/pull/9934))
- Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643))
- Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928))
- Clarify poll lifetime ([#9922](https://github.com/paritytech/parity-ethereum/pull/9922))
- Docs(require rust 1.30) ([#9923](https://github.com/paritytech/parity-ethereum/pull/9923))
- Use block header for building finality ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914))
- Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918))
- Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824))
- Eip 191 ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701))
- Fix(logger): `reqwest` no longer a dependency ([#9908](https://github.com/paritytech/parity-ethereum/pull/9908))
- Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906))
- Foundation: 6692865, ropsten: 4417537, kovan: 9363457 ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907))
- Ethcore: use Machine::verify_transaction on parent block ([#9900](https://github.com/paritytech/parity-ethereum/pull/9900))
- Chore(rpc-tests): remove unused rand ([#9896](https://github.com/paritytech/parity-ethereum/pull/9896))
- Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885))
- Chore(bump docopt): 0.8 -> 1.0 ([#9889](https://github.com/paritytech/parity-ethereum/pull/9889))
- Use expect ([#9883](https://github.com/paritytech/parity-ethereum/pull/9883))
- Use Weak reference in PubSubClient ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886))
- Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855))
- Remove unused code ([#9884](https://github.com/paritytech/parity-ethereum/pull/9884))
- Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873))
- Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876))
- Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854))
- Health endpoint ([#9847](https://github.com/paritytech/parity-ethereum/pull/9847))
- Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743))
- Clean up existing benchmarks ([#9839](https://github.com/paritytech/parity-ethereum/pull/9839))
- Update Callisto block reward code to support HF1 ([#9811](https://github.com/paritytech/parity-ethereum/pull/9811))
- Option to disable keep alive for JSON-RPC http transport ([#9848](https://github.com/paritytech/parity-ethereum/pull/9848))
- Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828))
- Support MIX. ([#9767](https://github.com/paritytech/parity-ethereum/pull/9767))
- Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788))
- Implement NoProof for json tests and update tests reference (replaces [#9744](https://github.com/paritytech/parity-ethereum/issues/9744)) ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814))
- Chore(bump regex) ([#9842](https://github.com/paritytech/parity-ethereum/pull/9842))
- Ignore global cache for patched accounts ([#9752](https://github.com/paritytech/parity-ethereum/pull/9752))
- Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841))
- Fix(docker-aarch64) : cross-compile config ([#9798](https://github.com/paritytech/parity-ethereum/pull/9798))
- Version: bump nightly to 2.3.0 ([#9819](https://github.com/paritytech/parity-ethereum/pull/9819))
- Tests modification for windows CI ([#9671](https://github.com/paritytech/parity-ethereum/pull/9671))
- Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631))
- Fix typo ([#9826](https://github.com/paritytech/parity-ethereum/pull/9826))
- Clean up serde rename and use rename_all = camelCase when possible ([#9823](https://github.com/paritytech/parity-ethereum/pull/9823))
- Backports For beta 2.2.2 ([#9976](https://github.com/paritytech/parity-ethereum/pull/9976))
- Version: bump beta to 2.2.2
- Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928))
- Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643))
- Rename db_restore => client
- First step: make it compile!
- Second step: working implementation!
- Refactoring
- Fix tests
- Migrate ancient blocks interacting backward
- Early return in block migration if snapshot is aborted
- Remove RwLock getter (PR Grumble I)
- Remove dependency on `Client`: only used Traits
- Add test for recovering aborted snapshot recovery
- Add test for migrating old blocks
- Release RwLock earlier
- Revert Cargo.lock
- Update _update ancient block_ logic: set local in `commit`
- Update typo in ethcore/src/snapshot/service.rs
- Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925))
- Pip Table Cost relative to average peers instead of max peers
- Add tracing in PIP new_cost_table
- Update stat peer_count
- Use number of leeching peers for Light serve costs
- Fix test::light_params_load_share_depends_on_max_peers (wrong type)
- Remove (now) useless test
- Remove `load_share` from LightParams.Config
- Add LEECHER_COUNT_FACTOR
- Pr Grumble: u64 to u32 for f64 casting
- Prevent u32 overflow for avg_peer_count
- Add tests for LightSync::Statistics
- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/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.
- Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946))
- Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952))
- Update informant:
- Decimal in Mgas/s
- Print every 5s (not randomly between 5s and 10s)
- Fix dead-lock in `blockchain.rs`
- Update locks ordering
- Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932))
- Add `is_idle` to LightSync to check importing status
- Use SyncStateWrapper to make sure is_idle gets updates
- Update is_major_import to use verified queue size as well
- Add comment for `is_idle`
- Add Debug to `SyncStateWrapper`
- `fn get` -> `fn into_inner`
- Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970))
- Ci: rearrange pipeline by logic
- Ci: rename docs script
- Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971))
- Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972))
- Add deny_unknown_fields to chainspec
- Add tests and fix existing one
- Remove serde_ignored dependency for chainspec
- Fix rpc test eth chain spec
- Fix starting_nonce_test spec
- Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954))
- Refactor sync to add priority tasks.
- Send priority tasks notifications.
- Propagate blocks, optimize transactions.
- Implement transaction propagation. Use sync_channel.
- Tone down info.
- Prevent deadlock by not waiting forever for sync lock.
- Fix lock order.
- Don't use sync_channel to prevent deadlocks.
- Fix tests.
- Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967))
- Don't sync all peers after each response
- Update formating
- Fix tests: add `continue_sync` to `Sync_step`
- Update ethcore/sync/src/chain/mod.rs
- Fix rpc middlewares
- Fix Cargo.lock
- Json: resolve merge in spec
- Rpc: fix starting_nonce_test
- Ci: allow nightl job to fail
## Parity-Ethereum [v2.2.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.1) (2018-11-15)
Parity-Ethereum 2.2.1-beta is the first v2.2 release, and might introduce features that break previous work flows, among others:
- Prevent zero network ID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763)) and drop support for Olympic testnet ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801)): The Olympic test net is dead for years and never used a chain ID but network ID zero. Parity Ethereum is now preventing the network ID to be zero, thus Olympic support is dropped. Make sure to chose positive non-zero network IDs in future.
- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239)): adds a CLI argument `--snapshot-threads` which specifies the number of threads. This helps improving the performance of full nodes that wish to provide warp-snapshots for the network. The gain in performance comes with a slight drawback in increased snapshot size.
- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439)): Parity Ethereum imports blocks in rounds. If at the end of any round, the queue is not empty, we consider it to be _importing_ and won't notify pubsub. On large re-orgs (10+ blocks), this is possible. The default `max_round_blocks_to_import` is increased to 12 and configurable via the `--max-round-blocks-to-import` CLI flag. With unstable network conditions, it is advised to increase the number. This shouldn't have any noticeable performance impact unless the number is set to really large.
- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564)): the default values for gas floor target are `8_000_000` and gas cap `10_000_000`, similar to Geth 1.8.15+.
- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725)): we now produce portable binaries, but it may incur some performance degradation. For ultimate performance it's now better to compile Parity Ethereum from source with `PORTABLE=OFF` environment variable.
- RPC: `parity_allTransactionHashes` ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745)): Get all pending transactions from the queue with the high performant `parity_allTransactionHashes` RPC method.
- Support `eth_chainId` RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783)): implements EIP-695 to get the chainID via RPC.
- AuRa: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692)): The AuRa engine was updated to emit ancestry actions to finalize blocks. The full client stores block finality in the database, the engine builds finality from an ancestry of `ExtendedHeader`; `is_epoch_end` was updated to take a vec of recently finalized headers; `is_epoch_end_light` was added which maintains the previous interface and is used by the light client since the client itself doesn't track finality.
The full list of included changes:
- Backport to parity 2.2.1 beta ([#9905](https://github.com/paritytech/parity-ethereum/pull/9905))
- Bump version to 2.2.1
- Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885))
- Fix Parity not closing on Ctrl-C ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886))
- Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873))
- Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854))
- Add hardcoded headers for light client ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907))
- Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743))
- Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876))
- Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906))
- Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824))
- Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631))
- Eip-191 implementation ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701))
- Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918))
- Fix performance issue importing Kovan blocks ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914))
- Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855))
- Backports to parity beta 2.2.0 ([#9820](https://github.com/paritytech/parity-ethereum/pull/9820))
- Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788))
- Implement NoProof for json tests and update tests reference ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814))
- Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841))
- Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828))
- Rpc: parity_allTransactionHashes ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745))
- Revert "prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763))" ([#9815](https://github.com/paritytech/parity-ethereum/pull/9815))
- Allow zero chain id in EIP155 signing process ([#9792](https://github.com/paritytech/parity-ethereum/pull/9792))
- Add readiness check for docker container ([#9804](https://github.com/paritytech/parity-ethereum/pull/9804))
- Insert dev account before unlocking ([#9813](https://github.com/paritytech/parity-ethereum/pull/9813))
- Removed "rustup" & added new runner tag ([#9731](https://github.com/paritytech/parity-ethereum/pull/9731))
- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439))
- Aura: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692))
- Sync: retry different peer after empty subchain heads response ([#9753](https://github.com/paritytech/parity-ethereum/pull/9753))
- Fix(light-rpc/parity) : Remove unused client ([#9802](https://github.com/paritytech/parity-ethereum/pull/9802))
- Drops support for olympic testnet, closes [#9800](https://github.com/paritytech/parity-ethereum/issues/9800) ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801))
- Replace `tokio_core` with `tokio` (`ring` -> 0.13) ([#9657](https://github.com/paritytech/parity-ethereum/pull/9657))
- Support eth_chainId RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783))
- Ethcore: bump ropsten forkblock checkpoint ([#9775](https://github.com/paritytech/parity-ethereum/pull/9775))
- Docs: changelogs for 2.0.8 and 2.1.3 ([#9758](https://github.com/paritytech/parity-ethereum/pull/9758))
- Prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763))
- Skip seal fields count check when --no-seal-check is used ([#9757](https://github.com/paritytech/parity-ethereum/pull/9757))
- Aura: fix panic on extra_info with unsealed block ([#9755](https://github.com/paritytech/parity-ethereum/pull/9755))
- Docs: update changelogs ([#9742](https://github.com/paritytech/parity-ethereum/pull/9742))
- Removed extra assert in generation_session_is_removed_when_succeeded ([#9738](https://github.com/paritytech/parity-ethereum/pull/9738))
- Make checkpoint_storage_at use plain loop instead of recursion ([#9734](https://github.com/paritytech/parity-ethereum/pull/9734))
- Use signed 256-bit integer for sstore gas refund substate ([#9746](https://github.com/paritytech/parity-ethereum/pull/9746))
- Heads ref not present for branches beta and stable ([#9741](https://github.com/paritytech/parity-ethereum/pull/9741))
- Add Callisto support ([#9534](https://github.com/paritytech/parity-ethereum/pull/9534))
- Add --force to cargo audit install script ([#9735](https://github.com/paritytech/parity-ethereum/pull/9735))
- Remove unused expired value from Handshake ([#9732](https://github.com/paritytech/parity-ethereum/pull/9732))
- Add hardcoded headers ([#9730](https://github.com/paritytech/parity-ethereum/pull/9730))
- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725))
- Gitlab ci: releasable_branches: change variables condition to schedule ([#9729](https://github.com/paritytech/parity-ethereum/pull/9729))
- Update a few parity-common dependencies ([#9663](https://github.com/paritytech/parity-ethereum/pull/9663))
- Hf in POA Core (2018-10-22) ([#9724](https://github.com/paritytech/parity-ethereum/pull/9724))
- Schedule nightly builds ([#9717](https://github.com/paritytech/parity-ethereum/pull/9717))
- Fix ancient blocks sync ([#9531](https://github.com/paritytech/parity-ethereum/pull/9531))
- Ci: Skip docs job for nightly ([#9693](https://github.com/paritytech/parity-ethereum/pull/9693))
- Fix (light/provider) : Make `read_only executions` read-only ([#9591](https://github.com/paritytech/parity-ethereum/pull/9591))
- Ethcore: fix detection of major import ([#9552](https://github.com/paritytech/parity-ethereum/pull/9552))
- Return 0 on error ([#9705](https://github.com/paritytech/parity-ethereum/pull/9705))
- Ethcore: delay ropsten hardfork ([#9704](https://github.com/paritytech/parity-ethereum/pull/9704))
- Make instantSeal engine backwards compatible, closes [#9696](https://github.com/paritytech/parity-ethereum/issues/9696) ([#9700](https://github.com/paritytech/parity-ethereum/pull/9700))
- Implement CREATE2 gas changes and fix some potential overflowing ([#9694](https://github.com/paritytech/parity-ethereum/pull/9694))
- Don't hash the init_code of CREATE. ([#9688](https://github.com/paritytech/parity-ethereum/pull/9688))
- Ethcore: minor optimization of modexp by using LR exponentiation ([#9697](https://github.com/paritytech/parity-ethereum/pull/9697))
- Removed redundant clone before each block import ([#9683](https://github.com/paritytech/parity-ethereum/pull/9683))
- Add Foundation Bootnodes ([#9666](https://github.com/paritytech/parity-ethereum/pull/9666))
- Docker: run as parity user ([#9689](https://github.com/paritytech/parity-ethereum/pull/9689))
- Ethcore: mcip3 block reward contract ([#9605](https://github.com/paritytech/parity-ethereum/pull/9605))
- Verify block syncing responses against requests ([#9670](https://github.com/paritytech/parity-ethereum/pull/9670))
- Add a new RPC `parity_submitWorkDetail` similar `eth_submitWork` but return block hash ([#9404](https://github.com/paritytech/parity-ethereum/pull/9404))
- Resumable EVM and heap-allocated callstack ([#9360](https://github.com/paritytech/parity-ethereum/pull/9360))
- Update parity-wordlist library ([#9682](https://github.com/paritytech/parity-ethereum/pull/9682))
- Ci: Remove unnecessary pipes ([#9681](https://github.com/paritytech/parity-ethereum/pull/9681))
- Test.sh: use cargo --target for platforms other than linux, win or mac ([#9650](https://github.com/paritytech/parity-ethereum/pull/9650))
- Ci: fix push script ([#9679](https://github.com/paritytech/parity-ethereum/pull/9679))
- Hardfork the testnets ([#9562](https://github.com/paritytech/parity-ethereum/pull/9562))
- Calculate sha3 instead of sha256 for push-release. ([#9673](https://github.com/paritytech/parity-ethereum/pull/9673))
- Ethcore-io retries failed work steal ([#9651](https://github.com/paritytech/parity-ethereum/pull/9651))
- Fix(light_fetch): avoid race with BlockNumber::Latest ([#9665](https://github.com/paritytech/parity-ethereum/pull/9665))
- Test fix for windows cache name... ([#9658](https://github.com/paritytech/parity-ethereum/pull/9658))
- Refactor(fetch) : light use only one `DNS` thread ([#9647](https://github.com/paritytech/parity-ethereum/pull/9647))
- Ethereum libfuzzer integration small change ([#9547](https://github.com/paritytech/parity-ethereum/pull/9547))
- Cli: remove reference to --no-ui in --unlock flag help ([#9616](https://github.com/paritytech/parity-ethereum/pull/9616))
- Remove master from releasable branches ([#9655](https://github.com/paritytech/parity-ethereum/pull/9655))
- Ethcore/VerificationQueue don't spawn up extra `worker-threads` when explictly specified not to ([#9620](https://github.com/paritytech/parity-ethereum/pull/9620))
- Rpc: parity_getBlockReceipts ([#9527](https://github.com/paritytech/parity-ethereum/pull/9527))
- Remove unused dependencies ([#9589](https://github.com/paritytech/parity-ethereum/pull/9589))
- Ignore key_server_cluster randomly failing tests ([#9639](https://github.com/paritytech/parity-ethereum/pull/9639))
- Ethcore: handle vm exception when estimating gas ([#9615](https://github.com/paritytech/parity-ethereum/pull/9615))
- Fix bad-block reporting no reason ([#9638](https://github.com/paritytech/parity-ethereum/pull/9638))
- Use static call and apparent value transfer for block reward contract code ([#9603](https://github.com/paritytech/parity-ethereum/pull/9603))
- Hf in POA Sokol (2018-09-19) ([#9607](https://github.com/paritytech/parity-ethereum/pull/9607))
- Bump smallvec to 0.6 in ethcore-light, ethstore and whisper ([#9588](https://github.com/paritytech/parity-ethereum/pull/9588))
- Add constantinople conf to EvmTestClient. ([#9570](https://github.com/paritytech/parity-ethereum/pull/9570))
- Fix(network): don't disconnect reserved peers ([#9608](https://github.com/paritytech/parity-ethereum/pull/9608))
- Fix failing node-table tests on mac os, closes [#9632](https://github.com/paritytech/parity-ethereum/issues/9632) ([#9633](https://github.com/paritytech/parity-ethereum/pull/9633))
- Update ropsten.json ([#9602](https://github.com/paritytech/parity-ethereum/pull/9602))
- Simplify ethcore errors by removing BlockImportError ([#9593](https://github.com/paritytech/parity-ethereum/pull/9593))
- Fix windows compilation, replaces [#9561](https://github.com/paritytech/parity-ethereum/issues/9561) ([#9621](https://github.com/paritytech/parity-ethereum/pull/9621))
- Master: rpc-docs set github token ([#9610](https://github.com/paritytech/parity-ethereum/pull/9610))
- Docs: add changelogs for 1.11.10, 1.11.11, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.1.0, and 2.1.1 ([#9554](https://github.com/paritytech/parity-ethereum/pull/9554))
- Docs(rpc): annotate tag with the provided message ([#9601](https://github.com/paritytech/parity-ethereum/pull/9601))
- Ci: fix regex roll_eyes ([#9597](https://github.com/paritytech/parity-ethereum/pull/9597))
- Remove snapcraft clean ([#9585](https://github.com/paritytech/parity-ethereum/pull/9585))
- Add snapcraft package image (master) ([#9584](https://github.com/paritytech/parity-ethereum/pull/9584))
- Docs(rpc): push the branch along with tags ([#9578](https://github.com/paritytech/parity-ethereum/pull/9578))
- Fix typo for jsonrpc-threads flag ([#9574](https://github.com/paritytech/parity-ethereum/pull/9574))
- Fix informant compile ([#9571](https://github.com/paritytech/parity-ethereum/pull/9571))
- Added ropsten bootnodes ([#9569](https://github.com/paritytech/parity-ethereum/pull/9569))
- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564))
- While working on the platform tests make them non-breaking ([#9563](https://github.com/paritytech/parity-ethereum/pull/9563))
- Improve P2P discovery ([#9526](https://github.com/paritytech/parity-ethereum/pull/9526))
- Move dockerfile for android build container to scripts repo ([#9560](https://github.com/paritytech/parity-ethereum/pull/9560))
- Simultaneous platform tests WIP ([#9557](https://github.com/paritytech/parity-ethereum/pull/9557))
- Update ethabi-derive, serde, serde_json, serde_derive, syn && quote ([#9553](https://github.com/paritytech/parity-ethereum/pull/9553))
- Ci: fix rpc docs generation 2 ([#9550](https://github.com/paritytech/parity-ethereum/pull/9550))
- Ci: always run build pipelines for win, mac, linux, and android ([#9537](https://github.com/paritytech/parity-ethereum/pull/9537))
- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239))
- New ethabi ([#9511](https://github.com/paritytech/parity-ethereum/pull/9511))
- Remove initial token for WS. ([#9545](https://github.com/paritytech/parity-ethereum/pull/9545))
- Net_version caches network_id to avoid redundant aquire of sync readlock ([#9544](https://github.com/paritytech/parity-ethereum/pull/9544))
- Correct before_script for nightly build versions ([#9543](https://github.com/paritytech/parity-ethereum/pull/9543))
- Deps: bump kvdb-rocksdb to 0.1.4 ([#9539](https://github.com/paritytech/parity-ethereum/pull/9539))
- State: test when contract creation fails, old storage values should re-appear ([#9532](https://github.com/paritytech/parity-ethereum/pull/9532))
- Allow dropping light client RPC query with no results ([#9318](https://github.com/paritytech/parity-ethereum/pull/9318))
- Bump master to 2.2.0 ([#9517](https://github.com/paritytech/parity-ethereum/pull/9517))
- Enable all Constantinople hard fork changes in constantinople_test.json ([#9505](https://github.com/paritytech/parity-ethereum/pull/9505))
- [Light] Validate `account balance` before importing transactions ([#9417](https://github.com/paritytech/parity-ethereum/pull/9417))
- In create memory calculation is the same for create2 because the additional parameter was popped before. ([#9522](https://github.com/paritytech/parity-ethereum/pull/9522))
- Update patricia trie to 0.2.2 ([#9525](https://github.com/paritytech/parity-ethereum/pull/9525))
- Replace hardcoded JSON with serde json! macro ([#9489](https://github.com/paritytech/parity-ethereum/pull/9489))
- Fix typo in version string ([#9516](https://github.com/paritytech/parity-ethereum/pull/9516))
## Previous releases
- [CHANGELOG-2.2](docs/CHANGELOG-2.2.md) (_stable_)
- [CHANGELOG-2.1](docs/CHANGELOG-2.1.md) (EOL: 2019-01-16)
- [CHANGELOG-2.1](docs/CHANGELOG-2.1.md) (_stable_)
- [CHANGELOG-2.0](docs/CHANGELOG-2.0.md) (EOL: 2018-11-15)
- [CHANGELOG-1.11](docs/CHANGELOG-1.11.md) (EOL: 2018-09-19)
- [CHANGELOG-1.10](docs/CHANGELOG-1.10.md) (EOL: 2018-07-18)

651
Cargo.lock generated

File diff suppressed because it is too large Load Diff

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.4.3"
version = "2.3.2"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
@@ -29,13 +29,11 @@ serde_derive = "1.0"
futures = "0.1"
fdlimit = "0.1"
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
jsonrpc-core = "10.0.1"
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" }
ethcore = { path = "ethcore", features = ["parity"] }
parity-bytes = "0.1"
common-types = { path = "ethcore/types" }
ethcore = { path = "ethcore", features = ["parity"] }
ethcore-accounts = { path = "accounts", optional = true }
ethcore-blockchain = { path = "ethcore/blockchain" }
ethcore-call-contract = { path = "ethcore/call-contract"}
ethcore-db = { path = "ethcore/db" }
ethcore-io = { path = "util/io" }
ethcore-light = { path = "ethcore/light" }
@@ -45,13 +43,12 @@ ethcore-network = { path = "util/network" }
ethcore-private-tx = { path = "ethcore/private-tx" }
ethcore-service = { path = "ethcore/service" }
ethcore-sync = { path = "ethcore/sync" }
ethereum-types = "0.4"
ethkey = { path = "accounts/ethkey" }
ethstore = { path = "accounts/ethstore" }
ethereum-types = "0.4"
node-filter = { path = "ethcore/node-filter" }
ethkey = { path = "accounts/ethkey" }
rlp = { version = "0.3.0", features = ["ethereum"] }
cli-signer= { path = "cli-signer" }
parity-daemonize = "0.3"
parity-hash-fetch = { path = "updater/hash-fetch" }
parity-ipfs-api = { path = "ipfs" }
parity-local-store = { path = "miner/local-store" }
@@ -81,22 +78,22 @@ pretty_assertions = "0.1"
ipnetwork = "0.12.6"
tempdir = "0.3"
fake-fetch = { path = "util/fake-fetch" }
lazy_static = "1.2.0"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] }
[target.'cfg(not(windows))'.dependencies]
daemonize = "0.3"
[features]
default = ["accounts"]
accounts = ["ethcore-accounts", "parity-rpc/accounts"]
miner-debug = ["ethcore/miner-debug"]
json-tests = ["ethcore/json-tests"]
ci-skip-tests = ["ethcore/ci-skip-tests"]
ci-skip-issue = ["ethcore/ci-skip-issue"]
test-heavy = ["ethcore/test-heavy"]
evm-debug = ["ethcore/evm-debug"]
evm-debug-tests = ["ethcore/evm-debug-tests"]
slow-blocks = ["ethcore/slow-blocks"]
secretstore = ["ethcore-secretstore", "ethcore-secretstore/accounts"]
secretstore = ["ethcore-secretstore"]
final = ["parity-version/final"]
deadlock_detection = ["parking_lot/deadlock_detection"]
# to create a memory profile (requires nightly rust), use e.g.
@@ -135,11 +132,6 @@ members = [
"evmbin",
"parity-clib",
"whisper/cli",
"util/triehash-ethereum",
"util/keccak-hasher",
"util/patricia-trie-ethereum",
"util/fastmap",
"util/time-utils"
]
[patch.crates-io]

View File

@@ -125,8 +125,7 @@ To start Parity Ethereum as a regular user using `systemd` init:
1. Copy `./scripts/parity.service` to your
`systemd` user directory (usually `~/.config/systemd/user`).
2. Copy release to bin folder, write `sudo install ./target/release/parity /usr/bin/parity`
3. To configure Parity Ethereum, write a `/etc/parity/config.toml` config file, see [Configuring Parity Ethereum](https://paritytech.github.io/wiki/Configuring-Parity) for details.
2. To configure Parity Ethereum, write a `/etc/parity/config.toml` config file, see [Configuring Parity Ethereum](https://paritytech.github.io/wiki/Configuring-Parity) for details.
## Parity Ethereum toolchain

View File

@@ -1,28 +0,0 @@
[package]
description = "Account management for Parity Ethereum"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore-accounts"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
common-types = { path = "../ethcore/types" }
ethkey = { path = "ethkey" }
ethstore = { path = "ethstore" }
log = "0.4"
parking_lot = "0.7"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))'.dependencies]
hardware-wallet = { path = "hw" }
[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))'.dependencies]
fake-hardware-wallet = { path = "fake-hardware-wallet" }
[dev-dependencies]
ethereum-types = "0.4"
tempdir = "0.3"

View File

@@ -6,7 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = "1.0"
edit-distance = "2.0"
parity-crypto = "0.3.0"
parity-crypto = "0.2"
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
ethereum-types = "0.4"
lazy_static = "1.0"

View File

@@ -6,7 +6,7 @@ Parity Ethereum keys generator.
```
Parity Ethereum keys generator.
Copyright 2015-2019 Parity Technologies (UK) Ltd.
Copyright 2015-2018 Parity Technologies (UK) Ltd.
Usage:
ethkey info <secret-or-phrase> [options]

View File

@@ -35,7 +35,7 @@ use rustc_hex::{FromHex, FromHexError};
const USAGE: &'static str = r#"
Parity Ethereum keys generator.
Copyright 2015-2019 Parity Technologies (UK) Ltd.
Copyright 2015-2018 Parity Technologies (UK) Ltd.
Usage:
ethkey info <secret-or-phrase> [options]

View File

@@ -16,13 +16,12 @@ tiny-keccak = "1.4"
time = "0.1.34"
itertools = "0.5"
parking_lot = "0.7"
parity-crypto = "0.3.0"
parity-crypto = "0.2"
ethereum-types = "0.4"
dir = { path = "../../util/dir" }
smallvec = "0.6"
parity-wordlist = "1.0"
tempdir = "0.3"
lazy_static = "1.2.0"
[dev-dependencies]
matches = "0.1"

View File

@@ -6,7 +6,7 @@ Parity Ethereum key management.
```
Parity Ethereum key management tool.
Copyright 2015-2019 Parity Technologies (UK) Ltd.
Copyright 2015-2018 Parity Technologies (UK) Ltd.
Usage:
ethstore insert <secret> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]

View File

@@ -41,7 +41,7 @@ mod crack;
pub const USAGE: &'static str = r#"
Parity Ethereum key management tool.
Copyright 2015-2019 Parity Technologies (UK) Ltd.
Copyright 2015-2018 Parity Technologies (UK) Ltd.
Usage:
ethstore insert <secret> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]

View File

@@ -15,7 +15,6 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::str;
use std::num::NonZeroU32;
use ethkey::{Password, Secret};
use {json, Error, crypto};
use crypto::Keccak256;
@@ -74,12 +73,12 @@ impl From<Crypto> for String {
impl Crypto {
/// Encrypt account secret
pub fn with_secret(secret: &Secret, password: &Password, iterations: NonZeroU32) -> Result<Self, crypto::Error> {
pub fn with_secret(secret: &Secret, password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
Crypto::with_plain(&*secret, password, iterations)
}
/// Encrypt custom plain data
pub fn with_plain(plain: &[u8], password: &Password, iterations: NonZeroU32) -> Result<Self, crypto::Error> {
pub fn with_plain(plain: &[u8], password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
let salt: [u8; 32] = Random::random();
let iv: [u8; 16] = Random::random();
@@ -160,17 +159,13 @@ impl Crypto {
#[cfg(test)]
mod tests {
use ethkey::{Generator, Random};
use super::{Crypto, Error, NonZeroU32};
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
}
use super::{Crypto, Error};
#[test]
fn crypto_with_secret_create() {
let keypair = Random.generate().unwrap();
let passwd = "this is sparta".into();
let crypto = Crypto::with_secret(keypair.secret(), &passwd, *ITERATIONS).unwrap();
let crypto = Crypto::with_secret(keypair.secret(), &passwd, 10240).unwrap();
let secret = crypto.secret(&passwd).unwrap();
assert_eq!(keypair.secret(), &secret);
}
@@ -178,7 +173,7 @@ mod tests {
#[test]
fn crypto_with_secret_invalid_password() {
let keypair = Random.generate().unwrap();
let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), *ITERATIONS).unwrap();
let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), 10240).unwrap();
assert_matches!(crypto.secret(&"this is sparta!".into()), Err(Error::InvalidPassword))
}
@@ -186,7 +181,7 @@ mod tests {
fn crypto_with_null_plain_data() {
let original_data = b"";
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data[..], &passwd, *ITERATIONS).unwrap();
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
@@ -195,7 +190,7 @@ mod tests {
fn crypto_with_tiny_plain_data() {
let original_data = b"{}";
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data[..], &passwd, *ITERATIONS).unwrap();
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
@@ -204,7 +199,7 @@ mod tests {
fn crypto_with_huge_plain_data() {
let original_data: Vec<_> = (1..65536).map(|i| (i % 256) as u8).collect();
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data, &passwd, *ITERATIONS).unwrap();
let crypto = Crypto::with_plain(&original_data, &passwd, 10240).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(&original_data, &decrypted_data);
}

View File

@@ -15,7 +15,6 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use json;
use std::num::NonZeroU32;
#[derive(Debug, PartialEq, Clone)]
pub enum Prf {
@@ -24,7 +23,7 @@ pub enum Prf {
#[derive(Debug, PartialEq, Clone)]
pub struct Pbkdf2 {
pub c: NonZeroU32,
pub c: u32,
pub dklen: u32,
pub prf: Prf,
pub salt: Vec<u8>,

View File

@@ -20,7 +20,6 @@ use {json, Error};
use account::Version;
use crypto;
use super::crypto::Crypto;
use std::num::NonZeroU32;
/// Account representation.
#[derive(Debug, PartialEq, Clone)]
@@ -60,7 +59,7 @@ impl SafeAccount {
keypair: &KeyPair,
id: [u8; 16],
password: &Password,
iterations: NonZeroU32,
iterations: u32,
name: String,
meta: String
) -> Result<Self, crypto::Error> {
@@ -136,7 +135,7 @@ impl SafeAccount {
}
/// Create a new `VaultKeyFile` from the given `self`
pub fn into_vault_file(self, iterations: NonZeroU32, password: &Password) -> Result<json::VaultKeyFile, Error> {
pub fn into_vault_file(self, iterations: u32, password: &Password) -> Result<json::VaultKeyFile, Error> {
let meta_plain = json::VaultKeyMeta {
address: self.address.into(),
name: Some(self.name),
@@ -178,7 +177,7 @@ impl SafeAccount {
}
/// Change account's password.
pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: NonZeroU32) -> Result<Self, Error> {
pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: u32) -> Result<Self, Error> {
let secret = self.crypto.secret(old_password)?;
let result = SafeAccount {
id: self.id.clone(),
@@ -201,19 +200,14 @@ impl SafeAccount {
#[cfg(test)]
mod tests {
use ethkey::{Generator, Random, verify_public, Message};
use super::{SafeAccount, NonZeroU32};
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
}
use super::SafeAccount;
#[test]
fn sign_and_verify_public() {
let keypair = Random.generate().unwrap();
let password = "hello world".into();
let message = Message::default();
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned());
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 10240, "Test".to_owned(), "{}".to_owned());
let signature = account.unwrap().sign(&password, &message).unwrap();
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
}
@@ -223,9 +217,10 @@ mod tests {
let keypair = Random.generate().unwrap();
let first_password = "hello world".into();
let sec_password = "this is sparta".into();
let i = 10240;
let message = Message::default();
let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap();
let new_account = account.change_password(&first_password, &sec_password, *ITERATIONS).unwrap();
let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap();
let new_account = account.change_password(&first_password, &sec_password, i).unwrap();
assert!(account.sign(&first_password, &message).is_ok());
assert!(account.sign(&sec_password, &message).is_err());
assert!(new_account.sign(&first_password, &message).is_err());

View File

@@ -356,16 +356,11 @@ mod test {
extern crate tempdir;
use std::{env, fs};
use std::num::NonZeroU32;
use super::{KeyDirectory, RootDiskDirectory, VaultKey};
use account::SafeAccount;
use ethkey::{Random, Generator};
use self::tempdir::TempDir;
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed");
}
#[test]
fn should_create_new_account() {
// given
@@ -376,7 +371,7 @@ mod test {
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
// when
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned());
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned());
let res = directory.insert(account.unwrap());
// then
@@ -397,7 +392,7 @@ mod test {
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
// when
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap();
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap();
let filename = "test".to_string();
let dedup = true;
@@ -433,7 +428,7 @@ mod test {
// and when
let before_root_items_count = fs::read_dir(&dir).unwrap().count();
let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(&password, *ITERATIONS));
let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(&password, 1024));
// then
assert!(vault.is_ok());
@@ -441,7 +436,7 @@ mod test {
assert!(after_root_items_count > before_root_items_count);
// and when
let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, *ITERATIONS));
let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, 1024));
// then
assert!(vault.is_ok());
@@ -458,9 +453,8 @@ mod test {
let temp_path = TempDir::new("").unwrap();
let directory = RootDiskDirectory::create(&temp_path).unwrap();
let vault_provider = directory.as_vault_provider().unwrap();
let iter = NonZeroU32::new(1).expect("1 > 0; qed");
vault_provider.create("vault1", VaultKey::new(&"password1".into(), iter)).unwrap();
vault_provider.create("vault2", VaultKey::new(&"password2".into(), iter)).unwrap();
vault_provider.create("vault1", VaultKey::new(&"password1".into(), 1)).unwrap();
vault_provider.create("vault2", VaultKey::new(&"password2".into(), 1)).unwrap();
// then
let vaults = vault_provider.list_vaults().unwrap();
@@ -482,7 +476,7 @@ mod test {
let keypair = Random.generate().unwrap();
let password = "test pass".into();
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned());
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned());
directory.insert(account.unwrap()).expect("Account should be inserted ok");
let new_hash = directory.files_hash().expect("New files hash should be calculated ok");

View File

@@ -17,7 +17,6 @@
//! Accounts Directory
use ethkey::Password;
use std::num::NonZeroU32;
use std::path::{PathBuf};
use {SafeAccount, Error};
@@ -42,7 +41,7 @@ pub struct VaultKey {
/// Vault password
pub password: Password,
/// Number of iterations to produce a derived key from password
pub iterations: NonZeroU32,
pub iterations: u32,
}
/// Keys directory
@@ -97,7 +96,7 @@ pub use self::vault::VaultDiskDirectory;
impl VaultKey {
/// Create new vault key
pub fn new(password: &Password, iterations: NonZeroU32) -> Self {
pub fn new(password: &Password, iterations: u32) -> Self {
VaultKey {
password: password.clone(),
iterations: iterations,

View File

@@ -282,17 +282,11 @@ mod test {
use std::fs;
use std::io::Write;
use std::num::NonZeroU32;
use std::path::PathBuf;
use super::VaultKey;
use super::{VAULT_FILE_NAME, check_vault_name, make_vault_dir_path, create_vault_file, read_vault_file, VaultDiskDirectory};
use self::tempdir::TempDir;
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed");
}
#[test]
fn check_vault_name_succeeds() {
assert!(check_vault_name("vault"));
@@ -331,7 +325,7 @@ mod test {
fn create_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
let key = VaultKey::new(&"password".into(), 1024);
let mut vault_dir: PathBuf = temp_path.path().into();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
@@ -350,7 +344,7 @@ mod test {
fn read_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
let key = VaultKey::new(&"password".into(), 1024);
let vault_file_contents = r#"{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"758696c8dc6378ab9b25bb42790da2f5"},"ciphertext":"54eb50683717d41caaeb12ea969f2c159daada5907383f26f327606a37dc7168","kdf":"pbkdf2","kdfparams":{"c":1024,"dklen":32,"prf":"hmac-sha256","salt":"3c320fa566a1a7963ac8df68a19548d27c8f40bf92ef87c84594dcd5bbc402b6"},"mac":"9e5c2314c2a0781962db85611417c614bd6756666b6b1e93840f5b6ed895f003"}}"#;
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
@@ -371,7 +365,7 @@ mod test {
fn read_vault_file_fails() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password1".into(), *ITERATIONS);
let key = VaultKey::new(&"password1".into(), 1024);
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
@@ -400,7 +394,7 @@ mod test {
fn vault_directory_can_be_created() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
// when
@@ -420,7 +414,7 @@ mod test {
fn vault_directory_cannot_be_created_if_already_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
let mut vault_dir = dir.clone();
vault_dir.push("vault");
@@ -437,7 +431,7 @@ mod test {
fn vault_directory_cannot_be_opened_if_not_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
// when

View File

@@ -15,12 +15,12 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::collections::{BTreeMap, HashMap};
use std::num::NonZeroU32;
use std::mem;
use std::path::PathBuf;
use parking_lot::{Mutex, RwLock};
use std::time::{Instant, Duration};
use crypto::KEY_ITERATIONS;
use random::Random;
use ethkey::{self, Signature, Password, Address, Message, Secret, Public, KeyPair, ExtendedKeyPair};
use accounts_dir::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError};
@@ -29,12 +29,6 @@ use presale::PresaleWallet;
use json::{self, Uuid, OpaqueKeyFile};
use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret};
lazy_static! {
static ref KEY_ITERATIONS: NonZeroU32 =
NonZeroU32::new(crypto::KEY_ITERATIONS as u32).expect("KEY_ITERATIONS > 0; qed");
}
/// Accounts store.
pub struct EthStore {
store: EthMultiStore,
@@ -43,11 +37,11 @@ pub struct EthStore {
impl EthStore {
/// Open a new accounts store with given key directory backend.
pub fn open(directory: Box<KeyDirectory>) -> Result<Self, Error> {
Self::open_with_iterations(directory, *KEY_ITERATIONS)
Self::open_with_iterations(directory, KEY_ITERATIONS as u32)
}
/// Open a new account store with given key directory backend and custom number of iterations.
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: NonZeroU32) -> Result<Self, Error> {
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: u32) -> Result<Self, Error> {
Ok(EthStore {
store: EthMultiStore::open_with_iterations(directory, iterations)?,
})
@@ -263,7 +257,7 @@ impl SecretStore for EthStore {
/// Similar to `EthStore` but may store many accounts (with different passwords) for the same `Address`
pub struct EthMultiStore {
dir: Box<KeyDirectory>,
iterations: NonZeroU32,
iterations: u32,
// order lock: cache, then vaults
cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>,
vaults: Mutex<HashMap<String, Box<VaultKeyDirectory>>>,
@@ -279,11 +273,11 @@ struct Timestamp {
impl EthMultiStore {
/// Open new multi-accounts store with given key directory backend.
pub fn open(directory: Box<KeyDirectory>) -> Result<Self, Error> {
Self::open_with_iterations(directory, *KEY_ITERATIONS)
Self::open_with_iterations(directory, KEY_ITERATIONS as u32)
}
/// Open new multi-accounts store with given key directory backend and custom number of iterations for new keys.
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: NonZeroU32) -> Result<Self, Error> {
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: u32) -> Result<Self, Error> {
let store = EthMultiStore {
dir: directory,
vaults: Mutex::new(HashMap::new()),

View File

@@ -15,7 +15,6 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::fmt;
use std::num::NonZeroU32;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Visitor, Error as SerdeError};
use super::{Error, Bytes};
@@ -109,7 +108,7 @@ impl<'a> Visitor<'a> for PrfVisitor {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Pbkdf2 {
pub c: NonZeroU32,
pub c: u32,
pub dklen: u32,
pub prf: Prf,
pub salt: Bytes,

View File

@@ -41,11 +41,6 @@ impl VaultFile {
mod test {
use serde_json;
use json::{VaultFile, Crypto, Cipher, Aes128Ctr, Kdf, Pbkdf2, Prf};
use std::num::NonZeroU32;
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed");
}
#[test]
fn to_and_from_json() {
@@ -56,7 +51,7 @@ mod test {
}),
ciphertext: "4d6938a1f49b7782".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
c: 1024,
dklen: 32,
prf: Prf::HmacSha256,
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),
@@ -81,7 +76,7 @@ mod test {
}),
ciphertext: "4d6938a1f49b7782".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
c: 1024,
dklen: 32,
prf: Prf::HmacSha256,
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),

View File

@@ -106,11 +106,6 @@ mod test {
use serde_json;
use json::{VaultKeyFile, Version, Crypto, Cipher, Aes128Ctr, Kdf, Pbkdf2, Prf,
insert_vault_name_to_json_meta, remove_vault_name_from_json_meta};
use std::num::NonZeroU32;
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
}
#[test]
fn to_and_from_json() {
@@ -123,7 +118,7 @@ mod test {
}),
ciphertext: "4befe0a66d9a4b6fec8e39eb5c90ac5dafdeaab005fff1af665fd1f9af925c91".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
c: 10240,
dklen: 32,
prf: Prf::HmacSha256,
salt: "f17731e84ecac390546692dbd4ccf6a3a2720dc9652984978381e61c28a471b2".into(),
@@ -136,7 +131,7 @@ mod test {
}),
ciphertext: "fef0d113d7576c1702daf380ad6f4c5408389e57991cae2a174facd74bd549338e1014850bddbab7eb486ff5f5c9c5532800c6a6d4db2be2212cd5cd3769244ab230e1f369e8382a9e6d7c0a".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
c: 10240,
dklen: 32,
prf: Prf::HmacSha256,
salt: "aca82865174a82249a198814b263f43a631f272cbf7ed329d0f0839d259c652a".into(),

View File

@@ -36,8 +36,6 @@ extern crate ethereum_types;
extern crate ethkey as _ethkey;
extern crate parity_wordlist;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]

View File

@@ -15,7 +15,6 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::fs;
use std::num::NonZeroU32;
use std::path::Path;
use json;
use ethkey::{Address, Secret, KeyPair, Password};
@@ -59,8 +58,7 @@ impl PresaleWallet {
let mut derived_key = [0u8; 32];
let salt = pbkdf2::Salt(password.as_bytes());
let sec = pbkdf2::Secret(password.as_bytes());
let iter = NonZeroU32::new(2000).expect("2000 > 0; qed");
pbkdf2::sha256(iter, salt, sec, &mut derived_key);
pbkdf2::sha256(2000, salt, sec, &mut derived_key);
let mut key = vec![0; self.ciphertext.len()];
let len = crypto::aes::decrypt_128_cbc(&derived_key[0..16], &self.iv, &self.ciphertext, &mut key)

View File

@@ -1,73 +0,0 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// 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 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Account Metadata
use std::{
collections::HashMap,
time::Instant,
};
use ethkey::{Address, Password};
use serde_derive::{Serialize, Deserialize};
use serde_json;
/// Type of unlock.
#[derive(Clone, PartialEq)]
pub enum Unlock {
/// If account is unlocked temporarily, it should be locked after first usage.
OneTime,
/// Account unlocked permanently can always sign message.
/// Use with caution.
Perm,
/// Account unlocked with a timeout
Timed(Instant),
}
/// Data associated with account.
#[derive(Clone)]
pub struct AccountData {
pub unlock: Unlock,
pub password: Password,
}
/// Collected account metadata
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct AccountMeta {
/// The name of the account.
pub name: String,
/// The rest of the metadata of the account.
pub meta: String,
/// The 128-bit Uuid of the account, if it has one (brain-wallets don't).
pub uuid: Option<String>,
}
impl AccountMeta {
/// Read a hash map of Address -> AccountMeta
pub fn read<R>(reader: R) -> Result<HashMap<Address, Self>, serde_json::Error> where
R: ::std::io::Read,
{
serde_json::from_reader(reader)
}
/// Write a hash map of Address -> AccountMeta
pub fn write<W>(m: &HashMap<Address, Self>, writer: &mut W) -> Result<(), serde_json::Error> where
W: ::std::io::Write,
{
serde_json::to_writer(writer, m)
}
}

View File

@@ -1,56 +0,0 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::fmt;
use ethstore::{Error as SSError};
use hardware_wallet::{Error as HardwareError};
/// Signing error
#[derive(Debug)]
pub enum SignError {
/// Account is not unlocked
NotUnlocked,
/// Account does not exist.
NotFound,
/// Low-level hardware device error.
Hardware(HardwareError),
/// Low-level error from store
SStore(SSError),
}
impl fmt::Display for SignError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
SignError::NotUnlocked => write!(f, "Account is locked"),
SignError::NotFound => write!(f, "Account does not exist"),
SignError::Hardware(ref e) => write!(f, "{}", e),
SignError::SStore(ref e) => write!(f, "{}", e),
}
}
}
impl From<HardwareError> for SignError {
fn from(e: HardwareError) -> Self {
SignError::Hardware(e)
}
}
impl From<SSError> for SignError {
fn from(e: SSError) -> Self {
SignError::SStore(e)
}
}

View File

@@ -14,7 +14,7 @@ serde_json = "1.0"
url = "1.2.0"
matches = "0.1"
parking_lot = "0.7"
jsonrpc-core = "10.0.1"
jsonrpc-ws-server = "10.0.1"
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" }
jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" }
parity-rpc = { path = "../../rpc" }
keccak-hash = "0.1"

View File

@@ -1,4 +1,4 @@
Note: Parity Ethereum 2.0 reached End-of-Life on 2018-11-15 (EOL).
Note: Parity 2.0 reached End-of-Life on 2018-11-15 (EOL).
## Parity-Ethereum [v2.0.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.9) (2018-10-29)

View File

@@ -1,31 +1,13 @@
Note: Parity Ethereum 2.1 reached End-of-Life on 2019-01-16 (EOL).
## Parity-Ethereum [v2.1.11](https://github.com/paritytech/parity-ethereum/releases/tag/v2.1.11) (2019-01-09)
Parity-Ethereum 2.1.11-stable is a bugfix release that improves performance and stability.
The full list of included changes:
- Stable backports v2.1.11 ([#10112](https://github.com/paritytech/parity-ethereum/pull/10112))
- Version: bump stable to v2.1.11
- HF in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077))
- Add --locked when running cargo ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107))
- Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123))
- Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128))
- Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134))
- Version: mark upgrade critical on kovan
## Parity-Ethereum [v2.1.10](https://github.com/paritytech/parity-ethereum/releases/tag/v2.1.10) (2018-12-14)
Parity-Ethereum 2.1.10-stable is an important release that introduces Constantinople fork at block 7080000 on Mainnet.
This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you.
Parity-Ethereum 2.1.10-stable is an important release that introduces Constantinople fork at block 7080000 on Mainnet.
This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you.
If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release`strict_empty_steps_transition` **is enabled by default at block 0** for any chain with `empty_steps`.
If your network uses `empty_steps` you **must**:
- plan a hard fork and change `strict_empty_steps_transition` to the desire fork block
- update the clients of the whole network to 2.2.5-beta / 2.1.10-stable.
If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it.
The full list of included changes:
The full list of included changes:
- Backports for stable 2.1.10 ([#10046](https://github.com/paritytech/parity-ethereum/pull/10046))
- Bump stable to 2.1.10 ([#10046](https://github.com/paritytech/parity-ethereum/pull/10046))

View File

@@ -1,317 +0,0 @@
## Parity-Ethereum [v2.2.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.7) (2019-01-15)
Parity-Ethereum 2.2.7-stable is a consensus-relevant security release that reverts Constantinople on the Ethereum network. Upgrading is mandatory for Ethereum, and strongly recommended for other networks.
- **Consensus** - Ethereum Network: Pull Constantinople protocol upgrade on Ethereum ([#10189](https://github.com/paritytech/parity-ethereum/pull/10189))
- Read more: [Security Alert: Ethereum Constantinople Postponement](https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/)
- **Networking** - All networks: Ping nodes from discovery ([#10167](https://github.com/paritytech/parity-ethereum/pull/10167))
- **Wasm** - Kovan Network: Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134))
_Note:_ This release marks Parity 2.2 as _stable_. All versions of Parity 2.1 now reached _end of life_.
The full list of included changes:
- Backports for stable 2.2.7 ([#10163](https://github.com/paritytech/parity-ethereum/pull/10163))
- Version: bump stable to 2.2.7
- Version: mark 2.2 track stable
- Version: mark update critical on all networks
- Handle the case for contract creation on an empty but exist account with storage items ([#10065](https://github.com/paritytech/parity-ethereum/pull/10065))
- Fix _cannot recursively call into `Core`_ issue ([#10144](https://github.com/paritytech/parity-ethereum/pull/10144))
- Snap: fix path in script ([#10157](https://github.com/paritytech/parity-ethereum/pull/10157))
- Ping nodes from discovery ([#10167](https://github.com/paritytech/parity-ethereum/pull/10167))
- Version: bump fork blocks for kovan and foundation, mark releases non critical
- Pull constantinople on ethereum network ([#10189](https://github.com/paritytech/parity-ethereum/pull/10189))
## Parity-Ethereum [v2.2.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.6) (2019-01-10)
Parity-Ethereum 2.2.6-beta is a bugfix release that improves performance and stability.
The full list of included changes:
- Beta backports v2.2.6 ([#10113](https://github.com/paritytech/parity-ethereum/pull/10113))
- Version: bump beta to v2.2.6
- Fill transaction hash on ethGetLog of light client. ([#9938](https://github.com/paritytech/parity-ethereum/pull/9938))
- Fix pubsub new_blocks notifications to include all blocks ([#9987](https://github.com/paritytech/parity-ethereum/pull/9987))
- Finality: dont require chain head to be in the chain ([#10054](https://github.com/paritytech/parity-ethereum/pull/10054))
- Handle the case for contract creation on an empty but exist account with storage items ([#10065](https://github.com/paritytech/parity-ethereum/pull/10065))
- Autogen docs for the "Configuring Parity Ethereum" wiki page. ([#10067](https://github.com/paritytech/parity-ethereum/pull/10067))
- HF in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077))
- Add --locked when running cargo ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107))
- Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123))
- Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128))
- Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134))
- Make sure parent block is not in importing queue when importing ancient blocks ([#10138](https://github.com/paritytech/parity-ethereum/pull/10138))
- CI: re-enable snap publishing ([#10142](https://github.com/paritytech/parity-ethereum/pull/10142))
- HF in POA Core (2019-01-18) - Constantinople ([#10155](https://github.com/paritytech/parity-ethereum/pull/10155))
- Version: mark upgrade critical on kovan
## Parity-Ethereum [v2.2.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.5) (2018-12-14)
Parity-Ethereum 2.2.5-beta is an important release that introduces Constantinople fork at block 7080000 on Mainnet.
This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you.
If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release`strict_empty_steps_transition` **is enabled by default at block 0** for any chain with `empty_steps`.
If your network uses `empty_steps` you **must**:
- plan a hard fork and change `strict_empty_steps_transition` to the desire fork block
- update the clients of the whole network to 2.2.5-beta / 2.1.10-stable.
If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it.
The full list of included changes:
- Backports for beta 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047))
- Bump beta to 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047))
- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939))
- Prevent sending empty step message twice
- Prevent sending empty step and then block in the same step
- Don't accept double empty steps
- Do basic validation of self-sealed blocks
- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041))
- Enables strict verification of empty steps - there can be no duplicates and empty steps should be ordered inside the seal.
- Note that authorities won't produce invalid seals after [#9939](https://github.com/paritytech/parity-ethereum/pull/9939), this PR just adds verification to the seal to prevent forging incorrect blocks and potentially causing consensus issues.
- This features is enabled by default so any AuRa + EmptySteps chain should set strict_empty_steps_transition fork block number in their spec and upgrade to v2.2.5-beta or v2.1.10-stable.
- ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/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](https://github.com/paritytech/parity-ethereum/pull/10024))
- Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019))
## Parity-Ethereum [v2.2.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.2) (2018-11-29)
Parity-Ethereum 2.2.2-beta is an exciting release. Among others, it improves sync performance, peering stability, block propagation, and transaction propagation times. Also, a warp-sync no longer removes existing blocks from the database, but rather reuses locally available information to decrease sync times and reduces required bandwidth.
Before upgrading to 2.2.2, please also verify the validity of your chain specs. Parity Ethereum now denies unknown fields in the specification. To do this, use the chainspec tool:
```
cargo build --release -p chainspec
./target/release/chainspec /path/to/spec.json
```
Last but not least, JSONRPC APIs which are not yet accepted as an EIP in the `eth`, `personal`, or `web3` namespace, are now considere experimental as their final specification might change in future. These APIs have to be manually enabled by explicitly running `--jsonrpc-experimental`.
The full list of included changes:
- Backports For beta 2.2.2 ([#9976](https://github.com/paritytech/parity-ethereum/pull/9976))
- Version: bump beta to 2.2.2
- Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928))
- Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643))
- Rename db_restore => client
- First step: make it compile!
- Second step: working implementation!
- Refactoring
- Fix tests
- Migrate ancient blocks interacting backward
- Early return in block migration if snapshot is aborted
- Remove RwLock getter (PR Grumble I)
- Remove dependency on `Client`: only used Traits
- Add test for recovering aborted snapshot recovery
- Add test for migrating old blocks
- Release RwLock earlier
- Revert Cargo.lock
- Update _update ancient block_ logic: set local in `commit`
- Update typo in ethcore/src/snapshot/service.rs
- Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925))
- Pip Table Cost relative to average peers instead of max peers
- Add tracing in PIP new_cost_table
- Update stat peer_count
- Use number of leeching peers for Light serve costs
- Fix test::light_params_load_share_depends_on_max_peers (wrong type)
- Remove (now) useless test
- Remove `load_share` from LightParams.Config
- Add LEECHER_COUNT_FACTOR
- Pr Grumble: u64 to u32 for f64 casting
- Prevent u32 overflow for avg_peer_count
- Add tests for LightSync::Statistics
- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/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.
- Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946))
- Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952))
- Update informant:
- Decimal in Mgas/s
- Print every 5s (not randomly between 5s and 10s)
- Fix dead-lock in `blockchain.rs`
- Update locks ordering
- Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932))
- Add `is_idle` to LightSync to check importing status
- Use SyncStateWrapper to make sure is_idle gets updates
- Update is_major_import to use verified queue size as well
- Add comment for `is_idle`
- Add Debug to `SyncStateWrapper`
- `fn get` -> `fn into_inner`
- Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970))
- Ci: rearrange pipeline by logic
- Ci: rename docs script
- Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971))
- Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972))
- Add deny_unknown_fields to chainspec
- Add tests and fix existing one
- Remove serde_ignored dependency for chainspec
- Fix rpc test eth chain spec
- Fix starting_nonce_test spec
- Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954))
- Refactor sync to add priority tasks.
- Send priority tasks notifications.
- Propagate blocks, optimize transactions.
- Implement transaction propagation. Use sync_channel.
- Tone down info.
- Prevent deadlock by not waiting forever for sync lock.
- Fix lock order.
- Don't use sync_channel to prevent deadlocks.
- Fix tests.
- Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967))
- Don't sync all peers after each response
- Update formating
- Fix tests: add `continue_sync` to `Sync_step`
- Update ethcore/sync/src/chain/mod.rs
- Fix rpc middlewares
- Fix Cargo.lock
- Json: resolve merge in spec
- Rpc: fix starting_nonce_test
- Ci: allow nightl job to fail
## Parity-Ethereum [v2.2.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.1) (2018-11-15)
Parity-Ethereum 2.2.1-beta is the first v2.2 release, and might introduce features that break previous work flows, among others:
- Prevent zero network ID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763)) and drop support for Olympic testnet ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801)): The Olympic test net is dead for years and never used a chain ID but network ID zero. Parity Ethereum is now preventing the network ID to be zero, thus Olympic support is dropped. Make sure to chose positive non-zero network IDs in future.
- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239)): adds a CLI argument `--snapshot-threads` which specifies the number of threads. This helps improving the performance of full nodes that wish to provide warp-snapshots for the network. The gain in performance comes with a slight drawback in increased snapshot size.
- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439)): Parity Ethereum imports blocks in rounds. If at the end of any round, the queue is not empty, we consider it to be _importing_ and won't notify pubsub. On large re-orgs (10+ blocks), this is possible. The default `max_round_blocks_to_import` is increased to 12 and configurable via the `--max-round-blocks-to-import` CLI flag. With unstable network conditions, it is advised to increase the number. This shouldn't have any noticeable performance impact unless the number is set to really large.
- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564)): the default values for gas floor target are `8_000_000` and gas cap `10_000_000`, similar to Geth 1.8.15+.
- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725)): we now produce portable binaries, but it may incur some performance degradation. For ultimate performance it's now better to compile Parity Ethereum from source with `PORTABLE=OFF` environment variable.
- RPC: `parity_allTransactionHashes` ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745)): Get all pending transactions from the queue with the high performant `parity_allTransactionHashes` RPC method.
- Support `eth_chainId` RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783)): implements EIP-695 to get the chainID via RPC.
- AuRa: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692)): The AuRa engine was updated to emit ancestry actions to finalize blocks. The full client stores block finality in the database, the engine builds finality from an ancestry of `ExtendedHeader`; `is_epoch_end` was updated to take a vec of recently finalized headers; `is_epoch_end_light` was added which maintains the previous interface and is used by the light client since the client itself doesn't track finality.
The full list of included changes:
- Backport to parity 2.2.1 beta ([#9905](https://github.com/paritytech/parity-ethereum/pull/9905))
- Bump version to 2.2.1
- Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885))
- Fix Parity not closing on Ctrl-C ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886))
- Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873))
- Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854))
- Add hardcoded headers for light client ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907))
- Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743))
- Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876))
- Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906))
- Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824))
- Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631))
- Eip-191 implementation ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701))
- Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918))
- Fix performance issue importing Kovan blocks ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914))
- Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855))
- Backports to parity beta 2.2.0 ([#9820](https://github.com/paritytech/parity-ethereum/pull/9820))
- Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788))
- Implement NoProof for json tests and update tests reference ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814))
- Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841))
- Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828))
- Rpc: parity_allTransactionHashes ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745))
- Revert "prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763))" ([#9815](https://github.com/paritytech/parity-ethereum/pull/9815))
- Allow zero chain id in EIP155 signing process ([#9792](https://github.com/paritytech/parity-ethereum/pull/9792))
- Add readiness check for docker container ([#9804](https://github.com/paritytech/parity-ethereum/pull/9804))
- Insert dev account before unlocking ([#9813](https://github.com/paritytech/parity-ethereum/pull/9813))
- Removed "rustup" & added new runner tag ([#9731](https://github.com/paritytech/parity-ethereum/pull/9731))
- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439))
- Aura: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692))
- Sync: retry different peer after empty subchain heads response ([#9753](https://github.com/paritytech/parity-ethereum/pull/9753))
- Fix(light-rpc/parity) : Remove unused client ([#9802](https://github.com/paritytech/parity-ethereum/pull/9802))
- Drops support for olympic testnet, closes [#9800](https://github.com/paritytech/parity-ethereum/issues/9800) ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801))
- Replace `tokio_core` with `tokio` (`ring` -> 0.13) ([#9657](https://github.com/paritytech/parity-ethereum/pull/9657))
- Support eth_chainId RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783))
- Ethcore: bump ropsten forkblock checkpoint ([#9775](https://github.com/paritytech/parity-ethereum/pull/9775))
- Docs: changelogs for 2.0.8 and 2.1.3 ([#9758](https://github.com/paritytech/parity-ethereum/pull/9758))
- Prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763))
- Skip seal fields count check when --no-seal-check is used ([#9757](https://github.com/paritytech/parity-ethereum/pull/9757))
- Aura: fix panic on extra_info with unsealed block ([#9755](https://github.com/paritytech/parity-ethereum/pull/9755))
- Docs: update changelogs ([#9742](https://github.com/paritytech/parity-ethereum/pull/9742))
- Removed extra assert in generation_session_is_removed_when_succeeded ([#9738](https://github.com/paritytech/parity-ethereum/pull/9738))
- Make checkpoint_storage_at use plain loop instead of recursion ([#9734](https://github.com/paritytech/parity-ethereum/pull/9734))
- Use signed 256-bit integer for sstore gas refund substate ([#9746](https://github.com/paritytech/parity-ethereum/pull/9746))
- Heads ref not present for branches beta and stable ([#9741](https://github.com/paritytech/parity-ethereum/pull/9741))
- Add Callisto support ([#9534](https://github.com/paritytech/parity-ethereum/pull/9534))
- Add --force to cargo audit install script ([#9735](https://github.com/paritytech/parity-ethereum/pull/9735))
- Remove unused expired value from Handshake ([#9732](https://github.com/paritytech/parity-ethereum/pull/9732))
- Add hardcoded headers ([#9730](https://github.com/paritytech/parity-ethereum/pull/9730))
- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725))
- Gitlab ci: releasable_branches: change variables condition to schedule ([#9729](https://github.com/paritytech/parity-ethereum/pull/9729))
- Update a few parity-common dependencies ([#9663](https://github.com/paritytech/parity-ethereum/pull/9663))
- Hf in POA Core (2018-10-22) ([#9724](https://github.com/paritytech/parity-ethereum/pull/9724))
- Schedule nightly builds ([#9717](https://github.com/paritytech/parity-ethereum/pull/9717))
- Fix ancient blocks sync ([#9531](https://github.com/paritytech/parity-ethereum/pull/9531))
- Ci: Skip docs job for nightly ([#9693](https://github.com/paritytech/parity-ethereum/pull/9693))
- Fix (light/provider) : Make `read_only executions` read-only ([#9591](https://github.com/paritytech/parity-ethereum/pull/9591))
- Ethcore: fix detection of major import ([#9552](https://github.com/paritytech/parity-ethereum/pull/9552))
- Return 0 on error ([#9705](https://github.com/paritytech/parity-ethereum/pull/9705))
- Ethcore: delay ropsten hardfork ([#9704](https://github.com/paritytech/parity-ethereum/pull/9704))
- Make instantSeal engine backwards compatible, closes [#9696](https://github.com/paritytech/parity-ethereum/issues/9696) ([#9700](https://github.com/paritytech/parity-ethereum/pull/9700))
- Implement CREATE2 gas changes and fix some potential overflowing ([#9694](https://github.com/paritytech/parity-ethereum/pull/9694))
- Don't hash the init_code of CREATE. ([#9688](https://github.com/paritytech/parity-ethereum/pull/9688))
- Ethcore: minor optimization of modexp by using LR exponentiation ([#9697](https://github.com/paritytech/parity-ethereum/pull/9697))
- Removed redundant clone before each block import ([#9683](https://github.com/paritytech/parity-ethereum/pull/9683))
- Add Foundation Bootnodes ([#9666](https://github.com/paritytech/parity-ethereum/pull/9666))
- Docker: run as parity user ([#9689](https://github.com/paritytech/parity-ethereum/pull/9689))
- Ethcore: mcip3 block reward contract ([#9605](https://github.com/paritytech/parity-ethereum/pull/9605))
- Verify block syncing responses against requests ([#9670](https://github.com/paritytech/parity-ethereum/pull/9670))
- Add a new RPC `parity_submitWorkDetail` similar `eth_submitWork` but return block hash ([#9404](https://github.com/paritytech/parity-ethereum/pull/9404))
- Resumable EVM and heap-allocated callstack ([#9360](https://github.com/paritytech/parity-ethereum/pull/9360))
- Update parity-wordlist library ([#9682](https://github.com/paritytech/parity-ethereum/pull/9682))
- Ci: Remove unnecessary pipes ([#9681](https://github.com/paritytech/parity-ethereum/pull/9681))
- Test.sh: use cargo --target for platforms other than linux, win or mac ([#9650](https://github.com/paritytech/parity-ethereum/pull/9650))
- Ci: fix push script ([#9679](https://github.com/paritytech/parity-ethereum/pull/9679))
- Hardfork the testnets ([#9562](https://github.com/paritytech/parity-ethereum/pull/9562))
- Calculate sha3 instead of sha256 for push-release. ([#9673](https://github.com/paritytech/parity-ethereum/pull/9673))
- Ethcore-io retries failed work steal ([#9651](https://github.com/paritytech/parity-ethereum/pull/9651))
- Fix(light_fetch): avoid race with BlockNumber::Latest ([#9665](https://github.com/paritytech/parity-ethereum/pull/9665))
- Test fix for windows cache name... ([#9658](https://github.com/paritytech/parity-ethereum/pull/9658))
- Refactor(fetch) : light use only one `DNS` thread ([#9647](https://github.com/paritytech/parity-ethereum/pull/9647))
- Ethereum libfuzzer integration small change ([#9547](https://github.com/paritytech/parity-ethereum/pull/9547))
- Cli: remove reference to --no-ui in --unlock flag help ([#9616](https://github.com/paritytech/parity-ethereum/pull/9616))
- Remove master from releasable branches ([#9655](https://github.com/paritytech/parity-ethereum/pull/9655))
- Ethcore/VerificationQueue don't spawn up extra `worker-threads` when explictly specified not to ([#9620](https://github.com/paritytech/parity-ethereum/pull/9620))
- Rpc: parity_getBlockReceipts ([#9527](https://github.com/paritytech/parity-ethereum/pull/9527))
- Remove unused dependencies ([#9589](https://github.com/paritytech/parity-ethereum/pull/9589))
- Ignore key_server_cluster randomly failing tests ([#9639](https://github.com/paritytech/parity-ethereum/pull/9639))
- Ethcore: handle vm exception when estimating gas ([#9615](https://github.com/paritytech/parity-ethereum/pull/9615))
- Fix bad-block reporting no reason ([#9638](https://github.com/paritytech/parity-ethereum/pull/9638))
- Use static call and apparent value transfer for block reward contract code ([#9603](https://github.com/paritytech/parity-ethereum/pull/9603))
- Hf in POA Sokol (2018-09-19) ([#9607](https://github.com/paritytech/parity-ethereum/pull/9607))
- Bump smallvec to 0.6 in ethcore-light, ethstore and whisper ([#9588](https://github.com/paritytech/parity-ethereum/pull/9588))
- Add constantinople conf to EvmTestClient. ([#9570](https://github.com/paritytech/parity-ethereum/pull/9570))
- Fix(network): don't disconnect reserved peers ([#9608](https://github.com/paritytech/parity-ethereum/pull/9608))
- Fix failing node-table tests on mac os, closes [#9632](https://github.com/paritytech/parity-ethereum/issues/9632) ([#9633](https://github.com/paritytech/parity-ethereum/pull/9633))
- Update ropsten.json ([#9602](https://github.com/paritytech/parity-ethereum/pull/9602))
- Simplify ethcore errors by removing BlockImportError ([#9593](https://github.com/paritytech/parity-ethereum/pull/9593))
- Fix windows compilation, replaces [#9561](https://github.com/paritytech/parity-ethereum/issues/9561) ([#9621](https://github.com/paritytech/parity-ethereum/pull/9621))
- Master: rpc-docs set github token ([#9610](https://github.com/paritytech/parity-ethereum/pull/9610))
- Docs: add changelogs for 1.11.10, 1.11.11, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.1.0, and 2.1.1 ([#9554](https://github.com/paritytech/parity-ethereum/pull/9554))
- Docs(rpc): annotate tag with the provided message ([#9601](https://github.com/paritytech/parity-ethereum/pull/9601))
- Ci: fix regex roll_eyes ([#9597](https://github.com/paritytech/parity-ethereum/pull/9597))
- Remove snapcraft clean ([#9585](https://github.com/paritytech/parity-ethereum/pull/9585))
- Add snapcraft package image (master) ([#9584](https://github.com/paritytech/parity-ethereum/pull/9584))
- Docs(rpc): push the branch along with tags ([#9578](https://github.com/paritytech/parity-ethereum/pull/9578))
- Fix typo for jsonrpc-threads flag ([#9574](https://github.com/paritytech/parity-ethereum/pull/9574))
- Fix informant compile ([#9571](https://github.com/paritytech/parity-ethereum/pull/9571))
- Added ropsten bootnodes ([#9569](https://github.com/paritytech/parity-ethereum/pull/9569))
- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564))
- While working on the platform tests make them non-breaking ([#9563](https://github.com/paritytech/parity-ethereum/pull/9563))
- Improve P2P discovery ([#9526](https://github.com/paritytech/parity-ethereum/pull/9526))
- Move dockerfile for android build container to scripts repo ([#9560](https://github.com/paritytech/parity-ethereum/pull/9560))
- Simultaneous platform tests WIP ([#9557](https://github.com/paritytech/parity-ethereum/pull/9557))
- Update ethabi-derive, serde, serde_json, serde_derive, syn && quote ([#9553](https://github.com/paritytech/parity-ethereum/pull/9553))
- Ci: fix rpc docs generation 2 ([#9550](https://github.com/paritytech/parity-ethereum/pull/9550))
- Ci: always run build pipelines for win, mac, linux, and android ([#9537](https://github.com/paritytech/parity-ethereum/pull/9537))
- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239))
- New ethabi ([#9511](https://github.com/paritytech/parity-ethereum/pull/9511))
- Remove initial token for WS. ([#9545](https://github.com/paritytech/parity-ethereum/pull/9545))
- Net_version caches network_id to avoid redundant aquire of sync readlock ([#9544](https://github.com/paritytech/parity-ethereum/pull/9544))
- Correct before_script for nightly build versions ([#9543](https://github.com/paritytech/parity-ethereum/pull/9543))
- Deps: bump kvdb-rocksdb to 0.1.4 ([#9539](https://github.com/paritytech/parity-ethereum/pull/9539))
- State: test when contract creation fails, old storage values should re-appear ([#9532](https://github.com/paritytech/parity-ethereum/pull/9532))
- Allow dropping light client RPC query with no results ([#9318](https://github.com/paritytech/parity-ethereum/pull/9318))
- Bump master to 2.2.0 ([#9517](https://github.com/paritytech/parity-ethereum/pull/9517))
- Enable all Constantinople hard fork changes in constantinople_test.json ([#9505](https://github.com/paritytech/parity-ethereum/pull/9505))
- [Light] Validate `account balance` before importing transactions ([#9417](https://github.com/paritytech/parity-ethereum/pull/9417))
- In create memory calculation is the same for create2 because the additional parameter was popped before. ([#9522](https://github.com/paritytech/parity-ethereum/pull/9522))
- Update patricia trie to 0.2.2 ([#9525](https://github.com/paritytech/parity-ethereum/pull/9525))
- Replace hardcoded JSON with serde json! macro ([#9489](https://github.com/paritytech/parity-ethereum/pull/9489))
- Fix typo in version string ([#9516](https://github.com/paritytech/parity-ethereum/pull/9516))

View File

@@ -14,19 +14,9 @@ parking_lot = "0.7"
primal = "0.2.3"
[dev-dependencies]
criterion = "0.2"
rustc-hex = "1.0"
serde_json = "1.0"
tempdir = "0.3"
[features]
default = []
bench = []
criterion = "0.2"
[[bench]]
name = "basic"
harness = false
[[bench]]
name = "progpow"
harness = false

View File

@@ -40,28 +40,28 @@ criterion_main!(basic);
fn bench_light_compute_memmap(b: &mut Criterion) {
use std::env;
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
let light = builder.light(&env::temp_dir(), 486382);
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE, u64::max_value())));
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE)));
}
fn bench_light_compute_memory(b: &mut Criterion) {
use std::env;
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
let light = builder.light(&env::temp_dir(), 486382);
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE, u64::max_value())));
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE)));
}
fn bench_light_new_round_trip_memmap(b: &mut Criterion) {
use std::env;
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
let light = builder.light(&env::temp_dir(), 486382);
light.compute(&HASH, NONCE, u64::max_value());
light.compute(&HASH, NONCE);
}));
}
@@ -69,9 +69,9 @@ fn bench_light_new_round_trip_memory(b: &mut Criterion) {
use std::env;
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
let light = builder.light(&env::temp_dir(), 486382);
light.compute(&HASH, NONCE, u64::max_value());
light.compute(&HASH, NONCE);
}));
}
@@ -81,15 +81,15 @@ fn bench_light_from_file_round_trip_memory(b: &mut Criterion) {
let dir = env::temp_dir();
let height = 486382;
{
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
let mut dummy = builder.light(&dir, height);
dummy.to_file().unwrap();
}
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
let light = builder.light_from_file(&dir, 486382).unwrap();
light.compute(&HASH, NONCE, u64::max_value());
light.compute(&HASH, NONCE);
}));
}
@@ -100,14 +100,14 @@ fn bench_light_from_file_round_trip_memmap(b: &mut Criterion) {
let height = 486382;
{
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
let mut dummy = builder.light(&dir, height);
dummy.to_file().unwrap();
}
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
let light = builder.light_from_file(&dir, 486382).unwrap();
light.compute(&HASH, NONCE, u64::max_value());
light.compute(&HASH, NONCE);
}));
}

View File

@@ -1,86 +0,0 @@
#[macro_use]
extern crate criterion;
extern crate ethash;
extern crate rustc_hex;
extern crate tempdir;
use criterion::Criterion;
use ethash::progpow;
use tempdir::TempDir;
use rustc_hex::FromHex;
use ethash::{NodeCacheBuilder, OptimizeFor};
use ethash::compute::light_compute;
fn bench_hashimoto_light(c: &mut Criterion) {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let light = builder.light(&tempdir.path(), 1);
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
c.bench_function("hashimoto_light", move |b| {
b.iter(|| light_compute(&light, &hash, 0))
});
}
fn bench_progpow_light(c: &mut Criterion) {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
c.bench_function("progpow_light", move |b| {
b.iter(|| {
let c_dag = progpow::generate_cdag(cache.as_ref());
progpow::progpow(
hash,
0,
0,
cache.as_ref(),
&c_dag,
);
})
});
}
fn bench_progpow_optimal_light(c: &mut Criterion) {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let c_dag = progpow::generate_cdag(cache.as_ref());
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
c.bench_function("progpow_optimal_light", move |b| {
b.iter(|| {
progpow::progpow(
hash,
0,
0,
cache.as_ref(),
&c_dag,
);
})
});
}
fn bench_keccak_f800_long(c: &mut Criterion) {
c.bench_function("keccak_f800_long(0, 0, 0)", |b| {
b.iter(|| progpow::keccak_f800_long([0; 32], 0, [0; 8]))
});
}
criterion_group!(benches,
bench_hashimoto_light,
bench_progpow_light,
bench_progpow_optimal_light,
bench_keccak_f800_long,
);
criterion_main!(benches);

View File

@@ -1,86 +0,0 @@
[
[
0,
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000",
"faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3",
"63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b"
],
[
49,
"63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b",
"0000000006ff2c47",
"c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d",
"9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922"
],
[
50,
"9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922",
"00000000076e482e",
"c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518",
"de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d"
],
[
99,
"de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d",
"000000003917afab",
"f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7",
"ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce"
],
[
29950,
"ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce",
"005d409dbc23a62a",
"07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e",
"e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5"
],
[
29999,
"e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5",
"005db5fa4c2a3d03",
"7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8",
"d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454"
],
[
30000,
"d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454",
"005db8607994ff30",
"f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4",
"8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64"
],
[
30049,
"8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64",
"005e2e215a8ca2e7",
"57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add",
"c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047"
],
[
30050,
"c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047",
"005e30899481055e",
"ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d",
"ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71"
],
[
30099,
"ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71",
"005ea6aef136f88b",
"cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd",
"49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6"
],
[
59950,
"49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6",
"02ebe0503bd7b1da",
"21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773",
"f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf"
],
[
59999,
"f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf",
"02edb6275bd221e3",
"653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98",
"341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e88"
]
]

View File

@@ -69,7 +69,6 @@ pub struct NodeCacheBuilder {
// TODO: Remove this locking and just use an `Rc`?
seedhash: Arc<Mutex<SeedHashCompute>>,
optimize_for: OptimizeFor,
progpow_transition: u64,
}
// TODO: Abstract the "optimize for" logic
@@ -83,18 +82,17 @@ pub struct NodeCache {
impl NodeCacheBuilder {
pub fn light(&self, cache_dir: &Path, block_number: u64) -> Light {
Light::new_with_builder(self, cache_dir, block_number, self.progpow_transition)
Light::new_with_builder(self, cache_dir, block_number)
}
pub fn light_from_file(&self, cache_dir: &Path, block_number: u64) -> io::Result<Light> {
Light::from_file_with_builder(self, cache_dir, block_number, self.progpow_transition)
Light::from_file_with_builder(self, cache_dir, block_number)
}
pub fn new<T: Into<Option<OptimizeFor>>>(optimize_for: T, progpow_transition: u64) -> Self {
pub fn new<T: Into<Option<OptimizeFor>>>(optimize_for: T) -> Self {
NodeCacheBuilder {
seedhash: Arc::new(Mutex::new(SeedHashCompute::default())),
optimize_for: optimize_for.into().unwrap_or_default(),
progpow_transition
}
}

View File

@@ -21,7 +21,6 @@
use keccak::{keccak_512, keccak_256, H256};
use cache::{NodeCache, NodeCacheBuilder};
use progpow::{CDag, generate_cdag, progpow, keccak_f800_short, keccak_f800_long};
use seed_compute::SeedHashCompute;
use shared::*;
use std::io;
@@ -31,7 +30,7 @@ use std::path::Path;
const MIX_WORDS: usize = ETHASH_MIX_BYTES / 4;
const MIX_NODES: usize = MIX_WORDS / NODE_WORDS;
pub const FNV_PRIME: u32 = 0x01000193;
const FNV_PRIME: u32 = 0x01000193;
/// Computation result
pub struct ProofOfWork {
@@ -41,15 +40,9 @@ pub struct ProofOfWork {
pub mix_hash: H256,
}
enum Algorithm {
Hashimoto,
Progpow(Box<CDag>),
}
pub struct Light {
block_number: u64,
cache: NodeCache,
algorithm: Algorithm,
}
/// Light cache structure
@@ -58,55 +51,32 @@ impl Light {
builder: &NodeCacheBuilder,
cache_dir: &Path,
block_number: u64,
progpow_transition: u64,
) -> Self {
let cache = builder.new_cache(cache_dir.to_path_buf(), block_number);
let algorithm = if block_number >= progpow_transition {
Algorithm::Progpow(Box::new(generate_cdag(cache.as_ref())))
} else {
Algorithm::Hashimoto
};
Light { block_number, cache, algorithm }
Light {
block_number: block_number,
cache: cache,
}
}
/// Calculate the light boundary data
/// `header_hash` - The header hash to pack into the mix
/// `nonce` - The nonce to pack into the mix
pub fn compute(&self, header_hash: &H256, nonce: u64, block_number: u64) -> ProofOfWork {
match self.algorithm {
Algorithm::Progpow(ref c_dag) => {
let (value, mix_hash) = progpow(
*header_hash,
nonce,
block_number,
self.cache.as_ref(),
c_dag,
);
ProofOfWork { value, mix_hash }
},
Algorithm::Hashimoto => light_compute(self, header_hash, nonce),
}
pub fn compute(&self, header_hash: &H256, nonce: u64) -> ProofOfWork {
light_compute(self, header_hash, nonce)
}
pub fn from_file_with_builder(
builder: &NodeCacheBuilder,
cache_dir: &Path,
block_number: u64,
progpow_transition: u64,
) -> io::Result<Self> {
let cache = builder.from_file(cache_dir.to_path_buf(), block_number)?;
let algorithm = if block_number >= progpow_transition {
Algorithm::Progpow(Box::new(generate_cdag(cache.as_ref())))
} else {
Algorithm::Hashimoto
};
Ok(Light { block_number, cache, algorithm })
Ok(Light {
block_number: block_number,
cache: cache,
})
}
pub fn to_file(&mut self) -> io::Result<&Path> {
@@ -129,32 +99,27 @@ fn fnv_hash(x: u32, y: u32) -> u32 {
/// `nonce` The block's nonce
/// `mix_hash` The mix digest hash
/// Boundary recovered from mix hash
pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256, progpow: bool) -> H256 {
pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256) -> H256 {
unsafe {
if progpow {
let seed = keccak_f800_short(*header_hash, nonce, [0u32; 8]);
keccak_f800_long(*header_hash, seed, mem::transmute(*mix_hash))
} else {
// This is safe - the `keccak_512` call below reads the first 40 bytes (which we explicitly set
// with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write
// the next 32 bytes before we read the whole thing with `keccak_256`.
//
// This cannot be elided by the compiler as it doesn't know the implementation of
// `keccak_512`.
let mut buf: [u8; 64 + 32] = mem::uninitialized();
// This is safe - the `keccak_512` call below reads the first 40 bytes (which we explicitly set
// with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write
// the next 32 bytes before we read the whole thing with `keccak_256`.
//
// This cannot be elided by the compiler as it doesn't know the implementation of
// `keccak_512`.
let mut buf: [u8; 64 + 32] = mem::uninitialized();
ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32);
ptr::copy_nonoverlapping(&nonce as *const u64 as *const u8, buf[32..].as_mut_ptr(), 8);
ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32);
ptr::copy_nonoverlapping(&nonce as *const u64 as *const u8, buf[32..].as_mut_ptr(), 8);
keccak_512::unchecked(buf.as_mut_ptr(), 64, buf.as_ptr(), 40);
ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32);
keccak_512::unchecked(buf.as_mut_ptr(), 64, buf.as_ptr(), 40);
ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32);
// This is initialized in `keccak_256`
let mut hash: [u8; 32] = mem::uninitialized();
keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len());
// This is initialized in `keccak_256`
let mut hash: [u8; 32] = mem::uninitialized();
keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len());
hash
}
hash
}
}
@@ -307,7 +272,7 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
// We overwrite the second half since `keccak_256` has an internal buffer and so allows
// overlapping arrays as input.
let write_ptr: *mut u8 = &mut buf.compress_bytes as *mut [u8; 32] as *mut u8;
unsafe {
unsafe {
keccak_256::unchecked(
write_ptr,
buf.compress_bytes.len(),
@@ -322,7 +287,7 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
}
// TODO: Use the `simd` crate
pub fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
let num_parent_nodes = cache.len();
let mut ret = cache[node_index as usize % num_parent_nodes].clone();
ret.as_words_mut()[0] ^= node_index;
@@ -396,13 +361,13 @@ mod test {
0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a,
0xe9, 0x7e, 0x53, 0x84,
];
assert_eq!(quick_get_difficulty(&hash, nonce, &mix_hash, false)[..], boundary_good[..]);
assert_eq!(quick_get_difficulty(&hash, nonce, &mix_hash)[..], boundary_good[..]);
let boundary_bad = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2,
0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a,
0xe9, 0x7e, 0x53, 0x84,
];
assert!(quick_get_difficulty(&hash, nonce, &mix_hash, false)[..] != boundary_bad[..]);
assert!(quick_get_difficulty(&hash, nonce, &mix_hash)[..] != boundary_bad[..]);
}
#[test]
@@ -426,7 +391,7 @@ mod test {
let tempdir = TempDir::new("").unwrap();
// difficulty = 0x085657254bd9u64;
let light = NodeCacheBuilder::new(None, u64::max_value()).light(tempdir.path(), 486382);
let light = NodeCacheBuilder::new(None).light(tempdir.path(), 486382);
let result = light_compute(&light, &hash, nonce);
assert_eq!(result.mix_hash[..], mix_hash[..]);
assert_eq!(result.value[..], boundary[..]);
@@ -435,7 +400,7 @@ mod test {
#[test]
fn test_drop_old_data() {
let tempdir = TempDir::new("").unwrap();
let builder = NodeCacheBuilder::new(None, u64::max_value());
let builder = NodeCacheBuilder::new(None);
let first = builder.light(tempdir.path(), 0).to_file().unwrap().to_owned();
let second = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH).to_file().unwrap().to_owned();

View File

@@ -25,30 +25,15 @@ extern crate crunchy;
#[macro_use]
extern crate log;
#[cfg(test)]
extern crate rustc_hex;
#[cfg(test)]
extern crate serde_json;
#[cfg(test)]
extern crate tempdir;
#[cfg(feature = "bench")]
pub mod compute;
#[cfg(not(feature = "bench"))]
mod compute;
mod seed_compute;
mod cache;
mod keccak;
mod shared;
#[cfg(feature = "bench")]
pub mod progpow;
#[cfg(not(feature = "bench"))]
mod progpow;
pub use cache::{NodeCacheBuilder, OptimizeFor};
pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number};
use compute::Light;
@@ -74,16 +59,14 @@ pub struct EthashManager {
nodecache_builder: NodeCacheBuilder,
cache: Mutex<LightCache>,
cache_dir: PathBuf,
progpow_transition: u64,
}
impl EthashManager {
/// Create a new new instance of ethash manager
pub fn new<T: Into<Option<OptimizeFor>>>(cache_dir: &Path, optimize_for: T, progpow_transition: u64) -> EthashManager {
pub fn new<T: Into<Option<OptimizeFor>>>(cache_dir: &Path, optimize_for: T) -> EthashManager {
EthashManager {
cache_dir: cache_dir.to_path_buf(),
nodecache_builder: NodeCacheBuilder::new(optimize_for.into().unwrap_or_default(), progpow_transition),
progpow_transition: progpow_transition,
nodecache_builder: NodeCacheBuilder::new(optimize_for.into().unwrap_or_default()),
cache: Mutex::new(LightCache {
recent_epoch: None,
recent: None,
@@ -102,33 +85,27 @@ impl EthashManager {
let epoch = block_number / ETHASH_EPOCH_LENGTH;
let light = {
let mut lights = self.cache.lock();
let light = if block_number == self.progpow_transition {
// we need to regenerate the cache to trigger algorithm change to progpow inside `Light`
None
} else {
match lights.recent_epoch.clone() {
Some(ref e) if *e == epoch => lights.recent.clone(),
_ => match lights.prev_epoch.clone() {
Some(e) if e == epoch => {
// don't swap if recent is newer.
if lights.recent_epoch > lights.prev_epoch {
None
} else {
// swap
let t = lights.prev_epoch;
lights.prev_epoch = lights.recent_epoch;
lights.recent_epoch = t;
let t = lights.prev.clone();
lights.prev = lights.recent.clone();
lights.recent = t;
lights.recent.clone()
}
let light = match lights.recent_epoch.clone() {
Some(ref e) if *e == epoch => lights.recent.clone(),
_ => match lights.prev_epoch.clone() {
Some(e) if e == epoch => {
// don't swap if recent is newer.
if lights.recent_epoch > lights.prev_epoch {
None
} else {
// swap
let t = lights.prev_epoch;
lights.prev_epoch = lights.recent_epoch;
lights.recent_epoch = t;
let t = lights.prev.clone();
lights.prev = lights.recent.clone();
lights.recent = t;
lights.recent.clone()
}
_ => None,
},
}
}
_ => None,
},
};
match light {
None => {
let light = match self.nodecache_builder.light_from_file(
@@ -155,7 +132,7 @@ impl EthashManager {
Some(light) => light,
}
};
light.compute(header_hash, nonce, block_number)
light.compute(header_hash, nonce)
}
}
@@ -187,7 +164,7 @@ fn test_lru() {
use tempdir::TempDir;
let tempdir = TempDir::new("").unwrap();
let ethash = EthashManager::new(tempdir.path(), None, u64::max_value());
let ethash = EthashManager::new(tempdir.path(), None);
let hash = [0u8; 32];
ethash.compute_light(1, &hash, 1);
ethash.compute_light(50000, &hash, 1);

View File

@@ -1,595 +0,0 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use compute::{FNV_PRIME, calculate_dag_item};
use keccak::H256;
use shared::{ETHASH_ACCESSES, ETHASH_MIX_BYTES, Node, get_data_size};
const PROGPOW_CACHE_BYTES: usize = 16 * 1024;
const PROGPOW_CACHE_WORDS: usize = PROGPOW_CACHE_BYTES / 4;
const PROGPOW_CNT_CACHE: usize = 12;
const PROGPOW_CNT_MATH: usize = 20;
const PROGPOW_CNT_DAG: usize = ETHASH_ACCESSES;
const PROGPOW_DAG_LOADS: usize = 4;
const PROGPOW_MIX_BYTES: usize = 2 * ETHASH_MIX_BYTES;
const PROGPOW_PERIOD_LENGTH: usize = 50; // blocks per progpow epoch (N)
const PROGPOW_LANES: usize = 16;
const PROGPOW_REGS: usize = 32;
const FNV_HASH: u32 = 0x811c9dc5;
const KECCAKF_RNDC: [u32; 24] = [
0x00000001, 0x00008082, 0x0000808a, 0x80008000, 0x0000808b, 0x80000001,
0x80008081, 0x00008009, 0x0000008a, 0x00000088, 0x80008009, 0x8000000a,
0x8000808b, 0x0000008b, 0x00008089, 0x00008003, 0x00008002, 0x00000080,
0x0000800a, 0x8000000a, 0x80008081, 0x00008080, 0x80000001, 0x80008008
];
const KECCAKF_ROTC: [u32; 24] = [
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
];
const KECCAKF_PILN: [usize; 24] = [
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
];
fn keccak_f800_round(st: &mut [u32; 25], r: usize) {
// Theta
let mut bc = [0u32; 5];
for i in 0..bc.len() {
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
}
for i in 0..bc.len() {
let t = bc[(i + 4) % 5] ^ bc[(i + 1) % 5].rotate_left(1);
for j in (0..st.len()).step_by(5) {
st[j + i] ^= t;
}
}
// Rho Pi
let mut t = st[1];
debug_assert_eq!(KECCAKF_ROTC.len(), 24);
for i in 0..24 {
let j = KECCAKF_PILN[i];
bc[0] = st[j];
st[j] = t.rotate_left(KECCAKF_ROTC[i]);
t = bc[0];
}
// Chi
for j in (0..st.len()).step_by(5) {
for i in 0..bc.len() {
bc[i] = st[j + i];
}
for i in 0..bc.len() {
st[j + i] ^= (!bc[(i + 1) % 5]) & bc[(i + 2) % 5];
}
}
// Iota
debug_assert!(r < KECCAKF_RNDC.len());
st[0] ^= KECCAKF_RNDC[r];
}
fn keccak_f800(header_hash: H256, nonce: u64, result: [u32; 8], st: &mut [u32; 25]) {
for i in 0..8 {
st[i] = (header_hash[4 * i] as u32) +
((header_hash[4 * i + 1] as u32) << 8) +
((header_hash[4 * i + 2] as u32) << 16) +
((header_hash[4 * i + 3] as u32) << 24);
}
st[8] = nonce as u32;
st[9] = (nonce >> 32) as u32;
for i in 0..8 {
st[10 + i] = result[i];
}
for r in 0..22 {
keccak_f800_round(st, r);
}
}
pub fn keccak_f800_short(header_hash: H256, nonce: u64, result: [u32; 8]) -> u64 {
let mut st = [0u32; 25];
keccak_f800(header_hash, nonce, result, &mut st);
(st[0].swap_bytes() as u64) << 32 | st[1].swap_bytes() as u64
}
pub fn keccak_f800_long(header_hash: H256, nonce: u64, result: [u32; 8]) -> H256 {
let mut st = [0u32; 25];
keccak_f800(header_hash, nonce, result, &mut st);
// NOTE: transmute from `[u32; 8]` to `[u8; 32]`
unsafe {
std::mem::transmute(
[st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7]]
)
}
}
#[inline]
fn fnv1a_hash(h: u32, d: u32) -> u32 {
(h ^ d).wrapping_mul(FNV_PRIME)
}
#[derive(Clone)]
struct Kiss99 {
z: u32,
w: u32,
jsr: u32,
jcong: u32,
}
impl Kiss99 {
fn new(z: u32, w: u32, jsr: u32, jcong: u32) -> Kiss99 {
Kiss99 { z, w, jsr, jcong }
}
#[inline]
fn next_u32(&mut self) -> u32 {
self.z = 36969u32.wrapping_mul(self.z & 65535).wrapping_add(self.z >> 16);
self.w = 18000u32.wrapping_mul(self.w & 65535).wrapping_add(self.w >> 16);
let mwc = (self.z << 16).wrapping_add(self.w);
self.jsr ^= self.jsr << 17;
self.jsr ^= self.jsr >> 13;
self.jsr ^= self.jsr << 5;
self.jcong = 69069u32.wrapping_mul(self.jcong).wrapping_add(1234567);
(mwc ^ self.jcong).wrapping_add(self.jsr)
}
}
fn fill_mix(seed: u64, lane_id: u32) -> [u32; PROGPOW_REGS] {
// Use FNV to expand the per-warp seed to per-lane
// Use KISS to expand the per-lane seed to fill mix
let z = fnv1a_hash(FNV_HASH, seed as u32);
let w = fnv1a_hash(z, (seed >> 32) as u32);
let jsr = fnv1a_hash(w, lane_id);
let jcong = fnv1a_hash(jsr, lane_id);
let mut rnd = Kiss99::new(z, w, jsr, jcong);
let mut mix = [0; PROGPOW_REGS];
debug_assert_eq!(PROGPOW_REGS, 32);
for i in 0..32 {
mix[i] = rnd.next_u32();
}
mix
}
// Merge new data from b into the value in a. Assuming A has high entropy only
// do ops that retain entropy even if B is low entropy (IE don't do A&B)
fn merge(a: u32, b: u32, r: u32) -> u32 {
match r % 4 {
0 => a.wrapping_mul(33).wrapping_add(b),
1 => (a ^ b).wrapping_mul(33),
2 => a.rotate_left(((r >> 16) % 31) + 1) ^ b,
_ => a.rotate_right(((r >> 16) % 31) + 1) ^ b,
}
}
fn math(a: u32, b: u32, r: u32) -> u32 {
match r % 11 {
0 => a.wrapping_add(b),
1 => a.wrapping_mul(b),
2 => ((a as u64).wrapping_mul(b as u64) >> 32) as u32,
3 => a.min(b),
4 => a.rotate_left(b),
5 => a.rotate_right(b),
6 => a & b,
7 => a | b,
8 => a ^ b,
9 => a.leading_zeros() + b.leading_zeros(),
_ => a.count_ones() + b.count_ones(),
}
}
fn progpow_init(seed: u64) -> (Kiss99, [u32; PROGPOW_REGS], [u32; PROGPOW_REGS]) {
let z = fnv1a_hash(FNV_HASH, seed as u32);
let w = fnv1a_hash(z, (seed >> 32) as u32);
let jsr = fnv1a_hash(w, seed as u32);
let jcong = fnv1a_hash(jsr, (seed >> 32) as u32);
let mut rnd = Kiss99::new(z, w, jsr, jcong);
// Create a random sequence of mix destinations for merge() and mix sources
// for cache reads guarantees every destination merged once and guarantees
// no duplicate cache reads, which could be optimized away. Uses
// Fisher-Yates shuffle.
let mut mix_seq_dst = [0u32; PROGPOW_REGS];
let mut mix_seq_cache = [0u32; PROGPOW_REGS];
for i in 0..mix_seq_dst.len() {
mix_seq_dst[i] = i as u32;
mix_seq_cache[i] = i as u32;
}
for i in (1..mix_seq_dst.len()).rev() {
let j = rnd.next_u32() as usize % (i + 1);
mix_seq_dst.swap(i, j);
let j = rnd.next_u32() as usize % (i + 1);
mix_seq_cache.swap(i, j);
}
(rnd, mix_seq_dst, mix_seq_cache)
}
pub type CDag = [u32; PROGPOW_CACHE_WORDS];
fn progpow_loop(
seed: u64,
loop_: usize,
mix: &mut [[u32; PROGPOW_REGS]; PROGPOW_LANES],
cache: &[Node],
c_dag: &CDag,
data_size: usize,
) {
// All lanes share a base address for the global load. Global offset uses
// mix[0] to guarantee it depends on the load result.
let g_offset = mix[loop_ % PROGPOW_LANES][0] as usize %
(64 * data_size / (PROGPOW_LANES * PROGPOW_DAG_LOADS));
// 256 bytes of dag data
let mut dag_item = [0u32; 64];
// Fetch DAG nodes (64 bytes each)
for l in 0..PROGPOW_DAG_LOADS {
let index = g_offset * PROGPOW_LANES * PROGPOW_DAG_LOADS + l * 16;
let node = calculate_dag_item(index as u32 / 16, cache);
dag_item[l * 16..(l + 1) * 16].clone_from_slice(node.as_words());
}
let (rnd, mix_seq_dst, mix_seq_cache) = progpow_init(seed);
// Lanes can execute in parallel and will be convergent
for l in 0..mix.len() {
let mut rnd = rnd.clone();
// Initialize the seed and mix destination sequence
let mut mix_seq_dst_cnt = 0;
let mut mix_seq_cache_cnt = 0;
let mut mix_dst = || {
let res = mix_seq_dst[mix_seq_dst_cnt % PROGPOW_REGS] as usize;
mix_seq_dst_cnt += 1;
res
};
let mut mix_cache = || {
let res = mix_seq_cache[mix_seq_cache_cnt % PROGPOW_REGS] as usize;
mix_seq_cache_cnt += 1;
res
};
for i in 0..PROGPOW_CNT_CACHE.max(PROGPOW_CNT_MATH) {
if i < PROGPOW_CNT_CACHE {
// Cached memory access, lanes access random 32-bit locations
// within the first portion of the DAG
let offset = mix[l][mix_cache()] as usize % PROGPOW_CACHE_WORDS;
let data = c_dag[offset];
let dst = mix_dst();
mix[l][dst] = merge(mix[l][dst], data, rnd.next_u32());
}
if i < PROGPOW_CNT_MATH {
// Random math
// Generate 2 unique sources
let src_rnd = rnd.next_u32() % (PROGPOW_REGS * (PROGPOW_REGS - 1)) as u32;
let src1 = src_rnd % PROGPOW_REGS as u32; // 0 <= src1 < PROGPOW_REGS
let mut src2 = src_rnd / PROGPOW_REGS as u32; // 0 <= src2 < PROGPOW_REGS - 1
if src2 >= src1 {
src2 += 1; // src2 is now any reg other than src1
}
let data = math(mix[l][src1 as usize], mix[l][src2 as usize], rnd.next_u32());
let dst = mix_dst();
mix[l][dst] = merge(mix[l][dst], data, rnd.next_u32());
}
}
// Global load to sequential locations
let mut data_g = [0u32; PROGPOW_DAG_LOADS];
let index = ((l ^ loop_) % PROGPOW_LANES) * PROGPOW_DAG_LOADS;
for i in 0..PROGPOW_DAG_LOADS {
data_g[i] = dag_item[index + i];
}
// Consume the global load data at the very end of the loop to allow
// full latency hiding. Always merge into `mix[0]` to feed the offset
// calculation.
mix[l][0] = merge(mix[l][0], data_g[0], rnd.next_u32());
for i in 1..PROGPOW_DAG_LOADS {
let dst = mix_dst();
mix[l][dst] = merge(mix[l][dst], data_g[i], rnd.next_u32());
}
}
}
pub fn progpow(
header_hash: H256,
nonce: u64,
block_number: u64,
cache: &[Node],
c_dag: &CDag,
) -> (H256, H256) {
let mut mix = [[0u32; PROGPOW_REGS]; PROGPOW_LANES];
let mut lane_results = [0u32; PROGPOW_LANES];
let mut result = [0u32; 8];
let data_size = get_data_size(block_number) / PROGPOW_MIX_BYTES;
// NOTE: This assert is required to aid the optimizer elide the non-zero
// remainder check in `progpow_loop`.
assert!(data_size > 0);
// Initialize mix for all lanes
let seed = keccak_f800_short(header_hash, nonce, result);
for l in 0..mix.len() {
mix[l] = fill_mix(seed, l as u32);
}
// Execute the randomly generated inner loop
let period = block_number / PROGPOW_PERIOD_LENGTH as u64;
for i in 0..PROGPOW_CNT_DAG {
progpow_loop(
period,
i,
&mut mix,
cache,
c_dag,
data_size,
);
}
// Reduce mix data to a single per-lane result
for l in 0..lane_results.len() {
lane_results[l] = FNV_HASH;
for i in 0..PROGPOW_REGS {
lane_results[l] = fnv1a_hash(lane_results[l], mix[l][i]);
}
}
// Reduce all lanes to a single 128-bit result
result = [FNV_HASH; 8];
for l in 0..PROGPOW_LANES {
result[l % 8] = fnv1a_hash(result[l % 8], lane_results[l]);
}
let digest = keccak_f800_long(header_hash, seed, result);
// NOTE: transmute from `[u32; 8]` to `[u8; 32]`
let result = unsafe { ::std::mem::transmute(result) };
(digest, result)
}
pub fn generate_cdag(cache: &[Node]) -> CDag {
let mut c_dag = [0u32; PROGPOW_CACHE_WORDS];
for i in 0..PROGPOW_CACHE_WORDS / 16 {
let node = calculate_dag_item(i as u32, cache);
for j in 0..16 {
c_dag[i * 16 + j] = node.as_words()[j];
}
}
c_dag
}
#[cfg(test)]
mod test {
use tempdir::TempDir;
use cache::{NodeCacheBuilder, OptimizeFor};
use keccak::H256;
use rustc_hex::FromHex;
use serde_json::{self, Value};
use std::collections::VecDeque;
use super::*;
fn h256(hex: &str) -> H256 {
let bytes = FromHex::from_hex(hex).unwrap();
let mut res = [0; 32];
res.copy_from_slice(&bytes);
res
}
#[test]
fn test_cdag() {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let c_dag = generate_cdag(cache.as_ref());
let expected = vec![
690150178u32, 1181503948, 2248155602, 2118233073, 2193871115,
1791778428, 1067701239, 724807309, 530799275, 3480325829, 3899029234,
1998124059, 2541974622, 1100859971, 1297211151, 3268320000, 2217813733,
2690422980, 3172863319, 2651064309
];
assert_eq!(
c_dag.iter().take(20).cloned().collect::<Vec<_>>(),
expected,
);
}
#[test]
fn test_random_merge() {
let tests = [
(1000000u32, 101u32, 33000101u32),
(2000000, 102, 66003366),
(3000000, 103, 6000103),
(4000000, 104, 2000104),
(1000000, 0, 33000000),
(2000000, 0, 66000000),
(3000000, 0, 6000000),
(4000000, 0, 2000000),
];
for (i, &(a, b, expected)) in tests.iter().enumerate() {
assert_eq!(
merge(a, b, i as u32),
expected,
);
}
}
#[test]
fn test_random_math() {
let tests = [
(20u32, 22u32, 42u32),
(70000, 80000, 1305032704),
(70000, 80000, 1),
(1, 2, 1),
(3, 10000, 196608),
(3, 0, 3),
(3, 6, 2),
(3, 6, 7),
(3, 6, 5),
(0, 0xffffffff, 32),
(3 << 13, 1 << 5, 3),
(22, 20, 42),
(80000, 70000, 1305032704),
(80000, 70000, 1),
(2, 1, 1),
(10000, 3, 80000),
(0, 3, 0),
(6, 3, 2),
(6, 3, 7),
(6, 3, 5),
(0, 0xffffffff, 32),
(3 << 13, 1 << 5, 3),
];
for (i, &(a, b, expected)) in tests.iter().enumerate() {
assert_eq!(
math(a, b, i as u32),
expected,
);
}
}
#[test]
fn test_keccak_256() {
let expected = "5dd431e5fbc604f499bfa0232f45f8f142d0ff5178f539e5a7800bf0643697af";
assert_eq!(
keccak_f800_long([0; 32], 0, [0; 8]),
h256(expected),
);
}
#[test]
fn test_keccak_64() {
let expected: u64 = 0x5dd431e5fbc604f4;
assert_eq!(
keccak_f800_short([0; 32], 0, [0; 8]),
expected,
);
}
#[test]
fn test_progpow_hash() {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let c_dag = generate_cdag(cache.as_ref());
let header_hash = [0; 32];
let (digest, result) = progpow(
header_hash,
0,
0,
cache.as_ref(),
&c_dag,
);
let expected_digest = FromHex::from_hex("63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b").unwrap();
let expected_result = FromHex::from_hex("faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3").unwrap();
assert_eq!(
digest.to_vec(),
expected_digest,
);
assert_eq!(
result.to_vec(),
expected_result,
);
}
#[test]
fn test_progpow_testvectors() {
struct ProgpowTest {
block_number: u64,
header_hash: H256,
nonce: u64,
mix_hash: H256,
final_hash: H256,
}
let tests: Vec<VecDeque<Value>> =
serde_json::from_slice(include_bytes!("../res/progpow_testvectors.json")).unwrap();
let tests: Vec<ProgpowTest> = tests.into_iter().map(|mut test: VecDeque<Value>| {
assert!(test.len() == 5);
let block_number: u64 = serde_json::from_value(test.pop_front().unwrap()).unwrap();
let header_hash: String = serde_json::from_value(test.pop_front().unwrap()).unwrap();
let nonce: String = serde_json::from_value(test.pop_front().unwrap()).unwrap();
let mix_hash: String = serde_json::from_value(test.pop_front().unwrap()).unwrap();
let final_hash: String = serde_json::from_value(test.pop_front().unwrap()).unwrap();
ProgpowTest {
block_number,
header_hash: h256(&header_hash),
nonce: u64::from_str_radix(&nonce, 16).unwrap(),
mix_hash: h256(&mix_hash),
final_hash: h256(&final_hash),
}
}).collect();
for test in tests {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.path().to_owned(), test.block_number);
let c_dag = generate_cdag(cache.as_ref());
let (digest, result) = progpow(
test.header_hash,
test.nonce,
test.block_number,
cache.as_ref(),
&c_dag,
);
assert_eq!(digest, test.final_hash);
assert_eq!(result, test.mix_hash);
}
}
}

View File

@@ -21,7 +21,6 @@ ethabi-derive = "6.0"
ethash = { path = "../ethash" }
ethcore-blockchain = { path = "./blockchain" }
ethcore-bloom-journal = { path = "../util/bloom" }
ethcore-call-contract = { path = "./call-contract" }
ethcore-db = { path = "./db" }
ethcore-io = { path = "../util/io" }
ethcore-miner = { path = "../miner" }
@@ -29,8 +28,9 @@ ethcore-stratum = { path = "../miner/stratum", optional = true }
ethereum-types = "0.4"
ethjson = { path = "../json" }
ethkey = { path = "../accounts/ethkey" }
ethstore = { path = "../accounts/ethstore" }
evm = { path = "evm" }
hash-db = "0.11.0"
hashdb = "0.3.0"
heapsize = "0.4"
itertools = "0.5"
journaldb = { path = "../util/journaldb" }
@@ -45,15 +45,15 @@ log = "0.4"
lru-cache = "0.1"
macros = { path = "../util/macros" }
memory-cache = { path = "../util/memory-cache" }
memory-db = "0.11.0"
memorydb = "0.3.0"
num = { version = "0.1", default-features = false, features = ["bigint"] }
num_cpus = "1.2"
parity-bytes = "0.1"
parity-crypto = "0.3.0"
parity-crypto = "0.2"
parity-machine = { path = "../machine" }
parity-snappy = "0.1"
parking_lot = "0.7"
trie-db = "0.11.0"
patricia-trie = "0.3.0"
patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" }
rand = "0.4"
rayon = "1.0"
@@ -64,7 +64,6 @@ serde = "1.0"
serde_derive = "1.0"
stats = { path = "../util/stats" }
tempdir = {version="0.3", optional = true}
time-utils = { path = "../util/time-utils" }
trace-time = "0.1"
triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" }
unexpected = { path = "../util/unexpected" }
@@ -72,14 +71,17 @@ using_queue = { path = "../miner/using-queue" }
vm = { path = "vm" }
wasm = { path = "wasm" }
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))'.dependencies]
hardware-wallet = { path = "../accounts/hw" }
[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))'.dependencies]
fake-hardware-wallet = { path = "../accounts/fake-hardware-wallet" }
[dev-dependencies]
blooms-db = { path = "../util/blooms-db" }
criterion = "0.2"
env_logger = "0.5"
ethcore-accounts = { path = "../accounts" }
fetch = { path = "../util/fetch" }
kvdb-rocksdb = "0.1.3"
parity-runtime = { path = "../util/runtime" }
rlp_compress = { path = "../util/rlp-compress" }
tempdir = "0.3"
trie-standardmap = "0.1"
@@ -108,7 +110,7 @@ slow-blocks = []
# Run JSON consensus tests.
json-tests = ["env_logger", "test-helpers", "to-pod-full"]
# Skip JSON consensus tests with pending issues.
ci-skip-tests = []
ci-skip-issue = []
# Run memory/cpu heavy tests.
test-heavy = []
# Compile test helpers

View File

@@ -668,21 +668,6 @@ impl BlockChain {
self.db.key_value().read_with_cache(db::COL_EXTRA, &self.block_details, parent).map_or(false, |d| d.children.contains(hash))
}
/// fetches the list of blocks from best block to n, and n's parent hash
/// where n > 0
pub fn block_headers_from_best_block(&self, n: u32) -> Option<(Vec<encoded::Header>, H256)> {
let mut blocks = Vec::with_capacity(n as usize);
let mut hash = self.best_block_hash();
for _ in 0..n {
let current_hash = self.block_header_data(&hash)?;
hash = current_hash.parent_hash();
blocks.push(current_hash);
}
Some((blocks, hash))
}
/// Returns a tree route between `from` and `to`, which is a tuple of:
///
/// - a vector of hashes of all blocks, ordered from `from` to `to`.

View File

@@ -33,5 +33,5 @@ pub use self::cache::CacheSize;
pub use self::config::Config;
pub use self::import_route::ImportRoute;
pub use self::update::ExtrasInsert;
pub use ethcore_db::keys::{BlockReceipts, BlockDetails, TransactionAddress, BlockNumberKey};
pub use ethcore_db::keys::{BlockReceipts, BlockDetails, TransactionAddress};
pub use common_types::tree_route::TreeRoute;

View File

@@ -1,11 +0,0 @@
[package]
name = "ethcore-call-contract"
version = "0.1.0"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
types = { path = "../types", package = "common-types" }
ethereum-types = "0.4"
bytes = { version = "0.1", package = "parity-bytes" }

View File

@@ -1,33 +0,0 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// 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 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Provides CallContract and RegistryInfo traits
use bytes::Bytes;
use ethereum_types::Address;
use types::ids::BlockId;
/// Provides `call_contract` method
pub trait CallContract {
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
}
/// Provides information on a blockchain service and it's registry
pub trait RegistryInfo {
/// Get the address of a particular blockchain service, if available.
fn registry_address(&self, name: String, block: BlockId) -> Option<Address>;
}

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.overflow_add(value.map_or_else(|| Cost::from(0), |val| match val.is_zero() {
let call_gas = call_gas + 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

@@ -14,12 +14,12 @@ ethcore = { path = ".."}
ethcore-db = { path = "../db" }
ethcore-blockchain = { path = "../blockchain" }
ethereum-types = "0.4"
memory-db = "0.11.0"
trie-db = "0.11.0"
memorydb = "0.3.0"
patricia-trie = "0.3.0"
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
ethcore-network = { path = "../../util/network" }
ethcore-io = { path = "../../util/io" }
hash-db = "0.11.0"
hashdb = "0.3.0"
heapsize = "0.4"
vm = { path = "../vm" }
fastmap = { path = "../../util/fastmap" }
@@ -41,7 +41,6 @@ triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" }
kvdb = "0.1"
memory-cache = { path = "../../util/memory-cache" }
error-chain = { version = "0.12", default-features = false }
journaldb = { path = "../../util/journaldb" }
[dev-dependencies]
ethcore = { path = "..", features = ["test-helpers"] }

View File

@@ -25,11 +25,10 @@
use common_types::ids::BlockId;
use ethereum_types::{H256, U256};
use hash_db::HashDB;
use hashdb::HashDB;
use keccak_hasher::KeccakHasher;
use kvdb::DBValue;
use memory_db::MemoryDB;
use journaldb::new_memory_db;
use memorydb::MemoryDB;
use bytes::Bytes;
use trie::{TrieMut, Trie, Recorder};
use ethtrie::{self, TrieDB, TrieDBMut};
@@ -74,8 +73,7 @@ impl<DB: HashDB<KeccakHasher, DBValue>> CHT<DB> {
if block_to_cht_number(num) != Some(self.number) { return Ok(None) }
let mut recorder = Recorder::with_depth(from_level);
let db: &HashDB<_,_> = &self.db;
let t = TrieDB::new(&db, &self.root)?;
let t = TrieDB::new(&self.db, &self.root)?;
t.get_with(&key!(num), &mut recorder)?;
Ok(Some(recorder.drain().into_iter().map(|x| x.data).collect()))
@@ -98,7 +96,7 @@ pub struct BlockInfo {
pub fn build<F>(cht_num: u64, mut fetcher: F) -> Option<CHT<MemoryDB<KeccakHasher, DBValue>>>
where F: FnMut(BlockId) -> Option<BlockInfo>
{
let mut db = new_memory_db();
let mut db = MemoryDB::<KeccakHasher, DBValue>::new();
// start from the last block by number and work backwards.
let last_num = start_number(cht_num + 1) - 1;
@@ -152,7 +150,7 @@ pub fn compute_root<I>(cht_num: u64, iterable: I) -> Option<H256>
/// verify the given trie branch and extract the canonical hash and total difficulty.
// TODO: better support for partially-checked queries.
pub fn check_proof(proof: &[Bytes], num: u64, root: H256) -> Option<(H256, U256)> {
let mut db = new_memory_db();
let mut db = MemoryDB::<KeccakHasher, DBValue>::new();
for node in proof { db.insert(&node[..]); }
let res = match TrieDB::new(&db, &root) {

View File

@@ -116,9 +116,6 @@ pub trait LightChainClient: Send + Sync {
/// Query whether a block is known.
fn is_known(&self, hash: &H256) -> bool;
/// Set the chain via a spec name.
fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()>;
/// Clear the queue.
fn clear_queue(&self);
@@ -167,8 +164,6 @@ pub struct Client<T> {
listeners: RwLock<Vec<Weak<LightChainNotify>>>,
fetcher: T,
verify_full: bool,
/// A closure to call when we want to restart the client
exit_handler: Mutex<Option<Box<Fn(String) + 'static + Send>>>,
}
impl<T: ChainDataFetcher> Client<T> {
@@ -195,7 +190,6 @@ impl<T: ChainDataFetcher> Client<T> {
listeners: RwLock::new(vec![]),
fetcher,
verify_full: config.verify_full,
exit_handler: Mutex::new(None),
})
}
@@ -366,14 +360,6 @@ impl<T: ChainDataFetcher> Client<T> {
self.chain.heap_size_of_children()
}
/// Set a closure to call when the client wants to be restarted.
///
/// The parameter passed to the callback is the name of the new chain spec to use after
/// the restart.
pub fn set_exit_handler<F>(&self, f: F) where F: Fn(String) + 'static + Send {
*self.exit_handler.lock() = Some(Box::new(f));
}
/// Get a handle to the verification engine.
pub fn engine(&self) -> &Arc<EthEngine> {
&self.engine
@@ -577,17 +563,6 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
Client::engine(self)
}
fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> {
trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name);
if let Some(ref h) = *self.exit_handler.lock() {
(*h)(new_spec_name);
Ok(())
} else {
warn!("Not hypervised; cannot change chain.");
Err(())
}
}
fn is_known(&self, hash: &H256) -> bool {
self.status(hash) == BlockStatus::InChain
}

View File

@@ -62,14 +62,14 @@ extern crate ethcore_network as network;
extern crate parity_bytes as bytes;
extern crate ethereum_types;
extern crate ethcore;
extern crate hash_db;
extern crate hashdb;
extern crate heapsize;
extern crate failsafe;
extern crate futures;
extern crate itertools;
extern crate keccak_hasher;
extern crate memory_db;
extern crate trie_db as trie;
extern crate memorydb;
extern crate patricia_trie as trie;
extern crate patricia_trie_ethereum as ethtrie;
extern crate fastmap;
extern crate rand;
@@ -92,4 +92,3 @@ extern crate error_chain;
extern crate kvdb_memorydb;
#[cfg(test)]
extern crate tempdir;
extern crate journaldb;

View File

@@ -533,9 +533,6 @@ impl LightProtocol {
// the timer approach will skip 1 (possibly 2) in rare occasions.
if peer_info.sent_head == announcement.head_hash ||
peer_info.status.head_num >= announcement.head_num ||
// fix for underflow reported in
// https://github.com/paritytech/parity-ethereum/issues/10419
now < peer_info.last_update ||
now - peer_info.last_update < UPDATE_INTERVAL {
continue
}

View File

@@ -30,8 +30,9 @@ use ethcore::state::{self, ProvedExecution};
use ethereum_types::{H256, U256, Address};
use ethtrie::{TrieError, TrieDB};
use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY, KECCAK_EMPTY_LIST_RLP, keccak};
use hash_db::HashDB;
use hashdb::HashDB;
use kvdb::DBValue;
use memorydb::MemoryDB;
use parking_lot::Mutex;
use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field};
use rlp::{RlpStream, Rlp};
@@ -980,7 +981,7 @@ impl Account {
let header = self.header.as_ref()?;
let state_root = header.state_root();
let mut db = journaldb::new_memory_db();
let mut db = MemoryDB::new();
for node in proof { db.insert(&node[..]); }
match TrieDB::new(&db, &state_root).and_then(|t| t.get(&keccak(&self.address)))? {
@@ -1100,6 +1101,7 @@ mod tests {
use super::*;
use std::time::Duration;
use ethereum_types::{H256, Address};
use memorydb::MemoryDB;
use parking_lot::Mutex;
use trie::{Trie, TrieMut};
use ethtrie::{SecTrieDB, SecTrieDBMut};
@@ -1279,7 +1281,7 @@ mod tests {
use rlp::RlpStream;
let mut root = H256::default();
let mut db = journaldb::new_memory_db();
let mut db = MemoryDB::new();
let mut header = Header::new();
header.set_number(123_456);
header.set_extra_data(b"test_header".to_vec());

View File

@@ -95,7 +95,7 @@ impl AccountTransactions {
}
fn next_nonce(&self) -> U256 {
self.current.last().map(|last| last.nonce.saturating_add(1.into()))
self.current.last().map(|last| last.nonce + 1)
.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.saturating_add(1.into());
next_nonce = next_nonce + 1;
}
promoted

View File

@@ -255,78 +255,4 @@ mod tests {
hash: Field::BackReference(0, 0),
})).unwrap();
}
#[test]
fn batch_tx_index_backreference() {
let mut builder = Builder::default();
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
num: 100.into(), // header proof puts hash at output 0.
})).unwrap();
builder.push(Request::TransactionIndex(IncompleteTransactionIndexRequest {
hash: Field::BackReference(0, 0),
})).unwrap();
let mut batch = builder.build();
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Hash(42.into())));
assert!(batch.next_complete().is_some());
batch.answered += 1;
assert!(batch.next_complete().is_some());
}
#[test]
#[should_panic]
fn batch_tx_index_backreference_wrong_output() {
let mut builder = Builder::default();
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
num: 100.into(), // header proof puts hash at output 0.
})).unwrap();
builder.push(Request::TransactionIndex(IncompleteTransactionIndexRequest {
hash: Field::BackReference(0, 0),
})).unwrap();
let mut batch = builder.build();
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Number(42)));
batch.next_complete();
batch.answered += 1;
batch.next_complete();
}
#[test]
fn batch_receipts_backreference() {
let mut builder = Builder::default();
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
num: 100.into(), // header proof puts hash at output 0.
})).unwrap();
builder.push(Request::Receipts(IncompleteReceiptsRequest {
hash: Field::BackReference(0, 0),
})).unwrap();
let mut batch = builder.build();
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Hash(42.into())));
assert!(batch.next_complete().is_some());
batch.answered += 1;
assert!(batch.next_complete().is_some());
}
#[test]
#[should_panic]
fn batch_receipts_backreference_wrong_output() {
let mut builder = Builder::default();
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
num: 100.into(), // header proof puts hash at output 0.
})).unwrap();
builder.push(Request::Receipts(IncompleteReceiptsRequest {
hash: Field::BackReference(0, 0),
})).unwrap();
let mut batch = builder.build();
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Number(42)));
batch.next_complete();
batch.answered += 1;
batch.next_complete();
}
}

View File

@@ -907,7 +907,7 @@ pub mod transaction_index {
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
if let Field::BackReference(req, idx) = self.hash {
self.hash = match oracle(req, idx) {
Ok(Output::Hash(hash)) => Field::Scalar(hash.into()),
Ok(Output::Number(hash)) => Field::Scalar(hash.into()),
_ => Field::BackReference(req, idx),
}
}
@@ -982,7 +982,7 @@ pub mod block_receipts {
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
if let Field::BackReference(req, idx) = self.hash {
self.hash = match oracle(req, idx) {
Ok(Output::Hash(hash)) => Field::Scalar(hash.into()),
Ok(Output::Number(hash)) => Field::Scalar(hash.into()),
_ => Field::BackReference(req, idx),
}
}

View File

@@ -12,7 +12,6 @@ ethabi = "6.0"
ethabi-contract = "6.0"
ethabi-derive = "6.0"
ethcore = { path = ".." }
ethcore-call-contract = { path = "../call-contract" }
ethcore-io = { path = "../../util/io" }
ethcore-miner = { path = "../../miner" }
ethereum-types = "0.4"
@@ -24,9 +23,9 @@ heapsize = "0.4"
keccak-hash = "0.1.2"
log = "0.4"
parity-bytes = "0.1"
parity-crypto = "0.3.0"
parity-crypto = "0.2"
parking_lot = "0.7"
trie-db = "0.11.0"
patricia-trie = "0.3.0"
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
rand = "0.3"
rlp = { version = "0.3.0", features = ["ethereum"] }

View File

@@ -1,43 +0,0 @@
[
{
"constant": true,
"inputs": [
{
"name":"user",
"type":"address"
}
],
"name": "availableKeys",
"outputs": [
{
"name": "",
"type": "bytes32[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant":true,
"inputs": [
{
"name":"user",
"type":"address"
},
{
"name":"document",
"type":"bytes32"
}
],
"name":"checkPermissions",
"outputs": [
{
"name":"",
"type":"bool"
}
],
"payable":false,
"type":"function"
}
]

View File

@@ -18,23 +18,22 @@
use std::io::Read;
use std::str::FromStr;
use std::sync::Arc;
use std::iter::repeat;
use std::time::{Instant, Duration};
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use parking_lot::Mutex;
use ethcore::account_provider::AccountProvider;
use ethereum_types::{H128, H256, Address};
use ethjson;
use ethkey::{Signature, Public};
use ethkey::{Signature, Password, Public};
use crypto;
use futures::Future;
use fetch::{Fetch, Client as FetchClient, Method, BodyReader, Request};
use bytes::{Bytes, ToPretty};
use error::{Error, ErrorKind};
use url::Url;
use super::Signer;
use super::key_server_keys::address_to_key;
use super::find_account_password;
/// Initialization vector length.
const INIT_VEC_LEN: usize = 16;
@@ -48,6 +47,7 @@ pub trait Encryptor: Send + Sync + 'static {
fn encrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
initialisation_vector: &H128,
plain_data: &[u8],
) -> Result<Bytes, Error>;
@@ -56,6 +56,7 @@ pub trait Encryptor: Send + Sync + 'static {
fn decrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
cypher: &[u8],
) -> Result<Bytes, Error>;
}
@@ -69,6 +70,8 @@ pub struct EncryptorConfig {
pub threshold: u32,
/// Account used for signing requests to key server
pub key_server_account: Option<Address>,
/// Passwords used to unlock accounts
pub passwords: Vec<Password>,
}
struct EncryptionSession {
@@ -81,20 +84,14 @@ pub struct SecretStoreEncryptor {
config: EncryptorConfig,
client: FetchClient,
sessions: Mutex<HashMap<Address, EncryptionSession>>,
signer: Arc<Signer>,
}
impl SecretStoreEncryptor {
/// Create new encryptor
pub fn new(
config: EncryptorConfig,
client: FetchClient,
signer: Arc<Signer>,
) -> Result<Self, Error> {
pub fn new(config: EncryptorConfig, client: FetchClient) -> Result<Self, Error> {
Ok(SecretStoreEncryptor {
config,
client,
signer,
sessions: Mutex::default(),
})
}
@@ -105,12 +102,13 @@ impl SecretStoreEncryptor {
url_suffix: &str,
use_post: bool,
contract_address: &Address,
accounts: &AccountProvider,
) -> Result<Bytes, Error> {
// check if the key was already cached
if let Some(key) = self.obtained_key(contract_address) {
return Ok(key);
}
let contract_address_signature = self.sign_contract_address(contract_address)?;
let contract_address_signature = self.sign_contract_address(contract_address, accounts)?;
let requester = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?;
// key id in SS is H256 && we have H160 here => expand with assitional zeros
@@ -150,9 +148,10 @@ impl SecretStoreEncryptor {
// response is JSON string (which is, in turn, hex-encoded, encrypted Public)
let encrypted_bytes: ethjson::bytes::Bytes = result.trim_matches('\"').parse().map_err(|e| ErrorKind::Encrypt(e))?;
let password = find_account_password(&self.config.passwords, &*accounts, &requester);
// decrypt Public
let decrypted_bytes = self.signer.decrypt(requester, &crypto::DEFAULT_MAC, &encrypted_bytes)?;
let decrypted_bytes = accounts.decrypt(requester, password, &crypto::DEFAULT_MAC, &encrypted_bytes)?;
let decrypted_key = Public::from_slice(&decrypted_bytes);
// and now take x coordinate of Public as a key
@@ -188,9 +187,12 @@ impl SecretStoreEncryptor {
}
}
fn sign_contract_address(&self, contract_address: &Address) -> Result<Signature, Error> {
fn sign_contract_address(&self, contract_address: &Address, accounts: &AccountProvider) -> Result<Signature, Error> {
// key id in SS is H256 && we have H160 here => expand with assitional zeros
let contract_address_extended: H256 = contract_address.into();
let key_server_account = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?;
Ok(self.signer.sign(key_server_account, address_to_key(contract_address))?)
let password = find_account_password(&self.config.passwords, accounts, &key_server_account);
Ok(accounts.sign(key_server_account, password, H256::from_slice(&contract_address_extended))?)
}
}
@@ -198,15 +200,16 @@ impl Encryptor for SecretStoreEncryptor {
fn encrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
initialisation_vector: &H128,
plain_data: &[u8],
) -> Result<Bytes, Error> {
// retrieve the key, try to generate it if it doesn't exist yet
let key = match self.retrieve_key("", false, contract_address) {
let key = match self.retrieve_key("", false, contract_address, &*accounts) {
Ok(key) => Ok(key),
Err(Error(ErrorKind::EncryptionKeyNotFound(_), _)) => {
trace!(target: "privatetx", "Key for account wasnt found in sstore. Creating. Address: {:?}", contract_address);
self.retrieve_key(&format!("/{}", self.config.threshold), true, contract_address)
self.retrieve_key(&format!("/{}", self.config.threshold), true, contract_address, &*accounts)
}
Err(err) => Err(err),
}?;
@@ -225,6 +228,7 @@ impl Encryptor for SecretStoreEncryptor {
fn decrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
cypher: &[u8],
) -> Result<Bytes, Error> {
// initialization vector takes INIT_VEC_LEN bytes
@@ -234,7 +238,7 @@ impl Encryptor for SecretStoreEncryptor {
}
// retrieve existing key
let key = self.retrieve_key("", false, contract_address)?;
let key = self.retrieve_key("", false, contract_address, accounts)?;
// use symmetric decryption to decrypt document
let (cypher, iv) = cypher.split_at(cypher_len - INIT_VEC_LEN);
@@ -254,6 +258,7 @@ impl Encryptor for NoopEncryptor {
fn encrypt(
&self,
_contract_address: &Address,
_accounts: &AccountProvider,
_initialisation_vector: &H128,
data: &[u8],
) -> Result<Bytes, Error> {
@@ -263,6 +268,7 @@ impl Encryptor for NoopEncryptor {
fn decrypt(
&self,
_contract_address: &Address,
_accounts: &AccountProvider,
data: &[u8],
) -> Result<Bytes, Error> {
Ok(data.to_vec())

View File

@@ -17,10 +17,10 @@
use ethereum_types::Address;
use rlp::DecoderError;
use ethtrie::TrieError;
use ethcore::account_provider::SignError;
use ethcore::error::{Error as EthcoreError, ExecutionError};
use types::transaction::Error as TransactionError;
use ethkey::Error as KeyError;
use ethkey::crypto::Error as CryptoError;
use txpool::Error as TxPoolError;
error_chain! {
@@ -29,7 +29,6 @@ error_chain! {
Decoder(DecoderError) #[doc = "RLP decoding error."];
Trie(TrieError) #[doc = "Error concerning TrieDBs."];
Txpool(TxPoolError) #[doc = "Tx pool error."];
Crypto(CryptoError) #[doc = "Crypto error."];
}
errors {
@@ -76,7 +75,7 @@ error_chain! {
}
#[doc = "Wrong private transaction type."]
BadTransactionType {
BadTransactonType {
description("Wrong private transaction type."),
display("Wrong private transaction type"),
}
@@ -153,6 +152,12 @@ error_chain! {
display("General signing error {}", err),
}
#[doc = "Account provider signing error."]
Sign(err: SignError) {
description("Account provider signing error."),
display("Account provider signing error {}", err),
}
#[doc = "Error of transactions processing."]
Transaction(err: TransactionError) {
description("Error of transactions processing."),
@@ -167,6 +172,12 @@ error_chain! {
}
}
impl From<SignError> for Error {
fn from(err: SignError) -> Self {
ErrorKind::Sign(err).into()
}
}
impl From<KeyError> for Error {
fn from(err: KeyError) -> Self {
ErrorKind::Key(err).into()

View File

@@ -1,173 +0,0 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Wrapper around key server responsible for access keys processing.
use std::sync::Arc;
use parking_lot::RwLock;
use ethereum_types::{H256, Address};
use call_contract::{CallContract, RegistryInfo};
use ethcore::client::BlockId;
use ethabi::FunctionOutputDecoder;
const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker";
use_contract!(keys_acl_contract, "res/keys_acl.json");
/// Returns the address (of the contract), that corresponds to the key
pub fn key_to_address(key: &H256) -> Address {
Address::from_slice(&key.to_vec()[..10])
}
/// Returns the key from the key server associated with the contract
pub fn address_to_key(contract_address: &Address) -> H256 {
// Current solution uses contract address extended with 0 as id
let contract_address_extended: H256 = contract_address.into();
H256::from_slice(&contract_address_extended)
}
/// Trait for keys server keys provider.
pub trait KeyProvider: Send + Sync + 'static {
/// Account, that is used for communication with key server
fn key_server_account(&self) -> Option<Address>;
/// List of keys available for the account
fn available_keys(&self, block: BlockId, account: &Address) -> Option<Vec<Address>>;
/// Update permissioning contract
fn update_acl_contract(&self);
}
/// Secret Store keys provider
pub struct SecretStoreKeys<C> where C: CallContract + RegistryInfo + Send + Sync + 'static {
client: Arc<C>,
key_server_account: Option<Address>,
keys_acl_contract: RwLock<Option<Address>>,
}
impl<C> SecretStoreKeys<C> where C: CallContract + RegistryInfo + Send + Sync + 'static {
/// Create provider
pub fn new(client: Arc<C>, key_server_account: Option<Address>) -> Self {
SecretStoreKeys {
client,
key_server_account,
keys_acl_contract: RwLock::new(None),
}
}
}
impl<C> KeyProvider for SecretStoreKeys<C> where C: CallContract + RegistryInfo + Send + Sync + 'static {
fn key_server_account(&self) -> Option<Address> {
self.key_server_account
}
fn available_keys(&self, block: BlockId, account: &Address) -> Option<Vec<Address>> {
match *self.keys_acl_contract.read() {
Some(acl_contract_address) => {
let (data, decoder) = keys_acl_contract::functions::available_keys::call(*account);
if let Ok(value) = self.client.call_contract(block, acl_contract_address, data) {
decoder.decode(&value).ok().map(|key_values| {
key_values.iter().map(key_to_address).collect()
})
} else {
None
}
}
None => None,
}
}
fn update_acl_contract(&self) {
let contract_address = self.client.registry_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.into(), BlockId::Latest);
if *self.keys_acl_contract.read() != contract_address {
trace!(target: "privatetx", "Configuring for ACL checker contract from address {:?}",
contract_address);
*self.keys_acl_contract.write() = contract_address;
}
}
}
/// Dummy keys provider.
pub struct StoringKeyProvider {
available_keys: RwLock<Option<Vec<Address>>>,
key_server_account: Option<Address>,
}
impl StoringKeyProvider {
/// Store available keys
pub fn set_available_keys(&self, keys: &Vec<Address>) {
*self.available_keys.write() = Some(keys.clone())
}
}
impl Default for StoringKeyProvider {
fn default() -> Self {
StoringKeyProvider {
available_keys: RwLock::new(None),
key_server_account: Some(Address::default()),
}
}
}
impl KeyProvider for StoringKeyProvider {
fn key_server_account(&self) -> Option<Address> {
self.key_server_account
}
fn available_keys(&self, _block: BlockId, _account: &Address) -> Option<Vec<Address>> {
self.available_keys.read().clone()
}
fn update_acl_contract(&self) {}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use ethkey::{Secret, KeyPair};
use bytes::Bytes;
use super::*;
struct DummyRegistryClient {
registry_address: Option<Address>,
}
impl DummyRegistryClient {
pub fn new(registry_address: Option<Address>) -> Self {
DummyRegistryClient {
registry_address
}
}
}
impl RegistryInfo for DummyRegistryClient {
fn registry_address(&self, _name: String, _block: BlockId) -> Option<Address> { self.registry_address }
}
impl CallContract for DummyRegistryClient {
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
}
#[test]
fn should_update_acl_contract() {
let key = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000011")).unwrap();
let client = DummyRegistryClient::new(Some(key.address()));
let keys_data = SecretStoreKeys::new(Arc::new(client), None);
keys_data.update_acl_contract();
assert_eq!(keys_data.keys_acl_contract.read().unwrap(), key.address());
}
}

View File

@@ -21,7 +21,6 @@
#![recursion_limit="256"]
mod encryptor;
mod key_server_keys;
mod private_transactions;
mod messages;
mod error;
@@ -29,7 +28,6 @@ mod error;
extern crate common_types as types;
extern crate ethabi;
extern crate ethcore;
extern crate ethcore_call_contract as call_contract;
extern crate ethcore_io as io;
extern crate ethcore_miner;
extern crate ethereum_types;
@@ -42,7 +40,7 @@ extern crate keccak_hash as hash;
extern crate parity_bytes as bytes;
extern crate parity_crypto as crypto;
extern crate parking_lot;
extern crate trie_db as trie;
extern crate patricia_trie as trie;
extern crate patricia_trie_ethereum as ethtrie;
extern crate rlp;
extern crate rustc_hex;
@@ -65,7 +63,6 @@ extern crate rand;
extern crate env_logger;
pub use encryptor::{Encryptor, SecretStoreEncryptor, EncryptorConfig, NoopEncryptor};
pub use key_server_keys::{KeyProvider, SecretStoreKeys, StoringKeyProvider};
pub use private_transactions::{VerifiedPrivateTransaction, VerificationStore, PrivateTransactionSigningDesc, SigningStore};
pub use messages::{PrivateTransaction, SignedPrivateTransaction};
pub use error::{Error, ErrorKind};
@@ -85,13 +82,13 @@ use types::transaction::{SignedTransaction, Transaction, Action, UnverifiedTrans
use ethcore::{contract_address as ethcore_contract_address};
use ethcore::client::{
Client, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage, BlockId,
Call, BlockInfo
CallContract, Call, BlockInfo
};
use ethcore::account_provider::AccountProvider;
use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
use ethcore::{state, state_db};
use ethcore::trace::{Tracer, VMTracer};
use call_contract::CallContract;
use rustc_hex::FromHex;
use ethkey::Password;
use ethabi::FunctionOutputDecoder;
// Source avaiable at https://github.com/parity-contracts/private-tx/blob/master/contracts/PrivateContract.sol
@@ -118,6 +115,8 @@ pub struct ProviderConfig {
pub validator_accounts: Vec<Address>,
/// Account used for signing public transactions created from private transactions
pub signer_account: Option<Address>,
/// Passwords used to unlock accounts
pub passwords: Vec<Password>,
}
#[derive(Debug)]
@@ -125,85 +124,50 @@ pub struct ProviderConfig {
pub struct Receipt {
/// Private transaction hash.
pub hash: H256,
/// Contract address.
pub contract_address: Address,
/// Created contract address if any.
pub contract_address: Option<Address>,
/// Execution status.
pub status_code: u8,
}
/// Payload signing and decrypting capabilities.
pub trait Signer: Send + Sync {
/// Decrypt payload using private key of given address.
fn decrypt(&self, account: Address, shared_mac: &[u8], payload: &[u8]) -> Result<Vec<u8>, Error>;
/// Sign given hash using provided account.
fn sign(&self, account: Address, hash: ethkey::Message) -> Result<Signature, Error>;
}
/// Signer implementation that errors on any request.
pub struct DummySigner;
impl Signer for DummySigner {
fn decrypt(&self, _account: Address, _shared_mac: &[u8], _payload: &[u8]) -> Result<Vec<u8>, Error> {
Err("Decrypting is not supported.".to_owned())?
}
fn sign(&self, _account: Address, _hash: ethkey::Message) -> Result<Signature, Error> {
Err("Signing is not supported.".to_owned())?
}
}
/// Signer implementation using multiple keypairs
pub struct KeyPairSigner(pub Vec<ethkey::KeyPair>);
impl Signer for KeyPairSigner {
fn decrypt(&self, account: Address, shared_mac: &[u8], payload: &[u8]) -> Result<Vec<u8>, Error> {
let kp = self.0.iter().find(|k| k.address() == account).ok_or(ethkey::Error::InvalidAddress)?;
Ok(ethkey::crypto::ecies::decrypt(kp.secret(), shared_mac, payload)?)
}
fn sign(&self, account: Address, hash: ethkey::Message) -> Result<Signature, Error> {
let kp = self.0.iter().find(|k| k.address() == account).ok_or(ethkey::Error::InvalidAddress)?;
Ok(ethkey::sign(kp.secret(), &hash)?)
}
}
/// Manager of private transactions
pub struct Provider {
encryptor: Box<Encryptor>,
validator_accounts: HashSet<Address>,
signer_account: Option<Address>,
passwords: Vec<Password>,
notify: RwLock<Vec<Weak<ChainNotify>>>,
transactions_for_signing: RwLock<SigningStore>,
transactions_for_verification: VerificationStore,
client: Arc<Client>,
miner: Arc<Miner>,
accounts: Arc<Signer>,
accounts: Arc<AccountProvider>,
channel: IoChannel<ClientIoMessage>,
keys_provider: Arc<KeyProvider>,
}
#[derive(Debug)]
pub struct PrivateExecutionResult<T, V> where T: Tracer, V: VMTracer {
code: Option<Bytes>,
state: Bytes,
contract_address: Address,
contract_address: Option<Address>,
result: Executed<T::Output, V::Output>,
}
impl Provider {
impl Provider where {
/// Create a new provider.
pub fn new(
client: Arc<Client>,
miner: Arc<Miner>,
accounts: Arc<Signer>,
accounts: Arc<AccountProvider>,
encryptor: Box<Encryptor>,
config: ProviderConfig,
channel: IoChannel<ClientIoMessage>,
keys_provider: Arc<KeyProvider>,
) -> Self {
keys_provider.update_acl_contract();
Provider {
encryptor,
validator_accounts: config.validator_accounts.into_iter().collect(),
signer_account: config.signer_account,
passwords: config.passwords,
notify: RwLock::default(),
transactions_for_signing: RwLock::default(),
transactions_for_verification: VerificationStore::default(),
@@ -211,7 +175,6 @@ impl Provider {
miner,
accounts,
channel,
keys_provider,
}
}
@@ -241,7 +204,7 @@ impl Provider {
bail!(ErrorKind::SignerAccountNotSet);
}
let tx_hash = signed_transaction.hash();
let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| ErrorKind::BadTransactionType)?;
let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| ErrorKind::BadTransactonType)?;
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);
@@ -262,7 +225,7 @@ impl Provider {
self.broadcast_private_transaction(private.hash(), private.rlp_bytes());
Ok(Receipt {
hash: tx_hash,
contract_address: contract,
contract_address: Some(contract),
status_code: 0,
})
}
@@ -276,20 +239,21 @@ impl Provider {
keccak(&state_buf.as_ref())
}
fn pool_client<'a>(&'a self, nonce_cache: &'a NonceCache, local_accounts: &'a HashSet<Address>) -> miner::pool_client::PoolClient<'a, Client> {
fn pool_client<'a>(&'a self, nonce_cache: &'a NonceCache) -> miner::pool_client::PoolClient<'a, Client> {
let engine = self.client.engine();
let refuse_service_transactions = true;
miner::pool_client::PoolClient::new(
&*self.client,
nonce_cache,
engine,
local_accounts,
Some(&*self.accounts),
refuse_service_transactions,
)
}
/// Retrieve and verify the first available private transaction for every sender
fn process_verification_queue(&self) -> Result<(), Error> {
let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE);
let process_transaction = |transaction: &VerifiedPrivateTransaction| -> Result<_, String> {
let private_hash = transaction.private_transaction.hash();
match transaction.validator_account {
@@ -319,7 +283,8 @@ impl Provider {
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 signed_state = self.accounts.sign(validator_account, 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);
}
@@ -331,9 +296,7 @@ impl Provider {
}
Ok(())
};
let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE);
let local_accounts = HashSet::new();
let ready_transactions = self.transactions_for_verification.drain(self.pool_client(&nonce_cache, &local_accounts));
let ready_transactions = self.transactions_for_verification.drain(self.pool_client(&nonce_cache));
for transaction in ready_transactions {
if let Err(e) = process_transaction(&transaction) {
warn!(target: "privatetx", "Error: {:?}", e);
@@ -374,7 +337,8 @@ impl Provider {
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)?;
let signature = self.accounts.sign(signer_account, hash)?;
let password = find_account_password(&self.passwords, &*self.accounts, &signer_account);
let signature = self.accounts.sign(signer_account, password, hash)?;
let signed = SignedTransaction::new(public_tx.with_signature(signature, chain_id))?;
match self.miner.import_own_transaction(&*self.client, signed.into()) {
Ok(_) => trace!(target: "privatetx", "Public transaction added to queue"),
@@ -415,7 +379,7 @@ impl Provider {
Action::Call(contract) => Ok(contract),
_ => {
warn!(target: "privatetx", "Incorrect type of action for the transaction");
bail!(ErrorKind::BadTransactionType);
bail!(ErrorKind::BadTransactonType);
}
}
}
@@ -469,12 +433,12 @@ impl Provider {
fn encrypt(&self, contract_address: &Address, initialisation_vector: &H128, data: &[u8]) -> Result<Bytes, Error> {
trace!(target: "privatetx", "Encrypt data using key(address): {:?}", contract_address);
Ok(self.encryptor.encrypt(contract_address, initialisation_vector, data)?)
Ok(self.encryptor.encrypt(contract_address, &*self.accounts, initialisation_vector, data)?)
}
fn decrypt(&self, contract_address: &Address, data: &[u8]) -> Result<Bytes, Error> {
trace!(target: "privatetx", "Decrypt data using key(address): {:?}", contract_address);
Ok(self.encryptor.decrypt(contract_address, data)?)
Ok(self.encryptor.decrypt(contract_address, &*self.accounts, data)?)
}
fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
@@ -518,14 +482,6 @@ impl Provider {
raw
}
fn patch_account_state(&self, contract_address: &Address, block: BlockId, state: &mut state::State<state_db::StateDB>) -> Result<(), Error> {
let contract_code = Arc::new(self.get_decrypted_code(contract_address, block)?);
let contract_state = self.get_decrypted_state(contract_address, block)?;
trace!(target: "privatetx", "Patching contract at {:?}, code: {:?}, state: {:?}", contract_address, contract_code, contract_state);
state.patch_account(contract_address, contract_code, Self::snapshot_to_storage(contract_state))?;
Ok(())
}
pub fn execute_private<T, V>(&self, transaction: &SignedTransaction, options: TransactOptions<T, V>, block: BlockId) -> Result<PrivateExecutionResult<T, V>, Error>
where
T: Tracer,
@@ -538,48 +494,41 @@ impl Provider {
// TODO #9825 in case of BlockId::Latest these need to operate on the same state
let contract_address = match transaction.action {
Action::Call(ref contract_address) => {
// Patch current contract state
self.patch_account_state(contract_address, block, &mut state)?;
let contract_code = Arc::new(self.get_decrypted_code(contract_address, block)?);
let contract_state = self.get_decrypted_state(contract_address, block)?;
trace!(target: "privatetx", "Patching contract at {:?}, code: {:?}, state: {:?}", contract_address, contract_code, contract_state);
state.patch_account(contract_address, contract_code, Self::snapshot_to_storage(contract_state))?;
Some(*contract_address)
},
Action::Create => None,
};
let engine = self.client.engine();
let sender = transaction.sender();
let nonce = state.nonce(&sender)?;
let contract_address = contract_address.unwrap_or_else(|| {
let contract_address = contract_address.or({
let sender = transaction.sender();
let nonce = state.nonce(&sender)?;
let (new_address, _) = ethcore_contract_address(engine.create_address_scheme(env_info.number), &sender, &nonce, &transaction.data);
new_address
Some(new_address)
});
// Patch other available private contracts' states as well
// TODO: #10133 patch only required for the contract states
if let Some(key_server_account) = self.keys_provider.key_server_account() {
if let Some(available_contracts) = self.keys_provider.available_keys(block, &key_server_account) {
for private_contract in available_contracts {
if private_contract == contract_address {
continue;
}
self.patch_account_state(&private_contract, block, &mut state)?;
}
}
}
let machine = engine.machine();
let schedule = machine.schedule(env_info.number);
let result = Executive::new(&mut state, &env_info, &machine, &schedule).transact_virtual(transaction, options)?;
let (encrypted_code, encrypted_storage) = {
let (code, storage) = state.into_account(&contract_address)?;
trace!(target: "privatetx", "Private contract executed. code: {:?}, state: {:?}, result: {:?}", code, storage, result.output);
let enc_code = match code {
Some(c) => Some(self.encrypt(&contract_address, &Self::iv_from_address(&contract_address), &c)?),
None => None,
};
(enc_code, self.encrypt(&contract_address, &Self::iv_from_transaction(transaction), &Self::snapshot_from_storage(&storage))?)
let (encrypted_code, encrypted_storage) = match contract_address {
None => bail!(ErrorKind::ContractDoesNotExist),
Some(address) => {
let (code, storage) = state.into_account(&address)?;
trace!(target: "privatetx", "Private contract executed. code: {:?}, state: {:?}, result: {:?}", code, storage, result.output);
let enc_code = match code {
Some(c) => Some(self.encrypt(&address, &Self::iv_from_address(&address), &c)?),
None => None,
};
(enc_code, self.encrypt(&address, &Self::iv_from_transaction(transaction), &Self::snapshot_from_storage(&storage))?)
},
};
Ok(PrivateExecutionResult {
code: encrypted_code,
state: encrypted_storage,
contract_address: contract_address,
contract_address,
result,
})
}
@@ -604,13 +553,16 @@ impl Provider {
/// Returns the key from the key server associated with the contract
pub fn contract_key_id(&self, contract_address: &Address) -> Result<H256, Error> {
Ok(key_server_keys::address_to_key(contract_address))
// Current solution uses contract address extended with 0 as id
let contract_address_extended: H256 = contract_address.into();
Ok(H256::from_slice(&contract_address_extended))
}
/// Create encrypted public contract deployment transaction.
pub fn public_creation_transaction(&self, block: BlockId, source: &SignedTransaction, validators: &[Address], gas_price: U256) -> Result<(Transaction, Address), Error> {
pub fn public_creation_transaction(&self, block: BlockId, source: &SignedTransaction, validators: &[Address], gas_price: U256) -> Result<(Transaction, Option<Address>), Error> {
if let Action::Call(_) = source.action {
bail!(ErrorKind::BadTransactionType);
bail!(ErrorKind::BadTransactonType);
}
let sender = source.sender();
let state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
@@ -649,7 +601,7 @@ impl Provider {
/// Create encrypted public contract deployment transaction. Returns updated encrypted state.
pub fn execute_private_transaction(&self, block: BlockId, source: &SignedTransaction) -> Result<Bytes, Error> {
if let Action::Create = source.action {
bail!(ErrorKind::BadTransactionType);
bail!(ErrorKind::BadTransactonType);
}
let result = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
Ok(result.state)
@@ -729,13 +681,12 @@ impl Importer for Arc<Provider> {
let transaction_bytes = self.decrypt(&contract, &encrypted_data)?;
let original_tx: UnverifiedTransaction = Rlp::new(&transaction_bytes).as_val()?;
let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE);
let local_accounts = HashSet::new();
// Add to the queue for further verification
self.transactions_for_verification.add_transaction(
original_tx,
validation_account.map(|&account| account),
private_tx,
self.pool_client(&nonce_cache, &local_accounts),
self.pool_client(&nonce_cache),
)?;
let provider = Arc::downgrade(self);
let result = self.channel.send(ClientIoMessage::execute(move |_| {
@@ -770,6 +721,16 @@ impl Importer for Arc<Provider> {
}
}
/// Try to unlock account using stored password, return found password if any
fn find_account_password(passwords: &Vec<Password>, account_provider: &AccountProvider, account: &Address) -> Option<Password> {
for password in passwords {
if let Ok(true) = account_provider.test_password(account, password) {
return Some(password.clone());
}
}
None
}
impl ChainNotify for Provider {
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.imported.is_empty() || new_blocks.has_more_blocks_to_import { return }
@@ -777,6 +738,5 @@ impl ChainNotify for Provider {
if let Err(err) = self.process_verification_queue() {
warn!(target: "privatetx", "Cannot prune private transactions queue. error: {:?}", err);
}
self.keys_provider.update_acl_contract();
}
}

View File

@@ -29,11 +29,12 @@ extern crate rustc_hex;
extern crate log;
use std::sync::Arc;
use rustc_hex::{FromHex, ToHex};
use rustc_hex::FromHex;
use types::ids::BlockId;
use types::transaction::{Transaction, Action};
use ethcore::CreateContractAddress;
use ethcore::account_provider::AccountProvider;
use ethcore::client::BlockChainClient;
use ethcore::executive::{contract_address};
use ethcore::miner::Miner;
@@ -41,7 +42,7 @@ use ethcore::test_helpers::{generate_dummy_client, push_block_with_transactions}
use ethkey::{Secret, KeyPair, Signature};
use hash::keccak;
use ethcore_private_tx::{NoopEncryptor, Provider, ProviderConfig, StoringKeyProvider};
use ethcore_private_tx::{NoopEncryptor, Provider, ProviderConfig};
#[test]
fn private_contract() {
@@ -53,25 +54,26 @@ fn private_contract() {
let _key2 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000012")).unwrap();
let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000013")).unwrap();
let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000014")).unwrap();
let signer = Arc::new(ethcore_private_tx::KeyPairSigner(vec![key1.clone(), key3.clone(), key4.clone()]));
let ap = Arc::new(AccountProvider::transient_provider());
ap.insert_account(key1.secret().clone(), &"".into()).unwrap();
ap.insert_account(key3.secret().clone(), &"".into()).unwrap();
ap.insert_account(key4.secret().clone(), &"".into()).unwrap();
let config = ProviderConfig{
validator_accounts: vec![key3.address(), key4.address()],
signer_account: None,
passwords: vec!["".into()],
};
let io = ethcore_io::IoChannel::disconnected();
let miner = Arc::new(Miner::new_for_tests(&::ethcore::spec::Spec::new_test(), None));
let private_keys = Arc::new(StoringKeyProvider::default());
let pm = Arc::new(Provider::new(
client.clone(),
miner,
signer.clone(),
ap.clone(),
Box::new(NoopEncryptor::default()),
config,
io,
private_keys,
));
let (address, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &0.into(), &[]);
@@ -153,123 +155,3 @@ fn private_contract() {
let result = pm.private_call(BlockId::Latest, &query_tx).unwrap();
assert_eq!(result.output, "2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap());
}
#[test]
fn call_other_private_contract() {
// This test verifies calls private contract methods from another one
// Two contract will be deployed
// The same contract A:
// contract Test1 {
// bytes32 public x;
// function setX(bytes32 _x) {
// x = _x;
// }
// }
// And the following contract B:
// contract Deployed {
// function setX(uint) {}
// function x() returns (uint) {}
//}
// contract Existing {
// Deployed dc;
// function Existing(address t) {
// dc = Deployed(t);
// }
// function getX() returns (uint) {
// return dc.x();
// }
// }
//ethcore_logger::init_log();
// Create client and provider
let client = generate_dummy_client(0);
let chain_id = client.signing_chain_id();
let key1 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000011")).unwrap();
let _key2 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000012")).unwrap();
let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000013")).unwrap();
let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000014")).unwrap();
let signer = Arc::new(ethcore_private_tx::KeyPairSigner(vec![key1.clone(), key3.clone(), key4.clone()]));
let config = ProviderConfig{
validator_accounts: vec![key3.address(), key4.address()],
signer_account: None,
};
let io = ethcore_io::IoChannel::disconnected();
let miner = Arc::new(Miner::new_for_tests(&::ethcore::spec::Spec::new_test(), None));
let private_keys = Arc::new(StoringKeyProvider::default());
let pm = Arc::new(Provider::new(
client.clone(),
miner,
signer.clone(),
Box::new(NoopEncryptor::default()),
config,
io,
private_keys.clone(),
));
// Deploy contract A
let (address_a, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &0.into(), &[]);
trace!("Creating private contract A");
let private_contract_a_test = "6060604052341561000f57600080fd5b60d88061001d6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630c55699c146046578063bc64b76d14607457600080fd5b3415605057600080fd5b60566098565b60405180826000191660001916815260200191505060405180910390f35b3415607e57600080fd5b6096600480803560001916906020019091905050609e565b005b60005481565b8060008160001916905550505600a165627a7a723058206acbdf4b15ca4c2d43e1b1879b830451a34f1e9d02ff1f2f394d8d857e79d2080029".from_hex().unwrap();
let mut private_create_tx1 = Transaction::default();
private_create_tx1.action = Action::Create;
private_create_tx1.data = private_contract_a_test;
private_create_tx1.gas = 200000.into();
private_create_tx1.nonce = 0.into();
let private_create_tx_signed = private_create_tx1.sign(&key1.secret(), None);
let validators = vec![key3.address(), key4.address()];
let (public_tx1, _) = pm.public_creation_transaction(BlockId::Latest, &private_create_tx_signed, &validators, 0.into()).unwrap();
let public_tx1 = public_tx1.sign(&key1.secret(), chain_id);
trace!("Transaction created. Pushing block");
push_block_with_transactions(&client, &[public_tx1]);
// Deploy contract B
let (address_b, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &1.into(), &[]);
trace!("Creating private contract B");
// Build constructor data
let mut deploy_data = "6060604052341561000f57600080fd5b6040516020806101c583398101604052808051906020019091905050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505061014a8061007b6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680635197c7aa14610046575b600080fd5b341561005157600080fd5b61005961006f565b6040518082815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c55699c6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156100fe57600080fd5b6102c65a03f1151561010f57600080fd5b505050604051805190509050905600a165627a7a723058207f8994e02725b47d76ec73e5c54a338d27b306dd1c830276bff2d75fcd1a5c920029000000000000000000000000".to_string();
deploy_data.push_str(&address_a.to_vec().to_hex());
let private_contract_b_test = deploy_data.from_hex().unwrap();
let mut private_create_tx2 = Transaction::default();
private_create_tx2.action = Action::Create;
private_create_tx2.data = private_contract_b_test;
private_create_tx2.gas = 200000.into();
private_create_tx2.nonce = 1.into();
let private_create_tx_signed = private_create_tx2.sign(&key1.secret(), None);
let (public_tx2, _) = pm.public_creation_transaction(BlockId::Latest, &private_create_tx_signed, &validators, 0.into()).unwrap();
let public_tx2 = public_tx2.sign(&key1.secret(), chain_id);
trace!("Transaction created. Pushing block");
push_block_with_transactions(&client, &[public_tx2]);
// Let provider know, that it has access to both keys for A and B
private_keys.set_available_keys(&vec![address_a, address_b]);
// Call A.setx(42)
trace!("Modifying private state");
let mut private_tx = Transaction::default();
private_tx.action = Action::Call(address_a.clone());
private_tx.data = "bc64b76d2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap(); //setX(42)
private_tx.gas = 120000.into();
private_tx.nonce = 2.into();
let private_tx = private_tx.sign(&key1.secret(), None);
let private_contract_nonce = pm.get_contract_nonce(&address_b, BlockId::Latest).unwrap();
let private_state = pm.execute_private_transaction(BlockId::Latest, &private_tx).unwrap();
let nonced_state_hash = pm.calculate_state_hash(&private_state, private_contract_nonce);
let signatures: Vec<_> = [&key3, &key4].iter().map(|k|
Signature::from(::ethkey::sign(&k.secret(), &nonced_state_hash).unwrap().into_electrum())).collect();
let public_tx = pm.public_transaction(private_state, &private_tx, &signatures, 2.into(), 0.into()).unwrap();
let public_tx = public_tx.sign(&key1.secret(), chain_id);
push_block_with_transactions(&client, &[public_tx]);
// Call B.getX()
trace!("Querying private state");
let mut query_tx = Transaction::default();
query_tx.action = Action::Call(address_b.clone());
query_tx.data = "5197c7aa".from_hex().unwrap(); // getX
query_tx.gas = 50000.into();
query_tx.nonce = 3.into();
let query_tx = query_tx.sign(&key1.secret(), chain_id);
let result = pm.private_call(BlockId::Latest, &query_tx).unwrap();
assert_eq!(&result.output[..], &("2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()[..]));
}

File diff suppressed because it is too large Load Diff

View File

@@ -181,8 +181,8 @@
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
},
"hardcodedSync": {
"header": "f90215a0ea51746efaaede944c3397e41ae72b7908c8ce25967c1edcd02618b068486feba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794829bd824b016326a401d083b33d092293333a830a0aee38c1032f191c3d42cc581f53d31adb1f0d91f463e6a8c12fc35fd1db58d5aa0568149713d45e959d5d07624917617d0d7865124c25c28eb9b798013096ddeafa0847bb20a0b62d1d8e2b467c33b28ded6796c556cd2b2a169b640b40e58fd2340b9010048c03883204a1ef0204300012248c8841814900c04362858000450c8927a22a88d5b471c4869c00001d8641080695910c20801022c2910408829a8002620115dc8200ec2851300611284301c3243e091030706068c8160505403250d03f44437410080072a69048082b43070805d08424a021328221500101418463040904ca094a189c801e50000c41402603426c4701a6302e1023040080d8380e21d600a2083003a2604082001b183068d1470840a49008a514148800a08030a8002c821b24010f20ea31c55060582801c14483ec29d4081c7152d2244840016c123da6f42249b6002c8401618a0000a8c8df892954d8080800c160244453086480d8264b6870ae8321581e6cb836ed001837a30a08379e5a2845c72b9c0947070796520e4b883e5bda9e7a59ee4bb99e9b1bca06883c088b374f7c667ed0fda0f1ec7c18890c892b88f14b41f03e7d927bcca82880db92c004f0313a8",
"totalDifficulty": "9242028122621986440675",
"header": "f9020aa016c0aa39e09bf4ec53d630cdea0be984445c6c76f769b1541ce6b11c281c2fbda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a0de05c24d96b1b9012d7a875feecf86924d7a8d98b00fd0b9b7768785088edb01a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000870892f443c80323836ab801837a121d80845c2bdd638c6e616e6f706f6f6c2e6f7267a08f47201b260e0e422100cebf3d61a6acdcc49f4a24e0b1e680e26f13bea9dc4e88bef16aef8812be32",
"totalDifficulty": "8531065961847479229671",
"CHTs": [
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
@@ -3598,138 +3598,7 @@
"0x43b9d76f1c2bbab800dadc6ccb88b966ccda198e30068364cb9c0b9a346f5f03",
"0x1c9ae4b3977a1d4969ef3d950d2c74548c8b44bcee652a65f7df128511b84e48",
"0xa06a1a6ba91e429f805640faf789214f42be0d8d574065b7daea7daa37b05865",
"0xf53ed26aeec7ba846e10a84814e7264197a0b2bf485c74d98e8315f0ddfd4b3d",
"0x57fa0c3eee29055cf5232125619ff171a60d2e8f0246af1ea8120969e03dc3f7",
"0xeca0088d30058eac4ecb7ce8dfa454e46e642154b7851db0faa430a01bf33744",
"0x3f43e499ddd06a059b192a9cb9881d15078157508c1ac30d687951454a22441f",
"0xd99f60df5d3b55202089a3a69147e43a021c5760485e0899116f56060ba56a92",
"0xe662a0a21e688b7452d0d5b6372bc8aeb00c589849f63da9c3fb4c280e6236b8",
"0xcc83d5becb2f1580e7771c576b97709778a8502096948677f1274e9b0ff444de",
"0x17cfc1a415766b30cfd1ecdb2bc8bca535928e1048803b9820e81d7058aa3b68",
"0x8e1410621e8b0edbfd9c98cd1dac02e6b5dc8336da445cdb00c16c457ca27750",
"0x3d8bc5d8acf9ff44f9099594290a91d47040eba0f766609f1dc034d6bb127f4d",
"0xbc32d05ddd709d4f7ba929353a618d70b8eecbe1d3b06010cdc7dbf053569e25",
"0x818d10c0a40a9675a1d87673d9dc55895b8ee337a0cdd99dda88d6c1d506a301",
"0x633d32a1adbc08ab373324175e0205412bd17ed1be4ee5882d20944c3439f77d",
"0x8107273c0ecc4179096f1492d21de076f84d0c4529ff6d563acaf85a8f5db5c9",
"0x5d8c25ebc9468667d043926dc4a6d28caaa6be696ba3e4d248ab7150b20fd771",
"0x5a8cdc39a49bff71df23eb7fb01811ce114edf6829f946a6155113b39480d023",
"0x72f7ce230da5fe9ad521901d2e1f7c88a20c98ea82fc09c240501ba327ff3518",
"0xc9c91729c335752f0e04f091dc181ce8659dfc13a77034b319c47554a5ff0bee",
"0x3773c7671613b65b8c6fbedc97c96ba6e3b8a6cf64acf6d1947f2881dfec93b1",
"0xb378b0953123036f313210f7e020441f41c81344b0437e5c947aa3d2e76cc357",
"0xcf3b0163249f3b6d1c9b756eddcabc9fb9d11e121dd96499c750350dd56cfa3d",
"0x8baa2ead915e991532ce72a856a001f7cc493a58016d3a0255cd416108357396",
"0xf748b8ba84812b2f5ac3b91b51402194fe08c1d15382d10895fcc8d4622b58f7",
"0x7ec5d0b6b989137882c20bebe11d2facc3e68e9a93a9b2c793d804d9e973304a",
"0x4512ed8b4f3586a79c971cba695d727684c6485ccadfff6a3db45ff93fb1e1dd",
"0xe6edc389d0ade0c7e558ffd357a7557af9f2d38b0b20c84a67936914acf088de",
"0xf2947281385a9b2077e6e8657a6bdfb9c93f82311bd739d8e9b96bf97454ade3",
"0xc768e9216d0dfa3da3fd3727ac4a673897567570653a8517219c079edd191496",
"0x9bcb33bab81663ac501a5a4d2f3d739668b42a6bd2cf7645c3571d58b37c60a6",
"0x540fda7f30ecbf8a61855b9619a139e502d8b9e1a3e72179f2399efb3aafab0e",
"0xde605b760659834d38aa120d97d5b0721eddcdfeaa69a716e44b35ef721c85c7",
"0x8979afdd57a677913bfd414f3c7cf88c3c7144f5168476e7c08518396cf8134c",
"0x6826b8b3aae4d8f97707e9751a4313738ad42861bac31090afb77a34f7214b7e",
"0xade12591565e41be9e81ac8a673324a680b0a9e6d980ede210c966b1b9252938",
"0xb2f3710b4e6c805bd20ad93fa0f254bd645b5c9b5fa299f1f8f9bb57d299e21d",
"0xdb80cf61e5a9d6b6237855eb518851f474d12db1fde3c534762e1f7d9367763f",
"0xc40c3599108f6057fb67f09e7aee418490af2a887d59f428af222519a7c03a12",
"0x0916f11f929196f5834bad46ea7eaf55716ec2d269aef9f486cac38fa7734831",
"0xd5362e4d43e3da51e12debe7966c2a06ae0fdd327cff666aeb7185b5d6cc71e2",
"0xaed4937eb0e5c9a5e6803cff864691f7ac63fa9f82d3c2e1ec9a2777d4d3f263",
"0x49f63292bb091a6d6e6515e5f822903da4a9e652847a7de5b0fba5ca69336ae2",
"0x7347591d5dc652262db2e95f65a570ae894f28a631dace959f6264027ae5f3c3",
"0x300ebb8f363f2921f5baa4ad46332bd7d10eb113679afa0851ede28a33ce62b7",
"0xff1b93baa7285220352ab656d513ee19c12da79c0c87d2035c148744164cf32f",
"0xd1793b3309372878fea3c14f2e4dae39588ddaa2396fe246b3c4cdb534a167dd",
"0xe2c7d728bb7899ab8b0ae0d07d585cd380a38f63fb9079532419fb5cbeacbe01",
"0xc972d3a0a76889c41d1130c52bf175526a5560d2fab7b28bba7c914a9b9621cc",
"0xebd731a2040b488d736e846efdb41ac5a6020e7c2b287249c105c71bf59b9504",
"0x8745a726f0e971fbe22c9b28234c3d93333c0f8d5c126ff9ee5000e26da7031b",
"0x3033928e0f79cc47d31814e409312127ef73a15a6aa915786e4410677942dc6b",
"0xeb77e57fc7de01107d1adfbf479a4c3a6ab5ddd008dab67069c5fb488551634e",
"0x6eae31a9b04e7d30e7781e33323f52e9f411fc7143b8feeefeb71cf6b4e86081",
"0x39ac81712892e1ca0cec0b63cb7d526edb0a276e6ff41369288f788d4eeff7a3",
"0x9de1c4046104a2bfe58e94215f59e1ce5898e3efcaa2ac6a7916817648e3b304",
"0x3d6fa25cdb3aa2cda4bf65a85927fa5b5c79d3ca427b6b128d34dd24aa08b5aa",
"0x8f5d95fb92d3eedb02da88535e4d0c9ed713fb2a6ded42ad8d2036306abd3b31",
"0x36abaa49a58fd335ecfe8b0ec61a68da28af30833018788fb710c3847dc3e258",
"0xe0224a4df20ed2e5cd78db19cd906d29bcf3aeb6f79135aeb62be16f766572ab",
"0x7584341a036595e957e7f7c09a5932c1e75e5a5a73ccd31fc2806b134a899082",
"0x1dd6909a77af37732b2e59d4341047ad85b610f470684433f2929673399c2fb0",
"0x5d9bf04171804ff9f2927a14176988349c0d0a86654d8a5897ada06ca4a18d02",
"0xa1714a70cbbaffc82a9018ec48acd7aaa70a5b6ed00800249fdd76326c5eb32a",
"0xb8fe04ca47841ffa34b5f17ce8922c86a9b98bb6d7d13c4b0fd27df931200422",
"0x308d034f42f0beba3aedda196573bff7b9c9852888d6f9e3362b4259d2c1cbe0",
"0x05be7b2c1b9f84273af920a4af58b183619b016aa20199fd6845eeacc479c744",
"0x613880fff823c896127092c2c4e0319e6cca955b650829ffa053c4b228429d61",
"0xca039f943e38b017fafd119e870ee80bcd19e7994b15449a03b7bf35c1a69add",
"0xfe29c86d46c9db3f2332f2109a81199c5f48730826755b56715a98eae6e6bef9",
"0x6e95261130af62956647ad47ebf45dba97a9dd684940d5b241a6b0cc36fc0b45",
"0x113eff6173e9551800e70882942c37723aa83d573f2349ac614e6d245411af19",
"0x07e9fbe087e6b8f4a2cf41373b1977823875a9d3be56b937b977503a20996437",
"0xae0792daa47529f8690d30dddb9e0ccbdcd3e4a3b3f0386f098b147c4cb3dd58",
"0x6ad953988a96ea288c407afc70581289c4dd6b8ffceda65f6d4a51e8cb7228a8",
"0x949d0b15d25fb79f31900f0e48ac3fef50b3d1b69f24f505fad87ca56ad883ca",
"0xf0e01643fc4c21dc3adb6dc1a0bc9f601af1bd4b5ed50ba156a280996d521db9",
"0xcf396c2e2018e5dc71ce2e8d8d2716565fd9ef6ae097b871b4349a487e0a6727",
"0x5f22e44bdf7a346985839c4a395f66e2fbed238f0463ab2b02d7dd23c4e25748",
"0x8808ab6e652afa85738443a808d140c103757cd1a356bbe2b409e95cced6fa7c",
"0x9ab3eb50f50a357020c69c9501cb2864febf0be1c04edd20cb1fce3fc075b7db",
"0xc360f24716b701218d2c486938e17d7b56a85b818b4e808f7c12c85778914f68",
"0x0e8388813ad36963923d68e9a223087e2e29282dec830d13e04ca444a6e1ed6f",
"0xf77bc7d25e80792e69d8900f5e77a9eb276bc13d391720c8b8a1c608deaca05e",
"0x0979a99fa0f1a046c1da8204f2912b3c09c6dc7d37e0b6dba11935e5af8b1fb5",
"0xf9327d2fb74c22853685a3d41d6f63984a354115af69c7873650c9f8bc2d31ba",
"0x9fa02b5ef88c4496cd054f6dd26f292e389976b38a22760cbb505f068754a60f",
"0x1dff7dbca8c5d169d2ad52a4434a01ef647f29707e59d4543053a8bc7afc664c",
"0x051dc8f86a07ed084afe4d14f0b39268fc5858c908056401586acd0c9bd628d4",
"0xe6776e7bffe6398d66564b7e5993ef70c7347287842319e585c7f844002d9555",
"0xc5bc5e2c1e26900fe2492019e11bc4ec5595e1c8eb68bc1ddde65aed94ab83b1",
"0x6f868ac5f8f7071b3742573d8f4a3aea1bff632f6c5c15988572ea1983e9e535",
"0x086a27e853ff55ef97cf876e0d703898eaa0769ee4efadffacbb8c03de35657e",
"0x00aa9b9ffb2837aec2fd6444802437a5dcd4654ddc2df584e1ca351832a9e163",
"0xd395a77dd37f2e397456a5385e1fe4e781458db37d3a6d8da3b1d5fb7c5558fe",
"0x7567bd55454dc888c6aca9481ac1fd6641a93b3d2f5d1bc81bab97dd78f490ad",
"0xb7e980a03060221442dc0f9487a6f0614f5b83ea23350d2de3ff0ae4e93d02a6",
"0x1b43c09f68af74141ab23bcc3402932257deece48af74503e6ca452ecd59d9a3",
"0xfde1e03da25883b8eb78e3ac92914feab4e7294eb78a94e801876d59aa559f8b",
"0x807aca1ff5c2132a7c2b5d67de9c536968755dcfc32e8873fdd296f807148d56",
"0x8f3160048010ee14d59c26c0c2767b78350023327534ca27b086feea4cde5910",
"0xb26f5f50bdef8212578eb07f7afb52785944811975e1671a405013a0fcfb88cf",
"0x4e14680b46a09bdf8b9046f62ec5a28b8edd5704c3cc91fefb83646a5dd3eee9",
"0x792f84baa0644328b9cf5af899a154faae97fbbae7a1e7874e6219085b271265",
"0xc4d26ab903ed6478fd9a0fa80382f7b4eecd25125b623c6dcbc4ebaf0d8b3fc1",
"0x906b46aba1de6a6e3692bea009597d0a8dc40b76a1c5a4476a9daeeed65c2b25",
"0x167fb1cbf8026a1af6c16ff3b18285dd9d934158a9b9ae75b90ba7895ca2b7c9",
"0xaa659098a8ed4e33e511872bc82cf758eb6c2b47e318899b4e4385bd32fae051",
"0x757c86586e3307882c6d966c2a88745e4bc1a9002337a5d137d83ef3d4496768",
"0xf342de6ecb6bb5579cfca4e7dd4dedd2c1a685287dcbd891fb918226eb82cacd",
"0xb025cb5c7c1d64a8138ddd439aa95cd9a4c1162d628dae1f09bbf8a225a49f22",
"0x6ab070192b7919718111a5b1d74862c48a5705d4e9c6b47a3a81564180c3526f",
"0xf9a23794eddea371183902ae36ae4b54387b4b8b170bf848dc24a5ea39649545",
"0xfb9dfb946dd83814681f93091ceb299d417d8ec8d28e2ddb7843d913b699a6a3",
"0x44ea56c8eabaaef19c9fde38ad0f92c074039d93960b51238c1b11ed2315163a",
"0x66f8ce000b102ea085a18cfb17e99f242e0458d0b0d9d39b6a8653008fdaa98b",
"0xd573e736c4609d90ade296503843c9a12ad8f3795eefb32635dce70f2fb17381",
"0xa783abcf83917308a63bee26ef64b010e15b62014ed560881adc3ce78f80c3b3",
"0xf8406110d71475627fa02fe434b3270c353eca0ea700bd196a9c42dd2e6c472d",
"0x5e3350f159e6370a741af5879bdcc8b08c44538dabd162fef2b745e9ff2828c6",
"0x915c517a16a1dc3095bfb9550f24afc3a60f442c9205a7ebddc7eed37fb267e7",
"0x9ec7f72f0e8d5509e3ec337b0c879f730c16c55e4259526c0816d6891feb1dc6",
"0xc294284cac5de499512f9b12707b5f66dbb3b635c1cc6d4419b17f40e272e339",
"0xfbda44ddfe4b7c31b915fa94a27aa01fcfb22a9fcf0b557f9788bbf48b3f7f32",
"0x4418fe011a16af7da4645f300143a6cb005650ea96ce23c6adb4a82f60f72beb",
"0xfd3a00e52f4cc05610976b0def190199543ff3e423f09f8bbe5cef8315f36d7a",
"0x5c9fee100da6ec53ab1cf96ca9f369401853753eeaea30bef75f6989faddc504",
"0x713e2e28396b62bc63ab0a3dcfeabe977bceece4057a687d157320358f2dd08b",
"0x62ba90cbd06efea1d7bb7128e37e33d94a21b246b7eb7159d2708b5552247a75",
"0xe13d2697cfeea63e973c7493b4c54917a639fcf13eb1b327e02acee353bf84bb",
"0x8ed199e2fd654bfc9dfd5e7ea7dc82bea9f4535eb480c95984a5a6bc1533bf8e",
"0x4e5475dae57c548460d4ddd15583223bf2a4a2046c2ee56ca670892794a37d90",
"0x80409971b3e59ec71deb1a158a92ab6fe8318cb9adebcf583586e23e42d370c4",
"0xeb35d7c78965874110f67b77307deae4bb29dc98c01fbac3737409ede61df7c6"
"0xf53ed26aeec7ba846e10a84814e7264197a0b2bf485c74d98e8315f0ddfd4b3d"
]
},
"nodes": [

View File

@@ -64,8 +64,8 @@
"gasLimit": "0x5B8D80"
},
"hardcodedSync": {
"header": "f90247a03dc1f4ed47c057717131ce81535d06194d990be6969334e9b8034e0c875f9dffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940010f94b296a852aaac52ea6c5ac72e03afd032da0fd1833e970c207ca16e1e74d937c9d8e01a1f719643fb25963028427295fc2cca00d9d5e376ebe3558b412402702d34a93256bb03a61df9f17ae234f0a70f95b20a0129c38f28acd251820f96305d217511a725a1fae1a434d77034bd7efef1f9f5ab901000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000080000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffa839f3801837a1200834bb5f3845c7361249fde8302020a8f5061726974792d457468657265756d86312e33322e30826c6984171cd849b841d077cf579661ac8634ee865b5cc67918223aed686d6ba189624a6f6c0dfc5249418b25423e30e072a79d5377e01845d5234ff5e0b9b0207b1bf2515f805b47e300",
"totalDifficulty": "3500253997070921577369506418666760871805116639",
"header": "f90247a0017c9292a6abf6bb9aa48c30f8854dc0e9649bceaf19079b1aac50ebea4fa316a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794007733a1fe69cf3f2cf989f81c7b4cac1693387aa06b81f6633226562f466201f0d097877c903a650f7427aefa7433fb971f601287a0098141509099d91ed2c2e503d43db5b5412d51880994e8e03a86e1d7a9ca8e8ca0495f318f8bfdd4beb517d115ad5d5330aebafe70eb2b1cfb0ab029221a0f48c1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe83975801837a120083035108845c2c49e49fde830202058f5061726974792d457468657265756d86312e33312e30826c6984170b1279b8413ee0655a59d1f7f8db39c22055c614346450e99965fef62efa43b21b20f0966e3e41eb65fcaf6f9ce3a34359dc064827e06f3a29d2c717f287234785d369e56f00",
"totalDifficulty": "3324635628632492920129912637269655024947201711",
"CHTs": [
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
@@ -4909,259 +4909,7 @@
"0xe3d68466d0747ab6245e5d8620eaae080a0f3c2aa34a56defe8adaef56d5474a",
"0x8d0f53bb5f7610133f04a763263815e092e43b0016369866e959d22eca466d85",
"0x8c8f0fff76977593112a64826f15ec0e909d9a1f1589e121a37f73d881e6b696",
"0x9ab1411e7ef5b295ab1a9dfe4ee1cd1a740af5b7e4b0a0e9c4a5f37e803c7c94",
"0x7a842e2c606aba52515ed7f114116bc782810bdade34b582077c57844e6af18d",
"0x40b14c755b9cecf8264622d80dcb5864241c0f41e9665908ef3683e83d33e9f1",
"0xd0faf39bcb44f583ded1cffebc93a8acb49a10b3bb2b0c9ed794b8aa4bd9e30c",
"0xe1eb93e1abdc400b49eda22b5818fcf61c56309f10d5e3cf3794bcd7760c4c0c",
"0xededdd50db9028797406a8559fd824a3e024b2362bb24f708c4f8423c657b31a",
"0x20f6ed1b586555773ded5606e711a4b9bc47b84f45bdb97653de8eb4c9aa40b7",
"0x77ade166b067475ddc450b0d6991b5a8de93c3b60d76d2b6a3f15ace449ea6d7",
"0x766c057ee18d96d84ac85caff6e0ff4954d3add40ed9488987ec5f4865f06ea3",
"0xe5dc0692cb0da1b9778ac99fb26b01ee7da45da56996dc7e5191f28e60a83bba",
"0xb86ddaab167daf9b8d4827e12f19201cb7ba2fdc7767aa7054f478650360b5a0",
"0x570f60bd9224065c7ac611e89e9737354b3186440dd328efa7ee0078850fc296",
"0x0438822dca67b58f7c5ede70758f24ad164e1c0e3f6628274535101c13121201",
"0x709382d302a6e5b21823af6ed14f22dfa79d7632b8649c67cff749fd9cad1d54",
"0xd42c07bf201d8025e9202ce752e25207cae1804877149a756536348853478dfb",
"0x82944c59acd3d43c731cc820a38f4b9ea4fafb3c5a5cc474ca0612c2e50f88a1",
"0xe9c2665ac57f450a47b8f5407dbfa7575ef4fd3bc4c90a1e64e7e0f597c6c4f2",
"0x862decca6c5c15a52cfc88a629237dc1740d533dea40a0850d8d0cff47672c43",
"0xeb453cbb85db88ed6ab19e57fc0b90c045c3c0dd6aca67f3be579c6e75e6a1ab",
"0x8f32d04dacbfaf1bdcde08205fe539f24a5e453c686257d5e39217ecf17e2a01",
"0x81f1d7ed305f8981fd6ef9adc7374a3bab51b9f5d042c35e7cb16c7eadaf37ed",
"0x8301660b9f830042d66b7197ca95eda84e9220d74f48ccef41aabcd8bec18c57",
"0x07c00b7b9e698074ac994f5a96cfbfbc6f3e8ba34bdd727deb60aa3ab9f0f1ff",
"0x44c59c12a76078144f62fc9646f8a37ac38a0db2db3cb002712834c0bf2a1bbe",
"0xb3abeacf4280e9fa9357fcdd9b4e866938c37513e0f8a31b9f8c5733c48498f5",
"0x72dd15a76cc64e9091fca937497027b77517334012d71b47502ec28f4cf31433",
"0x0f86404545ab226dda8789da56d1d67edaf201062dc4f3268e0a4c3314ca6628",
"0xf2c60e7441c1cd8b448b9d93fcc7e5f5a107d3b502454fb2f6b8607c49e12a01",
"0xc272b28ebdd6cb2cc76cc255f68602e731579bc79ee8c9f6a3471474f14febcf",
"0xed87c1f9b73e4f757d822e5161c6299aee52be1465ca389f0ce008eab6f51c17",
"0xcec988f7b79b0b5b9f4b1e43466b56dcae86823e45997fe208e7f2cbe4604947",
"0x0583ed42e92bf0cc3a54a4b80edde80606aa9a16d6254fe89b809faa0c7c5f46",
"0xc61e76957a49acc14fe008c525de69838370fdb7c3063bc04dd98b031b12eb92",
"0x5495eb0d9ac61871a364a5bd697628f4e480b8eea4c454cb583b0b11e59373ce",
"0x3ee00540b8bc71257573acbf77c97969e0af184589df1decccc5490858b1399b",
"0x6c10a21b5e7a430ed342bf38a88522919f217fb7a087576d7040f71b7d6a8e0f",
"0xc0410a1981bbae319921e5af78c1e80e4539e1ba9140adb9139ff40816255910",
"0x300f10eb6ba9d4ebd662710a91bfccde83a561b0dad7e14256a7b62e8b720662",
"0x9f5de17b88d3bbc6efbab33a7b2d8f2c120643b3844f8e37d19e10f1526195f8",
"0x2918baee5948882cfbbb57f6ba18a0434d2a0c3928eaea3d1b12de0054c00b5f",
"0xf5cb3b2a6d29bf9a0988877cbe22a01726883159a787a324bf1e685b92ab8018",
"0x08a9570f38daac2ca30d32e582f9f8f3a80e82020668b5020b29bf0456779b9a",
"0xf807d91faee554d99a4a728b219d285834f231129a6225a5a4340bd74693b133",
"0x7798ef990ab47b908f703dccfcc0d5507dcb7afaa9e5b98841825f7d2ac6b655",
"0xe5d3b714c47a7f5b8bc95dacec03facff800774c72f4379051a1c574b919bfee",
"0x5c5f6fdd4dc6d353865ee1edd5893b634f7239b327840b4973509027c8622f74",
"0xf713adae992084b0593ac33894fea127fd73a6439533cc94d07b89c50b071fc0",
"0x548d8bfbc57c4773fa2918dd13efd1f55a68d4a86b526f4560abcf48665ed637",
"0xf47bdfe91932a9b4e968e64ad23690b7c3421137b44030000ffdd78ac798b3bf",
"0x4ec25256a43c957c1cef4be253a69fc771889ad563ae677fe3e5ea6936cd760e",
"0x9b8a28041d701c32f976fada9ce9a73fcf5dad79587c9e02b5abd7a299d74292",
"0xc7c6285cea2145104924ab507bbd5aef09403f61e90ad04e0fa8a67e2abb140e",
"0x2e839dc3048ebe96490dacdf688b017f388288954704c9a99cdf25f9203fddce",
"0x37e37dbf1f4cb8b825cd5b68ea18a80a0bcbed46cbdb54c5ebb136ba4e88ff95",
"0xcdebce72ebb15b5fe081d0f3290cd8412c56e93269541af2461598fa2a05cd1e",
"0x37716cf58953f21168a83613bfb13db775fc96175384aee35f76e82095d19716",
"0x7f7ed8d8526f0586f08dcfba6a279689d0f7aebfb0b11e627c7cd0a31ea99256",
"0x1066be85b9d156b32227a7b74cd23b330f3c80e62f8b671b1dd03d2fbaf038b5",
"0x53b3ba2bf9f02a52c7caf9ef6b46df80d9fa1ab12437774b2f2d073e886dfd5b",
"0xad963410b3f77f2399b7ab925c7ef5cff512534c2e12e7e3e9573152f197f28d",
"0xa3b75316cb456a516d1e26ad8df52a0a2894f26ff3a2938f9e09cbd9354981d7",
"0x522ee88e34308bbdff564080e665cde9b3b4ae4a61afe558e5609996c1b2f855",
"0xd7d377a1ea94fdab72ce796d3e62cffa96b2b2226bbc9fcea51817414fc367a0",
"0x2ad4691181f4947c25d521a9d593e25c5e67c0b6150b3d9e27515c7808223633",
"0xf76442cc901ec7207c33840e6a029e3655d279394261b8e2fc350547f2fd4cd0",
"0x39688b8d86b6cacfea5d71e7311b01e2009a939c6531eb8af8e88b1d1b7a04a9",
"0xcc35ca75b97530d9c19199827d373210bc9624fa0ef572f7c3aaf2672918da58",
"0x85a6af5bf38ef40d2be7a529f3f370f56f380406fb8c5165f5bdff75a182b2ec",
"0x54296a0ca61a8a80d4ce9333c985983f953975f6bd7eb6beec593c149a3359cf",
"0xaa1f116c6fad9512afa8329eb499f197c5716a53ee283f06c417f45d9ce2fcf8",
"0xb9799045a8f20c5885649ec1a632eacd44a72b794dc7492469f8c1abff3edb24",
"0xd86348fcec2db2efc3deafcc18ca121de0176b1e89698a3c5244f377792784e7",
"0x7267a4a5e59e848f1c3c9e4c6f43e7aa128b73261adb296a89a7abccdfd16cd9",
"0x817a39c73cf85997721cb067b4e00812ab7fcde3e4506e37e6514c8c4e87846f",
"0xb8e7a1c1aa51637ee68590a2d5be7a8124fae067cb3b0ab3898f5c45fb275010",
"0x43f77794f4bb485488cf082b416885292a7b254057e7a75e331f4641c1ea2839",
"0x9bf3050d09ec32ddf7c40fb96ae136085587c3a4ef6cd413f73dd42615327218",
"0x069923933c215e6c60c8285f0afb83de8d4d9911a2c6417178f5f149388af874",
"0x01e1fb2dcd7bdf5e30e5569a677f39e9356d70ad5e7c30cbc8c73eec66bba5dc",
"0x39fcb505c1365111a0837993dfdf527a716a441628f248aeda785b32e04eeac4",
"0x7837393e026631af009ee2f61e1a39037f97f77f98690ce92fcdd934b80d3ddc",
"0x7695c9c3257358c759fd8c9018b2834ff56c42abecebaae806a281c03b887aa6",
"0x0446616edf3b74a68fbe0c22029b61d16b67c300022211e013572b90815b6050",
"0x274d5faf73eac9078b9d9c870bf07103aa749b0273871fa8e166932e3c0c1556",
"0x34fa06554a8bf6a2305d7ad293d1617f5295c046cd6de60689af2af9d44decc5",
"0xb641c3b6baa2370b85fb8bbb8c054fd9e7d44425a095778e859915f5b3931006",
"0xd4db8f0bebfa97e5ba93fe7aa444eb74782a98f03735720482b5080a4d3d980d",
"0x4261a0741221a7bcfa4d8bd1d6e8a62fe47ded969cc2b1446a7a76da9a23e844",
"0x6664826f16716dd01d707896f892a24b29aa9b78b2a162bfd01aade882314815",
"0xd9cacec24e60731fffc19e6fe8bf0241499ca78c51f38f841f6c1d91cb4f686d",
"0x57755fffef02b43c1be01eed12caee89bf5cb4ffa8b823aaed947083cde2d0ee",
"0x5d9bfb52ffa30989655e77512a3f40db66c790311c9cfb10d161b62b7542e334",
"0x302296acbdbd6737cdb060223f289ddd71516c8c42cc5128bdd545de6df02bb6",
"0xee1c6c48a63232e8dba59646f8d50dd6eded16ab310f39548300249efeaf7b45",
"0x60d151e272c9e6874c9c9bd90e8b241c0ec1e978b5b1db2d6632542f9b02488c",
"0x71c8d8c3da03c317eb14b12b5d403581432b3f0cea447da99dde8b60c9dc9cb7",
"0x9fd4de13da3b68bc5682debfae937d4ba4fb67f87cbc30677941ca53f5029945",
"0x2fb70f11714902235b3ca78b281c8ec80aab89f77e3fc59136bfbba44a2c46e2",
"0x30109aa2d8e89ef3669e4abb89870c77c5acf5a34bf273fd56b925d1a4fca03c",
"0x8d5c57cfcf34f5cd277a7d51c5a2fd1405b26231646db44043e735b8aae78478",
"0xaf961653148c2e6007d011e20d008c25a2c842f5dea15e2fefa76b3f324424ba",
"0xb4cc2c774796dd0c44923ecb3904e8f0c64839d32b7afd0c7f87eb0ba5e52949",
"0xf4c16b1aeaf622d35b4f897c5b9c96358af2fde5ede56d377132a6e57549565e",
"0x15c2a9f6eddc424c3ff3f91ebe6ac55d98442923267c80f59023d18b9d29cd9c",
"0x65abebec89e4a4d6e674a29f3e5ee304050da861a3a3c91ebe79a3a8aa159db5",
"0x46030219478d3c508cdbfe4cf76ce3924942cfbeb9ec6ac9e83dd5414cc8714a",
"0x4712aadd9407b29cdd5d3f0747374fea712eb3202fd2c13795268d498dd0843e",
"0xdc5ed31d4a9c4fce3f91f75102feef6da9a190638bf1f090df64175b531b1cc1",
"0x077992451f048591ea0bb7b46818c602b6fb1d535ddfab2dfbdaa6731745fb66",
"0x889307e6b877b390b86024c2f48afa3df0c9b375512e38ef778dde91dc950f55",
"0xc6127728eccce59452504b58e10c29ab854712f248d6c90b43360c2786f38647",
"0x76516eefb0f149ab9fbf2dace9fbdd4d435e583b3bb19820f45801abbb8309c8",
"0xa3771e4be252fc17bac8dd8cb9cce1168e531061b59be4fc9115838af2d3217e",
"0x1a0218061cd1c34a080b3a70cbb0c9f66420816a21a2f18f67e5fca6ce62b3f7",
"0x42751bae5dfa6d27b92cb15bf0c490d8184b97fb647563bbb4a7612f31369473",
"0x03bf5030aed483c4d07ba6a5be51ff968ce869decc37fe264b98661bccc55668",
"0xaf604a8c41a8a2fb37e317b2a565afa4e25c289a17b3e7030106849094d517ed",
"0xdbf8ed6fc0f94eddd863c883c17c974dd91f679194d4cc74316092327eb6bb42",
"0x27624ca6ec82b25f6bcaae3b0159c79803228ef5a5e4443498e39e7ca8280195",
"0x19338a8eb7d6884c8e6614b408ff2e5d44ed84e208673910f10fed7f1bf95c37",
"0xb612ba1448b74093a5be0f2ba8d330ca56647eaa2c84c3a1e3d2ef765f430126",
"0x523a7f824cb76717e0985ea2cabb23de5751c67ea03d6b569c30552d8bc9caf2",
"0xdc4f2e1b704ed39f818c36b26df95184c39927246f52a74772be1eebbddc78a7",
"0x4b5e3bc7c2e4f098b829f59ed096527216ea84bf9041d2a3c53c00cb7b5e7a56",
"0x3cec3a6e9f95bb0e2a63194ac6353ac6fe9a12fad00e8f603703454638e8d819",
"0x29b860f98a7239c9fe3994b68019ae8fd4d4009c07a088d23cd70ae6033fc727",
"0xa8d1900bc2c3156c6bc8a41378c0d2c646f0328d4f8b8963f52ac0dd506731ed",
"0xd9f8c709f2a6cbcda62ceae4c5244554af106e7f7fa0837d8887e23887d32e31",
"0xea7c17fa8dbc43b3680741957d5a020cf0df2d491aebd6955bf6027a63f75dd9",
"0xf764705990e0a12e1a97ea2cfe3d5fc0c28a601d1bb6c1bca0d24e61175d7403",
"0xbd5d6454bb6824df5a458fbd1a29476e76c645564c42064eb6cad79237e17a99",
"0x39e99ee5f716670380fcba0312b8b9d902dc3fe4e49e19bceaa4b2f3c2041366",
"0xbdb6860183ab7aa4362223c519791e7a0b63379b87ef4c30739e57515aae764e",
"0xbf6e060baab8b162bdf78e1996e30cdf4d6dd60b5daef909a5e7fada00090928",
"0x1ddc651ab0d26eda2c160911e4be92c8ef843ef510ee28f1d0b8356760c595f3",
"0xdfc38ad4e3225dcdd2dcadf32b024f754236601cb60c7aaec61a692a9f367acf",
"0x326cd0b07c68ed36049ef9ce9af1db0593a26193d9988d21d8ab05f7ffd91adf",
"0xfd76ef987cf758c89c04a221c10e50794132d3866bbf4e739e288a9b3014a9e8",
"0x590f03df3ea2123eac0957d2a84a4a0e0184be0eb75851643c0b876f364942cc",
"0x0fc92d4be9d7f7d5c49f3552d89203090fb7f4a4d34ac1a9925036c84d5d0d97",
"0xd90702e78e72b71a3f7db3510c25d0b26d098da80003cfa4abe3c525e3212d2b",
"0xec682fda87e3e66fc89855bd1ec01a80b515d6dda5f4b2d207cc5b2ac840532d",
"0xa75c0c5ae9cc31a14badd2f0cd66b9c081aa541e4f862ef0ee5aa8a692baa89c",
"0x9c237fd14d83ea449bc37922861be5fe81531264bb802d6a07c149b6883c826f",
"0xab2240195acb14c2cb5f3e6bdd352c4c36765ba6d2d3042bf15b3942b50471d7",
"0xe56052f2729f3d7d08b7958c0630b9c3ca2c6fcd9fd5655314bd1d5ca94e7852",
"0xd774822e8bd746a6b253e9c71f80fa6d6f9ad95bdffad3310eecb98785c549d6",
"0x4e478c8d5034a0e51e1e760fe258afc0c1f56cfa145f89bf34156426ea837b0e",
"0xf84cba0083c61307c45e7caa3844053ca78e2a1ce181edf17041130f314f4d00",
"0x24db4dc31929f9c0521a63d1b6ffd14939130c7d25df7a0827513a6ff0b28159",
"0x969f5efaeff2db44bcebbe23b9ff916a15087a313e814dd9f8140388fa62a48d",
"0xbdf6deadf158fbbe80670ae75744a419b999b747cc0804ec2a81b9082b5a4ccb",
"0xd25da9760de21e6483493f5f781cf526527aa0bc17ee9c9abefebda4e8bc5b71",
"0x83d5382a1a2132d7fa2bd48e06e59243f6ec71ee50626b65a84a7e5d3543f8f7",
"0xa5720e9755e2d04563583af4a2581a8a1761e82eb769dc7695b1f9654e36f753",
"0x97ceee5cb98a9e917223523650405aaa2e71cb12e568319baae1ee75df592fd8",
"0x1e1e8d3d81ae5be21cb8445833d9b8928b6c9a6b9217532b15ce0ba6cefa64e4",
"0x1c3ca12af63f1121e93b5fb602ab8c8ab1773d07bab5a60e78cb8e70e190bd4d",
"0xb343c9f8dbe3e65462838749865a748d4a5eeebe5b6622b56325e2e6680626ef",
"0x04eda02f974da35a3f4308d6b6be16b602d9317256209bf674f3282b2bda878a",
"0x0f85c864e5ac359d9a0ff54a4e0b44a31109c57d7c2171185138dee5638c627f",
"0x476f9f649f2365455d4756f541e8b8f8e34b32f8c67196a06fff2f71abddf5e5",
"0x185b523fa66564ed0e4cafadabe1c04a399b51114f5fb743136fcb2a0a53e477",
"0xc87106d70447c962f367b567b37281e4d840fc16d7b97dd349ecd073d0419cc6",
"0xc0e624f73d54230b99169c8919c965319ab2a93a31923bd22b50350bf0d25798",
"0xd78f2ea276fce38b53569cc64a6ce7ccec2fdf4f1a295106a1f2c54330a0db40",
"0x4a1c2807ccd57ecd989a2b0d4ed2d3ec609449e15c5652cff515ba5506cfb745",
"0x453e4ded943f491b41f0522188e88b28667172202b8a015f113171c29de193b2",
"0x9ea9a96b93c19a00f2238e15bb3c74409eca441e6d0ecb47b574fa8fe7390c67",
"0x9833f04cfbab3190d2d831116f1f0e1871018d862cc2389511bc266756963540",
"0x48ccbadc3d160d322bfc61d44962628b088da09d045c43d028b1b9fb979462bf",
"0x33d90a0c09d27087c15b01228250cac34fd4307d45593e7239096bb77822f6cc",
"0x545e2a8e511ef59a5fd7f183b0bed449d59788e4e377350b56bdb387e82ad4f8",
"0xe7e31fa668cee51a20ad4f2bbd459016639bcd47421836cc1bb3e0e2a4705998",
"0xaf6e1ffeaea0bcb61d5d90fb6d6146bf4f6102f49c3e5f653e1bcd6b043ab3ab",
"0x98bee111ed4d2cbd72725011d5a565b1873c86b8f3e17f16389ee009dfe3c6e3",
"0x2107b120a64b8fe21702af4bd26e8d981fec6d0051c83046bfa5dd05354ad05a",
"0xc982a8ce403f43557d0a812b8be06827d88e2410f6e7920971972fb205bc8a4c",
"0x5d58c764a39ccd3edc5e1b37f3ec73ddcfafde249e066c6185712c0d566b2e33",
"0x9afff9b16248767858ce0520877d7f414764eae8ad77d9810d615540c119e476",
"0x6154b7412dc1fabb80fd7ee43a3b91651e07b62d15afba8c004611d8ce2a88a9",
"0xfa859b6679bd6a2b283ad4ba43b8b3d96b19292d017e933cb307100e0e2a9c36",
"0xf32a85527d705fa439494f314800609a6c5f6657b205b0127b64cd595aa2c31c",
"0x02d1fe3725fad05e13189d6d9e078af8c825bccb5775dd1a6c90be3b57081d02",
"0xb003929860e22e0a4bebf5be75be8ac86a511e3f9e9b421aa9a99fe0fa4d9144",
"0x583341c3a9526d29c43bf22619df050676fc5e56974a8588a91bfef7409818f4",
"0xb94ebbab275786dbeff9189ca740bf324f916c76b800da87e6e507d546128ca9",
"0x5f26114f75c4f839fd6776b3a67b1a74fe6afe5fee1d3053fc5b09b38a2f31f5",
"0x053d6e94968bde9f906aa52065c0626810d138908f1645f2e563d3aca9660276",
"0x458fdb60ca1d0b7ffd846744ee6fc7219ce6700b4e5cd97603c4885563a0d14b",
"0xdc09316757c1ed63b9d984647db8fb69fc9e8e6153424a6e99016f868dea613c",
"0x409e2e26caddccbabf10754bf500262fca5aeaf6ebc937062e1d59b087873a70",
"0x288ee1a1e4b4437ac97c7130d4260bb0298ed2038b57c801fcf2389762a8dbe9",
"0xb82f496c7c8c8d2847ea7434e15c61883f4510e3151f56636394d88e902e19de",
"0x5fe701b2ac79e258c7201cadcf7892cd37e76bf9f7f9b9b46d39ba0fd359076c",
"0x32a841cf4e27eb60b5a6825665cc257fd1db222d501b42b5c6a814cdcddc1038",
"0x5b76c42acd108597e0f0ea8c92acb039a047dccc7f294205d1e404981bcffe0c",
"0x7084da3532f91d33a42701d9c580905f4cbc4137f33db33a579aec2ce5db1c53",
"0x11e58ad87c481e2d1b1583bed5b6e71ffbc1114bed29b7ac14a75d852a4741b2",
"0xdbbe146f3e58fa32d465a175205d757f18929cea4870bccbaa2698c58cd32f6c",
"0xf1dacbb951e0663d5db612046e090c04f18bbe31271d3d786f20deffd44b4205",
"0xa11dd2266cbe0af5b7f1f7955c28fc43a88abb8d82ac18e835723c85e8fd2d22",
"0x716ed679abca531ed520deed7b6d955e1c07c5ea483cb57a2322ed8c7a5a31e1",
"0xca4e5b466b978777d7a60a8bd841271da8643bdf0085379677131bf4b3604f33",
"0xe3ab5b13f5cb1bd8dc38c5182a7f16c02abdcae7a310d6c0233b96070d9d30f7",
"0x5f29236e49036d429f283d25a2e4cd6ee8f01b314201a34713b50871ac1ab628",
"0xf1e41d548090c62f207208b575e0bb7b4eb08c30abe40525effbcbb8b5511482",
"0x088fcad31ede2ffe1cb9e67becae368ba3be97a02d4837be59bef650f4b90e4c",
"0x4f4cadc003d445a2014dd5f819a2b67e67620a21af8302469f9ec264cee75e2a",
"0x23b331796e1c5c95a701a1f791ca392da953a7a9d5d2a834d0cc941ef6567250",
"0xb147414487aa60ae8ef7aef8577ce50b4a750b0ab77175aaa39fe78ca5d2e12c",
"0xa2250e2b126ef24cb732c79cf87afc5186b88402b70e0c9b7d3139205c7dfd09",
"0x5c40cffeb999c74452e77145e22c3c1d1080deadf4f49e40cd5184c683f628d8",
"0xe2f8ad15a61579535dc9afc59d9ad16308b80e409fed46af55b7938856485c33",
"0xec81eb466fd503be4a807bad9b2d0b6ccc24d1dce3f82f69adc99dc81d69a3b5",
"0xb87d20dbc44c1a473048e96a2957a4b9fb2ea606cf7b3de9d44937d18695f0d9",
"0xbf0dd81b0e07b07b22deb6b97d5cbd1d03a2726a1e7bf9f795c8104d1ff1c458",
"0x6aeed28f1590a1c96f1085a1867a4957673cbb8e4251e5876a43182e7b40e4ec",
"0x24df74cf385560d990f59f8c59d3545662f71b42736bbd1c1361b5a1c45d2b47",
"0x881647b453a1e3ff0b6e64a3667db62add41599f003f9032418576323a5ce1f2",
"0x9fb9c9bdcfcf35e02f0029f74b86d131be7cb49f409055cc075008e9ae33bff5",
"0x5f17c4c7b4d1b0cfd3929eadb46bf1060b8394f6bd5c0095623f73de5f8acf03",
"0x63c4b4aa80474a3cf70243f3a2d891266760f6f54693f4f189c0aa9b3d6302ec",
"0x97921aed12f6d78f6052050f7401caca6bd07cd643fd7a30f681a72a45b64a0c",
"0x82e6c73da95617192ccbc9374bbdec4c4323f8f63a27197cdb52a0d73b88e16d",
"0x3e24fcbe6a8d8ba769994150cc7a17dbb38d2248af14bc8328f729f4e01fe173",
"0x8390ef908e1dd84308347bdecd7f7e1f176551e291c6b8851c1f90d0ee4d87a3",
"0x016143668addb39c55a8c5397cf097567faeec1787643a89f8feaf817ea10d5b",
"0xde78935eace5f67e88d141d650c35b2b0c5144b12833a3c4bb64441aca1afc23",
"0x129345fd67f04b97d9e76fc9758c80b0616a68710f51decc61f85fed9250396a",
"0xcf6625191fe20056831cfa3839cd3f8fe60d17e6e4248dc46ecd35401986770a",
"0xda56c24559455221d6e465dc3385bb8fe8b547f96952e07647e46e10127873fb",
"0x85045ce82b529f7055bb8496f4084283edc86b6b79f0f1fa060ed9050419c542",
"0x4b94dbf2a96a4749a04d47fe563644b7f396f4c81753d8ec3a70e5065df0a3b9",
"0x4b025b46575b54136db392c9075b5973a421fb521ab37d8760a04f90b4f8526b",
"0xcfdf125601a1939cca129c4d38dc89a6157cf0a51400bfd8cbc1ea9a3ac5e859",
"0xbb9b417a9d9c975a1707778fa83950a2a6f6c7c20620e623e913509cc256c26c",
"0xc2dc9b5d9413508462391fbac33d1d4ac2fc4b3167d152d0888c5ef9b18a9bf8",
"0x918d35dede6db7175e5a11d9c26ed38fe8198da231d3955b1eee020ad32fa3d3",
"0x12515f32629d7e71e2f1ef0de1a08ab2ed2cf9cb2ffea11aeab06e7dab64eec8",
"0x3484f89e98c0436f603319b8c5d5e324f3e2cb6995be3334641e14a21e998b21",
"0xb045c079ca13a4a6760bae38dccad8b35503437c4643b1180f99b2bef15b9eff",
"0xf81cb06b474d642ef15ae0382f3d792071862d4a00a967ed352fcf5fc55529b0",
"0x2edc394894bdc21c9827c789cd1f1226459e5489f7a87dd941efdcee56d0be78",
"0x7a1993168a29b0869fbb337144031dd0bc47520ab9498c9065b71fc90a100294",
"0x1963f11d488f5db4ea7f6e99b0bfe5006702e911930a7a95fab8a45ea1c4c955",
"0x7e12d33b54970a2fba8539d57c02b8318fab2f22ceb8b0ef69b6cc9ccfbd0658",
"0x32655b99bb59604c91af6270b15834688de512ca3088544785c0f0304d1faa20",
"0xec8984da3bc415604c9facb5cec0238f162b3da22fc4d20bcfed387c647728fe",
"0x7ba1756f8fa6637d8cb6cc588a679f6366827bc2044865744837c63e8a5aadcc",
"0xfc1a94a88f1e52bb78a0862eea4b996444f0264a3b301c1a31e59744d0216de8",
"0x79472bc4de84a0c430f15bcf8569486cddd2de985409ceb8e48abec8aa3e3fe7",
"0x02bc578dcc715304c651a43d8dcb4a761d2073a93cca2c39da3ee513f0c6d415"
"0x9ab1411e7ef5b295ab1a9dfe4ee1cd1a740af5b7e4b0a0e9c4a5f37e803c7c94"
]
},
"accounts": {
@@ -5267,8 +5015,8 @@
"nodes": [
"enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303",
"enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303",
"enode://38e6e7fd416293ed120d567a2675fe078c0205ab0671abf16982ce969823bd1f3443d590c18b321dfae7dcbe1f6ba98ef8702f255c3c9822a188abb82c53adca@51.77.66.187:30303",
"enode://6f289111f7c77c68651b0f4803c3a47bcec801f9c618bb41231a1a24a6dbb9c76f2fdb63ba7a21357c41ebb7f6922c17397c1b5c8f71f7d3ef7965505d4945de@144.217.72.209:30303",
"enode://b6340eb94c3db1362ee517801389fe21cce6354275376b1006f8ce84f8a5cfa2b836268b3727be9db7cd3e581f356f39da39418c4ec1d63d959abc235d99cd86@145.239.7.213:30303"
"enode://8fa162563a8e5a05eef3e1cd5abc5828c71344f7277bb788a395cce4a0e30baf2b34b92fe0b2dbbba2313ee40236bae2aab3c9811941b9f5a7e8e90aaa27ecba@52.165.239.18:30303",
"enode://7e2e7f00784f516939f94e22bdc6cf96153603ca2b5df1c7cc0f90a38e7a2f218ffb1c05b156835e8b49086d11fdd1b3e2965be16baa55204167aa9bf536a4d9@52.243.47.56:30303",
"enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303"
]
}

View File

@@ -62,8 +62,8 @@
"gasLimit": "0x1000000"
},
"hardcodedSync": {
"header": "f90217a058893ba2a7f3d1625239b0ffab5b58219412b5fb51a608fc6ae7ff012496db9ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942b126e450158f14add6770739a2e6b4037526817a0a46d5b8474c625b4efd3d1d2864d7790770737587aa926fb223945d55a1d0da8a04ff0c821428157d6a4ace26e17d775eac4f42cc7d777898ded413780207fda11a0777f1c1c378807634128348e4f0eeca6a0e7f516ea411690ca04266323f671a4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000844737e14e834dd801837a1200830186a0845c76311499d883010816846765746888676f312e31312e35856c696e7578a0676e77abeb493056c28a2d8fcd1238da73a29c9d915441fd8b5e36f6e910fa5d8803afeb22c339444f",
"totalDifficulty": "18334236703652990",
"header": "f90218a00379bed5cf7fb318965ec9b496aadc573fb78d1570ad2c43703c72e6c6ed997aa0b86c16b5c12556b0ea79b4d52ec77e3a3362ef43eeea51b594afc53c4b0ac115942450ec589db090d88e8de36c1790ca309841181da06183029c4e9e730abd17f5ea5427b626ed83796cab9bb4f28444cb7ab159f8f2a00ef00ef22f20f7d802cbede6ed8ff42d62671a7c07af9496e14710d7e63bbb9ea0a0e273f9d56a2ad827fb338fc0a109c28c0eee076d01454b76d42c99f8c54168b90100000c0002000000000000000000000400000000000000000000002000080000000008800010000000000000000000000002100000000000000000000020000000000000000000420000000008002000000000000000000000800001100000200004000000000000000000000008000000000000000000000000020010000000000000010000000010000040000000000000000020000000000000000028000018000000000000000000002000008000000800000000004000000000000000000000000002000009000000000810000000000040000000000000200100000000040000000000000000000200200000000000000000000000000000000000200000844af3d7d883486001837a120083146f76845c2c29239ad983010814846765746888676f312e31312e348664617277696ea071764589dfd7ecd322aee118da27aa747da4f5d14c1a5951f9b3a297d47a031888ba12cdb8daaeae57",
"totalDifficulty": "17277173430188370",
"CHTs": [
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
@@ -2380,182 +2380,7 @@
"0x12cf00d3b11cbfaf2038ca1e9de63e4dff65a3352da5824043978ba8fe7e08cf",
"0xd64011bda551b01b0b33e1065b0069fd1fe103e2e68c50fc5bdf1f99b4ab5e0f",
"0x3e3bef8f3d76d1f410327cfd8f4453e0fb9ed392da173e26ffaaed662411f7af",
"0x435816db536c536e0470a3fbfa32fcd6adab877831ffa66417e19bfaa2c9c62b",
"0x19d27119d0c702eb7735d70b30c26567d6ae4c5d204870a036f2273f027a80a9",
"0xd48c41e8365e9872d953b89e2b3dd0fa762b3360958ec9928124f54c79df5f19",
"0x7da805659d8b9e3f6b14aab3a5bd8d25e9d2d960076b4baf6c394a02fc763d12",
"0x5491cc6940517e3a790bf6e32437537e0241c9fcb3302a3bf94133ceb65b8862",
"0x0568a4d9b4e91fd1046fda2cb8a718ba57ba1526610013f465be7777e94356c1",
"0x0831b1ce49717503b49502ffe6b854ab2eb2c4db30f5ea5033c011f5e5e3d309",
"0xabd50d7ea56144421474763563ecdb591ec1df8645ccba4e28990d8b9b8ed16e",
"0xfe4ceb9425449bde581ef04b46c1fc7bdbd8f422c43d64b2d1bbbe3ff4dd7a26",
"0x489137c52ef8c71e620220d8e9e842c2a5befa812b70b0a709ab4603a729047d",
"0x8fa480e08230c6b9d964bca0bc5d5a246e4eac6c8d45c75a4cfac8c4601f455d",
"0xe5cde020c71c0ad3e7f9a789247e5518bc1b824b4c6297e12d09a42e265e4bef",
"0xd4c0b9e39b70ef4f229884817c317f20f53386969f8c1e2ddc69cfa57b1014f9",
"0x75b91e206eb0a2fa7752da4d6421fc294a4cd7d6d06dbdeb7b7df50e157ae99e",
"0xa650044c8fb1c0d98b1e671d576f389b0b7be37e946b7623ff6203ca72c574aa",
"0xe6dd07898de5688be966dbc612764a9956ef1105a7a02695ea269b6e40ccb077",
"0xd1c7d40ae3558d4b42cbf6bce332e718ed8f9b7026b81195beea713ea9fe81da",
"0xdfd6c816adcdd1a588db0bbb4c09050527a107bcc47d76be91c7e309a54dec92",
"0xa67e60d39fad4b6389908ced2c0b6fc4d0b1ae78379de0452963589cde410618",
"0x88a629bbfd9f5ec014580d47210562cc0ba162fc2e7f609dcc34babef9d2f89a",
"0x685dcd734516a666b7e9018a420cc1ed6f1cd13d13f54dc782d3d2529bafd375",
"0x00adf1bec319f440e54009e1ffc45d58f38a120644a111239aef09d1f91c20ed",
"0x0ec349f19c0374334a6f9463b349e97c6a6696984c7779cf29bf048a6317224e",
"0x0f190a67c3804e6aa618106b554578687d0f3983c8350709362fb7e4728adace",
"0x7af75c91424ed2a01f0b796ea4772780395cf77d4051c91552fcb962a384a04c",
"0xa43e2914fa364effea580b8d8ae6d7c5480acf7b9330b226438c12fb5e478ea2",
"0x38deda38720cb7918d43b4b7296fa0168d77ffefee1217bbe198b382fefade22",
"0x40e97169e2871117267eedd1095f76d97719f6e9dec56b3423a9258bb09815d7",
"0x3368d112a868cabf7d21ea1c5c851fe0a37551c03d72cfd6b235e3a904eb5889",
"0xaa25f4d9f97ca1cdbda79c61f1ab84883a037eed60d9ec2301cdd5c404c9805b",
"0x21132089753a085a0a982388817137c591a9a34d2cd9e6651c57c76a8b80b716",
"0xdf0c2df6ca5680424ac369b411ce78031614632c5fe44e2d8af1ddac30cd729a",
"0x4f55598eecadc5136e90d15fcb9f87e1eec65ce18121127b49cd159c69c94098",
"0x8a6b7276e3def38187b0cf9156aec251bab76637505f97583dc4d426ec86be50",
"0xe8a516509c5bcb7e81372ce88f7d51982e092ea93f895e5dc666ddaea58edd54",
"0x3edb18c971bd2f867ab6dbb3d63228aa94ed0d0eb9f603af71ebfb201095b836",
"0x0e7de89c28113289c1f84ed91c289328b9cac13495b289ce11cd1c5942be1188",
"0x2610da85e8fb400db625442fecb8cbe20435e8736fedf3bbf715501697ae6be0",
"0x5668c3a61683c91b17467e48b2f27c7e377010eaee64c69d53ecb1ab89dee1e1",
"0x58bb1cf79609e7223f1883dcc6d80538e278e514b1e11c6c2871db55dcdd9914",
"0xfd8faec518007958057845c7b9f204c8dd473db5dc19ad5f2460802b1fae2693",
"0x304b287a3513bf02a35fa61a8cb6aeb214d453d9d53213f458c207d2e15a537e",
"0x7b8f9c4775a775637d9e3274068df7c5330096a52750d604e6f3818c4a7f0b15",
"0xaac892295bff6dc1d99e51a4114857a5fffbc3c8b2b24bd057156c91a5e3bf7a",
"0x34266cdb180c5227ebae64b8ddbecec44a6144214b9412d723924a92fb4a93c4",
"0x1ed56966b89b57904056fcec5d2a23ca5a5d809a7f5c889c5123e3994d660398",
"0xb44dde8ad3b29068b5d3b3551bef7082d8f09366ac622e57f6b494bd594c7a03",
"0xabebaf98aa2e70020b83e45d5ab56164dcc58a4493264cdd6dfff3e921b395aa",
"0xdf26e98e5499f58665912d987eaebe8234eec92c9cb4e788b274b9e9cc8b527d",
"0xdb1f809c70c5633bac0f1642ad929984ff56154b16e0d81b8fa6b10706336c3e",
"0xecc6cfaadef8dab02149f15d1f39932e53b3fcf25fdb1d0379ef9b933222c018",
"0x17351e250078e53f17a144aad0933172ddc648a8f2fc530f0d4468623328b43a",
"0xb832ca94746ea0be489afd60548e74d654278b8a08bffdda83f87e58459769c8",
"0xbe1d486c25ec6042a110acb68d2fb9daeafb830f1d739506213b5a0de51887b5",
"0x560e8231a58aa914a6b82977734a8ce364d970af688f014e8957933ca3026d66",
"0x76b6b1959f5e0579fef78f6549b171028811c2fd64265bafd701e0a2de9d64b4",
"0xba8ee49b308ea0c0475cd30b90252f4909063b86119e4d1cd53dcf6b4671b0bb",
"0x168bfb6c2fd68fd7194561d6b0f6f76e733dfa092d550de243a2a7c0e6b14fa0",
"0x8d5dbd6b82c31c1237d84256a837ff86e005033d83622531bb00de243da0e5f4",
"0xd12f68a021b6f806c9d75468486f2c4fbad295ec51c0f507c445fc535a0caa81",
"0xdbe40f0f8ee88a80512e2f9162776abf02218c6dfb61a36042ba973ab55aad3a",
"0x6cf853351f1371aacafc02da272b304b246176c2867377185b349c5f5880257f",
"0x3f37a65caa18187a3552e300aab18b27d4a2b2a25c049f29e5d8d7a2c57af78f",
"0xad59d1d4be0ce243a38e94ffee6b21fe073b28b0bee9b0249f560219e9bf604d",
"0xe28ca7ade73017341acecc09a647c6c0e638f6ebdf1566b534dd27d5e9ad67ce",
"0xe3577a39c6d3670d2fcee9f36bfb4e79bcbea5695013ae037a7a7b4c5302979a",
"0x56a8566c6bb04d61331e9950a97248e152742d6f0408a77258c102efde79a0bd",
"0xf199dbb8b24df16441c45f5db31af6597172dcff5bcb84306a3f8ee9e7ebdea1",
"0x85a9e253bae3c1c5064f320911e7f964c7315602e83374f5df7ba532cd2acefc",
"0x80ce75ad1b2de3054cc12adc1774ef8e37f3123387d06daeb545953b7a2bb044",
"0xb26d9c8ece65562068826bc872a6fd93e76634b8b7b598769d3df142ed5d17d2",
"0xa43a1662961c4bd1bfa93fdf911067aca94460c733f5a9e296f9e47740b6f8a2",
"0xf84716d76638301b784430585722e4c112375a69329ac03fb8e98882fbbd2fb3",
"0xbdb1551fc7d0e24f2096586ea482b83b8603db1642ba6aa12d8369214af5e4c4",
"0x8f8f8de670e0dc95346e2b14b82bf8a63d9a2a4eca385b1fafc19964cf98f710",
"0x6d3f91249ce7f7f852a4ffab23b7e949117df088f2e2aa3db0fb386755a16c92",
"0xeb9c005485707baed2b7ab034e68597bb8be65bd6f8283b690cd338bf7d1826b",
"0xcaa884959fbea1f5110d7cc4360c24b2ede43d32f8cba522d28946ffd2d900fa",
"0xa561dbe805f8ba3cb6d3d1524c4b3bcbc95ac330e6d71d33642412f8f0a1a2a3",
"0xf158b9329dbbb90083c88982656840cb134713ba122e7e39b287bca4b0605dd4",
"0xee3ce79371c0f0a1ac399a3a722a1c7515f6b02d2e03118e3fb6d521e245ab6e",
"0x1083d6dba68c10cb19935b627e5576b5bc4e7904c8ff59657ced1c8397468017",
"0xa893338e4a49166bd36f4361799c7cccaaee211b512e0c8821136cdb823e8ac8",
"0x1327e2948ee57993f1b721e9fedc8f7d2e91f041b3e01340375bcbbdead83bfc",
"0x6bc88c663e475911e9fbdfb9a33931c34bcfff5e533e82059d33cd69ee414d94",
"0x81d95020affda45f536e01b1a4b840eb72afe2e82633d81de11acdeada45d93b",
"0x91e59cb7e3729c776c4dd441c3377659b37fd881760b9e70c73d5288e99bfa0a",
"0xbf69325ef2072cd5e3d2e93b8e6e2abbaa03434212e1ba4d36459a0f064a64ba",
"0x11f4a2d21c3145af81ba0edb80a9c27cf1e2d53b1a43a42b58b49d4340ce4fa2",
"0x8c366dac642346ca05e2fc047999f9adcab3b8166482854b06c77c2439e0655d",
"0xdcae4952619f997d791aa6a973f1c8c1d3a0c21859b0c37bec64533a6f7c0630",
"0x5300c16e42bf43e34c9e59fc5748c3e05d38437943956eb80ae91cebb4e33d87",
"0x40ec29594f14d9d9a76b13342face2565914b050cc5e5eb96299c51ec92a529d",
"0xa7da6ccf5a72ad5b8cfb6d00aed5f9f7e2bd70670c57873735ce976249fdd5d9",
"0x177a1ca473ae2fb06ed39e180567da24fd14faffa062edbdcb0cffe4520045b9",
"0xea7c63d98ea30c23e0f4df53566214eda57c96f9449aab5a02c165ddb8e61bd7",
"0x6bf4bac02febf1f9459a433d08b373143f44c0beabd3f7bce4218259e8d91311",
"0x6883559d2ed97c78d0aea12c0d14f0dbc911db36a3bd9e3f8a7142e1083e118f",
"0x999416083ffc7371c9b95b6d1bea32da9c2b00827e1f0e1f615354dfe76dd5aa",
"0x82873c88efa3041aae1d36c2a787e592a7af56c3d86f321b1dc619b974c88ff6",
"0x6bfb4371b0a7b9eb9e3fb1f6987854d6e4210286b98bf8dfe6f71f12014ffe59",
"0x5502ec7d23c5559afca6ac2d6178c1f2c778e4dca22a6bc8b16619082cafdc00",
"0x97307b650b949382bc80b6ea446b629c0fbd37bb65a36ac1b33b1e4ac310c056",
"0xe33b1569d06b2b5d05065c11a0dc4f22d214a7a4e4003c1888f7469094330a8d",
"0x691870ffdeabba194cbc10492332d51702d75c40681662fcbd5489753bd5fcaf",
"0xd9676a94b8e3eeac02389ca8c0a6d730e2718c0cfc3a5bab3110aa170d64bbf5",
"0xf558d9d27beca0657bd8ca7e82d1788b1777dbe06b474b7598acdfd46e8030cf",
"0x381d766d66669a50d13a141535c441887cad897984d7b2bd52e9bf33c385669c",
"0xacbc99a6cf54ca6fcc9ad8f844f8bbd7639791b663956cda2ac59fed34027024",
"0x04e5b5dfedaa9369bed72fe0ce827e3c16e7a07a274661d76ec92347baa8deda",
"0x2a905b1aa12a30fb04f56b2d9a26a38ce10cc2e9dc910f213ec3c6b368b15bf0",
"0x0f40416a8bc6d699c404972d27c9b69093b387a78f22295cb0a6001cd437a4fa",
"0x05a52a1501ff0d2c044f0c1932e5eb217aa734cabd527d865796fdd120fd8856",
"0x36c70cc55f4b571882ecab711522e4bffd3ae8f6873d940a0e4626ade7797612",
"0x4a7af1b12b32d3bb38ec4aa0cda6535cd96043466a56f0641253c7b21abe9205",
"0xf637f992df45cd4b58d2db4d5c8360a65cf05a11f14dba70638e50b5bf70bff4",
"0x5b271fd0d5a0adaa16218fab9f75e0599d85c093233761a76c03ba060d5b7948",
"0x8e3554617c506afbd2eed41a4c8e2ecc1bf619b163843a983411c884e5b07320",
"0x96c35e763be9f9a95f76c81fbe1659d22715f5cdc0cb36c168c67a1062818914",
"0x1d1235e2789d0d283a3d4c06e391a1e38869c788255facbaca7e23c4e76e5ba4",
"0x25246df476679b7364020ebe600ff596b6eb17b23c68ab05885a02616bd2e5f5",
"0x0a516b13c9e864bcaabf531c43ed3ca725d4521c9d34ee08280fd13500cdcfb5",
"0x15b0defb12ba7d05f4c5b387efbcf5eb41e325ece9a0b83619a5b7e19283b677",
"0x5000d5c4cad2ef87de73eb2f10d6733a840d069200cb30d4221031381e8c8f36",
"0x15e98f25d14ef227fbca0b760e2d436e291d3668498f486611a6a3118f5a8556",
"0xdc0d786b90d673f30f84706d29643bf0c392464f30ea66052b153ec28ee4b7cb",
"0xe4da2a6b7a254b85df06dbe8f2bf24b4ca3ef6d5c3b0fc8c17e0ebd32d5d69ac",
"0xe2e6fe80f327eded1c263684cbc525e27839bc816b237588b902c66623c38eb7",
"0x1b8c963829103769fab68bdf45dfe4d6130abc9560590871665f23b190e959e6",
"0x5d2e7cb7a42acaadbc832fb8974756f9473b18263ea50aa281fbcfe217a15762",
"0xcf46e1381d84a33aa488d4674b3ac43a1b6afb102c7a425fcc1447769ef5e6f9",
"0x00532839fe3e0691e406d230c8d384b6bc562923048ea0d89f1be054252eee58",
"0xa68d5545328145a3dabe1b143a57a13057d14866c6b9c9da8b4781f4efed4945",
"0x5223699aa191c964875eb16507aacefde636e88c0f0093d92bc38be221fb3792",
"0xa9b807ba38a8434b3befcc91f6b93427dc81f365354f62d5ee69730e319ce5d9",
"0xfd0dd9977372d780c38981010a339dd6552e8f81fc7654362590e7c6b9fd1f6f",
"0xca3900d2a87a6e0b04d679bb87dc81bd1ac11e79e4f0355e314c7e41d76de4e3",
"0x78ee224a33ce3b2629f7640392846f17c228288b89d6c2d9db42726cf64225cb",
"0x48a4acdd0758838c9ce2b322bc77459c1cc0fdca3d588d60697c8a5aa3035273",
"0x6eb8aeeda5a4b26e73ac2bd7f838c974b5bc45de138d14ba58b51bfb6d51cf93",
"0xd6895877c885791db924b0ab1a1d666c06a10e6d210e02cf9c2f29726d3c565b",
"0xcffa80c70e6246e7b17173c071384a7b46dfdd5ab4b4b524c88871ca02c7e658",
"0xbf64411370653f8e08373438b03ccff7fc6ae1d70385cd26a7e73b57da07dd75",
"0xd9a39f3b774d208608c7d1d9d1fcdacf0c0ff6e8cb7915bca57e8056a8b914c9",
"0xd6a1f8fae6440d4ba8b2e392dbd07f6dd6290651a221b3749cd2dd6b0f39ba0c",
"0xa1ad925960651423f598ab111a0f2bcc5d3fc7f62fc72eb2753815277183a4ac",
"0xf3f6feaa55dcb3eb9c572404a0da1cf7dbb53983a98873b3f0398aad91773b69",
"0xdb902ac0d33bba7b0bcfbbe3b5533b970d07381fb00a973b4dd92c8f7af7bcb8",
"0x5f97ac6dd3f55bbf179eafc50c64042f2daccfcb3bae9c4305045b709cf19ae2",
"0x7061adfb4514170759ff4ddf3922b10f2c85c1a65c361936e504ec77df84b703",
"0x07ae6b39e66142978d35c4c2a517c55c23ec47ae341557e8cbe8a0d001df0f6f",
"0x0e6b9fc3fec4e75d812128fbbae0946dc48b511b198a5301833992e763423da3",
"0x7e1da14382f9908299fe46dedaf1878a6d01e9070554f1436514d320e0a4ebc8",
"0xdb6cdc7239c51386bb9eb371765cccb84e4e4de38acc5ad7e5503bd0f60a31a4",
"0xcd0069c9fb9ba8d136a2020580827799eac95f613f7b75bce8322fe67ecdc2e0",
"0x06932b0dc851ffb7ce68ed9083cecb5ba074716f188c5bb4df94de8e7e057046",
"0x3a2e83e02240263c4e416898f9d54bd0b579ddb0076537b58c47c3a17df15208",
"0x61b166d6dee81bdf6d101f23bf8ca40b74c2eb3f47561b4ef024d30f410f88a7",
"0x7a9e85a9000cb7308a5c57c7b1421b22f63e64f48630a79e449e7a207cf586a1",
"0xd573fcbaafb3882fdb1985c1b939961d35dd7bcbd5865be82276d0cea1afc7a8",
"0x697152abd7502169e0d801346a41c815d8bd8e75e55845d4a4b251def64a9583",
"0x77e5cfae8dc5913c4bbd4f4d84a797bf8919a0c21a4eab4f5dfb42fe8c5019d3",
"0x6e7af8bd163f679b81489d3ec3cc4948cc57ccb3e0c8cbc80e387783bb87641d",
"0x4bd5ece25cfda291179b8977a84369ab1590c9d4d5b45a24865ca010e5ffa676",
"0x6331f61c715be1fe8e0c90740cb89c0a7cee24524be2258ad49542959f845477",
"0x0af729bb18715399a1b07ffe2e0d562f71c27ee2bc01921c25327d421165bef7",
"0x98ee97e5bbeaa0715143a39f38ac56736f54fe5b971584b4061c58721c051a3f",
"0xd06e19176339b1fb5cf469b1f0ee4350a416d20aaa9c1be50bdd26687b2424bc",
"0x2385cde28be71e40f64ba5db5bd1a8e5f4b767a9a17c21a96fd2642ead428394",
"0x3d2ef2f0e4bae5c2ca6fb9fcfa1a9ffc435471a7a533b3b7df2b28402d335f58",
"0x2ecc6ed70661e692248c80735650c253dfe6b3c2213bfc259ebc70c898ee8e6e",
"0x8a68b3eb663796ca2189e49b9fe5902e36615d03d28ac34c01f63a135b930f0b",
"0x563d7efb4175fc12dab431175b5097186c2379a5aca1901e39d641d02865d426",
"0x1a55cf9842f9008e0730ae9fc6af9f288edba323803d0ae787fc0fdda99be8c9",
"0xccdf47cee7142cad27bbf224f0afd1a6e5178345cab510f2f8ee27115ab27ff7",
"0xc5b3582937ad993c5c234d059e6cd3b98f2fa4e3fe4ad591ecb6ae710b51fee9"
"0x435816db536c536e0470a3fbfa32fcd6adab877831ffa66417e19bfaa2c9c62b"
]
},
"nodes": [

View File

@@ -1,65 +0,0 @@
{
"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

@@ -32,8 +32,9 @@ use ethcore::miner::Miner;
use ethcore::snapshot::service::{Service as SnapshotService, ServiceParams as SnapServiceParams};
use ethcore::snapshot::{SnapshotService as _SnapshotService, RestorationStatus};
use ethcore::spec::Spec;
use ethcore::account_provider::AccountProvider;
use ethcore_private_tx::{self, Importer, Signer};
use ethcore_private_tx::{self, Importer};
use Error;
pub struct PrivateTxService {
@@ -95,10 +96,9 @@ impl ClientService {
restoration_db_handler: Box<BlockChainDBHandler>,
_ipc_path: &Path,
miner: Arc<Miner>,
signer: Arc<Signer>,
account_provider: Arc<AccountProvider>,
encryptor: Box<ethcore_private_tx::Encryptor>,
private_tx_conf: ethcore_private_tx::ProviderConfig,
private_encryptor_conf: ethcore_private_tx::EncryptorConfig,
) -> Result<ClientService, Error>
{
let io_service = IoService::<ClientIoMessage>::start()?;
@@ -127,18 +127,13 @@ impl ClientService {
};
let snapshot = Arc::new(SnapshotService::new(snapshot_params)?);
let private_keys = Arc::new(ethcore_private_tx::SecretStoreKeys::new(
client.clone(),
private_encryptor_conf.key_server_account,
));
let provider = Arc::new(ethcore_private_tx::Provider::new(
client.clone(),
miner,
signer,
encryptor,
private_tx_conf,
io_service.channel(),
private_keys,
client.clone(),
miner,
account_provider,
encryptor,
private_tx_conf,
io_service.channel(),
));
let private_tx = Arc::new(PrivateTxService::new(provider));
@@ -281,6 +276,7 @@ mod tests {
use tempdir::TempDir;
use ethcore_db::NUM_COLUMNS;
use ethcore::account_provider::AccountProvider;
use ethcore::client::ClientConfig;
use ethcore::miner::Miner;
use ethcore::spec::Spec;
@@ -315,10 +311,9 @@ mod tests {
restoration_db_handler,
tempdir.path(),
Arc::new(Miner::new_for_tests(&spec, None)),
Arc::new(ethcore_private_tx::DummySigner),
Arc::new(AccountProvider::transient_provider()),
Box::new(ethcore_private_tx::NoopEncryptor),
Default::default(),
Default::default(),
);
assert!(service.is_ok());
drop(service.unwrap());

View File

@@ -17,10 +17,11 @@
//! DB backend wrapper for Account trie
use ethereum_types::H256;
use hash::{KECCAK_NULL_RLP, keccak};
use hash_db::{HashDB, AsHashDB};
use hashdb::{HashDB, AsHashDB};
use keccak_hasher::KeccakHasher;
use kvdb::DBValue;
use rlp::NULL_RLP;
use std::collections::HashMap;
#[cfg(test)]
use ethereum_types::Address;
@@ -98,11 +99,15 @@ impl<'db> AccountDB<'db> {
}
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDB<'db> {
fn as_hash_db(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hash_db_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDB<'db> {
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
fn get(&self, key: &H256) -> Option<DBValue> {
if key == &KECCAK_NULL_RLP {
return Some(DBValue::from_slice(&NULL_RLP));
@@ -158,6 +163,10 @@ impl<'db> AccountDBMut<'db> {
}
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDBMut<'db>{
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
fn get(&self, key: &H256) -> Option<DBValue> {
if key == &KECCAK_NULL_RLP {
return Some(DBValue::from_slice(&NULL_RLP));
@@ -200,18 +209,22 @@ impl<'db> HashDB<KeccakHasher, DBValue> for AccountDBMut<'db>{
}
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDBMut<'db> {
fn as_hash_db(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hash_db_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
struct Wrapping<'db>(&'db HashDB<KeccakHasher, DBValue>);
impl<'db> AsHashDB<KeccakHasher, DBValue> for Wrapping<'db> {
fn as_hash_db(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hash_db_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher, DBValue> for Wrapping<'db> {
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
fn get(&self, key: &H256) -> Option<DBValue> {
if key == &KECCAK_NULL_RLP {
return Some(DBValue::from_slice(&NULL_RLP));
@@ -241,11 +254,15 @@ impl<'db> HashDB<KeccakHasher, DBValue> for Wrapping<'db> {
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher, DBValue>);
impl<'db> AsHashDB<KeccakHasher, DBValue> for WrappingMut<'db> {
fn as_hash_db(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hash_db_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher, DBValue> for WrappingMut<'db>{
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
fn get(&self, key: &H256) -> Option<DBValue> {
if key == &KECCAK_NULL_RLP {
return Some(DBValue::from_slice(&NULL_RLP));

View File

@@ -14,55 +14,94 @@
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
#![warn(missing_docs)]
//! Account management.
mod account_data;
mod error;
mod stores;
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
extern crate fake_hardware_wallet as hardware_wallet;
use self::account_data::{Unlock, AccountData};
use self::stores::AddressBook;
use std::collections::HashMap;
use std::fmt;
use std::time::{Instant, Duration};
use common_types::transaction::{Action, Transaction};
use ethkey::{Address, Message, Public, Secret, Password, Random, Generator};
use ethstore::accounts_dir::MemoryDirectory;
use ethstore::ethkey::{Address, Message, Public, Secret, Password, Random, Generator};
use ethjson::misc::AccountMeta;
use ethstore::{
SimpleSecretStore, SecretStore, EthStore, EthMultiStore,
SimpleSecretStore, SecretStore, Error as SSError, EthStore, EthMultiStore,
random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret,
};
use log::{warn, debug};
use parking_lot::RwLock;
use types::transaction::{Action, Transaction};
pub use ethkey::Signature;
pub use ethstore::{Derivation, IndexDerivation, KeyFile, Error};
pub use ethstore::ethkey::Signature;
pub use ethstore::{Derivation, IndexDerivation, KeyFile};
pub use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo};
pub use self::account_data::AccountMeta;
pub use self::error::SignError;
/// Type of unlock.
#[derive(Clone, PartialEq)]
enum Unlock {
/// If account is unlocked temporarily, it should be locked after first usage.
OneTime,
/// Account unlocked permanently can always sign message.
/// Use with caution.
Perm,
/// Account unlocked with a timeout
Timed(Instant),
}
/// Data associated with account.
#[derive(Clone)]
struct AccountData {
unlock: Unlock,
password: Password,
}
/// Signing error
#[derive(Debug)]
pub enum SignError {
/// Account is not unlocked
NotUnlocked,
/// Account does not exist.
NotFound,
/// Low-level hardware device error.
Hardware(HardwareError),
/// Low-level error from store
SStore(SSError),
}
impl fmt::Display for SignError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
SignError::NotUnlocked => write!(f, "Account is locked"),
SignError::NotFound => write!(f, "Account does not exist"),
SignError::Hardware(ref e) => write!(f, "{}", e),
SignError::SStore(ref e) => write!(f, "{}", e),
}
}
}
impl From<HardwareError> for SignError {
fn from(e: HardwareError) -> Self {
SignError::Hardware(e)
}
}
impl From<SSError> for SignError {
fn from(e: SSError) -> Self {
SignError::SStore(e)
}
}
/// `AccountProvider` errors.
pub type Error = SSError;
fn transient_sstore() -> EthMultiStore {
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
}
type AccountToken = Password;
/// Account management settings.
#[derive(Debug, Default)]
pub struct AccountProviderSettings {
/// Enable hardware wallet support.
pub enable_hardware_wallets: bool,
/// Use the classic chain key on the hardware wallet.
pub hardware_wallet_classic_key: bool,
/// Store raw account secret when unlocking the account permanently.
pub unlock_keep_secret: bool,
/// Disallowed accounts.
pub blacklisted_accounts: Vec<Address>,
}
/// Account management.
/// Responsible for unlocking accounts.
pub struct AccountProvider {
@@ -85,8 +124,27 @@ pub struct AccountProvider {
blacklisted_accounts: Vec<Address>,
}
fn transient_sstore() -> EthMultiStore {
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
/// Account management settings.
pub struct AccountProviderSettings {
/// Enable hardware wallet support.
pub enable_hardware_wallets: bool,
/// Use the classic chain key on the hardware wallet.
pub hardware_wallet_classic_key: bool,
/// Store raw account secret when unlocking the account permanently.
pub unlock_keep_secret: bool,
/// Disallowed accounts.
pub blacklisted_accounts: Vec<Address>,
}
impl Default for AccountProviderSettings {
fn default() -> Self {
AccountProviderSettings {
enable_hardware_wallets: false,
hardware_wallet_classic_key: false,
unlock_keep_secret: false,
blacklisted_accounts: vec![],
}
}
}
impl AccountProvider {
@@ -163,7 +221,7 @@ impl AccountProvider {
let account = self.sstore.insert_account(SecretVaultRef::Root, secret, password)?;
if self.blacklisted_accounts.contains(&account.address) {
self.sstore.remove_account(&account, password)?;
return Err(Error::InvalidAccount.into());
return Err(SSError::InvalidAccount.into());
}
Ok(account.address)
}
@@ -193,7 +251,7 @@ impl AccountProvider {
let account = self.sstore.import_wallet(SecretVaultRef::Root, json, password, gen_id)?;
if self.blacklisted_accounts.contains(&account.address) {
self.sstore.remove_account(&account, password)?;
return Err(Error::InvalidAccount.into());
return Err(SSError::InvalidAccount.into());
}
Ok(Address::from(account.address).into())
}
@@ -226,7 +284,7 @@ impl AccountProvider {
return Ok(accounts.into_iter().map(|a| a.address).collect());
}
}
Err(Error::Custom("No hardware wallet accounts were found".into()))
Err(SSError::Custom("No hardware wallet accounts were found".into()))
}
/// Get a list of paths to locked hardware wallets
@@ -611,7 +669,7 @@ impl AccountProvider {
mod tests {
use super::{AccountProvider, Unlock};
use std::time::{Duration, Instant};
use ethkey::{Generator, Random, Address};
use ethstore::ethkey::{Generator, Random, Address};
use ethstore::{StoreAccountRef, Derivation};
use ethereum_types::H256;

View File

@@ -20,10 +20,8 @@ use std::{fs, fmt, hash, ops};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use ethkey::Address;
use log::{trace, warn};
use crate::AccountMeta;
use ethstore::ethkey::Address;
use ethjson::misc::AccountMeta;
/// Disk-backed map from Address to String. Uses JSON.
pub struct AddressBook {
@@ -155,8 +153,8 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
mod tests {
use super::AddressBook;
use std::collections::HashMap;
use ethjson::misc::AccountMeta;
use tempdir::TempDir;
use crate::account_data::AccountMeta;
#[test]
fn should_save_and_reload_address_book() {
@@ -165,9 +163,7 @@ mod tests {
b.set_name(1.into(), "One".to_owned());
b.set_meta(1.into(), "{1:1}".to_owned());
let b = AddressBook::new(tempdir.path());
assert_eq!(b.get(), vec![
(1, AccountMeta {name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None})
].into_iter().map(|(a, b)| (a.into(), b)).collect::<HashMap<_, _>>());
assert_eq!(b.get(), hash_map![1.into() => AccountMeta{name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}]);
}
#[test]
@@ -181,9 +177,9 @@ mod tests {
b.remove(2.into());
let b = AddressBook::new(tempdir.path());
assert_eq!(b.get(), vec![
(1, AccountMeta{name: "One".to_owned(), meta: "{}".to_owned(), uuid: None}),
(3, AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}),
].into_iter().map(|(a, b)| (a.into(), b)).collect::<HashMap<_, _>>());
assert_eq!(b.get(), hash_map![
1.into() => AccountMeta{name: "One".to_owned(), meta: "{}".to_owned(), uuid: None},
3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}
]);
}
}

View File

@@ -21,11 +21,9 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::sync::{Arc, Weak};
use std::time::{Instant, Duration};
use blockchain::{BlockReceipts, BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert, BlockNumberKey};
use blockchain::{BlockReceipts, BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert};
use bytes::Bytes;
use call_contract::{CallContract, RegistryInfo};
use ethcore_miner::pool::VerifiedTransaction;
use ethcore_miner::service_transaction_checker::ServiceTransactionChecker;
use ethereum_types::{H256, Address, U256};
use evm::Schedule;
use hash::keccak;
@@ -48,11 +46,11 @@ use vm::{EnvInfo, LastHashes};
use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock};
use client::ancient_import::AncientVerifier;
use client::{
Nonce, Balance, ChainInfo, BlockInfo, TransactionInfo,
ReopenBlock, PrepareOpenBlock, ScheduleInfo, ImportSealedBlock,
Nonce, Balance, ChainInfo, BlockInfo, CallContract, TransactionInfo,
RegistryInfo, ReopenBlock, PrepareOpenBlock, ScheduleInfo, ImportSealedBlock,
BroadcastProposalBlock, ImportBlock, StateOrBlock, StateInfo, StateClient, Call,
AccountData, BlockChain as BlockChainTrait, BlockProducer, SealedBlockImporter,
ClientIoMessage, BlockChainReset
ClientIoMessage,
};
use client::{
BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient,
@@ -61,8 +59,7 @@ use client::{
IoClient, BadBlocks,
};
use client::bad_blocks;
use engines::{EthEngine, EpochTransition, ForkChoice, EngineError};
use engines::epoch::PendingTransition;
use engines::{EthEngine, EpochTransition, ForkChoice};
use error::{
ImportErrorKind, ExecutionError, CallError, BlockError,
QueueError, QueueErrorKind, Error as EthcoreError, EthcoreResult, ErrorKind as EthcoreErrorKind
@@ -80,14 +77,12 @@ use verification::queue::kind::BlockLike;
use verification::queue::kind::blocks::Unverified;
use verification::{PreverifiedBlock, Verifier, BlockQueue};
use verification;
use ansi_term::Colour;
// re-export
pub use types::blockchain_info::BlockChainInfo;
pub use types::block_status::BlockStatus;
pub use blockchain::CacheSize as BlockChainCacheSize;
pub use verification::QueueInfo as BlockQueueInfo;
use db::Writable;
use_contract!(registry, "res/contracts/registrar.json");
@@ -296,8 +291,8 @@ impl Importer {
continue;
}
match self.check_and_lock_block(&bytes, block, client) {
Ok((closed_block, pending)) => {
match self.check_and_lock_block(block, client) {
Ok(closed_block) => {
if self.engine.is_proposal(&header) {
self.block_queue.mark_as_good(&[hash]);
proposed_blocks.push(bytes);
@@ -306,7 +301,7 @@ impl Importer {
let transactions_len = closed_block.transactions().len();
let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client);
let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), client);
import_results.push(route);
client.report.write().accrue_block(&header, transactions_len);
@@ -358,7 +353,7 @@ impl Importer {
imported
}
fn check_and_lock_block(&self, bytes: &[u8], block: PreverifiedBlock, client: &Client) -> EthcoreResult<(LockedBlock, Option<PendingTransition>)> {
fn check_and_lock_block(&self, block: PreverifiedBlock, client: &Client) -> EthcoreResult<LockedBlock> {
let engine = &*self.engine;
let header = block.header.clone();
@@ -442,15 +437,7 @@ impl Importer {
bail!(e);
}
let pending = self.check_epoch_end_signal(
&header,
bytes,
locked_block.receipts(),
locked_block.state().db(),
client
)?;
Ok((locked_block, pending))
Ok(locked_block)
}
/// Import a block with transaction receipts.
@@ -482,8 +469,7 @@ impl Importer {
// it is for reconstructing the state transition.
//
// The header passed is from the original block data and is sealed.
// TODO: should return an error if ImportRoute is none, issue #9910
fn commit_block<B>(&self, block: B, header: &Header, block_data: encoded::Block, pending: Option<PendingTransition>, client: &Client) -> ImportRoute where B: Drain {
fn commit_block<B>(&self, block: B, header: &Header, block_data: encoded::Block, client: &Client) -> ImportRoute where B: Drain {
let hash = &header.hash();
let number = header.number();
let parent = header.parent_hash();
@@ -538,9 +524,15 @@ impl Importer {
// check epoch end signal, potentially generating a proof on the current
// state.
if let Some(pending) = pending {
chain.insert_pending_transition(&mut batch, header.hash(), pending);
}
self.check_epoch_end_signal(
&header,
block_data.raw(),
&receipts,
&state,
&chain,
&mut batch,
client
);
state.journal_under(&mut batch, number, hash).expect("DB commit failed");
@@ -595,8 +587,10 @@ impl Importer {
block_bytes: &[u8],
receipts: &[Receipt],
state_db: &StateDB,
chain: &BlockChain,
batch: &mut DBTransaction,
client: &Client,
) -> EthcoreResult<Option<PendingTransition>> {
) {
use engines::EpochChange;
let hash = header.hash();
@@ -607,6 +601,7 @@ impl Importer {
match self.engine.signals_epoch_end(header, auxiliary) {
EpochChange::Yes(proof) => {
use engines::epoch::PendingTransition;
use engines::Proof;
let proof = match proof {
@@ -624,7 +619,7 @@ impl Importer {
let call = move |addr, data| {
let mut state_db = state_db.boxed_clone();
let backend = ::state::backend::Proving::new(state_db.as_hash_db_mut());
let backend = ::state::backend::Proving::new(state_db.as_hashdb_mut());
let transaction =
client.contract_call_tx(BlockId::Hash(*header.parent_hash()), addr, data);
@@ -643,9 +638,11 @@ impl Importer {
.transact(&transaction, options);
let res = match res {
Err(ExecutionError::Internal(e)) =>
Err(format!("Internal error: {}", e)),
Err(e) => {
trace!(target: "client", "Proved call failed: {}", e);
Err(e.to_string())
Ok((Vec::new(), state.drop().1.extract_proof()))
}
Ok(res) => Ok((res.output, state.drop().1.extract_proof())),
};
@@ -658,7 +655,7 @@ impl Importer {
Err(e) => {
warn!(target: "client", "Failed to generate transition proof for block {}: {}", hash, e);
warn!(target: "client", "Snapshots produced by this client may be incomplete");
return Err(EngineError::FailedSystemCall(e).into())
Vec::new()
}
}
}
@@ -666,13 +663,13 @@ impl Importer {
debug!(target: "client", "Block {} signals epoch end.", hash);
Ok(Some(PendingTransition { proof: proof }))
let pending = PendingTransition { proof: proof };
chain.insert_pending_transition(batch, hash, pending);
},
EpochChange::No => Ok(None),
EpochChange::No => {},
EpochChange::Unsure(_) => {
warn!(target: "client", "Detected invalid engine implementation.");
warn!(target: "client", "Engine claims to require more block data, but everything provided.");
Err(EngineError::InvalidEngine.into())
}
}
}
@@ -1176,7 +1173,7 @@ impl Client {
};
let processing_threads = self.config.snapshot.processing_threads;
snapshot::take_snapshot(&*self.engine, &self.chain.read(), start_hash, db.as_hash_db(), writer, p, processing_threads)?;
snapshot::take_snapshot(&*self.engine, &self.chain.read(), start_hash, db.as_hashdb(), writer, p, processing_threads)?;
Ok(())
}
@@ -1331,48 +1328,6 @@ impl snapshot::DatabaseRestore for Client {
}
}
impl BlockChainReset for Client {
fn reset(&self, num: u32) -> Result<(), String> {
if num as u64 > self.pruning_history() {
return Err("Attempting to reset to block with pruned state".into())
}
let (blocks_to_delete, best_block_hash) = self.chain.read()
.block_headers_from_best_block(num)
.ok_or("Attempted to reset past genesis block")?;
let mut db_transaction = DBTransaction::with_capacity((num + 1) as usize);
for hash in &blocks_to_delete {
db_transaction.delete(::db::COL_HEADERS, &hash.hash());
db_transaction.delete(::db::COL_BODIES, &hash.hash());
db_transaction.delete(::db::COL_EXTRA, &hash.hash());
Writable::delete::<H256, BlockNumberKey>
(&mut db_transaction, ::db::COL_EXTRA, &hash.number());
}
// update the new best block hash
db_transaction.put(::db::COL_EXTRA, b"best", &*best_block_hash);
self.db.read()
.key_value()
.write(db_transaction)
.map_err(|err| format!("could not complete reset operation; io error occured: {}", err))?;
let hashes = blocks_to_delete.iter().map(|b| b.hash()).collect::<Vec<_>>();
info!("Deleting block hashes {}",
Colour::Red
.bold()
.paint(format!("{:#?}", hashes))
);
info!("New best block hash {}", Colour::Green.bold().paint(format!("{:?}", best_block_hash)));
Ok(())
}
}
impl Nonce for Client {
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> {
self.state_at(id).and_then(|s| s.nonce(address).ok())
@@ -1706,17 +1661,15 @@ impl BlockChainClient for Client {
self.config.spec_name.clone()
}
fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> {
fn set_spec_name(&self, new_spec_name: String) {
trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name);
if !self.enabled.load(AtomicOrdering::Relaxed) {
return Err(());
return;
}
if let Some(ref h) = *self.exit_handler.lock() {
(*h)(new_spec_name);
Ok(())
} else {
warn!("Not hypervised; cannot change chain.");
Err(())
}
}
@@ -1783,8 +1736,7 @@ impl BlockChainClient for Client {
};
let (root, db) = state.drop();
let db = &db.as_hash_db();
let trie = match self.factories.trie.readonly(db, &root) {
let trie = match self.factories.trie.readonly(db.as_hashdb(), &root) {
Ok(trie) => trie,
_ => {
trace!(target: "fatdb", "list_accounts: Couldn't open the DB");
@@ -1830,9 +1782,8 @@ impl BlockChainClient for Client {
};
let (_, db) = state.drop();
let account_db = &self.factories.accountdb.readonly(db.as_hash_db(), keccak(account));
let account_db = &account_db.as_hash_db();
let trie = match self.factories.trie.readonly(account_db, &root) {
let account_db = self.factories.accountdb.readonly(db.as_hashdb(), keccak(account));
let trie = match self.factories.trie.readonly(account_db.as_hashdb(), &root) {
Ok(trie) => trie,
_ => {
trace!(target: "fatdb", "list_storage: Couldn't open the DB");
@@ -2159,16 +2110,11 @@ impl BlockChainClient for Client {
fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> {
let authoring_params = self.importer.miner.authoring_params();
let service_transaction_checker = ServiceTransactionChecker::default();
let gas_price = match service_transaction_checker.check_address(self, authoring_params.author) {
Ok(true) => U256::zero(),
_ => self.importer.miner.sensible_gas_price(),
};
let transaction = transaction::Transaction {
nonce: self.latest_nonce(&authoring_params.author),
action: Action::Call(address),
gas: self.importer.miner.sensible_gas_limit(),
gas_price,
gas_price: self.importer.miner.sensible_gas_price(),
value: U256::zero(),
data: data,
};
@@ -2382,20 +2328,7 @@ impl ImportSealedBlock for Client {
let block_data = block.rlp_bytes();
let pending = self.importer.check_epoch_end_signal(
&header,
&block_data,
block.receipts(),
block.state().db(),
self
)?;
let route = self.importer.commit_block(
block,
&header,
encoded::Block::new(block_data),
pending,
self
);
let route = self.importer.commit_block(block, &header, encoded::Block::new(block_data), self);
trace!(target: "client", "Imported sealed block #{} ({})", header.number(), hash);
self.state_db.write().sync_cache(&route.enacted, &route.retracted, false);
route
@@ -2503,7 +2436,7 @@ impl ProvingBlockChainClient for Client {
let mut jdb = self.state_db.read().journal_db().boxed_clone();
state::prove_transaction_virtual(
jdb.as_hash_db_mut(),
jdb.as_hashdb_mut(),
header.state_root().clone(),
&transaction,
self.engine.machine(),

View File

@@ -93,7 +93,6 @@ 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

@@ -36,9 +36,8 @@ pub use self::io_message::ClientIoMessage;
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
pub use self::chain_notify::{ChainNotify, NewBlocks, ChainRoute, ChainRouteType, ChainMessageType};
pub use self::traits::{
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, TransactionInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock,
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock,
StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, BadBlocks,
BlockChainReset
};
pub use state::StateInfo;
pub use self::traits::{BlockChainClient, EngineClient, ProvingBlockChainClient, IoClient};

View File

@@ -49,9 +49,8 @@ use types::views::BlockView;
use vm::Schedule;
use block::{OpenBlock, SealedBlock, ClosedBlock};
use call_contract::{CallContract, RegistryInfo};
use client::{
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, TransactionInfo,
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, CallContract, TransactionInfo, RegistryInfo,
PrepareOpenBlock, BlockChainClient, BlockChainInfo, BlockStatus, BlockId, Mode,
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics,
ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock,
@@ -863,7 +862,7 @@ impl BlockChainClient for TestBlockChainClient {
fn spec_name(&self) -> String { "foundation".into() }
fn set_spec_name(&self, _: String) -> Result<(), ()> { unimplemented!(); }
fn set_spec_name(&self, _: String) { unimplemented!(); }
fn disable(&self) { self.disabled.store(true, AtomicOrder::Relaxed); }

View File

@@ -19,7 +19,6 @@ use std::sync::Arc;
use blockchain::{BlockReceipts, TreeRoute};
use bytes::Bytes;
use call_contract::{CallContract, RegistryInfo};
use ethcore_miner::pool::VerifiedTransaction;
use ethereum_types::{H256, U256, Address};
use evm::Schedule;
@@ -158,6 +157,12 @@ pub trait StateClient {
/// Provides various blockchain information, like block header, chain state etc.
pub trait BlockChain: ChainInfo + BlockInfo + TransactionInfo {}
/// Provides information on a blockchain service and it's registry
pub trait RegistryInfo {
/// Get the address of a particular blockchain service, if available.
fn registry_address(&self, name: String, block: BlockId) -> Option<Address>;
}
// FIXME Why these methods belong to BlockChainClient and not MiningBlockChainClient?
/// Provides methods to import block into blockchain
pub trait ImportBlock {
@@ -165,6 +170,12 @@ pub trait ImportBlock {
fn import_block(&self, block: Unverified) -> EthcoreResult<H256>;
}
/// Provides `call_contract` method
pub trait CallContract {
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
}
/// Provides `call` and `call_many` methods
pub trait Call {
/// Type representing chain state
@@ -360,7 +371,7 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
fn spec_name(&self) -> String;
/// Set the chain via a spec name.
fn set_spec_name(&self, spec_name: String) -> Result<(), ()>;
fn set_spec_name(&self, spec_name: String);
/// Disable the client from importing blocks. This cannot be undone in this session and indicates
/// that a subsystem has reason to believe this executable incapable of syncing the chain.
@@ -471,9 +482,3 @@ pub trait ProvingBlockChainClient: BlockChainClient {
/// Get an epoch change signal by block hash.
fn epoch_signal(&self, hash: H256) -> Option<Vec<u8>>;
}
/// resets the blockchain
pub trait BlockChainReset {
/// reset to best_block - n
fn reset(&self, num: u32) -> Result<(), String>;
}

View File

@@ -24,6 +24,7 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::sync::{Weak, Arc};
use std::time::{UNIX_EPOCH, SystemTime, Duration};
use account_provider::AccountProvider;
use block::*;
use client::EngineClient;
use engines::{Engine, Seal, EngineError, ConstructedVerifier};
@@ -36,7 +37,7 @@ use hash::keccak;
use super::signer::EngineSigner;
use super::validator_set::{ValidatorSet, SimpleList, new_validator_set};
use self::finality::RollingFinality;
use ethkey::{self, Signature};
use ethkey::{self, Password, Signature};
use io::{IoContext, IoHandler, TimerToken, IoService};
use itertools::{self, Itertools};
use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, Rlp};
@@ -47,9 +48,6 @@ use types::header::{Header, ExtendedHeader};
use types::ancestry_action::AncestryAction;
use unexpected::{Mismatch, OutOfBounds};
#[cfg(not(time_checked_add))]
use time_utils::CheckedSystemTime;
mod finality;
/// `AuthorityRound` params.
@@ -414,7 +412,7 @@ pub struct AuthorityRound {
transition_service: IoService<()>,
step: Arc<PermissionedStep>,
client: Arc<RwLock<Option<Weak<EngineClient>>>>,
signer: RwLock<Option<Box<EngineSigner>>>,
signer: RwLock<EngineSigner>,
validators: Box<ValidatorSet>,
validate_score_transition: u64,
validate_step_transition: u64,
@@ -573,15 +571,8 @@ fn verify_timestamp(step: &Step, header_step: u64) -> Result<(), BlockError> {
// NOTE This error might be returned only in early stage of verification (Stage 1).
// Returning it further won't recover the sync process.
trace!(target: "engine", "verify_timestamp: block too early");
let now = SystemTime::now();
let found = now.checked_add(Duration::from_secs(oob.found)).ok_or(BlockError::TimestampOverflow)?;
let max = oob.max.and_then(|m| now.checked_add(Duration::from_secs(m)));
let min = oob.min.and_then(|m| now.checked_add(Duration::from_secs(m)));
let new_oob = OutOfBounds { min, max, found };
Err(BlockError::TemporarilyInvalid(new_oob).into())
let oob = oob.map(|n| SystemTime::now() + Duration::from_secs(n));
Err(BlockError::TemporarilyInvalid(oob).into())
},
Ok(_) => Ok(()),
}
@@ -617,7 +608,6 @@ fn combine_proofs(signal_number: BlockNumber, set_proof: &[u8], finality_proof:
stream.out()
}
fn destructure_proofs(combined: &[u8]) -> Result<(BlockNumber, &[u8], &[u8]), Error> {
let rlp = Rlp::new(combined);
Ok((
@@ -633,7 +623,7 @@ trait AsMillis {
impl AsMillis for Duration {
fn as_millis(&self) -> u64 {
self.as_secs() * 1_000 + (self.subsec_nanos() / 1_000_000) as u64
self.as_secs()*1_000 + (self.subsec_nanos()/1_000_000) as u64
}
}
@@ -675,7 +665,7 @@ impl AuthorityRound {
can_propose: AtomicBool::new(true),
}),
client: Arc::new(RwLock::new(None)),
signer: RwLock::new(None),
signer: Default::default(),
validators: our_params.validators,
validate_score_transition: our_params.validate_score_transition,
validate_step_transition: our_params.validate_step_transition,
@@ -798,7 +788,7 @@ impl AuthorityRound {
return;
}
if let (true, Some(me)) = (current_step > parent_step + 1, self.signer.read().as_ref().map(|s| s.address())) {
if let (true, Some(me)) = (current_step > parent_step + 1, self.signer.read().address()) {
debug!(target: "engine", "Author {} built block with step gap. current step: {}, parent step: {}",
header.author(), current_step, parent_step);
let mut reported = HashSet::new();
@@ -1416,10 +1406,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
let first = chain_head.number() == 0;
// Apply transitions that don't require finality and should be enacted immediately (e.g from chain spec)
// apply immediate transitions.
if let Some(change) = self.validators.is_epoch_end(first, chain_head) {
info!(target: "engine", "Immediately applying validator set change signalled at block {}", chain_head.number());
self.epoch_manager.lock().note_new_epoch();
let change = combine_proofs(chain_head.number(), &change, &[]);
return Some(change)
}
@@ -1504,16 +1492,12 @@ impl Engine<EthereumMachine> for AuthorityRound {
self.validators.register_client(client);
}
fn set_signer(&self, signer: Box<EngineSigner>) {
*self.signer.write() = Some(signer);
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: Password) {
self.signer.write().set(ap, address, password);
}
fn sign(&self, hash: H256) -> Result<Signature, Error> {
Ok(self.signer.read()
.as_ref()
.ok_or(ethkey::Error::InvalidAddress)?
.sign(hash)?
)
Ok(self.signer.read().sign(hash)?)
}
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {
@@ -1548,16 +1532,16 @@ mod tests {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use hash::keccak;
use accounts::AccountProvider;
use ethereum_types::{Address, H520, H256, U256};
use ethkey::Signature;
use types::header::Header;
use rlp::encode;
use block::*;
use test_helpers::{
generate_dummy_client_with_spec, get_temp_state_db,
generate_dummy_client_with_spec_and_accounts, get_temp_state_db,
TestNotify
};
use account_provider::AccountProvider;
use spec::Spec;
use types::transaction::{Action, Transaction};
use engines::{Seal, Engine, EngineError, EthEngine};
@@ -1636,14 +1620,14 @@ mod tests {
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b2 = b2.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) {
assert!(b1.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None);
}
engine.set_signer(Box::new((tap, addr2, "2".into())));
engine.set_signer(tap, addr2, "2".into());
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
assert!(b2.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
@@ -1670,13 +1654,13 @@ mod tests {
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b2 = b2.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
match engine.generate_seal(b1.block(), &genesis_header) {
Seal::None | Seal::Proposal(_) => panic!("wrong seal"),
Seal::Regular(_) => {
engine.step();
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
engine.set_signer(tap.clone(), addr2, "0".into());
match engine.generate_seal(b2.block(), &genesis_header) {
Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"),
Seal::None => {}
@@ -1784,7 +1768,7 @@ mod tests {
assert!(aura.verify_block_family(&header, &parent_header).is_ok());
assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 0);
aura.set_signer(Box::new((Arc::new(AccountProvider::transient_provider()), Default::default(), "".into())));
aura.set_signer(Arc::new(AccountProvider::transient_provider()), Default::default(), "".into());
// Do not report on steps skipped between genesis and first block.
header.set_number(1);
@@ -1894,12 +1878,12 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
let notify = Arc::new(TestNotify::default());
client.add_notify(notify.clone());
engine.register_client(Arc::downgrade(&client) as _);
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b1 = b1.close_and_lock().unwrap();
@@ -1933,7 +1917,7 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
let notify = Arc::new(TestNotify::default());
client.add_notify(notify.clone());
engine.register_client(Arc::downgrade(&client) as _);
@@ -1943,7 +1927,7 @@ mod tests {
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
engine.step();
@@ -1960,9 +1944,9 @@ mod tests {
let b2 = b2.close_and_lock().unwrap();
// we will now seal a block with 1tx and include the accumulated empty step message
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
engine.set_signer(tap.clone(), addr2, "0".into());
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
let empty_steps = ::rlp::encode_list(&vec![empty_step2]);
@@ -1986,7 +1970,7 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
let notify = Arc::new(TestNotify::default());
client.add_notify(notify.clone());
engine.register_client(Arc::downgrade(&client) as _);
@@ -1996,14 +1980,14 @@ mod tests {
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
engine.step();
// step 3
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b2 = b2.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
engine.set_signer(tap.clone(), addr2, "0".into());
assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None);
engine.step();
@@ -2012,10 +1996,10 @@ mod tests {
let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b3 = b3.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
if let Seal::Regular(seal) = engine.generate_seal(b3.block(), &genesis_header) {
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
engine.set_signer(tap.clone(), addr2, "0".into());
let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash());
let empty_steps = ::rlp::encode_list(&vec![empty_step2, empty_step3]);
@@ -2038,7 +2022,7 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
engine.register_client(Arc::downgrade(&client) as _);
// step 2
@@ -2046,7 +2030,7 @@ mod tests {
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
engine.step();
@@ -2100,7 +2084,7 @@ mod tests {
);
// empty step with valid signature from incorrect proposer for step
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())];
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
@@ -2110,9 +2094,9 @@ mod tests {
);
// valid empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
let empty_step2 = sealed_empty_step(engine, 2, &parent_header.hash());
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
engine.set_signer(tap.clone(), addr2, "0".into());
let empty_step3 = sealed_empty_step(engine, 3, &parent_header.hash());
let empty_steps = vec![empty_step2, empty_step3];
@@ -2137,7 +2121,10 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let client = generate_dummy_client_with_spec(Spec::new_test_round_block_reward_contract);
let client = generate_dummy_client_with_spec_and_accounts(
Spec::new_test_round_block_reward_contract,
None,
);
engine.register_client(Arc::downgrade(&client) as _);
// step 2
@@ -2157,7 +2144,7 @@ mod tests {
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
engine.step();
@@ -2195,7 +2182,7 @@ mod tests {
let engine = &*spec.engine;
let addr1 = accounts[0];
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
engine.set_signer(tap.clone(), addr1, "1".into());
let mut header: Header = Header::default();
let empty_step = empty_step(engine, 1, &header.parent_hash());
@@ -2276,7 +2263,7 @@ mod tests {
header.set_author(accounts[0]);
// when
engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into())));
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()),
@@ -2313,9 +2300,9 @@ mod tests {
header.set_author(accounts[0]);
// when
engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into())));
engine.set_signer(tap.clone(), accounts[1], "0".into());
let es1 = sealed_empty_step(&*engine, 1, &parent.hash());
engine.set_signer(Box::new((tap.clone(), accounts[0], "1".into())));
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];

View File

@@ -16,18 +16,19 @@
//! A blockchain engine that supports a basic, non-BFT proof-of-authority.
use std::sync::Weak;
use ethereum_types::{H256, H520};
use std::sync::{Weak, Arc};
use ethereum_types::{H256, H520, Address};
use parking_lot::RwLock;
use ethkey::{self, Signature};
use ethkey::{self, Password, Signature};
use account_provider::AccountProvider;
use block::*;
use engines::{Engine, Seal, ConstructedVerifier, EngineError};
use engines::signer::EngineSigner;
use error::{BlockError, Error};
use ethjson;
use client::EngineClient;
use machine::{AuxiliaryData, Call, EthereumMachine};
use types::header::{Header, ExtendedHeader};
use super::signer::EngineSigner;
use super::validator_set::{ValidatorSet, SimpleList, new_validator_set};
/// `BasicAuthority` params.
@@ -75,7 +76,7 @@ fn verify_external(header: &Header, validators: &ValidatorSet) -> Result<(), Err
/// Engine using `BasicAuthority`, trivial proof-of-authority consensus.
pub struct BasicAuthority {
machine: EthereumMachine,
signer: RwLock<Option<Box<EngineSigner>>>,
signer: RwLock<EngineSigner>,
validators: Box<ValidatorSet>,
}
@@ -84,7 +85,7 @@ impl BasicAuthority {
pub fn new(our_params: BasicAuthorityParams, machine: EthereumMachine) -> Self {
BasicAuthority {
machine: machine,
signer: RwLock::new(None),
signer: Default::default(),
validators: new_validator_set(our_params.validators),
}
}
@@ -189,16 +190,12 @@ impl Engine<EthereumMachine> for BasicAuthority {
self.validators.register_client(client);
}
fn set_signer(&self, signer: Box<EngineSigner>) {
*self.signer.write() = Some(signer);
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: Password) {
self.signer.write().set(ap, address, password);
}
fn sign(&self, hash: H256) -> Result<Signature, Error> {
Ok(self.signer.read()
.as_ref()
.ok_or_else(|| ethkey::Error::InvalidAddress)?
.sign(hash)?
)
Ok(self.signer.read().sign(hash)?)
}
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {
@@ -217,7 +214,7 @@ mod tests {
use ethereum_types::H520;
use block::*;
use test_helpers::get_temp_state_db;
use accounts::AccountProvider;
use account_provider::AccountProvider;
use types::header::Header;
use spec::Spec;
use engines::Seal;
@@ -260,7 +257,7 @@ mod tests {
let spec = new_test_authority();
let engine = &*spec.engine;
engine.set_signer(Box::new((Arc::new(tap), addr, "".into())));
engine.set_signer(Arc::new(tap), addr, "".into());
let genesis_header = spec.genesis_header();
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
@@ -278,7 +275,7 @@ mod tests {
let engine = new_test_authority().engine;
assert!(!engine.seals_internally().unwrap());
engine.set_signer(Box::new((Arc::new(tap), authority, "".into())));
engine.set_signer(Arc::new(tap), authority, "".into());
assert!(engine.seals_internally().unwrap());
}
}

View File

@@ -25,7 +25,7 @@ use std::sync::Arc;
use hash::keccak;
use error::Error;
use machine::WithRewards;
use parity_machine::Machine;
use parity_machine::{Machine, WithBalances};
use trace;
use types::BlockNumber;
use super::{SystemOrCodeCall, SystemOrCodeCallKind};
@@ -152,7 +152,7 @@ impl BlockRewardContract {
/// Applies the given block rewards, i.e. adds the given balance to each beneficiary' address.
/// If tracing is enabled the operations are recorded.
pub fn apply_block_rewards<M: Machine + WithRewards>(
pub fn apply_block_rewards<M: Machine + WithBalances + WithRewards>(
rewards: &[(Address, RewardKind, U256)],
block: &mut M::LiveBlock,
machine: &M,
@@ -170,14 +170,17 @@ mod test {
use client::PrepareOpenBlock;
use ethereum_types::U256;
use spec::Spec;
use test_helpers::generate_dummy_client_with_spec;
use test_helpers::generate_dummy_client_with_spec_and_accounts;
use engines::SystemOrCodeCallKind;
use super::{BlockRewardContract, RewardKind};
#[test]
fn block_reward_contract() {
let client = generate_dummy_client_with_spec(Spec::new_test_round_block_reward_contract);
let client = generate_dummy_client_with_spec_and_accounts(
Spec::new_test_round_block_reward_contract,
None,
);
let machine = Spec::new_test_machine();

View File

@@ -20,17 +20,16 @@ mod authority_round;
mod basic_authority;
mod instant_seal;
mod null_engine;
mod signer;
mod validator_set;
pub mod block_reward;
pub mod signer;
pub use self::authority_round::AuthorityRound;
pub use self::basic_authority::BasicAuthority;
pub use self::epoch::{EpochVerifier, Transition as EpochTransition};
pub use self::instant_seal::{InstantSeal, InstantSealParams};
pub use self::null_engine::NullEngine;
pub use self::signer::EngineSigner;
// TODO [ToDr] Remove re-export (#10130)
pub use types::engines::ForkChoice;
@@ -40,6 +39,7 @@ use std::sync::{Weak, Arc};
use std::collections::{BTreeMap, HashMap};
use std::{fmt, error};
use account_provider::AccountProvider;
use builtin::Builtin;
use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue};
use error::Error;
@@ -49,7 +49,7 @@ use snapshot::SnapshotComponents;
use spec::CommonParams;
use types::transaction::{self, UnverifiedTransaction, SignedTransaction};
use ethkey::{Signature};
use ethkey::{Password, Signature};
use parity_machine::{Machine, LocalizedMachine as Localized, TotalScoredHeader};
use ethereum_types::{H256, U256, Address};
use unexpected::{Mismatch, OutOfBounds};
@@ -81,8 +81,6 @@ pub enum EngineError {
MalformedMessage(String),
/// Requires client ref, but none registered.
RequiresClient,
/// Invalid engine specification or implementation.
InvalidEngine,
}
impl fmt::Display for EngineError {
@@ -98,7 +96,6 @@ impl fmt::Display for EngineError {
FailedSystemCall(ref msg) => format!("Failed to make system call: {}", msg),
MalformedMessage(ref msg) => format!("Received malformed consensus message: {}", msg),
RequiresClient => format!("Call requires client but none registered"),
InvalidEngine => format!("Invalid engine specification or implementation"),
};
f.write_fmt(format_args!("Engine error ({})", msg))
@@ -380,8 +377,8 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Takes a header of a fully verified block.
fn is_proposal(&self, _verified_header: &M::Header) -> bool { false }
/// Register a component which signs consensus messages.
fn set_signer(&self, _signer: Box<EngineSigner>) {}
/// Register an account which signs consensus messages.
fn set_signer(&self, _account_provider: Arc<AccountProvider>, _address: Address, _password: Password) {}
/// Sign using the EngineSigner, to be used for consensus tx signing.
fn sign(&self, _hash: H256) -> Result<Signature, M::Error> { unimplemented!() }

View File

@@ -18,7 +18,7 @@ use engines::Engine;
use engines::block_reward::{self, RewardKind};
use ethereum_types::U256;
use machine::WithRewards;
use parity_machine::{Machine, Header, LiveBlock, TotalScoredHeader};
use parity_machine::{Header, LiveBlock, WithBalances, TotalScoredHeader};
use types::BlockNumber;
/// Params for a null engine.
@@ -58,7 +58,7 @@ impl<M: Default> Default for NullEngine<M> {
}
}
impl<M: Machine + WithRewards> Engine<M> for NullEngine<M>
impl<M: WithBalances + WithRewards> Engine<M> for NullEngine<M>
where M::ExtendedHeader: TotalScoredHeader,
<M::ExtendedHeader as TotalScoredHeader>::Value: Ord
{

View File

@@ -16,68 +16,49 @@
//! A signer used by Engines which need to sign messages.
use std::sync::Arc;
use ethereum_types::{H256, Address};
use ethkey::{self, Signature};
use ethkey::{Password, Signature};
use account_provider::{self, AccountProvider};
/// Everything that an Engine needs to sign messages.
pub trait EngineSigner: Send + Sync {
pub struct EngineSigner {
account_provider: Arc<AccountProvider>,
address: Option<Address>,
password: Option<Password>,
}
impl Default for EngineSigner {
fn default() -> Self {
EngineSigner {
account_provider: Arc::new(AccountProvider::transient_provider()),
address: Default::default(),
password: Default::default(),
}
}
}
impl EngineSigner {
/// Set up the signer to sign with given address and password.
pub fn set(&mut self, ap: Arc<AccountProvider>, address: Address, password: Password) {
self.account_provider = ap;
self.address = Some(address);
self.password = Some(password);
debug!(target: "poa", "Setting Engine signer to {}", address);
}
/// Sign a consensus message hash.
fn sign(&self, hash: H256) -> Result<Signature, ethkey::Error>;
/// Signing address
fn address(&self) -> Address;
}
/// Creates a new `EngineSigner` from given key pair.
pub fn from_keypair(keypair: ethkey::KeyPair) -> Box<EngineSigner> {
Box::new(Signer(keypair))
}
struct Signer(ethkey::KeyPair);
impl EngineSigner for Signer {
fn sign(&self, hash: H256) -> Result<Signature, ethkey::Error> {
ethkey::sign(self.0.secret(), &hash)
pub fn sign(&self, hash: H256) -> Result<Signature, account_provider::SignError> {
self.account_provider.sign(self.address.unwrap_or_else(Default::default), self.password.clone(), hash)
}
fn address(&self) -> Address {
self.0.address()
}
}
#[cfg(test)]
mod test_signer {
use std::sync::Arc;
use ethkey::Password;
use accounts::{self, AccountProvider, SignError};
use super::*;
impl EngineSigner for (Arc<AccountProvider>, Address, Password) {
fn sign(&self, hash: H256) -> Result<Signature, ethkey::Error> {
match self.0.sign(self.1, Some(self.2.clone()), hash) {
Err(SignError::NotUnlocked) => unreachable!(),
Err(SignError::NotFound) => Err(ethkey::Error::InvalidAddress),
Err(SignError::Hardware(err)) => {
warn!("Error using hardware wallet for engine: {:?}", err);
Err(ethkey::Error::InvalidSecret)
},
Err(SignError::SStore(accounts::Error::EthKey(err))) => Err(err),
Err(SignError::SStore(accounts::Error::EthKeyCrypto(err))) => {
warn!("Low level crypto error: {:?}", err);
Err(ethkey::Error::InvalidSecret)
},
Err(SignError::SStore(err)) => {
warn!("Error signing for engine: {:?}", err);
Err(ethkey::Error::InvalidSignature)
},
Ok(ok) => Ok(ok),
}
}
fn address(&self) -> Address {
self.1
}
/// Signing address.
pub fn address(&self) -> Option<Address> {
self.address.clone()
}
/// Check if the signing address was set.
pub fn is_some(&self) -> bool {
self.address.is_some()
}
}

View File

@@ -141,18 +141,17 @@ mod tests {
use rlp::encode;
use spec::Spec;
use types::header::Header;
use accounts::AccountProvider;
use miner::{self, MinerService};
use account_provider::AccountProvider;
use miner::MinerService;
use types::ids::BlockId;
use test_helpers::generate_dummy_client_with_spec;
use call_contract::CallContract;
use client::{BlockChainClient, ChainInfo, BlockInfo};
use test_helpers::generate_dummy_client_with_spec_and_accounts;
use client::{BlockChainClient, ChainInfo, BlockInfo, CallContract};
use super::super::ValidatorSet;
use super::ValidatorContract;
#[test]
fn fetches_validators() {
let client = generate_dummy_client_with_spec(Spec::new_validator_contract);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, None);
let vc = Arc::new(ValidatorContract::new("0000000000000000000000000000000000000005".parse::<Address>().unwrap()));
vc.register_client(Arc::downgrade(&client) as _);
let last_hash = client.best_block_header().hash();
@@ -164,14 +163,13 @@ mod tests {
fn reports_validators() {
let tap = Arc::new(AccountProvider::transient_provider());
let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap();
let client = generate_dummy_client_with_spec(Spec::new_validator_contract);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, Some(tap.clone()));
client.engine().register_client(Arc::downgrade(&client) as _);
let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
// Make sure reporting can be done.
client.miner().set_gas_range_target((1_000_000.into(), 1_000_000.into()));
let signer = Box::new((tap.clone(), v1, "".into()));
client.miner().set_author(miner::Author::Sealer(signer));
client.miner().set_author(v1, Some("".into())).unwrap();
// Check a block that is a bit in future, reject it but don't report the validator.
let mut header = Header::default();

View File

@@ -150,15 +150,15 @@ mod tests {
use std::sync::Arc;
use std::collections::BTreeMap;
use hash::keccak;
use accounts::AccountProvider;
use account_provider::AccountProvider;
use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock};
use engines::EpochChange;
use engines::validator_set::ValidatorSet;
use ethkey::Secret;
use types::header::Header;
use miner::{self, MinerService};
use miner::MinerService;
use spec::Spec;
use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data};
use test_helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data};
use types::ids::BlockId;
use ethereum_types::Address;
use verification::queue::kind::blocks::Unverified;
@@ -171,29 +171,26 @@ mod tests {
let s0: Secret = keccak("0").into();
let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap();
let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap();
let client = generate_dummy_client_with_spec(Spec::new_validator_multi);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_multi, Some(tap));
client.engine().register_client(Arc::downgrade(&client) as _);
// Make sure txs go through.
client.miner().set_gas_range_target((1_000_000.into(), 1_000_000.into()));
// Wrong signer for the first block.
let signer = Box::new((tap.clone(), v1, "".into()));
client.miner().set_author(miner::Author::Sealer(signer));
client.miner().set_author(v1, Some("".into())).unwrap();
client.transact_contract(Default::default(), Default::default()).unwrap();
::client::EngineClient::update_sealing(&*client);
assert_eq!(client.chain_info().best_block_number, 0);
// Right signer for the first block.
let signer = Box::new((tap.clone(), v0, "".into()));
client.miner().set_author(miner::Author::Sealer(signer));
client.miner().set_author(v0, Some("".into())).unwrap();
::client::EngineClient::update_sealing(&*client);
assert_eq!(client.chain_info().best_block_number, 1);
// This time v0 is wrong.
client.transact_contract(Default::default(), Default::default()).unwrap();
::client::EngineClient::update_sealing(&*client);
assert_eq!(client.chain_info().best_block_number, 1);
let signer = Box::new((tap.clone(), v1, "".into()));
client.miner().set_author(miner::Author::Sealer(signer));
client.miner().set_author(v1, Some("".into())).unwrap();
::client::EngineClient::update_sealing(&*client);
assert_eq!(client.chain_info().best_block_number, 2);
// v1 is still good.

View File

@@ -445,19 +445,19 @@ mod tests {
use ethereum_types::Address;
use types::ids::BlockId;
use spec::Spec;
use accounts::AccountProvider;
use account_provider::AccountProvider;
use types::transaction::{Transaction, Action};
use client::{ChainInfo, BlockInfo, ImportBlock};
use ethkey::Secret;
use miner::{self, MinerService};
use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data};
use miner::MinerService;
use test_helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data};
use super::super::ValidatorSet;
use super::{ValidatorSafeContract, EVENT_NAME_HASH};
use verification::queue::kind::blocks::Unverified;
#[test]
fn fetches_validators() {
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
let vc = Arc::new(ValidatorSafeContract::new("0000000000000000000000000000000000000005".parse::<Address>().unwrap()));
vc.register_client(Arc::downgrade(&client) as _);
let last_hash = client.best_block_header().hash();
@@ -472,12 +472,11 @@ mod tests {
let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap();
let v1 = tap.insert_account(keccak("0").into(), &"".into()).unwrap();
let chain_id = Spec::new_validator_safe_contract().chain_id();
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap));
client.engine().register_client(Arc::downgrade(&client) as _);
let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
let signer = Box::new((tap.clone(), v1, "".into()));
client.miner().set_author(miner::Author::Sealer(signer));
client.miner().set_author(v1, Some("".into())).unwrap();
// Remove "1" validator.
let tx = Transaction {
nonce: 0.into(),
@@ -505,13 +504,11 @@ mod tests {
assert_eq!(client.chain_info().best_block_number, 1);
// Switch to the validator that is still there.
let signer = Box::new((tap.clone(), v0, "".into()));
client.miner().set_author(miner::Author::Sealer(signer));
client.miner().set_author(v0, Some("".into())).unwrap();
::client::EngineClient::update_sealing(&*client);
assert_eq!(client.chain_info().best_block_number, 2);
// Switch back to the added validator, since the state is updated.
let signer = Box::new((tap.clone(), v1, "".into()));
client.miner().set_author(miner::Author::Sealer(signer));
client.miner().set_author(v1, Some("".into())).unwrap();
let tx = Transaction {
nonce: 2.into(),
gas_price: 0.into(),
@@ -542,7 +539,7 @@ mod tests {
use types::header::Header;
use types::log_entry::LogEntry;
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
let engine = client.engine().clone();
let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
@@ -579,7 +576,7 @@ mod tests {
use types::header::Header;
use engines::{EpochChange, Proof};
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
let engine = client.engine().clone();
let mut new_header = Header::default();

View File

@@ -25,10 +25,11 @@ use ethtrie::TrieError;
use rlp;
use snappy::InvalidInput;
use snapshot::Error as SnapshotError;
use types::BlockNumber;
use types::transaction::Error as TransactionError;
use types::BlockNumber;
use unexpected::{Mismatch, OutOfBounds};
use account_provider::SignError as AccountsError;
use engines::EngineError;
pub use executed::{ExecutionError, CallError};
@@ -89,8 +90,6 @@ 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.
@@ -140,7 +139,6 @@ 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),
};
@@ -246,6 +244,12 @@ error_chain! {
display("Snapshot error {}", err)
}
#[doc = "Account Provider error"]
AccountProvider(err: AccountsError) {
description("Accounts Provider error")
display("Accounts Provider error {}", err)
}
#[doc = "PoW hash is invalid or out of date."]
PowHashInvalid {
description("PoW hash is invalid or out of date.")
@@ -266,6 +270,12 @@ error_chain! {
}
}
impl From<AccountsError> for Error {
fn from(err: AccountsError) -> Error {
ErrorKind::AccountProvider(err).into()
}
}
impl From<SnapshotError> for Error {
fn from(err: SnapshotError) -> Error {
match err {

View File

@@ -113,8 +113,6 @@ pub struct EthashParams {
pub block_reward_contract: Option<BlockRewardContract>,
/// Difficulty bomb delays.
pub difficulty_bomb_delays: BTreeMap<BlockNumber, BlockNumber>,
/// Block to transition to progpow
pub progpow_transition: u64,
}
impl From<ethjson::spec::EthashParams> for EthashParams {
@@ -155,7 +153,6 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
}),
expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into),
expip2_duration_limit: p.expip2_duration_limit.map_or(30, Into::into),
progpow_transition: p.progpow_transition.map_or(u64::max_value(), Into::into),
block_reward_contract_transition: p.block_reward_contract_transition.map_or(0, Into::into),
block_reward_contract: match (p.block_reward_contract_code, p.block_reward_contract_address) {
(Some(code), _) => Some(BlockRewardContract::new_from_code(Arc::new(code.into()))),
@@ -185,12 +182,10 @@ impl Ethash {
machine: EthereumMachine,
optimize_for: T,
) -> Arc<Self> {
let progpow_transition = ethash_params.progpow_transition;
Arc::new(Ethash {
ethash_params,
machine,
pow: EthashManager::new(cache_dir.as_ref(), optimize_for.into(), progpow_transition),
pow: EthashManager::new(cache_dir.as_ref(), optimize_for.into()),
})
}
}
@@ -325,8 +320,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
let difficulty = ethash::boundary_to_difficulty(&H256(quick_get_difficulty(
&header.bare_hash().0,
seal.nonce.low_u64(),
&seal.mix_hash.0,
header.number() >= self.ethash_params.progpow_transition
&seal.mix_hash.0
)));
if &difficulty < header.difficulty() {
@@ -529,7 +523,6 @@ mod tests {
block_reward_contract: None,
block_reward_contract_transition: 0,
difficulty_bomb_delays: BTreeMap::new(),
progpow_transition: u64::max_value(),
}
}

View File

@@ -148,9 +148,6 @@ 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")) }
@@ -171,9 +168,6 @@ 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

@@ -312,7 +312,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.saturating_add(prev_bal), nonce_offset)?;
state.new_contract(&params.address, val + prev_bal, nonce_offset)?;
} else {
state.new_contract(&params.address, prev_bal, nonce_offset)?;
}
@@ -1103,13 +1103,9 @@ 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.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()));
}
let gas_used = t.gas - gas_left;
let refund_value = gas_left * t.gas_price;
let fees_value = gas_used * t.gas_price;
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);
@@ -1127,7 +1123,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).overflowing_mul(t.gas_price).0) } else { None };
let min_balance = if schedule.kill_dust != CleanDustMode::Off { Some(U256::from(schedule.tx_gas) * t.gas_price) } else { None };
self.state.kill_garbage(&substate.touched, schedule.kill_empty, &min_balance, schedule.kill_dust == CleanDustMode::WithCodeAndStorage)?;
match result {

View File

@@ -18,7 +18,10 @@
use ethjson;
#[cfg(feature="ci-skip-tests")]
#[cfg(all(not(test), feature = "ci-skip-tests"))]
compile_error!("ci-skip-tests can only be enabled for testing builds.");
#[cfg(feature="ci-skip-issue")]
lazy_static!{
pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = {
let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json");
@@ -26,7 +29,7 @@ lazy_static!{
};
}
#[cfg(not(feature="ci-skip-tests"))]
#[cfg(not(feature="ci-skip-issue"))]
lazy_static!{
pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = {
ethjson::test::SkipStates::empty()

View File

@@ -165,7 +165,6 @@ 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/"}
@@ -178,6 +177,7 @@ 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

@@ -18,6 +18,9 @@ use ethjson;
use trie::{TrieFactory, TrieSpec};
use ethtrie::RlpCodec;
use ethereum_types::H256;
use memorydb::MemoryDB;
use keccak_hasher::KeccakHasher;
use kvdb::DBValue;
use super::HookType;
@@ -34,7 +37,7 @@ fn test_trie<H: FnMut(&str, HookType)>(json: &[u8], trie: TrieSpec, start_stop_h
for (name, test) in tests.into_iter() {
start_stop_hook(&name, HookType::OnStart);
let mut memdb = journaldb::new_memory_db();
let mut memdb = MemoryDB::<KeccakHasher, DBValue>::new();
let mut root = H256::default();
let mut t = factory.create(&mut memdb, &mut root);

View File

@@ -15,7 +15,6 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
#![warn(missing_docs, unused_extern_crates)]
#![cfg_attr(feature = "time_checked_add", feature(time_checked_add))]
//! Ethcore library
//!
@@ -67,14 +66,14 @@ extern crate ethabi;
extern crate ethash;
extern crate ethcore_blockchain as blockchain;
extern crate ethcore_bloom_journal as bloom_journal;
extern crate ethcore_call_contract as call_contract;
extern crate ethcore_db as db;
extern crate ethcore_io as io;
extern crate ethcore_miner;
extern crate ethereum_types;
extern crate ethjson;
extern crate ethkey;
extern crate hash_db;
extern crate ethstore;
extern crate hashdb;
extern crate heapsize;
extern crate itertools;
extern crate journaldb;
@@ -85,7 +84,7 @@ extern crate kvdb_memorydb;
extern crate len_caching_lock;
extern crate lru_cache;
extern crate memory_cache;
extern crate memory_db;
extern crate memorydb;
extern crate num;
extern crate num_cpus;
extern crate parity_bytes as bytes;
@@ -93,7 +92,7 @@ extern crate parity_crypto;
extern crate parity_machine;
extern crate parity_snappy as snappy;
extern crate parking_lot;
extern crate trie_db as trie;
extern crate patricia_trie as trie;
extern crate patricia_trie_ethereum as ethtrie;
extern crate rand;
extern crate rayon;
@@ -107,8 +106,6 @@ extern crate using_queue;
extern crate vm;
extern crate wasm;
#[cfg(test)]
extern crate ethcore_accounts as accounts;
#[cfg(feature = "stratum")]
extern crate ethcore_stratum;
#[cfg(any(test, feature = "tempdir"))]
@@ -117,10 +114,12 @@ extern crate tempdir;
extern crate kvdb_rocksdb;
#[cfg(any(test, feature = "blooms-db"))]
extern crate blooms_db;
#[cfg(any(test, feature = "env_logger"))]
extern crate env_logger;
#[cfg(test)]
extern crate rlp_compress;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
extern crate hardware_wallet;
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))]
extern crate fake_hardware_wallet as hardware_wallet;
#[macro_use]
extern crate ethabi_derive;
@@ -144,15 +143,12 @@ extern crate serde_derive;
#[cfg_attr(test, macro_use)]
extern crate evm;
#[cfg(all(test, feature = "price-info"))]
extern crate fetch;
#[cfg(all(test, feature = "price-info"))]
extern crate parity_runtime;
#[cfg(not(time_checked_add))]
extern crate time_utils;
#[cfg(any(test, feature = "env_logger"))]
extern crate env_logger;
#[cfg(test)]
extern crate rlp_compress;
pub mod account_provider;
pub mod block;
pub mod builtin;
pub mod client;

View File

@@ -30,8 +30,7 @@ use vm::{EnvInfo, Schedule, CreateContractAddress};
use block::{ExecutedBlock, IsBlock};
use builtin::Builtin;
use call_contract::CallContract;
use client::BlockInfo;
use client::{BlockInfo, CallContract};
use error::Error;
use executive::Executive;
use spec::CommonParams;
@@ -438,7 +437,14 @@ impl ::parity_machine::Machine for EthereumMachine {
type AncestryAction = ::types::ancestry_action::AncestryAction;
type Error = Error;
}
impl<'a> ::parity_machine::LocalizedMachine<'a> for EthereumMachine {
type StateContext = Call<'a>;
type AuxiliaryData = AuxiliaryData<'a>;
}
impl ::parity_machine::WithBalances for EthereumMachine {
fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result<U256, Error> {
live.state().balance(address).map_err(Into::into)
}
@@ -448,11 +454,6 @@ impl ::parity_machine::Machine for EthereumMachine {
}
}
impl<'a> ::parity_machine::LocalizedMachine<'a> for EthereumMachine {
type StateContext = Call<'a>;
type AuxiliaryData = AuxiliaryData<'a>;
}
/// A state machine that uses block rewards.
pub trait WithRewards: ::parity_machine::Machine {
/// Note block rewards, traces each reward storing information about benefactor, amount and type

View File

@@ -21,13 +21,12 @@ use std::sync::Arc;
use ansi_term::Colour;
use bytes::Bytes;
use call_contract::CallContract;
use ethcore_miner::gas_pricer::GasPricer;
use ethcore_miner::local_accounts::LocalAccounts;
use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStatus, PrioritizationStrategy};
#[cfg(feature = "work-notify")]
use ethcore_miner::work_notify::NotifyWork;
use ethereum_types::{H256, U256, Address};
use ethkey::Password;
use io::IoChannel;
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
use miner;
@@ -46,12 +45,13 @@ use types::header::Header;
use types::receipt::RichReceipt;
use using_queue::{UsingQueue, GetAction};
use account_provider::{AccountProvider, SignError as AccountError};
use block::{ClosedBlock, IsBlock, SealedBlock};
use client::{
BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
};
use client::{BlockId, ClientIoMessage};
use engines::{EthEngine, Seal, EngineSigner};
use engines::{EthEngine, Seal};
use error::{Error, ErrorKind};
use executed::ExecutionError;
use executive::contract_address;
@@ -196,25 +196,6 @@ pub struct AuthoringParams {
pub extra_data: Bytes,
}
/// Block sealing mechanism
pub enum Author {
/// Sealing block is external and we only need a reward beneficiary (i.e. PoW)
External(Address),
/// Sealing is done internally, we need a way to create signatures to seal block (i.e. PoA)
Sealer(Box<EngineSigner>),
}
impl Author {
/// Get author's address.
pub fn address(&self) -> Address {
match *self {
Author::External(address) => address,
Author::Sealer(ref sealer) => sealer.address(),
}
}
}
struct SealingWork {
queue: UsingQueue<ClosedBlock>,
enabled: bool,
@@ -245,7 +226,7 @@ pub struct Miner {
// TODO [ToDr] Arc is only required because of price updater
transaction_queue: Arc<TransactionQueue>,
engine: Arc<EthEngine>,
accounts: Arc<LocalAccounts>,
accounts: Option<Arc<AccountProvider>>,
io_channel: RwLock<Option<IoChannel<ClientIoMessage>>>,
}
@@ -263,11 +244,11 @@ impl Miner {
}
/// Creates new instance of miner Arc.
pub fn new<A: LocalAccounts + 'static>(
pub fn new(
options: MinerOptions,
gas_pricer: GasPricer,
spec: &Spec,
accounts: A,
accounts: Option<Arc<AccountProvider>>,
) -> Self {
let limits = options.pool_limits.clone();
let verifier_options = options.pool_verification_options.clone();
@@ -290,7 +271,7 @@ impl Miner {
nonce_cache: NonceCache::new(nonce_cache_size),
options,
transaction_queue: Arc::new(TransactionQueue::new(limits, verifier_options, tx_queue_strategy)),
accounts: Arc::new(accounts),
accounts,
engine: spec.engine.clone(),
io_channel: RwLock::new(None),
}
@@ -299,7 +280,7 @@ impl Miner {
/// Creates new instance of miner with given spec and accounts.
///
/// NOTE This should be only used for tests.
pub fn new_for_tests(spec: &Spec, accounts: Option<HashSet<Address>>) -> Miner {
pub fn new_for_tests(spec: &Spec, accounts: Option<Arc<AccountProvider>>) -> Miner {
let minimal_gas_price = 0.into();
Miner::new(MinerOptions {
pool_verification_options: pool::verifier::Options {
@@ -310,7 +291,7 @@ impl Miner {
},
reseal_min_period: Duration::from_secs(0),
..Default::default()
}, GasPricer::new_fixed(minimal_gas_price), spec, accounts.unwrap_or_default())
}, GasPricer::new_fixed(minimal_gas_price), spec, accounts)
}
/// Sets `IoChannel`
@@ -377,7 +358,7 @@ impl Miner {
chain,
&self.nonce_cache,
&*self.engine,
&*self.accounts,
self.accounts.as_ref().map(|x| &**x),
self.options.refuse_service_transactions,
)
}
@@ -845,11 +826,14 @@ impl miner::MinerService for Miner {
self.params.write().extra_data = extra_data;
}
fn set_author(&self, author: Author) {
self.params.write().author = author.address();
fn set_author(&self, address: Address, password: Option<Password>) -> Result<(), AccountError> {
self.params.write().author = address;
if let Author::Sealer(signer) = author {
if self.engine.seals_internally().is_some() {
if self.engine.seals_internally().is_some() && password.is_some() {
if let Some(ref ap) = self.accounts {
let password = password.unwrap_or_else(|| Password::from(String::new()));
// Sign test message
ap.sign(address.clone(), Some(password.clone()), Default::default())?;
// Enable sealing
self.sealing.lock().enabled = true;
// --------------------------------------------------------------------------
@@ -857,10 +841,14 @@ impl miner::MinerService for Miner {
// | (some `Engine`s call `EngineClient.update_sealing()`) |
// | Make sure to release the locks before calling that method. |
// --------------------------------------------------------------------------
self.engine.set_signer(signer);
self.engine.set_signer(ap.clone(), address, password);
Ok(())
} else {
warn!("Setting an EngineSigner while Engine does not require one.");
warn!(target: "miner", "No account provider");
Err(AccountError::NotFound)
}
} else {
Ok(())
}
}
@@ -873,32 +861,6 @@ impl miner::MinerService for Miner {
self.params.read().gas_range_target.0 / 5
}
fn set_minimal_gas_price(&self, new_price: U256) -> Result<bool, &str> {
match *self.gas_pricer.lock() {
// Binding the gas pricer to `gp` here to prevent
// a deadlock when calling recalibrate()
ref mut gp @ GasPricer::Fixed(_) => {
trace!(target: "miner", "minimal_gas_price: recalibrating fixed...");
*gp = GasPricer::new_fixed(new_price);
let txq = self.transaction_queue.clone();
let mut options = self.options.pool_verification_options.clone();
gp.recalibrate(move |gas_price| {
debug!(target: "miner", "minimal_gas_price: Got gas price! {}", gas_price);
options.minimal_gas_price = gas_price;
txq.set_verifier_options(options);
});
Ok(true)
},
#[cfg(feature = "price-info")]
GasPricer::Calibrated(_) => {
let error_msg = "Can't update fixed gas price while automatic gas calibration is enabled.";
return Err(error_msg);
},
}
}
fn import_external_transactions<C: miner::BlockChainClient>(
&self,
chain: &C,
@@ -954,12 +916,11 @@ impl miner::MinerService for Miner {
pending: PendingTransaction,
trusted: bool
) -> Result<(), transaction::Error> {
// treat the tx as local if the option is enabled, if we have the account, or if
// the account is specified as a Prioritized Local Addresses
// treat the tx as local if the option is enabled, or if we have the account
let sender = pending.sender();
let treat_as_local = trusted
|| !self.options.tx_queue_no_unfamiliar_locals
|| self.accounts.is_local(&sender);
|| self.accounts.as_ref().map(|accts| accts.has_account(sender)).unwrap_or(false);
if treat_as_local {
self.import_own_transaction(chain, pending)
@@ -1288,7 +1249,7 @@ impl miner::MinerService for Miner {
chain,
&nonce_cache,
&*engine,
&*accounts,
accounts.as_ref().map(|x| &**x),
refuse_service_transactions,
);
queue.cull(client);
@@ -1322,10 +1283,7 @@ impl miner::MinerService for Miner {
#[cfg(test)]
mod tests {
use std::iter::FromIterator;
use super::*;
use accounts::AccountProvider;
use ethkey::{Generator, Random};
use hash::keccak;
use rustc_hex::FromHex;
@@ -1333,7 +1291,7 @@ mod tests {
use client::{TestBlockChainClient, EachBlockWith, ChainInfo, ImportSealedBlock};
use miner::{MinerService, PendingOrdering};
use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec};
use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec_and_accounts};
use types::transaction::{Transaction};
#[test]
@@ -1396,7 +1354,7 @@ mod tests {
},
GasPricer::new_fixed(0u64.into()),
&Spec::new_test(),
::std::collections::HashSet::new(), // local accounts
None, // accounts provider
)
}
@@ -1509,8 +1467,8 @@ mod tests {
// given
let keypair = Random.generate().unwrap();
let client = TestBlockChainClient::default();
let mut local_accounts = ::std::collections::HashSet::new();
local_accounts.insert(keypair.address());
let account_provider = AccountProvider::transient_provider();
account_provider.insert_account(keypair.secret().clone(), &"".into()).expect("can add accounts to the provider we just created");
let miner = Miner::new(
MinerOptions {
@@ -1519,7 +1477,7 @@ mod tests {
},
GasPricer::new_fixed(0u64.into()),
&Spec::new_test(),
local_accounts,
Some(Arc::new(account_provider)),
);
let transaction = transaction();
let best_block = 0;
@@ -1551,32 +1509,6 @@ mod tests {
assert_eq!(miner.prepare_pending_block(&client), BlockPreparationStatus::NotPrepared);
}
#[test]
fn should_prioritize_locals() {
let client = TestBlockChainClient::default();
let transaction = transaction();
let miner = Miner::new(
MinerOptions {
tx_queue_no_unfamiliar_locals: true, // should work even with this enabled
..miner().options
},
GasPricer::new_fixed(0u64.into()),
&Spec::new_test(),
HashSet::from_iter(vec![transaction.sender()].into_iter()),
);
let best_block = 0;
// Miner with sender as a known local address should prioritize transactions from that address
let res2 = miner.import_claimed_local_transaction(&client, PendingTransaction::new(transaction, None), false);
// check to make sure the prioritized transaction is pending
assert_eq!(res2.unwrap(), ());
assert_eq!(miner.pending_transactions(best_block).unwrap().len(), 1);
assert_eq!(miner.pending_receipts(best_block).unwrap().len(), 1);
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 1);
assert_eq!(miner.prepare_pending_block(&client), BlockPreparationStatus::NotPrepared);
}
#[test]
fn should_not_seal_unless_enabled() {
let miner = miner();
@@ -1614,19 +1546,12 @@ mod tests {
}
#[test]
fn should_not_fail_setting_engine_signer_without_account_provider() {
let spec = Spec::new_test_round;
fn should_fail_setting_engine_signer_without_account_provider() {
let spec = Spec::new_instant;
let tap = Arc::new(AccountProvider::transient_provider());
let addr = tap.insert_account(keccak("1").into(), &"".into()).unwrap();
let client = generate_dummy_client_with_spec(spec);
let engine_signer = Box::new((tap.clone(), addr, "".into()));
let msg = Default::default();
assert!(client.engine().sign(msg).is_err());
// should set engine signer and miner author
client.miner().set_author(Author::Sealer(engine_signer));
assert_eq!(client.miner().authoring_params().author, addr);
assert!(client.engine().sign(msg).is_ok());
let client = generate_dummy_client_with_spec_and_accounts(spec, None);
assert!(match client.miner().set_author(addr, Some("".into())) { Err(AccountError::NotFound) => true, _ => false });
}
#[test]
@@ -1680,60 +1605,4 @@ mod tests {
assert!(miner.is_currently_sealing());
}
#[test]
fn should_set_new_minimum_gas_price() {
// Creates a new GasPricer::Fixed behind the scenes
let miner = Miner::new_for_tests(&Spec::new_test(), None);
let expected_minimum_gas_price: U256 = 0x1337.into();
miner.set_minimal_gas_price(expected_minimum_gas_price).unwrap();
let txq_options = miner.transaction_queue.status().options;
let current_minimum_gas_price = txq_options.minimal_gas_price;
assert!(current_minimum_gas_price == expected_minimum_gas_price);
}
#[cfg(feature = "price-info")]
fn dynamic_gas_pricer() -> GasPricer {
use std::time::Duration;
use parity_runtime::Executor;
use fetch::Client as FetchClient;
use ethcore_miner::gas_price_calibrator::{GasPriceCalibrator, GasPriceCalibratorOptions};
// Don't really care about any of these settings since
// the gas pricer is never actually going to be used
let fetch = FetchClient::new(1).unwrap();
let p = Executor::new_sync();
GasPricer::new_calibrated(
GasPriceCalibrator::new(
GasPriceCalibratorOptions {
usd_per_tx: 0.0,
recalibration_period: Duration::from_secs(0),
},
fetch,
p,
)
)
}
#[test]
#[cfg(feature = "price-info")]
fn should_fail_to_set_new_minimum_gas_price() {
// We get a fixed gas pricer by default, need to change that
let miner = Miner::new_for_tests(&Spec::new_test(), None);
let calibrated_gas_pricer = dynamic_gas_pricer();
*miner.gas_pricer.lock() = calibrated_gas_pricer;
let expected_minimum_gas_price: U256 = 0x1337.into();
let result = miner.set_minimal_gas_price(expected_minimum_gas_price);
assert!(result.is_err());
let received_error_msg = result.unwrap_err();
let expected_error_msg = "Can't update fixed gas price while automatic gas calibration is enabled.";
assert!(received_error_msg == expected_error_msg);
}
}

View File

@@ -20,13 +20,13 @@
//! Keeps track of transactions and currently sealed pending block.
mod miner;
mod service_transaction_checker;
pub mod pool_client;
#[cfg(feature = "stratum")]
pub mod stratum;
pub use self::miner::{Miner, MinerOptions, Penalization, PendingSet, AuthoringParams, Author};
pub use ethcore_miner::local_accounts::LocalAccounts;
pub use self::miner::{Miner, MinerOptions, Penalization, PendingSet, AuthoringParams};
pub use ethcore_miner::pool::PendingOrdering;
use std::sync::Arc;
@@ -35,6 +35,7 @@ use std::collections::{BTreeSet, BTreeMap};
use bytes::Bytes;
use ethcore_miner::pool::{VerifiedTransaction, QueueStatus, local_transactions};
use ethereum_types::{H256, U256, Address};
use ethkey::Password;
use types::transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction};
use types::BlockNumber;
use types::block::Block;
@@ -42,9 +43,8 @@ use types::header::Header;
use types::receipt::RichReceipt;
use block::SealedBlock;
use call_contract::{CallContract, RegistryInfo};
use client::{
ScheduleInfo,
CallContract, RegistryInfo, ScheduleInfo,
BlockChain, BlockProducer, SealedBlockImporter, ChainInfo,
AccountData, Nonce,
};
@@ -130,8 +130,8 @@ pub trait MinerService : Send + Sync {
/// Set info necessary to sign consensus messages and block authoring.
///
/// On chains where sealing is done externally (e.g. PoW) we provide only reward beneficiary.
fn set_author(&self, author: Author);
/// On PoW password is optional.
fn set_author(&self, address: Address, password: Option<Password>) -> Result<(), ::account_provider::SignError>;
// Transaction Pool
@@ -205,8 +205,4 @@ pub trait MinerService : Send + Sync {
/// Suggested gas limit.
fn sensible_gas_limit(&self) -> U256;
/// Set a new minimum gas limit.
/// Will not work if dynamic gas calibration is set.
fn set_minimal_gas_price(&self, gas_price: U256) -> Result<bool, &str>;
}

View File

@@ -23,10 +23,8 @@ use std::{
};
use ethereum_types::{H256, U256, Address};
use ethcore_miner::local_accounts::LocalAccounts;
use ethcore_miner::pool;
use ethcore_miner::pool::client::NonceClient;
use ethcore_miner::service_transaction_checker::ServiceTransactionChecker;
use types::transaction::{
self,
UnverifiedTransaction,
@@ -35,10 +33,11 @@ use types::transaction::{
use types::header::Header;
use parking_lot::RwLock;
use call_contract::CallContract;
use client::{TransactionId, BlockInfo, Nonce};
use account_provider::AccountProvider;
use client::{TransactionId, BlockInfo, CallContract, Nonce};
use engines::EthEngine;
use miner;
use miner::service_transaction_checker::ServiceTransactionChecker;
use transaction_ext::Transaction;
/// Cache for state nonces.
@@ -73,7 +72,7 @@ pub struct PoolClient<'a, C: 'a> {
chain: &'a C,
cached_nonces: CachedNonceClient<'a, C>,
engine: &'a EthEngine,
accounts: &'a LocalAccounts,
accounts: Option<&'a AccountProvider>,
best_block_header: Header,
service_transaction_checker: Option<ServiceTransactionChecker>,
}
@@ -92,14 +91,14 @@ impl<'a, C: 'a> Clone for PoolClient<'a, C> {
}
impl<'a, C: 'a> PoolClient<'a, C> where
C: BlockInfo + CallContract,
C: BlockInfo + CallContract,
{
/// Creates new client given chain, nonce cache, accounts and service transaction verifier.
pub fn new(
chain: &'a C,
cache: &'a NonceCache,
engine: &'a EthEngine,
accounts: &'a LocalAccounts,
accounts: Option<&'a AccountProvider>,
refuse_service_transactions: bool,
) -> Self {
let best_block_header = chain.best_block_header();
@@ -151,7 +150,7 @@ impl<'a, C: 'a> pool::client::Client for PoolClient<'a, C> where
pool::client::AccountDetails {
nonce: self.cached_nonces.account_nonce(address),
balance: self.chain.latest_balance(address),
is_local: self.accounts.is_local(address),
is_local: self.accounts.map_or(false, |accounts| accounts.has_account(*address)),
}
}

View File

@@ -16,11 +16,9 @@
//! A service transactions contract checker.
use call_contract::{CallContract, RegistryInfo};
use types::ids::BlockId;
use client::{RegistryInfo, CallContract, BlockId};
use types::transaction::SignedTransaction;
use ethabi::FunctionOutputDecoder;
use ethereum_types::Address;
use_contract!(service_transaction, "res/contracts/service_transaction.json");
@@ -31,24 +29,23 @@ const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transa
pub struct ServiceTransactionChecker;
impl ServiceTransactionChecker {
/// Checks if given address in tx is whitelisted to send service transactions.
/// Checks if given address is whitelisted to send service transactions.
pub fn check<C: CallContract + RegistryInfo>(&self, client: &C, tx: &SignedTransaction) -> Result<bool, String> {
let sender = tx.sender();
let hash = tx.hash();
// Skip checking the contract if the transaction does not have zero gas price
if !tx.gas_price.is_zero() {
return Ok(false)
}
self.check_address(client, sender)
}
/// Checks if given address is whitelisted to send service transactions.
pub fn check_address<C: CallContract + RegistryInfo>(&self, client: &C, sender: Address) -> Result<bool, String> {
let contract_address = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest)
let address = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest)
.ok_or_else(|| "contract is not configured")?;
trace!(target: "txqueue", "Checking service transaction checker contract from {}", sender);
trace!(target: "txqueue", "[{:?}] Checking service transaction checker contract from {}", hash, sender);
let (data, decoder) = service_transaction::functions::certified::call(sender);
let value = client.call_contract(BlockId::Latest, contract_address, data)?;
let value = client.call_contract(BlockId::Latest, address, data)?;
decoder.decode(&value).map_err(|e| e.to_string())
}
}

View File

@@ -21,7 +21,7 @@ use std::collections::BTreeMap;
use itertools::Itertools;
use hash::{keccak};
use ethereum_types::{H256, U256};
use hash_db::HashDB;
use hashdb::HashDB;
use kvdb::DBValue;
use keccak_hasher::KeccakHasher;
use triehash::sec_trie_root;

View File

@@ -22,7 +22,7 @@ use bytes::Bytes;
use ethereum_types::{H256, U256};
use ethtrie::{TrieDB, TrieDBMut};
use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP};
use hash_db::HashDB;
use hashdb::HashDB;
use rlp::{RlpStream, Rlp};
use snapshot::Error;
use std::collections::HashSet;
@@ -66,8 +66,7 @@ impl CodeState {
// account address hash, account properties and the storage. Each item contains at most `max_storage_items`
// storage records split according to snapshot format definition.
pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet<H256>, first_chunk_size: usize, max_chunk_size: usize) -> Result<Vec<Bytes>, Error> {
let db = &(acct_db as &HashDB<_,_>);
let db = TrieDB::new(db, &acc.storage_root)?;
let db = TrieDB::new(acct_db, &acc.storage_root)?;
let mut chunks = Vec::new();
let mut db_iter = db.iter()?;
let mut target_chunk_size = first_chunk_size;
@@ -78,7 +77,7 @@ pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB,
account_stream.begin_list(5);
account_stream.append(&acc.nonce)
.append(&acc.balance);
.append(&acc.balance);
// [has_code, code_hash].
if acc.code_hash == KECCAK_EMPTY {
@@ -188,7 +187,7 @@ pub fn from_fat_rlp(
};
let pairs = rlp.at(4)?;
for pair_rlp in pairs.iter() {
let k: Bytes = pair_rlp.val_at(0)?;
let k: Bytes = pair_rlp.val_at(0)?;
let v: Bytes = pair_rlp.val_at(1)?;
storage_trie.insert(&k, &v)?;
@@ -214,7 +213,7 @@ mod tests {
use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak};
use ethereum_types::{H256, Address};
use hash_db::HashDB;
use hashdb::HashDB;
use kvdb::DBValue;
use rlp::Rlp;
@@ -237,9 +236,9 @@ mod tests {
let thin_rlp = ::rlp::encode(&account);
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp).unwrap(), account);
let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap();
let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap();
let fat_rlp = Rlp::new(&fat_rlps[0]).at(1).unwrap();
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account);
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account);
}
#[test]
@@ -248,7 +247,7 @@ mod tests {
let addr = Address::random();
let account = {
let acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr);
let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr);
let mut root = KECCAK_NULL_RLP;
fill_storage(acct_db, &mut root, &mut H256::zero());
BasicAccount {
@@ -262,9 +261,9 @@ mod tests {
let thin_rlp = ::rlp::encode(&account);
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp).unwrap(), account);
let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap();
let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap();
let fat_rlp = Rlp::new(&fat_rlp[0]).at(1).unwrap();
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account);
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account);
}
#[test]
@@ -273,7 +272,7 @@ mod tests {
let addr = Address::random();
let account = {
let acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr);
let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr);
let mut root = KECCAK_NULL_RLP;
fill_storage(acct_db, &mut root, &mut H256::zero());
BasicAccount {
@@ -287,12 +286,12 @@ mod tests {
let thin_rlp = ::rlp::encode(&account);
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp).unwrap(), account);
let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), 500, 1000).unwrap();
let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 500, 1000).unwrap();
let mut root = KECCAK_NULL_RLP;
let mut restored_account = None;
for rlp in fat_rlps {
let fat_rlp = Rlp::new(&rlp).at(1).unwrap();
restored_account = Some(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, root).unwrap().0);
restored_account = Some(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, root).unwrap().0);
root = restored_account.as_ref().unwrap().storage_root.clone();
}
assert_eq!(restored_account, Some(account));
@@ -306,12 +305,12 @@ mod tests {
let addr2 = Address::random();
let code_hash = {
let mut acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr1);
let mut acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr1);
acct_db.insert(b"this is definitely code")
};
{
let mut acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr2);
let mut acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr2);
acct_db.emplace(code_hash.clone(), DBValue::from_slice(b"this is definitely code"));
}
@@ -331,18 +330,18 @@ mod tests {
let mut used_code = HashSet::new();
let fat_rlp1 = to_fat_rlps(&keccak(&addr1), &account1, &AccountDB::new(db.as_hash_db(), &addr1), &mut used_code, usize::max_value(), usize::max_value()).unwrap();
let fat_rlp2 = to_fat_rlps(&keccak(&addr2), &account2, &AccountDB::new(db.as_hash_db(), &addr2), &mut used_code, usize::max_value(), usize::max_value()).unwrap();
let fat_rlp1 = to_fat_rlps(&keccak(&addr1), &account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code, usize::max_value(), usize::max_value()).unwrap();
let fat_rlp2 = to_fat_rlps(&keccak(&addr2), &account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code, usize::max_value(), usize::max_value()).unwrap();
assert_eq!(used_code.len(), 1);
let fat_rlp1 = Rlp::new(&fat_rlp1[0]).at(1).unwrap();
let fat_rlp2 = Rlp::new(&fat_rlp2[0]).at(1).unwrap();
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr2), fat_rlp2, H256::zero()).unwrap();
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr2), fat_rlp2, H256::zero()).unwrap();
assert!(maybe_code.is_none());
assert_eq!(acc, account2);
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr1), fat_rlp1, H256::zero()).unwrap();
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr1), fat_rlp1, H256::zero()).unwrap();
assert_eq!(maybe_code, Some(b"this is definitely code".to_vec()));
assert_eq!(acc, account1);
}
@@ -350,6 +349,6 @@ mod tests {
#[test]
fn encoding_empty_acc() {
let mut db = get_temp_state_db();
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &Address::default()), Rlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None));
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &Address::default()), Rlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None));
}
}

Some files were not shown because too many files have changed in this diff Show More