Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec81d67009 | ||
|
|
2a7dc644b7 | ||
|
|
b00a21f39a | ||
|
|
e9396e158b | ||
|
|
7fbcdfeed4 | ||
|
|
f44d885b6d | ||
|
|
6b0a280685 | ||
|
|
78ceec6c6e | ||
|
|
5c56fc5023 | ||
|
|
5a7e54fb9e |
@@ -1,27 +1,3 @@
|
||||
# NOTE: if you make changes here, remember to also update:
|
||||
# scripts/test-linux.sh
|
||||
# scripts/build-linux.sh
|
||||
# scripts/build-windows.sh
|
||||
|
||||
# Using 'cfg` is broken, see https://github.com/rust-lang/cargo/issues/6858
|
||||
#[target.'cfg(target_arch = "x86_64")']
|
||||
#rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
# …so instead we list all target triples (Tier 1 64-bit platforms)
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
[target.x86_64-pc-windows-gnu]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
# Link the C runtime statically ; https://github.com/paritytech/parity-ethereum/issues/6643
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3", "-Ctarget-feature=+crt-static"]
|
||||
|
||||
[target.x86_64-apple-darwin]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
rustflags = ["-Ctarget-feature=+crt-static"]
|
||||
|
||||
37
.github/CONTRIBUTING.md
vendored
37
.github/CONTRIBUTING.md
vendored
@@ -24,42 +24,7 @@ Also, try to include **steps to reproduce** the issue and expand on the **actual
|
||||
|
||||
If you would like to contribute to Parity Ethereum, please **fork it**, fix bugs or implement features, and [propose a pull request](https://github.com/paritytech/parity-ethereum/compare).
|
||||
|
||||
### Labels & Milestones
|
||||
|
||||
We use [labels](https://github.com/paritytech/parity-ethereum/labels) to manage PRs and issues and communicate the state of a PR. Please familiarize yourself with them. Furthermore we are organizing issues in [milestones](https://github.com/paritytech/parity-ethereum/milestones). Best way to get started is to a pick a ticket from the current milestone tagged [`easy`](https://github.com/paritytech/parity-ethereum/labels/Q2-easy%20%F0%9F%92%83) and get going, or [`mentor`](https://github.com/paritytech/parity-ethereum/labels/Q1-mentor%20%F0%9F%95%BA) and get in contact with the mentor offering their support on that larger task.
|
||||
|
||||
### Rules
|
||||
|
||||
There are a few basic ground-rules for contributors (including the maintainer(s) of the project):
|
||||
|
||||
* **No pushing directly to the master branch**.
|
||||
* **All modifications** must be made in a **pull-request** to solicit feedback from other contributors.
|
||||
* Pull-requests cannot be merged before CI runs green and two reviewers have given their approval.
|
||||
* Contributors should adhere to the [Parity Ethereum Style Guide](https://wiki.parity.io/Parity-Ethereum-Style-Guide).
|
||||
|
||||
### Recommendations
|
||||
|
||||
* **Non-master branch names** *should* be prefixed with a short name moniker, followed by the associated Github Issue ID (if any), and a brief description of the task using the format `<GITHUB_USERNAME>-<ISSUE_ID>-<BRIEF_DESCRIPTION>` (e.g. `gavin-123-readme`). The name moniker helps people to inquiry about their unfinished work, and the GitHub Issue ID helps your future self and other developers (particularly those who are onboarding) find out about and understand the original scope of the task, and where it fits into Parity Ethereum [Projects](https://github.com/paritytech/parity-ethereum/projects).
|
||||
* **Remove stale branches periodically**
|
||||
|
||||
### Preparing Pull Requests
|
||||
|
||||
* If your PR does not alter any logic (e.g. comments, dependencies, docs), then it may be tagged [`insubstantial`](https://github.com/paritytech/parity-ethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22).
|
||||
|
||||
* Once a PR is ready for review please add the [`pleasereview`](https://github.com/paritytech/parity-ethereum/pulls?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+label%3A%22A0-pleasereview+%F0%9F%A4%93%22+) label.
|
||||
|
||||
### Reviewing Pull Requests*:
|
||||
|
||||
* At least two reviewers are required to review PRs (even for PRs tagged [`insubstantial`](https://github.com/paritytech/parity-ethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22)).
|
||||
|
||||
When doing a review, make sure to look for any:
|
||||
|
||||
* Buggy behavior.
|
||||
* Undue maintenance burden.
|
||||
* Breaking with house coding style.
|
||||
* Pessimization (i.e. reduction of speed as measured in the projects benchmarks).
|
||||
* Breaking changes should be carefuly reviewed and tagged as such so they end up in the [changelog](../CHANGELOG.md).
|
||||
* Uselessness (i.e. it does not strictly add a feature or fix a known issue).
|
||||
Please, refer to the [Coding Guide](https://wiki.parity.io/Coding-guide) in our wiki for more details about hacking on Parity.
|
||||
|
||||
## License.
|
||||
|
||||
|
||||
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,14 +1,10 @@
|
||||
_Before filing a new issue, please **provide the following information**._
|
||||
|
||||
_If you think that your issue is an exploitable security vulnerability, please mail your bugreport to security@parity.io instead; your submission might be eligible for our Bug Bounty._
|
||||
_You can find mode info on the reporting process in [SECURITY.md](https://github.com/paritytech/parity-ethereum/blob/master/SECURITY.md)_
|
||||
|
||||
|
||||
- **Parity Ethereum version**: 0.0.0
|
||||
- **Operating system**: Windows / MacOS / Linux
|
||||
- **Installation**: homebrew / one-line installer / built from source
|
||||
- **Fully synchronized**: no / yes
|
||||
- **Network**: ethereum / ropsten / goerli / ...
|
||||
- **Network**: ethereum / ropsten / kovan / ...
|
||||
- **Restarted**: no / yes
|
||||
|
||||
_Your issue description goes here below. Try to include **actual** vs. **expected behavior** and **steps to reproduce** the issue._
|
||||
|
||||
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,21 +0,0 @@
|
||||
Thank you for your Pull Request!
|
||||
|
||||
Before you submitting, please check that:
|
||||
|
||||
- [ ] You added a brief description of the PR, e.g.:
|
||||
- What does it do?
|
||||
- What important points reviewers should know?
|
||||
- Is there something left for follow-up PRs?
|
||||
- [ ] You labeled the PR with appropriate labels if you have permissions to do so.
|
||||
- [ ] You mentioned a related issue if this PR related to it, e.g. `Fixes #228` or `Related #1337`.
|
||||
- [ ] You asked any particular reviewers to review. If you aren't sure, start with GH suggestions.
|
||||
- [ ] Your PR adheres [the style guide](https://wiki.parity.io/Coding-guide)
|
||||
- In particular, mind the maximal line length.
|
||||
- There is no commented code checked in unless necessary.
|
||||
- Any panickers have a proof or removed.
|
||||
- [ ] You updated any rustdocs which may have changed
|
||||
|
||||
After you've read this notice feel free to remove it.
|
||||
Thank you!
|
||||
|
||||
✄ -----------------------------------------------------------------------------
|
||||
353
.gitlab-ci.yml
353
.gitlab-ci.yml
@@ -4,19 +4,12 @@ stages:
|
||||
- publish
|
||||
- optional
|
||||
|
||||
image: parity/parity-ci-linux:latest
|
||||
variables:
|
||||
GIT_STRATEGY: fetch
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
CI_SERVER_NAME: "GitLab CI"
|
||||
CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_JOB_NAME}"
|
||||
SCCACHE_DIR: "/ci-cache/${CI_PROJECT_NAME}/sccache"
|
||||
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
|
||||
@@ -25,316 +18,154 @@ 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/
|
||||
- tools/
|
||||
- artifacts/
|
||||
|
||||
.docker-cache-status: &docker-cache-status
|
||||
variables:
|
||||
CARGO_HOME: "/ci-cache/parity-ethereum/cargo/${CI_JOB_NAME}"
|
||||
dependencies: []
|
||||
before_script:
|
||||
- rustup show
|
||||
- cargo --version
|
||||
- SCCACHE_ERROR_LOG=/builds/parity/parity-ethereum/sccache_debug.log
|
||||
RUST_LOG=sccache=debug
|
||||
sccache --start-server
|
||||
- sccache -s
|
||||
after_script:
|
||||
# sccache debug info
|
||||
- if test -e sccache_debug.log;
|
||||
then
|
||||
echo "_____All crate-types:_____";
|
||||
grep 'parse_arguments.*--crate-type' sccache_debug.log | sed -re 's/.*"--crate-type", "([^"]+)".*/\1/' | sort | uniq -c;
|
||||
echo "_____Non-cacheable reasons:_____";
|
||||
grep CannotCache sccache_debug.log | sed -re 's/.*CannotCache\((.+)\).*/\1/' | sort | uniq -c;
|
||||
else
|
||||
echo "_____No logs from sccache_____";
|
||||
exit 0;
|
||||
fi
|
||||
tags:
|
||||
- linux-docker
|
||||
|
||||
.build-on-linux: &build-on-linux
|
||||
stage: build
|
||||
<<: *docker-cache-status
|
||||
<<: *collect_artifacts
|
||||
script:
|
||||
- scripts/gitlab/build-linux.sh
|
||||
- sccache -s
|
||||
after_script:
|
||||
- mkdir -p tools
|
||||
- cp -r scripts/docker/hub/* ./tools
|
||||
- cp scripts/gitlab/publish-snap.sh ./tools
|
||||
- cp scripts/gitlab/publish-onchain.sh ./tools
|
||||
- cp scripts/gitlab/safe-curl.sh ./tools
|
||||
- echo v"$(sed -r -n '1,/^version/s/^version\s*=\s*"([^"]+)".*$/\1/p' Cargo.toml)" |
|
||||
tee ./tools/VERSION
|
||||
- echo "$(sed -r -n '1,/^track/s/^track\s*=\s*"([^"]+)".*$/\1/p' ./util/version/Cargo.toml)" |
|
||||
tee ./tools/TRACK
|
||||
|
||||
|
||||
cargo-check 0 3:
|
||||
stage: test
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- time cargo check --target $CARGO_TARGET --locked --no-default-features --verbose --color=always
|
||||
- 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 --verbose --color=always
|
||||
- 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" --verbose --color=always
|
||||
- sccache -s
|
||||
|
||||
cargo-audit:
|
||||
stage: test
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- cargo audit
|
||||
allow_failure: true # failed cargo audit shouldn't prevent a PR from being merged
|
||||
|
||||
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 stable
|
||||
- sccache -s
|
||||
|
||||
test-linux-beta:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- ./scripts/gitlab/test-linux.sh beta
|
||||
- sccache -s
|
||||
|
||||
test-linux-nightly:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- ./scripts/gitlab/test-linux.sh nightly
|
||||
- sccache -s
|
||||
allow_failure: true
|
||||
|
||||
build-android:
|
||||
<<: *build-on-linux
|
||||
image: parity/parity-ci-android:stretch
|
||||
stage: test
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
RUN_TESTS: all
|
||||
script:
|
||||
- scripts/gitlab/test-all.sh stable
|
||||
tags:
|
||||
- rust-stable
|
||||
|
||||
test-audit:
|
||||
stage: test
|
||||
script:
|
||||
- scripts/gitlab/cargo-audit.sh
|
||||
tags:
|
||||
- rust-stable
|
||||
|
||||
build-linux:
|
||||
<<: *build-on-linux
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
|
||||
build-linux-i386:
|
||||
<<: *build-on-linux
|
||||
only: *releaseable_branches
|
||||
image: parity/parity-ci-i386:latest
|
||||
variables:
|
||||
CARGO_TARGET: i686-unknown-linux-gnu
|
||||
|
||||
build-linux-arm64:
|
||||
<<: *build-on-linux
|
||||
only: *releaseable_branches
|
||||
image: parity/parity-ci-arm64:latest
|
||||
variables:
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
|
||||
build-linux-armhf:
|
||||
<<: *build-on-linux
|
||||
only: *releaseable_branches
|
||||
image: parity/parity-ci-armhf:latest
|
||||
variables:
|
||||
CARGO_TARGET: armv7-unknown-linux-gnueabihf
|
||||
script:
|
||||
- scripts/gitlab/build-unix.sh
|
||||
<<: *collect_artifacts
|
||||
tags:
|
||||
- rust-stable
|
||||
|
||||
build-darwin:
|
||||
stage: build
|
||||
<<: *collect_artifacts
|
||||
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
|
||||
|
||||
build-windows:
|
||||
stage: build
|
||||
<<: *collect_artifacts
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-pc-windows-msvc
|
||||
CARGO_HOME: "C:/ci-cache/parity-ethereum/cargo/$CI_JOB_NAME"
|
||||
GIT_SUBMODULE_STRATEGY: none
|
||||
script:
|
||||
- sh scripts/gitlab/build-windows.sh
|
||||
tags:
|
||||
- rust-windows
|
||||
- rust-windows
|
||||
<<: *collect_artifacts
|
||||
|
||||
publish-docker:
|
||||
stage: publish
|
||||
<<: *no_git
|
||||
only: *releaseable_branches
|
||||
except:
|
||||
variables:
|
||||
- $SCHEDULE_TAG == "nightly"
|
||||
dependencies:
|
||||
- build-linux
|
||||
environment:
|
||||
name: parity-build
|
||||
cache: {}
|
||||
image: docker:stable
|
||||
services:
|
||||
- docker:dind
|
||||
variables:
|
||||
DOCKER_HOST: tcp://localhost:2375
|
||||
DOCKER_DRIVER: overlay2
|
||||
GIT_STRATEGY: none
|
||||
# DOCKERFILE: tools/Dockerfile
|
||||
# CONTAINER_IMAGE: parity/parity
|
||||
script:
|
||||
# we stopped pushing nightlies to dockerhub, will push to own registry prb.
|
||||
- ./tools/publish-docker.sh
|
||||
tags:
|
||||
- kubernetes-parity-build
|
||||
|
||||
publish-snap: &publish-snap
|
||||
stage: publish
|
||||
<<: *no_git
|
||||
only: *releaseable_branches
|
||||
image: snapcore/snapcraft
|
||||
variables:
|
||||
BUILD_ARCH: amd64
|
||||
cache: {}
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
tags:
|
||||
- linux-docker
|
||||
- shell
|
||||
script:
|
||||
- ./tools/publish-snap.sh
|
||||
- scripts/gitlab/publish-docker.sh parity
|
||||
|
||||
publish-snap-i386:
|
||||
<<: *publish-snap
|
||||
variables:
|
||||
BUILD_ARCH: i386
|
||||
CARGO_TARGET: i686-unknown-linux-gnu
|
||||
dependencies:
|
||||
- build-linux-i386
|
||||
|
||||
publish-snap-arm64:
|
||||
<<: *publish-snap
|
||||
variables:
|
||||
BUILD_ARCH: arm64
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
dependencies:
|
||||
- build-linux-arm64
|
||||
|
||||
publish-snap-armhf:
|
||||
<<: *publish-snap
|
||||
variables:
|
||||
BUILD_ARCH: armhf
|
||||
CARGO_TARGET: armv7-unknown-linux-gnueabihf
|
||||
dependencies:
|
||||
- build-linux-armhf
|
||||
|
||||
publish-onchain:
|
||||
publish-snap:
|
||||
stage: publish
|
||||
<<: *no_git
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
image: parity/snapcraft:gitlab-ci
|
||||
variables:
|
||||
BUILD_ARCH: amd64
|
||||
cache: {}
|
||||
before_script: *determine_version
|
||||
dependencies:
|
||||
- build-linux
|
||||
tags:
|
||||
- rust-stable
|
||||
script:
|
||||
- scripts/gitlab/publish-snap.sh
|
||||
allow_failure: true
|
||||
<<: *collect_artifacts
|
||||
|
||||
publish-awss3:
|
||||
stage: publish
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
- build-darwin
|
||||
- build-windows
|
||||
before_script: *determine_version
|
||||
script:
|
||||
- ./tools/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
|
||||
image: parity/parity-ci-docs:latest
|
||||
stage: publish
|
||||
only:
|
||||
- tags
|
||||
except:
|
||||
- nightly
|
||||
cache: {}
|
||||
dependencies: []
|
||||
cache: {}
|
||||
script:
|
||||
- scripts/gitlab/publish-docs.sh
|
||||
tags:
|
||||
- linux-docker
|
||||
allow_failure: true
|
||||
|
||||
publish-av-whitelist:
|
||||
stage: publish
|
||||
<<: *no_git
|
||||
only: *releaseable_branches
|
||||
except:
|
||||
variables:
|
||||
- $SCHEDULE_TAG == "nightly"
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-windows
|
||||
build-android:
|
||||
stage: optional
|
||||
image: parity/rust-android:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
script:
|
||||
- scripts/gitlab/publish-av-whitelists.sh
|
||||
- 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
|
||||
|
||||
1008
CHANGELOG.md
1008
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
3036
Cargo.lock
generated
3036
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
77
Cargo.toml
77
Cargo.toml
@@ -2,15 +2,16 @@
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity-ethereum"
|
||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||
version = "2.6.2"
|
||||
version = "2.2.8"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
blooms-db = { path = "util/blooms-db" }
|
||||
log = "0.4"
|
||||
env_logger = "0.5"
|
||||
rustc-hex = "1.0"
|
||||
docopt = "1.0"
|
||||
docopt = "0.8"
|
||||
clap = "2"
|
||||
term_size = "0.3"
|
||||
textwrap = "0.9"
|
||||
@@ -18,9 +19,9 @@ num_cpus = "1.2"
|
||||
number_prefix = "0.2"
|
||||
rpassword = "1.0"
|
||||
semver = "0.9"
|
||||
ansi_term = "0.11"
|
||||
parking_lot = "0.7"
|
||||
regex = "1.0"
|
||||
ansi_term = "0.10"
|
||||
parking_lot = "0.6"
|
||||
regex = "0.2"
|
||||
atty = "0.2.8"
|
||||
toml = "0.4"
|
||||
serde = "1.0"
|
||||
@@ -29,51 +30,45 @@ serde_derive = "1.0"
|
||||
futures = "0.1"
|
||||
fdlimit = "0.1"
|
||||
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
|
||||
jsonrpc-core = "12.0.0"
|
||||
parity-bytes = "0.1"
|
||||
common-types = { path = "ethcore/types" }
|
||||
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" }
|
||||
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" }
|
||||
parity-bytes = "0.1"
|
||||
ethcore-io = { path = "util/io" }
|
||||
ethcore-light = { path = "ethcore/light" }
|
||||
ethcore-logger = { path = "parity/logger" }
|
||||
ethcore-logger = { path = "logger" }
|
||||
ethcore-miner = { path = "miner" }
|
||||
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.6.0"
|
||||
ethkey = { path = "accounts/ethkey" }
|
||||
ethstore = { path = "accounts/ethstore" }
|
||||
node-filter = { path = "ethcore/node-filter" }
|
||||
rlp = "0.4.0"
|
||||
cli-signer= { path = "cli-signer" }
|
||||
parity-daemonize = "0.3"
|
||||
parity-hash-fetch = { path = "updater/hash-fetch" }
|
||||
ethcore-transaction = { path = "ethcore/transaction" }
|
||||
ethereum-types = "0.4"
|
||||
node-filter = { path = "ethcore/node_filter" }
|
||||
ethkey = { path = "ethkey" }
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rpc-cli = { path = "rpc_cli" }
|
||||
parity-hash-fetch = { path = "hash-fetch" }
|
||||
parity-ipfs-api = { path = "ipfs" }
|
||||
parity-local-store = { path = "miner/local-store" }
|
||||
parity-local-store = { path = "local-store" }
|
||||
parity-runtime = { path = "util/runtime" }
|
||||
parity-rpc = { path = "rpc" }
|
||||
parity-rpc-client = { path = "rpc_client" }
|
||||
parity-updater = { path = "updater" }
|
||||
parity-version = { path = "util/version" }
|
||||
parity-whisper = { path = "whisper" }
|
||||
parity-path = "0.1"
|
||||
dir = { path = "util/dir" }
|
||||
panic_hook = { path = "util/panic-hook" }
|
||||
keccak-hash = "0.2.0"
|
||||
panic_hook = { path = "util/panic_hook" }
|
||||
keccak-hash = "0.1"
|
||||
migration-rocksdb = { path = "util/migration-rocksdb" }
|
||||
kvdb = "0.1"
|
||||
kvdb-rocksdb = "0.1.3"
|
||||
journaldb = { path = "util/journaldb" }
|
||||
mem = { path = "util/mem" }
|
||||
|
||||
ethcore-secretstore = { path = "secret-store", optional = true }
|
||||
ethcore-secretstore = { path = "secret_store", optional = true }
|
||||
|
||||
registrar = { path = "util/registrar" }
|
||||
|
||||
parity-util-mem = { version = "0.1", features = ["jemalloc-global"] }
|
||||
registrar = { path = "registrar" }
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.2"
|
||||
@@ -87,17 +82,18 @@ fake-fetch = { path = "util/fake-fetch" }
|
||||
[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.
|
||||
@@ -119,25 +115,28 @@ path = "parity/lib.rs"
|
||||
path = "parity/main.rs"
|
||||
name = "parity"
|
||||
|
||||
[profile.dev]
|
||||
|
||||
[profile.release]
|
||||
debug = false
|
||||
lto = true
|
||||
|
||||
[workspace]
|
||||
# This should only list projects that are not
|
||||
# in the dependency tree in any other way
|
||||
# (i.e. pretty much only standalone CLI tools)
|
||||
members = [
|
||||
"accounts/ethkey/cli",
|
||||
"accounts/ethstore/cli",
|
||||
"chainspec",
|
||||
"ethcore/wasm/run",
|
||||
"ethcore/types",
|
||||
"ethkey/cli",
|
||||
"ethstore/cli",
|
||||
"evmbin",
|
||||
"miner",
|
||||
"parity-clib",
|
||||
"whisper",
|
||||
"whisper/cli",
|
||||
"util/triehash-ethereum",
|
||||
"util/keccak-hasher",
|
||||
"util/patricia-trie-ethereum",
|
||||
"util/fastmap",
|
||||
"util/time-utils",
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
heapsize = { git = "https://github.com/cheme/heapsize.git", branch = "ec-macfix" }
|
||||
|
||||
280
README.md
280
README.md
@@ -1,31 +1,12 @@
|
||||

|
||||
|
||||
<h2 align="center">The Fastest and most Advanced Ethereum Client.</h2>
|
||||
## The fastest and most advanced Ethereum client.
|
||||
|
||||
<p align="center"><strong><a href="https://github.com/paritytech/parity-ethereum/releases/latest">» Download the latest release «</a></strong></p>
|
||||
|
||||
<p align="center"><a href="https://gitlab.parity.io/parity/parity-ethereum/commits/master" target="_blank"><img src="https://gitlab.parity.io/parity/parity-ethereum/badges/master/build.svg" /></a>
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank"><img src="https://img.shields.io/badge/license-GPL%20v3-green.svg" /></a></p>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Description](#chapter-001)
|
||||
2. [Technical Overview](#chapter-002)
|
||||
3. [Building](#chapter-003)<br>
|
||||
3.1 [Building Dependencies](#chapter-0031)<br>
|
||||
3.2 [Building from Source Code](#chapter-0032)<br>
|
||||
3.3 [Simple One-Line Installer for Mac and Linux](#chapter-0033)<br>
|
||||
3.4 [Starting Parity Ethereum](#chapter-0034)
|
||||
4. [Testing](#chapter-004)
|
||||
5. [Documentation](#chapter-005)
|
||||
6. [Toolchain](#chapter-006)
|
||||
7. [Community](#chapter-007)
|
||||
8. [Contributing](#chapter-008)
|
||||
9. [License](#chapter-009)
|
||||
|
||||
|
||||
## 1. Description <a id="chapter-001"></a>
|
||||
|
||||
**Built for mission-critical use**: Miners, service providers, and exchanges need fast synchronisation and maximum uptime. Parity Ethereum provides the core infrastructure essential for speedy and reliable services.
|
||||
|
||||
- Clean, modular codebase for easy customisation
|
||||
@@ -34,7 +15,7 @@
|
||||
- Synchronise in hours, not days with Warp Sync
|
||||
- Modular for light integration into your service or product
|
||||
|
||||
## 2. Technical Overview <a id="chapter-002"></a>
|
||||
## Technical Overview
|
||||
|
||||
Parity Ethereum's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity Ethereum using the sophisticated and cutting-edge **Rust programming language**. Parity Ethereum is licensed under the GPLv3 and can be used for all your Ethereum needs.
|
||||
|
||||
@@ -44,11 +25,9 @@ If you run into problems while using Parity Ethereum, check out the [wiki for do
|
||||
|
||||
Parity Ethereum's current beta-release is 2.1. You can download it at [the releases page](https://github.com/paritytech/parity-ethereum/releases) or follow the instructions below to build from source. Please, mind the [CHANGELOG.md](CHANGELOG.md) for a list of all changes between different versions.
|
||||
|
||||
## 3. Building <a id="chapter-003"></a>
|
||||
## Build Dependencies
|
||||
|
||||
### 3.1 Build Dependencies <a id="chapter-0031"></a>
|
||||
|
||||
Parity Ethereum requires **latest stable Rust version** to build.
|
||||
Parity Ethereum requires **Rust version 1.29.x** to build.
|
||||
|
||||
We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have `rustup`, you can install it like this:
|
||||
|
||||
@@ -57,7 +36,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
Parity Ethereum also requires `gcc`, `g++`, `pkg-config`, `file`, `make`, and `cmake` packages to be installed.
|
||||
Parity Ethereum also requires `gcc`, `g++`, `libudev-dev`, `pkg-config`, `file`, `make`, and `cmake` packages to be installed.
|
||||
|
||||
- OSX:
|
||||
```bash
|
||||
@@ -66,7 +45,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
|
||||
|
||||
`clang` is required. It comes with Xcode command line tools or can be installed with homebrew.
|
||||
|
||||
- Windows:
|
||||
- Windows
|
||||
Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the `rustup` installer from
|
||||
https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe, start "VS2015 x64 Native Tools Command Prompt", and use the following command to install and set up the `msvc` toolchain:
|
||||
```bash
|
||||
@@ -79,7 +58,7 @@ Once you have `rustup` installed, then you need to install:
|
||||
|
||||
Make sure that these binaries are in your `PATH`. After that, you should be able to build Parity Ethereum from source.
|
||||
|
||||
### 3.2 Build from Source Code <a id="chapter-0032"></a>
|
||||
## Build from Source Code
|
||||
|
||||
```bash
|
||||
# download Parity Ethereum code
|
||||
@@ -116,7 +95,7 @@ or
|
||||
$ git checkout beta
|
||||
```
|
||||
|
||||
### 3.3 Simple One-Line Installer for Mac and Linux <a id="chapter-0033"></a>
|
||||
## Simple One-Line Installer for Mac and Linux
|
||||
|
||||
```bash
|
||||
bash <(curl https://get.parity.io -L)
|
||||
@@ -128,9 +107,9 @@ The one-line installer always defaults to the latest beta release. To install a
|
||||
bash <(curl https://get.parity.io -L) -r stable
|
||||
```
|
||||
|
||||
### 3.4 Starting Parity Ethereum <a id="chapter-0034"></a>
|
||||
## Start Parity Ethereum
|
||||
|
||||
#### Manually
|
||||
### Manually
|
||||
|
||||
To start Parity Ethereum manually, just run
|
||||
|
||||
@@ -140,234 +119,25 @@ $ ./target/release/parity
|
||||
|
||||
so Parity Ethereum begins syncing the Ethereum blockchain.
|
||||
|
||||
#### Using `systemd` service file
|
||||
### Using `systemd` service file
|
||||
|
||||
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.
|
||||
|
||||
## 4. Testing <a id="chapter-004"></a>
|
||||
|
||||
You can run tests with the following commands:
|
||||
|
||||
* **All** packages
|
||||
```
|
||||
cargo test --all
|
||||
```
|
||||
|
||||
* Specific package
|
||||
```
|
||||
cargo test --package <spec>
|
||||
```
|
||||
|
||||
Replace `<spec>` with one of the packages from the [package list](#package-list) (e.g. `cargo test --package evmbin`).
|
||||
|
||||
You can show your logs in the test output by passing `--nocapture` (i.e. `cargo test --package evmbin -- --nocapture`)
|
||||
|
||||
## 5. Documentation <a id="chapter-005"></a>
|
||||
|
||||
Official website: https://parity.io
|
||||
|
||||
Be sure to [check out our wiki](https://wiki.parity.io) for more information.
|
||||
|
||||
### Viewing documentation for Parity Ethereum packages
|
||||
|
||||
You can generate documentation for Parity Ethereum Rust packages that automatically opens in your web browser using [rustdoc with Cargo](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo) (of the The Rustdoc Book), by running the the following commands:
|
||||
|
||||
* **All** packages
|
||||
```
|
||||
cargo doc --document-private-items --open
|
||||
```
|
||||
|
||||
* Specific package
|
||||
```
|
||||
cargo doc --package <spec> -- --document-private-items --open
|
||||
```
|
||||
|
||||
Use`--document-private-items` to also view private documentation and `--no-deps` to exclude building documentation for dependencies.
|
||||
|
||||
Replacing `<spec>` with one of the following from the details section below (i.e. `cargo doc --package parity-ethereum --open`):
|
||||
|
||||
<a id="package-list"></a>
|
||||
**Package List**
|
||||
<details><p>
|
||||
|
||||
* Parity Ethereum (EthCore) Client Application
|
||||
```bash
|
||||
parity-ethereum
|
||||
```
|
||||
* Parity Ethereum Account Management, Key Management Tool, and Keys Generator
|
||||
```bash
|
||||
ethcore-accounts, ethkey-cli, ethstore, ethstore-cli
|
||||
```
|
||||
* Parity Chain Specification
|
||||
```bash
|
||||
chainspec
|
||||
```
|
||||
* Parity CLI Signer Tool & RPC Client
|
||||
```bash
|
||||
cli-signer parity-rpc-client
|
||||
```
|
||||
* Parity Ethereum Ethash & ProgPoW Implementations
|
||||
```bash
|
||||
ethash
|
||||
```
|
||||
* Parity (EthCore) Library
|
||||
```bash
|
||||
ethcore
|
||||
```
|
||||
* Parity Ethereum Blockchain Database, Test Generator, Configuration,
|
||||
Caching, Importing Blocks, and Block Information
|
||||
```bash
|
||||
ethcore-blockchain
|
||||
```
|
||||
* Parity Ethereum (EthCore) Contract Calls and Blockchain Service & Registry Information
|
||||
```bash
|
||||
ethcore-call-contract
|
||||
```
|
||||
* Parity Ethereum (EthCore) Database Access & Utilities, Database Cache Manager
|
||||
```bash
|
||||
ethcore-db
|
||||
```
|
||||
* Parity Ethereum Virtual Machine (EVM) Rust Implementation
|
||||
```bash
|
||||
evm
|
||||
```
|
||||
* Parity Ethereum (EthCore) Light Client Implementation
|
||||
```bash
|
||||
ethcore-light
|
||||
```
|
||||
* Parity Smart Contract based Node Filter, Manage Permissions of Network Connections
|
||||
```bash
|
||||
node-filter
|
||||
```
|
||||
* Parity Private Transactions
|
||||
```bash
|
||||
ethcore-private-tx
|
||||
```
|
||||
* Parity Ethereum (EthCore) Client & Network Service Creation & Registration with the I/O Subsystem
|
||||
```bash
|
||||
ethcore-service
|
||||
```
|
||||
* Parity Ethereum (EthCore) Blockchain Synchronization
|
||||
```bash
|
||||
ethcore-sync
|
||||
```
|
||||
* Parity Ethereum Common Types
|
||||
```bash
|
||||
common-types
|
||||
```
|
||||
* Parity Ethereum Virtual Machines (VM) Support Library
|
||||
```bash
|
||||
vm
|
||||
```
|
||||
* Parity Ethereum WASM Interpreter
|
||||
```bash
|
||||
wasm
|
||||
```
|
||||
* Parity Ethereum WASM Test Runner
|
||||
```bash
|
||||
pwasm-run-test
|
||||
```
|
||||
* Parity EVM Implementation
|
||||
```bash
|
||||
evmbin
|
||||
```
|
||||
* Parity Ethereum IPFS-compatible API
|
||||
```bash
|
||||
parity-ipfs-api
|
||||
```
|
||||
* Parity Ethereum JSON Deserialization
|
||||
```bash
|
||||
ethjson
|
||||
```
|
||||
* Parity Ethereum State Machine Generalization for Consensus Engines
|
||||
```bash
|
||||
parity-machine
|
||||
```
|
||||
* Parity Ethereum (EthCore) Miner Interface
|
||||
```bash
|
||||
ethcore-miner parity-local-store price-info ethcore-stratum using_queue
|
||||
```
|
||||
* Parity Ethereum (EthCore) Logger Implementation
|
||||
```bash
|
||||
ethcore-logger
|
||||
```
|
||||
* C bindings library for the Parity Ethereum client
|
||||
```bash
|
||||
parity-clib
|
||||
```
|
||||
* Parity Ethereum JSON-RPC Servers
|
||||
```bash
|
||||
parity-rpc
|
||||
```
|
||||
* Parity Ethereum (EthCore) Secret Store
|
||||
```bash
|
||||
ethcore-secretstore
|
||||
```
|
||||
* Parity Updater Service
|
||||
```bash
|
||||
parity-updater parity-hash-fetch
|
||||
```
|
||||
* Parity Core Libraries (Parity Util)
|
||||
```bash
|
||||
ethcore-bloom-journal blooms-db dir eip-712 fake-fetch fastmap fetch ethcore-io
|
||||
journaldb keccak-hasher len-caching-lock macros memory-cache memzero
|
||||
migration-rocksdb ethcore-network ethcore-network-devp2p panic_hook
|
||||
patricia-trie-ethereum registrar rlp_compress rlp_derive parity-runtime stats
|
||||
time-utils triehash-ethereum unexpected parity-version
|
||||
```
|
||||
* Parity Whisper Protocol Implementation
|
||||
```bash
|
||||
parity-whisper whisper-cli
|
||||
```
|
||||
|
||||
</p></details>
|
||||
|
||||
### Contributing to documentation for Parity Ethereum packages
|
||||
|
||||
[Document source code](https://doc.rust-lang.org/1.9.0/book/documentation.html) for Parity Ethereum packages by annotating the source code with documentation comments.
|
||||
|
||||
Example (generic documentation comment):
|
||||
```markdown
|
||||
/// Summary
|
||||
///
|
||||
/// Description
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Summary of Example 1
|
||||
///
|
||||
/// ```rust
|
||||
/// // insert example 1 code here for use with documentation as tests
|
||||
/// ```
|
||||
///
|
||||
```
|
||||
|
||||
## 6. Toolchain <a id="chapter-006"></a>
|
||||
## Parity Ethereum toolchain
|
||||
|
||||
In addition to the Parity Ethereum client, there are additional tools in this repository available:
|
||||
|
||||
- [evmbin](./evmbin) - Parity Ethereum EVM Implementation.
|
||||
- [ethstore](./accounts/ethstore) - Parity Ethereum Key Management.
|
||||
- [ethkey](./accounts/ethkey) - Parity Ethereum Keys Generator.
|
||||
- [whisper](./whisper) - Parity Ethereum Whisper-v2 PoC Implementation.
|
||||
- [evmbin](https://github.com/paritytech/parity-ethereum/blob/master/evmbin/) - EVM implementation for Parity Ethereum.
|
||||
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum function calls encoding.
|
||||
- [ethstore](https://github.com/paritytech/parity-ethereum/blob/master/ethstore/) - Parity Ethereum key management.
|
||||
- [ethkey](https://github.com/paritytech/parity-ethereum/blob/master/ethkey/) - Parity Ethereum keys generator.
|
||||
- [whisper](https://github.com/paritytech/parity-ethereum/blob/master/whisper/) - Implementation of Whisper-v2 PoC.
|
||||
|
||||
The following tool is available in a separate repository:
|
||||
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum Encoding of Function Calls. [Docs here](https://crates.io/crates/ethabi)
|
||||
|
||||
## 7. Community <a id="chapter-007"></a>
|
||||
|
||||
### Join the chat!
|
||||
## Join the chat!
|
||||
|
||||
Questions? Get in touch with us on Gitter:
|
||||
[](https://gitter.im/paritytech/parity)
|
||||
@@ -378,14 +148,8 @@ Questions? Get in touch with us on Gitter:
|
||||
Alternatively, join our community on Matrix:
|
||||
[](https://riot.im/app/#/group/+parity:matrix.parity.io)
|
||||
|
||||
## 8. Contributing <a id="chapter-008"></a>
|
||||
## Documentation
|
||||
|
||||
An introduction has been provided in the ["So You Want to be a Core Developer" presentation slides by Hernando Castano](http://tiny.cc/contrib-to-parity-eth). Additional guidelines are provided in [CONTRIBUTING](./.github/CONTRIBUTING.md).
|
||||
Official website: https://parity.io
|
||||
|
||||
### Contributor Code of Conduct
|
||||
|
||||
[CODE_OF_CONDUCT](./.github/CODE_OF_CONDUCT.md)
|
||||
|
||||
## 9. License <a id="chapter-009"></a>
|
||||
|
||||
[LICENSE](./LICENSE)
|
||||
Be sure to [check out our wiki](https://wiki.parity.io) for more information.
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
description = "Parity Ethereum Account Management"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-accounts"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ethkey = { path = "ethkey" }
|
||||
ethstore = { path = "ethstore" }
|
||||
log = "0.4"
|
||||
parking_lot = "0.7"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
ethereum-types = "0.6.0"
|
||||
tempdir = "0.3"
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[package]
|
||||
description = "Parity Ethereum Chain Specification"
|
||||
name = "chainspec"
|
||||
version = "0.1.0"
|
||||
authors = ["Marek Kotewicz <marek@parity.io>"]
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate serde_json;
|
||||
extern crate ethjson;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
description = "Parity Ethereum RPC Client"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "parity-rpc-client"
|
||||
version = "1.4.0"
|
||||
authors = ["Parity <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.6.0"
|
||||
futures = "0.1"
|
||||
log = "0.4"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
url = "1.2.0"
|
||||
matches = "0.1"
|
||||
parking_lot = "0.7"
|
||||
jsonrpc-core = "12.0.0"
|
||||
jsonrpc-ws-server = "12.0.0"
|
||||
parity-rpc = { path = "../../rpc" }
|
||||
keccak-hash = "0.2.0"
|
||||
7
devtools/Cargo.toml
Normal file
7
devtools/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
description = "Ethcore development/test/build tools"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-devtools"
|
||||
version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
@@ -30,7 +30,7 @@ pub struct Response {
|
||||
impl Response {
|
||||
pub fn assert_header(&self, header: &str, value: &str) {
|
||||
let header = format!("{}: {}", header, value);
|
||||
assert!(self.headers.iter().any(|h| h == &header), "Couldn't find header {} in {:?}", header, &self.headers)
|
||||
assert!(self.headers.iter().find(|h| *h == &header).is_some(), "Couldn't find header {} in {:?}", header, &self.headers)
|
||||
}
|
||||
|
||||
pub fn assert_status(&self, status: &str) {
|
||||
@@ -98,35 +98,35 @@ pub fn request(address: &SocketAddr, request: &str) -> Response {
|
||||
let mut lines = response.lines();
|
||||
let status = lines.next().expect("Expected a response").to_owned();
|
||||
let headers_raw = read_block(&mut lines, false);
|
||||
let headers = headers_raw.split('\n').map(ToOwned::to_owned).collect();
|
||||
let headers = headers_raw.split('\n').map(|v| v.to_owned()).collect();
|
||||
let body = read_block(&mut lines, true);
|
||||
|
||||
Response {
|
||||
status,
|
||||
headers,
|
||||
headers_raw,
|
||||
body,
|
||||
status: status,
|
||||
headers: headers,
|
||||
headers_raw: headers_raw,
|
||||
body: body,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if all required security headers are present
|
||||
pub fn assert_security_headers_present(headers: &[String], port: Option<u16>) {
|
||||
if port.is_none() {
|
||||
if let None = port {
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN"),
|
||||
headers.iter().find(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN").is_some(),
|
||||
"X-Frame-Options: SAMEORIGIN missing: {:?}", headers
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-XSS-Protection: 1; mode=block"),
|
||||
headers.iter().find(|header| header.as_str() == "X-XSS-Protection: 1; mode=block").is_some(),
|
||||
"X-XSS-Protection missing: {:?}", headers
|
||||
);
|
||||
assert!(
|
||||
headers.iter().any(|header| header.as_str() == "X-Content-Type-Options: nosniff"),
|
||||
headers.iter().find(|header| header.as_str() == "X-Content-Type-Options: nosniff").is_some(),
|
||||
"X-Content-Type-Options missing: {:?}", headers
|
||||
);
|
||||
assert!(
|
||||
headers.iter().any(|header| header.starts_with("Content-Security-Policy: ")),
|
||||
headers.iter().find(|header| header.starts_with("Content-Security-Policy: ")).is_some(),
|
||||
"Content-Security-Policy missing: {:?}", headers
|
||||
)
|
||||
}
|
||||
@@ -1,23 +1,19 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Ethereum Transactions
|
||||
//! dev-tools
|
||||
|
||||
mod error;
|
||||
mod transaction;
|
||||
|
||||
pub use self::error::Error;
|
||||
pub use self::transaction::*;
|
||||
pub mod http_client;
|
||||
@@ -1,26 +1,3 @@
|
||||
Note: Parity Ethereum 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)
|
||||
|
||||
Parity-Ethereum 2.0.9-stable is a bug-fix release to improve performance and stability.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Backports: parity stable 2.0.9 ([#9786](https://github.com/paritytech/parity-ethereum/pull/9786))
|
||||
- Version: bump parity stable to 2.0.9
|
||||
- Ethcore: bump ropsten forkblock checkpoint ([#9775](https://github.com/paritytech/parity-ethereum/pull/9775))
|
||||
- Ethcore: handle vm exception when estimating gas ([#9615](https://github.com/paritytech/parity-ethereum/pull/9615))
|
||||
- Update jsonrpc-core to a1b2bb742ce16d1168669ffb13ffe856e8131228 ([#9780](https://github.com/paritytech/parity-ethereum/pull/9780))
|
||||
- Removed "rustup" & added new runner tag ([#9731](https://github.com/paritytech/parity-ethereum/pull/9731))
|
||||
- Removed "rustup" & added new runner tag
|
||||
- Exchanged tag "rust-windows" with "windows"
|
||||
- Revert windows tag change
|
||||
- Allow zero chain id in EIP155 signing process ([#9792](https://github.com/paritytech/parity-ethereum/pull/9792))
|
||||
- Allow zero chain id in EIP155 signing process
|
||||
- Rename test
|
||||
- Fix test failure
|
||||
- Insert dev account before unlocking ([#9813](https://github.com/paritytech/parity-ethereum/pull/9813))
|
||||
|
||||
## Parity-Ethereum [v2.0.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.8) (2018-10-16)
|
||||
|
||||
Parity-Ethereum 2.0.8-stable is a release that fixes a consensus issue with the recent Constantinople release. Upgrading is mandatory whatever network you are connected to that plans enabling EIP-1283, e.g., Ropsten, Kovan, Ethereum.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,392 +0,0 @@
|
||||
Note: Parity Ethereum 2.2 reached End-of-Life on 2019-02-25 (EOL).
|
||||
|
||||
## Parity-Ethereum [v2.2.11](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.11) (2019-02-21)
|
||||
|
||||
Parity-Ethereum 2.2.11-stable is a maintenance release that fixes snap and docker installations.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Stable: snap: release untagged versions from branches to the candidate ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) ([#10372](https://github.com/paritytech/parity-ethereum/pull/10372))
|
||||
- Snap: release untagged versions from branches to the candidate snap channel ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357))
|
||||
- Snap: add the removable-media plug ([#10377](https://github.com/paritytech/parity-ethereum/pull/10377))
|
||||
- Exchanged old(azure) bootnodes with new(ovh) ones ([#10309](https://github.com/paritytech/parity-ethereum/pull/10309))
|
||||
- Stable Backports ([#10353](https://github.com/paritytech/parity-ethereum/pull/10353))
|
||||
- Version: bump stable to 2.2.11
|
||||
- Snap: prefix version and populate candidate channel ([#10343](https://github.com/paritytech/parity-ethereum/pull/10343))
|
||||
- Snap: populate candidate releases with beta snaps to avoid stale channel
|
||||
- Snap: prefix version with v*
|
||||
- No volumes are needed, just run -v volume:/path/in/the/container ([#10345](https://github.com/paritytech/parity-ethereum/pull/10345))
|
||||
|
||||
## Parity-Ethereum [v2.2.10](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.10) (2019-02-13)
|
||||
|
||||
Parity-Ethereum 2.2.10-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
|
||||
|
||||
- https://www.parity.io/new-parity-ethereum-update-fixes-several-rpc-vulnerabilities/
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Additional error for invalid gas ([#10327](https://github.com/paritytech/parity-ethereum/pull/10327)) ([#10329](https://github.com/paritytech/parity-ethereum/pull/10329))
|
||||
- Backports for Stable 2.2.10 ([#10332](https://github.com/paritytech/parity-ethereum/pull/10332))
|
||||
- fix(docker-aarch64) : cross-compile config ([#9798](https://github.com/paritytech/parity-ethereum/pull/9798))
|
||||
- import rpc transactions sequentially ([#10051](https://github.com/paritytech/parity-ethereum/pull/10051))
|
||||
- fix(docker): fix not receives SIGINT ([#10059](https://github.com/paritytech/parity-ethereum/pull/10059))
|
||||
- snap: official image / test ([#10168](https://github.com/paritytech/parity-ethereum/pull/10168))
|
||||
- perform stripping during build ([#10208](https://github.com/paritytech/parity-ethereum/pull/10208))
|
||||
- Additional tests for uint/hash/bytes deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279))
|
||||
- Don't run the CPP example on CI ([#10285](https://github.com/paritytech/parity-ethereum/pull/10285))
|
||||
- CI optimizations ([#10297](https://github.com/paritytech/parity-ethereum/pull/10297))
|
||||
- fix publish job ([#10317](https://github.com/paritytech/parity-ethereum/pull/10317))
|
||||
- Add Statetest support for Constantinople Fix ([#10323](https://github.com/paritytech/parity-ethereum/pull/10323))
|
||||
- Add helper for Timestamp overflows ([#10330](https://github.com/paritytech/parity-ethereum/pull/10330))
|
||||
- Don't add discovery initiators to the node table ([#10305](https://github.com/paritytech/parity-ethereum/pull/10305))
|
||||
- change docker image based on debian instead of ubuntu due to the chan ([#10336](https://github.com/paritytech/parity-ethereum/pull/10336))
|
||||
- role back docker build image and docker deploy image to ubuntu:xenial based ([#10338](https://github.com/paritytech/parity-ethereum/pull/10338))
|
||||
|
||||
## Parity-Ethereum [v2.2.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.9) (2019-02-03)
|
||||
|
||||
Parity-Ethereum 2.2.9-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
|
||||
|
||||
- https://www.parity.io/security-alert-parity-ethereum-03-02/
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Additional tests for uint deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) ([#10281](https://github.com/paritytech/parity-ethereum/pull/10281))
|
||||
- Version: bump stable to 2.2.9 ([#10282](https://github.com/paritytech/parity-ethereum/pull/10282))
|
||||
|
||||
## Parity-Ethereum [v2.2.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.8) (2019-02-01)
|
||||
|
||||
Parity-Ethereum 2.2.8-stable is a consensus-relevant release that enables _St. Petersfork_ on:
|
||||
|
||||
- Ethereum Block `7280000` (along with Constantinople)
|
||||
- Kovan Block `10255201`
|
||||
- Ropsten Block `4939394`
|
||||
- POA Sokol Block `7026400`
|
||||
|
||||
In addition to this, Constantinople is cancelled for the POA Core network. Upgrading is mandatory for clients on any of these chains.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Backports for stable 2.2.8 ([#10224](https://github.com/paritytech/parity-ethereum/pull/10224))
|
||||
- Update for Android cross-compilation. ([#10180](https://github.com/paritytech/parity-ethereum/pull/10180))
|
||||
- Cancel Constantinople HF on POA Core ([#10198](https://github.com/paritytech/parity-ethereum/pull/10198))
|
||||
- Add EIP-1283 disable transition ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214))
|
||||
- Enable St-Peters-Fork ("Constantinople Fix") ([#10223](https://github.com/paritytech/parity-ethereum/pull/10223))
|
||||
- Stable: Macos heapsize force jemalloc ([#10234](https://github.com/paritytech/parity-ethereum/pull/10234)) ([#10258](https://github.com/paritytech/parity-ethereum/pull/10258))
|
||||
|
||||
## 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))
|
||||
@@ -1,288 +0,0 @@
|
||||
## Parity-Ethereum [v2.3.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.8) (2019-03-22)
|
||||
|
||||
Parity-Ethereum 2.3.8-stable is a bugfix release that improves performance and stability. This patch release contains a critical bug fix where serving light clients previously led to client crashes. Upgrading is highly recommended.
|
||||
|
||||
The full list of included changes:
|
||||
- 2.3.8 stable backports ([#10507](https://github.com/paritytech/parity-ethereum/pull/10507))
|
||||
- Version: bump stable
|
||||
- Add additional request tests ([#10503](https://github.com/paritytech/parity-ethereum/pull/10503))
|
||||
|
||||
## Parity-Ethereum [v2.3.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.7) (2019-03-20)
|
||||
|
||||
Parity-Ethereum 2.3.7-stable is a bugfix release that improves performance and stability.
|
||||
|
||||
The full list of included changes:
|
||||
- 2.3.7 stable backports ([#10487](https://github.com/paritytech/parity-ethereum/pull/10487))
|
||||
- Version: bump stable
|
||||
- Сaching through docker volume ([#10477](https://github.com/paritytech/parity-ethereum/pull/10477))
|
||||
- fix win&mac build ([#10486](https://github.com/paritytech/parity-ethereum/pull/10486))
|
||||
- fix(extract `timestamp_checked_add` as lib) ([#10383](https://github.com/paritytech/parity-ethereum/pull/10383))
|
||||
|
||||
## Parity-Ethereum [v2.3.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.6) (2019-03-19)
|
||||
|
||||
Parity-Ethereum 2.3.6-stable is a bugfix release that improves performance and stability.
|
||||
|
||||
The full list of included changes:
|
||||
- 2.3.6 stable backports ([#10470](https://github.com/paritytech/parity-ethereum/pull/10470))
|
||||
- Version: bump stable
|
||||
- CI publish to aws ([#10446](https://github.com/paritytech/parity-ethereum/pull/10446))
|
||||
- Ensure static validator set changes are recognized ([#10467](https://github.com/paritytech/parity-ethereum/pull/10467))
|
||||
- CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))
|
||||
- Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))" ([#10456](https://github.com/paritytech/parity-ethereum/pull/10456))
|
||||
- Tests parallelized ([#10452](https://github.com/paritytech/parity-ethereum/pull/10452))
|
||||
|
||||
## Parity-Ethereum [v2.3.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.5) (2019-02-25)
|
||||
|
||||
Parity-Ethereum 2.3.5-stable is a bugfix release that improves performance and stability.
|
||||
|
||||
Note, all 2.2 releases and older are now unsupported and upgrading is recommended.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- More Backports for Stable 2.3.5 ([#10430](https://github.com/paritytech/parity-ethereum/pull/10430))
|
||||
- Revert some changes, could be buggy ([#10399](https://github.com/paritytech/parity-ethereum/pull/10399))
|
||||
- Ci: clean up gitlab-ci.yml leftovers from previous merge ([#10429](https://github.com/paritytech/parity-ethereum/pull/10429))
|
||||
- 10000 > 5000 ([#10422](https://github.com/paritytech/parity-ethereum/pull/10422))
|
||||
- Fix underflow in pip, closes [#10419](https://github.com/paritytech/parity-ethereum/pull/10419) ([#10423](https://github.com/paritytech/parity-ethereum/pull/10423))
|
||||
- Fix panic when logging directory does not exist, closes [#10420](https://github.com/paritytech/parity-ethereum/pull/10420) ([#10424](https://github.com/paritytech/parity-ethereum/pull/10424))
|
||||
- Update hardcoded headers for Foundation, Ropsten, Kovan and Classic ([#10417](https://github.com/paritytech/parity-ethereum/pull/10417))
|
||||
- Backports for Stable 2.3.5 ([#10414](https://github.com/paritytech/parity-ethereum/pull/10414))
|
||||
- No-git for publish jobs, empty artifacts dir ([#10393](https://github.com/paritytech/parity-ethereum/pull/10393))
|
||||
- Snap: reenable i386, arm64, armhf architecture publishing ([#10386](https://github.com/paritytech/parity-ethereum/pull/10386))
|
||||
- Tx pool: always accept local transactions ([#10375](https://github.com/paritytech/parity-ethereum/pull/10375))
|
||||
- Fix to_pod storage trie value decoding ([#10368)](https://github.com/paritytech/parity-ethereum/pull/10368))
|
||||
- Version: mark 2.3.5 as stable
|
||||
|
||||
## Parity-Ethereum [v2.3.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.4) (2019-02-21)
|
||||
|
||||
Parity-Ethereum 2.3.4-beta is a maintenance release that fixes snap and docker installations.
|
||||
|
||||
The full list of included changes:
|
||||
- Beta: snap: release untagged versions from branches to the candidate ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) ([#10373](https://github.com/paritytech/parity-ethereum/pull/10373))
|
||||
- Snap: release untagged versions from branches to the candidate snap channel ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357))
|
||||
- Snap: add the removable-media plug ([#10377](https://github.com/paritytech/parity-ethereum/pull/10377))
|
||||
- Exchanged old(azure) bootnodes with new(ovh) ones ([#10309](https://github.com/paritytech/parity-ethereum/pull/10309))
|
||||
- Beta Backports ([#10354](https://github.com/paritytech/parity-ethereum/pull/10354))
|
||||
- Version: bump beta to 2.3.4
|
||||
- Snap: prefix version and populate candidate channel ([#10343](https://github.com/paritytech/parity-ethereum/pull/10343))
|
||||
- Snap: populate candidate releases with beta snaps to avoid stale channel
|
||||
- Snap: prefix version with v*
|
||||
- No volumes are needed, just run -v volume:/path/in/the/container ([#10345](https://github.com/paritytech/parity-ethereum/pull/10345))
|
||||
|
||||
## Parity-Ethereum [v2.3.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.3) (2019-02-13)
|
||||
|
||||
Parity-Ethereum 2.3.3-beta is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
|
||||
|
||||
- https://www.parity.io/new-parity-ethereum-update-fixes-several-rpc-vulnerabilities/
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Additional error for invalid gas ([#10327](https://github.com/paritytech/parity-ethereum/pull/10327)) ([#10328](https://github.com/paritytech/parity-ethereum/pull/10328))
|
||||
- Backports for Beta 2.3.3 ([#10333](https://github.com/paritytech/parity-ethereum/pull/10333))
|
||||
- Properly handle check_epoch_end_signal errors ([#10015](https://github.com/paritytech/parity-ethereum/pull/10015))
|
||||
- import rpc transactions sequentially ([#10051](https://github.com/paritytech/parity-ethereum/pull/10051))
|
||||
- fix(docker): fix not receives SIGINT ([#10059](https://github.com/paritytech/parity-ethereum/pull/10059))
|
||||
- snap: official image / test ([#10168](https://github.com/paritytech/parity-ethereum/pull/10168))
|
||||
- Extract CallContract and RegistryInfo traits into their own crate ([#10178](https://github.com/paritytech/parity-ethereum/pull/10178))
|
||||
- perform stripping during build ([#10208](https://github.com/paritytech/parity-ethereum/pull/10208))
|
||||
- Remove CallContract and RegistryInfo re-exports from `ethcore/client` ([#10205](https://github.com/paritytech/parity-ethereum/pull/10205))
|
||||
- fixed: types::transaction::SignedTransaction; ([#10229](https://github.com/paritytech/parity-ethereum/pull/10229))
|
||||
- Additional tests for uint/hash/bytes deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279))
|
||||
- Fix Windows build ([#10284](https://github.com/paritytech/parity-ethereum/pull/10284))
|
||||
- Don't run the CPP example on CI ([#10285](https://github.com/paritytech/parity-ethereum/pull/10285))
|
||||
- CI optimizations ([#10297](https://github.com/paritytech/parity-ethereum/pull/10297))
|
||||
- fix publish job ([#10317](https://github.com/paritytech/parity-ethereum/pull/10317))
|
||||
- Add Statetest support for Constantinople Fix ([#10323](https://github.com/paritytech/parity-ethereum/pull/10323))
|
||||
- Add helper for Timestamp overflows ([#10330](https://github.com/paritytech/parity-ethereum/pull/10330))
|
||||
- Don't add discovery initiators to the node table ([#10305](https://github.com/paritytech/parity-ethereum/pull/10305))
|
||||
- change docker image based on debian instead of ubuntu due to the chan ([#10336](https://github.com/paritytech/parity-ethereum/pull/10336))
|
||||
- role back docker build image and docker deploy image to ubuntu:xenial based ([#10338](https://github.com/paritytech/parity-ethereum/pull/10338))
|
||||
|
||||
## Parity-Ethereum [v2.3.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.2) (2019-02-03)
|
||||
|
||||
Parity-Ethereum 2.3.2-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
|
||||
|
||||
- https://www.parity.io/security-alert-parity-ethereum-03-02/
|
||||
|
||||
The full list of included changes:
|
||||
- Version: bump beta to 2.3.2 ([#10283](https://github.com/paritytech/parity-ethereum/pull/10283))
|
||||
- Additional tests for uint deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) ([#10280](https://github.com/paritytech/parity-ethereum/pull/10280))
|
||||
- Backport [#10285](https://github.com/paritytech/parity-ethereum/pull/10285) to beta ([#10286](https://github.com/paritytech/parity-ethereum/pull/10286))
|
||||
|
||||
## Parity-Ethereum [v2.3.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.1) (2019-02-01)
|
||||
|
||||
Parity-Ethereum 2.3.1-beta is a consensus-relevant release that enables _St. Petersfork_ on:
|
||||
|
||||
- Ethereum Block `7280000` (along with Constantinople)
|
||||
- Kovan Block `10255201`
|
||||
- Ropsten Block `4939394`
|
||||
- POA Sokol Block `7026400`
|
||||
|
||||
In addition to this, Constantinople is cancelled for the POA Core network. Upgrading is mandatory for clients on any of these chains.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Backports for beta 2.3.1 ([#10225](https://github.com/paritytech/parity-ethereum/pull/10225))
|
||||
- Fix _cannot recursively call into `Core`_ issue ([#10144](https://github.com/paritytech/parity-ethereum/pull/10144))
|
||||
- Update for Android cross-compilation. ([#10180](https://github.com/paritytech/parity-ethereum/pull/10180))
|
||||
- Fix _cannot recursively call into `Core`_ - Part 2 ([#10195](https://github.com/paritytech/parity-ethereum/pull/10195))
|
||||
- Cancel Constantinople HF on POA Core ([#10198](https://github.com/paritytech/parity-ethereum/pull/10198))
|
||||
- Add EIP-1283 disable transition ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214))
|
||||
- Enable St-Peters-Fork ("Constantinople Fix") ([#10223](https://github.com/paritytech/parity-ethereum/pull/10223))
|
||||
- Beta: Macos heapsize force jemalloc ([#10234](https://github.com/paritytech/parity-ethereum/pull/10234)) ([#10259](https://github.com/paritytech/parity-ethereum/pull/10259))
|
||||
|
||||
## Parity-Ethereum [v2.3.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.0) (2019-01-16)
|
||||
|
||||
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.
|
||||
|
||||
- **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))
|
||||
|
||||
Other notable changes:
|
||||
|
||||
- Existing blocks in the database are now kept when restoring a Snapshot. ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643))
|
||||
- Block and transaction propagation is improved significantly. ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954))
|
||||
- The ERC-191 Signed Data Standard is now supported by `personal_sign191`. ([#9701](https://github.com/paritytech/parity-ethereum/pull/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](https://github.com/paritytech/parity-ethereum/pull/9631))
|
||||
- Add support for ERC-1186 `eth_getProof` ([#9001](https://github.com/paritytech/parity-ethereum/pull/9001))
|
||||
- Add experimental RPCs flag to enable ERC-191, ERC-712, and ERC-1186 APIs via `--jsonrpc-experimental` ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928))
|
||||
- Make `CALLCODE` to trace value to be the code address. ([#9881](https://github.com/paritytech/parity-ethereum/pull/9881))
|
||||
|
||||
Configuration changes:
|
||||
|
||||
- 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](https://github.com/paritytech/parity-ethereum/pull/9955))
|
||||
- Also, unknown fields in chain specs are now rejected. ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972))
|
||||
- The Tendermint engine was removed from Parity Ethereum and is no longer available and maintained. ([#9980](https://github.com/paritytech/parity-ethereum/pull/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](https://github.com/paritytech/parity-ethereum/pull/10123))
|
||||
- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/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_.
|
||||
|
||||
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))
|
||||
@@ -1,128 +0,0 @@
|
||||
## Parity-Ethereum [v2.4.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.9)
|
||||
|
||||
Parity Ethereum v2.4.9-stable is a security update which addresses servo/rust-smallvec#148
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* cargo update -p smallvec ([#10822](https://github.com/paritytech/parity-ethereum/pull/10822))
|
||||
|
||||
## Parity-Ethereum [v2.4.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.8)
|
||||
|
||||
Parity-Ethereum 2.4.8-stable is a bugfix release that improves performance and stability.
|
||||
|
||||
* Blockchain: fix reset chain
|
||||
* State tests: treat empty accounts the same as non-existant accounts (EIP 1052)
|
||||
* Aura: fix Timestamp Overflow
|
||||
* Networking: support discovery-only peers (geth bootnodes)
|
||||
* Snapshotting: fix unclean shutdown while snappshotting is under way
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/paritytech/parity-ethereum/pull/10766))
|
||||
* fix docker tags for publishing ([#10741](https://github.com/paritytech/parity-ethereum/pull/10741))
|
||||
* Reset blockchain properly ([#10669](https://github.com/paritytech/parity-ethereum/pull/10669))
|
||||
* adds rpc error message for --no-ancient-blocks ([#10608](https://github.com/paritytech/parity-ethereum/pull/10608))
|
||||
* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/paritytech/parity-ethereum/pull/10775))
|
||||
* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720))
|
||||
* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/paritytech/parity-ethereum/pull/10705))
|
||||
* Revert "fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720))"
|
||||
* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/paritytech/parity-ethereum/pull/10744))
|
||||
|
||||
## Parity-Ethereum [v2.4.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.7)
|
||||
|
||||
Parity-Ethereum 2.4.7-stable is a bugfix release that improves performance and stability.
|
||||
|
||||
Among others, it enables the _Atlantis_ hardfork on **Morden** and **Kotti** Classic networks.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* [CI] allow cargo audit to fail ([#10676](https://github.com/paritytech/parity-ethereum/pull/10676))
|
||||
* new image ([#10673](https://github.com/paritytech/parity-ethereum/pull/10673))
|
||||
* Update publishing ([#10644](https://github.com/paritytech/parity-ethereum/pull/10644))
|
||||
* enable lto for release builds ([#10717](https://github.com/paritytech/parity-ethereum/pull/10717))
|
||||
* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/paritytech/parity-ethereum/pull/10719))
|
||||
* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/paritytech/parity-ethereum/pull/10731))
|
||||
|
||||
## Parity-Ethereum [v2.4.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.6)
|
||||
|
||||
Parity-Ethereum 2.4.6-stable is a bugfix release that improves performance and stability.
|
||||
|
||||
Among others, it enables the Petersburg hardfork on **Rinkeby** and **POA-Core** Network, as well as the **Kovan** Network community hardfork.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ci: publish docs debug ([#10638](https://github.com/paritytech/parity-ethereum/pull/10638))
|
||||
|
||||
## Parity-Ethereum [v2.4.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.5)
|
||||
|
||||
Parity-Ethereum 2.4.5-stable is a bugfix release that improves performance and stability. This release improves memory optimizations around timestamp handling and stabilizes the 2.4 release branch.
|
||||
|
||||
As of today, Parity-Ethereum 2.3 reaches end of life and everyone is encouraged to upgrade.
|
||||
|
||||
## Parity-Ethereum [v2.4.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.4)
|
||||
|
||||
Parity-Ethereum 2.4.4-beta is a bugfix release that improves performance and stability. This patch release removes the dead chain configs for Easthub and Ethereum Social.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* fix(rpc-types): replace uint and hash with `ethereum_types v0.4` ([#10217](https://github.com/paritytech/parity-ethereum/pull/10217))
|
||||
* chore(bump ethereum-types) ([#10396](https://github.com/paritytech/parity-ethereum/pull/10396))
|
||||
* fix(light eth_gasPrice): ask network if not in cache ([#10535](https://github.com/paritytech/parity-ethereum/pull/10535))
|
||||
* fix(light account response): update `tx_queue` ([#10545](https://github.com/paritytech/parity-ethereum/pull/10545))
|
||||
* fix(bump dependencies) ([#10540](https://github.com/paritytech/parity-ethereum/pull/10540))
|
||||
* tx-pool: check transaction readiness before replacing ([#10526](https://github.com/paritytech/parity-ethereum/pull/10526))
|
||||
* fix #10390 ([#10391](https://github.com/paritytech/parity-ethereum/pull/10391))
|
||||
* private-tx: replace error_chain ([#10510](https://github.com/paritytech/parity-ethereum/pull/10510))
|
||||
|
||||
## Parity-Ethereum [v2.4.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.3)
|
||||
|
||||
Parity-Ethereum 2.4.3-beta is a bugfix release that improves performance and stability. This patch release contains a critical bug fix where serving light clients previously led to client crashes. Upgrading is highly recommended.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* Add additional request tests ([#10503](https://github.com/paritytech/parity-ethereum/pull/10503))
|
||||
|
||||
## Parity-Ethereum [v2.4.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.2)
|
||||
|
||||
Parity-Ethereum 2.4.2-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* Сaching through docker volume ([#10477](https://github.com/paritytech/parity-ethereum/pull/10477))
|
||||
* fix win&mac build ([#10486](https://github.com/paritytech/parity-ethereum/pull/10486))
|
||||
* fix(extract `timestamp_checked_add` as lib) ([#10383](https://github.com/paritytech/parity-ethereum/pull/10383))
|
||||
|
||||
## Parity-Ethereum [v2.4.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.1)
|
||||
|
||||
Parity-Ethereum 2.4.1-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* Implement parity_versionInfo & parity_setChain on LC; fix parity_setChain ([#10312](https://github.com/paritytech/parity-ethereum/pull/10312))
|
||||
* CI publish to aws ([#10446](https://github.com/paritytech/parity-ethereum/pull/10446))
|
||||
* CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))
|
||||
* Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))" (#10456)
|
||||
* Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))"
|
||||
* Tests parallelized ([#10452](https://github.com/paritytech/parity-ethereum/pull/10452))
|
||||
* Ensure static validator set changes are recognized ([#10467](https://github.com/paritytech/parity-ethereum/pull/10467))
|
||||
|
||||
## Parity-Ethereum [v2.4.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.0)
|
||||
|
||||
Parity-Ethereum 2.4.0-beta is our trifortnightly minor version release coming with a lot of new features as well as bugfixes and performance improvements.
|
||||
|
||||
Notable changes:
|
||||
- Account management is now deprecated ([#10213](https://github.com/paritytech/parity-ethereum/pull/10213))
|
||||
- Local accounts can now be specified via CLI ([#9960](https://github.com/paritytech/parity-ethereum/pull/9960))
|
||||
- Chains can now be reset to a particular block via CLI ([#9782](https://github.com/paritytech/parity-ethereum/pull/9782))
|
||||
- Ethash now additionally implements ProgPoW ([#9762](https://github.com/paritytech/parity-ethereum/pull/9762))
|
||||
- The `eip1283DisableTransition` flag was added to revert EIP-1283 ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214))
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* revert some changes, could be buggy ([#10399](https://github.com/paritytech/parity-ethereum/pull/10399))
|
||||
* 10000 > 5000 ([#10422](https://github.com/paritytech/parity-ethereum/pull/10422))
|
||||
* fix panic when logging directory does not exist, closes #10420 ([#10424](https://github.com/paritytech/parity-ethereum/pull/10424))
|
||||
* fix underflow in pip, closes #10419 ([#10423](https://github.com/paritytech/parity-ethereum/pull/10423))
|
||||
* ci: clean up gitlab-ci.yml leftovers from previous merge ([#10429](https://github.com/paritytech/parity-ethereum/pull/10429))
|
||||
* Update hardcoded headers for Foundation, Ropsten, Kovan and Classic ([#10417](https://github.com/paritytech/parity-ethereum/pull/10417))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[package]
|
||||
description = "Parity Ethereum Ethash & ProgPoW Implementations"
|
||||
name = "ethash"
|
||||
version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
@@ -7,27 +6,15 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
crunchy = "0.1.0"
|
||||
either = "1.0.0"
|
||||
ethereum-types = "0.6.0"
|
||||
keccak-hash = "0.2.0"
|
||||
ethereum-types = "0.4"
|
||||
keccak-hash = "0.1"
|
||||
log = "0.4"
|
||||
memmap = "0.6"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.6"
|
||||
primal = "0.2.3"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.2"
|
||||
rustc-hex = "1.0"
|
||||
serde_json = "1.0"
|
||||
tempdir = "0.3"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
bench = []
|
||||
|
||||
[[bench]]
|
||||
name = "basic"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "progpow"
|
||||
harness = false
|
||||
benches = []
|
||||
|
||||
@@ -1,113 +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/>.
|
||||
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
extern crate ethash;
|
||||
|
||||
use criterion::Criterion;
|
||||
use ethash::{NodeCacheBuilder, OptimizeFor};
|
||||
|
||||
const HASH: [u8; 32] = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe,
|
||||
0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f,
|
||||
0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72];
|
||||
const NONCE: u64 = 0xd7b3ac70a301a249;
|
||||
|
||||
criterion_group!(
|
||||
basic,
|
||||
bench_light_compute_memmap,
|
||||
bench_light_compute_memory,
|
||||
bench_light_new_round_trip_memmap,
|
||||
bench_light_new_round_trip_memory,
|
||||
bench_light_from_file_round_trip_memory,
|
||||
bench_light_from_file_round_trip_memmap
|
||||
);
|
||||
criterion_main!(basic);
|
||||
|
||||
fn bench_light_compute_memmap(b: &mut Criterion) {
|
||||
use std::env;
|
||||
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
|
||||
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())));
|
||||
}
|
||||
|
||||
fn bench_light_compute_memory(b: &mut Criterion) {
|
||||
use std::env;
|
||||
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
|
||||
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())));
|
||||
}
|
||||
|
||||
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 light = builder.light(&env::temp_dir(), 486382);
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
}));
|
||||
}
|
||||
|
||||
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 light = builder.light(&env::temp_dir(), 486382);
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
}));
|
||||
}
|
||||
|
||||
fn bench_light_from_file_round_trip_memory(b: &mut Criterion) {
|
||||
use std::env;
|
||||
|
||||
let dir = env::temp_dir();
|
||||
let height = 486382;
|
||||
{
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
|
||||
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 light = builder.light_from_file(&dir, 486382).unwrap();
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
}));
|
||||
}
|
||||
|
||||
fn bench_light_from_file_round_trip_memmap(b: &mut Criterion) {
|
||||
use std::env;
|
||||
|
||||
let dir = env::temp_dir();
|
||||
let height = 486382;
|
||||
|
||||
{
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
|
||||
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 light = builder.light_from_file(&dir, 486382).unwrap();
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
}));
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
]
|
||||
]
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use compute::Light;
|
||||
use either::Either;
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Ethash implementation
|
||||
//! See https://github.com/ethereum/wiki/wiki/Ethash
|
||||
@@ -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();
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate keccak_hash as hash;
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![cfg_attr(feature = "benches", feature(test))]
|
||||
|
||||
extern crate either;
|
||||
extern crate ethereum_types;
|
||||
@@ -25,41 +27,26 @@ 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;
|
||||
use ethereum_types::{BigEndianHash, U256, U512};
|
||||
use ethereum_types::{U256, U512};
|
||||
use keccak::H256;
|
||||
use parking_lot::Mutex;
|
||||
pub use seed_compute::SeedHashCompute;
|
||||
pub use shared::ETHASH_EPOCH_LENGTH;
|
||||
use std::mem;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
struct LightCache {
|
||||
@@ -74,16 +61,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 +87,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,18 +134,18 @@ impl EthashManager {
|
||||
Some(light) => light,
|
||||
}
|
||||
};
|
||||
light.compute(header_hash, nonce, block_number)
|
||||
light.compute(header_hash, nonce)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn boundary_to_difficulty(boundary: ðereum_types::H256) -> U256 {
|
||||
difficulty_to_boundary_aux(&boundary.into_uint())
|
||||
difficulty_to_boundary_aux(&**boundary)
|
||||
}
|
||||
|
||||
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn difficulty_to_boundary(difficulty: &U256) -> ethereum_types::H256 {
|
||||
BigEndianHash::from_uint(&difficulty_to_boundary_aux(difficulty))
|
||||
difficulty_to_boundary_aux(difficulty).into()
|
||||
}
|
||||
|
||||
fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U256 {
|
||||
@@ -177,8 +156,8 @@ fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U
|
||||
if difficulty == U512::one() {
|
||||
U256::max_value()
|
||||
} else {
|
||||
const PROOF: &str = "difficulty > 1, so result never overflows 256 bits; qed";
|
||||
U256::try_from((U512::one() << 256) / difficulty).expect(PROOF)
|
||||
// difficulty > 1, so result should never overflow 256 bits
|
||||
U256::from((U512::one() << 256) / difficulty)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +166,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);
|
||||
@@ -203,10 +182,10 @@ fn test_lru() {
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary() {
|
||||
use ethereum_types::{H256, BigEndianHash};
|
||||
use ethereum_types::H256;
|
||||
use std::str::FromStr;
|
||||
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(1)), BigEndianHash::from_uint(&U256::max_value()));
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
@@ -220,18 +199,9 @@ fn test_difficulty_to_boundary_regression() {
|
||||
// https://github.com/paritytech/parity-ethereum/issues/8397
|
||||
for difficulty in 1..9 {
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&difficulty_to_boundary(&difficulty.into())));
|
||||
assert_eq!(
|
||||
H256::from_low_u64_be(difficulty),
|
||||
difficulty_to_boundary(&boundary_to_difficulty(&H256::from_low_u64_be(difficulty))),
|
||||
);
|
||||
assert_eq!(
|
||||
U256::from(difficulty),
|
||||
boundary_to_difficulty(&BigEndianHash::from_uint(&boundary_to_difficulty(&H256::from_low_u64_be(difficulty)))),
|
||||
);
|
||||
assert_eq!(
|
||||
H256::from_low_u64_be(difficulty),
|
||||
difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into_uint()),
|
||||
);
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&boundary_to_difficulty(&difficulty.into())));
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&boundary_to_difficulty(&difficulty.into()).into()));
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,5 +214,102 @@ fn test_difficulty_to_boundary_panics_on_zero() {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_boundary_to_difficulty_panics_on_zero() {
|
||||
boundary_to_difficulty(ðereum_types::H256::zero());
|
||||
boundary_to_difficulty(ðereum_types::H256::from(0));
|
||||
}
|
||||
|
||||
#[cfg(feature = "benches")]
|
||||
mod benchmarks {
|
||||
extern crate test;
|
||||
|
||||
use self::test::Bencher;
|
||||
use cache::{NodeCacheBuilder, OptimizeFor};
|
||||
use compute::{Light, light_compute};
|
||||
|
||||
const HASH: [u8; 32] = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe,
|
||||
0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f,
|
||||
0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72];
|
||||
const NONCE: u64 = 0xd7b3ac70a301a249;
|
||||
|
||||
#[bench]
|
||||
fn bench_light_compute_memmap(b: &mut Bencher) {
|
||||
use std::env;
|
||||
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
|
||||
let light = builder.light(&env::temp_dir(), 486382);
|
||||
|
||||
b.iter(|| light_compute(&light, &HASH, NONCE));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_light_compute_memory(b: &mut Bencher) {
|
||||
use std::env;
|
||||
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
|
||||
let light = builder.light(&env::temp_dir(), 486382);
|
||||
|
||||
b.iter(|| light_compute(&light, &HASH, NONCE));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[ignore]
|
||||
fn bench_light_new_round_trip_memmap(b: &mut Bencher) {
|
||||
use std::env;
|
||||
|
||||
b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
|
||||
let light = builder.light(&env::temp_dir(), 486382);
|
||||
light_compute(&light, &HASH, NONCE);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[ignore]
|
||||
fn bench_light_new_round_trip_memory(b: &mut Bencher) {
|
||||
use std::env;
|
||||
|
||||
b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
|
||||
let light = builder.light(&env::temp_dir(), 486382);
|
||||
light_compute(&light, &HASH, NONCE);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_light_from_file_round_trip_memory(b: &mut Bencher) {
|
||||
use std::env;
|
||||
|
||||
let dir = env::temp_dir();
|
||||
let height = 486382;
|
||||
{
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
|
||||
let mut dummy = builder.light(&dir, height);
|
||||
dummy.to_file().unwrap();
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu);
|
||||
let light = builder.light_from_file(&dir, 486382).unwrap();
|
||||
light_compute(&light, &HASH, NONCE);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_light_from_file_round_trip_memmap(b: &mut Bencher) {
|
||||
use std::env;
|
||||
|
||||
let dir = env::temp_dir();
|
||||
let height = 486382;
|
||||
|
||||
{
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
|
||||
let mut dummy = builder.light(&dir, height);
|
||||
dummy.to_file().unwrap();
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory);
|
||||
let light = builder.light_from_file(&dir, 486382).unwrap();
|
||||
light_compute(&light, &HASH, NONCE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,611 +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/>.
|
||||
|
||||
//! ProgPoW (Programmatic Proof-of-Work) is the Ethereum network's proposed new Application-Specific Integrated
|
||||
//! Circuit (ASIC) resistant Proof-of-Work mining algorithm.
|
||||
//!
|
||||
//! ProgPoW's aim is to reduce the efficiencies of specialized mining devices known as ASIC chips
|
||||
//! (and accelerated GPU-based setups), and to maximize the performance of General Purpose Hardware (GPUs) to enable
|
||||
//! more users to compete for new cryptocurrency awarded by the protocol.
|
||||
//!
|
||||
//! ASIC chips are those that are tailored to efficiently mining cryptocurrency based on a specific hashing algorithm.
|
||||
//!
|
||||
//! GPU mining setups are less specialised are struggle to compete for mining rewards.
|
||||
//!
|
||||
//! It would be a change from Ethereum's current PoW mining algorithm known as Ethash.
|
||||
//!
|
||||
//! ProgPoW audits have been proposed to analyse the efficiency of a ProgPoW ASICs over
|
||||
//! GPUs and analysis of the economic impact on the Ethereum protocol.
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use shared;
|
||||
use keccak::{keccak_256, H256};
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use primal::is_prime;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
description = "Parity Ethereum (EthCore) Library"
|
||||
description = "Ethcore library"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore"
|
||||
@@ -7,86 +7,78 @@ version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
account-db = { path = "account-db" }
|
||||
ansi_term = "0.11"
|
||||
blooms-db = { path = "../util/blooms-db", optional = true }
|
||||
ansi_term = "0.10"
|
||||
blooms-db = { path = "../util/blooms-db" }
|
||||
bn = { git = "https://github.com/paritytech/bn", default-features = false }
|
||||
byteorder = "1.0"
|
||||
common-types = { path = "types" }
|
||||
crossbeam-utils = "0.6"
|
||||
derive_more = "0.14.0"
|
||||
env_logger = { version = "0.5", optional = true }
|
||||
ethabi = "8.0"
|
||||
ethabi-contract = "8.0"
|
||||
ethabi-derive = "8.0"
|
||||
crossbeam = "0.4"
|
||||
ethash = { path = "../ethash" }
|
||||
ethcore-blockchain = { path = "./blockchain" }
|
||||
ethcore-bloom-journal = { path = "../util/bloom" }
|
||||
ethcore-call-contract = { path = "./call-contract" }
|
||||
ethcore-db = { path = "./db" }
|
||||
parity-bytes = "0.1"
|
||||
hashdb = "0.3.0"
|
||||
memorydb = "0.3.0"
|
||||
patricia-trie = "0.3.0"
|
||||
patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" }
|
||||
parity-crypto = "0.2"
|
||||
error-chain = { version = "0.12", default-features = false }
|
||||
ethcore-io = { path = "../util/io" }
|
||||
ethcore-logger = { path = "../logger" }
|
||||
ethcore-miner = { path = "../miner" }
|
||||
ethcore-stratum = { path = "../miner/stratum", optional = true }
|
||||
ethereum-types = "0.6.0"
|
||||
ethcore-stratum = { path = "./stratum", optional = true }
|
||||
ethcore-transaction = { path = "./transaction" }
|
||||
ethereum-types = "0.4"
|
||||
memory-cache = { path = "../util/memory_cache" }
|
||||
ethabi = "6.0"
|
||||
ethabi-derive = "6.0"
|
||||
ethabi-contract = "6.0"
|
||||
ethjson = { path = "../json" }
|
||||
ethkey = { path = "../accounts/ethkey" }
|
||||
ethkey = { path = "../ethkey" }
|
||||
ethstore = { path = "../ethstore" }
|
||||
evm = { path = "evm" }
|
||||
futures = "0.1"
|
||||
hash-db = "0.12.4"
|
||||
parity-util-mem = "0.1"
|
||||
heapsize = "0.4"
|
||||
itertools = "0.5"
|
||||
journaldb = { path = "../util/journaldb" }
|
||||
keccak-hash = "0.2.0"
|
||||
keccak-hasher = { path = "../util/keccak-hasher" }
|
||||
kvdb = "0.1"
|
||||
kvdb-memorydb = "0.1"
|
||||
kvdb-rocksdb = { version = "0.1.3", optional = true }
|
||||
lazy_static = "1.2.0"
|
||||
len-caching-lock = { path = "../util/len-caching-lock" }
|
||||
lazy_static = "1.0"
|
||||
log = "0.4"
|
||||
lru-cache = "0.1"
|
||||
macros = { path = "../util/macros" }
|
||||
memory-cache = { path = "../util/memory-cache" }
|
||||
memory-db = "0.12.4"
|
||||
num = { version = "0.1", default-features = false, features = ["bigint"] }
|
||||
num_cpus = "1.2"
|
||||
parity-bytes = "0.1"
|
||||
parity-crypto = "0.4.0"
|
||||
parity-machine = { path = "../machine" }
|
||||
parking_lot = "0.6"
|
||||
rayon = "1.0"
|
||||
rand = "0.4"
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rlp_compress = { path = "../util/rlp_compress" }
|
||||
rlp_derive = { path = "../util/rlp_derive" }
|
||||
kvdb = "0.1"
|
||||
kvdb-memorydb = "0.1"
|
||||
parity-snappy = "0.1"
|
||||
parking_lot = "0.7"
|
||||
pod-account = { path = "pod-account" }
|
||||
trie-db = "0.12.4"
|
||||
patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" }
|
||||
rand = "0.6"
|
||||
rayon = "1.1"
|
||||
rlp = "0.4.0"
|
||||
rlp_derive = { path = "../util/rlp-derive" }
|
||||
stop-guard = { path = "../util/stop-guard" }
|
||||
macros = { path = "../util/macros" }
|
||||
rustc-hex = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
state-account = { path = "state-account" }
|
||||
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" }
|
||||
using_queue = { path = "../miner/using-queue" }
|
||||
using_queue = { path = "../util/using_queue" }
|
||||
vm = { path = "vm" }
|
||||
wasm = { path = "wasm" }
|
||||
rand_xorshift = "0.1.1"
|
||||
keccak-hash = "0.1"
|
||||
triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" }
|
||||
unexpected = { path = "../util/unexpected" }
|
||||
journaldb = { path = "../util/journaldb" }
|
||||
keccak-hasher = { path = "../util/keccak-hasher" }
|
||||
kvdb-rocksdb = "0.1.3"
|
||||
tempdir = {version="0.3", optional = true}
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))'.dependencies]
|
||||
hardware-wallet = { path = "../hw" }
|
||||
|
||||
[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))'.dependencies]
|
||||
fake-hardware-wallet = { path = "../util/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" }
|
||||
serde_json = "1.0"
|
||||
env_logger = "0.4"
|
||||
tempdir = "0.3"
|
||||
trie-standardmap = "0.12.4"
|
||||
trie-standardmap = "0.1"
|
||||
|
||||
[features]
|
||||
parity = ["work-notify", "price-info", "stratum"]
|
||||
@@ -110,16 +102,12 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
|
||||
# EVM debug traces are printed.
|
||||
slow-blocks = []
|
||||
# Run JSON consensus tests.
|
||||
json-tests = ["env_logger", "test-helpers", "to-pod-full"]
|
||||
json-tests = ["ethcore-transaction/json-tests", "test-helpers", "tempdir"]
|
||||
# Skip JSON consensus tests with pending issues.
|
||||
ci-skip-tests = []
|
||||
ci-skip-issue = []
|
||||
# Run memory/cpu heavy tests.
|
||||
test-heavy = []
|
||||
# Compile benches
|
||||
benches = []
|
||||
# Compile test helpers
|
||||
test-helpers = ["tempdir", "kvdb-rocksdb", "blooms-db"]
|
||||
# Enables slow 'to-pod-full' method for use in tests and evmbin.
|
||||
to-pod-full = []
|
||||
|
||||
[[bench]]
|
||||
name = "builtin"
|
||||
harness = false
|
||||
test-helpers = ["tempdir"]
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
[package]
|
||||
description = "DB backend wrapper for Account trie"
|
||||
name = "account-db"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.6"
|
||||
hash-db = "0.12.4"
|
||||
keccak-hash = "0.2.0"
|
||||
keccak-hasher = { path = "../../util/keccak-hasher" }
|
||||
kvdb = "0.1"
|
||||
rlp = "0.4"
|
||||
@@ -1,262 +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/>.
|
||||
|
||||
//! DB backend wrapper for Account trie
|
||||
use ethereum_types::H256;
|
||||
use keccak_hash::{KECCAK_NULL_RLP, keccak};
|
||||
use hash_db::{HashDB, AsHashDB, Prefix};
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use kvdb::DBValue;
|
||||
use rlp::NULL_RLP;
|
||||
|
||||
// Combines a key with an address hash to ensure uniqueness.
|
||||
// leaves the first 96 bits untouched in order to support partial key lookup.
|
||||
#[inline]
|
||||
fn combine_key<'a>(address_hash: &'a H256, key: &'a H256) -> H256 {
|
||||
let mut dst = key.clone();
|
||||
{
|
||||
let last_src: &[u8] = address_hash.as_bytes();
|
||||
let last_dst: &mut [u8] = dst.as_bytes_mut();
|
||||
for (k, a) in last_dst[12..].iter_mut().zip(&last_src[12..]) {
|
||||
*k ^= *a
|
||||
}
|
||||
}
|
||||
|
||||
dst
|
||||
}
|
||||
|
||||
/// A factory for different kinds of account dbs.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Factory {
|
||||
/// Mangle hashes based on address. This is the default.
|
||||
Mangled,
|
||||
/// Don't mangle hashes.
|
||||
Plain,
|
||||
}
|
||||
|
||||
impl Default for Factory {
|
||||
fn default() -> Self { Factory::Mangled }
|
||||
}
|
||||
|
||||
impl Factory {
|
||||
/// Create a read-only accountdb.
|
||||
/// This will panic when write operations are called.
|
||||
pub fn readonly<'db>(&self, db: &'db dyn HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<dyn HashDB<KeccakHasher, DBValue> + 'db> {
|
||||
match *self {
|
||||
Factory::Mangled => Box::new(AccountDB::from_hash(db, address_hash)),
|
||||
Factory::Plain => Box::new(Wrapping(db)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new mutable hashdb.
|
||||
pub fn create<'db>(&self, db: &'db mut dyn HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<dyn HashDB<KeccakHasher, DBValue> + 'db> {
|
||||
match *self {
|
||||
Factory::Mangled => Box::new(AccountDBMut::from_hash(db, address_hash)),
|
||||
Factory::Plain => Box::new(WrappingMut(db)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: introduce HashDBMut?
|
||||
/// DB backend wrapper for Account trie
|
||||
/// Transforms trie node keys for the database
|
||||
pub struct AccountDB<'db> {
|
||||
db: &'db dyn HashDB<KeccakHasher, DBValue>,
|
||||
address_hash: H256,
|
||||
}
|
||||
|
||||
impl<'db> AccountDB<'db> {
|
||||
/// Create a new AccountDB from an address' hash.
|
||||
pub fn from_hash(db: &'db dyn HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
|
||||
AccountDB { db, address_hash }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDB<'db> {
|
||||
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDB<'db> {
|
||||
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return Some(DBValue::from_slice(&NULL_RLP));
|
||||
}
|
||||
self.db.get(&combine_key(&self.address_hash, key), prefix)
|
||||
}
|
||||
|
||||
fn contains(&self, key: &H256, prefix: Prefix) -> bool {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return true;
|
||||
}
|
||||
self.db.contains(&combine_key(&self.address_hash, key), prefix)
|
||||
}
|
||||
|
||||
fn insert(&mut self, _prefix: Prefix, _value: &[u8]) -> H256 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn emplace(&mut self, _key: H256, _prefix: Prefix, _value: DBValue) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn remove(&mut self, _key: &H256, _prefix: Prefix) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// DB backend wrapper for Account trie
|
||||
pub struct AccountDBMut<'db> {
|
||||
db: &'db mut dyn HashDB<KeccakHasher, DBValue>,
|
||||
address_hash: H256,
|
||||
}
|
||||
|
||||
impl<'db> AccountDBMut<'db> {
|
||||
/// Create a new `AccountDBMut` from an address' hash.
|
||||
pub fn from_hash(db: &'db mut dyn HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
|
||||
AccountDBMut { db, address_hash }
|
||||
}
|
||||
|
||||
/// Create an `AccountDB` from an `AccountDBMut` (used in tests).
|
||||
pub fn immutable(&'db self) -> AccountDB<'db> {
|
||||
AccountDB { db: self.db, address_hash: self.address_hash.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDBMut<'db>{
|
||||
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return Some(DBValue::from_slice(&NULL_RLP));
|
||||
}
|
||||
self.db.get(&combine_key(&self.address_hash, key), prefix)
|
||||
}
|
||||
|
||||
fn contains(&self, key: &H256, prefix: Prefix) -> bool {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return true;
|
||||
}
|
||||
self.db.contains(&combine_key(&self.address_hash, key), prefix)
|
||||
}
|
||||
|
||||
fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H256 {
|
||||
if value == &NULL_RLP {
|
||||
return KECCAK_NULL_RLP.clone();
|
||||
}
|
||||
let k = keccak(value);
|
||||
let ak = combine_key(&self.address_hash, &k);
|
||||
self.db.emplace(ak, prefix, DBValue::from_slice(value));
|
||||
k
|
||||
}
|
||||
|
||||
fn emplace(&mut self, key: H256, prefix: Prefix, value: DBValue) {
|
||||
if key == KECCAK_NULL_RLP {
|
||||
return;
|
||||
}
|
||||
let key = combine_key(&self.address_hash, &key);
|
||||
self.db.emplace(key, prefix, value)
|
||||
}
|
||||
|
||||
fn remove(&mut self, key: &H256, prefix: Prefix) {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return;
|
||||
}
|
||||
let key = combine_key(&self.address_hash, key);
|
||||
self.db.remove(&key, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDBMut<'db> {
|
||||
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
struct Wrapping<'db>(&'db dyn HashDB<KeccakHasher, DBValue>);
|
||||
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for Wrapping<'db> {
|
||||
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for Wrapping<'db> {
|
||||
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return Some(DBValue::from_slice(&NULL_RLP));
|
||||
}
|
||||
self.0.get(key, prefix)
|
||||
}
|
||||
|
||||
fn contains(&self, key: &H256, prefix: Prefix) -> bool {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return true;
|
||||
}
|
||||
self.0.contains(key, prefix)
|
||||
}
|
||||
|
||||
fn insert(&mut self, _prefix: Prefix, _value: &[u8]) -> H256 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn emplace(&mut self, _key: H256, _prefix: Prefix, _value: DBValue) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn remove(&mut self, _key: &H256, _prefix: Prefix) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
struct WrappingMut<'db>(&'db mut dyn HashDB<KeccakHasher, DBValue>);
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for WrappingMut<'db> {
|
||||
fn as_hash_db(&self) -> &dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hash_db_mut(&mut self) -> &mut dyn HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for WrappingMut<'db>{
|
||||
fn get(&self, key: &H256, prefix: Prefix) -> Option<DBValue> {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return Some(DBValue::from_slice(&NULL_RLP));
|
||||
}
|
||||
self.0.get(key, prefix)
|
||||
}
|
||||
|
||||
fn contains(&self, key: &H256, prefix: Prefix) -> bool {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return true;
|
||||
}
|
||||
self.0.contains(key, prefix)
|
||||
}
|
||||
|
||||
fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H256 {
|
||||
if value == &NULL_RLP {
|
||||
return KECCAK_NULL_RLP.clone();
|
||||
}
|
||||
self.0.insert(prefix, value)
|
||||
}
|
||||
|
||||
fn emplace(&mut self, key: H256, prefix: Prefix, value: DBValue) {
|
||||
if key == KECCAK_NULL_RLP {
|
||||
return;
|
||||
}
|
||||
self.0.emplace(key, prefix, value)
|
||||
}
|
||||
|
||||
fn remove(&mut self, key: &H256, prefix: Prefix) {
|
||||
if key == &KECCAK_NULL_RLP {
|
||||
return;
|
||||
}
|
||||
self.0.remove(key, prefix)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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
|
||||
// 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/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
@@ -25,16 +25,16 @@ extern crate ethereum_types;
|
||||
extern crate parity_bytes as bytes;
|
||||
extern crate rustc_hex;
|
||||
|
||||
use criterion::{Criterion, Bencher};
|
||||
use bytes::BytesRef;
|
||||
use ethcore::builtin::Builtin;
|
||||
use ethcore::machine::Machine;
|
||||
use ethereum_types::H160;
|
||||
use ethcore::machine::EthereumMachine;
|
||||
use ethereum_types::U256;
|
||||
use ethcore::ethereum::new_byzantium_test_machine;
|
||||
use rustc_hex::FromHex;
|
||||
use self::test::Bencher;
|
||||
|
||||
lazy_static! {
|
||||
static ref BYZANTIUM_MACHINE: Machine = new_byzantium_test_machine();
|
||||
static ref BYZANTIUM_MACHINE: EthereumMachine = new_byzantium_test_machine();
|
||||
}
|
||||
|
||||
struct BuiltinBenchmark<'a> {
|
||||
@@ -46,9 +46,8 @@ struct BuiltinBenchmark<'a> {
|
||||
impl<'a> BuiltinBenchmark<'a> {
|
||||
fn new(builtin_address: &'static str, input: &str, expected: &str) -> BuiltinBenchmark<'a> {
|
||||
let builtins = BYZANTIUM_MACHINE.builtins();
|
||||
use std::str::FromStr;
|
||||
let addr = H160::from_str(builtin_address).unwrap();
|
||||
let builtin = builtins.get(&addr).unwrap().clone();
|
||||
|
||||
let builtin = builtins.get(&builtin_address.into()).unwrap().clone();
|
||||
let input = FromHex::from_hex(input).unwrap();
|
||||
let expected = FromHex::from_hex(expected).unwrap();
|
||||
|
||||
@@ -57,6 +56,10 @@ impl<'a> BuiltinBenchmark<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn gas_cost(&self) -> U256 {
|
||||
self.builtin.cost(&self.input)
|
||||
}
|
||||
|
||||
fn run(&self, b: &mut Bencher) {
|
||||
let mut output = vec![0; self.expected.len()];
|
||||
|
||||
@@ -69,81 +72,20 @@ impl<'a> BuiltinBenchmark<'a> {
|
||||
}
|
||||
|
||||
fn bench(
|
||||
id: &str,
|
||||
builtin_address: &'static str,
|
||||
input: &str,
|
||||
expected: &str,
|
||||
b: &mut Criterion,
|
||||
b: &mut Bencher,
|
||||
) {
|
||||
let bench = BuiltinBenchmark::new(builtin_address, input, expected);
|
||||
b.bench_function(id, move |b| bench.run(b));
|
||||
|
||||
println!("gas cost: {}", bench.gas_cost());
|
||||
bench.run(b);
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
builtin,
|
||||
ecrecover,
|
||||
sha256,
|
||||
ripemd,
|
||||
identity,
|
||||
modexp_eip_example1,
|
||||
modexp_eip_example2,
|
||||
modexp_nagydani_1_square,
|
||||
modexp_nagydani_1_qube,
|
||||
modexp_nagydani_1_pow0x10001,
|
||||
modexp_nagydani_2_square,
|
||||
modexp_nagydani_2_qube,
|
||||
modexp_nagydani_2_pow0x10001,
|
||||
modexp_nagydani_3_square,
|
||||
modexp_nagydani_3_qube,
|
||||
modexp_nagydani_3_pow0x10001,
|
||||
modexp_nagydani_4_square,
|
||||
modexp_nagydani_4_qube,
|
||||
modexp_nagydani_4_pow0x10001,
|
||||
modexp_nagydani_5_square,
|
||||
modexp_nagydani_5_qube,
|
||||
modexp_nagydani_5_pow0x10001,
|
||||
alt_bn128_add_chfast1,
|
||||
alt_bn128_add_chfast2,
|
||||
alt_bn128_add_cdetrio1,
|
||||
alt_bn128_add_cdetrio2,
|
||||
alt_bn128_add_cdetrio3,
|
||||
alt_bn128_add_cdetrio4,
|
||||
alt_bn128_add_cdetrio5,
|
||||
alt_bn128_add_cdetrio6,
|
||||
alt_bn128_add_cdetrio7,
|
||||
alt_bn128_add_cdetrio8,
|
||||
alt_bn128_add_cdetrio9,
|
||||
alt_bn128_add_cdetrio10,
|
||||
alt_bn128_add_cdetrio11,
|
||||
alt_bn128_add_cdetrio12,
|
||||
alt_bn128_add_cdetrio13,
|
||||
alt_bn128_add_cdetrio14,
|
||||
alt_bn128_mul_chfast1,
|
||||
alt_bn128_mul_chfast2,
|
||||
alt_bn128_mul_chfast3,
|
||||
alt_bn128_mul_cdetrio1,
|
||||
alt_bn128_mul_cdetrio6,
|
||||
alt_bn128_mul_cdetrio11,
|
||||
alt_bn128_pairing_jeff1,
|
||||
alt_bn128_pairing_jeff2,
|
||||
alt_bn128_pairing_jeff3,
|
||||
alt_bn128_pairing_jeff4,
|
||||
alt_bn128_pairing_jeff5,
|
||||
alt_bn128_pairing_jeff6,
|
||||
alt_bn128_pairing_empty_data,
|
||||
alt_bn128_pairing_one_point,
|
||||
alt_bn128_pairing_two_point_match_2,
|
||||
alt_bn128_pairing_two_point_match_3,
|
||||
alt_bn128_pairing_two_point_match_4,
|
||||
alt_bn128_pairing_ten_point_match_1,
|
||||
alt_bn128_pairing_ten_point_match_2,
|
||||
alt_bn128_pairing_ten_point_match_3
|
||||
);
|
||||
criterion_main!(builtin);
|
||||
|
||||
fn ecrecover(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn ecrecover(b: &mut Bencher) {
|
||||
bench(
|
||||
"ecrecover",
|
||||
"0000000000000000000000000000000000000001", // ecrecover
|
||||
"38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
|
||||
"000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d",
|
||||
@@ -151,9 +93,9 @@ fn ecrecover(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn sha256(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn sha256(b: &mut Bencher) {
|
||||
bench(
|
||||
"sha256",
|
||||
"0000000000000000000000000000000000000002", // sha256
|
||||
"38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
|
||||
"811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d",
|
||||
@@ -161,9 +103,9 @@ fn sha256(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn ripemd(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn ripemd(b: &mut Bencher) {
|
||||
bench(
|
||||
"ripemd",
|
||||
"0000000000000000000000000000000000000003", // ripemd
|
||||
"38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
|
||||
"0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6",
|
||||
@@ -171,9 +113,9 @@ fn ripemd(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn identity(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn identity(b: &mut Bencher) {
|
||||
bench(
|
||||
"identity",
|
||||
"0000000000000000000000000000000000000004", // identity
|
||||
"38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
|
||||
"38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
|
||||
@@ -181,9 +123,9 @@ fn identity(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_eip_example1(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_eip_example1(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_eip_example1",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -191,9 +133,9 @@ fn modexp_eip_example1(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_eip_example2(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_eip_example2(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_eip_example2",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -201,9 +143,9 @@ fn modexp_eip_example2(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_1_square(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_1_square(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_1_square",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc",
|
||||
@@ -211,9 +153,9 @@ fn modexp_nagydani_1_square(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_1_qube(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_1_qube(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_1_qube",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec",
|
||||
@@ -221,9 +163,9 @@ fn modexp_nagydani_1_qube(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_1_pow0x10001(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_1_pow0x10001(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_1_pow0x10001",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2",
|
||||
@@ -231,9 +173,9 @@ fn modexp_nagydani_1_pow0x10001(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_2_square(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_2_square(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_2_square",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70",
|
||||
@@ -241,9 +183,10 @@ fn modexp_nagydani_2_square(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_2_qube(b: &mut Criterion) {
|
||||
|
||||
#[bench]
|
||||
fn modexp_nagydani_2_qube(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_2_qube",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f",
|
||||
@@ -251,9 +194,9 @@ fn modexp_nagydani_2_qube(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_2_pow0x10001(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_2_pow0x10001(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_2_pow0x10001",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2",
|
||||
@@ -261,9 +204,9 @@ fn modexp_nagydani_2_pow0x10001(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_3_square(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_3_square(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_3_square",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8",
|
||||
@@ -271,9 +214,9 @@ fn modexp_nagydani_3_square(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_3_qube(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_3_qube(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_3_qube",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e",
|
||||
@@ -281,9 +224,9 @@ fn modexp_nagydani_3_qube(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_3_pow0x10001(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_3_pow0x10001(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_3_pow0x10001",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76",
|
||||
@@ -291,9 +234,9 @@ fn modexp_nagydani_3_pow0x10001(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_4_square(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_4_square(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_4_square",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10",
|
||||
@@ -301,9 +244,9 @@ fn modexp_nagydani_4_square(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_4_qube(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_4_qube(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_4_qube",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc",
|
||||
@@ -311,9 +254,9 @@ fn modexp_nagydani_4_qube(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_4_pow0x10001(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_4_pow0x10001(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_4_pow0x10001",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963",
|
||||
@@ -321,9 +264,9 @@ fn modexp_nagydani_4_pow0x10001(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_5_square(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_5_square(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_5_square",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb",
|
||||
@@ -331,9 +274,9 @@ fn modexp_nagydani_5_square(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_5_qube(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn modexp_nagydani_5_qube(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_5_qube",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f",
|
||||
@@ -341,9 +284,10 @@ fn modexp_nagydani_5_qube(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn modexp_nagydani_5_pow0x10001(b: &mut Criterion) {
|
||||
|
||||
#[bench]
|
||||
fn modexp_nagydani_5_pow0x10001(b: &mut Bencher) {
|
||||
bench(
|
||||
"modexp_nagydani_5_pow0x10001",
|
||||
"0000000000000000000000000000000000000005", // modexp
|
||||
"000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500",
|
||||
@@ -351,9 +295,9 @@ fn modexp_nagydani_5_pow0x10001(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_chfast1(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_chfast1(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_chfast1",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7",
|
||||
"2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915",
|
||||
@@ -361,9 +305,9 @@ fn alt_bn128_add_chfast1(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_chfast2(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_chfast2(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_chfast2",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91518b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266",
|
||||
"2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204",
|
||||
@@ -371,9 +315,9 @@ fn alt_bn128_add_chfast2(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio1(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio1(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio1",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -381,9 +325,9 @@ fn alt_bn128_add_cdetrio1(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio2(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio2(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio2",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -391,9 +335,9 @@ fn alt_bn128_add_cdetrio2(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio3(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio3(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio3",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -401,9 +345,9 @@ fn alt_bn128_add_cdetrio3(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio4(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio4(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio4",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -411,9 +355,9 @@ fn alt_bn128_add_cdetrio4(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio5(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio5(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio5",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -421,9 +365,9 @@ fn alt_bn128_add_cdetrio5(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio6(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio6(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio6",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
@@ -431,9 +375,9 @@ fn alt_bn128_add_cdetrio6(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio7(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio7(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio7",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
@@ -441,9 +385,9 @@ fn alt_bn128_add_cdetrio7(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio8(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio8(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio8",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
@@ -451,9 +395,9 @@ fn alt_bn128_add_cdetrio8(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio9(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio9(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio9",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
@@ -461,9 +405,9 @@ fn alt_bn128_add_cdetrio9(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio10(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio10(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio10",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
@@ -471,9 +415,9 @@ fn alt_bn128_add_cdetrio10(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio11(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio11(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio11",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
"030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4",
|
||||
@@ -481,9 +425,9 @@ fn alt_bn128_add_cdetrio11(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio12(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio12(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio12",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4",
|
||||
@@ -491,9 +435,9 @@ fn alt_bn128_add_cdetrio12(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio13(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio13(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio13",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98",
|
||||
"15bf2bb17880144b5d1cd2b1f46eff9d617bffd1ca57c37fb5a49bd84e53cf66049c797f9ce0d17083deb32b5e36f2ea2a212ee036598dd7624c168993d1355f",
|
||||
@@ -501,9 +445,9 @@ fn alt_bn128_add_cdetrio13(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_add_cdetrio14(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_add_cdetrio14(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_add_cdetrio14",
|
||||
"0000000000000000000000000000000000000006", // alt_bn128_add
|
||||
"17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -511,9 +455,9 @@ fn alt_bn128_add_cdetrio14(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_mul_chfast1(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_mul_chfast1(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_mul_chfast1",
|
||||
"0000000000000000000000000000000000000007", // alt_bn128_mul
|
||||
"2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2",
|
||||
"070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc",
|
||||
@@ -521,9 +465,9 @@ fn alt_bn128_mul_chfast1(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_mul_chfast2(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_mul_chfast2(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_mul_chfast2",
|
||||
"0000000000000000000000000000000000000007", // alt_bn128_mul
|
||||
"070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46",
|
||||
"025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e",
|
||||
@@ -531,9 +475,9 @@ fn alt_bn128_mul_chfast2(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_mul_chfast3(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_mul_chfast3(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_mul_chfast3",
|
||||
"0000000000000000000000000000000000000007", // alt_bn128_mul
|
||||
"025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3",
|
||||
"14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27",
|
||||
@@ -541,9 +485,9 @@ fn alt_bn128_mul_chfast3(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_mul_cdetrio1(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_mul_cdetrio1(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_mul_cdetrio1",
|
||||
"0000000000000000000000000000000000000007", // alt_bn128_mul
|
||||
"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11",
|
||||
@@ -551,9 +495,9 @@ fn alt_bn128_mul_cdetrio1(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_mul_cdetrio6(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_mul_cdetrio6(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_mul_cdetrio6",
|
||||
"0000000000000000000000000000000000000007", // alt_bn128_mul
|
||||
"17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"29e587aadd7c06722aabba753017c093f70ba7eb1f1c0104ec0564e7e3e21f6022b1143f6a41008e7755c71c3d00b6b915d386de21783ef590486d8afa8453b1",
|
||||
@@ -561,9 +505,9 @@ fn alt_bn128_mul_cdetrio6(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_mul_cdetrio11(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_mul_cdetrio11(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_mul_cdetrio11",
|
||||
"0000000000000000000000000000000000000007", // alt_bn128_mul
|
||||
"039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"00a1a234d08efaa2616607e31eca1980128b00b415c845ff25bba3afcb81dc00242077290ed33906aeb8e42fd98c41bcb9057ba03421af3f2d08cfc441186024",
|
||||
@@ -571,9 +515,9 @@ fn alt_bn128_mul_cdetrio11(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_jeff1(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_jeff1(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_jeff1",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -581,9 +525,9 @@ fn alt_bn128_pairing_jeff1(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_jeff2(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_jeff2(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_jeff2",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -591,9 +535,9 @@ fn alt_bn128_pairing_jeff2(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_jeff3(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_jeff3(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_jeff3",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -601,9 +545,9 @@ fn alt_bn128_pairing_jeff3(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_jeff4(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_jeff4(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_jeff4",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -611,9 +555,9 @@ fn alt_bn128_pairing_jeff4(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_jeff5(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_jeff5(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_jeff5",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -621,9 +565,9 @@ fn alt_bn128_pairing_jeff5(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_jeff6(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_jeff6(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_jeff6",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -631,9 +575,9 @@ fn alt_bn128_pairing_jeff6(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_empty_data(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_empty_data(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_empty_data",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -641,9 +585,9 @@ fn alt_bn128_pairing_empty_data(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_one_point(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_one_point(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_one_point",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
@@ -651,9 +595,9 @@ fn alt_bn128_pairing_one_point(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_two_point_match_2(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_two_point_match_2(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_two_point_match_2",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -661,9 +605,9 @@ fn alt_bn128_pairing_two_point_match_2(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_two_point_match_3(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_two_point_match_3(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_two_point_match_3",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -671,9 +615,9 @@ fn alt_bn128_pairing_two_point_match_3(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_two_point_match_4(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_two_point_match_4(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_two_point_match_4",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -681,9 +625,9 @@ fn alt_bn128_pairing_two_point_match_4(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_ten_point_match_1(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_ten_point_match_1(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_ten_point_match_1",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -691,9 +635,9 @@ fn alt_bn128_pairing_ten_point_match_1(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_ten_point_match_2(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_ten_point_match_2(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_ten_point_match_2",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
@@ -701,9 +645,9 @@ fn alt_bn128_pairing_ten_point_match_2(b: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
fn alt_bn128_pairing_ten_point_match_3(b: &mut Criterion) {
|
||||
#[bench]
|
||||
fn alt_bn128_pairing_ten_point_match_3(b: &mut Bencher) {
|
||||
bench(
|
||||
"alt_bn128_pairing_ten_point_match_3",
|
||||
"0000000000000000000000000000000000000008", // alt_bn128_pairing
|
||||
"105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
[package]
|
||||
description = "Parity Ethereum Blockchain Database, Test Generator, Configuration, Caching, Importing Blocks, and Block Information"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-blockchain"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.11"
|
||||
blooms-db = { path = "../../util/blooms-db" }
|
||||
common-types = { path = "../types" }
|
||||
ethcore-db = { path = "../db" }
|
||||
ethereum-types = "0.6.0"
|
||||
parity-util-mem = "0.1"
|
||||
itertools = "0.5"
|
||||
kvdb = "0.1"
|
||||
log = "0.4"
|
||||
parity-bytes = "0.1"
|
||||
parking_lot = "0.7"
|
||||
rayon = "1.1"
|
||||
rlp = "0.4.0"
|
||||
rlp_compress = { path = "../../util/rlp-compress" }
|
||||
rlp_derive = { path = "../../util/rlp-derive" }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.5"
|
||||
ethkey = { path = "../../accounts/ethkey" }
|
||||
keccak-hash = "0.2.0"
|
||||
rustc-hex = "1.0"
|
||||
tempdir = "0.3"
|
||||
kvdb-memorydb = "0.1"
|
||||
@@ -1,12 +0,0 @@
|
||||
[package]
|
||||
description = "Parity Ethereum (EthCore) Contract Calls and Blockchain Service & Registry Information"
|
||||
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.6.0"
|
||||
bytes = { version = "0.1", package = "parity-bytes" }
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -1,27 +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/>.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
//! Call Contract module
|
||||
//!
|
||||
//! This crate exposes traits required to call contracts at particular block.
|
||||
//! All utilities that depend on on-chain data should use those traits to access it.
|
||||
|
||||
pub mod call_contract;
|
||||
|
||||
// Re-export
|
||||
pub use self::call_contract::*;
|
||||
@@ -1,17 +0,0 @@
|
||||
[package]
|
||||
description = "Ethcore DB access utilities"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-db"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
common-types = { path = "../types" }
|
||||
ethereum-types = "0.6.0"
|
||||
kvdb = "0.1"
|
||||
parity-util-mem = "0.1"
|
||||
parking_lot = "0.7"
|
||||
rlp = "0.4.0"
|
||||
rlp_derive = { path = "../../util/rlp-derive" }
|
||||
@@ -1,29 +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/>.
|
||||
|
||||
//! Parity Ethereum database access utilities.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
extern crate parity_util_mem as mem;
|
||||
extern crate parity_util_mem as malloc_size_of;
|
||||
|
||||
mod db;
|
||||
|
||||
pub mod keys;
|
||||
pub mod cache_manager;
|
||||
|
||||
pub use self::db::*;
|
||||
@@ -1,5 +1,4 @@
|
||||
[package]
|
||||
description = "Parity Ethereum Virtual Machine (EVM) Rust Implementation"
|
||||
name = "evm"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
@@ -7,23 +6,18 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
bit-set = "0.4"
|
||||
parity-bytes = "0.1"
|
||||
ethereum-types = "0.6.0"
|
||||
parity-util-mem = "0.1"
|
||||
ethereum-types = "0.4"
|
||||
heapsize = "0.4"
|
||||
lazy_static = "1.0"
|
||||
log = "0.4"
|
||||
vm = { path = "../vm" }
|
||||
keccak-hash = "0.2.0"
|
||||
parking_lot = "0.7"
|
||||
memory-cache = { path = "../../util/memory-cache" }
|
||||
keccak-hash = "0.1"
|
||||
parking_lot = "0.6"
|
||||
memory-cache = { path = "../../util/memory_cache" }
|
||||
|
||||
[dev-dependencies]
|
||||
rustc-hex = "1.0"
|
||||
criterion = "0.2"
|
||||
|
||||
[features]
|
||||
evm-debug = []
|
||||
evm-debug-tests = ["evm-debug"]
|
||||
|
||||
[[bench]]
|
||||
name = "basic"
|
||||
harness = false
|
||||
|
||||
@@ -1,209 +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/>.
|
||||
|
||||
//! benchmarking for EVM
|
||||
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
extern crate bit_set;
|
||||
extern crate ethereum_types;
|
||||
extern crate parking_lot;
|
||||
extern crate parity_util_mem as mem;
|
||||
extern crate vm;
|
||||
extern crate evm;
|
||||
extern crate keccak_hash as hash;
|
||||
extern crate memory_cache;
|
||||
extern crate parity_bytes as bytes;
|
||||
extern crate rustc_hex;
|
||||
|
||||
use criterion::{Criterion, Bencher, black_box};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use ethereum_types::{U256, Address};
|
||||
use vm::{ActionParams, Result, GasLeft, Ext};
|
||||
use vm::tests::FakeExt;
|
||||
use evm::Factory;
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
criterion_group!(
|
||||
basic,
|
||||
simple_loop_log0_usize,
|
||||
simple_loop_log0_u256,
|
||||
mem_gas_calculation_same_usize,
|
||||
mem_gas_calculation_same_u256,
|
||||
mem_gas_calculation_increasing_usize,
|
||||
mem_gas_calculation_increasing_u256,
|
||||
blockhash_mulmod_small,
|
||||
blockhash_mulmod_large,
|
||||
);
|
||||
criterion_main!(basic);
|
||||
|
||||
fn simple_loop_log0_usize(b: &mut Criterion) {
|
||||
b.bench_function("simple_loop_log0_usize", |b| {
|
||||
simple_loop_log0(U256::from(::std::usize::MAX), b);
|
||||
});
|
||||
}
|
||||
|
||||
fn simple_loop_log0_u256(b: &mut Criterion) {
|
||||
b.bench_function("simple_loop_log0_u256", |b| {
|
||||
simple_loop_log0(!U256::zero(), b);
|
||||
});
|
||||
}
|
||||
|
||||
fn simple_loop_log0(gas: U256, b: &mut Bencher) {
|
||||
let factory = Factory::default();
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
let code = black_box(
|
||||
"62ffffff5b600190036000600fa0600357".from_hex().unwrap()
|
||||
);
|
||||
|
||||
b.iter(|| {
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = gas;
|
||||
params.code = Some(Arc::new(code.clone()));
|
||||
|
||||
let vm = factory.create(params, ext.schedule(), 0);
|
||||
|
||||
result(vm.exec(&mut ext).ok().unwrap())
|
||||
});
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_same_usize(b: &mut Criterion) {
|
||||
b.bench_function("mem_gas_calculation_same_usize", |b| {
|
||||
mem_gas_calculation_same(U256::from(::std::usize::MAX), b);
|
||||
});
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_same_u256(b: &mut Criterion) {
|
||||
b.bench_function("mem_gas_calculation_same_u256", |b| {
|
||||
mem_gas_calculation_same(!U256::zero(), b);
|
||||
});
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_same(gas: U256, b: &mut Bencher) {
|
||||
let factory = Factory::default();
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let code = black_box(
|
||||
"6110006001556001546000555b610fff805560016000540380600055600c57".from_hex().unwrap()
|
||||
);
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = gas;
|
||||
params.code = Some(Arc::new(code.clone()));
|
||||
|
||||
let vm = factory.create(params, ext.schedule(), 0);
|
||||
|
||||
result(vm.exec(&mut ext).ok().unwrap())
|
||||
});
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_increasing_usize(b: &mut Criterion) {
|
||||
b.bench_function("mem_gas_calculation_increasing_usize", |b| {
|
||||
mem_gas_calculation_increasing(U256::from(::std::usize::MAX), b);
|
||||
});
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_increasing_u256(b: &mut Criterion) {
|
||||
b.bench_function("mem_gas_calculation_increasing_u256", |b| {
|
||||
mem_gas_calculation_increasing(!U256::zero(), b);
|
||||
});
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_increasing(gas: U256, b: &mut Bencher) {
|
||||
let factory = Factory::default();
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let code = black_box(
|
||||
"6110006001556001546000555b610fff60005401805560016000540380600055600c57".from_hex().unwrap()
|
||||
);
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = gas;
|
||||
params.code = Some(Arc::new(code.clone()));
|
||||
|
||||
let vm = factory.create(params, ext.schedule(), 0);
|
||||
|
||||
result(vm.exec(&mut ext).ok().unwrap())
|
||||
});
|
||||
}
|
||||
|
||||
fn blockhash_mulmod_small(b: &mut Criterion) {
|
||||
b.bench_function("blockhash_mulmod_small", |b| {
|
||||
let factory = Factory::default();
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let code = black_box(
|
||||
"6080604052348015600f57600080fd5b5060005a90505b60c881111560de5760017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8009505a90506016565b506035806100ed6000396000f3fe6080604052600080fdfea165627a7a72305820bde4a0ac6d0fac28fc879244baf8a6a0eda514bc95fb7ecbcaaebf2556e2687c0029".from_hex().unwrap()
|
||||
);
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = U256::from(4_000u64);
|
||||
params.code = Some(Arc::new(code.clone()));
|
||||
|
||||
let vm = factory.create(params, ext.schedule(), 0);
|
||||
|
||||
result(vm.exec(&mut ext).ok().unwrap())
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn blockhash_mulmod_large(b: &mut Criterion) {
|
||||
b.bench_function("blockhash_mulmod_large", |b| {
|
||||
let factory = Factory::default();
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let code = black_box(
|
||||
"608060405234801561001057600080fd5b5060005a90505b60c8811115610177577efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009505a9050610017565b506035806101866000396000f3fe6080604052600080fdfea165627a7a72305820dcaec306f67bb96f3044fff25c9af2ec66f01d0954d0656964f046f42f2780670029".from_hex().unwrap()
|
||||
);
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = U256::from(4_000u64);
|
||||
params.code = Some(Arc::new(code.clone()));
|
||||
|
||||
let vm = factory.create(params, ext.schedule(), 0);
|
||||
|
||||
result(vm.exec(&mut ext).ok().unwrap())
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn result(r: Result<evm::GasLeft>) -> U256 {
|
||||
match r {
|
||||
Ok(GasLeft::Known(gas_left)) => gas_left,
|
||||
Ok(GasLeft::NeedsReturn { gas_left, .. }) => gas_left,
|
||||
_ => U256::zero(),
|
||||
}
|
||||
}
|
||||
129
ethcore/evm/src/benches/mod.rs
Normal file
129
ethcore/evm/src/benches/mod.rs
Normal file
@@ -0,0 +1,129 @@
|
||||
// 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/>.
|
||||
|
||||
//! benchmarking for EVM
|
||||
//! should be started with:
|
||||
//! ```bash
|
||||
//! multirust run nightly cargo bench
|
||||
//! ```
|
||||
|
||||
extern crate test;
|
||||
|
||||
use self::test::{Bencher, black_box};
|
||||
|
||||
use bigint::prelude::U256;
|
||||
use bigint::hash::H256;
|
||||
use util::*;
|
||||
use vm::ActionParams;
|
||||
use evm::{self, Factory, VMType};
|
||||
use evm::tests::FakeExt;
|
||||
|
||||
#[bench]
|
||||
fn simple_loop_log0_usize(b: &mut Bencher) {
|
||||
simple_loop_log0(U256::from(::std::usize::MAX), b)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn simple_loop_log0_u256(b: &mut Bencher) {
|
||||
simple_loop_log0(!U256::zero(), b)
|
||||
}
|
||||
|
||||
fn simple_loop_log0(gas: U256, b: &mut Bencher) {
|
||||
let mut vm = Factory::new(VMType::Interpreter).create(gas);
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
let code = black_box(
|
||||
"62ffffff5b600190036000600fa0600357".from_hex().unwrap()
|
||||
);
|
||||
|
||||
b.iter(|| {
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = gas;
|
||||
params.code = Some(code.clone());
|
||||
|
||||
result(vm.exec(params, &mut ext))
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn mem_gas_calculation_same_usize(b: &mut Bencher) {
|
||||
mem_gas_calculation_same(U256::from(::std::usize::MAX), b)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn mem_gas_calculation_same_u256(b: &mut Bencher) {
|
||||
mem_gas_calculation_same(!U256::zero(), b)
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_same(gas: U256, b: &mut Bencher) {
|
||||
let mut vm = Factory::new(VMType::Interpreter).create(gas);
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let code = black_box(
|
||||
"6110006001556001546000555b610fff805560016000540380600055600c57".from_hex().unwrap()
|
||||
);
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = gas;
|
||||
params.code = Some(code.clone());
|
||||
|
||||
result(vm.exec(params, &mut ext))
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn mem_gas_calculation_increasing_usize(b: &mut Bencher) {
|
||||
mem_gas_calculation_increasing(U256::from(::std::usize::MAX), b)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn mem_gas_calculation_increasing_u256(b: &mut Bencher) {
|
||||
mem_gas_calculation_increasing(!U256::zero(), b)
|
||||
}
|
||||
|
||||
fn mem_gas_calculation_increasing(gas: U256, b: &mut Bencher) {
|
||||
let mut vm = Factory::new(VMType::Interpreter).create(gas);
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let code = black_box(
|
||||
"6110006001556001546000555b610fff60005401805560016000540380600055600c57".from_hex().unwrap()
|
||||
);
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = address.clone();
|
||||
params.gas = gas;
|
||||
params.code = Some(code.clone());
|
||||
|
||||
result(vm.exec(params, &mut ext))
|
||||
});
|
||||
}
|
||||
|
||||
fn result(r: evm::Result<evm::GasLeft>) -> U256 {
|
||||
match r {
|
||||
Ok(evm::GasLeft::Known(v)) => v,
|
||||
Ok(evm::GasLeft::NeedsReturn(v, _)) => v,
|
||||
_ => U256::zero(),
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Evm interface.
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Evm factory.
|
||||
//!
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! VM Instructions list and utility functions
|
||||
|
||||
@@ -354,6 +354,7 @@ impl Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Returns stack position of item to duplicate
|
||||
/// DUP1 -> 0
|
||||
pub fn dup_position(&self) -> Option<usize> {
|
||||
@@ -364,6 +365,7 @@ impl Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Returns stack position of item to SWAP top with
|
||||
/// SWAP1 -> 1
|
||||
pub fn swap_position(&self) -> Option<usize> {
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::cmp;
|
||||
use ethereum_types::{BigEndianHash, U256};
|
||||
use ethereum_types::{U256, H256};
|
||||
use super::u256_to_address;
|
||||
|
||||
use {evm, vm};
|
||||
@@ -121,12 +121,12 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
Request::Gas(Gas::from(1))
|
||||
},
|
||||
instructions::SSTORE => {
|
||||
let address = BigEndianHash::from_uint(stack.peek(0));
|
||||
let address = H256::from(stack.peek(0));
|
||||
let newval = stack.peek(1);
|
||||
let val = ext.storage_at(&address)?.into_uint();
|
||||
let val = U256::from(&*ext.storage_at(&address)?);
|
||||
|
||||
let gas = if schedule.eip1283 {
|
||||
let orig = ext.initial_storage_at(&address)?.into_uint();
|
||||
let orig = U256::from(&*ext.initial_storage_at(&address)?);
|
||||
calculate_eip1283_sstore_gas(schedule, &orig, &val, &newval)
|
||||
} else {
|
||||
if val.is_zero() && !newval.is_zero() {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub use self::inner::*;
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use ethereum_types::U256;
|
||||
use vm::ReturnData;
|
||||
@@ -38,6 +38,7 @@ pub trait Memory {
|
||||
fn read_slice(&self, offset: U256, size: U256) -> &[u8];
|
||||
/// Retrieve writeable part of memory
|
||||
fn writeable_slice(&mut self, offset: U256, size: U256) -> &mut[u8];
|
||||
fn dump(&self);
|
||||
/// Convert memory into return data.
|
||||
fn into_return_data(self, offset: U256, size: U256) -> ReturnData;
|
||||
}
|
||||
@@ -50,6 +51,14 @@ pub fn is_valid_range(off: usize, size: usize) -> bool {
|
||||
}
|
||||
|
||||
impl Memory for Vec<u8> {
|
||||
fn dump(&self) {
|
||||
println!("MemoryDump:");
|
||||
for i in self.iter() {
|
||||
println!("{:02x} ", i);
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Rust VM implementation
|
||||
|
||||
@@ -26,11 +26,9 @@ mod shared_cache;
|
||||
use std::marker::PhantomData;
|
||||
use std::{cmp, mem};
|
||||
use std::sync::Arc;
|
||||
use std::convert::TryFrom;
|
||||
use hash::keccak;
|
||||
use bytes::Bytes;
|
||||
use ethereum_types::{U256, U512, H256, Address, BigEndianHash};
|
||||
|
||||
use ethereum_types::{U256, U512, H256, Address};
|
||||
|
||||
use vm::{
|
||||
self, ActionParams, ParamsType, ActionValue, CallType, MessageCallResult,
|
||||
@@ -109,6 +107,8 @@ enum InstructionResult<Gas> {
|
||||
Trap(TrapKind),
|
||||
}
|
||||
|
||||
enum Never {}
|
||||
|
||||
/// ActionParams without code, so that it can be feed into CodeReader.
|
||||
#[derive(Debug)]
|
||||
struct InterpreterParams {
|
||||
@@ -166,6 +166,12 @@ pub enum InterpreterResult {
|
||||
Trap(TrapKind),
|
||||
}
|
||||
|
||||
impl From<vm::Error> for InterpreterResult {
|
||||
fn from(error: vm::Error) -> InterpreterResult {
|
||||
InterpreterResult::Done(Err(error))
|
||||
}
|
||||
}
|
||||
|
||||
/// Intepreter EVM implementation
|
||||
pub struct Interpreter<Cost: CostType> {
|
||||
mem: Vec<u8>,
|
||||
@@ -298,7 +304,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
} else if self.reader.len() == 0 {
|
||||
InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_ref().expect("Gasometer None case is checked above; qed").current_gas.as_u256())))
|
||||
} else {
|
||||
self.step_inner(ext)
|
||||
self.step_inner(ext).err().expect("step_inner never returns Ok(()); qed")
|
||||
};
|
||||
|
||||
if let &InterpreterResult::Done(_) = &result {
|
||||
@@ -310,7 +316,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
|
||||
/// Inner helper function for step.
|
||||
#[inline(always)]
|
||||
fn step_inner(&mut self, ext: &mut dyn vm::Ext) -> InterpreterResult {
|
||||
fn step_inner(&mut self, ext: &mut vm::Ext) -> Result<Never, InterpreterResult> {
|
||||
let result = match self.resume_result.take() {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
@@ -325,28 +331,22 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
|
||||
let instruction = match instruction {
|
||||
Some(i) => i,
|
||||
None => return InterpreterResult::Done(Err(vm::Error::BadInstruction {
|
||||
None => return Err(InterpreterResult::Done(Err(vm::Error::BadInstruction {
|
||||
instruction: opcode
|
||||
})),
|
||||
}))),
|
||||
};
|
||||
|
||||
let info = instruction.info();
|
||||
self.last_stack_ret_len = info.ret;
|
||||
if let Err(e) = self.verify_instruction(ext, instruction, info) {
|
||||
return InterpreterResult::Done(Err(e));
|
||||
};
|
||||
self.verify_instruction(ext, instruction, info)?;
|
||||
|
||||
// Calculate gas cost
|
||||
let requirements = match self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size()) {
|
||||
Ok(t) => t,
|
||||
Err(e) => return InterpreterResult::Done(Err(e)),
|
||||
};
|
||||
let requirements = self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size())?;
|
||||
if self.do_trace {
|
||||
ext.trace_prepare_execute(self.reader.position - 1, opcode, requirements.gas_cost.as_u256(), Self::mem_written(instruction, &self.stack), Self::store_written(instruction, &self.stack));
|
||||
}
|
||||
if let Err(e) = self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost) {
|
||||
return InterpreterResult::Done(Err(e));
|
||||
}
|
||||
|
||||
self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost)?;
|
||||
self.mem.expand(requirements.memory_required_size);
|
||||
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_mem_gas = requirements.memory_total_gas;
|
||||
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas - requirements.gas_cost;
|
||||
@@ -355,19 +355,18 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
|
||||
// Execute instruction
|
||||
let current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas;
|
||||
let result = match self.exec_instruction(
|
||||
let result = self.exec_instruction(
|
||||
current_gas, ext, instruction, requirements.provide_gas
|
||||
) {
|
||||
Err(x) => return InterpreterResult::Done(Err(x)),
|
||||
Ok(x) => x,
|
||||
};
|
||||
)?;
|
||||
|
||||
evm_debug!({ self.informant.after_instruction(instruction) });
|
||||
|
||||
result
|
||||
},
|
||||
};
|
||||
|
||||
if let InstructionResult::Trap(trap) = result {
|
||||
return InterpreterResult::Trap(trap);
|
||||
return Err(InterpreterResult::Trap(trap));
|
||||
}
|
||||
|
||||
if let InstructionResult::UnusedGas(ref gas) = result {
|
||||
@@ -389,31 +388,28 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
self.valid_jump_destinations = Some(self.cache.jump_destinations(&self.params.code_hash, &self.reader.code));
|
||||
}
|
||||
let jump_destinations = self.valid_jump_destinations.as_ref().expect("jump_destinations are initialized on first jump; qed");
|
||||
let pos = match self.verify_jump(position, jump_destinations) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return InterpreterResult::Done(Err(e))
|
||||
};
|
||||
let pos = self.verify_jump(position, jump_destinations)?;
|
||||
self.reader.position = pos;
|
||||
},
|
||||
InstructionResult::StopExecutionNeedsReturn {gas, init_off, init_size, apply} => {
|
||||
let mem = mem::replace(&mut self.mem, Vec::new());
|
||||
return InterpreterResult::Done(Ok(GasLeft::NeedsReturn {
|
||||
return Err(InterpreterResult::Done(Ok(GasLeft::NeedsReturn {
|
||||
gas_left: gas.as_u256(),
|
||||
data: mem.into_return_data(init_off, init_size),
|
||||
apply_state: apply
|
||||
}));
|
||||
})));
|
||||
},
|
||||
InstructionResult::StopExecution => {
|
||||
return InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256())));
|
||||
return Err(InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256()))));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
if self.reader.position >= self.reader.len() {
|
||||
return InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256())));
|
||||
return Err(InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256()))));
|
||||
}
|
||||
|
||||
InterpreterResult::Continue
|
||||
Err(InterpreterResult::Continue)
|
||||
}
|
||||
|
||||
fn verify_instruction(&self, ext: &vm::Ext, instruction: Instruction, info: &InstructionInfo) -> vm::Result<()> {
|
||||
@@ -512,7 +508,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
let init_size = self.stack.pop_back();
|
||||
let address_scheme = match instruction {
|
||||
instructions::CREATE => CreateContractAddress::FromSenderAndNonce,
|
||||
instructions::CREATE2 => CreateContractAddress::FromSenderSaltAndCodeHash(BigEndianHash::from_uint(&self.stack.pop_back())),
|
||||
instructions::CREATE2 => CreateContractAddress::FromSenderSaltAndCodeHash(self.stack.pop_back().into()),
|
||||
_ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"),
|
||||
};
|
||||
|
||||
@@ -575,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 {
|
||||
@@ -669,7 +665,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
let size = self.stack.pop_back();
|
||||
let topics = self.stack.pop_n(no_of_topics)
|
||||
.iter()
|
||||
.map(BigEndianHash::from_uint)
|
||||
.map(H256::from)
|
||||
.collect();
|
||||
ext.log(topics, self.mem.read_slice(offset, size))?;
|
||||
},
|
||||
@@ -706,21 +702,21 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
let offset = self.stack.pop_back();
|
||||
let size = self.stack.pop_back();
|
||||
let k = keccak(self.mem.read_slice(offset, size));
|
||||
self.stack.push(k.into_uint());
|
||||
self.stack.push(U256::from(&*k));
|
||||
},
|
||||
instructions::SLOAD => {
|
||||
let key = BigEndianHash::from_uint(&self.stack.pop_back());
|
||||
let word = ext.storage_at(&key)?.into_uint();
|
||||
let key = H256::from(&self.stack.pop_back());
|
||||
let word = U256::from(&*ext.storage_at(&key)?);
|
||||
self.stack.push(word);
|
||||
},
|
||||
instructions::SSTORE => {
|
||||
let address = BigEndianHash::from_uint(&self.stack.pop_back());
|
||||
let address = H256::from(&self.stack.pop_back());
|
||||
let val = self.stack.pop_back();
|
||||
|
||||
let current_val = ext.storage_at(&address)?.into_uint();
|
||||
let current_val = U256::from(&*ext.storage_at(&address)?);
|
||||
// Increase refund for clear
|
||||
if ext.schedule().eip1283 {
|
||||
let original_val = ext.initial_storage_at(&address)?.into_uint();
|
||||
let original_val = U256::from(&*ext.initial_storage_at(&address)?);
|
||||
gasometer::handle_eip1283_sstore_clears_refund(ext, &original_val, ¤t_val, &val);
|
||||
} else {
|
||||
if !current_val.is_zero() && val.is_zero() {
|
||||
@@ -728,7 +724,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
ext.add_sstore_refund(sstore_clears_schedule);
|
||||
}
|
||||
}
|
||||
ext.set_storage(address, BigEndianHash::from_uint(&val))?;
|
||||
ext.set_storage(address, H256::from(&val))?;
|
||||
},
|
||||
instructions::PC => {
|
||||
self.stack.push(U256::from(self.reader.position - 1));
|
||||
@@ -789,7 +785,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
instructions::EXTCODEHASH => {
|
||||
let address = u256_to_address(&self.stack.pop_back());
|
||||
let hash = ext.extcodehash(&address)?.unwrap_or_else(H256::zero);
|
||||
self.stack.push(hash.into_uint());
|
||||
self.stack.push(U256::from(hash));
|
||||
},
|
||||
instructions::CALLDATACOPY => {
|
||||
Self::copy_data_to_memory(&mut self.mem, &mut self.stack, &self.params.data.as_ref().map_or_else(|| &[] as &[u8], |d| &*d as &[u8]));
|
||||
@@ -823,7 +819,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
instructions::BLOCKHASH => {
|
||||
let block_number = self.stack.pop_back();
|
||||
let block_hash = ext.blockhash(&block_number);
|
||||
self.stack.push(block_hash.into_uint());
|
||||
self.stack.push(U256::from(&*block_hash));
|
||||
},
|
||||
instructions::COINBASE => {
|
||||
self.stack.push(address_to_u256(ext.env_info().author.clone()));
|
||||
@@ -1013,12 +1009,11 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
let c = self.stack.pop_back();
|
||||
|
||||
self.stack.push(if !c.is_zero() {
|
||||
let a_512 = U512::from(a);
|
||||
let b_512 = U512::from(b);
|
||||
let c_512 = U512::from(c);
|
||||
let res = a_512 + b_512;
|
||||
let x = res % c_512;
|
||||
U256::try_from(x).expect("U512 % U256 fits U256; qed")
|
||||
// upcast to 512
|
||||
let a5 = U512::from(a);
|
||||
let res = a5.overflowing_add(U512::from(b)).0;
|
||||
let x = res % U512::from(c);
|
||||
U256::from(x)
|
||||
} else {
|
||||
U256::zero()
|
||||
});
|
||||
@@ -1029,12 +1024,10 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
let c = self.stack.pop_back();
|
||||
|
||||
self.stack.push(if !c.is_zero() {
|
||||
let a_512 = U512::from(a);
|
||||
let b_512 = U512::from(b);
|
||||
let c_512 = U512::from(c);
|
||||
let res = a_512 * b_512;
|
||||
let x = res % c_512;
|
||||
U256::try_from(x).expect("U512 % U256 fits U256; qed")
|
||||
let a5 = U512::from(a);
|
||||
let res = a5.overflowing_mul(U512::from(b)).0;
|
||||
let x = res % U512::from(c);
|
||||
U256::from(x)
|
||||
} else {
|
||||
U256::zero()
|
||||
});
|
||||
@@ -1174,13 +1167,12 @@ fn set_sign(value: U256, sign: bool) -> U256 {
|
||||
|
||||
#[inline]
|
||||
fn u256_to_address(value: &U256) -> Address {
|
||||
let addr: H256 = BigEndianHash::from_uint(value);
|
||||
Address::from(addr)
|
||||
Address::from(H256::from(value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn address_to_u256(value: Address) -> U256 {
|
||||
H256::from(value).into_uint()
|
||||
U256::from(&*H256::from(value))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -1191,7 +1183,6 @@ mod tests {
|
||||
use factory::Factory;
|
||||
use vm::{self, Exec, ActionParams, ActionValue};
|
||||
use vm::tests::{FakeExt, test_finalize};
|
||||
use ethereum_types::Address;
|
||||
|
||||
fn interpreter(params: ActionParams, ext: &vm::Ext) -> Box<Exec> {
|
||||
Factory::new(VMType::Interpreter, 1).create(params, ext.schedule(), ext.depth())
|
||||
@@ -1202,13 +1193,13 @@ mod tests {
|
||||
let code = "7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000620f120660406000601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055".from_hex().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = Address::from_low_u64_be(5);
|
||||
params.address = 5.into();
|
||||
params.gas = 300_000.into();
|
||||
params.gas_price = 1.into();
|
||||
params.value = ActionValue::Transfer(100_000.into());
|
||||
params.code = Some(Arc::new(code));
|
||||
let mut ext = FakeExt::new();
|
||||
ext.balances.insert(Address::from_low_u64_be(5), 1_000_000_000.into());
|
||||
ext.balances.insert(5.into(), 1_000_000_000.into());
|
||||
ext.tracing = true;
|
||||
|
||||
let gas_left = {
|
||||
@@ -1225,12 +1216,12 @@ mod tests {
|
||||
let code = "6001600160000360003e00".from_hex().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.address = Address::from_low_u64_be(5);
|
||||
params.address = 5.into();
|
||||
params.gas = 300_000.into();
|
||||
params.gas_price = 1.into();
|
||||
params.code = Some(Arc::new(code));
|
||||
let mut ext = FakeExt::new_byzantium();
|
||||
ext.balances.insert(Address::from_low_u64_be(5), 1_000_000_000.into());
|
||||
ext.balances.insert(5.into(), 1_000_000_000.into());
|
||||
ext.tracing = true;
|
||||
|
||||
let err = {
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::sync::Arc;
|
||||
use hash::KECCAK_EMPTY;
|
||||
use parity_util_mem::{MallocSizeOf, MallocSizeOfOps};
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethereum_types::H256;
|
||||
use parking_lot::Mutex;
|
||||
use memory_cache::MemoryLruCache;
|
||||
@@ -25,12 +25,11 @@ use super::super::instructions::{self, Instruction};
|
||||
|
||||
const DEFAULT_CACHE_SIZE: usize = 4 * 1024 * 1024;
|
||||
|
||||
/// Stub for a sharing `BitSet` data in cache (reference counted)
|
||||
/// and implementing MallocSizeOf on it.
|
||||
// stub for a HeapSizeOf implementation.
|
||||
struct Bits(Arc<BitSet>);
|
||||
|
||||
impl MallocSizeOf for Bits {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
impl HeapSizeOf for Bits {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
// dealing in bits here
|
||||
self.0.capacity() * 8
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
use instructions;
|
||||
@@ -66,7 +66,11 @@ impl<S : fmt::Display> Stack<S> for VecStack<S> {
|
||||
}
|
||||
|
||||
fn pop_back(&mut self) -> S {
|
||||
self.stack.pop().expect("instruction validation prevents from popping too many items; qed")
|
||||
let val = self.stack.pop();
|
||||
match val {
|
||||
Some(x) => x,
|
||||
None => panic!("Tried to pop from empty stack.")
|
||||
}
|
||||
}
|
||||
|
||||
fn pop_n(&mut self, no_of_elems: usize) -> &[S] {
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Ethereum virtual machine.
|
||||
|
||||
extern crate bit_set;
|
||||
extern crate ethereum_types;
|
||||
extern crate parking_lot;
|
||||
extern crate parity_util_mem;
|
||||
extern crate heapsize;
|
||||
extern crate vm;
|
||||
extern crate keccak_hash as hash;
|
||||
extern crate memory_cache;
|
||||
@@ -44,6 +44,8 @@ mod instructions;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
#[cfg(all(feature = "benches", test))]
|
||||
mod benches;
|
||||
|
||||
pub use vm::{
|
||||
Schedule, CleanDustMode, EnvInfo, CallType, ActionParams, Ext,
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::str::FromStr;
|
||||
@@ -239,7 +239,7 @@ fn test_blockhash(factory: super::Factory) {
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_974));
|
||||
assert_eq!(ext.store.get(&H256::zero()).unwrap(), &blockhash);
|
||||
assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash);
|
||||
}
|
||||
|
||||
evm_test!{test_calldataload: test_calldataload_int}
|
||||
@@ -726,8 +726,8 @@ evm_test!{test_calls: test_calls_int}
|
||||
fn test_calls(factory: super::Factory) {
|
||||
let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap();
|
||||
|
||||
let address = Address::from_low_u64_be(0x155);
|
||||
let code_address = Address::from_low_u64_be(0x998);
|
||||
let address = Address::from(0x155);
|
||||
let code_address = Address::from(0x998);
|
||||
let mut params = ActionParams::default();
|
||||
params.gas = U256::from(150_000);
|
||||
params.code = Some(Arc::new(code));
|
||||
@@ -772,7 +772,7 @@ evm_test!{test_create_in_staticcall: test_create_in_staticcall_int}
|
||||
fn test_create_in_staticcall(factory: super::Factory) {
|
||||
let code = "600060006064f000".from_hex().unwrap();
|
||||
|
||||
let address = Address::from_low_u64_be(0x155);
|
||||
let address = Address::from(0x155);
|
||||
let mut params = ActionParams::default();
|
||||
params.gas = U256::from(100_000);
|
||||
params.code = Some(Arc::new(code));
|
||||
@@ -1066,5 +1066,5 @@ fn assert_set_contains<T : Debug + Eq + PartialEq + Hash>(set: &HashSet<T>, val:
|
||||
}
|
||||
|
||||
fn assert_store(ext: &FakeExt, pos: u64, val: &str) {
|
||||
assert_eq!(ext.store.get(&H256::from_low_u64_be(pos)).unwrap(), &H256::from_str(val).unwrap());
|
||||
assert_eq!(ext.store.get(&H256::from(pos)).unwrap(), &H256::from_str(val).unwrap());
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
description = "Parity Ethereum (EthCore) Light Client Implementation (Block Import IO Service, Blockchain Data Fetching, Light Client Header Chain Storage, Parity Light Protocol (PLP) Provider, Light Transaction Queue, CHT Definitions, Light Client Data Cache), Parity Light Protocol (PLP) Implementation, P2P Network I/O and Event Context Generalization, Peer Error Handling & Punishment, Request Load Timer & Distribution Manager, Pending Request Set Storage, Request Credit Management, Light Client Request Types, Request Chain Builder Utility, On-demand Chain Request Service over LES (for RPCs), ResponseGuard Implementation)"
|
||||
description = "Parity Light Client Implementation"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-light"
|
||||
@@ -8,42 +8,36 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
parity-bytes = "0.1"
|
||||
common-types = { path = "../types" }
|
||||
derive_more = "0.14.0"
|
||||
ethcore = { path = ".."}
|
||||
ethcore-db = { path = "../db" }
|
||||
ethcore-blockchain = { path = "../blockchain" }
|
||||
ethereum-types = "0.6.0"
|
||||
memory-db = "0.12.4"
|
||||
trie-db = "0.12.4"
|
||||
parity-bytes = "0.1"
|
||||
ethcore-transaction = { path = "../transaction" }
|
||||
ethereum-types = "0.4"
|
||||
memorydb = "0.3.0"
|
||||
patricia-trie = "0.3.0"
|
||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
||||
ethcore-network = { path = "../../util/network" }
|
||||
ethcore-miner = { path = "../../miner" }
|
||||
ethcore-io = { path = "../../util/io" }
|
||||
hash-db = "0.12.4"
|
||||
parity-util-mem = "0.1"
|
||||
hashdb = "0.3.0"
|
||||
heapsize = "0.4"
|
||||
vm = { path = "../vm" }
|
||||
fastmap = { path = "../../util/fastmap" }
|
||||
failsafe = { version = "0.3.0", default-features = false, features = ["parking_lot_mutex"] }
|
||||
rlp = "0.4.0"
|
||||
rlp_derive = { path = "../../util/rlp-derive" }
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rlp_derive = { path = "../../util/rlp_derive" }
|
||||
smallvec = "0.6"
|
||||
futures = "0.1"
|
||||
rand = "0.6"
|
||||
rand = "0.4"
|
||||
itertools = "0.5"
|
||||
bincode = "1.1"
|
||||
bincode = "0.8.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.6"
|
||||
stats = { path = "../../util/stats" }
|
||||
keccak-hash = "0.2.0"
|
||||
keccak-hash = "0.1"
|
||||
keccak-hasher = { path = "../../util/keccak-hasher" }
|
||||
triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" }
|
||||
kvdb = "0.1"
|
||||
memory-cache = { path = "../../util/memory-cache" }
|
||||
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"] }
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Cache for data fetched from the network.
|
||||
//!
|
||||
@@ -20,15 +20,15 @@
|
||||
//! Furthermore, stores a "gas price corpus" of relative recency, which is a sorted
|
||||
//! vector of all gas prices from a recent range of blocks.
|
||||
|
||||
use std::time::{Instant, Duration};
|
||||
use parity_util_mem::{MallocSizeOf, MallocSizeOfOps, MallocSizeOfExt};
|
||||
use ethcore::encoded;
|
||||
use ethcore::header::BlockNumber;
|
||||
use ethcore::receipt::Receipt;
|
||||
|
||||
use common_types::encoded;
|
||||
use common_types::BlockNumber;
|
||||
use common_types::receipt::Receipt;
|
||||
use stats::Corpus;
|
||||
use std::time::{Instant, Duration};
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethereum_types::{H256, U256};
|
||||
use memory_cache::MemoryLruCache;
|
||||
use stats::Corpus;
|
||||
|
||||
/// Configuration for how much data to cache.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
@@ -157,20 +157,18 @@ impl Cache {
|
||||
|
||||
/// Get the memory used.
|
||||
pub fn mem_used(&self) -> usize {
|
||||
self.malloc_size_of()
|
||||
self.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This is fast method: it is possible to have a more exhaustive implementation
|
||||
impl MallocSizeOf for Cache {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
impl HeapSizeOf for Cache {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.headers.current_size()
|
||||
+ self.canon_hashes.current_size()
|
||||
+ self.bodies.current_size()
|
||||
+ self.receipts.current_size()
|
||||
+ self.chain_score.current_size()
|
||||
// `self.corpus` is skipped
|
||||
// TODO: + corpus
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Canonical hash trie definitions and helper functions.
|
||||
//!
|
||||
@@ -23,13 +23,12 @@
|
||||
//! root has. A correct proof implies that the claimed block is identical to the one
|
||||
//! we discarded.
|
||||
|
||||
use common_types::ids::BlockId;
|
||||
use ethcore::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()))
|
||||
@@ -95,17 +93,16 @@ pub struct BlockInfo {
|
||||
/// Build an in-memory CHT from a closure which provides necessary information
|
||||
/// about blocks. If the fetcher ever fails to provide the info, the CHT
|
||||
/// will not be generated.
|
||||
pub fn build<F>(cht_num: u64, mut fetcher: F)
|
||||
-> Option<CHT<MemoryDB<KeccakHasher, memory_db::HashKey<KeccakHasher>, DBValue>>>
|
||||
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;
|
||||
let mut id = BlockId::Number(last_num);
|
||||
|
||||
let mut root = H256::zero();
|
||||
let mut root = H256::default();
|
||||
|
||||
{
|
||||
let mut t = TrieDBMut::new(&mut db, &mut root);
|
||||
@@ -153,9 +150,9 @@ 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(hash_db::EMPTY_PREFIX, &node[..]); }
|
||||
for node in proof { db.insert(&node[..]); }
|
||||
let res = match TrieDB::new(&db, &root) {
|
||||
Err(_) => return None,
|
||||
Ok(trie) => trie.get_with(&key!(num), |val: &[u8]| {
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Trait for fetching chain data.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_types::encoded;
|
||||
use common_types::header::Header;
|
||||
use common_types::receipt::Receipt;
|
||||
use ethcore::engines::{Engine, StateDependentProof};
|
||||
use ethereum_types::H256;
|
||||
use ethcore::encoded;
|
||||
use ethcore::engines::{EthEngine, StateDependentProof};
|
||||
use ethcore::machine::EthereumMachine;
|
||||
use ethcore::header::Header;
|
||||
use ethcore::receipt::Receipt;
|
||||
use futures::future::IntoFuture;
|
||||
use ethereum_types::H256;
|
||||
|
||||
/// Provides full chain data.
|
||||
pub trait ChainDataFetcher: Send + Sync + 'static {
|
||||
@@ -47,8 +48,8 @@ pub trait ChainDataFetcher: Send + Sync + 'static {
|
||||
fn epoch_transition(
|
||||
&self,
|
||||
_hash: H256,
|
||||
_engine: Arc<Engine>,
|
||||
_checker: Arc<StateDependentProof>
|
||||
_engine: Arc<EthEngine>,
|
||||
_checker: Arc<StateDependentProof<EthereumMachine>>
|
||||
) -> Self::Transition;
|
||||
}
|
||||
|
||||
@@ -76,8 +77,8 @@ impl ChainDataFetcher for Unavailable {
|
||||
fn epoch_transition(
|
||||
&self,
|
||||
_hash: H256,
|
||||
_engine: Arc<Engine>,
|
||||
_checker: Arc<StateDependentProof>
|
||||
_engine: Arc<EthEngine>,
|
||||
_checker: Arc<StateDependentProof<EthereumMachine>>
|
||||
) -> Self::Transition {
|
||||
Err("fetching epoch transition proofs unavailable")
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Light client header chain.
|
||||
//!
|
||||
@@ -30,15 +30,15 @@ use std::sync::Arc;
|
||||
|
||||
use cache::Cache;
|
||||
use cht;
|
||||
use common_types::block_status::BlockStatus;
|
||||
use common_types::encoded;
|
||||
use common_types::header::Header;
|
||||
use common_types::ids::BlockId;
|
||||
use ethcore::block_status::BlockStatus;
|
||||
use ethcore::encoded;
|
||||
use ethcore::engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
|
||||
use ethcore::error::{Error, EthcoreResult, BlockError};
|
||||
use ethcore::error::{Error, EthcoreResult, ErrorKind as EthcoreErrorKind, BlockError};
|
||||
use ethcore::header::Header;
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::spec::{Spec, SpecHardcodedSync};
|
||||
use ethereum_types::{H256, H264, U256};
|
||||
use parity_util_mem::{MallocSizeOf, MallocSizeOfOps};
|
||||
use heapsize::HeapSizeOf;
|
||||
use kvdb::{DBTransaction, KeyValueDB};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use fastmap::H256FastMap;
|
||||
@@ -95,8 +95,8 @@ struct Entry {
|
||||
canonical_hash: H256,
|
||||
}
|
||||
|
||||
impl MallocSizeOf for Entry {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
impl HeapSizeOf for Entry {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
if self.candidates.spilled() {
|
||||
self.candidates.capacity() * ::std::mem::size_of::<Candidate>()
|
||||
} else {
|
||||
@@ -154,11 +154,8 @@ fn pending_transition_key(block_hash: H256) -> H264 {
|
||||
|
||||
let mut key = H264::default();
|
||||
|
||||
{
|
||||
let bytes = key.as_bytes_mut();
|
||||
bytes[0] = LEADING;
|
||||
bytes[1..].copy_from_slice(block_hash.as_bytes());
|
||||
}
|
||||
key[0] = LEADING;
|
||||
key.0[1..].copy_from_slice(&block_hash.0[..]);
|
||||
|
||||
key
|
||||
}
|
||||
@@ -168,11 +165,8 @@ fn transition_key(block_hash: H256) -> H264 {
|
||||
|
||||
let mut key = H264::default();
|
||||
|
||||
{
|
||||
let bytes = key.as_bytes_mut();
|
||||
bytes[0] = LEADING;
|
||||
bytes[1..].copy_from_slice(block_hash.as_bytes());
|
||||
}
|
||||
key[0] = LEADING;
|
||||
key.0[1..].copy_from_slice(&block_hash.0[..]);
|
||||
|
||||
key
|
||||
}
|
||||
@@ -202,21 +196,14 @@ pub enum HardcodedSync {
|
||||
Deny,
|
||||
}
|
||||
|
||||
#[derive(MallocSizeOf)]
|
||||
/// Header chain. See module docs for more details.
|
||||
pub struct HeaderChain {
|
||||
#[ignore_malloc_size_of = "ignored for performance reason"]
|
||||
genesis_header: encoded::Header, // special-case the genesis.
|
||||
candidates: RwLock<BTreeMap<u64, Entry>>,
|
||||
#[ignore_malloc_size_of = "ignored for performance reason"]
|
||||
best_block: RwLock<BlockDescriptor>,
|
||||
#[ignore_malloc_size_of = "ignored for performance reason"]
|
||||
live_epoch_proofs: RwLock<H256FastMap<EpochTransition>>,
|
||||
#[ignore_malloc_size_of = "ignored for performance reason"]
|
||||
db: Arc<KeyValueDB>,
|
||||
#[ignore_malloc_size_of = "ignored for performance reason"]
|
||||
col: Option<u32>,
|
||||
#[ignore_malloc_size_of = "ignored for performance reason"]
|
||||
cache: Arc<Mutex<Cache>>,
|
||||
}
|
||||
|
||||
@@ -250,7 +237,7 @@ impl HeaderChain {
|
||||
for c in &entry.candidates {
|
||||
let key = transition_key(c.hash);
|
||||
|
||||
if let Some(proof) = db.get(col, key.as_bytes())? {
|
||||
if let Some(proof) = db.get(col, &*key)? {
|
||||
live_epoch_proofs.insert(c.hash, EpochTransition {
|
||||
block_hash: c.hash,
|
||||
block_number: cur_number,
|
||||
@@ -267,7 +254,7 @@ impl HeaderChain {
|
||||
let best_block = {
|
||||
let era = match candidates.get(&curr.best_num) {
|
||||
Some(era) => era,
|
||||
None => return Err("Database corrupt: highest block referenced but no data.".into()),
|
||||
None => bail!("Database corrupt: highest block referenced but no data."),
|
||||
};
|
||||
|
||||
let best = &era.candidates[0];
|
||||
@@ -416,7 +403,7 @@ impl HeaderChain {
|
||||
.and_then(|entry| entry.candidates.iter().find(|c| c.hash == parent_hash))
|
||||
.map(|c| c.total_difficulty)
|
||||
.ok_or_else(|| BlockError::UnknownParent(parent_hash))
|
||||
.map_err(Error::Block)?
|
||||
.map_err(EthcoreErrorKind::Block)?
|
||||
};
|
||||
|
||||
parent_td + *header.difficulty()
|
||||
@@ -444,7 +431,7 @@ impl HeaderChain {
|
||||
}
|
||||
|
||||
if let Some(transition) = transition {
|
||||
transaction.put(self.col, transition_key(hash).as_bytes(), &transition.proof);
|
||||
transaction.put(self.col, &*transition_key(hash), &transition.proof);
|
||||
self.live_epoch_proofs.write().insert(hash, transition);
|
||||
}
|
||||
|
||||
@@ -521,10 +508,10 @@ impl HeaderChain {
|
||||
for ancient in &era_entry.candidates {
|
||||
let maybe_transition = live_epoch_proofs.remove(&ancient.hash);
|
||||
if let Some(epoch_transition) = maybe_transition {
|
||||
transaction.delete(self.col, transition_key(ancient.hash).as_bytes());
|
||||
transaction.delete(self.col, &*transition_key(ancient.hash));
|
||||
|
||||
if ancient.hash == era_entry.canonical_hash {
|
||||
last_canonical_transition = match self.db.get(self.col, ancient.hash.as_bytes()) {
|
||||
last_canonical_transition = match self.db.get(self.col, &ancient.hash) {
|
||||
Err(e) => {
|
||||
warn!(target: "chain", "Error reading from DB: {}\n
|
||||
", e);
|
||||
@@ -539,7 +526,7 @@ impl HeaderChain {
|
||||
}
|
||||
}
|
||||
|
||||
transaction.delete(self.col, ancient.hash.as_bytes());
|
||||
transaction.delete(self.col, &ancient.hash);
|
||||
}
|
||||
|
||||
let canon = &era_entry.candidates[0];
|
||||
@@ -589,7 +576,7 @@ impl HeaderChain {
|
||||
} else {
|
||||
let msg = format!("header of block #{} not found in DB ; database in an \
|
||||
inconsistent state", h_num);
|
||||
return Err(msg.into());
|
||||
bail!(msg);
|
||||
};
|
||||
|
||||
let decoded = header.decode().expect("decoding db value failed");
|
||||
@@ -660,7 +647,7 @@ impl HeaderChain {
|
||||
match cache.block_header(&hash) {
|
||||
Some(header) => Some(header),
|
||||
None => {
|
||||
match self.db.get(self.col, hash.as_bytes()) {
|
||||
match self.db.get(self.col, &hash) {
|
||||
Ok(db_value) => {
|
||||
db_value.map(|x| x.into_vec()).map(encoded::Header::new)
|
||||
.and_then(|header| {
|
||||
@@ -785,7 +772,7 @@ impl HeaderChain {
|
||||
|
||||
/// Get block status.
|
||||
pub fn status(&self, hash: &H256) -> BlockStatus {
|
||||
if self.db.get(self.col, hash.as_bytes()).ok().map_or(false, |x| x.is_some()) {
|
||||
if self.db.get(self.col, hash).ok().map_or(false, |x| x.is_some()) {
|
||||
BlockStatus::InChain
|
||||
} else {
|
||||
BlockStatus::Unknown
|
||||
@@ -795,13 +782,13 @@ impl HeaderChain {
|
||||
/// Insert a pending transition.
|
||||
pub fn insert_pending_transition(&self, batch: &mut DBTransaction, hash: H256, t: &PendingEpochTransition) {
|
||||
let key = pending_transition_key(hash);
|
||||
batch.put(self.col, key.as_bytes(), &*::rlp::encode(t));
|
||||
batch.put(self.col, &*key, &*::rlp::encode(t));
|
||||
}
|
||||
|
||||
/// Get pending transition for a specific block hash.
|
||||
pub fn pending_transition(&self, hash: H256) -> Option<PendingEpochTransition> {
|
||||
let key = pending_transition_key(hash);
|
||||
match self.db.get(self.col, key.as_bytes()) {
|
||||
match self.db.get(self.col, &*key) {
|
||||
Ok(db_fetch) => db_fetch.map(|bytes| ::rlp::decode(&bytes).expect("decoding value from db failed")),
|
||||
Err(e) => {
|
||||
warn!(target: "chain", "Error reading from database: {}", e);
|
||||
@@ -845,6 +832,12 @@ impl HeaderChain {
|
||||
}
|
||||
}
|
||||
|
||||
impl HeapSizeOf for HeaderChain {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.candidates.read().heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over a block's ancestry.
|
||||
pub struct AncestryIter<'a> {
|
||||
next: Option<encoded::Header>,
|
||||
@@ -869,11 +862,11 @@ mod tests {
|
||||
use super::{HeaderChain, HardcodedSync};
|
||||
use std::sync::Arc;
|
||||
|
||||
use cache::Cache;
|
||||
use common_types::header::Header;
|
||||
use common_types::ids::BlockId;
|
||||
use ethcore::spec::Spec;
|
||||
use ethereum_types::U256;
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::header::Header;
|
||||
use ethcore::spec::Spec;
|
||||
use cache::Cache;
|
||||
use kvdb::KeyValueDB;
|
||||
use kvdb_memorydb;
|
||||
|
||||
|
||||
@@ -1,39 +1,38 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Light client implementation. Stores data from light sync
|
||||
|
||||
use std::sync::{Weak, Arc};
|
||||
|
||||
use ethcore::block_status::BlockStatus;
|
||||
use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage};
|
||||
use ethcore::engines::{epoch, Engine, EpochChange, EpochTransition, Proof};
|
||||
use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof};
|
||||
use ethcore::machine::EthereumMachine;
|
||||
use ethcore::error::{Error, EthcoreResult};
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::header::{BlockNumber, Header};
|
||||
use ethcore::verification::queue::{self, HeaderQueue};
|
||||
use ethcore::blockchain_info::BlockChainInfo;
|
||||
use ethcore::spec::{Spec, SpecHardcodedSync};
|
||||
use ethcore::encoded;
|
||||
use io::IoChannel;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use ethereum_types::{H256, U256};
|
||||
use futures::{IntoFuture, Future};
|
||||
use common_types::BlockNumber;
|
||||
use common_types::block_status::BlockStatus;
|
||||
use common_types::blockchain_info::BlockChainInfo;
|
||||
use common_types::encoded;
|
||||
use common_types::header::Header;
|
||||
use common_types::ids::BlockId;
|
||||
use common_types::verification_queue_info::VerificationQueueInfo as BlockQueueInfo;
|
||||
|
||||
use kvdb::KeyValueDB;
|
||||
|
||||
@@ -91,9 +90,6 @@ pub trait LightChainClient: Send + Sync {
|
||||
/// Attempt to get a block hash by block id.
|
||||
fn block_hash(&self, id: BlockId) -> Option<H256>;
|
||||
|
||||
/// Get block queue information.
|
||||
fn queue_info(&self) -> BlockQueueInfo;
|
||||
|
||||
/// Attempt to get block header by block id.
|
||||
fn block_header(&self, id: BlockId) -> Option<encoded::Header>;
|
||||
|
||||
@@ -114,20 +110,20 @@ pub trait LightChainClient: Send + Sync {
|
||||
fn env_info(&self, id: BlockId) -> Option<EnvInfo>;
|
||||
|
||||
/// Get a handle to the consensus engine.
|
||||
fn engine(&self) -> &Arc<Engine>;
|
||||
fn engine(&self) -> &Arc<EthEngine>;
|
||||
|
||||
/// 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);
|
||||
|
||||
/// Flush the queue.
|
||||
fn flush_queue(&self);
|
||||
|
||||
/// Get queue info.
|
||||
fn queue_info(&self) -> queue::QueueInfo;
|
||||
|
||||
/// Get the `i`th CHT root.
|
||||
fn cht_root(&self, i: usize) -> Option<H256>;
|
||||
|
||||
@@ -159,7 +155,7 @@ impl<T: LightChainClient> AsLightClient for T {
|
||||
/// Light client implementation.
|
||||
pub struct Client<T> {
|
||||
queue: HeaderQueue,
|
||||
engine: Arc<Engine>,
|
||||
engine: Arc<EthEngine>,
|
||||
chain: HeaderChain,
|
||||
report: RwLock<ClientReport>,
|
||||
import_lock: Mutex<()>,
|
||||
@@ -167,8 +163,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 +189,6 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
listeners: RwLock::new(vec![]),
|
||||
fetcher,
|
||||
verify_full: config.verify_full,
|
||||
exit_handler: Mutex::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -361,21 +354,13 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
|
||||
/// Get blockchain mem usage in bytes.
|
||||
pub fn chain_mem_used(&self) -> usize {
|
||||
use parity_util_mem::MallocSizeOfExt;
|
||||
use heapsize::HeapSizeOf;
|
||||
|
||||
self.chain.malloc_size_of()
|
||||
}
|
||||
|
||||
/// 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));
|
||||
self.chain.heap_size_of_children()
|
||||
}
|
||||
|
||||
/// Get a handle to the verification engine.
|
||||
pub fn engine(&self) -> &Arc<Engine> {
|
||||
pub fn engine(&self) -> &Arc<EthEngine> {
|
||||
&self.engine
|
||||
}
|
||||
|
||||
@@ -467,7 +452,7 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
true
|
||||
}
|
||||
|
||||
fn check_epoch_signal(&self, verified_header: &Header) -> Result<Option<Proof>, T::Error> {
|
||||
fn check_epoch_signal(&self, verified_header: &Header) -> Result<Option<Proof<EthereumMachine>>, T::Error> {
|
||||
use ethcore::machine::{AuxiliaryRequest, AuxiliaryData};
|
||||
|
||||
let mut block: Option<Vec<u8>> = None;
|
||||
@@ -513,7 +498,7 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
}
|
||||
|
||||
// attempts to fetch the epoch proof from the network until successful.
|
||||
fn write_pending_proof(&self, header: &Header, proof: Proof) -> Result<(), T::Error> {
|
||||
fn write_pending_proof(&self, header: &Header, proof: Proof<EthereumMachine>) -> Result<(), T::Error> {
|
||||
let proof = match proof {
|
||||
Proof::Known(known) => known,
|
||||
Proof::WithState(state_dependent) => {
|
||||
@@ -534,7 +519,6 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
fn add_listener(&self, listener: Weak<LightChainNotify>) {
|
||||
Client::add_listener(self, listener)
|
||||
@@ -542,10 +526,6 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
|
||||
fn chain_info(&self) -> BlockChainInfo { Client::chain_info(self) }
|
||||
|
||||
fn queue_info(&self) -> queue::QueueInfo {
|
||||
self.queue.queue_info()
|
||||
}
|
||||
|
||||
fn queue_header(&self, header: Header) -> EthcoreResult<H256> {
|
||||
self.import_header(header)
|
||||
}
|
||||
@@ -578,21 +558,10 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
Client::env_info(self, id)
|
||||
}
|
||||
|
||||
fn engine(&self) -> &Arc<Engine> {
|
||||
fn engine(&self) -> &Arc<EthEngine> {
|
||||
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
|
||||
}
|
||||
@@ -605,6 +574,10 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
Client::flush_queue(self);
|
||||
}
|
||||
|
||||
fn queue_info(&self) -> queue::QueueInfo {
|
||||
self.queue.queue_info()
|
||||
}
|
||||
|
||||
fn cht_root(&self, i: usize) -> Option<H256> {
|
||||
Client::cht_root(self, i)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Minimal IO service for light client.
|
||||
//! Just handles block import messages and passes them to the client.
|
||||
@@ -20,9 +20,8 @@
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ethcore_db as db;
|
||||
use ethcore_blockchain::BlockChainDB;
|
||||
use ethcore::client::ClientIoMessage;
|
||||
use ethcore::{db, BlockChainDB};
|
||||
use ethcore::error::Error as CoreError;
|
||||
use ethcore::spec::Spec;
|
||||
use io::{IoContext, IoError, IoHandler, IoService};
|
||||
@@ -75,8 +74,9 @@ impl<T: ChainDataFetcher> Service<T> {
|
||||
io_service.channel(),
|
||||
cache,
|
||||
)?);
|
||||
spec.engine.register_client(Arc::downgrade(&client) as _);
|
||||
|
||||
io_service.register_handler(Arc::new(ImportBlocks(client.clone()))).map_err(Error::Io)?;
|
||||
spec.engine.register_client(Arc::downgrade(&client) as _);
|
||||
|
||||
Ok(Service {
|
||||
client,
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Light client logic and implementation.
|
||||
//!
|
||||
@@ -54,25 +54,19 @@ extern crate serde_derive;
|
||||
extern crate log;
|
||||
|
||||
extern crate bincode;
|
||||
extern crate common_types;
|
||||
extern crate ethcore_blockchain;
|
||||
extern crate ethcore_db;
|
||||
extern crate ethcore_io as io;
|
||||
extern crate ethcore_network as network;
|
||||
extern crate parity_bytes as bytes;
|
||||
extern crate ethcore_transaction as transaction;
|
||||
extern crate ethereum_types;
|
||||
extern crate ethcore_miner as miner;
|
||||
extern crate ethcore;
|
||||
extern crate hash_db;
|
||||
extern crate parity_util_mem;
|
||||
extern crate parity_util_mem as mem;
|
||||
extern crate parity_util_mem as malloc_size_of;
|
||||
extern crate failsafe;
|
||||
extern crate hashdb;
|
||||
extern crate heapsize;
|
||||
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;
|
||||
@@ -88,10 +82,10 @@ extern crate keccak_hash as hash;
|
||||
extern crate triehash_ethereum as triehash;
|
||||
extern crate kvdb;
|
||||
extern crate memory_cache;
|
||||
extern crate derive_more;
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate kvdb_memorydb;
|
||||
#[cfg(test)]
|
||||
extern crate tempdir;
|
||||
extern crate journaldb;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! I/O and event context generalizations.
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Defines error types and levels of punishment to use upon
|
||||
//! encountering.
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Request load timer and distribution manager.
|
||||
//!
|
||||
@@ -199,15 +199,15 @@ pub struct FileStore(pub PathBuf);
|
||||
impl SampleStore for FileStore {
|
||||
fn load(&self) -> HashMap<Kind, VecDeque<u64>> {
|
||||
File::open(&self.0)
|
||||
.map_err(|e| Box::new(bincode::ErrorKind::Io(e)))
|
||||
.and_then(|mut file| bincode::deserialize_from(&mut file))
|
||||
.map_err(|e| Box::new(bincode::ErrorKind::IoError(e)))
|
||||
.and_then(|mut file| bincode::deserialize_from(&mut file, bincode::Infinite))
|
||||
.unwrap_or_else(|_| HashMap::new())
|
||||
}
|
||||
|
||||
fn store(&self, samples: &HashMap<Kind, VecDeque<u64>>) {
|
||||
let res = File::create(&self.0)
|
||||
.map_err(|e| Box::new(bincode::ErrorKind::Io(e)))
|
||||
.and_then(|mut file| bincode::serialize_into(&mut file, samples));
|
||||
.map_err(|e| Box::new(bincode::ErrorKind::IoError(e)))
|
||||
.and_then(|mut file| bincode::serialize_into(&mut file, samples, bincode::Infinite));
|
||||
|
||||
if let Err(e) = res {
|
||||
warn!(target: "pip", "Error writing light request timing samples to file: {}", e);
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! PLP Protocol Version 1 implementation.
|
||||
//!
|
||||
//! This uses a "Provider" to answer requests.
|
||||
|
||||
use common_types::transaction::UnverifiedTransaction;
|
||||
use transaction::UnverifiedTransaction;
|
||||
|
||||
use ethereum_types::{H256, U256};
|
||||
use io::TimerToken;
|
||||
use kvdb::DBValue;
|
||||
@@ -533,9 +534,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
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Request credit management.
|
||||
//!
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Pending request set.
|
||||
//!
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Peer status and capabilities.
|
||||
|
||||
@@ -382,7 +382,7 @@ mod tests {
|
||||
protocol_version: 1,
|
||||
network_id: 1,
|
||||
head_td: U256::default(),
|
||||
head_hash: H256::zero(),
|
||||
head_hash: H256::default(),
|
||||
head_num: 10,
|
||||
genesis_hash: H256::zero(),
|
||||
last_head: None,
|
||||
@@ -417,7 +417,7 @@ mod tests {
|
||||
protocol_version: 1,
|
||||
network_id: 1,
|
||||
head_td: U256::default(),
|
||||
head_hash: H256::zero(),
|
||||
head_hash: H256::default(),
|
||||
head_num: 10,
|
||||
genesis_hash: H256::zero(),
|
||||
last_head: None,
|
||||
@@ -452,7 +452,7 @@ mod tests {
|
||||
protocol_version: 1,
|
||||
network_id: 1,
|
||||
head_td: U256::default(),
|
||||
head_hash: H256::zero(),
|
||||
head_hash: H256::default(),
|
||||
head_num: 10,
|
||||
genesis_hash: H256::zero(),
|
||||
last_head: None,
|
||||
@@ -550,7 +550,7 @@ mod tests {
|
||||
protocol_version: 1,
|
||||
network_id: 1,
|
||||
head_td: U256::default(),
|
||||
head_hash: H256::zero(),
|
||||
head_hash: H256::default(),
|
||||
head_num: 10,
|
||||
genesis_hash: H256::zero(),
|
||||
last_head: None,
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Tests for the `LightProtocol` implementation.
|
||||
//! These don't test of the higher level logic on top of
|
||||
|
||||
use common_types::blockchain_info::BlockChainInfo;
|
||||
use common_types::encoded;
|
||||
use common_types::ids::BlockId;
|
||||
use common_types::transaction::{Action, PendingTransaction};
|
||||
use ethcore::blockchain_info::BlockChainInfo;
|
||||
use ethcore::client::{EachBlockWith, TestBlockChainClient};
|
||||
use ethereum_types::{H256, U256, Address, BigEndianHash};
|
||||
use net::context::IoContext;
|
||||
use net::load_timer::MOVING_SAMPLE_SIZE;
|
||||
use net::status::{Capabilities, Status};
|
||||
use ethcore::encoded;
|
||||
use ethcore::ids::BlockId;
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use net::{LightProtocol, Params, packet, Peer, Statistics};
|
||||
use net::context::IoContext;
|
||||
use net::status::{Capabilities, Status};
|
||||
use net::load_timer::MOVING_SAMPLE_SIZE;
|
||||
use network::{PeerId, NodeId};
|
||||
use provider::Provider;
|
||||
use request::*;
|
||||
use request;
|
||||
use request::*;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use transaction::{Action, PendingTransaction};
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
@@ -158,7 +158,7 @@ impl Provider for TestProvider {
|
||||
|
||||
fn contract_code(&self, req: request::CompleteCodeRequest) -> Option<request::CodeResponse> {
|
||||
Some(CodeResponse {
|
||||
code: req.block_hash.as_bytes().iter().chain(req.code_hash.as_bytes().iter()).cloned().collect(),
|
||||
code: req.block_hash.iter().chain(req.code_hash.iter()).cloned().collect(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ fn genesis_mismatch() {
|
||||
let (provider, proto) = setup(capabilities);
|
||||
|
||||
let mut status = status(provider.client.chain_info());
|
||||
status.genesis_hash = H256::zero();
|
||||
status.genesis_hash = H256::default();
|
||||
|
||||
let packet_body = write_handshake(&status, &capabilities, &proto);
|
||||
|
||||
@@ -472,16 +472,16 @@ fn get_state_proofs() {
|
||||
}
|
||||
|
||||
let req_id = 112;
|
||||
let key1: H256 = BigEndianHash::from_uint(&U256::from(11223344));
|
||||
let key2: H256 = BigEndianHash::from_uint(&U256::from(99988887));
|
||||
let key1: H256 = U256::from(11223344).into();
|
||||
let key2: H256 = U256::from(99988887).into();
|
||||
|
||||
let mut builder = Builder::default();
|
||||
builder.push(Request::Account(IncompleteAccountRequest {
|
||||
block_hash: H256::zero().into(),
|
||||
block_hash: H256::default().into(),
|
||||
address_hash: key1.into(),
|
||||
})).unwrap();
|
||||
builder.push(Request::Storage(IncompleteStorageRequest {
|
||||
block_hash: H256::zero().into(),
|
||||
block_hash: H256::default().into(),
|
||||
address_hash: key1.into(),
|
||||
key_hash: key2.into(),
|
||||
})).unwrap();
|
||||
@@ -492,11 +492,11 @@ fn get_state_proofs() {
|
||||
let response = {
|
||||
let responses = vec![
|
||||
Response::Account(provider.account_proof(CompleteAccountRequest {
|
||||
block_hash: H256::zero(),
|
||||
block_hash: H256::default(),
|
||||
address_hash: key1,
|
||||
}).unwrap()),
|
||||
Response::Storage(provider.storage_proof(CompleteStorageRequest {
|
||||
block_hash: H256::zero(),
|
||||
block_hash: H256::default(),
|
||||
address_hash: key1,
|
||||
key_hash: key2,
|
||||
}).unwrap()),
|
||||
@@ -529,8 +529,8 @@ fn get_contract_code() {
|
||||
}
|
||||
|
||||
let req_id = 112;
|
||||
let key1: H256 = BigEndianHash::from_uint(&U256::from(11223344));
|
||||
let key2: H256 = BigEndianHash::from_uint(&U256::from(99988887));
|
||||
let key1: H256 = U256::from(11223344).into();
|
||||
let key2: H256 = U256::from(99988887).into();
|
||||
|
||||
let request = Request::Code(IncompleteCodeRequest {
|
||||
block_hash: key1.into(),
|
||||
@@ -541,7 +541,7 @@ fn get_contract_code() {
|
||||
let request_body = make_packet(req_id, &requests);
|
||||
let response = {
|
||||
let response = vec![Response::Code(CodeResponse {
|
||||
code: key1.as_bytes().iter().chain(key2.as_bytes().iter()).cloned().collect(),
|
||||
code: key1.iter().chain(key2.iter()).cloned().collect(),
|
||||
})];
|
||||
|
||||
let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()).unwrap();
|
||||
@@ -616,9 +616,9 @@ fn proof_of_execution() {
|
||||
|
||||
let req_id = 112;
|
||||
let mut request = Request::Execution(request::IncompleteExecutionRequest {
|
||||
block_hash: H256::zero().into(),
|
||||
from: Address::zero(),
|
||||
action: Action::Call(Address::zero()),
|
||||
block_hash: H256::default().into(),
|
||||
from: Address::default(),
|
||||
action: Action::Call(Address::default()),
|
||||
gas: 100.into(),
|
||||
gas_price: 0.into(),
|
||||
value: 0.into(),
|
||||
@@ -755,7 +755,7 @@ fn get_transaction_index() {
|
||||
}
|
||||
|
||||
let req_id = 112;
|
||||
let key1: H256 = BigEndianHash::from_uint(&U256::from(11223344));
|
||||
let key1: H256 = U256::from(11223344).into();
|
||||
|
||||
let request = Request::TransactionIndex(IncompleteTransactionIndexRequest {
|
||||
hash: key1.into(),
|
||||
|
||||
@@ -1,116 +1,92 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! On-demand chain requests over LES. This is a major building block for RPCs.
|
||||
//! The request service is implemented using Futures. Higher level request handlers
|
||||
//! will take the raw data received here and extract meaningful results from it.
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, BTreeSet};
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use ethcore::executed::{Executed, ExecutionError};
|
||||
|
||||
use futures::{Poll, Future, Async};
|
||||
use futures::sync::oneshot::{self, Receiver};
|
||||
use network::PeerId;
|
||||
use parking_lot::{RwLock, Mutex};
|
||||
use rand;
|
||||
use rand::Rng;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use net::{
|
||||
Handler, PeerStatus, Status, Capabilities,
|
||||
self, Handler, PeerStatus, Status, Capabilities,
|
||||
Announcement, EventContext, BasicContext, ReqId,
|
||||
};
|
||||
|
||||
use cache::Cache;
|
||||
use request::{self as basic_request, Request as NetworkRequest};
|
||||
use self::request::CheckedRequest;
|
||||
|
||||
pub use ethcore::executed::ExecutionResult;
|
||||
pub use self::request::{Request, Response, HeaderRef, Error as ValidityError};
|
||||
pub use self::request_guard::{RequestGuard, Error as RequestError};
|
||||
pub use self::response_guard::{ResponseGuard, Error as ResponseGuardError, Inner as ResponseGuardInner};
|
||||
pub use types::request::ResponseError;
|
||||
pub use self::request::{Request, Response, HeaderRef};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub mod request;
|
||||
mod request_guard;
|
||||
mod response_guard;
|
||||
|
||||
/// The initial backoff interval for OnDemand queries
|
||||
pub const DEFAULT_REQUEST_MIN_BACKOFF_DURATION: Duration = Duration::from_secs(10);
|
||||
/// The maximum request interval for OnDemand queries
|
||||
pub const DEFAULT_REQUEST_MAX_BACKOFF_DURATION: Duration = Duration::from_secs(100);
|
||||
/// The default window length a response is evaluated
|
||||
pub const DEFAULT_RESPONSE_TIME_TO_LIVE: Duration = Duration::from_secs(10);
|
||||
/// The default number of maximum backoff iterations
|
||||
pub const DEFAULT_MAX_REQUEST_BACKOFF_ROUNDS: usize = 10;
|
||||
/// The default number failed request to be regarded as failure
|
||||
pub const DEFAULT_NUM_CONSECUTIVE_FAILED_REQUESTS: usize = 1;
|
||||
/// The result of execution
|
||||
pub type ExecutionResult = Result<Executed, ExecutionError>;
|
||||
|
||||
/// The default number of retries for OnDemand queries to send to the other nodes
|
||||
pub const DEFAULT_RETRY_COUNT: usize = 10;
|
||||
|
||||
/// The default time limit in milliseconds for inactive (no new peer to connect to) OnDemand queries (0 for unlimited)
|
||||
pub const DEFAULT_QUERY_TIME_LIMIT: Duration = Duration::from_millis(10000);
|
||||
|
||||
const NULL_DURATION: Duration = Duration::from_secs(0);
|
||||
|
||||
/// OnDemand related errors
|
||||
pub mod error {
|
||||
use futures::sync::oneshot::Canceled;
|
||||
|
||||
/// OnDemand Error
|
||||
#[derive(Debug, derive_more::Display, derive_more::From)]
|
||||
pub enum Error {
|
||||
/// Canceled oneshot channel
|
||||
ChannelCanceled(Canceled),
|
||||
/// Timeout bad response
|
||||
BadResponse(String),
|
||||
/// OnDemand requests limit exceeded
|
||||
#[display(fmt = "OnDemand request maximum backoff iterations exceeded")]
|
||||
RequestLimit,
|
||||
}
|
||||
error_chain! {
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(std::error::Error + 'static)> {
|
||||
match self {
|
||||
Error::ChannelCanceled(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
foreign_links {
|
||||
ChannelCanceled(Canceled) #[doc = "Canceled oneshot channel"];
|
||||
}
|
||||
|
||||
errors {
|
||||
#[doc = "Max number of on-demand query attempts reached without result."]
|
||||
MaxAttemptReach(query_index: usize) {
|
||||
description("On-demand query limit reached")
|
||||
display("On-demand query limit reached on query #{}", query_index)
|
||||
}
|
||||
|
||||
#[doc = "No reply with current peer set, time out occured while waiting for new peers for additional query attempt."]
|
||||
TimeoutOnNewPeers(query_index: usize, remaining_attempts: usize) {
|
||||
description("Timeout for On-demand query")
|
||||
display("Timeout for On-demand query; {} query attempts remain for query #{}", remaining_attempts, query_index)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// OnDemand Result
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
}
|
||||
|
||||
/// Public interface for performing network requests `OnDemand`
|
||||
pub trait OnDemandRequester: Send + Sync {
|
||||
/// Submit a strongly-typed batch of requests.
|
||||
///
|
||||
/// Fails if back-reference are not coherent.
|
||||
fn request<T>(&self, ctx: &BasicContext, requests: T) -> Result<OnResponses<T>, basic_request::NoSuchOutput>
|
||||
where
|
||||
T: request::RequestAdapter;
|
||||
|
||||
/// Submit a vector of requests to be processed together.
|
||||
///
|
||||
/// Fails if back-references are not coherent.
|
||||
/// The returned vector of responses will correspond to the requests exactly.
|
||||
fn request_raw(&self, ctx: &BasicContext, requests: Vec<Request>)
|
||||
-> Result<Receiver<PendingResponse>, basic_request::NoSuchOutput>;
|
||||
}
|
||||
|
||||
|
||||
// relevant peer info.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct Peer {
|
||||
@@ -137,6 +113,7 @@ impl Peer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Either an array of responses or a single error.
|
||||
type PendingResponse = self::error::Result<Vec<Response>>;
|
||||
|
||||
@@ -147,8 +124,10 @@ struct Pending {
|
||||
required_capabilities: Capabilities,
|
||||
responses: Vec<Response>,
|
||||
sender: oneshot::Sender<PendingResponse>,
|
||||
request_guard: RequestGuard,
|
||||
response_guard: ResponseGuard,
|
||||
base_query_index: usize,
|
||||
remaining_query_count: usize,
|
||||
query_id_history: BTreeSet<PeerId>,
|
||||
inactive_time_limit: Option<SystemTime>,
|
||||
}
|
||||
|
||||
impl Pending {
|
||||
@@ -211,7 +190,7 @@ impl Pending {
|
||||
fn try_complete(self) -> Option<Self> {
|
||||
if self.requests.is_complete() {
|
||||
if self.sender.send(Ok(self.responses)).is_err() {
|
||||
debug!(target: "on_demand", "Dropped oneshot channel receiver on request");
|
||||
debug!(target: "on_demand", "Dropped oneshot channel receiver on complete request at query #{}", self.query_id_history.len());
|
||||
}
|
||||
None
|
||||
} else {
|
||||
@@ -248,38 +227,20 @@ impl Pending {
|
||||
self.required_capabilities = capabilities;
|
||||
}
|
||||
|
||||
// received too many empty responses, may be away to indicate a faulty request
|
||||
fn bad_response(self, response_err: ResponseGuardError) {
|
||||
let reqs: Vec<&str> = self.requests.requests().iter().map(|req| {
|
||||
match req {
|
||||
CheckedRequest::HeaderProof(_, _) => "HeaderProof",
|
||||
CheckedRequest::HeaderByHash(_, _) => "HeaderByHash",
|
||||
CheckedRequest::HeaderWithAncestors(_, _) => "HeaderWithAncestors",
|
||||
CheckedRequest::TransactionIndex(_, _) => "TransactionIndex",
|
||||
CheckedRequest::Receipts(_, _) => "Receipts",
|
||||
CheckedRequest::Body(_, _) => "Body",
|
||||
CheckedRequest::Account(_, _) => "Account",
|
||||
CheckedRequest::Code(_, _) => "Code",
|
||||
CheckedRequest::Execution(_, _) => "Execution",
|
||||
CheckedRequest::Signal(_, _) => "Signal",
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let err = format!("Bad response on {}: [ {} ]. {}",
|
||||
if reqs.len() > 1 { "requests" } else { "request" },
|
||||
reqs.join(", "),
|
||||
response_err
|
||||
);
|
||||
|
||||
let err = self::error::Error::BadResponse(err);
|
||||
// returning no reponse, it will result in an error.
|
||||
// self is consumed on purpose.
|
||||
fn no_response(self) {
|
||||
trace!(target: "on_demand", "Dropping a pending query (no reply) at query #{}", self.query_id_history.len());
|
||||
let err = self::error::ErrorKind::MaxAttemptReach(self.requests.num_answered());
|
||||
if self.sender.send(Err(err.into())).is_err() {
|
||||
debug!(target: "on_demand", "Dropped oneshot channel receiver on no response");
|
||||
}
|
||||
}
|
||||
|
||||
// returning a peer discovery timeout during query attempts
|
||||
fn request_limit_reached(self) {
|
||||
let err = self::error::Error::RequestLimit;
|
||||
fn time_out(self) {
|
||||
trace!(target: "on_demand", "Dropping a pending query (no new peer time out) at query #{}", self.query_id_history.len());
|
||||
let err = self::error::ErrorKind::TimeoutOnNewPeers(self.requests.num_answered(), self.query_id_history.len());
|
||||
if self.sender.send(Err(err.into())).is_err() {
|
||||
debug!(target: "on_demand", "Dropped oneshot channel receiver on time out");
|
||||
}
|
||||
@@ -365,15 +326,40 @@ pub struct OnDemand {
|
||||
in_transit: RwLock<HashMap<ReqId, Pending>>,
|
||||
cache: Arc<Mutex<Cache>>,
|
||||
no_immediate_dispatch: bool,
|
||||
response_time_window: Duration,
|
||||
request_backoff_start: Duration,
|
||||
request_backoff_max: Duration,
|
||||
request_backoff_rounds_max: usize,
|
||||
request_number_of_consecutive_errors: usize
|
||||
base_retry_count: usize,
|
||||
query_inactive_time_limit: Option<Duration>,
|
||||
}
|
||||
|
||||
impl OnDemandRequester for OnDemand {
|
||||
fn request_raw(&self, ctx: &BasicContext, requests: Vec<Request>)
|
||||
impl OnDemand {
|
||||
|
||||
/// Create a new `OnDemand` service with the given cache.
|
||||
pub fn new(cache: Arc<Mutex<Cache>>) -> Self {
|
||||
OnDemand {
|
||||
pending: RwLock::new(Vec::new()),
|
||||
peers: RwLock::new(HashMap::new()),
|
||||
in_transit: RwLock::new(HashMap::new()),
|
||||
cache,
|
||||
no_immediate_dispatch: false,
|
||||
base_retry_count: DEFAULT_RETRY_COUNT,
|
||||
query_inactive_time_limit: Some(DEFAULT_QUERY_TIME_LIMIT),
|
||||
}
|
||||
}
|
||||
|
||||
// make a test version: this doesn't dispatch pending requests
|
||||
// until you trigger it manually.
|
||||
#[cfg(test)]
|
||||
fn new_test(cache: Arc<Mutex<Cache>>) -> Self {
|
||||
let mut me = OnDemand::new(cache);
|
||||
me.no_immediate_dispatch = true;
|
||||
|
||||
me
|
||||
}
|
||||
|
||||
/// Submit a vector of requests to be processed together.
|
||||
///
|
||||
/// Fails if back-references are not coherent.
|
||||
/// The returned vector of responses will correspond to the requests exactly.
|
||||
pub fn request_raw(&self, ctx: &BasicContext, requests: Vec<Request>)
|
||||
-> Result<Receiver<PendingResponse>, basic_request::NoSuchOutput>
|
||||
{
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
@@ -417,19 +403,19 @@ impl OnDemandRequester for OnDemand {
|
||||
required_capabilities: capabilities,
|
||||
responses,
|
||||
sender,
|
||||
request_guard: RequestGuard::new(
|
||||
self.request_number_of_consecutive_errors as u32,
|
||||
self.request_backoff_rounds_max,
|
||||
self.request_backoff_start,
|
||||
self.request_backoff_max,
|
||||
),
|
||||
response_guard: ResponseGuard::new(self.response_time_window),
|
||||
base_query_index: 0,
|
||||
remaining_query_count: 0,
|
||||
query_id_history: BTreeSet::new(),
|
||||
inactive_time_limit: None,
|
||||
});
|
||||
|
||||
Ok(receiver)
|
||||
}
|
||||
|
||||
fn request<T>(&self, ctx: &BasicContext, requests: T) -> Result<OnResponses<T>, basic_request::NoSuchOutput>
|
||||
/// Submit a strongly-typed batch of requests.
|
||||
///
|
||||
/// Fails if back-reference are not coherent.
|
||||
pub fn request<T>(&self, ctx: &BasicContext, requests: T) -> Result<OnResponses<T>, basic_request::NoSuchOutput>
|
||||
where T: request::RequestAdapter
|
||||
{
|
||||
self.request_raw(ctx, requests.make_requests()).map(|recv| OnResponses {
|
||||
@@ -438,69 +424,6 @@ impl OnDemandRequester for OnDemand {
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl OnDemand {
|
||||
|
||||
/// Create a new `OnDemand` service with the given cache.
|
||||
pub fn new(
|
||||
cache: Arc<Mutex<Cache>>,
|
||||
response_time_window: Duration,
|
||||
request_backoff_start: Duration,
|
||||
request_backoff_max: Duration,
|
||||
request_backoff_rounds_max: usize,
|
||||
request_number_of_consecutive_errors: usize,
|
||||
) -> Self {
|
||||
|
||||
Self {
|
||||
pending: RwLock::new(Vec::new()),
|
||||
peers: RwLock::new(HashMap::new()),
|
||||
in_transit: RwLock::new(HashMap::new()),
|
||||
cache,
|
||||
no_immediate_dispatch: false,
|
||||
response_time_window: Self::sanitize_circuit_breaker_input(response_time_window, "Response time window"),
|
||||
request_backoff_start: Self::sanitize_circuit_breaker_input(request_backoff_start, "Request initial backoff time window"),
|
||||
request_backoff_max: Self::sanitize_circuit_breaker_input(request_backoff_max, "Request maximum backoff time window"),
|
||||
request_backoff_rounds_max,
|
||||
request_number_of_consecutive_errors,
|
||||
}
|
||||
}
|
||||
|
||||
fn sanitize_circuit_breaker_input(dur: Duration, name: &'static str) -> Duration {
|
||||
if dur.as_secs() < 1 {
|
||||
warn!(target: "on_demand",
|
||||
"{} is too short must be at least 1 second, configuring it to 1 second", name);
|
||||
Duration::from_secs(1)
|
||||
} else {
|
||||
dur
|
||||
}
|
||||
}
|
||||
|
||||
// make a test version: this doesn't dispatch pending requests
|
||||
// until you trigger it manually.
|
||||
#[cfg(test)]
|
||||
fn new_test(
|
||||
cache: Arc<Mutex<Cache>>,
|
||||
request_ttl: Duration,
|
||||
request_backoff_start: Duration,
|
||||
request_backoff_max: Duration,
|
||||
request_backoff_rounds_max: usize,
|
||||
request_number_of_consecutive_errors: usize,
|
||||
) -> Self {
|
||||
let mut me = OnDemand::new(
|
||||
cache,
|
||||
request_ttl,
|
||||
request_backoff_start,
|
||||
request_backoff_max,
|
||||
request_backoff_rounds_max,
|
||||
request_number_of_consecutive_errors,
|
||||
);
|
||||
me.no_immediate_dispatch = true;
|
||||
|
||||
me
|
||||
}
|
||||
|
||||
|
||||
// maybe dispatch pending requests.
|
||||
// sometimes
|
||||
fn attempt_dispatch(&self, ctx: &BasicContext) {
|
||||
@@ -512,56 +435,82 @@ impl OnDemand {
|
||||
// dispatch pending requests, and discard those for which the corresponding
|
||||
// receiver has been dropped.
|
||||
fn dispatch_pending(&self, ctx: &BasicContext) {
|
||||
if self.pending.read().is_empty() {
|
||||
return
|
||||
}
|
||||
|
||||
if self.pending.read().is_empty() { return }
|
||||
let mut pending = self.pending.write();
|
||||
|
||||
debug!(target: "on_demand", "Attempting to dispatch {} pending requests", pending.len());
|
||||
|
||||
// iterate over all pending requests, and check them for hang-up.
|
||||
// then, try and find a peer who can serve it.
|
||||
let peers = self.peers.read();
|
||||
|
||||
*pending = ::std::mem::replace(&mut *pending, Vec::new())
|
||||
.into_iter()
|
||||
*pending = ::std::mem::replace(&mut *pending, Vec::new()).into_iter()
|
||||
.filter(|pending| !pending.sender.is_canceled())
|
||||
.filter_map(|mut pending| {
|
||||
|
||||
// the peer we dispatch to is chosen randomly
|
||||
let num_peers = peers.len();
|
||||
// The first peer to dispatch the request is chosen at random
|
||||
let rand = rand::thread_rng().gen_range(0, cmp::max(1, num_peers));
|
||||
|
||||
for (peer_id, peer) in peers
|
||||
.iter()
|
||||
.cycle()
|
||||
.skip(rand)
|
||||
.take(num_peers)
|
||||
{
|
||||
|
||||
if !peer.can_fulfill(&pending.required_capabilities) {
|
||||
trace!(target: "on_demand", "Peer {} without required capabilities, skipping", peer_id);
|
||||
continue
|
||||
let history_len = pending.query_id_history.len();
|
||||
let offset = if history_len == 0 {
|
||||
pending.remaining_query_count = self.base_retry_count;
|
||||
let rand = rand::random::<usize>();
|
||||
pending.base_query_index = rand;
|
||||
rand
|
||||
} else {
|
||||
pending.base_query_index + history_len
|
||||
} % cmp::max(num_peers, 1);
|
||||
let init_remaining_query_count = pending.remaining_query_count; // to fail in case of big reduction of nb of peers
|
||||
for (peer_id, peer) in peers.iter().chain(peers.iter())
|
||||
.skip(offset).take(num_peers) {
|
||||
// TODO: see which requests can be answered by the cache?
|
||||
if pending.remaining_query_count == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if pending.request_guard.is_call_permitted() {
|
||||
if let Ok(req_id) = ctx.request_from(*peer_id, pending.net_requests.clone()) {
|
||||
self.in_transit.write().insert(req_id, pending);
|
||||
return None;
|
||||
if pending.query_id_history.insert(peer_id.clone()) {
|
||||
|
||||
if !peer.can_fulfill(&pending.required_capabilities) {
|
||||
trace!(target: "on_demand", "Peer {} without required capabilities, skipping, {} remaining attempts", peer_id, pending.remaining_query_count);
|
||||
continue
|
||||
}
|
||||
|
||||
pending.remaining_query_count -= 1;
|
||||
pending.inactive_time_limit = None;
|
||||
|
||||
match ctx.request_from(*peer_id, pending.net_requests.clone()) {
|
||||
Ok(req_id) => {
|
||||
trace!(target: "on_demand", "Dispatched request {} to peer {}, {} remaining attempts", req_id, peer_id, pending.remaining_query_count);
|
||||
self.in_transit.write().insert(req_id, pending);
|
||||
return None
|
||||
}
|
||||
Err(net::Error::NoCredits) | Err(net::Error::NotServer) => {}
|
||||
Err(e) => debug!(target: "on_demand", "Error dispatching request to peer: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register that the request round failed
|
||||
if let RequestError::ReachedLimit = pending.request_guard.register_error() {
|
||||
pending.request_limit_reached();
|
||||
if pending.remaining_query_count == 0 {
|
||||
pending.no_response();
|
||||
None
|
||||
} else if init_remaining_query_count == pending.remaining_query_count {
|
||||
if let Some(query_inactive_time_limit) = self.query_inactive_time_limit {
|
||||
let now = SystemTime::now();
|
||||
if let Some(inactive_time_limit) = pending.inactive_time_limit {
|
||||
if now > inactive_time_limit {
|
||||
pending.time_out();
|
||||
return None
|
||||
}
|
||||
} else {
|
||||
debug!(target: "on_demand", "No more peers to query, waiting for {} seconds until dropping query", query_inactive_time_limit.as_secs());
|
||||
pending.inactive_time_limit = Some(now + query_inactive_time_limit);
|
||||
}
|
||||
}
|
||||
Some(pending)
|
||||
} else {
|
||||
Some(pending)
|
||||
}
|
||||
})
|
||||
.collect(); // `pending` now contains all requests we couldn't dispatch
|
||||
})
|
||||
.collect(); // `pending` now contains all requests we couldn't dispatch.
|
||||
|
||||
trace!(target: "on_demand", "Was unable to dispatch {} requests.", pending.len());
|
||||
debug!(target: "on_demand", "Was unable to dispatch {} requests.", pending.len());
|
||||
}
|
||||
|
||||
// submit a pending request set. attempts to answer from cache before
|
||||
@@ -572,14 +521,26 @@ impl OnDemand {
|
||||
|
||||
pending.answer_from_cache(&*self.cache);
|
||||
if let Some(mut pending) = pending.try_complete() {
|
||||
// update cached requests
|
||||
pending.update_net_requests();
|
||||
// push into `pending` buffer
|
||||
self.pending.write().push(pending);
|
||||
// try to dispatch
|
||||
self.attempt_dispatch(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the retry count for a query.
|
||||
pub fn default_retry_number(&mut self, nb_retry: usize) {
|
||||
self.base_retry_count = nb_retry;
|
||||
}
|
||||
|
||||
/// Set the time limit for a query.
|
||||
pub fn query_inactive_time_limit(&mut self, inactive_time_limit: Duration) {
|
||||
self.query_inactive_time_limit = if inactive_time_limit == NULL_DURATION {
|
||||
None
|
||||
} else {
|
||||
Some(inactive_time_limit)
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Handler for OnDemand {
|
||||
@@ -633,11 +594,13 @@ impl Handler for OnDemand {
|
||||
};
|
||||
|
||||
if responses.is_empty() {
|
||||
// Max number of `bad` responses reached, drop the request
|
||||
if let Err(e) = pending.response_guard.register_error(&ResponseError::Validity(ValidityError::Empty)) {
|
||||
pending.bad_response(e);
|
||||
if pending.remaining_query_count == 0 {
|
||||
pending.no_response();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// do not keep query counter for others elements of this batch
|
||||
pending.query_id_history.clear();
|
||||
}
|
||||
|
||||
// for each incoming response
|
||||
@@ -650,11 +613,7 @@ impl Handler for OnDemand {
|
||||
debug!(target: "on_demand", "Peer {} gave bad response: {:?}", peer, e);
|
||||
ctx.disable_peer(peer);
|
||||
|
||||
// Max number of `bad` responses reached, drop the request
|
||||
if let Err(err) = pending.response_guard.register_error(&e) {
|
||||
pending.bad_response(err);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Request types, verification, and verification errors.
|
||||
|
||||
@@ -20,20 +20,22 @@ use std::cmp;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::Bytes;
|
||||
use common_types::basic_account::BasicAccount;
|
||||
use common_types::encoded;
|
||||
use common_types::receipt::Receipt;
|
||||
use common_types::transaction::SignedTransaction;
|
||||
use ethcore::engines::{Engine, StateDependentProof};
|
||||
use ethcore::basic_account::BasicAccount;
|
||||
use ethcore::encoded;
|
||||
use ethcore::engines::{EthEngine, StateDependentProof};
|
||||
use ethcore::machine::EthereumMachine;
|
||||
use ethcore::receipt::Receipt;
|
||||
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};
|
||||
use transaction::SignedTransaction;
|
||||
use trie::Trie;
|
||||
use vm::EnvInfo;
|
||||
|
||||
@@ -979,10 +981,10 @@ impl Account {
|
||||
let header = self.header.as_ref()?;
|
||||
let state_root = header.state_root();
|
||||
|
||||
let mut db = journaldb::new_memory_db();
|
||||
for node in proof { db.insert(hash_db::EMPTY_PREFIX, &node[..]); }
|
||||
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).as_bytes()))? {
|
||||
match TrieDB::new(&db, &state_root).and_then(|t| t.get(&keccak(&self.address)))? {
|
||||
Some(val) => {
|
||||
let rlp = Rlp::new(&val);
|
||||
Ok(Some(BasicAccount {
|
||||
@@ -1037,7 +1039,7 @@ pub struct TransactionProof {
|
||||
// TODO: it's not really possible to provide this if the header is unknown.
|
||||
pub env_info: EnvInfo,
|
||||
/// Consensus engine.
|
||||
pub engine: Arc<Engine>,
|
||||
pub engine: Arc<EthEngine>,
|
||||
}
|
||||
|
||||
impl TransactionProof {
|
||||
@@ -1080,9 +1082,9 @@ pub struct Signal {
|
||||
/// Block hash and number to fetch proof for.
|
||||
pub hash: H256,
|
||||
/// Consensus engine, used to check the proof.
|
||||
pub engine: Arc<Engine>,
|
||||
pub engine: Arc<EthEngine>,
|
||||
/// Special checker for the proof.
|
||||
pub proof_check: Arc<StateDependentProof>,
|
||||
pub proof_check: Arc<StateDependentProof<EthereumMachine>>,
|
||||
}
|
||||
|
||||
impl Signal {
|
||||
@@ -1099,16 +1101,17 @@ 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};
|
||||
use trie::Recorder;
|
||||
use hash::keccak;
|
||||
|
||||
use ethcore::client::{BlockChainClient, BlockInfo, TestBlockChainClient, EachBlockWith};
|
||||
use common_types::header::Header;
|
||||
use common_types::encoded;
|
||||
use common_types::receipt::{Receipt, TransactionOutcome};
|
||||
use ::ethcore::client::{BlockChainClient, BlockInfo, TestBlockChainClient, EachBlockWith};
|
||||
use ethcore::header::Header;
|
||||
use ethcore::encoded;
|
||||
use ethcore::receipt::{Receipt, TransactionOutcome};
|
||||
|
||||
fn make_cache() -> ::cache::Cache {
|
||||
::cache::Cache::new(Default::default(), Duration::from_secs(1))
|
||||
@@ -1161,7 +1164,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn check_header_with_ancestors() {
|
||||
let mut last_header_hash = H256::zero();
|
||||
let mut last_header_hash = H256::default();
|
||||
let mut headers = (0..11).map(|num| {
|
||||
let mut header = Header::new();
|
||||
header.set_number(num);
|
||||
@@ -1277,8 +1280,8 @@ mod tests {
|
||||
fn check_state_proof() {
|
||||
use rlp::RlpStream;
|
||||
|
||||
let mut root = H256::zero();
|
||||
let mut db = journaldb::new_memory_db();
|
||||
let mut root = H256::default();
|
||||
let mut db = MemoryDB::new();
|
||||
let mut header = Header::new();
|
||||
header.set_number(123_456);
|
||||
header.set_extra_data(b"test_header".to_vec());
|
||||
@@ -1297,17 +1300,17 @@ mod tests {
|
||||
let mut trie = SecTrieDBMut::new(&mut db, &mut root);
|
||||
for _ in 0..100 {
|
||||
let address = Address::random();
|
||||
trie.insert(address.as_bytes(), &rand_acc()).unwrap();
|
||||
trie.insert(&*address, &rand_acc()).unwrap();
|
||||
}
|
||||
|
||||
trie.insert(addr.as_bytes(), &rand_acc()).unwrap();
|
||||
trie.insert(&*addr, &rand_acc()).unwrap();
|
||||
}
|
||||
|
||||
let proof = {
|
||||
let trie = SecTrieDB::new(&db, &root).unwrap();
|
||||
let mut recorder = Recorder::new();
|
||||
|
||||
trie.get_with(addr.as_bytes(), &mut recorder).unwrap().unwrap();
|
||||
trie.get_with(&*addr, &mut recorder).unwrap().unwrap();
|
||||
|
||||
recorder.drain().into_iter().map(|r| r.data).collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
@@ -1,123 +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/>.
|
||||
|
||||
use failsafe;
|
||||
use std::time::Duration;
|
||||
|
||||
type RequestPolicy = failsafe::failure_policy::ConsecutiveFailures<failsafe::backoff::Exponential>;
|
||||
|
||||
/// Error wrapped on-top of `FailsafeError`
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
/// The call is let through
|
||||
LetThrough,
|
||||
/// The call rejected by the guard
|
||||
Rejected,
|
||||
/// The request reached the maximum of backoff iterations
|
||||
ReachedLimit,
|
||||
}
|
||||
|
||||
/// Handle and register requests that can fail
|
||||
#[derive(Debug)]
|
||||
pub struct RequestGuard {
|
||||
backoff_round: usize,
|
||||
max_backoff_rounds: usize,
|
||||
state: failsafe::StateMachine<RequestPolicy, ()>,
|
||||
}
|
||||
|
||||
impl RequestGuard {
|
||||
/// Constructor
|
||||
pub fn new(
|
||||
consecutive_failures: u32,
|
||||
max_backoff_rounds: usize,
|
||||
start_backoff: Duration,
|
||||
max_backoff: Duration,
|
||||
) -> Self {
|
||||
let backoff = failsafe::backoff::exponential(start_backoff, max_backoff);
|
||||
// success_rate not used because only errors are registered
|
||||
let policy = failsafe::failure_policy::consecutive_failures(consecutive_failures as u32, backoff);
|
||||
|
||||
Self {
|
||||
backoff_round: 0,
|
||||
max_backoff_rounds,
|
||||
state: failsafe::StateMachine::new(policy, ()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the state after a `faulty` call
|
||||
pub fn register_error(&mut self) -> Error {
|
||||
trace!(target: "circuit_breaker", "RequestGuard; backoff_round: {}/{}, state {:?}",
|
||||
self.backoff_round, self.max_backoff_rounds, self.state);
|
||||
|
||||
if self.backoff_round >= self.max_backoff_rounds {
|
||||
Error::ReachedLimit
|
||||
} else if self.state.is_call_permitted() {
|
||||
self.state.on_error();
|
||||
if self.state.is_call_permitted() {
|
||||
Error::LetThrough
|
||||
} else {
|
||||
self.backoff_round += 1;
|
||||
Error::Rejected
|
||||
}
|
||||
} else {
|
||||
Error::Rejected
|
||||
}
|
||||
}
|
||||
|
||||
/// Poll the circuit breaker, to check if the call is permitted
|
||||
pub fn is_call_permitted(&self) -> bool {
|
||||
self.state.is_call_permitted()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::iter;
|
||||
use std::time::Instant;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn one_consecutive_failure_with_10_backoffs() {
|
||||
// 1, 2, 4, 5, 5 .... 5
|
||||
let binary_exp_backoff = vec![1_u64, 2, 4].into_iter().chain(iter::repeat(5_u64).take(7));
|
||||
let mut guard = RequestGuard::new(1, 10, Duration::from_secs(1), Duration::from_secs(5));
|
||||
for backoff in binary_exp_backoff {
|
||||
assert_eq!(guard.register_error(), Error::Rejected);
|
||||
let now = Instant::now();
|
||||
while now.elapsed() <= Duration::from_secs(backoff) {}
|
||||
}
|
||||
assert_eq!(guard.register_error(), Error::ReachedLimit, "10 backoffs should be error");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn five_consecutive_failures_with_3_backoffs() {
|
||||
let mut guard = RequestGuard::new(5, 3, Duration::from_secs(1), Duration::from_secs(30));
|
||||
|
||||
// register five errors
|
||||
for _ in 0..4 {
|
||||
assert_eq!(guard.register_error(), Error::LetThrough);
|
||||
}
|
||||
|
||||
let binary_exp_backoff = [1, 2, 4];
|
||||
for backoff in &binary_exp_backoff {
|
||||
assert_eq!(guard.register_error(), Error::Rejected);
|
||||
let now = Instant::now();
|
||||
while now.elapsed() <= Duration::from_secs(*backoff) {}
|
||||
}
|
||||
|
||||
assert_eq!(guard.register_error(), Error::ReachedLimit, "3 backoffs should be an error");
|
||||
}
|
||||
}
|
||||
@@ -1,173 +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/>.
|
||||
|
||||
//! ResponseGuard implementation.
|
||||
//! It is responsible for the receiving end of `Pending Request` (see `OnDemand` module docs for more information)
|
||||
//! The major functionality is the following:
|
||||
//! 1) Register non-successful responses which will reported back if it fails
|
||||
//! 2) A timeout mechanism that will wait for successful response at most t seconds
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
use super::{ResponseError, ValidityError};
|
||||
|
||||
/// Response guard error type
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Error {
|
||||
/// No majority, the error reason can't be determined
|
||||
NoMajority(usize),
|
||||
/// Majority, with the error reason
|
||||
Majority(Inner, usize, usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error::Majority(err, majority, total) => {
|
||||
write!(f, "Error cause was {:?}, (majority count: {} / total: {})",
|
||||
err, majority, total)
|
||||
}
|
||||
Error::NoMajority(total) => {
|
||||
write!(f, "Error cause couldn't be determined, the total number of responses was {}", total)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dummy type to convert a generic type with no trait bounds
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Inner {
|
||||
/// Bad execution proof
|
||||
BadProof,
|
||||
/// RLP decoding
|
||||
Decoder,
|
||||
/// Empty response
|
||||
EmptyResponse,
|
||||
/// Wrong header sequence
|
||||
HeaderByNumber,
|
||||
/// Too few results
|
||||
TooFewResults,
|
||||
/// Too many results
|
||||
TooManyResults,
|
||||
/// Trie error
|
||||
Trie,
|
||||
/// Unresolved header
|
||||
UnresolvedHeader,
|
||||
/// No responses expected.
|
||||
Unexpected,
|
||||
/// Wrong hash
|
||||
WrongHash,
|
||||
/// Wrong Header sequence
|
||||
WrongHeaderSequence,
|
||||
/// Wrong response kind
|
||||
WrongKind,
|
||||
/// Wrong number
|
||||
WrongNumber,
|
||||
/// Wrong Trie Root
|
||||
WrongTrieRoot,
|
||||
}
|
||||
|
||||
/// Handle and register responses that can fail
|
||||
#[derive(Debug)]
|
||||
pub struct ResponseGuard {
|
||||
request_start: Instant,
|
||||
time_to_live: Duration,
|
||||
responses: HashMap<Inner, usize>,
|
||||
number_responses: usize,
|
||||
}
|
||||
|
||||
impl ResponseGuard {
|
||||
/// Constructor
|
||||
pub fn new(time_to_live: Duration) -> Self {
|
||||
Self {
|
||||
request_start: Instant::now(),
|
||||
time_to_live,
|
||||
responses: HashMap::new(),
|
||||
number_responses: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_reason(&self, err: &ResponseError<super::request::Error>) -> Inner {
|
||||
match err {
|
||||
ResponseError::Unexpected => Inner::Unexpected,
|
||||
ResponseError::Validity(ValidityError::BadProof) => Inner::BadProof,
|
||||
ResponseError::Validity(ValidityError::Decoder(_)) => Inner::Decoder,
|
||||
ResponseError::Validity(ValidityError::Empty) => Inner::EmptyResponse,
|
||||
ResponseError::Validity(ValidityError::HeaderByNumber) => Inner::HeaderByNumber,
|
||||
ResponseError::Validity(ValidityError::TooFewResults(_, _)) => Inner::TooFewResults,
|
||||
ResponseError::Validity(ValidityError::TooManyResults(_, _)) => Inner::TooManyResults,
|
||||
ResponseError::Validity(ValidityError::Trie(_)) => Inner::Trie,
|
||||
ResponseError::Validity(ValidityError::UnresolvedHeader(_)) => Inner::UnresolvedHeader,
|
||||
ResponseError::Validity(ValidityError::WrongHash(_, _)) => Inner::WrongHash,
|
||||
ResponseError::Validity(ValidityError::WrongHeaderSequence) => Inner::WrongHeaderSequence,
|
||||
ResponseError::Validity(ValidityError::WrongKind) => Inner::WrongKind,
|
||||
ResponseError::Validity(ValidityError::WrongNumber(_, _)) => Inner::WrongNumber,
|
||||
ResponseError::Validity(ValidityError::WrongTrieRoot(_, _)) => Inner::WrongTrieRoot,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the state after a `faulty` call
|
||||
pub fn register_error(&mut self, err: &ResponseError<super::request::Error>) -> Result<(), Error> {
|
||||
let err = self.into_reason(err);
|
||||
*self.responses.entry(err).or_insert(0) += 1;
|
||||
self.number_responses = self.number_responses.saturating_add(1);
|
||||
trace!(target: "circuit_breaker", "ResponseGuard: {:?}", self.responses);
|
||||
// The request has exceeded its timeout
|
||||
if self.request_start.elapsed() >= self.time_to_live {
|
||||
let (&err, &max_count) = self.responses.iter().max_by_key(|(_k, v)| *v).expect("got at least one element; qed");
|
||||
let majority = self.responses.values().filter(|v| **v == max_count).count() == 1;
|
||||
if majority {
|
||||
Err(Error::Majority(err, max_count, self.number_responses))
|
||||
} else {
|
||||
Err(Error::NoMajority(self.number_responses))
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::thread;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_basic_by_majority() {
|
||||
let mut guard = ResponseGuard::new(Duration::from_secs(5));
|
||||
guard.register_error(&ResponseError::Validity(ValidityError::Empty)).unwrap();
|
||||
guard.register_error(&ResponseError::Unexpected).unwrap();
|
||||
guard.register_error(&ResponseError::Unexpected).unwrap();
|
||||
guard.register_error(&ResponseError::Unexpected).unwrap();
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
|
||||
assert_eq!(guard.register_error(&ResponseError::Validity(ValidityError::WrongKind)), Err(Error::Majority(Inner::Unexpected, 3, 5)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_majority() {
|
||||
let mut guard = ResponseGuard::new(Duration::from_secs(5));
|
||||
guard.register_error(&ResponseError::Validity(ValidityError::Empty)).unwrap();
|
||||
guard.register_error(&ResponseError::Validity(ValidityError::Empty)).unwrap();
|
||||
guard.register_error(&ResponseError::Unexpected).unwrap();
|
||||
guard.register_error(&ResponseError::Unexpected).unwrap();
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
|
||||
assert_eq!(guard.register_error(&ResponseError::Validity(ValidityError::WrongKind)), Err(Error::NoMajority(5)));
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,34 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Tests for the on-demand service.
|
||||
|
||||
use cache::Cache;
|
||||
use ethcore::header::Header;
|
||||
use futures::Future;
|
||||
use network::{PeerId, NodeId};
|
||||
use net::*;
|
||||
use common_types::header::Header;
|
||||
use ethereum_types::H256;
|
||||
use parking_lot::Mutex;
|
||||
use request::{self as basic_request, Response};
|
||||
use std::time::Duration;
|
||||
use ::request::{self as basic_request, Response};
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::thread;
|
||||
|
||||
use super::{request, OnDemand, OnDemandRequester, Peer, HeaderRef};
|
||||
use super::{request, OnDemand, Peer, HeaderRef};
|
||||
|
||||
// useful contexts to give the service.
|
||||
enum Context {
|
||||
@@ -37,7 +36,6 @@ enum Context {
|
||||
WithPeer(PeerId),
|
||||
RequestFrom(PeerId, ReqId),
|
||||
Punish(PeerId),
|
||||
FaultyRequest,
|
||||
}
|
||||
|
||||
impl EventContext for Context {
|
||||
@@ -46,7 +44,6 @@ impl EventContext for Context {
|
||||
Context::WithPeer(id)
|
||||
| Context::RequestFrom(id, _)
|
||||
| Context::Punish(id) => id,
|
||||
| Context::FaultyRequest => 0,
|
||||
_ => panic!("didn't expect to have peer queried."),
|
||||
}
|
||||
}
|
||||
@@ -63,7 +60,6 @@ impl BasicContext for Context {
|
||||
fn request_from(&self, peer_id: PeerId, _: ::request::NetworkRequests) -> Result<ReqId, Error> {
|
||||
match *self {
|
||||
Context::RequestFrom(id, req_id) => if peer_id == id { Ok(req_id) } else { Err(Error::NoCredits) },
|
||||
Context::FaultyRequest => Err(Error::NoCredits),
|
||||
_ => panic!("didn't expect to have requests dispatched."),
|
||||
}
|
||||
}
|
||||
@@ -93,17 +89,7 @@ impl Harness {
|
||||
fn create() -> Self {
|
||||
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(60))));
|
||||
Harness {
|
||||
service: OnDemand::new_test(
|
||||
cache,
|
||||
// Response `time_to_live`
|
||||
Duration::from_secs(5),
|
||||
// Request start backoff
|
||||
Duration::from_secs(1),
|
||||
// Request max backoff
|
||||
Duration::from_secs(20),
|
||||
super::DEFAULT_MAX_REQUEST_BACKOFF_ROUNDS,
|
||||
super::DEFAULT_NUM_CONSECUTIVE_FAILED_REQUESTS
|
||||
)
|
||||
service: OnDemand::new_test(cache),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,9 +103,9 @@ fn dummy_status() -> Status {
|
||||
protocol_version: 1,
|
||||
network_id: 999,
|
||||
head_td: 1.into(),
|
||||
head_hash: H256::zero(),
|
||||
head_hash: H256::default(),
|
||||
head_num: 1359,
|
||||
genesis_hash: H256::zero(),
|
||||
genesis_hash: H256::default(),
|
||||
last_head: None,
|
||||
}
|
||||
}
|
||||
@@ -138,7 +124,7 @@ fn detects_hangup() {
|
||||
let on_demand = Harness::create().service;
|
||||
let result = on_demand.request_raw(
|
||||
&Context::NoOp,
|
||||
vec![request::HeaderByHash(H256::zero().into()).into()],
|
||||
vec![request::HeaderByHash(H256::default().into()).into()],
|
||||
);
|
||||
|
||||
assert_eq!(on_demand.pending.read().len(), 1);
|
||||
@@ -199,7 +185,7 @@ fn no_capabilities() {
|
||||
|
||||
let _recv = harness.service.request_raw(
|
||||
&Context::NoOp,
|
||||
vec![request::HeaderByHash(H256::zero().into()).into()]
|
||||
vec![request::HeaderByHash(H256::default().into()).into()]
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(harness.service.pending.read().len(), 1);
|
||||
@@ -395,7 +381,7 @@ fn wrong_kind() {
|
||||
|
||||
let _recv = harness.service.request_raw(
|
||||
&Context::NoOp,
|
||||
vec![request::HeaderByHash(H256::zero().into()).into()]
|
||||
vec![request::HeaderByHash(H256::default().into()).into()]
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(harness.service.pending.read().len(), 1);
|
||||
@@ -509,90 +495,3 @@ fn fill_from_cache() {
|
||||
|
||||
assert!(recv.wait().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_without_response_should_backoff_and_then_be_dropped() {
|
||||
let harness = Harness::create();
|
||||
let peer_id = 0;
|
||||
let req_id = ReqId(13);
|
||||
|
||||
harness.inject_peer(
|
||||
peer_id,
|
||||
Peer {
|
||||
status: dummy_status(),
|
||||
capabilities: dummy_capabilities(),
|
||||
}
|
||||
);
|
||||
|
||||
let binary_exp_backoff: Vec<u64> = vec![1, 2, 4, 8, 16, 20, 20, 20, 20, 20];
|
||||
|
||||
let _recv = harness.service.request_raw(
|
||||
&Context::RequestFrom(peer_id, req_id),
|
||||
vec![request::HeaderByHash(Header::default().encoded().hash().into()).into()],
|
||||
).unwrap();
|
||||
assert_eq!(harness.service.pending.read().len(), 1);
|
||||
|
||||
for backoff in &binary_exp_backoff {
|
||||
harness.service.dispatch_pending(&Context::FaultyRequest);
|
||||
assert_eq!(harness.service.pending.read().len(), 1, "Request should not be dropped");
|
||||
let now = Instant::now();
|
||||
while now.elapsed() < Duration::from_secs(*backoff) {}
|
||||
}
|
||||
|
||||
harness.service.dispatch_pending(&Context::FaultyRequest);
|
||||
assert_eq!(harness.service.pending.read().len(), 0, "Request exceeded the 10 backoff rounds should be dropped");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_responses_exceeds_limit_should_be_dropped() {
|
||||
let harness = Harness::create();
|
||||
let peer_id = 0;
|
||||
let req_id = ReqId(13);
|
||||
|
||||
harness.inject_peer(
|
||||
peer_id,
|
||||
Peer {
|
||||
status: dummy_status(),
|
||||
capabilities: dummy_capabilities(),
|
||||
}
|
||||
);
|
||||
|
||||
let _recv = harness.service.request_raw(
|
||||
&Context::RequestFrom(peer_id, req_id),
|
||||
vec![request::HeaderByHash(Header::default().encoded().hash().into()).into()],
|
||||
).unwrap();
|
||||
|
||||
harness.service.dispatch_pending(&Context::RequestFrom(peer_id, req_id));
|
||||
|
||||
assert_eq!(harness.service.pending.read().len(), 0);
|
||||
assert_eq!(harness.service.in_transit.read().len(), 1);
|
||||
|
||||
let now = Instant::now();
|
||||
|
||||
// Send `empty responses` in the current time window
|
||||
// Use only half of the `time_window` because we can't be sure exactly
|
||||
// when the window started and the clock accurancy
|
||||
while now.elapsed() < harness.service.response_time_window / 2 {
|
||||
harness.service.on_responses(
|
||||
&Context::RequestFrom(13, req_id),
|
||||
req_id,
|
||||
&[]
|
||||
);
|
||||
assert!(harness.service.pending.read().len() != 0);
|
||||
let pending = harness.service.pending.write().remove(0);
|
||||
harness.service.in_transit.write().insert(req_id, pending);
|
||||
}
|
||||
|
||||
// Make sure we passed the first `time window`
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
|
||||
// Now, response is in failure state but need another response to be `polled`
|
||||
harness.service.on_responses(
|
||||
&Context::RequestFrom(13, req_id),
|
||||
req_id,
|
||||
&[]
|
||||
);
|
||||
|
||||
assert!(harness.service.in_transit.read().is_empty());
|
||||
assert!(harness.service.pending.read().is_empty());
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! A provider for the PIP protocol. This is typically a full node, who can
|
||||
//! give as much data as necessary to its peers.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_types::blockchain_info::BlockChainInfo;
|
||||
use common_types::encoded;
|
||||
use common_types::ids::BlockId;
|
||||
use common_types::transaction::PendingTransaction;
|
||||
use ethcore::blockchain_info::BlockChainInfo;
|
||||
use ethcore::client::{BlockChainClient, ProvingBlockChainClient, ChainInfo, BlockInfo as ClientBlockInfo};
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::encoded;
|
||||
use ethereum_types::H256;
|
||||
use parking_lot::RwLock;
|
||||
use transaction::PendingTransaction;
|
||||
|
||||
use cht::{self, BlockInfo};
|
||||
use client::{LightChainClient, AsLightClient};
|
||||
@@ -161,7 +161,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
||||
fn transaction_index(&self, req: request::CompleteTransactionIndexRequest)
|
||||
-> Option<request::TransactionIndexResponse>
|
||||
{
|
||||
use common_types::ids::TransactionId;
|
||||
use ethcore::ids::TransactionId;
|
||||
|
||||
self.transaction_receipt(TransactionId::Hash(req.hash)).map(|receipt| request::TransactionIndexResponse {
|
||||
num: receipt.block_number,
|
||||
@@ -265,7 +265,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
||||
}
|
||||
|
||||
fn transaction_proof(&self, req: request::CompleteExecutionRequest) -> Option<request::ExecutionResponse> {
|
||||
use common_types::transaction::Transaction;
|
||||
use transaction::Transaction;
|
||||
|
||||
let id = BlockId::Hash(req.block_hash);
|
||||
let nonce = match self.nonce(&req.from, id) {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Light Transaction Queue.
|
||||
//!
|
||||
@@ -24,15 +24,12 @@
|
||||
//! address-wise manner.
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use common_types::transaction::{self, Condition, PendingTransaction, SignedTransaction};
|
||||
use transaction::{self, Condition, PendingTransaction, SignedTransaction};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use fastmap::H256FastMap;
|
||||
use futures::sync::mpsc;
|
||||
use miner::pool::TxStatus;
|
||||
|
||||
// Knowledge of an account's current nonce.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -98,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())
|
||||
}
|
||||
|
||||
@@ -110,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
|
||||
@@ -129,13 +126,14 @@ pub enum ImportDestination {
|
||||
Future,
|
||||
}
|
||||
|
||||
type Listener = Box<Fn(&[H256]) + Send + Sync>;
|
||||
|
||||
/// Light transaction queue. See module docs for more details.
|
||||
#[derive(Default)]
|
||||
pub struct TransactionQueue {
|
||||
by_account: HashMap<Address, AccountTransactions>,
|
||||
by_hash: H256FastMap<PendingTransaction>,
|
||||
pending_listeners: Vec<mpsc::UnboundedSender<Arc<Vec<H256>>>>,
|
||||
full_listeners: Vec<mpsc::UnboundedSender<Arc<Vec<(H256, TxStatus)>>>>,
|
||||
listeners: Vec<Listener>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for TransactionQueue {
|
||||
@@ -143,8 +141,7 @@ impl fmt::Debug for TransactionQueue {
|
||||
fmt.debug_struct("TransactionQueue")
|
||||
.field("by_account", &self.by_account)
|
||||
.field("by_hash", &self.by_hash)
|
||||
.field("pending_listeners", &self.pending_listeners.len())
|
||||
.field("full_listeners", &self.pending_listeners.len())
|
||||
.field("listeners", &self.listeners.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
@@ -234,7 +231,7 @@ impl TransactionQueue {
|
||||
};
|
||||
|
||||
self.by_hash.insert(hash, tx);
|
||||
self.notify(&promoted, TxStatus::Added);
|
||||
self.notify(&promoted);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -346,8 +343,6 @@ impl TransactionQueue {
|
||||
trace!(target: "txqueue", "Culled {} old transactions from sender {} (nonce={})",
|
||||
removed_hashes.len(), address, cur_nonce);
|
||||
|
||||
self.notify(&removed_hashes, TxStatus::Culled);
|
||||
|
||||
for hash in removed_hashes {
|
||||
self.by_hash.remove(&hash);
|
||||
}
|
||||
@@ -359,40 +354,15 @@ impl TransactionQueue {
|
||||
}
|
||||
|
||||
/// Add a transaction queue listener.
|
||||
pub fn pending_transactions_receiver(&mut self) -> mpsc::UnboundedReceiver<Arc<Vec<H256>>> {
|
||||
let (sender, receiver) = mpsc::unbounded();
|
||||
self.pending_listeners.push(sender);
|
||||
receiver
|
||||
}
|
||||
|
||||
/// Add a transaction queue listener.
|
||||
pub fn full_transactions_receiver(&mut self) -> mpsc::UnboundedReceiver<Arc<Vec<(H256, TxStatus)>>> {
|
||||
let (sender, receiver) = mpsc::unbounded();
|
||||
self.full_listeners.push(sender);
|
||||
receiver
|
||||
pub fn add_listener(&mut self, f: Listener) {
|
||||
self.listeners.push(f);
|
||||
}
|
||||
|
||||
/// Notifies all listeners about new pending transaction.
|
||||
fn notify(&mut self, hashes: &[H256], status: TxStatus) {
|
||||
if status == TxStatus::Added {
|
||||
let to_pending_send: Arc<Vec<H256>> = Arc::new(
|
||||
hashes
|
||||
.into_iter()
|
||||
.map(|hash| hash.clone())
|
||||
.collect()
|
||||
);
|
||||
self.pending_listeners.retain(|listener| listener.unbounded_send(to_pending_send.clone()).is_ok());
|
||||
|
||||
fn notify(&self, hashes: &[H256]) {
|
||||
for listener in &self.listeners {
|
||||
listener(hashes)
|
||||
}
|
||||
|
||||
let to_full_send: Arc<Vec<(H256, TxStatus)>> = Arc::new(
|
||||
hashes
|
||||
.into_iter()
|
||||
.map(|hash| (hash.clone(), status))
|
||||
.collect()
|
||||
);
|
||||
|
||||
self.full_listeners.retain(|listener| listener.unbounded_send(to_full_send.clone()).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,11 +370,11 @@ impl TransactionQueue {
|
||||
mod tests {
|
||||
use super::TransactionQueue;
|
||||
use ethereum_types::Address;
|
||||
use common_types::transaction::{Transaction, PendingTransaction, Condition};
|
||||
use transaction::{Transaction, PendingTransaction, Condition};
|
||||
|
||||
#[test]
|
||||
fn queued_senders() {
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
let mut txq = TransactionQueue::default();
|
||||
let tx = Transaction::default().fake_sign(sender);
|
||||
|
||||
@@ -420,7 +390,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn next_nonce() {
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
let mut txq = TransactionQueue::default();
|
||||
|
||||
for i in (0..5).chain(10..15) {
|
||||
@@ -451,7 +421,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn current_to_future() {
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
let mut txq = TransactionQueue::default();
|
||||
|
||||
for i in 5..10 {
|
||||
@@ -494,7 +464,7 @@ mod tests {
|
||||
#[test]
|
||||
fn conditional() {
|
||||
let mut txq = TransactionQueue::default();
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
|
||||
for i in 0..5 {
|
||||
let mut tx = Transaction::default();
|
||||
@@ -516,7 +486,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn cull_from_future() {
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
let mut txq = TransactionQueue::default();
|
||||
|
||||
for i in (0..1).chain(3..10) {
|
||||
@@ -536,7 +506,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn import_old() {
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
let mut txq = TransactionQueue::default();
|
||||
|
||||
let mut tx_a = Transaction::default();
|
||||
@@ -553,7 +523,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn replace_is_removed() {
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
let mut txq = TransactionQueue::default();
|
||||
|
||||
let tx_b: PendingTransaction = Transaction::default().fake_sign(sender).into();
|
||||
@@ -573,7 +543,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn future_transactions() {
|
||||
let sender = Address::zero();
|
||||
let sender = Address::default();
|
||||
let mut txq = TransactionQueue::default();
|
||||
|
||||
for i in (0..1).chain(3..10) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod request;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Request chain builder utility.
|
||||
//! Push requests with `push`. Back-references and data required to verify responses must be
|
||||
@@ -220,7 +220,7 @@ mod tests {
|
||||
num: 100.into(),
|
||||
})).unwrap();
|
||||
builder.push(Request::Receipts(IncompleteReceiptsRequest {
|
||||
hash: H256::zero().into(),
|
||||
hash: H256::default().into(),
|
||||
})).unwrap();
|
||||
}
|
||||
|
||||
@@ -255,63 +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(H256::from_low_u64_be(42))));
|
||||
|
||||
assert!(batch.next_complete().is_some());
|
||||
batch.answered += 1;
|
||||
assert!(batch.next_complete().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn batch_tx_index_backreference_public_api() {
|
||||
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();
|
||||
|
||||
assert!(batch.next_complete().is_some());
|
||||
let hdr_proof_res = header_proof::Response {
|
||||
proof: vec![],
|
||||
hash: H256::from_low_u64_be(12),
|
||||
td: 21.into(),
|
||||
};
|
||||
batch.supply_response_unchecked(&hdr_proof_res);
|
||||
|
||||
assert!(batch.next_complete().is_some());
|
||||
}
|
||||
|
||||
#[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(H256::from_low_u64_be(42))));
|
||||
|
||||
assert!(batch.next_complete().is_some());
|
||||
batch.answered += 1;
|
||||
assert!(batch.next_complete().is_some());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Light protocol request types.
|
||||
|
||||
@@ -670,7 +670,7 @@ pub trait ResponseLike {
|
||||
/// Header request.
|
||||
pub mod header {
|
||||
use super::{Field, HashOrNumber, NoSuchOutput, OutputKind, Output};
|
||||
use common_types::encoded;
|
||||
use ethcore::encoded;
|
||||
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
|
||||
|
||||
/// Potentially incomplete headers request.
|
||||
@@ -753,7 +753,7 @@ pub mod header {
|
||||
|
||||
impl Decodable for Response {
|
||||
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
|
||||
use common_types::header::Header as FullHeader;
|
||||
use ethcore::header::Header as FullHeader;
|
||||
|
||||
let mut headers = Vec::new();
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
@@ -954,7 +954,7 @@ pub mod transaction_index {
|
||||
/// Request and response for block receipts
|
||||
pub mod block_receipts {
|
||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||
use common_types::receipt::Receipt;
|
||||
use ethcore::receipt::Receipt;
|
||||
use ethereum_types::H256;
|
||||
|
||||
/// Potentially incomplete block receipts request.
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
@@ -1022,7 +1022,7 @@ pub mod block_receipts {
|
||||
/// Request and response for a block body
|
||||
pub mod block_body {
|
||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||
use common_types::encoded;
|
||||
use ethcore::encoded;
|
||||
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
|
||||
use ethereum_types::H256;
|
||||
|
||||
@@ -1089,8 +1089,8 @@ pub mod block_body {
|
||||
|
||||
impl Decodable for Response {
|
||||
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
|
||||
use common_types::header::Header as FullHeader;
|
||||
use common_types::transaction::UnverifiedTransaction;
|
||||
use ethcore::header::Header as FullHeader;
|
||||
use transaction::UnverifiedTransaction;
|
||||
|
||||
// check body validity.
|
||||
let _: Vec<UnverifiedTransaction> = rlp.list_at(0)?;
|
||||
@@ -1406,7 +1406,7 @@ pub mod contract_code {
|
||||
/// A request for proof of execution.
|
||||
pub mod execution {
|
||||
use super::{Field, NoSuchOutput, OutputKind, Output};
|
||||
use common_types::transaction::Action;
|
||||
use transaction::Action;
|
||||
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use kvdb::DBValue;
|
||||
@@ -1629,7 +1629,7 @@ pub mod epoch_signal {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use common_types::header::Header;
|
||||
use ethcore::header::Header;
|
||||
|
||||
fn check_roundtrip<T>(val: T)
|
||||
where T: ::rlp::Encodable + ::rlp::Decodable + PartialEq + ::std::fmt::Debug
|
||||
@@ -1648,7 +1648,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn hash_or_number_roundtrip() {
|
||||
let hash = HashOrNumber::Hash(H256::zero());
|
||||
let hash = HashOrNumber::Hash(H256::default());
|
||||
let number = HashOrNumber::Number(5);
|
||||
|
||||
check_roundtrip(hash);
|
||||
@@ -1676,7 +1676,7 @@ mod tests {
|
||||
let full_req = Request::Headers(req.clone());
|
||||
let res = HeadersResponse {
|
||||
headers: vec![
|
||||
::common_types::encoded::Header::new(::rlp::encode(&Header::default()))
|
||||
::ethcore::encoded::Header::new(::rlp::encode(&Header::default()))
|
||||
]
|
||||
};
|
||||
let full_res = Response::Headers(res.clone());
|
||||
@@ -1729,7 +1729,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn receipts_roundtrip() {
|
||||
use common_types::receipt::{Receipt, TransactionOutcome};
|
||||
use ethcore::receipt::{Receipt, TransactionOutcome};
|
||||
let req = IncompleteReceiptsRequest {
|
||||
hash: Field::Scalar(Default::default()),
|
||||
};
|
||||
@@ -1749,7 +1749,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn body_roundtrip() {
|
||||
use common_types::transaction::{Transaction, UnverifiedTransaction};
|
||||
use transaction::{Transaction, UnverifiedTransaction};
|
||||
let req = IncompleteBodyRequest {
|
||||
hash: Field::Scalar(Default::default()),
|
||||
};
|
||||
@@ -1757,13 +1757,13 @@ mod tests {
|
||||
let full_req = Request::Body(req.clone());
|
||||
let res = BodyResponse {
|
||||
body: {
|
||||
let header = ::common_types::header::Header::default();
|
||||
let header = ::ethcore::header::Header::default();
|
||||
let tx = UnverifiedTransaction::from(Transaction::default().fake_sign(Default::default()));
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.begin_list(2).append(&tx).append(&tx)
|
||||
.begin_list(1).append(&header);
|
||||
|
||||
::common_types::encoded::Body::new(stream.out())
|
||||
::ethcore::encoded::Body::new(stream.out())
|
||||
},
|
||||
};
|
||||
let full_res = Response::Body(res.clone());
|
||||
@@ -1808,7 +1808,7 @@ mod tests {
|
||||
let full_req = Request::Storage(req.clone());
|
||||
let res = StorageResponse {
|
||||
proof: vec![vec![1, 2, 3], vec![4, 5, 6]],
|
||||
value: H256::zero(),
|
||||
value: H256::default(),
|
||||
};
|
||||
let full_res = Response::Storage(res.clone());
|
||||
|
||||
@@ -1844,7 +1844,7 @@ mod tests {
|
||||
let req = IncompleteExecutionRequest {
|
||||
block_hash: Field::Scalar(Default::default()),
|
||||
from: Default::default(),
|
||||
action: ::common_types::transaction::Action::Create,
|
||||
action: ::transaction::Action::Create,
|
||||
gas: 100_000.into(),
|
||||
gas_price: 0.into(),
|
||||
value: 100_000_001.into(),
|
||||
@@ -1874,7 +1874,7 @@ mod tests {
|
||||
let reqs: Vec<_> = (0..10).map(|_| IncompleteExecutionRequest {
|
||||
block_hash: Field::Scalar(Default::default()),
|
||||
from: Default::default(),
|
||||
action: ::common_types::transaction::Action::Create,
|
||||
action: ::transaction::Action::Create,
|
||||
gas: 100_000.into(),
|
||||
gas_price: 0.into(),
|
||||
value: 100_000_001.into(),
|
||||
@@ -1892,11 +1892,11 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn responses_vec() {
|
||||
use common_types::receipt::{Receipt, TransactionOutcome};
|
||||
use ethcore::receipt::{Receipt, TransactionOutcome};
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.begin_list(0).begin_list(0);
|
||||
|
||||
let body = ::common_types::encoded::Body::new(stream.out());
|
||||
let body = ::ethcore::encoded::Body::new(stream.out());
|
||||
let reqs = vec![
|
||||
Response::Headers(HeadersResponse { headers: vec![] }),
|
||||
Response::HeaderProof(HeaderProofResponse { proof: vec![], hash: Default::default(), td: 100.into()}),
|
||||
@@ -1909,7 +1909,7 @@ mod tests {
|
||||
code_hash: Default::default(),
|
||||
storage_root: Default::default()
|
||||
}),
|
||||
Response::Storage(StorageResponse { proof: vec![], value: H256::zero() }),
|
||||
Response::Storage(StorageResponse { proof: vec![], value: H256::default() }),
|
||||
Response::Code(CodeResponse { code: vec![1, 2, 3, 4, 5] }),
|
||||
Response::Execution(ExecutionResponse { items: vec![] }),
|
||||
];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
description = "Parity Smart Contract based Node Filter, Manage Permissions of Network Connections"
|
||||
description = "Parity smart network connections"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "node-filter"
|
||||
@@ -10,12 +10,12 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
ethcore = { path = ".."}
|
||||
ethcore-network = { path = "../../util/network" }
|
||||
ethcore-network-devp2p = { path = "../../util/network-devp2p" }
|
||||
ethereum-types = "0.6.0"
|
||||
ethereum-types = "0.4"
|
||||
log = "0.4"
|
||||
parking_lot = "0.7"
|
||||
ethabi = "8.0"
|
||||
ethabi-derive = "8.0"
|
||||
ethabi-contract = "8.0"
|
||||
parking_lot = "0.6"
|
||||
ethabi = "6.0"
|
||||
ethabi-derive = "6.0"
|
||||
ethabi-contract = "6.0"
|
||||
lru-cache = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Smart contract based node filter.
|
||||
|
||||
@@ -37,45 +37,35 @@ extern crate tempdir;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::sync::Weak;
|
||||
|
||||
use ethcore::client::{BlockChainClient, BlockId, ChainNotify, NewBlocks};
|
||||
use lru_cache::LruCache;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use ethcore::client::{BlockChainClient, BlockId};
|
||||
use ethereum_types::{H256, Address};
|
||||
use ethabi::FunctionOutputDecoder;
|
||||
use network::{ConnectionFilter, ConnectionDirection};
|
||||
use devp2p::NodeId;
|
||||
use devp2p::MAX_NODES_IN_TABLE;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use_contract!(peer_set, "res/peer_set.json");
|
||||
|
||||
const MAX_CACHE_SIZE: usize = 4096;
|
||||
|
||||
/// Connection filter that uses a contract to manage permissions.
|
||||
pub struct NodeFilter {
|
||||
client: Weak<BlockChainClient>,
|
||||
contract_address: Address,
|
||||
cache: RwLock<Cache>
|
||||
permission_cache: Mutex<LruCache<(H256, NodeId), bool>>,
|
||||
}
|
||||
|
||||
struct Cache {
|
||||
cache: HashMap<NodeId, bool>,
|
||||
order: VecDeque<NodeId>
|
||||
}
|
||||
|
||||
// Increase cache size due to possible reserved peers, which do not count in the node table size
|
||||
pub const CACHE_SIZE: usize = MAX_NODES_IN_TABLE + 1024;
|
||||
|
||||
impl NodeFilter {
|
||||
/// Create a new instance. Accepts a contract address.
|
||||
pub fn new(client: Weak<BlockChainClient>, contract_address: Address) -> NodeFilter {
|
||||
NodeFilter {
|
||||
client,
|
||||
contract_address,
|
||||
cache: RwLock::new(Cache{
|
||||
cache: HashMap::with_capacity(CACHE_SIZE),
|
||||
order: VecDeque::with_capacity(CACHE_SIZE)
|
||||
})
|
||||
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,8 +77,16 @@ impl ConnectionFilter for NodeFilter {
|
||||
None => return false,
|
||||
};
|
||||
|
||||
if let Some(allowed) = self.cache.read().cache.get(connecting_id) {
|
||||
return *allowed;
|
||||
let block_hash = match client.block_hash(BlockId::Latest) {
|
||||
Some(block_hash) => block_hash,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let key = (block_hash, *connecting_id);
|
||||
|
||||
let mut cache = self.permission_cache.lock();
|
||||
if let Some(res) = cache.get_mut(&key) {
|
||||
return *res;
|
||||
}
|
||||
|
||||
let address = self.contract_address;
|
||||
@@ -104,23 +102,9 @@ impl ConnectionFilter for NodeFilter {
|
||||
debug!("Error callling peer set contract: {:?}", e);
|
||||
false
|
||||
});
|
||||
let mut cache = self.cache.write();
|
||||
if cache.cache.len() == CACHE_SIZE {
|
||||
let popped = cache.order.pop_front().expect("the cache is full so there's at least one item we can pop; qed");
|
||||
cache.cache.remove(&popped);
|
||||
};
|
||||
if cache.cache.insert(*connecting_id, allowed).is_none() {
|
||||
cache.order.push_back(*connecting_id);
|
||||
}
|
||||
allowed
|
||||
}
|
||||
}
|
||||
|
||||
impl ChainNotify for NodeFilter {
|
||||
fn new_blocks(&self, _new_blocks: NewBlocks) {
|
||||
let mut cache = self.cache.write();
|
||||
cache.cache.clear();
|
||||
cache.order.clear();
|
||||
cache.insert(key, allowed);
|
||||
allowed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,13 +119,11 @@ mod test {
|
||||
use io::IoChannel;
|
||||
use super::NodeFilter;
|
||||
use tempdir::TempDir;
|
||||
use ethereum_types::Address;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// Contract code: https://gist.github.com/arkpar/467dbcc73cbb85b0997a7a10ffa0695f
|
||||
#[test]
|
||||
fn node_filter() {
|
||||
let contract_addr = Address::from_str("0000000000000000000000000000000000000005").unwrap();
|
||||
let contract_addr = "0000000000000000000000000000000000000005".into();
|
||||
let data = include_bytes!("../res/node_filter.json");
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let spec = Spec::load(&tempdir.path(), &data[..]).unwrap();
|
||||
@@ -155,11 +137,11 @@ mod test {
|
||||
IoChannel::disconnected(),
|
||||
).unwrap();
|
||||
let filter = NodeFilter::new(Arc::downgrade(&client) as Weak<BlockChainClient>, contract_addr);
|
||||
let self1 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002").unwrap();
|
||||
let self2 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003").unwrap();
|
||||
let node1 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012").unwrap();
|
||||
let node2 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000022").unwrap();
|
||||
let nodex = NodeId::from_str("77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
|
||||
let self1: NodeId = "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002".into();
|
||||
let self2: NodeId = "00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003".into();
|
||||
let node1: NodeId = "00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012".into();
|
||||
let node2: NodeId = "00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000022".into();
|
||||
let nodex: NodeId = "77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
|
||||
|
||||
assert!(filter.connection_allowed(&self1, &node1, ConnectionDirection::Inbound));
|
||||
assert!(filter.connection_allowed(&self1, &nodex, ConnectionDirection::Inbound));
|
||||
@@ -1,27 +0,0 @@
|
||||
[package]
|
||||
description = "Account system expressed in Plain Old Data."
|
||||
name = "pod-account"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
common-types = { path = "../types" }
|
||||
ethereum-types = "0.6"
|
||||
ethjson = { path = "../../json" }
|
||||
ethtrie = { package = "patricia-trie-ethereum", path = "../../util/patricia-trie-ethereum" }
|
||||
hash-db = "0.12"
|
||||
itertools = "0.8"
|
||||
keccak-hash = "0.2.0"
|
||||
keccak-hasher = { path = "../../util/keccak-hasher" }
|
||||
kvdb = "0.1"
|
||||
log = "0.4"
|
||||
parity-bytes = "0.1.0"
|
||||
rlp = "0.4"
|
||||
rustc-hex = "1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
trie-db = "0.12.4"
|
||||
triehash = { package = "triehash-ethereum", version = "0.2", path = "../../util/triehash-ethereum" }
|
||||
|
||||
[dev-dependencies]
|
||||
macros = { path = "../../util/macros" }
|
||||
@@ -6,40 +6,38 @@ license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
common-types = { path = "../types" }
|
||||
derive_more = "0.14.0"
|
||||
ethabi = "8.0"
|
||||
ethabi-contract = "8.0"
|
||||
ethabi-derive = "8.0"
|
||||
error-chain = { version = "0.12", default-features = false }
|
||||
ethabi = "6.0"
|
||||
ethabi-derive = "6.0"
|
||||
ethabi-contract = "6.0"
|
||||
ethcore = { path = ".." }
|
||||
ethcore-call-contract = { path = "../call-contract" }
|
||||
parity-bytes = "0.1"
|
||||
parity-crypto = "0.2"
|
||||
ethcore-io = { path = "../../util/io" }
|
||||
ethcore-logger = { path = "../../logger" }
|
||||
ethcore-miner = { path = "../../miner" }
|
||||
ethereum-types = "0.6.0"
|
||||
ethcore-transaction = { path = "../transaction" }
|
||||
ethereum-types = "0.4"
|
||||
ethjson = { path = "../../json" }
|
||||
ethkey = { path = "../../accounts/ethkey" }
|
||||
ethkey = { path = "../../ethkey" }
|
||||
fetch = { path = "../../util/fetch" }
|
||||
futures = "0.1"
|
||||
parity-util-mem = "0.1"
|
||||
keccak-hash = "0.2.0"
|
||||
heapsize = "0.4"
|
||||
keccak-hash = "0.1.2"
|
||||
log = "0.4"
|
||||
parity-bytes = "0.1"
|
||||
parity-crypto = "0.4.0"
|
||||
parking_lot = "0.7"
|
||||
trie-db = "0.12.4"
|
||||
parking_lot = "0.6"
|
||||
patricia-trie = "0.3.0"
|
||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
||||
rand = "0.3"
|
||||
rlp = "0.4.0"
|
||||
rlp_derive = { path = "../../util/rlp-derive" }
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rlp_derive = { path = "../../util/rlp_derive" }
|
||||
rustc-hex = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
time-utils = { path = "../../util/time-utils" }
|
||||
tiny-keccak = "1.4"
|
||||
transaction-pool = "2.0"
|
||||
transaction-pool = "1.13.2"
|
||||
url = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.5"
|
||||
ethcore = { path = "..", features = ["test-helpers"] }
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
@@ -1,171 +1 @@
|
||||
[
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getVersion",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newState",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8[]"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32[]"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "setState",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "code",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "validators",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "changesOriginator",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "originalTransactionHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "notifyChanges",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "nonce",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getValidators",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "state",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"name": "initialValidators",
|
||||
"type": "address[]"
|
||||
},
|
||||
{
|
||||
"name": "initialCode",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "initialState",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "changesOriginator",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "originalTransactionHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "PrivateStateChanged",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
||||
[{"constant": false,"inputs": [{"name": "newState","type": "bytes"},{"name": "v","type": "uint8[]"},{"name": "r","type": "bytes32[]"},{"name": "s","type": "bytes32[]"}],"name": "setState","outputs": [],"payable": false,"stateMutability": "nonpayable","type": "function"},{"constant": true,"inputs": [],"name": "code","outputs": [{"name": "","type": "bytes"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [{"name": "","type": "uint256"}],"name": "validators","outputs": [{"name": "","type": "address"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "nonce","outputs": [{"name": "","type": "uint256"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "getValidators","outputs": [{"name": "","type": "address[]"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "state","outputs": [{"name": "","type": "bytes"}],"payable": false,"stateMutability": "view","type": "function"},{"inputs": [{"name": "initialValidators","type": "address[]"},{"name": "initialCode","type": "bytes"},{"name": "initialState","type": "bytes"}],"payable": false,"stateMutability": "nonpayable","type": "constructor"}]
|
||||
|
||||
@@ -1,40 +1,39 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Encryption providers.
|
||||
|
||||
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;
|
||||
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,11 +56,12 @@ pub trait Encryptor: Send + Sync + 'static {
|
||||
fn decrypt(
|
||||
&self,
|
||||
contract_address: &Address,
|
||||
accounts: &AccountProvider,
|
||||
cypher: &[u8],
|
||||
) -> Result<Bytes, Error>;
|
||||
}
|
||||
|
||||
/// Configuration for key server encryptor
|
||||
/// Configurtion for key server encryptor
|
||||
#[derive(Default, PartialEq, Debug, Clone)]
|
||||
pub struct EncryptorConfig {
|
||||
/// URL to key server
|
||||
@@ -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,17 +102,18 @@ 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 requester = self.config.key_server_account.ok_or_else(|| Error::KeyServerAccountNotSet)?;
|
||||
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
|
||||
let contract_address_extended: H256 = (*contract_address).into();
|
||||
let base_url = self.config.base_url.clone().ok_or_else(|| Error::KeyServerNotSet)?;
|
||||
let contract_address_extended: H256 = contract_address.into();
|
||||
let base_url = self.config.base_url.clone().ok_or_else(|| ErrorKind::KeyServerNotSet)?;
|
||||
|
||||
// prepare request url
|
||||
let url = format!("{}/{}/{}{}",
|
||||
@@ -132,16 +130,16 @@ impl SecretStoreEncryptor {
|
||||
Method::GET
|
||||
};
|
||||
|
||||
let url = Url::from_str(&url).map_err(|e| Error::Encrypt(e.to_string()))?;
|
||||
let url = Url::from_str(&url).map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
|
||||
let response = self.client.fetch(Request::new(url, method), Default::default()).wait()
|
||||
.map_err(|e| Error::Encrypt(e.to_string()))?;
|
||||
.map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
|
||||
|
||||
if response.is_not_found() {
|
||||
return Err(Error::EncryptionKeyNotFound(*contract_address));
|
||||
bail!(ErrorKind::EncryptionKeyNotFound(*contract_address));
|
||||
}
|
||||
|
||||
if !response.is_success() {
|
||||
return Err(Error::Encrypt(response.status().canonical_reason().unwrap_or("unknown").into()));
|
||||
bail!(ErrorKind::Encrypt(response.status().canonical_reason().unwrap_or("unknown").into()));
|
||||
}
|
||||
|
||||
// read HTTP response
|
||||
@@ -149,14 +147,15 @@ impl SecretStoreEncryptor {
|
||||
BodyReader::new(response).read_to_string(&mut result)?;
|
||||
|
||||
// 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| Error::Encrypt(e))?;
|
||||
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
|
||||
let key: Bytes = decrypted_key.as_bytes()[..INIT_VEC_LEN].into();
|
||||
let key: Bytes = (*decrypted_key)[..INIT_VEC_LEN].into();
|
||||
|
||||
// cache the key in the session and clear expired sessions
|
||||
self.sessions.lock().insert(*contract_address, EncryptionSession{
|
||||
@@ -188,9 +187,12 @@ impl SecretStoreEncryptor {
|
||||
}
|
||||
}
|
||||
|
||||
fn sign_contract_address(&self, contract_address: &Address) -> Result<Signature, Error> {
|
||||
let key_server_account = self.config.key_server_account.ok_or_else(|| Error::KeyServerAccountNotSet)?;
|
||||
Ok(self.signer.sign(key_server_account, address_to_key(contract_address))?)
|
||||
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)?;
|
||||
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,25 +200,26 @@ 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::EncryptionKeyNotFound(_)) => {
|
||||
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),
|
||||
}?;
|
||||
|
||||
// encrypt data
|
||||
let mut cypher = Vec::with_capacity(plain_data.len() + initialisation_vector.as_bytes().len());
|
||||
let mut cypher = Vec::with_capacity(plain_data.len() + initialisation_vector.len());
|
||||
cypher.extend(repeat(0).take(plain_data.len()));
|
||||
crypto::aes::encrypt_128_ctr(&key, initialisation_vector.as_bytes(), plain_data, &mut cypher)
|
||||
.map_err(|e| Error::Encrypt(e.to_string()))?;
|
||||
cypher.extend_from_slice(&initialisation_vector.as_bytes());
|
||||
crypto::aes::encrypt_128_ctr(&key, initialisation_vector, plain_data, &mut cypher)
|
||||
.map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
|
||||
cypher.extend_from_slice(&initialisation_vector);
|
||||
|
||||
Ok(cypher)
|
||||
}
|
||||
@@ -225,23 +228,24 @@ impl Encryptor for SecretStoreEncryptor {
|
||||
fn decrypt(
|
||||
&self,
|
||||
contract_address: &Address,
|
||||
accounts: &AccountProvider,
|
||||
cypher: &[u8],
|
||||
) -> Result<Bytes, Error> {
|
||||
// initialization vector takes INIT_VEC_LEN bytes
|
||||
let cypher_len = cypher.len();
|
||||
if cypher_len < INIT_VEC_LEN {
|
||||
return Err(Error::Decrypt("Invalid cypher".into()));
|
||||
bail!(ErrorKind::Decrypt("Invalid cypher".into()));
|
||||
}
|
||||
|
||||
// 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);
|
||||
let mut plain_data = Vec::with_capacity(cypher_len - INIT_VEC_LEN);
|
||||
plain_data.extend(repeat(0).take(cypher_len - INIT_VEC_LEN));
|
||||
crypto::aes::decrypt_128_ctr(&key, &iv, cypher, &mut plain_data)
|
||||
.map_err(|e| Error::Decrypt(e.to_string()))?;
|
||||
.map_err(|e| ErrorKind::Decrypt(e.to_string()))?;
|
||||
Ok(plain_data)
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
|
||||
@@ -1,215 +1,204 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::error;
|
||||
use derive_more::Display;
|
||||
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 transaction::Error as TransactionError;
|
||||
use ethkey::Error as KeyError;
|
||||
use ethkey::crypto::Error as CryptoError;
|
||||
use txpool::VerifiedTransaction;
|
||||
use private_transactions::VerifiedPrivateTransaction;
|
||||
use serde_json::{Error as SerdeError};
|
||||
use txpool::Error as TxPoolError;
|
||||
|
||||
type TxPoolError = txpool::Error<<VerifiedPrivateTransaction as VerifiedTransaction>::Hash>;
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
Io(::std::io::Error) #[doc = "Error concerning the Rust standard library's IO subsystem."];
|
||||
Decoder(DecoderError) #[doc = "RLP decoding error."];
|
||||
Trie(TrieError) #[doc = "Error concerning TrieDBs."];
|
||||
Txpool(TxPoolError) #[doc = "Tx pool error."];
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
pub enum Error {
|
||||
/// Error concerning the Rust standard library's IO subsystem.
|
||||
#[display(fmt = "Io Error: {}", _0)]
|
||||
Io(::std::io::Error),
|
||||
/// RLP decoding error.
|
||||
#[display(fmt = "Decoder Error: {}", _0)]
|
||||
Decoder(DecoderError),
|
||||
/// Error concerning TrieDBs.
|
||||
#[display(fmt = "Trie Error: {}", _0)]
|
||||
Trie(TrieError),
|
||||
/// Transaction pool error.
|
||||
#[display(fmt = "Transaction Pool Error: {}", _0)]
|
||||
TxPool(TxPoolError),
|
||||
/// Crypto error.
|
||||
#[display(fmt = "Crypto Error {}", _0)]
|
||||
Crypto(CryptoError),
|
||||
/// Serialization error.
|
||||
#[display(fmt = "Serialization Error {}", _0)]
|
||||
Json(SerdeError),
|
||||
/// Encryption error.
|
||||
#[display(fmt = "Encryption error. ({})", _0)]
|
||||
Encrypt(String),
|
||||
/// Decryption error.
|
||||
#[display(fmt = "Decryption error. ({})", _0)]
|
||||
Decrypt(String),
|
||||
/// Address not authorized.
|
||||
#[display(fmt = "Private transaction execution is not authorised for {}", _0)]
|
||||
NotAuthorised(Address),
|
||||
/// Transaction creates more than one contract.
|
||||
#[display(fmt = "Private transaction created too many contracts")]
|
||||
TooManyContracts,
|
||||
/// Contract call error.
|
||||
#[display(fmt = "Contract call error. ({})", _0)]
|
||||
Call(String),
|
||||
/// State is not available.
|
||||
#[display(fmt = "State is not available")]
|
||||
StatePruned,
|
||||
/// State is incorrect.
|
||||
#[display(fmt = "State is incorrect")]
|
||||
StateIncorrect,
|
||||
/// Wrong private transaction type.
|
||||
#[display(fmt = "Wrong private transaction type")]
|
||||
BadTransactionType,
|
||||
/// Contract does not exist or was not created.
|
||||
#[display(fmt = "Contract does not exist or was not created")]
|
||||
ContractDoesNotExist,
|
||||
/// Reference to the client is corrupted.
|
||||
#[display(fmt = "Reference to the client is corrupted")]
|
||||
ClientIsMalformed,
|
||||
/// Queue of private transactions for verification is full.
|
||||
#[display(fmt = "Queue of private transactions for verification is full")]
|
||||
QueueIsFull,
|
||||
/// The transaction already exists in queue of private transactions.
|
||||
#[display(fmt = "The transaction already exists in queue of private transactions.")]
|
||||
PrivateTransactionAlreadyImported,
|
||||
/// The information about private transaction is not found in the store.
|
||||
#[display(fmt = "The information about private transaction is not found in the store.")]
|
||||
PrivateTransactionNotFound,
|
||||
/// Account for signing public transactions not set.
|
||||
#[display(fmt = "Account for signing public transactions not set.")]
|
||||
SignerAccountNotSet,
|
||||
/// Account for validating private transactions not set.
|
||||
#[display(fmt = "Account for validating private transactions not set.")]
|
||||
ValidatorAccountNotSet,
|
||||
/// Account for signing requests to key server not set.
|
||||
#[display(fmt = "Account for signing requests to key server not set.")]
|
||||
KeyServerAccountNotSet,
|
||||
/// Encryption key is not found on key server.
|
||||
#[display(fmt = "Encryption key is not found on key server for {}", _0)]
|
||||
EncryptionKeyNotFound(Address),
|
||||
/// Key server URL is not set.
|
||||
#[display(fmt = "Key server URL is not set.")]
|
||||
KeyServerNotSet,
|
||||
/// Transaction not found in logs.
|
||||
#[display(fmt = "Private transaction not found in logs.")]
|
||||
TxNotFoundInLog,
|
||||
/// Path for logging not set.
|
||||
#[display(fmt = "Path for logging not set.")]
|
||||
LoggingPathNotSet,
|
||||
/// Timestamp overflow error.
|
||||
#[display(fmt = "Timestamp overflow error.")]
|
||||
TimestampOverflow,
|
||||
/// VM execution error.
|
||||
#[display(fmt = "VM execution error {}", _0)]
|
||||
Execution(ExecutionError),
|
||||
/// General signing error.
|
||||
#[display(fmt = "General signing error {}", _0)]
|
||||
Key(KeyError),
|
||||
/// Error of transactions processing.
|
||||
#[display(fmt = "Error of transactions processing {}", _0)]
|
||||
Transaction(TransactionError),
|
||||
/// General ethcore error.
|
||||
#[display(fmt = "General ethcore error {}", _0)]
|
||||
Ethcore(EthcoreError),
|
||||
/// A convenient variant for String.
|
||||
#[display(fmt = "{}", _0)]
|
||||
Msg(String),
|
||||
}
|
||||
errors {
|
||||
#[doc = "Encryption error."]
|
||||
Encrypt(err: String) {
|
||||
description("Encryption error"),
|
||||
display("Encryption error. ({})", err),
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(error::Error + 'static)> {
|
||||
match self {
|
||||
Error::Io(e) => Some(e),
|
||||
Error::Decoder(e) => Some(e),
|
||||
Error::Trie(e) => Some(e),
|
||||
Error::TxPool(e) => Some(e),
|
||||
Error::Json(e) => Some(e),
|
||||
Error::Crypto(e) => Some(e),
|
||||
Error::Execution(e) => Some(e),
|
||||
Error::Key(e) => Some(e),
|
||||
Error::Transaction(e) => Some(e),
|
||||
Error::Ethcore(e) => Some(e),
|
||||
_ => None,
|
||||
#[doc = "Decryption error."]
|
||||
Decrypt(err: String) {
|
||||
description("Decryption error"),
|
||||
display("Decryption error. ({})", err),
|
||||
}
|
||||
|
||||
#[doc = "Address not authorized."]
|
||||
NotAuthorised(address: Address) {
|
||||
description("Address not authorized"),
|
||||
display("Private transaction execution is not authorised for {}", address),
|
||||
}
|
||||
|
||||
#[doc = "Transaction creates more than one contract."]
|
||||
TooManyContracts {
|
||||
description("Transaction creates more than one contract."),
|
||||
display("Private transaction created too many contracts"),
|
||||
}
|
||||
|
||||
#[doc = "Contract call error."]
|
||||
Call(err: String) {
|
||||
description("Contract call error."),
|
||||
display("Contract call error. ({})", err),
|
||||
}
|
||||
|
||||
#[doc = "State is not available."]
|
||||
StatePruned {
|
||||
description("State is not available."),
|
||||
display("State is not available"),
|
||||
}
|
||||
|
||||
#[doc = "State is incorrect."]
|
||||
StateIncorrect {
|
||||
description("State is incorrect."),
|
||||
display("State is incorrect"),
|
||||
}
|
||||
|
||||
#[doc = "Wrong private transaction type."]
|
||||
BadTransactonType {
|
||||
description("Wrong private transaction type."),
|
||||
display("Wrong private transaction type"),
|
||||
}
|
||||
|
||||
#[doc = "Contract does not exist or was not created."]
|
||||
ContractDoesNotExist {
|
||||
description("Contract does not exist or was not created."),
|
||||
display("Contract does not exist or was not created"),
|
||||
}
|
||||
|
||||
#[doc = "Reference to the client is corrupted."]
|
||||
ClientIsMalformed {
|
||||
description("Reference to the client is corrupted."),
|
||||
display("Reference to the client is corrupted"),
|
||||
}
|
||||
|
||||
#[doc = "Queue of private transactions for verification is full."]
|
||||
QueueIsFull {
|
||||
description("Queue of private transactions for verification is full."),
|
||||
display("Queue of private transactions for verification is full"),
|
||||
}
|
||||
|
||||
#[doc = "The transaction already exists in queue of private transactions."]
|
||||
PrivateTransactionAlreadyImported {
|
||||
description("The transaction already exists in queue of private transactions."),
|
||||
display("The transaction already exists in queue of private transactions."),
|
||||
}
|
||||
|
||||
#[doc = "The information about private transaction is not found in the store."]
|
||||
PrivateTransactionNotFound {
|
||||
description("The information about private transaction is not found in the store."),
|
||||
display("The information about private transaction is not found in the store."),
|
||||
}
|
||||
|
||||
#[doc = "Account for signing public transactions not set."]
|
||||
SignerAccountNotSet {
|
||||
description("Account for signing public transactions not set."),
|
||||
display("Account for signing public transactions not set."),
|
||||
}
|
||||
|
||||
#[doc = "Account for validating private transactions not set."]
|
||||
ValidatorAccountNotSet {
|
||||
description("Account for validating private transactions not set."),
|
||||
display("Account for validating private transactions not set."),
|
||||
}
|
||||
|
||||
#[doc = "Account for signing requests to key server not set."]
|
||||
KeyServerAccountNotSet {
|
||||
description("Account for signing requests to key server not set."),
|
||||
display("Account for signing requests to key server not set."),
|
||||
}
|
||||
|
||||
#[doc = "Encryption key is not found on key server."]
|
||||
EncryptionKeyNotFound(address: Address) {
|
||||
description("Encryption key is not found on key server"),
|
||||
display("Encryption key is not found on key server for {}", address),
|
||||
}
|
||||
|
||||
#[doc = "Key server URL is not set."]
|
||||
KeyServerNotSet {
|
||||
description("Key server URL is not set."),
|
||||
display("Key server URL is not set."),
|
||||
}
|
||||
|
||||
#[doc = "VM execution error."]
|
||||
Execution(err: ExecutionError) {
|
||||
description("VM execution error."),
|
||||
display("VM execution error {}", err),
|
||||
}
|
||||
|
||||
#[doc = "General signing error."]
|
||||
Key(err: KeyError) {
|
||||
description("General signing error."),
|
||||
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."),
|
||||
display("Error of transactions processing {}", err),
|
||||
}
|
||||
|
||||
#[doc = "General ethcore error."]
|
||||
Ethcore(err: EthcoreError) {
|
||||
description("General ethcore error."),
|
||||
display("General ethcore error {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Error {
|
||||
fn from(s: String) -> Self {
|
||||
Error::Msg(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
Error::Io(err).into()
|
||||
impl From<SignError> for Error {
|
||||
fn from(err: SignError) -> Self {
|
||||
ErrorKind::Sign(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyError> for Error {
|
||||
fn from(err: KeyError) -> Self {
|
||||
Error::Key(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CryptoError> for Error {
|
||||
fn from(err: CryptoError) -> Self {
|
||||
Error::Crypto(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DecoderError> for Error {
|
||||
fn from(err: DecoderError) -> Self {
|
||||
Error::Decoder(err).into()
|
||||
ErrorKind::Key(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ExecutionError> for Error {
|
||||
fn from(err: ExecutionError) -> Self {
|
||||
Error::Execution(err).into()
|
||||
ErrorKind::Execution(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransactionError> for Error {
|
||||
fn from(err: TransactionError) -> Self {
|
||||
Error::Transaction(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TrieError> for Error {
|
||||
fn from(err: TrieError) -> Self {
|
||||
Error::Trie(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxPoolError> for Error {
|
||||
fn from(err: TxPoolError) -> Self {
|
||||
Error::TxPool(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SerdeError> for Error {
|
||||
fn from(err: SerdeError) -> Self {
|
||||
Error::Json(err).into()
|
||||
ErrorKind::Transaction(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EthcoreError> for Error {
|
||||
fn from(err: EthcoreError) -> Self {
|
||||
Error::Ethcore(err).into()
|
||||
ErrorKind::Ethcore(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.as_bytes()[..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.as_bytes())
|
||||
}
|
||||
|
||||
/// 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::zero()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -1,82 +1,75 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Private transactions module.
|
||||
|
||||
// Recursion limit required because of
|
||||
// error_chain foreign_links.
|
||||
#![recursion_limit="256"]
|
||||
|
||||
mod encryptor;
|
||||
mod key_server_keys;
|
||||
mod private_transactions;
|
||||
mod messages;
|
||||
mod error;
|
||||
mod log;
|
||||
|
||||
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;
|
||||
extern crate ethjson;
|
||||
extern crate ethkey;
|
||||
extern crate fetch;
|
||||
extern crate futures;
|
||||
extern crate parity_util_mem;
|
||||
extern crate keccak_hash as hash;
|
||||
extern crate parity_bytes as bytes;
|
||||
extern crate parity_crypto as crypto;
|
||||
extern crate ethcore_io as io;
|
||||
extern crate ethcore_miner;
|
||||
extern crate ethcore_transaction as transaction;
|
||||
extern crate ethabi;
|
||||
extern crate ethereum_types;
|
||||
extern crate ethkey;
|
||||
extern crate ethjson;
|
||||
extern crate fetch;
|
||||
extern crate futures;
|
||||
extern crate heapsize;
|
||||
extern crate keccak_hash as hash;
|
||||
extern crate parking_lot;
|
||||
extern crate trie_db as trie;
|
||||
extern crate patricia_trie as trie;
|
||||
extern crate transaction_pool as txpool;
|
||||
extern crate patricia_trie_ethereum as ethtrie;
|
||||
extern crate rlp;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate rustc_hex;
|
||||
extern crate transaction_pool as txpool;
|
||||
extern crate url;
|
||||
extern crate rustc_hex;
|
||||
#[macro_use]
|
||||
extern crate log as ethlog;
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate ethabi_derive;
|
||||
#[macro_use]
|
||||
extern crate ethabi_contract;
|
||||
extern crate derive_more;
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
#[macro_use]
|
||||
extern crate rlp_derive;
|
||||
|
||||
#[cfg(not(time_checked_add))]
|
||||
extern crate time_utils;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate rand;
|
||||
#[cfg(test)]
|
||||
extern crate env_logger;
|
||||
extern crate ethcore_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;
|
||||
pub use log::{Logging, TransactionLog, ValidatorLog, PrivateTxStatus, FileLogsSerializer};
|
||||
pub use error::{Error, ErrorKind};
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::collections::{HashMap, HashSet, BTreeMap};
|
||||
use ethereum_types::{H128, H256, U256, Address, BigEndianHash};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use ethereum_types::{H128, H256, U256, Address};
|
||||
use hash::keccak;
|
||||
use rlp::*;
|
||||
use parking_lot::RwLock;
|
||||
@@ -85,17 +78,16 @@ use ethkey::{Signature, recover, public_to_address};
|
||||
use io::IoChannel;
|
||||
use ethcore::executive::{Executive, TransactOptions};
|
||||
use ethcore::executed::{Executed};
|
||||
use types::transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction};
|
||||
use transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction};
|
||||
use ethcore::{contract_address as ethcore_contract_address};
|
||||
use ethcore::client::{
|
||||
Client, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage, BlockId,
|
||||
Call, BlockInfo
|
||||
Client, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage, BlockId, CallContract
|
||||
};
|
||||
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
|
||||
@@ -122,8 +114,8 @@ pub struct ProviderConfig {
|
||||
pub validator_accounts: Vec<Address>,
|
||||
/// Account used for signing public transactions created from private transactions
|
||||
pub signer_account: Option<Address>,
|
||||
/// Path to private tx logs
|
||||
pub logs_path: Option<String>,
|
||||
/// Passwords used to unlock accounts
|
||||
pub passwords: Vec<Password>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -131,86 +123,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>,
|
||||
logging: Option<Logging>,
|
||||
}
|
||||
|
||||
#[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(),
|
||||
@@ -218,8 +174,6 @@ impl Provider {
|
||||
miner,
|
||||
accounts,
|
||||
channel,
|
||||
keys_provider,
|
||||
logging: config.logs_path.map(|path| Logging::new(Arc::new(FileLogsSerializer::with_path(path)))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,14 +200,18 @@ impl Provider {
|
||||
trace!(target: "privatetx", "Creating private transaction from regular transaction: {:?}", signed_transaction);
|
||||
if self.signer_account.is_none() {
|
||||
warn!(target: "privatetx", "Signing account not set");
|
||||
return Err(Error::SignerAccountNotSet);
|
||||
bail!(ErrorKind::SignerAccountNotSet);
|
||||
}
|
||||
let tx_hash = signed_transaction.hash();
|
||||
let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| Error::BadTransactionType)?;
|
||||
match signed_transaction.action {
|
||||
Action::Create => {
|
||||
bail!(ErrorKind::BadTransactonType);
|
||||
}
|
||||
Action::Call(contract) => {
|
||||
let data = signed_transaction.rlp_bytes();
|
||||
let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?;
|
||||
let private = PrivateTransaction::new(encrypted_transaction, contract);
|
||||
// TODO #9825 [ToDr] Using BlockId::Latest is bad here,
|
||||
// TODO [ToDr] Using BlockId::Latest is bad here,
|
||||
// the block may change in the middle of execution
|
||||
// causing really weird stuff to happen.
|
||||
// We should retrieve hash and stick to that. IMHO
|
||||
@@ -266,41 +224,41 @@ impl Provider {
|
||||
trace!(target: "privatetx", "Required validators: {:?}", contract_validators);
|
||||
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
|
||||
trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash);
|
||||
self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, &contract_validators, private_state, contract_nonce)?;
|
||||
self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?;
|
||||
self.broadcast_private_transaction(private.hash(), private.rlp_bytes());
|
||||
if let Some(ref logging) = self.logging {
|
||||
logging.private_tx_created(&tx_hash, &contract_validators);
|
||||
}
|
||||
Ok(Receipt {
|
||||
hash: tx_hash,
|
||||
contract_address: contract,
|
||||
contract_address: Some(contract),
|
||||
status_code: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate hash from united private state and contract nonce
|
||||
pub fn calculate_state_hash(&self, state: &Bytes, nonce: U256) -> H256 {
|
||||
let state_hash = keccak(state);
|
||||
let nonce_h256: H256 = BigEndianHash::from_uint(&nonce);
|
||||
let mut state_buf = [0u8; 64];
|
||||
state_buf[..32].clone_from_slice(state_hash.as_bytes());
|
||||
state_buf[32..].clone_from_slice(nonce_h256.as_bytes());
|
||||
state_buf[..32].clone_from_slice(&state_hash);
|
||||
state_buf[32..].clone_from_slice(&H256::from(nonce));
|
||||
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,
|
||||
None, // refuse_service_transactions = true
|
||||
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 {
|
||||
@@ -315,36 +273,38 @@ impl Provider {
|
||||
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes());
|
||||
return Ok(());
|
||||
}
|
||||
let contract = Self::contract_address_from_transaction(&transaction.transaction)
|
||||
.map_err(|_| "Incorrect type of action for the transaction")?;
|
||||
// TODO #9825 [ToDr] Usage of BlockId::Latest
|
||||
let tx_action = transaction.transaction.action.clone();
|
||||
if let Action::Call(contract) = tx_action {
|
||||
// TODO [ToDr] Usage of BlockId::Latest
|
||||
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest);
|
||||
if let Err(e) = contract_nonce {
|
||||
return Err(format!("Cannot retrieve contract nonce: {:?}", e).into());
|
||||
bail!("Cannot retrieve contract nonce: {:?}", e);
|
||||
}
|
||||
let contract_nonce = contract_nonce.expect("Error was checked before");
|
||||
let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction);
|
||||
if let Err(e) = private_state {
|
||||
return Err(format!("Cannot retrieve private state: {:?}", e).into());
|
||||
bail!("Cannot retrieve private state: {:?}", e);
|
||||
}
|
||||
let private_state = private_state.expect("Error was checked before");
|
||||
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
|
||||
trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash);
|
||||
let 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 {
|
||||
return Err(format!("Cannot sign the state: {:?}", e).into());
|
||||
bail!("Cannot sign the state: {:?}", e);
|
||||
}
|
||||
let signed_state = signed_state.expect("Error was checked before");
|
||||
let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None);
|
||||
trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction);
|
||||
self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes());
|
||||
} else {
|
||||
bail!("Incorrect type of action for the transaction");
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
@@ -367,101 +327,73 @@ impl Provider {
|
||||
Some(desc) => desc,
|
||||
};
|
||||
let last = self.last_required_signature(&desc, signed_tx.signature())?;
|
||||
let original_tx_hash = desc.original_transaction.hash();
|
||||
|
||||
if last.0 {
|
||||
if last {
|
||||
let mut signatures = desc.received_signatures.clone();
|
||||
signatures.push(signed_tx.signature());
|
||||
let rsv: Vec<Signature> = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect();
|
||||
// Create public transaction
|
||||
let signer_account = self.signer_account.ok_or_else(|| Error::SignerAccountNotSet)?;
|
||||
let state = self.client.state_at(BlockId::Latest).ok_or(Error::StatePruned)?;
|
||||
let nonce = state.nonce(&signer_account)?;
|
||||
let public_tx = self.public_transaction(
|
||||
desc.state.clone(),
|
||||
&desc.original_transaction,
|
||||
&rsv,
|
||||
nonce,
|
||||
desc.original_transaction.nonce,
|
||||
desc.original_transaction.gas_price
|
||||
)?;
|
||||
trace!(target: "privatetx", "Last required signature received, public transaction created: {:?}", public_tx);
|
||||
// Sign and add it to the queue
|
||||
let chain_id = desc.original_transaction.chain_id();
|
||||
let public_tx_hash = public_tx.hash(chain_id);
|
||||
let signature = self.accounts.sign(signer_account, public_tx_hash)?;
|
||||
let hash = public_tx.hash(chain_id);
|
||||
let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?;
|
||||
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"),
|
||||
Err(err) => {
|
||||
warn!(target: "privatetx", "Failed to add transaction to queue, error: {:?}", err);
|
||||
return Err(err.into());
|
||||
bail!(err);
|
||||
}
|
||||
}
|
||||
// Notify about state changes
|
||||
let contract = Self::contract_address_from_transaction(&desc.original_transaction)?;
|
||||
// TODO #9825 Usage of BlockId::Latest
|
||||
if self.get_contract_version(BlockId::Latest, &contract) >= PRIVATE_CONTRACT_WITH_NOTIFICATION_VER {
|
||||
match self.state_changes_notify(BlockId::Latest, &contract, &desc.original_transaction.sender(), desc.original_transaction.hash()) {
|
||||
Ok(_) => trace!(target: "privatetx", "Notification about private state changes sent"),
|
||||
Err(err) => warn!(target: "privatetx", "Failed to send private state changed notification, error: {:?}", err),
|
||||
}
|
||||
}
|
||||
// Store logs
|
||||
if let Some(ref logging) = self.logging {
|
||||
logging.signature_added(&original_tx_hash, &last.1);
|
||||
logging.tx_deployed(&original_tx_hash, &public_tx_hash);
|
||||
}
|
||||
// Remove from store for signing
|
||||
if let Err(err) = self.transactions_for_signing.write().remove(&private_hash) {
|
||||
warn!(target: "privatetx", "Failed to remove transaction from signing store, error: {:?}", err);
|
||||
return Err(err);
|
||||
bail!(err);
|
||||
}
|
||||
} else {
|
||||
// Add signature to the store
|
||||
match self.transactions_for_signing.write().add_signature(&private_hash, signed_tx.signature()) {
|
||||
Ok(_) => {
|
||||
trace!(target: "privatetx", "Signature stored for private transaction");
|
||||
if let Some(ref logging) = self.logging {
|
||||
logging.signature_added(&original_tx_hash, &last.1);
|
||||
}
|
||||
}
|
||||
Ok(_) => trace!(target: "privatetx", "Signature stored for private transaction"),
|
||||
Err(err) => {
|
||||
warn!(target: "privatetx", "Failed to add signature to signing store, error: {:?}", err);
|
||||
return Err(err);
|
||||
bail!(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn contract_address_from_transaction(transaction: &SignedTransaction) -> Result<Address, Error> {
|
||||
match transaction.action {
|
||||
Action::Call(contract) => Ok(contract),
|
||||
_ => {
|
||||
warn!(target: "privatetx", "Incorrect type of action for the transaction");
|
||||
return Err(Error::BadTransactionType);
|
||||
}
|
||||
fn last_required_signature(&self, desc: &PrivateTransactionSigningDesc, sign: Signature) -> Result<bool, Error> {
|
||||
if desc.received_signatures.contains(&sign) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
fn last_required_signature(&self, desc: &PrivateTransactionSigningDesc, sign: Signature) -> Result<(bool, Address), Error> {
|
||||
let state_hash = self.calculate_state_hash(&desc.state, desc.contract_nonce);
|
||||
match recover(&sign, &state_hash) {
|
||||
Ok(public) => {
|
||||
let sender = public_to_address(&public);
|
||||
match desc.validators.contains(&sender) {
|
||||
true => {
|
||||
Ok((desc.received_signatures.len() + 1 == desc.validators.len(), sender))
|
||||
Ok(desc.received_signatures.len() + 1 == desc.validators.len())
|
||||
}
|
||||
false => {
|
||||
warn!(target: "privatetx", "Sender's state doesn't correspond to validator's");
|
||||
return Err(Error::StateIncorrect);
|
||||
bail!(ErrorKind::StateIncorrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(target: "privatetx", "Sender's state doesn't correspond to validator's, error {:?}", err);
|
||||
return Err(err.into());
|
||||
bail!(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,44 +410,44 @@ impl Provider {
|
||||
|
||||
fn iv_from_transaction(transaction: &SignedTransaction) -> H128 {
|
||||
let nonce = keccak(&transaction.nonce.rlp_bytes());
|
||||
let (iv, _) = nonce.as_bytes().split_at(INIT_VEC_LEN);
|
||||
let (iv, _) = nonce.split_at(INIT_VEC_LEN);
|
||||
H128::from_slice(iv)
|
||||
}
|
||||
|
||||
fn iv_from_address(contract_address: &Address) -> H128 {
|
||||
let address = keccak(&contract_address.rlp_bytes());
|
||||
let (iv, _) = address.as_bytes().split_at(INIT_VEC_LEN);
|
||||
let (iv, _) = address.split_at(INIT_VEC_LEN);
|
||||
H128::from_slice(iv)
|
||||
}
|
||||
|
||||
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> {
|
||||
let (data, decoder) = private_contract::functions::state::call();
|
||||
let value = self.client.call_contract(block, *address, data)?;
|
||||
let state = decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)))?;
|
||||
let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
|
||||
self.decrypt(address, &state)
|
||||
}
|
||||
|
||||
fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
|
||||
let (data, decoder) = private_contract::functions::code::call();
|
||||
let value = self.client.call_contract(block, *address, data)?;
|
||||
let state = decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)))?;
|
||||
let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
|
||||
self.decrypt(address, &state)
|
||||
}
|
||||
|
||||
pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result<U256, Error> {
|
||||
let (data, decoder) = private_contract::functions::nonce::call();
|
||||
let value = self.client.call_contract(block, *address, data)?;
|
||||
decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)).into())
|
||||
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
|
||||
}
|
||||
|
||||
fn snapshot_to_storage(raw: Bytes) -> HashMap<H256, H256> {
|
||||
@@ -530,77 +462,60 @@ impl Provider {
|
||||
|
||||
fn snapshot_from_storage(storage: &HashMap<H256, H256>) -> Bytes {
|
||||
let mut raw = Vec::with_capacity(storage.len() * 64);
|
||||
// Sort the storage to guarantee the order for all parties
|
||||
let sorted_storage: BTreeMap<&H256, &H256> = storage.iter().collect();
|
||||
for (key, value) in sorted_storage {
|
||||
raw.extend_from_slice(key.as_bytes());
|
||||
raw.extend_from_slice(value.as_bytes());
|
||||
for (key, value) in storage {
|
||||
raw.extend_from_slice(key);
|
||||
raw.extend_from_slice(value);
|
||||
};
|
||||
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,
|
||||
V: VMTracer,
|
||||
{
|
||||
let mut env_info = self.client.env_info(block).ok_or(Error::StatePruned)?;
|
||||
let mut env_info = self.client.env_info(block).ok_or(ErrorKind::StatePruned)?;
|
||||
env_info.gas_limit = transaction.gas;
|
||||
|
||||
let mut state = self.client.state_at(block).ok_or(Error::StatePruned)?;
|
||||
// TODO #9825 in case of BlockId::Latest these need to operate on the same state
|
||||
let mut state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
|
||||
// TODO: 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)?;
|
||||
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))?)
|
||||
},
|
||||
};
|
||||
trace!(target: "privatetx", "Private contract executed. code: {:?}, state: {:?}, result: {:?}", encrypted_code, encrypted_storage, result.output);
|
||||
Ok(PrivateExecutionResult {
|
||||
code: encrypted_code,
|
||||
state: encrypted_storage,
|
||||
contract_address: contract_address,
|
||||
contract_address,
|
||||
result,
|
||||
})
|
||||
}
|
||||
@@ -618,59 +533,47 @@ impl Provider {
|
||||
v[31] = s.v();
|
||||
v
|
||||
}).collect::<Vec<[u8; 32]>>(),
|
||||
signatures.iter().map(|s| H256::from_slice(s.r())).collect::<Vec<H256>>(),
|
||||
signatures.iter().map(|s| H256::from_slice(s.s())).collect::<Vec<H256>>(),
|
||||
signatures.iter().map(|s| s.r()).collect::<Vec<&[u8]>>(),
|
||||
signatures.iter().map(|s| s.s()).collect::<Vec<&[u8]>>()
|
||||
)
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
return Err(Error::BadTransactionType);
|
||||
bail!(ErrorKind::BadTransactonType);
|
||||
}
|
||||
let sender = source.sender();
|
||||
let state = self.client.state_at(block).ok_or(Error::StatePruned)?;
|
||||
let state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
|
||||
let nonce = state.nonce(&sender)?;
|
||||
let executed = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
|
||||
let header = self.client.block_header(block)
|
||||
.ok_or(Error::StatePruned)
|
||||
.and_then(|h| h.decode().map_err(|_| Error::StateIncorrect).into())?;
|
||||
let (executed_code, executed_state) = (executed.code.unwrap_or_default(), executed.state);
|
||||
let tx_data = Self::generate_constructor(validators, executed_code.clone(), executed_state.clone());
|
||||
let mut tx = Transaction {
|
||||
let gas: u64 = 650000 +
|
||||
validators.len() as u64 * 30000 +
|
||||
executed.code.as_ref().map_or(0, |c| c.len() as u64) * 8000 +
|
||||
executed.state.len() as u64 * 8000;
|
||||
Ok((Transaction {
|
||||
nonce: nonce,
|
||||
action: Action::Create,
|
||||
gas: u64::max_value().into(),
|
||||
gas: gas.into(),
|
||||
gas_price: gas_price,
|
||||
value: source.value,
|
||||
data: tx_data,
|
||||
};
|
||||
tx.gas = match self.client.estimate_gas(&tx.clone().fake_sign(sender), &state, &header) {
|
||||
Ok(estimated_gas) => estimated_gas,
|
||||
Err(_) => self.estimate_tx_gas(validators, &executed_code, &executed_state, &[]),
|
||||
};
|
||||
|
||||
Ok((tx, executed.contract_address))
|
||||
}
|
||||
|
||||
fn estimate_tx_gas(&self, validators: &[Address], code: &Bytes, state: &Bytes, signatures: &[Signature]) -> U256 {
|
||||
let default_gas = 650000 +
|
||||
validators.len() as u64 * 30000 +
|
||||
code.len() as u64 * 8000 +
|
||||
signatures.len() as u64 * 50000 +
|
||||
state.len() as u64 * 8000;
|
||||
default_gas.into()
|
||||
data: Self::generate_constructor(validators, executed.code.unwrap_or_default(), executed.state)
|
||||
},
|
||||
executed.contract_address))
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
return Err(Error::BadTransactionType);
|
||||
bail!(ErrorKind::BadTransactonType);
|
||||
}
|
||||
let result = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
|
||||
Ok(result.state)
|
||||
@@ -678,7 +581,7 @@ impl Provider {
|
||||
|
||||
/// Create encrypted public transaction from private transaction.
|
||||
pub fn public_transaction(&self, state: Bytes, source: &SignedTransaction, signatures: &[Signature], nonce: U256, gas_price: U256) -> Result<Transaction, Error> {
|
||||
let gas = self.estimate_tx_gas(&[], &Vec::new(), &state, signatures);
|
||||
let gas: u64 = 650000 + state.len() as u64 * 8000 + signatures.len() as u64 * 50000;
|
||||
Ok(Transaction {
|
||||
nonce: nonce,
|
||||
action: source.action.clone(),
|
||||
@@ -695,34 +598,11 @@ impl Provider {
|
||||
Ok(result.result)
|
||||
}
|
||||
|
||||
/// Retrieves log information about private transaction
|
||||
pub fn private_log(&self, tx_hash: H256) -> Result<TransactionLog, Error> {
|
||||
match self.logging {
|
||||
Some(ref logging) => logging.tx_log(&tx_hash).ok_or(Error::TxNotFoundInLog),
|
||||
None => Err(Error::LoggingPathNotSet),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns private validators for a contract.
|
||||
pub fn get_validators(&self, block: BlockId, address: &Address) -> Result<Vec<Address>, Error> {
|
||||
let (data, decoder) = private_contract::functions::get_validators::call();
|
||||
let value = self.client.call_contract(block, *address, data)?;
|
||||
decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)).into())
|
||||
}
|
||||
|
||||
fn get_contract_version(&self, block: BlockId, address: &Address) -> usize {
|
||||
let (data, decoder) = private_contract::functions::get_version::call();
|
||||
match self.client.call_contract(block, *address, data)
|
||||
.and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) {
|
||||
Ok(version) => version.low_u64() as usize,
|
||||
Err(_) => INITIAL_PRIVATE_CONTRACT_VER,
|
||||
}
|
||||
}
|
||||
|
||||
fn state_changes_notify(&self, block: BlockId, address: &Address, originator: &Address, transaction_hash: H256) -> Result<(), Error> {
|
||||
let (data, _) = private_contract::functions::notify_changes::call(*originator, transaction_hash.0.to_vec());
|
||||
let _value = self.client.call_contract(block, *address, data)?;
|
||||
Ok(())
|
||||
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,18 +633,17 @@ impl Importer for Arc<Provider> {
|
||||
.iter()
|
||||
.find(|address| self.validator_accounts.contains(address));
|
||||
|
||||
// Extract the original transaction
|
||||
//extract the original transaction
|
||||
let encrypted_data = private_tx.encrypted();
|
||||
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
|
||||
//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 |_| {
|
||||
@@ -799,13 +678,22 @@ 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 }
|
||||
trace!(target: "privatetx", "New blocks imported, try to prune the queue");
|
||||
if let Err(err) = self.process_verification_queue() {
|
||||
warn!(target: "privatetx", "Cannot prune private transactions queue. error: {:?}", err);
|
||||
trace!(target: "privatetx", "New blocks imported, try to prune the queue");
|
||||
if let Err(err) = self.process_verification_queue() {
|
||||
warn!(target: "privatetx", "Cannot prune private transactions queue. error: {:?}", err);
|
||||
}
|
||||
self.keys_provider.update_acl_contract();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,409 +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/>.
|
||||
|
||||
//! Private transactions logs.
|
||||
|
||||
use ethereum_types::{H256, Address};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, Duration, Instant};
|
||||
use parking_lot::RwLock;
|
||||
use serde::ser::{Serializer, SerializeSeq};
|
||||
use error::Error;
|
||||
|
||||
#[cfg(not(time_checked_add))]
|
||||
use time_utils::CheckedSystemTime;
|
||||
|
||||
/// Maximum amount of stored private transaction logs.
|
||||
const MAX_JOURNAL_LEN: usize = 1000;
|
||||
|
||||
/// Maximum period for storing private transaction logs.
|
||||
/// Logs older than 20 days will not be processed
|
||||
const MAX_STORING_TIME: Duration = Duration::from_secs(60 * 60 * 24 * 20);
|
||||
|
||||
/// Source of monotonic time for log timestamps
|
||||
struct MonoTime {
|
||||
start_time: SystemTime,
|
||||
start_inst: Instant
|
||||
}
|
||||
|
||||
impl MonoTime {
|
||||
fn new(start: SystemTime) -> Self {
|
||||
Self {
|
||||
start_time: start,
|
||||
start_inst: Instant::now()
|
||||
}
|
||||
}
|
||||
|
||||
fn elapsed(&self) -> Duration {
|
||||
self.start_inst.elapsed()
|
||||
}
|
||||
|
||||
fn to_system_time(&self) -> SystemTime {
|
||||
self.start_time + self.elapsed()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MonoTime {
|
||||
fn default() -> Self {
|
||||
MonoTime::new(SystemTime::now())
|
||||
}
|
||||
}
|
||||
|
||||
/// Current status of the private transaction
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
|
||||
pub enum PrivateTxStatus {
|
||||
/// Private tx was created but no validation received yet
|
||||
Created,
|
||||
/// Several validators (but not all) validated the transaction
|
||||
Validating,
|
||||
/// All validators has validated the private tx
|
||||
/// Corresponding public tx was created and added into the pool
|
||||
Deployed,
|
||||
}
|
||||
|
||||
/// Information about private tx validation
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ValidatorLog {
|
||||
/// Account of the validator
|
||||
pub account: Address,
|
||||
/// Validation timestamp, None if the transaction is not validated
|
||||
pub validation_timestamp: Option<SystemTime>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl PartialEq for ValidatorLog {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.account == other.account
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about the private transaction
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TransactionLog {
|
||||
/// Original signed transaction hash (used as a source for private tx)
|
||||
pub tx_hash: H256,
|
||||
/// Current status of the private transaction
|
||||
pub status: PrivateTxStatus,
|
||||
/// Creation timestamp
|
||||
pub creation_timestamp: SystemTime,
|
||||
/// List of validations
|
||||
pub validators: Vec<ValidatorLog>,
|
||||
/// Timestamp of the resulting public tx deployment
|
||||
pub deployment_timestamp: Option<SystemTime>,
|
||||
/// Hash of the resulting public tx
|
||||
pub public_tx_hash: Option<H256>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl PartialEq for TransactionLog {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.tx_hash == other.tx_hash &&
|
||||
self.status == other.status &&
|
||||
self.validators == other.validators &&
|
||||
self.public_tx_hash == other.public_tx_hash
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper other JSON serializer
|
||||
pub trait LogsSerializer: Send + Sync + 'static {
|
||||
/// Read logs from the source
|
||||
fn read_logs(&self) -> Result<Vec<TransactionLog>, Error>;
|
||||
|
||||
/// Write all logs to the source
|
||||
fn flush_logs(&self, logs: &HashMap<H256, TransactionLog>) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Logs serializer to the json file
|
||||
pub struct FileLogsSerializer {
|
||||
logs_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl FileLogsSerializer {
|
||||
pub fn with_path<P: Into<PathBuf>>(logs_dir: P) -> Self {
|
||||
FileLogsSerializer {
|
||||
logs_dir: logs_dir.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn open_file(&self, to_create: bool) -> Result<File, Error> {
|
||||
let file_path = self.logs_dir.with_file_name("private_tx.log");
|
||||
if to_create {
|
||||
File::create(&file_path).map_err(From::from)
|
||||
} else {
|
||||
File::open(&file_path).map_err(From::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LogsSerializer for FileLogsSerializer {
|
||||
fn read_logs(&self) -> Result<Vec<TransactionLog>, Error> {
|
||||
let log_file = self.open_file(false)?;
|
||||
match serde_json::from_reader(log_file) {
|
||||
Ok(logs) => Ok(logs),
|
||||
Err(err) => {
|
||||
error!(target: "privatetx", "Cannot deserialize logs from file: {}", err);
|
||||
return Err(format!("Cannot deserialize logs from file: {:?}", err).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn flush_logs(&self, logs: &HashMap<H256, TransactionLog>) -> Result<(), Error> {
|
||||
if logs.is_empty() {
|
||||
// Do not create empty file
|
||||
return Ok(());
|
||||
}
|
||||
let log_file = self.open_file(true)?;
|
||||
let mut json = serde_json::Serializer::new(log_file);
|
||||
let mut json_array = json.serialize_seq(Some(logs.len()))?;
|
||||
for v in logs.values() {
|
||||
json_array.serialize_element(v)?;
|
||||
}
|
||||
json_array.end()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Private transactions logging
|
||||
pub struct Logging {
|
||||
logs: RwLock<HashMap<H256, TransactionLog>>,
|
||||
logs_serializer: Arc<LogsSerializer>,
|
||||
mono_time: MonoTime,
|
||||
}
|
||||
|
||||
impl Logging {
|
||||
/// Creates the logging object
|
||||
pub fn new(logs_serializer: Arc<LogsSerializer>) -> Self {
|
||||
let mut logging = Logging {
|
||||
logs: RwLock::new(HashMap::new()),
|
||||
logs_serializer,
|
||||
mono_time: MonoTime::default(),
|
||||
};
|
||||
match logging.read_logs() {
|
||||
// Initialize time source by max from current system time and max creation time from already saved logs
|
||||
Ok(initial_time) => logging.mono_time = MonoTime::new(initial_time),
|
||||
Err(err) => warn!(target: "privatetx", "Cannot read logs: {:?}", err),
|
||||
}
|
||||
logging
|
||||
}
|
||||
|
||||
/// Retrieves log for the corresponding tx hash
|
||||
pub fn tx_log(&self, tx_hash: &H256) -> Option<TransactionLog> {
|
||||
self.logs.read().get(&tx_hash).cloned()
|
||||
}
|
||||
|
||||
/// Logs the creation of the private transaction
|
||||
pub fn private_tx_created(&self, tx_hash: &H256, validators: &[Address]) {
|
||||
let mut validator_logs = Vec::new();
|
||||
for account in validators {
|
||||
validator_logs.push(ValidatorLog {
|
||||
account: *account,
|
||||
validation_timestamp: None,
|
||||
});
|
||||
}
|
||||
let mut logs = self.logs.write();
|
||||
if logs.len() > MAX_JOURNAL_LEN {
|
||||
// Remove the oldest log
|
||||
if let Some(tx_hash) = logs.values()
|
||||
.min_by(|x, y| x.creation_timestamp.cmp(&y.creation_timestamp))
|
||||
.map(|oldest| oldest.tx_hash)
|
||||
{
|
||||
logs.remove(&tx_hash);
|
||||
}
|
||||
}
|
||||
logs.insert(*tx_hash, TransactionLog {
|
||||
tx_hash: *tx_hash,
|
||||
status: PrivateTxStatus::Created,
|
||||
creation_timestamp: self.mono_time.to_system_time(),
|
||||
validators: validator_logs,
|
||||
deployment_timestamp: None,
|
||||
public_tx_hash: None,
|
||||
});
|
||||
}
|
||||
|
||||
/// Logs the validation of the private transaction by one of its validators
|
||||
pub fn signature_added(&self, tx_hash: &H256, validator: &Address) {
|
||||
let mut logs = self.logs.write();
|
||||
if let Some(transaction_log) = logs.get_mut(&tx_hash) {
|
||||
if let Some(ref mut validator_log) = transaction_log.validators.iter_mut().find(|log| log.account == *validator) {
|
||||
transaction_log.status = PrivateTxStatus::Validating;
|
||||
validator_log.validation_timestamp = Some(self.mono_time.to_system_time());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Logs the final deployment of the resulting public transaction
|
||||
pub fn tx_deployed(&self, tx_hash: &H256, public_tx_hash: &H256) {
|
||||
let mut logs = self.logs.write();
|
||||
if let Some(log) = logs.get_mut(&tx_hash) {
|
||||
log.status = PrivateTxStatus::Deployed;
|
||||
log.deployment_timestamp = Some(self.mono_time.to_system_time());
|
||||
log.public_tx_hash = Some(*public_tx_hash);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_logs(&self) -> Result<SystemTime, Error> {
|
||||
let mut transaction_logs = self.logs_serializer.read_logs()?;
|
||||
// Drop old logs
|
||||
let earliest_possible = SystemTime::now().checked_sub(MAX_STORING_TIME).ok_or(Error::TimestampOverflow)?;
|
||||
transaction_logs.retain(|tx_log| tx_log.creation_timestamp > earliest_possible);
|
||||
// Sort logs by their creation time in order to find the most recent
|
||||
transaction_logs.sort_by(|a, b| b.creation_timestamp.cmp(&a.creation_timestamp));
|
||||
let initial_timestamp = transaction_logs.first()
|
||||
.map_or(SystemTime::now(), |l| std::cmp::max(SystemTime::now(), l.creation_timestamp));
|
||||
let mut logs = self.logs.write();
|
||||
for log in transaction_logs {
|
||||
logs.insert(log.tx_hash, log);
|
||||
}
|
||||
Ok(initial_timestamp)
|
||||
}
|
||||
|
||||
fn flush_logs(&self) -> Result<(), Error> {
|
||||
let logs = self.logs.read();
|
||||
self.logs_serializer.flush_logs(&logs)
|
||||
}
|
||||
}
|
||||
|
||||
// Flush all logs on drop
|
||||
impl Drop for Logging {
|
||||
fn drop(&mut self) {
|
||||
if let Err(err) = self.flush_logs() {
|
||||
warn!(target: "privatetx", "Cannot write logs: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json;
|
||||
use error::Error;
|
||||
use ethereum_types::{H256, Address};
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, Duration};
|
||||
use std::str::FromStr;
|
||||
use types::transaction::Transaction;
|
||||
use parking_lot::RwLock;
|
||||
use super::{TransactionLog, Logging, PrivateTxStatus, LogsSerializer, ValidatorLog};
|
||||
|
||||
#[cfg(not(time_checked_add))]
|
||||
use time_utils::CheckedSystemTime;
|
||||
|
||||
struct StringLogSerializer {
|
||||
string_log: RwLock<String>,
|
||||
}
|
||||
|
||||
impl StringLogSerializer {
|
||||
fn new(source: String) -> Self {
|
||||
StringLogSerializer {
|
||||
string_log: RwLock::new(source),
|
||||
}
|
||||
}
|
||||
|
||||
fn log(&self) -> String {
|
||||
let log = self.string_log.read();
|
||||
log.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl LogsSerializer for StringLogSerializer {
|
||||
fn read_logs(&self) -> Result<Vec<TransactionLog>, Error> {
|
||||
let source = self.string_log.read();
|
||||
if source.is_empty() {
|
||||
return Ok(Vec::new())
|
||||
}
|
||||
let logs = serde_json::from_str(&source).unwrap();
|
||||
Ok(logs)
|
||||
}
|
||||
|
||||
fn flush_logs(&self, logs: &HashMap<H256, TransactionLog>) -> Result<(), Error> {
|
||||
// Sort logs in order to have the same order
|
||||
let sorted_logs: BTreeMap<&H256, &TransactionLog> = logs.iter().collect();
|
||||
*self.string_log.write() = serde_json::to_string(&sorted_logs.values().collect::<Vec<&&TransactionLog>>())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn private_log_format() {
|
||||
let s = r#"{
|
||||
"tx_hash":"0x64f648ca7ae7f4138014f860ae56164d8d5732969b1cea54d8be9d144d8aa6f6",
|
||||
"status":"Deployed",
|
||||
"creation_timestamp":{"secs_since_epoch":1557220355,"nanos_since_epoch":196382053},
|
||||
"validators":[{
|
||||
"account":"0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1",
|
||||
"validation_timestamp":{"secs_since_epoch":1557220355,"nanos_since_epoch":196382053}
|
||||
}],
|
||||
"deployment_timestamp":{"secs_since_epoch":1557220355,"nanos_since_epoch":196382053},
|
||||
"public_tx_hash":"0x69b9c691ede7993effbcc88911c309af1c82be67b04b3882dd446b808ae146da"
|
||||
}"#;
|
||||
|
||||
let _deserialized: TransactionLog = serde_json::from_str(s).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn private_log_status() {
|
||||
let logger = Logging::new(Arc::new(StringLogSerializer::new("".into())));
|
||||
let private_tx = Transaction::default();
|
||||
let hash = private_tx.hash(None);
|
||||
logger.private_tx_created(&hash, &vec![Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap()]);
|
||||
logger.signature_added(&hash, &Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap());
|
||||
logger.tx_deployed(&hash, &hash);
|
||||
let tx_log = logger.tx_log(&hash).unwrap();
|
||||
assert_eq!(tx_log.status, PrivateTxStatus::Deployed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialization() {
|
||||
let current_timestamp = SystemTime::now();
|
||||
let initial_validator_log = ValidatorLog {
|
||||
account: Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap(),
|
||||
validation_timestamp: Some(current_timestamp.checked_add(Duration::from_secs(1)).unwrap()),
|
||||
};
|
||||
let initial_log = TransactionLog {
|
||||
tx_hash: H256::from_str("64f648ca7ae7f4138014f860ae56164d8d5732969b1cea54d8be9d144d8aa6f6").unwrap(),
|
||||
status: PrivateTxStatus::Deployed,
|
||||
creation_timestamp: current_timestamp,
|
||||
validators: vec![initial_validator_log],
|
||||
deployment_timestamp: Some(current_timestamp.checked_add(Duration::from_secs(2)).unwrap()),
|
||||
public_tx_hash: Some(H256::from_str("69b9c691ede7993effbcc88911c309af1c82be67b04b3882dd446b808ae146da").unwrap()),
|
||||
};
|
||||
let serializer = Arc::new(StringLogSerializer::new(serde_json::to_string(&vec![initial_log.clone()]).unwrap()));
|
||||
let logger = Logging::new(serializer.clone());
|
||||
let hash = H256::from_str("63c715e88f7291e66069302f6fcbb4f28a19ef5d7cbd1832d0c01e221c0061c6").unwrap();
|
||||
logger.private_tx_created(&hash, &vec![Address::from_str("7ffbe3512782069be388f41be4d8eb350672d3a5").unwrap()]);
|
||||
logger.signature_added(&hash, &Address::from_str("7ffbe3512782069be388f41be4d8eb350672d3a5").unwrap());
|
||||
logger.tx_deployed(&hash, &H256::from_str("de2209a8635b9cab9eceb67928b217c70ab53f6498e5144492ec01e6f43547d7").unwrap());
|
||||
drop(logger);
|
||||
let added_validator_log = ValidatorLog {
|
||||
account: Address::from_str("7ffbe3512782069be388f41be4d8eb350672d3a5").unwrap(),
|
||||
validation_timestamp: Some(current_timestamp.checked_add(Duration::from_secs(7)).unwrap()),
|
||||
};
|
||||
let added_log = TransactionLog {
|
||||
tx_hash: H256::from_str("63c715e88f7291e66069302f6fcbb4f28a19ef5d7cbd1832d0c01e221c0061c6").unwrap(),
|
||||
status: PrivateTxStatus::Deployed,
|
||||
creation_timestamp: current_timestamp.checked_add(Duration::from_secs(6)).unwrap(),
|
||||
validators: vec![added_validator_log],
|
||||
deployment_timestamp: Some(current_timestamp.checked_add(Duration::from_secs(8)).unwrap()),
|
||||
public_tx_hash: Some(H256::from_str("de2209a8635b9cab9eceb67928b217c70ab53f6498e5144492ec01e6f43547d7").unwrap()),
|
||||
};
|
||||
let should_be_final = vec![added_log, initial_log];
|
||||
let deserialized_logs: Vec<TransactionLog> = serde_json::from_str(&serializer.log()).unwrap();
|
||||
assert_eq!(deserialized_logs, should_be_final);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,25 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use ethereum_types::{H256, U256, Address, BigEndianHash};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use bytes::Bytes;
|
||||
use hash::keccak;
|
||||
use rlp::Encodable;
|
||||
use ethkey::Signature;
|
||||
use types::transaction::signature::{add_chain_replay_protection, check_replay_protection};
|
||||
use transaction::signature::{add_chain_replay_protection, check_replay_protection};
|
||||
|
||||
/// Message with private transaction encrypted
|
||||
#[derive(Default, Debug, Clone, PartialEq, RlpEncodable, RlpDecodable, Eq)]
|
||||
@@ -38,7 +38,7 @@ impl PrivateTransaction {
|
||||
PrivateTransaction {
|
||||
encrypted,
|
||||
contract,
|
||||
hash: H256::zero(),
|
||||
hash: 0.into(),
|
||||
}.compute_hash()
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ impl SignedPrivateTransaction {
|
||||
r: sig.r().into(),
|
||||
s: sig.s().into(),
|
||||
v: add_chain_replay_protection(sig.v() as u64, chain_id),
|
||||
hash: H256::zero(),
|
||||
hash: 0.into(),
|
||||
}.compute_hash()
|
||||
}
|
||||
|
||||
@@ -100,11 +100,7 @@ impl SignedPrivateTransaction {
|
||||
|
||||
/// Construct a signature object from the sig.
|
||||
pub fn signature(&self) -> Signature {
|
||||
Signature::from_rsv(
|
||||
&BigEndianHash::from_uint(&self.r),
|
||||
&BigEndianHash::from_uint(&self.s),
|
||||
self.standard_v(),
|
||||
)
|
||||
Signature::from_rsv(&self.r.into(), &self.s.into(), self.standard_v())
|
||||
}
|
||||
|
||||
/// Get the hash of of the original transaction.
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// 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 Ethereum is distributed in the hope that it will be useful,
|
||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::cmp;
|
||||
@@ -21,14 +21,14 @@ use std::collections::{HashMap, HashSet};
|
||||
use bytes::Bytes;
|
||||
use ethcore_miner::pool;
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use parity_util_mem::MallocSizeOfExt;
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethkey::Signature;
|
||||
use messages::PrivateTransaction;
|
||||
use parking_lot::RwLock;
|
||||
use types::transaction::{UnverifiedTransaction, SignedTransaction};
|
||||
use transaction::{UnverifiedTransaction, SignedTransaction};
|
||||
use txpool;
|
||||
use txpool::{VerifiedTransaction, Verifier};
|
||||
use error::Error;
|
||||
use error::{Error, ErrorKind};
|
||||
|
||||
type Pool = txpool::Pool<VerifiedPrivateTransaction, pool::scoring::NonceAndGasPrice>;
|
||||
|
||||
@@ -59,7 +59,7 @@ impl txpool::VerifiedTransaction for VerifiedPrivateTransaction {
|
||||
}
|
||||
|
||||
fn mem_usage(&self) -> usize {
|
||||
self.transaction.malloc_size_of()
|
||||
self.transaction.heap_size_of_children()
|
||||
}
|
||||
|
||||
fn sender(&self) -> &Address {
|
||||
@@ -154,7 +154,7 @@ impl Default for VerificationStore {
|
||||
|
||||
impl VerificationStore {
|
||||
/// Adds private transaction for verification into the store
|
||||
pub fn add_transaction<C: pool::client::Client + pool::client::NonceClient + Clone>(
|
||||
pub fn add_transaction<C: pool::client::Client>(
|
||||
&self,
|
||||
transaction: UnverifiedTransaction,
|
||||
validator_account: Option<Address>,
|
||||
@@ -164,7 +164,7 @@ impl VerificationStore {
|
||||
|
||||
let options = self.verification_options.clone();
|
||||
// Use pool's verifying pipeline for original transaction's verification
|
||||
let verifier = pool::verifier::Verifier::new(client.clone(), options, Default::default(), None);
|
||||
let verifier = pool::verifier::Verifier::new(client, options, Default::default(), None);
|
||||
let unverified = pool::verifier::Transaction::Unverified(transaction);
|
||||
let verified_tx = verifier.verify_transaction(unverified)?;
|
||||
let signed_tx: SignedTransaction = verified_tx.signed().clone();
|
||||
@@ -177,9 +177,8 @@ impl VerificationStore {
|
||||
transaction_hash: signed_hash,
|
||||
transaction_sender: signed_sender,
|
||||
};
|
||||
let replace = pool::replace::ReplaceByScoreAndReadiness::new(
|
||||
self.verification_pool.read().scoring().clone(), client);
|
||||
self.verification_pool.write().import(verified, &replace)?;
|
||||
let mut pool = self.verification_pool.write();
|
||||
pool.import(verified)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -224,12 +223,12 @@ impl SigningStore {
|
||||
&mut self,
|
||||
private_hash: H256,
|
||||
transaction: SignedTransaction,
|
||||
validators: &Vec<Address>,
|
||||
validators: Vec<Address>,
|
||||
state: Bytes,
|
||||
contract_nonce: U256,
|
||||
) -> Result<(), Error> {
|
||||
if self.transactions.len() > MAX_QUEUE_LEN {
|
||||
return Err(Error::QueueIsFull);
|
||||
bail!(ErrorKind::QueueIsFull);
|
||||
}
|
||||
|
||||
self.transactions.insert(private_hash, PrivateTransactionSigningDesc {
|
||||
@@ -255,7 +254,7 @@ impl SigningStore {
|
||||
|
||||
/// Adds received signature for the stored private transaction
|
||||
pub fn add_signature(&mut self, private_hash: &H256, signature: Signature) -> Result<(), Error> {
|
||||
let desc = self.transactions.get_mut(private_hash).ok_or_else(|| Error::PrivateTransactionNotFound)?;
|
||||
let desc = self.transactions.get_mut(private_hash).ok_or_else(|| ErrorKind::PrivateTransactionNotFound)?;
|
||||
if !desc.received_signatures.contains(&signature) {
|
||||
desc.received_signatures.push(signature);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user